⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 at9263funcs.c

📁 can4linux-3.5.3.gz can4 linux
💻 C
📖 第 1 页 / 共 3 页
字号:
/* at9263funcs.c** can4linux -- LINUX CAN device driver source*  * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * * Copyright (c) 2007 port GmbH Halle/Saale* (c) 2001 Heinz-Juergen Oertel (oe@port.de)*------------------------------------------------------------------* $Header: /z2/cvsroot/products/0530/software/can4linux/src/at9263funcs.c,v 1.1 2008/11/23 12:05:28 oe Exp $**--------------------------------------------------------------------------*** modification history* --------------------* $Log: at9263funcs.c,v $* Revision 1.1  2008/11/23 12:05:28  oe* - Update and released for 3.5.3** Revision 1.1  2008/10/17 15:19:24  oe* Initial revision***/#include "linux/delay.h"#include <asm/arch/hardware.h>#include <asm/arch/at91_pmc.h>#include <asm/arch/at91_pio.h>#include "defs.h"#include "at9263.h"#include <asm/arch/gpio.h>static enum can_state state;static enum can_state oldstate;/* timing values */static const BTR_TAB_AT91_T can_btr_tab_at91[] = {#  ifdef CAN_BTR_10K					{  10, CAN_BTR_10K   },#  endif										{  20, CAN_BTR_20K   },					{  50, CAN_BTR_50K   },					{ 100, CAN_BTR_100K  },					{ 125, CAN_BTR_125K  },					{ 250, CAN_BTR_250K  },					{ 500, CAN_BTR_500K  },					{ 800, CAN_BTR_800K  },					{1000, CAN_BTR_1000K },					{0, 0}  /* last entry */				      };#ifdef CAN_INDEXED_PORT_IOcanregs_t* regbase = 0;#endif#ifdef DEBUGint CAN_ShowStat (int board){    if (dbgMask && (dbgMask & DBG_DATA)) {#if 0    printk(" MODE 0x%x,", CANin(board, canmode));    printk(" STAT 0x%x,", CANin(board, canstat));    printk(" IRQE 0x%x,", CANin(board, canirq_enable));    printk(" INT 0x%x\n", CANin(board, canirq));#endif    printk("\n");    }    return 0;}#endif/* can_GetStat - read back as many status information as possible ** Because the CAN protocol itself describes different kind of information* already, and the driver has some generic information* (e.g about it's buffers)* we can define a more or less hardware independent format.***/int can_GetStat(	struct inode *inode,	struct file *file,	CanStatusPar_t *stat	){unsigned int minor = iminor(inode);	msg_fifo_t *Fifo;unsigned long flags;		/* processor irq flags 	*/int rx_fifo = ((struct _instance_data *)(file->private_data))->rx_index;u32 tmp;    stat->type = CAN_TYPE_AT91SAM9263;    stat->baud                = Baud[minor];    stat->error_warning_limit = 96; /* fix in the AT91SAM9263 */    tmp                       = CANinl(minor, ecr);    stat->rx_errors           = (tmp & 0xff);    stat->tx_errors           = (tmp & 0x00ff0000ul) >> 16;    stat->status              = CANinl(minor, sr);    stat->error_code          = stat->status;     /* Disable CAN (All !!) Interrupts */    /* !!!!!!!!!!!!!!!!!!!!! */    /* save_flags(flags); cli(); */    local_irq_save(flags);    Fifo = &Rx_Buf[minor][rx_fifo];    stat->rx_buffer_size = MAX_BUFSIZE;	/**< size of rx buffer  */    /* number of messages */    stat->rx_buffer_used =    	(Fifo->head < Fifo->tail)    	? (MAX_BUFSIZE - Fifo->tail + Fifo->head) : (Fifo->head - Fifo->tail);    Fifo = &Tx_Buf[minor];    stat->tx_buffer_size = MAX_BUFSIZE;	/* size of tx buffer  */    /* number of messages */    stat->tx_buffer_used =     	(Fifo->head < Fifo->tail)    	? (MAX_BUFSIZE - Fifo->tail + Fifo->head) : (Fifo->head - Fifo->tail);    /* Enable CAN Interrupts */    /* !!!!!!!!!!!!!!!!!!!!! */    /* restore_flags(flags); */    local_irq_restore(flags);    return 0;}int CAN_ChipReset(int minor){/* u8	status; */u32	pcsr;			/* peripheral clock status */int	i;			/* counter */    DBGin();    /* printk(" ------- RESET ----------------------- \n"); */    /*     * After power-up reset, the CAN controller is disabled.     * The CAN controller clock must be activated     * by the Power Management Controller (PMC)     * and the CAN controller interrupt line must be enabled     * by the interrupt controller (AIC).     * For both a peripheral identifier is used in case of CAN     * this is AT91SAM9263_ID_CAN (Table 10-1)      *     The user can individually enable and disable the Master Clock     on the peripherals by writing into the Peripheral Clock Enable     (PMC_PCER). The bit number within the Peripheral Clock Control registers     (PMC_PCER, PMC_PCDR, and PMC_PCSR) is the Peripheral Identifier     defined at the product level.     Generally, the bit number corresponds to the interrupt source number     assigned to the peripheral.     We assum that the system clock etc. are all set,     Linux is running already     */#if 1  /* clock settings in at91sam9263.c */    pcsr = at91_sys_read(AT91_PMC_PCSR);    pcsr |= 1 << AT91SAM9263_ID_CAN;     at91_sys_write(AT91_PMC_PCER, pcsr);#endif    /*      * In case CAN is not in Reset mode, reset it     */    CANoutl(minor, mode, CANBIT_MR_CANDIS);    udelay(10);    /*     * The pins used for interfacing the CAN     * may be multiplexed with the PIO lines (chapter 30).     * The programmer must first program the PIO controller     * to assign the desired CAN pins to their peripheral function.	When a pin is multiplexed with one or two peripheral	functions, the selection is controlled with the registers	PIO_PER (PIO Enable Register) and PIO_PDR (PIO Disable	Register).	The register PIO_PSR (PIO Status Register) is the result	of the set and clear registers and indicates whether the	pin is controlled by the corresponding peripheral or by	the PIO Controller.	A value of 0 indicates that the pin is controlled by the	corresponding on-chip peripheral selected in the PIO_ABSR	(AB Select Status Register). A value of 1 indicates the	pin is controlled by the PIO controller.	PIO pin programming/assignment is done in	./arch/arm/mach-at91rm9200/at91sam9263_devices.c	function at91_add_device_can()     */#if 1    at91_set_A_periph(AT91_PIN_PA13,   0);	/* CANTX */    at91_set_A_periph(AT91_PIN_PA14,   0);	/* CANRX */#endif    /* disable all IRQ's of all channels */    CANoutl(minor, idr, 0xFFFFFFFFul);    #if 0    DBGprint(DBG_DATA, ("[%d] CAN_mode 0x%x\n", minor, CANinl(minor, mode)));    DBGprint(DBG_DATA, ("[%d] CAN_stat 0x%x\n", minor, CANinl(minor, sr)));    DBGprint(DBG_DATA, ("[%d] CAN_br   0x%x\n", minor, CANinl(minor, br)));    #endif    CAN_SetTiming(minor, Baud[minor]);    DBGprint(DBG_DATA, ("[%d] CAN_br   0x%x\n", minor, CANinl(minor, br)));    /* CAN_register_dump(minor); */    /* CAN_object_dump(minor, TRANSMIT_OBJ); */    /* CAN_object_dump(minor, RECEIVE_STD_OBJ); */    /* initialize all Mailboxes */    for(i = 0; i <= CAN_LAST_OBJ; i++) {	/* disable all */	CAN_OBJ[i].mmr = CANBIT_MMR_MOT_DISABLE;	/* receive only the Message equal the Identifier Register */	CAN_OBJ[i].mam = 0x7FFul << 18;    }    /* enable CAN controller and time stamping */    CANoutl(minor, mode, CANBIT_MR_CANEN | CANBIT_MR_TEOF);#if 0    /* busy waiting for CAN ready */    for(i = 0; i < 10000; i++) {	if(0 != (CANinl(minor, sr) & CANBIT_SR_WAKEUP)) break;    }    printk("==> wake up cnt %d %x\n", i, i);    /* FIXME: use better return value ? */    if (i == 10000) return -ENXIO; /* Configuration mode not left */#endif    /* Create some CAN mail boxes */    /* ---- TRANSMIT_OBJ --------------- */    /* Mailbox Mode register */    /* set MOT Mailbox Object type to TX */    CAN_OBJ[TRANSMIT_OBJ].mmr = CANBIT_MMR_MOT_TX;    /* Mailbox ID register */    /* CAN_WRITE_OID(TRANSMIT_OBJ, 0x123); */    /* CAN_OBJ[TRANSMIT_OBJ].mcr = (8 << CANBIT_MCR_MDLC_POS) | CANBIT_MCR_MTCR; */    CAN_OBJ[TRANSMIT_OBJ].mcr = 0x00400000;    /* CAN_register_dump(minor); */    /* CAN_object_dump(minor, TRANSMIT_OBJ); */    /* ---- RECEIVE_STD_OBJ ------------- */    /* set MOT Mailbox Object type to RX */    /* receive all Messages     * If a bit in the Message Acceptance Register is zero       than it always psses the acceptance test, it is not compared        with the bit in the Message ID Register     */    CAN_OBJ[RECEIVE_STD_OBJ].mam = 0;    CAN_OBJ[RECEIVE_STD_OBJ].mmr = CANBIT_MMR_MOT_RX;    CAN_OBJ[RECEIVE_STD_OBJ].mcr &= ~CANBIT_MCR_MTCR;    /* ---- RECEIVE_EXT_OBJ ------------- */    /* ---- RECEIVE_RTR_OBJ ------------- */    /* AT the moment it seems working using only one CAN mailbox     * for all kind of message to be received.      * No need for these additional receive objects     */      DBGout();    return 0;}/* * Configures bit timing registers directly. Chip must be in bus off state. * The CAN Baud Reta register is 32 bit width. * in the can4linux we use btr0 for *       bit       24 containing the SMP bit  *       bits 23 - 16 containing the BRP Baudrate Prescaler value * and btr1 for *       bits 15 -  0 containing the fields SJW,PROPAG, PHASE1 and PHASE2 *   according to the AT91SAM9263 manual * */int CAN_SetBTR (int minor, int btr0, int btr1){unsigned long br;    DBGin();    DBGprint(DBG_DATA, ("[%d] btr0=%d, btr1=%d", minor, btr0, btr1));    br = (btr1 & 0xFFFF) + ((btr0 & 0x01FF) << 16);    /* write timings to CAN controller */    CANoutl(minor, br, br);    DBGprint(DBG_DATA,("CAN_BR 0x%8x", CANinl(minor, br)));    DBGout();    return 0;}/* * Configures bit timing of selected CAN channel. * Chip must be in configuration state. */int CAN_SetTiming (int minor, int baud){BTR_TAB_AT91_T * table = (BTR_TAB_AT91_T*)can_btr_tab_at91;    DBGin();    DBGprint(DBG_DATA, ("baud[%d]=%d", minor, baud));    /* search for data from table */    while(1) {        if (table->rate == 0 || table->rate == baud) {    	    break;    	}    	table++;    }    if (table->rate == 0) {	/* try to use baud  as custom specific bit rate	 * not implemented yet	 */	return -ENXIO;    }    /* disable CAN Controller, if it is not disabled */    CANoutl(minor, mode, CANBIT_MR_CANDIS);    /* write timings to CAN controller */    CANoutl(minor, br, (unsigned long)table->btr);        DBGprint(DBG_DATA,("CAN Baudrate register = 0x%x\n", CANinl(minor, br)));    /*     * Stay in configuration mode; a call to CAN_StartCHip() is necessary to     * activate the CAN controller with the new bit rate     */    DBGout();    return 0;}int CAN_StartChip (int minor){#if 0int i;#endif    DBGin();    RxErr[minor] = TxErr[minor] = 0L;    DBGprint(DBG_DATA, ("[%d] CAN_mode 0x%x\n", minor, CANinl(minor, mode)));    /* clear _All_  tx and rx interrupts */    /* no idea how this could be done on AT91SAM9263 */     udelay(10);    /* Interrupts on Rx, TX, any Status change and data overrun */    /* CAN Interrupt Enable Register     * anclinux does not care about specific protocol errors      * like bit error, crc error, bit stuffing error, etc      */    CANoutl(minor, ier, 	    (1 << (TRANSMIT_OBJ))	+   (1 << (RECEIVE_STD_OBJ))	/* +   (1 << (RECEIVE_EXT_OBJ) ) */	+    CANBIT_IR_BOFF	+    CANBIT_IR_ERRP	/* +    CANBIT_IR_ERRA */    );    /* Now: leave configuration mode */    /* enable CAN controller and time stamping */    CANoutl(minor, mode, CANBIT_MR_CANEN | CANBIT_MR_TEOF);#if 0    /* Wake-up of CAN was checked already in CAN_ChipReset      * we dont need it here again      */    /* busy waiting for CAN ready */    for(i = 0; i < 10000; i++) {	if(0 != (CANinl(minor, sr) & CANBIT_SR_WAKEUP)) break;    }    printk("==> wake up cnt %d %x\n", i, i);    /* FIXME: use better return value ? */    if (i == 10000) return -ENXIO; /* Configuration mode not left */#endif    state = oldstate = active;    /* printk(" int mask = %x\n", CANinl(minor, imr) ); */    DBGprint(DBG_DATA, ("[%d] Int Mask 0x%x\n", minor, CANinl(minor, imr)));    DBGout();    return 0;}int CAN_StopChip(int minor){    DBGin();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -