| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294 |
- /******************************************************************************
- 版权所有:
- 文件名称: flexcan.c
- 文件版本: 01.01
- 创建作者: sunxi
- 创建日期: 2013-02-03
- 功能说明: FLEXCAN驱动
- 其它说明:
- 修改记录:
- */
- /*------------------------------- 头文件 --------------------------------------
- */
- #include "bspconfig.h"
- #include "rt.h"
- // sunxi 20220408 #include "mcf5441x_gpio.h"
- // sunxi 20220408 #include "mcf5441x_flexcan.h"
- #include "flexcan.h"
- #ifdef BSP_CAN_ENABLE
-
- /*------------------------------- 宏定义 --------------------------------------
- */
- #define CAN_FIFO
- // 优先级
- #define CAN_PRIO_MAX 4
- // 短帧BUF
- #define CAN_FRAME_NUM 256 // CAN短帧BUF数量
- #define CAN_FRAME_LEN 16 // CAN短帧BUF长度
- #define CAN_FRAME_HEAD_LEN 8 // CAN短帧帧头长度
- #define CAN_FRAME_DATA_LEN 8 // CAN短帧数据长度
- // 长帧BUF
- #define CAN_LONGFRAME_NUM 16 // CAN长帧BUF数量
- #define CAN_LONGFRAME_LEN CAN_FRAME_LEN_MAX // CAN长帧BUF长度
- #define CAN_LONGFRAME_HEAD_LEN 4 // CAN长帧头长度
- #define CAN_LONGFRAME_DATA_LEN (CAN_LONGFRAME_LEN-CAN_LONGFRAME_HEAD_LEN) // CAN长帧数据长度
- // 帧标志,数字越小,优先级越高
- #define CAN_FRAME_SINGLE 0 // 单帧(既是起始帧,又是结束帧)
- #define CAN_FRAME_END 1 // 结束帧
- #define CAN_FRAME_MIDDLE 2 // 中间帧
- #define CAN_FRAME_BEGIN 3 // 开始帧
- //帧ID中各个域的位偏移
- #define CAN_FRAME_OFFSET_SN 0 // 帧序号偏移
- #define CAN_FRAME_OFFSET_MARK 6 // 帧标志偏移
- #define CAN_FRAME_OFFSET_SRC 8 // 帧源地址偏移
- #define CAN_FRAME_OFFSET_DST 12 // 帧目的地址偏移
- #define CAN_FRAME_OFFSET_TYPE 16 // 帧类型偏移
- #define CAN_FRAME_OFFSET_PRIOR 23 // 帧优先级偏移(帧优先级是帧类型的高2位)
- #define CAN_FRAME_OFFSET_LEN 16 // 帧长度偏移
- #define CAN_FRAME_MASK_SN 0X3F // 帧序号屏蔽位
- #define CAN_FRAME_MASK_MARK 0X03 // 帧标志屏蔽位
- #define CAN_FRAME_MASK_SRC 0X0F // 帧源地址屏蔽位
- #define CAN_FRAME_MASK_DST 0X0F // 帧目的地址屏蔽位
- #define CAN_FRAME_MASK_TYPE 0XFF // 帧类型屏蔽位
- #define CAN_FRAME_MASK_PRIOR 0X03 // 帧优先级屏蔽位(帧优先级是帧类型的高2位)
- #define CAN_FRAME_MASK_LEN 0X0F // 帧长度屏蔽位
- //缓冲区为空
- #define CAN_BUF_EMPTY(ring) ((ring)->head == (ring)->tail)
- //缓冲区满
- #define CAN_BUF_FULL(ring, size) (((unsigned char)((ring)->head - (ring)->tail))==((unsigned char)(size-1)))
- //缓冲区剩余空间
- #define CAN_BUF_SPACE(ring, size) (((unsigned char)((ring)->tail - (ring)->head) -1) & (unsigned char)(size-1))
- //强制中断寄存器
- #define REG_MCF_INTFRCL1 (*( volatile unsigned int*)(0xFC04C014))
- // 调试开关
- // #define CAN_DEBUG
- #ifdef CAN_DEBUG
- # define can_printf(x...) rt_printf(x)
- #else
- # define can_printf(x...)
- #endif
- // 打印报文
- #ifdef CAN_DEBUG
- # define can_print_mem(x...) print_mem_time(x)
- #else
- # define can_print_mem(x...)
- #endif
- /*------------------------------ 类型结构 -------------------------------------
- */
- // 保证所有结构的大小都是4的倍数
- //长帧缓冲区
- struct can_longframe_buf
- {
- unsigned char head;//头位置
- unsigned char tail;//尾位置
- unsigned char reserverd[2];
- unsigned char buf[CAN_LONGFRAME_NUM][CAN_LONGFRAME_LEN];
- };
- //缓冲区描述符
- struct can_buf
- {
- unsigned char head; //头位置
- unsigned char tail; //尾位置
- unsigned char frameno; //帧序号
- unsigned char reserverd;
- unsigned char buf[CAN_FRAME_NUM][CAN_FRAME_LEN];
- };
- //CAN统计信息数据结构
- struct can_dev_stats{
- uint32_t rx_shortframes; //接收短帧数
- uint32_t tx_shortframes; //发送短帧数
- uint32_t rx_longframes; //接收长帧数
- uint32_t tx_longframes; //发送长帧数
- uint32_t rx_dropped; //接收缓冲区满溢出次数
- uint32_t tx_dropped; //发送缓冲区满溢出次数
- uint32_t hw_bus_errors;
- uint32_t overrun;
- uint32_t max_mbcnt; //统计最大的未处理的MB个数
- uint32_t max_proctime; //处理MB的最大时间
- };
- #if 0
- //短帧描述符
- struct can_shortframe_des
- {
- unsigned char info;
- unsigned char flag1;
- unsigned char srcaddr;
- unsigned char dstaddr;
- unsigned char frameno;
- unsigned char data[8];
- unsigned char reserved[3];
- };
- #endif
- //时间戳差值数据结构
- struct can_timestamp
- {
- unsigned short timestamp; //时间戳差值,该差值是指当前时间戳与有数据的MB的时间戳差值
- short caniflg_bit; //MB下标即是那一个MB
- };
- //flexcan 设备数据结构
- struct can_dev
- {
- uint32_t no;
- uint32_t base_addr;
-
- struct can_dev_stats stats; //网络统计信息
-
- struct can_timestamp ts[CAN_MB]; //记录各时间戳差值
- struct can_buf tx_buf[CAN_PRIO_MAX]; //发送缓冲区
- struct can_buf rx_buf[CAN_PRIO_MAX]; //接收缓冲区
- struct can_longframe_buf longframe_buf_rx[CAN_PRIO_MAX]; //接收长帧缓冲区
- };
- /* Message type access macros.*/
- #define FLEXCAN_SET_MODE_RETRIES 255
- /* Message Buffer 0 configure as Tx */
- #define SEND_BUF 15
- #define SEND_BUF_BIT (1<<SEND_BUF)
- /* Structure of the message buffer */
- struct can_mb
- {
- volatile u32 can_dlc;
- volatile u32 can_id;
- u8 data[8];
- };
- struct can_regs
- {
- volatile u32 canmcr; /* FLEXCAN 0x00 */
- volatile u32 canctrl; /* FLEXCAN 0x04 */
- volatile u32 cantimer; /* FLEXCAN 0x08 */
- volatile u32 reserved1;
- volatile u32 canrxgmsk; /* FLEXCAN 0x10 */
- volatile u32 canrx14msk; /* FLEXCAN 0x14 */
- volatile u32 canrx15msk; /* FLEXCAN 0x18 */
- volatile u32 canerrcnt; /* FLEXCAN 0x1C */
- volatile u32 canerrstat; /* FLEXCAN 0x20 */
- volatile u32 reserved2;
- volatile u32 canimask; /* FLEXCAN 0x28 */
- volatile u32 reserved3;
- volatile u32 caniflg; /* FLEXCAN 0x30 */
- volatile u32 reserved4[19];
- struct can_mb cantxfg[CAN_MB];
- volatile u32 reserved5[448];
- volatile u32 rximr[CAN_MB];
- };
- /* @clock_src:
- 1 = The FLEXCAN clock source is the onchip Bus Clock.
- 0 = The FLEXCAN clock source is the chip Oscillator Clock.*/
- struct can_platform_data
- {
- unsigned int clock_src; /* FLEXCAN_CLKSRC_BUS or FLEXCAN_CLKSRC_XTAL */
- unsigned int clock_frq; /* can ref. clock, in Hz */
- };
- /*------------------------------ 全局变量 -------------------------------------
- */
- //flexcan设备
- static struct can_dev g_can_dev[CAN_BUS_NUM] __attribute__ ((aligned(4)));
- FN_CAN_RECV_CALLBACK g_can_recv_callback;
- u8 g_app_buf_tx[CAN_PRIO_MAX][CAN_FRAME_LEN_MAX]; //应用可根据优先级申请的长帧缓冲区
- extern int g_print_can;
- extern int g_print_can_monitor;
- /*------------------------------ 函数声明 -------------------------------------
- */
- static int _can_set_reset_mode(struct can_dev *dev);
- static int _can_set_normal_mode(struct can_dev *dev);
- static int _can_set_bittiming(struct can_dev *dev);
- static void _can_chipset_init(struct can_dev *dev, int clock_src);
- void _can_isr_0(void);
- void _can_isr_1(void);
- void _can_isr_err_0(void);
- void _can_isr_err_1(void);
- int _can_irq_force(int no);
- int _can_irq_clear(int no);
- int _can_irq_is_force(int no);
- /*------------------------------ 外部函数 -------------------------------------
- 外部函数供其它实体文件引用,必须仔细检查传入参数的合法性.
- */
- int can_init(void)
- {
- struct can_dev *dev;
- int i;
- //初始化缓冲区
- memset(g_can_dev,0,sizeof(g_can_dev));
-
- for(i=0; i<CAN_BUS_NUM; i++)
- {
- dev = &g_can_dev[i];
- dev->no = i;
- if(i==0)
- {
- /* CAN0 */
- dev->base_addr = 0xFC020000;
-
- MCF_PMM_PPMCR0 = 8; /* enable FlexCAN0 clock */
-
- MCF_GPIO_PAR_CANI2C =
- (MCF_GPIO_PAR_CANI2C & MCF_GPIO_PAR_CANI2C_I2C0SCL_MASK) |
- MCF_GPIO_PAR_CANI2C_I2C0SCL_CAN0TX;
- MCF_GPIO_PAR_CANI2C =
- (MCF_GPIO_PAR_CANI2C & MCF_GPIO_PAR_CANI2C_I2C0SDA_MASK) |
- MCF_GPIO_PAR_CANI2C_I2C0SDA_CAN0RX;
-
- //设置驱动能力
- MCF_GPIO_SRCR_CANI2C=MCF_GPIO_SRCR_CANI2C | 0x03 ;
-
- }
- else
- {
- /* CAN1 */
- dev->base_addr = 0xFC024000;
-
- MCF_PMM_PPMCR0 = 9; /* enable FlexCAN1 clock */
-
- MCF_GPIO_PAR_CANI2C =
- (MCF_GPIO_PAR_CANI2C & MCF_GPIO_PAR_CANI2C_CAN1TX_MASK) |
- MCF_GPIO_PAR_CANI2C_CAN1TX_CAN1TX;
- MCF_GPIO_PAR_CANI2C =
- (MCF_GPIO_PAR_CANI2C & MCF_GPIO_PAR_CANI2C_CAN1RX_MASK) |
- MCF_GPIO_PAR_CANI2C_CAN1RX_CAN1RX;
-
- //设置驱动能力
- MCF_GPIO_SRCR_CANI2C=MCF_GPIO_SRCR_CANI2C | 0x0C ;
- }
- MCF_GPIO_PAR_CANI2C = 0x5f;
-
- /* set chip into reset mode */
- _can_set_reset_mode(dev);
- _can_set_bittiming(dev);
- // 申请实时中断
- if(i == 0)
- {
- rt_request_irq(CFG_CAN_VECTOR_BEGIN + 0,CFG_INT_LEVEL_CAN,_can_isr_0,"can_isr_0");
- rt_request_irq(CFG_CAN_VECTOR_BEGIN + 1,CFG_INT_LEVEL_CAN,_can_isr_err_0,"can_isr_err_00");
- rt_request_irq(CFG_CAN_VECTOR_BEGIN + 3,CFG_INT_LEVEL_CAN,_can_isr_err_0,"can_isr_err_01");
- }
- else
- {
- rt_request_irq(CFG_CAN_VECTOR_BEGIN + 4,CFG_INT_LEVEL_CAN,_can_isr_1,"can_isr_1");
- rt_request_irq(CFG_CAN_VECTOR_BEGIN + 5,CFG_INT_LEVEL_CAN,_can_isr_err_1,"can_isr_err_10");
- rt_request_irq(CFG_CAN_VECTOR_BEGIN + 7,CFG_INT_LEVEL_CAN,_can_isr_err_1,"can_isr_err_11");
- }
- /* init and start flexcan */
- _can_chipset_init(dev, 0);
- _can_set_normal_mode(dev);
- }
- return 0;
- }
- int can_exit(void)
- {
- rt_free_irq(CFG_CAN_VECTOR_BEGIN + 0);
- rt_free_irq(CFG_CAN_VECTOR_BEGIN + 1);
- rt_free_irq(CFG_CAN_VECTOR_BEGIN + 3);
- rt_free_irq(CFG_CAN_VECTOR_BEGIN + 4);
- rt_free_irq(CFG_CAN_VECTOR_BEGIN + 5);
- rt_free_irq(CFG_CAN_VECTOR_BEGIN + 7);
- return 0;
- }
- int can_regester_recv_callback(FN_CAN_RECV_CALLBACK fn)
- {
- g_can_recv_callback = fn;
- return 0;
- }
- u8 * can_request_tx_buf(u8 type)
- {
- int prior;
-
- //提取优先级
- prior=(type >> 6 ) & CAN_FRAME_MASK_PRIOR;
- return g_app_buf_tx[prior];
- }
- int can_send(u32 no,u8 *buf)
- {
- struct can_dev *dev;
- struct can_mb *pfm;
-
- int i,sf_num,sf_len ;
- int frame_mark; // 帧标识
- unsigned char prior; //应用优先级
- unsigned char *p;
- u32 len;
- // 检查参数
- if(no >= CAN_BUS_NUM)
- {
- return -1;
- }
- if(buf == NULL)
- {
- return -2;
- }
- // 检查地址
- if(buf[1]>= CAN_BUS_ADDR_NUM || buf[2] >= CAN_BUS_ADDR_NUM)
- {
- return -5;
- }
- // 检查长度
- len = buf[3];
- if(len > CAN_LONGFRAME_DATA_LEN)
- {
- return -6;
- }
- dev = &g_can_dev[no];
-
- //提取优先级
- prior=(buf[0] >> 6 ) & CAN_FRAME_MASK_PRIOR;
- // 将长帧转换为短帧
- //计算需要分为多少帧短帧
- sf_num=(len + CAN_FRAME_DATA_LEN - 1)/CAN_FRAME_DATA_LEN;
- if(sf_num == 0)
- {
- sf_num = 1;
- }
-
- //空间够吗?
- if(CAN_BUF_SPACE(&dev->tx_buf[prior], CAN_FRAME_NUM) < sf_num)
- {
- //发送溢出次数
- dev->stats.tx_dropped++;
- return -7;
- }
- // 打印报文
- if(g_print_can)
- {
- print_msg("TX_CAN:",buf,len+CAN_LONGFRAME_HEAD_LEN);
- }
-
- //帧序号递加
- dev->tx_buf[prior].frameno++;
- i=0;
- p= buf + CAN_LONGFRAME_HEAD_LEN;
- while(i<sf_num)
- {
- // 短帧数据长度
- sf_len = len>=CAN_FRAME_DATA_LEN?CAN_FRAME_DATA_LEN:len;
- // 帧标识
- if(sf_num == 1)
- {
- frame_mark = CAN_FRAME_SINGLE;
- }
- else
- {
- if(i == 0)
- {
- frame_mark = CAN_FRAME_BEGIN;
- }
- else if(i == (sf_num - 1))
- {
- frame_mark = CAN_FRAME_END ;
- }
- else
- {
- frame_mark = CAN_FRAME_MIDDLE;
- }
- }
-
- //指向当前头位置缓冲区
- pfm=(struct can_mb *)dev->tx_buf[prior].buf[dev->tx_buf[prior].head];
-
- //结构信息
- pfm->can_dlc=MB_CNT_CODE(0x08)|(1 << 21)|(1 << 22)|(sf_len << 16) ;
- // 帧ID
- pfm->can_id= (buf[0] << CAN_FRAME_OFFSET_TYPE)
- | (buf[1] << CAN_FRAME_OFFSET_DST)
- | (buf[2] << CAN_FRAME_OFFSET_SRC)
- | (frame_mark << CAN_FRAME_OFFSET_MARK)
- | (dev->tx_buf[prior].frameno & CAN_FRAME_MASK_SN);
- // 数据
- memcpy(pfm->data, p, sf_len);
- len -= sf_len; //剩余多少数据
- p += sf_len; //调整数据指针
- //头下标往后移
- dev->tx_buf[prior].head++;
-
- //下一短帧
- i++;
- }
- //统计发送长帧
- dev->stats.tx_longframes++;
- // 启动发送
- _can_irq_force(no);
-
- return (buf[3] + CAN_LONGFRAME_HEAD_LEN);
- }
- int can_recv(u32 no,u8 *buf,u32 len)
- {
- struct can_dev *dev;
- int i;
- int framelen;
- // 检查参数
- if(no >= CAN_BUS_NUM)
- {
- return -1;
- }
- if(buf == NULL)
- {
- return -2;
- }
- dev = &g_can_dev[no];
-
- //从0优先级开始,读取接收缓冲区的数据
- for(i=0;i<CAN_PRIO_MAX;i++)
- {
- //对应的长帧缓冲区没有长帧
- if(CAN_BUF_EMPTY(&dev->longframe_buf_rx[i]))
- continue;
-
- //长帧长度
- framelen=dev->longframe_buf_rx[i].buf[dev->longframe_buf_rx[i].tail][CAN_LONGFRAME_HEAD_LEN - 1] + CAN_LONGFRAME_HEAD_LEN;
- //拷贝数据到用户空间
- if(framelen <= len)
- {
- memcpy(buf, dev->longframe_buf_rx[i].buf[dev->longframe_buf_rx[i].tail], framelen);
-
- //调整尾位置
- dev->longframe_buf_rx[i].tail = (dev->longframe_buf_rx[i].tail+1) & (CAN_LONGFRAME_NUM-1);
- }
- else
- {
- rt_printf("can_recv:framelen=%d, len=%d\r\n",framelen,len);
- framelen=-3;
- }
-
- return framelen;
- }
-
- return 0;
- }
- int can_stat(void)
- {
- int i=0;
-
- rt_printf("flexcan communicate stat\r\n");
- for(i=0;i<CAN_BUS_NUM;i++)
- {
- rt_printf("flexcan%d:\r\n",i);
- rt_printf("tx_longframes:\t%u\r\n",g_can_dev[i].stats.tx_longframes);
- rt_printf("rx_longframes:\t%u\r\n",g_can_dev[i].stats.rx_longframes);
- rt_printf("tx_shortframes:\t%u\r\n",g_can_dev[i].stats.tx_shortframes);
- rt_printf("rx_shortframes:\t%u\r\n",g_can_dev[i].stats.rx_shortframes);
- rt_printf("tx_dropped:\t%u\r\n",g_can_dev[i].stats.tx_dropped);
- rt_printf("rx_dropped:\t%u\r\n",g_can_dev[i].stats.rx_dropped);
- rt_printf("hw_bus_errors:\t%u\r\n",g_can_dev[i].stats.hw_bus_errors);
- rt_printf("overrun:\t%u\r\n",g_can_dev[i].stats.overrun);
- }
-
- return 0;
-
- }
- int can_stat_reset(void)
- {
- int i=0;
-
- for(i=0;i<CAN_BUS_NUM;i++)
- {
- memset(&g_can_dev[i].stats,0,sizeof(g_can_dev[i].stats));
- }
- return 0;
- }
- /*------------------------------ 内部函数 -------------------------------------
- 内部函数以下划线‘_’开头,不需要检查参数的合法性.
- */
- /******************************************************************************
- 函数名称: _can_set_reset_mode
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2010-09-25
- 函数说明: 复位FLEXCAN
- 参数说明:
- dev: flexcan 设备
-
- 返回值:成功返回0,失败返回1
- 修改记录:
- */
- static int _can_set_reset_mode(struct can_dev *dev)
- {
- volatile struct can_regs *regs = \
- (volatile struct can_regs *)dev->base_addr;
- int i;
- /* disable all MB interrupts */
- regs->canimask = IMASK_BUFF_DISABLE_ALL;
- /* disable error and bus off interrupt */
- regs->canctrl &= ~(CANCTRL_ERRMSK | CANCTRL_BOFFMSK);
- /* reset chip */
- regs->canmcr &= ~(CANMCR_MDIS);
- regs->canmcr |= CANMCR_SOFTRST;
- for (i = 0; i < FLEXCAN_SET_MODE_RETRIES; i++) {
- /* check reset bit */
- if ((regs->canmcr & CANMCR_SOFTRST) == 0x00) {
- //priv->can.state = CAN_STATE_STOPPED;
- return 0;
- }
- ustimer_delay(10*USTIMER_US);
- }
- return 1;
- }
- /******************************************************************************
- 函数名称: _can_set_normal_mode
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2010-09-25
- 函数说明: 设置正常模式
- 参数说明:
- dev: flexcan 设备
-
- 返回值:成功返回0,失败返回1
- 修改记录:
- */
- static int _can_set_normal_mode(struct can_dev *dev)
- {
- volatile struct can_regs *regs = \
- (volatile struct can_regs *)dev->base_addr;
- int i;
- // 模式寄存器配置
- // regs->canmcr |= CANMCR_SRXDIS; // 禁止自接收(如果允许监视所有短帧,必须允许自接收)
- regs->canmcr |= CANMCR_WARN_EN; // 允许告警
- regs->canmcr |= CANMCR_FEN; // 允许接收FIFO
-
- /* enable the module */
- regs->canmcr &= ~CANMCR_MDIS;
- /* synchronize with can bus*/
- regs->canmcr &= ~CANMCR_HALT;
- for (i = 0; i < FLEXCAN_SET_MODE_RETRIES; i++)
- {
- /* check freeze and disabled bit */
- if (!(regs->canmcr & (CANMCR_NOTRDY | CANMCR_FRZACK)))
- {
- /* enable all MB interrupts */
- regs->canimask = IMASK_BUFF_ENABLE_ALL;
- /* Enable error and bus off interrupt */
- // regs->canctrl |= (CANCTRL_ERRMSK | CANCTRL_BOFFMSK);
- regs->canctrl |= (CANCTRL_TWRN_MSK | CANCTRL_RWRN_MSK | CANCTRL_BOFFMSK);
- return 0;
- }
- ustimer_delay(10*USTIMER_US);
- }
-
- return 1;
- }
- /******************************************************************************
- 函数名称: _can_set_bittiming
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2010-09-25
- 函数说明: 波特率设置函数
- 使用外部晶振50M
- 配置为500K:
- reg = CANCTRL_PRESDIV(9) | CANCTRL_RJW(0);
- reg |= (CANCTRL_PROPSEG(2) |
- CANCTRL_PSEG1(3) |
- CANCTRL_PSEG2(1) |
- CANCTRL_SAMP(0));
- regs->canctrl |= reg;
- 配置为1M:
- reg = CANCTRL_PRESDIV(4) | CANCTRL_RJW(0);
- reg |= (CANCTRL_PROPSEG(3) |
- CANCTRL_PSEG1(2) |
- CANCTRL_PSEG2(1) |
- CANCTRL_SAMP(0));
- regs->canctrl |= reg;
- 参数说明:
- dev: flexcan 设备
-
- 返回值: 返回0
- 修改记录:
- */
- static int _can_set_bittiming(struct can_dev *dev)
- {
- volatile struct can_regs *regs = \
- (struct can_regs *)dev->base_addr;
- volatile u32 reg = 0;
- /* Clear the old bittiming */
- reg = CANCTRL_PRESDIV(0xFF) | CANCTRL_RJW(0x03);
- reg |= (CANCTRL_PROPSEG(0x07) |
- CANCTRL_PSEG1(0x07) |
- CANCTRL_PSEG2(0x07) |
- CANCTRL_SAMP(0x01));
- regs->canctrl &= ~reg;
- //配置波特率为1M
- reg = CANCTRL_PRESDIV(4) | CANCTRL_RJW(0);
- reg |= (CANCTRL_PROPSEG(3) |
- CANCTRL_PSEG1(2) |
- CANCTRL_PSEG2(1) |
- CANCTRL_SAMP(0));
- regs->canctrl |= reg;
- return 0;
- }
- /******************************************************************************
- 函数名称: _can_chipset_init
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2010-09-25
- 函数说明: 初始化flexcan
- 参数说明:
- dev: flexcan 设备
- clock_src: 时钟源,0表示外部晶振,1表示内部总线时钟
-
- 返回值:
- 修改记录:
- */
- /*
- * initialize flexcan:
- * - set clock source
- * - set output mode
- * - set baudrate
- * - enable interrupts
- * - start operating mode
- */
- static void _can_chipset_init(struct can_dev *dev, int clock_src)
- {
- volatile struct can_regs *regs = \
- (volatile struct can_regs *)dev->base_addr;
- int i, j;
- /* Setting the Clk */
- if (clock_src)
- regs->canctrl |= CANCTRL_CLKSRC;
- else
- regs->canctrl &= ~CANCTRL_CLKSRC;
- /* set LBUF to sending from lower buffer*/
- regs->canctrl |= CANCTRL_LBUF;
-
- // 初始化消息buf
- for (i = 0; i < CAN_MB; i++)
- {
- regs->cantxfg[i].can_dlc = 0;
- regs->cantxfg[i].can_id = 0;
- for (j = 0; j < 8; j++)
- regs->cantxfg[i].data[j] = 0;
- }
- //使用各自独立的报文过滤
- regs->canmcr |= CANMCR_BCC;
- for (i = 0; i < CAN_MB; i++)
- {
- //不过滤报文
- regs->rximr[i]=0x00000000;
- }
- //闭环模式
- #if 0
- regs->canctrl |= CANCTRL_LPB;
- #else
- regs->canctrl &= ~CANCTRL_LPB;
- #endif
- }
- /******************************************************************************
- 函数名称: _can_int_tx
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2010-09-25
- 函数说明: flexcan发送处理
- 参数说明:
- dev: flexcan 设备
-
- 返回值:
- 修改记录:
- */
- static void _can_int_tx(struct can_dev *dev)
- {
- int i=0;
- struct can_mb *pfm;
- int txbuf = SEND_BUF;
- volatile struct can_regs *regs = (volatile struct can_regs *)dev->base_addr;
-
- for(i=0;i<CAN_PRIO_MAX;i++)
- {
- int j=0;
- unsigned int code=0;
-
- //对应优先级的缓冲区是否有数据
- if(CAN_BUF_EMPTY(&dev->tx_buf[i]))
- {
- continue;
- }
-
- //当前位置的缓冲区
- pfm=(struct can_mb *)dev->tx_buf[i].buf[dev->tx_buf[i].tail];
-
- //检查是否可以发送. code==8说明上一次成功发送完毕,code==0是第一次将CODE配置0了即是MB_CNT_CODE(0)
- code= (regs->cantxfg[txbuf].can_dlc >> 24) & 0x0F;
- if(!((code==8) || (code==0)))
- {
- //rt_printf("bus is busy\r\n");
- break;
- }
-
- //写数据到寄存器
- regs->cantxfg[txbuf].can_dlc=pfm->can_dlc;
- regs->cantxfg[txbuf].can_id=pfm->can_id;
- for(j=0;j<8;j++)
- {
- regs->cantxfg[txbuf].data[j]=pfm->data[j];
- }
-
- /*Control/status word to hold Tx MB active */
- regs->cantxfg[txbuf].can_dlc |= MB_CNT_CODE(0x0c);
- //调整尾指针
- dev->tx_buf[i].tail++;
-
- //统计发送短帧总数加一
- dev->stats.tx_shortframes++;
-
- break;
- }
- }
- /******************************************************************************
- 函数名称: _can_frame_short2long
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2010-09-25
- 函数说明: 短帧组长帧
- 参数说明:
- dev: flexcan 设备
- prior: 优先级
-
- 返回值:
- 修改记录:
- */
- static int _can_frame_short2long(struct can_dev *dev, int prior)
- {
- static unsigned char pos_rec[CAN_FRAME_NUM];
- int pos_index;
- int i,len,is_deal;
- struct can_mb *pfm;
- struct can_mb *pfmtmp;
- unsigned char *pd,*p;
- unsigned char tmppos=dev->rx_buf[prior].head-1;
- unsigned char srcaddr;
- unsigned char dstaddr;
- unsigned char frameno;
- unsigned char frame_type;
- unsigned char frame_len;
- unsigned int frame_mark;
- unsigned char srcaddrtmp;
- unsigned char dstaddrtmp;
- unsigned char framenotmp;
- unsigned char frame_type_tmp;
- //结束帧指针
- pfm=(struct can_mb *)dev->rx_buf[prior].buf[tmppos];
-
- srcaddr=(pfm->can_id >> CAN_FRAME_OFFSET_SRC) & CAN_FRAME_MASK_SRC;
- dstaddr=(pfm->can_id >> CAN_FRAME_OFFSET_DST) & CAN_FRAME_MASK_DST;
- frameno=pfm->can_id & CAN_FRAME_MASK_SN;
- frame_type=(unsigned char)(pfm->can_id >> CAN_FRAME_OFFSET_TYPE) & CAN_FRAME_MASK_TYPE;
- frame_len = (pfm->can_dlc >> CAN_FRAME_OFFSET_LEN) & CAN_FRAME_MASK_LEN;
- // 查找起始帧
- pos_index = 0;
- for(i=0;i<CAN_FRAME_NUM;i++)
- {
- // 短帧
- pfmtmp=(struct can_mb *)dev->rx_buf[prior].buf[tmppos];
- frame_mark = (pfmtmp->can_id >> CAN_FRAME_OFFSET_MARK)& CAN_FRAME_MASK_MARK;
- srcaddrtmp = (pfmtmp->can_id >> CAN_FRAME_OFFSET_SRC) & CAN_FRAME_MASK_SRC;
- dstaddrtmp = (pfmtmp->can_id >> CAN_FRAME_OFFSET_DST) & CAN_FRAME_MASK_DST;
- framenotmp = pfmtmp->can_id & CAN_FRAME_MASK_SN;
- frame_type_tmp = (unsigned char)(pfmtmp->can_id >> CAN_FRAME_OFFSET_TYPE) & CAN_FRAME_MASK_TYPE;
-
- // 是要找的短帧
- if((srcaddr == srcaddrtmp ) && ( dstaddr==dstaddrtmp) && (frameno==framenotmp) && (frame_type == frame_type_tmp))
- {
- // 记录短帧位置
- pos_rec[pos_index++] = tmppos;
-
- // 找到起始帧
- if((frame_mark == CAN_FRAME_BEGIN) || (frame_mark == CAN_FRAME_SINGLE) )
- {
- break;
- }
- }
-
- // 前一短帧
- tmppos--;
- }
- if(pos_index == 0)
- {
- rt_printf("_can_frame_short2long:pos_index=%d\r\n",pos_index);
- dev->stats.rx_dropped++;
- return -1;
- }
- if(i == CAN_FRAME_NUM)
- {
- #if 0
- rt_printf("_can_frame_short2long:i=%d,pos_index=%d.\r\n",i,pos_index);
- #endif
- dev->stats.rx_dropped++;
- return -11;
- }
- // 检查长度
- len = frame_len + (pos_index - 1)*CAN_FRAME_DATA_LEN;
- if(len > CAN_LONGFRAME_DATA_LEN)
- {
- rt_printf("_can_frame_short2long:i=%d\r\n",i);
- dev->stats.rx_dropped++;
- return -2;
- }
-
- //长帧缓冲区首指针
- pd=dev->longframe_buf_rx[prior].buf[dev->longframe_buf_rx[prior].head];
- p = pd;
-
- // 长帧头
- p[0] = (pfmtmp->can_id >> CAN_FRAME_OFFSET_TYPE);
- p[1] = dstaddrtmp;
- p[2] = srcaddrtmp;
- p[3] = len;
- // 长帧数据
- p += CAN_LONGFRAME_HEAD_LEN;
- while(pos_index--)
- {
- len = pos_index == 0 ? frame_len : 8;
- pfmtmp=(struct can_mb *)dev->rx_buf[prior].buf[pos_rec[pos_index]];
- memcpy(p, pfmtmp->data, len);
- // 置帧空标志
- pfmtmp->can_dlc = 0;
- p+=8;
- }
- // 打印报文
- if(g_print_can)
- {
- print_msg("RX_CAN:",pd,pd[3] + CAN_LONGFRAME_HEAD_LEN);
- }
- // 回调处理此长帧
- is_deal = 0;
- if(g_can_recv_callback)
- {
- is_deal = g_can_recv_callback(dev->no,pd);
- }
- // 如果此长帧没有处理,调整头位置
- if(is_deal != 1)
- {
- if(CAN_BUF_SPACE(&dev->longframe_buf_rx[prior], CAN_LONGFRAME_NUM) == 0)
- {
- dev->stats.rx_dropped++;
- rt_printf("长帧溢出\r\n");
- }
- else
- {
- dev->longframe_buf_rx[prior].head=(dev->longframe_buf_rx[prior].head+1) & (CAN_LONGFRAME_NUM-1);
- }
- // 唤醒主循环处理此长帧
- mainloop_wakeup();
- }
- return 0;
- }
- /******************************************************************************
- 函数名称: _can_int_rx
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2010-09-25
- 函数说明: flexcan接收中断处理
- 参数说明:
- dev: flexcan 设备
- i: 表示第几个接收MB
-
- 返回值:
- 修改记录:
- */
- void _can_bus_monitor(u8 *buf)
- {
- static s8 str[128];
- s8 *p;
- int i;
- sprintf(str,"CAN_RS:");
- p = str + 7;
- for(i=0;i<16;i++)
- {
- sprintf(p,"%02x ",buf[i]);
- p += 3;
- }
- sprintf(p,"\r\n");
- rt_printf(str);
-
- }
- static void _can_int_rx(struct can_dev *dev, int i)
- {
- volatile struct can_regs *regs = (volatile struct can_regs *)dev->base_addr;
- struct can_mb *mb = (struct can_mb *)®s->cantxfg[i];
- struct can_mb *pfm;
-
- int ctrl = mb->can_dlc;
- int canid=mb->can_id;
- u32 prior=(canid >> CAN_FRAME_OFFSET_PRIOR) & 0x03;
- u32 srcaddr = (canid >> CAN_FRAME_OFFSET_SRC) & CAN_FRAME_MASK_SRC;
- int k;
- // 取短帧BUF
- pfm=(struct can_mb *)dev->rx_buf[prior].buf[dev->rx_buf[prior].head];
- if(pfm->can_dlc)
- {
- #if 0
- print_mem("CAN_BUF_FULL: ",(u8*)pfm,16);
- #endif
- dev->stats.overrun++;
- }
-
- // 得到内容
- pfm->can_dlc = ctrl;
- pfm->can_id = mb->can_id;
- for (k = 0; k < 8; k++)
- pfm->data[k] =\
- regs->cantxfg[i].data[k];
- // 如果总线监视,打印短帧
- if(g_print_can_monitor)
- {
- _can_bus_monitor((u8*)pfm);
- }
- // 如果是自己发送的帧,直接返回
- if(srcaddr == 0)
- {
- // 置帧空标志
- pfm->can_dlc = 0;
- return;
- }
-
- //统计接收短帧总数
- dev->stats.rx_shortframes++;
-
- //调整当前位置
- dev->rx_buf[prior].head++;
- //是结束帧就开始组长帧
- if(((canid >> CAN_FRAME_OFFSET_MARK) & CAN_FRAME_MASK_MARK) < 0x02)
- {
- //统计接收长帧总数
- dev->stats.rx_longframes++;
-
- //短帧组长帧
- _can_frame_short2long(dev, prior);
- }
- }
- void _can_isr(int no)
- {
- struct can_dev *dev = &g_can_dev[no];
- volatile struct can_regs *regs = (volatile struct can_regs *)dev->base_addr;
-
- u32 oflags;
- // 得到中断标志
- oflags = regs->caniflg;
- // 处理发送软中断
- if(_can_irq_is_force(no))
- {
- // 应用程序启动发送
- oflags |= SEND_BUF_BIT;
- _can_irq_clear(no);
- }
- // 检查发送标志
- if(oflags & SEND_BUF_BIT)
- {
- // 清发送中断
- regs->caniflg = SEND_BUF_BIT;
- oflags &= (~SEND_BUF_BIT);
- // 发送一帧
- _can_int_tx(dev);
- }
- // 处理接收中断
- // 硬件overrun
- if(oflags & 0x80)
- {
- dev->stats.overrun++;
- }
- // 接收一帧
- if(oflags & 0x20)
- {
- _can_int_rx(dev,0);
- }
- // 清接收中断标志
- regs->caniflg = oflags;
- return ;
- }
- void _can_isr_err(int no)
- {
- struct can_dev *dev = &g_can_dev[no];
- volatile struct can_regs *regs = (struct can_regs *)dev->base_addr;
- u32 errstate = regs->canerrstat;
- regs->canerrstat = errstate;
- dev->stats.hw_bus_errors++;//统计出错信息
-
- return ;
- }
- void _can_isr_0(void)
- {
-
- _can_isr(0);
- }
- void _can_isr_1(void)
- {
-
- _can_isr(1);
- }
- void _can_isr_err_0(void)
- {
-
- _can_isr_err(0);
- }
- void _can_isr_err_1(void)
- {
-
- _can_isr_err(1);
- }
- int _can_irq_force(int no)
- {
- uint32_t flags;
- no *= 4;
- rt_irq_save(flags);
- REG_MCF_INTFRCL1 |= 1 << no;
- rt_irq_restore(flags);
- return 0;
- }
- int _can_irq_clear(int no)
- {
- uint32_t flags;
-
- no *= 4;
-
- rt_irq_save(flags);
- REG_MCF_INTFRCL1 &= ~(1 << no);
- rt_irq_restore(flags);
- return 0;
- }
- int _can_irq_is_force(int no)
- {
- no *= 4;
- if(REG_MCF_INTFRCL1 & (1 << no))
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
- /*------------------------------ 测试函数 -------------------------------------
- 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中
- 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数).
- */
- #define LOOP_BEGIN 1
- int can_test(void)
- {
- static unsigned char buf_tx[CAN_LONGFRAME_LEN],buf_rx[CAN_LONGFRAME_LEN];
- static unsigned char loop = LOOP_BEGIN;
- static uint32_t us0 = 0,err_count=0;
-
- uint32_t us1;
- int i;
- int len_tx,len_rx;
- // 1S调用一次
- us1 = ustimer_get_origin();
- if(us1 - us0 < USTIMER_SEC*10)
- {
- return 0;
- }
- us0 = us1;
-
- // 发送一帧
- memset(buf_tx,0,sizeof(buf_tx));
- buf_tx[0] = loop;
- buf_tx[1] = 1;
- buf_tx[2] = 2;
- buf_tx[3] = loop;
-
- for(i=0; i<buf_tx[3]; i++)
- {
- buf_tx[CAN_LONGFRAME_HEAD_LEN + i] = i;
- }
- len_tx = can_send(0,buf_tx);
- // len_tx = can_send(1,buf_tx);
- // 延时5ms
- ustimer_delay(USTIMER_MS*50);
-
- // 接收一帧
- memset(buf_rx,0,sizeof(buf_rx));
- len_rx = can_recv(0,buf_rx,256);
- if((len_tx == len_rx) && (memcmp(buf_tx,buf_rx,len_tx) == 0))
- {
- rt_printf("can_test ok(%03d,err_count=%d):[len_tx=%d,len_rx=%d]\r\n",loop,err_count,len_tx,len_rx);
- }
- else
- {
- err_count++;
- rt_printf("can_test err(%03d,err_count=%d):[len_tx=%d,len_rx=%d]\r\n",loop,err_count,len_tx,len_rx);
- // can_print_mem("TX:",buf_tx,len_tx);
- // can_print_mem("RX:",buf_rx,len_rx);
- }
- // loop++;
- if(loop > CAN_LONGFRAME_DATA_LEN)
- {
- loop = LOOP_BEGIN;
- }
-
- return 0;
- }
- #endif
- /*------------------------------ 文件结束 -------------------------------------
- */
|