浏览代码

[BSP][ls1c]Add can driver and lib

sundm75 7 年之前
父节点
当前提交
d08ce950e5

+ 542 - 0
bsp/ls1cdev/drivers/drv_can.c

@@ -0,0 +1,542 @@
+/*
+ * File      : drv_can.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2018-01-06     sundm75       first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <board.h>
+#include <rthw.h>
+
+#include <Drv_can.h>
+
+
+#include "ls1c.h"
+#include "ls1c_public.h"
+#include "ls1c_regs.h"
+#include "ls1c_clock.h"
+#include "ls1c_can.h"
+#include "ls1c_pin.h"
+
+
+#ifdef RT_USING_CAN
+
+CanRxMsg RxMessage;
+
+struct ls1c_bxcan
+{
+    CAN_TypeDef *reg;
+    void * irq;
+};
+
+static rt_err_t bxmodifyfilter(struct ls1c_bxcan *pbxcan, struct rt_can_filter_item *pitem, rt_uint32_t actived)
+{
+    rt_int32_t fcase;
+    rt_err_t res;
+    rt_int32_t hdr, fbase, foff;
+    CAN_TypeDef* CANx;
+    CANx = pbxcan->reg;
+    
+    /*pitem->mode     1-掩码模式; 0- 滤波器模式 SJA1000中使用以下方式*/
+    /*SJA1000中AFM    1-单滤波器模式; 0- 双滤波器模式 */
+
+    fcase = pitem->mode;/*1-单滤波器模式; 0- 双滤波器模式*/
+    {
+        if (!actived)
+        {
+            return RT_EOK;
+        }
+        else if (pitem->hdr == -1)
+        {
+            res = -1;
+            if (res != RT_EOK)
+            {
+                return res;
+            }
+        }
+        else if (pitem->hdr >= 0)
+        {
+            rt_enter_critical();
+            res = RT_EOK;
+            if (res != RT_EOK)
+            {
+                return res;
+            }
+            hdr = pitem->hdr;
+            rt_exit_critical();
+        }
+    }
+
+    CAN_FilterInitTypeDef   CAN_FilterInitStruct;
+    unsigned char ide, rtr, id , idmask, mode; 
+    ide =  (unsigned char) pitem->ide;
+    rtr = (unsigned char)  pitem->rtr;
+    id = pitem->id;
+    idmask = pitem->mask;
+    mode = (unsigned char) pitem->mode;
+    CAN_FilterInitStruct.IDE = ide;
+    CAN_FilterInitStruct.RTR = rtr;
+    CAN_FilterInitStruct.ID = id;
+    CAN_FilterInitStruct.IDMASK = idmask;
+    CAN_FilterInitStruct.MODE = mode;
+    CAN_FilterInit(CANx, &CAN_FilterInitStruct);
+    
+    return RT_EOK;
+}
+
+static rt_err_t setfilter(struct ls1c_bxcan *pbxcan, struct rt_can_filter_config *pconfig)
+{
+    struct rt_can_filter_item *pitem = pconfig->items;
+    rt_uint32_t count = pconfig->count;
+    rt_err_t res;
+    while (count)
+    {
+        res = bxmodifyfilter(pbxcan, pitem, pconfig->actived);
+        if (res != RT_EOK)
+        {
+            return res;
+        }
+        pitem++;
+        count--;
+    }
+    return RT_EOK;
+}
+static void bxcan0_filter_init(struct rt_can_device *can)
+{
+        struct ls1c_bxcan *pbxcan;
+        pbxcan = (struct ls1c_bxcan *) can->parent.user_data; 
+    
+}
+
+static void bxcan1_filter_init(struct rt_can_device *can)
+{
+        struct ls1c_bxcan *pbxcan;
+        pbxcan = (struct ls1c_bxcan *) can->parent.user_data; 
+    
+}
+
+static void bxcan_init(CAN_TypeDef *pcan, rt_uint32_t baud, rt_uint32_t mode)
+{
+    CAN_InitTypeDef        CAN_InitStructure;
+
+    Ls1c_CanBPS_t bps ;
+
+         switch(baud)
+            {
+                case CAN1MBaud:
+                    bps = LS1C_CAN1MBaud;
+          break;
+                case CAN800kBaud:
+                    bps = LS1C_CAN800kBaud;
+          break;
+                case CAN500kBaud:
+                    bps = LS1C_CAN500kBaud;
+          break;
+                case CAN250kBaud:
+                    bps = LS1C_CAN250kBaud;
+          break;
+                case CAN125kBaud:
+                    bps = LS1C_CAN125kBaud;
+          break;
+                case CAN50kBaud:
+                    bps = LS1C_CAN40kBaud;
+          break;
+                default:
+                    bps = LS1C_CAN250kBaud;
+          break;
+            }
+
+    switch (mode)
+    {
+    case RT_CAN_MODE_NORMAL:
+        CAN_InitStructure.CAN_Mode = 0x00;
+        break;
+    case RT_CAN_MODE_LISEN:
+        CAN_InitStructure.CAN_Mode = CAN_Mode_LOM;
+        break;
+    case RT_CAN_MODE_LOOPBACK:
+        CAN_InitStructure.CAN_Mode = CAN_Mode_STM;
+        
+        break;
+    case RT_CAN_MODE_LOOPBACKANLISEN:
+        CAN_InitStructure.CAN_Mode = CAN_Mode_STM|CAN_Mode_LOM;
+        break;
+    }
+    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
+
+    switch (bps)
+    {
+        case LS1C_CAN1MBaud: 
+            CAN_InitStructure.CAN_Prescaler = 9;
+            CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq;
+            CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN800kBaud: 
+            CAN_InitStructure.CAN_Prescaler = 8;
+            CAN_InitStructure.CAN_BS1 = CAN_BS1_7tq;
+            CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN500kBaud: 
+            CAN_InitStructure.CAN_Prescaler = 9;
+            CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq;
+            CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN250kBaud: 
+            CAN_InitStructure.CAN_Prescaler = 36;
+            CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq;
+            CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN125kBaud: 
+            CAN_InitStructure.CAN_Prescaler = 36;
+            CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq;
+            CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN100kBaud: 
+            CAN_InitStructure.CAN_Prescaler = 63;
+            CAN_InitStructure.CAN_BS1 = CAN_BS1_7tq;
+            CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN50kBaud: 
+            CAN_InitStructure.CAN_Prescaler = 63;
+            CAN_InitStructure.CAN_BS1 = CAN_BS1_16tq;
+            CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq;
+        break;
+        default: //250K
+            CAN_InitStructure.CAN_Prescaler = 36;
+            CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq;
+            CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
+        break;
+    }
+
+    CAN_Init(pcan, &CAN_InitStructure);
+}
+
+#ifdef USING_BXCAN0
+static void bxcan0_hw_init(void)
+{
+    pin_set_purpose(54, PIN_PURPOSE_OTHER);
+    pin_set_purpose(55, PIN_PURPOSE_OTHER);
+    pin_set_remap(54, PIN_REMAP_THIRD);
+    pin_set_remap(55, PIN_REMAP_THIRD);
+}
+#endif
+
+#ifdef USING_BXCAN1
+static void bxcan1_hw_init(void)
+{
+    pin_set_purpose(56, PIN_PURPOSE_GPIO);
+    pin_set_purpose(57, PIN_PURPOSE_GPIO);
+    pin_set_remap(56, PIN_REMAP_DEFAULT);
+    pin_set_remap(57, PIN_REMAP_DEFAULT);
+}
+#endif
+
+
+static rt_err_t configure(struct rt_can_device *can, struct can_configure *cfg)
+{
+    CAN_TypeDef *pbxcan;
+
+    pbxcan = ((struct ls1c_bxcan *) can->parent.user_data)->reg;
+    if (pbxcan == CAN0)
+    {
+#ifdef USING_BXCAN0
+        bxcan0_hw_init();  
+        bxcan_init(pbxcan, cfg->baud_rate, cfg->mode);
+#endif
+    }
+    else  if (pbxcan == CAN1)
+    {
+#ifdef USING_BXCAN1
+        bxcan1_hw_init();  
+        bxcan_init(pbxcan, cfg->baud_rate, cfg->mode);
+#endif
+    }
+    return RT_EOK;
+}
+
+static rt_err_t control(struct rt_can_device *can, int cmd, void *arg)
+{
+    struct ls1c_bxcan *pbxcan;
+    rt_uint32_t argval;
+
+    pbxcan = (struct ls1c_bxcan *) can->parent.user_data;
+    switch (cmd)
+    {
+    case RT_CAN_CMD_SET_FILTER:
+          return setfilter(pbxcan, (struct rt_can_filter_config *) arg);
+        break;
+    case RT_CAN_CMD_SET_MODE:
+        argval = (rt_uint32_t) arg;
+        if (argval != RT_CAN_MODE_NORMAL ||
+                argval != RT_CAN_MODE_LISEN ||
+                argval != RT_CAN_MODE_LOOPBACK ||
+                argval != RT_CAN_MODE_LOOPBACKANLISEN)
+        {
+            return RT_ERROR;
+        }
+        if (argval != can->config.mode)
+        {
+            can->config.mode = argval;
+            return CAN_SetMode(pbxcan->reg, argval);
+        }
+        break;
+    case RT_CAN_CMD_SET_BAUD:
+        argval = (rt_uint32_t) arg;
+        if (argval != CAN1MBaud &&
+                argval != CAN800kBaud &&
+                argval != CAN500kBaud &&
+                argval != CAN250kBaud &&
+                argval != CAN125kBaud &&
+                argval != CAN100kBaud &&
+                argval != CAN50kBaud  )
+        {
+            return RT_ERROR;
+        }
+        if (argval != can->config.baud_rate)
+        {
+            can->config.baud_rate = argval;
+         Ls1c_CanBPS_t bps;
+         switch(argval)
+            {
+                case CAN1MBaud:
+                    bps = LS1C_CAN1MBaud;
+          break;
+                case CAN800kBaud:
+                    bps = LS1C_CAN800kBaud;
+          break;
+                case CAN500kBaud:
+                    bps = LS1C_CAN500kBaud;
+          break;
+                case CAN250kBaud:
+                    bps = LS1C_CAN250kBaud;
+          break;
+                case CAN125kBaud:
+                    bps = LS1C_CAN125kBaud;
+          break;
+                case CAN50kBaud:
+                    bps = LS1C_CAN40kBaud;
+          break;
+                default:
+                    bps = LS1C_CAN250kBaud;
+          break;
+            }
+            return CAN_SetBps( pbxcan->reg,  bps);
+        }
+        break;
+    case RT_CAN_CMD_GET_STATUS:
+    { 
+        rt_uint32_t errtype;
+
+        errtype = pbxcan->reg->RXERR;
+        can->status.rcverrcnt = errtype ;
+        errtype = pbxcan->reg->TXERR;
+        can->status.snderrcnt = errtype ;
+        errtype = pbxcan->reg->ECC;
+        can->status.errcode = errtype ;
+        if (arg != &can->status)
+        {
+            rt_memcpy(arg, &can->status, sizeof(can->status));
+        }
+    }
+    break;
+    }
+
+    return RT_EOK;
+}
+
+static int sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno)
+{
+    CAN_TypeDef *pbxcan;
+    CanTxMsg TxMessage;
+    struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
+    int i;
+
+    pbxcan = ((struct ls1c_bxcan *) can->parent.user_data)->reg;
+
+    TxMessage.StdId = pmsg->id;
+    TxMessage.ExtId = pmsg->id;
+    TxMessage.RTR = pmsg->rtr;
+    TxMessage.IDE = pmsg->ide;
+    TxMessage.DLC = pmsg->len;
+    for( i=0; i<TxMessage.DLC ;i++)
+    {
+      TxMessage.Data[i] = pmsg->data[i];
+    }
+    CAN_Transmit(pbxcan, &TxMessage);
+
+    return RT_EOK;
+}
+
+static int recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno)
+{
+    CAN_TypeDef *pbxcan;
+
+   struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
+   int i;
+
+    pbxcan = ((struct ls1c_bxcan *) can->parent.user_data)->reg;
+
+    pmsg->ide = (rt_uint32_t) RxMessage.IDE; 
+    if(RxMessage.IDE == 1)
+        pmsg->id = RxMessage.ExtId;
+    else
+        pmsg->id = RxMessage.StdId;
+    pmsg->len = RxMessage.DLC;
+    pmsg->rtr = RxMessage.RTR;
+    pmsg->hdr = 0;
+    for(i= 0;i< RxMessage.DLC; i++)
+    {
+      pmsg->data[i] = RxMessage.Data[i];
+    }
+     return RT_EOK;
+}
+
+static const struct rt_can_ops canops =
+{
+    configure,
+    control,
+    sendmsg,
+    recvmsg,
+};
+
+#ifdef USING_BXCAN0
+struct rt_can_device bxcan0;
+void ls1c_can0_irqhandler(int irq, void *param)  
+{  
+    CAN_TypeDef* CANx;
+    unsigned char status;
+    CANx =  CAN0;
+    /*读寄存器清除中断*/
+   status = CANx->IR;
+   
+    /*接收中断*/
+    if (( status & CAN_IR_RI) == CAN_IR_RI) 
+    {
+        /*清除RI 中断*/
+       CAN_Receive(CANx, &RxMessage);
+       CANx->CMR |= CAN_CMR_RRB; 
+       CANx->CMR |= CAN_CMR_CDO; 
+       rt_hw_can_isr(&bxcan0, RT_CAN_EVENT_RX_IND);
+       rt_kprintf("\r\nCan0 int RX happened!\r\n");
+    }
+    /*发送中断*/
+    else if (( status  & CAN_IR_TI) == CAN_IR_TI) 
+    {
+       rt_hw_can_isr(&bxcan0, RT_CAN_EVENT_TX_DONE | 0 << 8);
+       rt_kprintf("\r\nCan0 int TX happened!\r\n");
+    }
+    /*数据溢出中断*/
+    else if (( status  & CAN_IR_TI) == CAN_IR_DOI) 
+    {
+       rt_hw_can_isr(&bxcan0, RT_CAN_EVENT_RXOF_IND);
+       rt_kprintf("\r\nCan0 int RX OF happened!\r\n");
+    }
+}  
+static struct ls1c_bxcan bxcan0data =
+{
+    .reg = CAN0,
+    .irq = ls1c_can0_irqhandler,
+};
+#endif /*USING_BXCAN0*/
+
+#ifdef USING_BXCAN1
+struct rt_can_device bxcan1;
+void ls1c_can1_irqhandler(int irq, void *param)  
+{  
+    CAN_TypeDef* CANx;
+    unsigned char status;
+    CANx =  CAN1;
+    /*读寄存器清除中断*/
+   status = CANx->IR;
+   
+    /*接收中断*/
+    if (( status & CAN_IR_RI) == CAN_IR_RI) 
+    {
+        /*清除RI 中断*/
+       CAN_Receive(CANx, &RxMessage);
+       CANx->CMR |= CAN_CMR_RRB; 
+       CANx->CMR |= CAN_CMR_CDO; 
+       rt_hw_can_isr(&bxcan1, RT_CAN_EVENT_RX_IND);
+       rt_kprintf("\r\nCan1 int RX happened!\r\n");
+    }
+    /*发送中断*/
+    else if (( status  & CAN_IR_TI) == CAN_IR_TI) 
+    {
+       rt_hw_can_isr(&bxcan1, RT_CAN_EVENT_TX_DONE | 0 << 8);
+       rt_kprintf("\r\nCan1 int TX happened!\r\n");
+    }
+    /*数据溢出中断*/
+    else if (( status  & CAN_IR_TI) == CAN_IR_DOI) 
+    {
+       rt_hw_can_isr(&bxcan1, RT_CAN_EVENT_RXOF_IND);
+       rt_kprintf("\r\nCan1 int RX OF happened!\r\n");
+    }
+}  
+static struct ls1c_bxcan bxcan1data =
+{
+    .reg = CAN1,
+    .irq = ls1c_can1_irqhandler,
+};
+
+#endif /*USING_BXCAN1*/
+
+int ls1c_bxcan_init(void)
+{
+
+#ifdef USING_BXCAN0
+    bxcan0.config.baud_rate = CAN250kBaud;
+    bxcan0.config.msgboxsz = 1;
+    bxcan0.config.sndboxnumber = 1;
+    bxcan0.config.mode = RT_CAN_MODE_NORMAL;
+    bxcan0.config.privmode = 0;
+    bxcan0.config.ticks = 50;
+#ifdef RT_CAN_USING_HDR
+    bxcan0.config.maxhdr = 2;
+#endif
+    rt_hw_can_register(&bxcan0, "bxcan0", &canops, &bxcan0data);
+    rt_kprintf("\r\ncan0 register! \r\n");
+    
+    rt_hw_interrupt_install(LS1C_CAN0_IRQ,( rt_isr_handler_t)bxcan0data.irq , RT_NULL, "can0");  
+    rt_hw_interrupt_umask(LS1C_CAN0_IRQ); 
+#endif
+#ifdef USING_BXCAN1
+    bxcan1.config.baud_rate = CAN250kBaud;
+    bxcan1.config.msgboxsz = 1;
+    bxcan1.config.sndboxnumber = 1;
+    bxcan1.config.mode = RT_CAN_MODE_NORMAL;
+    bxcan1.config.privmode = 0;
+    bxcan1.config.ticks = 50;
+#ifdef RT_CAN_USING_HDR
+    bxcan1.config.maxhdr = 2;
+#endif
+    rt_hw_can_register(&bxcan1, "bxcan1", &canops, &bxcan1data);
+    rt_kprintf("\r\ncan1 register! \r\n");
+    
+    rt_hw_interrupt_install(LS1C_CAN1_IRQ,( rt_isr_handler_t)bxcan1data.irq , RT_NULL, "can1");  
+    rt_hw_interrupt_umask(LS1C_CAN1_IRQ); 
+#endif
+    return RT_EOK;
+}
+
+INIT_BOARD_EXPORT(ls1c_bxcan_init);
+
+#endif /*RT_USING_CAN*/

+ 30 - 0
bsp/ls1cdev/drivers/drv_can.h

@@ -0,0 +1,30 @@
+/*
+ * File      : bxcan.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-01-06     sundm75       first version
+ */
+
+#ifndef LS1C_DRV_CAN_H
+#define LS1C_DRV_CAN_H
+
+extern int ls1c_bxcan_init(void);
+
+#endif /*DRV_CAN_H_*/

+ 460 - 0
bsp/ls1cdev/libraries/Ls1c_can.c

@@ -0,0 +1,460 @@
+/*
+ * File      : ls1c_can.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-01-06     sundm75       first version
+ */
+
+#include "ls1c.h"
+#include "ls1c_public.h"
+#include "ls1c_can.h"
+
+unsigned char  set_reset_mode(CAN_TypeDef* CANx)
+{
+  unsigned char status;
+  int i;
+
+  /*检查复位标志*/
+  status = CANx->MOD;
+
+  /* 关闭中断 */
+  CANx->IER = 0x00;
+  
+  for (i = 0; i < 100; i++)
+  {
+    if((status & CAN_Mode_RM) == CAN_Mode_RM)
+        return 1;
+  
+    /* 设置复位*/
+    CANx->MOD |=  ((unsigned char)CAN_Mode_RM);
+  
+    /*延时*/
+    delay_us(10);
+
+    /*检查复位标志*/
+    status = CANx->MOD;
+  }
+  rt_kprintf("\r\nSetting SJA1000 into reset mode failed!\r\n");
+  return 0;  
+}
+
+static unsigned char  set_normal_mode(CAN_TypeDef* CANx)
+{
+  unsigned char status;
+  int i;
+
+  /*检查复位标志*/
+  status = CANx->MOD;
+  
+  for (i = 0; i < 100; i++)
+  {
+    if((status & CAN_Mode_RM) != CAN_Mode_RM)
+    {
+      /*开所有中断 (总线错误中断不开)*/
+      CANx->IER |= (~(unsigned char)CAN_IR_BEI);	
+      return 1;
+    }
+    /* 设置正常工作模式*/
+    CANx->MOD &= (~(unsigned char) CAN_Mode_RM); 
+    /*延时*/
+    delay_us(10); 
+    status = CANx->MOD;	
+  }
+  rt_kprintf("\r\nSetting SJA1000 into normal mode failed!\r\n");
+  return 0;
+}
+
+unsigned char  set_start(CAN_TypeDef* CANx)
+{
+  /*复位TX错误计数器*/
+  CANx->TXERR = 0;
+  /*复位RX错误计数器*/
+  CANx->RXERR = 0;
+  /*时钟分频寄存器: PeliCAN模式; CBP=1,中止输入比较器, RX0激活*/
+  CANx->CDR = 0xC0;	
+ 
+  return  set_normal_mode(CANx);  
+}
+
+ unsigned char CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct)
+{
+  unsigned char InitStatus = CAN_InitStatus_Failed;
+  unsigned long wait_ack = 0x00000000;
+  unsigned char status;
+
+  status = CANx->MOD;
+  if( status == 0xFF)
+  {
+    rt_kprintf("\n Probe can0 failed \r\n");  	   
+    return CAN_InitStatus_Failed;
+  }
+
+   /* 进入复位模式 */
+  InitStatus = set_reset_mode(CANx);
+  
+  if((CAN_InitStruct->CAN_Mode & CAN_Mode_SM) == CAN_Mode_SM) 
+  {
+    /* 睡眠模式 1: 睡眠 0: 唤醒*/
+    CANx->MOD|= (unsigned char)CAN_Mode_SM;    
+  }
+  else
+  {
+     CANx->MOD&=~ (unsigned char)CAN_Mode_SM; 
+  }
+
+ if((CAN_InitStruct->CAN_Mode & CAN_Mode_LOM) == CAN_Mode_LOM) 
+  {
+    /*只听模式 1:只听  0:正常 */
+    CANx->MOD|= (unsigned char)CAN_Mode_LOM;    
+  }
+  else
+  {
+     CANx->MOD&=~ (unsigned char)CAN_Mode_LOM; 
+  }
+
+  if((CAN_InitStruct->CAN_Mode & CAN_Mode_AFM) == CAN_Mode_AFM) 
+  {
+    /*单滤波模式 1:单 0: 双*/
+    CANx->MOD |= (unsigned char)CAN_Mode_AFM;    
+  }
+  else
+  {
+     CANx->MOD&=~ (unsigned char)CAN_Mode_AFM; 
+  }
+
+  if((CAN_InitStruct->CAN_Mode & CAN_Mode_STM) == CAN_Mode_STM) 
+  {
+    /*自检测模式 1:自检测  0:正常  */
+    CANx->MOD |= (unsigned char)CAN_Mode_STM;    
+  }
+  else
+  {
+     CANx->MOD&=~ (unsigned char)CAN_Mode_STM;
+  }
+  
+  /* 配置时钟频率 */
+  CANx->BTR0 = (( unsigned char )( unsigned char )CAN_InitStruct->CAN_Prescaler -1) | \
+               (unsigned char)CAN_InitStruct->CAN_SJW << 6;
+  
+  CANx->BTR1 = ((unsigned char)CAN_InitStruct->CAN_BS1) | \
+               ((unsigned char)CAN_InitStruct->CAN_BS2 << 4) | \
+               ((unsigned char)CAN_InitStruct->CAN_SJW<<7);
+
+   /* 进入工作模式 */
+  set_start(CANx);    
+  
+  /* 返回初始化结果 */
+  return InitStatus;
+}
+
+void CAN_FilterInit(CAN_TypeDef* CANx,    CAN_FilterInitTypeDef * CAN_FilterInitStruct)
+{
+    unsigned long rtr;
+    unsigned long fcase;
+    unsigned long ide;
+    unsigned long thisid, thisid1, thisid2;
+    unsigned long thismask, thismask1, thismask2;
+    unsigned long firstdata;
+    unsigned long datamask;
+    unsigned char CAN_FilterId0, CAN_FilterId1, CAN_FilterId2, CAN_FilterId3 ;
+    unsigned char CAN_FilterMaskId0, CAN_FilterMaskId1, CAN_FilterMaskId2, CAN_FilterMaskId3;
+
+    thisid = CAN_FilterInitStruct->ID;
+    thismask = CAN_FilterInitStruct->IDMASK;
+    thisid1 = (CAN_FilterInitStruct->ID & 0xFFFF0000 )>>16;
+    thismask1 = (CAN_FilterInitStruct->IDMASK & 0xFFFF0000 )>>16;
+    thisid2 = (CAN_FilterInitStruct->ID & 0x0000FFFF );
+    thismask2 = ( CAN_FilterInitStruct->IDMASK& 0x0000FFFF  );
+    rtr = CAN_FilterInitStruct->RTR; 
+    ide = CAN_FilterInitStruct->IDE;
+    firstdata = CAN_FilterInitStruct->First_Data;
+    datamask = CAN_FilterInitStruct->Data_Mask;
+    fcase = CAN_FilterInitStruct->MODE; 
+
+    if(ide == 0)//标准帧
+    {
+        if(fcase == 0)// 0- 双滤波器模式
+        {
+            CAN_FilterId0  = thisid1>>3;
+            CAN_FilterMaskId0 = thismask1>>3;
+            CAN_FilterId1  = thisid1<<5 | firstdata>>4| rtr<<4;
+            CAN_FilterMaskId1 = thismask1<<4 | datamask>>4 ;
+            CAN_FilterId2  = thisid2 >> 3;
+            CAN_FilterMaskId2 = thismask2 >>3;
+            CAN_FilterId3  = firstdata & 0x0F | thisid2 <<5 | rtr<<4;
+            CAN_FilterMaskId3 = datamask <<4  ;
+        }
+        else if(fcase == 1)// 1-单滤波器模式
+        {
+            CAN_FilterId0  = thisid>>3;
+            CAN_FilterMaskId0 = thismask>>3;
+            CAN_FilterId1  = thisid<<5 | rtr<<4;
+            CAN_FilterMaskId1 = thismask<<5  ;
+            CAN_FilterMaskId1 |= 0x0F ;
+            CAN_FilterId2  = 0x00;
+            CAN_FilterMaskId2 = 0xFF;
+            CAN_FilterId3  = 0x00;
+            CAN_FilterMaskId3 = 0xFF  ;
+        }
+    }
+    else if(ide == 1)//扩展帧
+    {
+        if(fcase == 0)// 0- 双滤波器模式
+        {
+            CAN_FilterId0  = thisid1>>8;
+            CAN_FilterMaskId0 = thismask1>>8;
+            CAN_FilterId1  = thisid1 ;
+            CAN_FilterMaskId1 = thismask1 ;
+            CAN_FilterId2  = thisid2>>8;
+            CAN_FilterMaskId2 = thismask2>>8;
+            CAN_FilterId3  = thisid2 ;
+            CAN_FilterMaskId3 = thismask2 ;
+        }
+        else if(fcase == 1)// 1-单滤波器模式
+        {
+            CAN_FilterId0  = thisid>>21;
+            CAN_FilterMaskId0 = thismask>>21;
+            CAN_FilterId1  = thisid>>13 ;
+            CAN_FilterMaskId1 = thismask>>13 ;
+            CAN_FilterId2  = thisid>>5;
+            CAN_FilterMaskId2 = thismask>>5;
+            CAN_FilterId3  = thisid<<3 | rtr<<2;
+            CAN_FilterMaskId3 = thismask<<3;
+            CAN_FilterMaskId3 |= 0x03;
+        }
+    }
+
+    /* 进入复位模式 */
+    set_reset_mode(CANx);
+  
+    if(fcase == 1)// 1-单滤波器模式
+    {
+        /*单滤波模式 */
+        CANx->MOD |= (unsigned char)CAN_Mode_AFM;
+    }
+    else if(fcase == 1)// 0- 双滤波器模式
+    {
+        /*双滤波模式 */
+        CANx->MOD &=(~ (unsigned char) CAN_Mode_AFM);
+    }
+
+    CANx->IDE_RTR_DLC = CAN_FilterId0;
+    CANx->ID[0] =  CAN_FilterId1;
+    CANx->ID[1] =  CAN_FilterId2;
+    CANx->ID[2] =  CAN_FilterId3;
+    CANx->ID[3] =  CAN_FilterMaskId0;
+    CANx->BUF[0] = CAN_FilterMaskId1;
+    CANx->BUF[1] = CAN_FilterMaskId2;
+    CANx->BUF[2] = CAN_FilterMaskId3;
+   /* 进入工作模式 */
+    set_start(CANx);
+}
+
+unsigned char CAN_SetBps(CAN_TypeDef* CANx, Ls1c_CanBPS_t  Bps)
+{
+    unsigned char InitStatus = CAN_InitStatus_Failed;
+    unsigned char  CAN_Prescaler, CAN_BS1, CAN_BS2, CAN_SJW; 
+    CAN_SJW = CAN_SJW_1tq;
+   /* 进入复位模式 */
+  InitStatus = set_reset_mode(CANx);
+  if( InitStatus == CAN_InitStatus_Failed)
+  	return CAN_InitStatus_Failed;
+
+    /* BaudRate= f(APB)/((1+BS1+BS2)(SJW*2*Prescaler))=126000000/[(1+7+2)*1*2*63]=100000=100K*/
+    /* BPS     PRE   BS1   BS2   最低40K
+       1M      9       4       2   
+       800K    8       7       2   
+       500K    9       11      2   
+       250K    36      4       2   
+       125K    36      11      2   
+       100K    63      7       2   
+       50K     63      16      3`  
+       40K     63      16      8   
+    */
+    switch (Bps)
+    {
+        case LS1C_CAN1MBaud: 
+            CAN_Prescaler = 9;
+            CAN_BS1 = CAN_BS1_4tq;
+            CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN800kBaud: 
+            CAN_Prescaler = 8;
+            CAN_BS1 = CAN_BS1_7tq;
+            CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN500kBaud: 
+            CAN_Prescaler = 9;
+            CAN_BS1 = CAN_BS1_11tq;
+            CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN250kBaud: 
+            CAN_Prescaler = 36;
+            CAN_BS1 = CAN_BS1_4tq;
+            CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN125kBaud: 
+            CAN_Prescaler = 36;
+            CAN_BS1 = CAN_BS1_11tq;
+            CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN100kBaud: 
+            CAN_Prescaler = 63;
+            CAN_BS1 = CAN_BS1_7tq;
+            CAN_BS2 = CAN_BS2_2tq;
+        break;
+        case LS1C_CAN50kBaud: 
+            CAN_Prescaler = 63;
+            CAN_BS1 = CAN_BS1_16tq;
+            CAN_BS2 = CAN_BS2_3tq;
+        break;
+        case LS1C_CAN40kBaud: 
+            CAN_Prescaler = 63;
+            CAN_BS1 = CAN_BS1_16tq;
+            CAN_BS2 = CAN_BS2_8tq;
+        break;
+        default: //100K
+            CAN_Prescaler = 63;
+            CAN_BS1 = CAN_BS1_7tq;
+            CAN_BS2 = CAN_BS2_2tq;
+        break;
+    }
+  /* 配置时钟频率 */
+  CANx->BTR0 = (( unsigned char )CAN_Prescaler -1) | \
+               (unsigned char)CAN_SJW << 6;
+  
+  CANx->BTR1 = ((unsigned char)CAN_BS1) | \
+               ((unsigned char)CAN_BS2 << 4) | \
+               ((unsigned char)CAN_SJW<<7);
+
+   /* 进入工作模式 */
+  set_start(CANx);    
+  /* 返回初始化结果 */
+  return CAN_InitStatus_Failed;
+}
+
+
+unsigned char CAN_SetMode(CAN_TypeDef* CANx, unsigned char  mode)
+{
+  unsigned char InitStatus = CAN_InitStatus_Failed;
+  unsigned long wait_ack = 0x00000000;
+  CAN_InitTypeDef        CAN_InitStructure;
+
+   /* 进入复位模式 */
+  InitStatus = set_reset_mode(CANx);
+  if( InitStatus == CAN_InitStatus_Failed)
+  	return CAN_InitStatus_Failed;
+
+  switch( mode )
+  {
+    case 0://正常
+        CANx->MOD &= ~(unsigned char)CAN_Mode_STM;  
+        CANx->MOD &= ~(unsigned char)CAN_Mode_LOM;  
+      break;
+    case 1://只听
+        CANx->MOD &= ~(unsigned char)CAN_Mode_STM;  
+        CANx->MOD |= (unsigned char)CAN_Mode_LOM;  
+      break;
+    case 2://回环
+        CANx->MOD |= (unsigned char)CAN_Mode_STM;  
+        CANx->MOD &= ~(unsigned char)CAN_Mode_LOM;  
+      break;
+    case 3://只听回环
+        CANx->MOD |= (unsigned char)CAN_Mode_STM;  
+        CANx->MOD |= (unsigned char)CAN_Mode_LOM;  
+      break;
+  }
+   /* 进入工作模式 */
+  set_start(CANx);    
+  
+  /* 返回初始化结果 */
+  return CAN_InitStatus_Failed;
+ }
+
+unsigned char  CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage)
+{
+    int i;
+    if (TxMessage->IDE == CAN_Id_Extended)
+    {
+        CANx->ID[0]= TxMessage ->ExtId>> 21;
+        CANx->ID[1]= TxMessage ->ExtId>> 13;
+        CANx->ID[2]= TxMessage ->ExtId>> 5;
+        CANx->ID[3]= TxMessage ->ExtId<<3;
+        CANx->IDE_RTR_DLC= (TxMessage ->IDE & 0x01) << 7 |\
+            (TxMessage ->RTR & 0x01) << 6 |\
+            (TxMessage ->DLC & 0x0F);
+        for( i=0;i<TxMessage ->DLC; i++)
+        {
+           CANx->BUF[i]= TxMessage->Data[i];
+        }
+    }
+    else if (TxMessage->IDE ==CAN_Id_Standard)
+    {
+        CANx->ID[0]= TxMessage ->StdId>> 3;
+        CANx->ID[1]= TxMessage ->StdId<< 5;
+        CANx->IDE_RTR_DLC= (TxMessage ->IDE & 0x01) << 7 |\
+            (TxMessage ->RTR & 0x01) << 6 |\
+            (TxMessage ->DLC & 0x0F);
+        CANx->ID[2]= TxMessage ->Data[0];
+        CANx->ID[3]= TxMessage ->Data[1];
+        for( i=0;i<TxMessage ->DLC-2; i++)
+        {
+           CANx->BUF[i]= TxMessage->Data[i+2];
+        }
+    }
+    CANx->CMR = CAN_CMR_TR ;
+}
+
+void CAN_Receive(CAN_TypeDef* CANx,  CanRxMsg* RxMessage)
+{
+  /* 获取 IDE */
+  RxMessage->IDE = (CANx->IDE_RTR_DLC  & 0x80)>>7;
+  /* 获取 RTR */
+  RxMessage->RTR = (CANx->IDE_RTR_DLC  & 0x40)>>4;
+  /* 获取 DLC */
+  RxMessage->DLC= (CANx->IDE_RTR_DLC  & 0x0F);
+  if (RxMessage->IDE == CAN_Id_Standard)
+  {
+    RxMessage->StdId = CANx->ID[0]<<3 |CANx->ID[1]>>5 ;
+    /* 获取数据 */
+    RxMessage->Data[0] = (unsigned char)CANx->ID[2];
+    RxMessage->Data[1] = (unsigned char)CANx->ID[3];
+    RxMessage->Data[2] = (unsigned char)CANx->BUF[0];
+    RxMessage->Data[3] = (unsigned char)CANx->BUF[1];
+    RxMessage->Data[4] = (unsigned char)CANx->BUF[2];
+    RxMessage->Data[5] = (unsigned char)CANx->BUF[3];
+    RxMessage->Data[6] = (unsigned char)CANx->BUF[4];
+    RxMessage->Data[7] = (unsigned char)CANx->BUF[5];
+  }
+  else  if (RxMessage->IDE == CAN_Id_Extended)
+  {
+    RxMessage->ExtId= CANx->ID[0]<<21 |CANx->ID[1]<<13|CANx->ID[2]<<5|CANx->ID[3]>>3 ;
+    /* 获取数据 */
+    RxMessage->Data[0] = (unsigned char)CANx->BUF[0];
+    RxMessage->Data[1] = (unsigned char)CANx->BUF[1];
+    RxMessage->Data[2] = (unsigned char)CANx->BUF[2];
+    RxMessage->Data[3] = (unsigned char)CANx->BUF[3];
+    RxMessage->Data[4] = (unsigned char)CANx->BUF[4];
+    RxMessage->Data[5] = (unsigned char)CANx->BUF[5];
+    RxMessage->Data[6] = (unsigned char)CANx->BUF[6];
+    RxMessage->Data[7] = (unsigned char)CANx->BUF[7];
+  }  
+}
+

+ 227 - 0
bsp/ls1cdev/libraries/Ls1c_can.h

@@ -0,0 +1,227 @@
+
+/*
+ * File      : ls1c_can.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:  (Pelican Mode) 
+ * Date           Author       Notes
+ * 2018-01-06     sundm75       first version
+ */
+
+#ifndef __OPENLOONGSON_CAN_H
+#define __OPENLOONGSON_CAN_H
+
+#define CAN0               ( (CAN_TypeDef* )LS1C_REG_BASE_CAN0)
+#define CAN1               ( (CAN_TypeDef* )LS1C_REG_BASE_CAN1)
+
+#define CAN_InitStatus_Failed              ((unsigned char)0x00) /*!< CAN initialization failed */
+#define CAN_InitStatus_Success             ((unsigned char)0x01) /*!< CAN initialization OK */
+
+#define CAN_SJW_1tq                 ((unsigned char)0x00)  /*!< 1 time quantum */
+#define CAN_SJW_2tq                 ((unsigned char)0x01)  /*!< 2 time quantum */
+#define CAN_SJW_3tq                 ((unsigned char)0x02)  /*!< 3 time quantum */
+#define CAN_SJW_4tq                 ((unsigned char)0x03)  /*!< 4 time quantum */
+
+#define CAN_BS1_1tq                 ((unsigned char)0x00)  /*!< 1 time quantum */
+#define CAN_BS1_2tq                 ((unsigned char)0x01)  /*!< 2 time quantum */
+#define CAN_BS1_3tq                 ((unsigned char)0x02)  /*!< 3 time quantum */
+#define CAN_BS1_4tq                 ((unsigned char)0x03)  /*!< 4 time quantum */
+#define CAN_BS1_5tq                 ((unsigned char)0x04)  /*!< 5 time quantum */
+#define CAN_BS1_6tq                 ((unsigned char)0x05)  /*!< 6 time quantum */
+#define CAN_BS1_7tq                 ((unsigned char)0x06)  /*!< 7 time quantum */
+#define CAN_BS1_8tq                 ((unsigned char)0x07)  /*!< 8 time quantum */
+#define CAN_BS1_9tq                 ((unsigned char)0x08)  /*!< 9 time quantum */
+#define CAN_BS1_10tq                ((unsigned char)0x09)  /*!< 10 time quantum */
+#define CAN_BS1_11tq                ((unsigned char)0x0A)  /*!< 11 time quantum */
+#define CAN_BS1_12tq                ((unsigned char)0x0B)  /*!< 12 time quantum */
+#define CAN_BS1_13tq                ((unsigned char)0x0C)  /*!< 13 time quantum */
+#define CAN_BS1_14tq                ((unsigned char)0x0D)  /*!< 14 time quantum */
+#define CAN_BS1_15tq                ((unsigned char)0x0E)  /*!< 15 time quantum */
+#define CAN_BS1_16tq                ((unsigned char)0x0F)  /*!< 16 time quantum */
+
+#define CAN_BS2_1tq                 ((unsigned char)0x00)  /*!< 1 time quantum */
+#define CAN_BS2_2tq                 ((unsigned char)0x01)  /*!< 2 time quantum */
+#define CAN_BS2_3tq                 ((unsigned char)0x02)  /*!< 3 time quantum */
+#define CAN_BS2_4tq                 ((unsigned char)0x03)  /*!< 4 time quantum */
+#define CAN_BS2_5tq                 ((unsigned char)0x04)  /*!< 5 time quantum */
+#define CAN_BS2_6tq                 ((unsigned char)0x05)  /*!< 6 time quantum */
+#define CAN_BS2_7tq                 ((unsigned char)0x06)  /*!< 7 time quantum */
+#define CAN_BS2_8tq                 ((unsigned char)0x07)  /*!< 8 time quantum */
+
+#define CAN_Id_Standard           0
+#define CAN_Id_Extended           1
+#define CAN_RTR_DATA               0
+#define CAN_RTR_Remote            1
+
+#define CAN_MODE_NORMAL              0
+#define CAN_MODE_LISEN               1
+#define CAN_MODE_LOOPBACK            2
+#define CAN_MODE_LOOPBACKANLISEN     3
+
+/*!< CAN 控制状态寄存器 */
+/************************** CAN_MOD 寄存器位定义*******************************/
+#define CAN_Mode_RM                 ((unsigned char)0x01)  /*!< 复位模式 */
+#define CAN_Mode_LOM                ((unsigned char)0x02)  /*!< 只听模式 1:只听  0:正常  */
+#define CAN_Mode_STM                ((unsigned char)0x04)  /*!< 正常工作模式1:自检测  0:正常  */
+#define CAN_Mode_AFM                ((unsigned char)0x08)  /*!< 单/双滤波模式 1:单 0: 双*/
+#define CAN_Mode_SM                 ((unsigned char)0x10)  /*!< 睡眠模式1: 睡眠 0: 唤醒 */
+
+/************************** CAN_CMR 寄存器位定义*******************************/
+ #define  CAN_CMR_TR                         ((unsigned char)0x01)         /*!< 发送请求 1: 当前信息被发送  0: 空 */
+ #define  CAN_CMR_AT                         ((unsigned char)0x02)         /*!< 中止发送 1: 等待发送的信息取消  0: 空缺  */
+ #define  CAN_CMR_RRB                        ((unsigned char)0x04)         /*!< 释放接收缓冲器  1:释放  0: 无动作 */
+ #define  CAN_CMR_CDO                        ((unsigned char)0x08)         /*!< 清除数据溢出  1:清除  0: 无动作    */
+//#define  CAN_CMR_GTS                        ((unsigned char)0x10)        /*!< STD模式< 睡眠: 1:进入睡眠  0: 唤醒  */
+ #define  CAN_CMR_SRR                        ((unsigned char)0x10)         /*!< 自接收请求  1:  0:   */
+ #define  CAN_CMR_EFF                        ((unsigned char)0x80)         /*!< 扩展模式 1:扩展帧 0: 标准帧  */
+
+/************************** CAN_SR 寄存器位定义********************************/
+ #define  CAN_SR_BBS                         ((unsigned char)0x01)         /*!< 接收缓存器状态1: 满  0: 空 */
+ #define  CAN_SR_DOS                         ((unsigned char)0x02)         /*!< 数据溢出状态 1: 溢出  0: 空缺  */
+ #define  CAN_SR_TBS                         ((unsigned char)0x04)         /*!< 发送缓存器状态1: 释放  0: 锁定 */
+ #define  CAN_SR_TCS                         ((unsigned char)0x08)         /*!< 发送完毕状态1: 完毕  0: 未完毕    */
+ #define  CAN_SR_RS                          ((unsigned char)0x10)         /*!< 接收状态1: 接收  0: 空闲  */
+ #define  CAN_SR_TS                          ((unsigned char)0x20)         /*!< 发送状态1:  发送 0:  空闲*/
+ #define  CAN_SR_ES                          ((unsigned char)0x40)         /*!< 出错状态1:出错 0: 正常 */
+ #define  CAN_SR_BS                          ((unsigned char)0x80)         /*!< 总线状态1: 关闭  0: 开启  */
+ 
+/************************** CAN_IR 中断寄存器位定义****************************/
+ #define  CAN_IR_RI                          ((unsigned char)0x01)         /*!< 接收中断 */
+ #define  CAN_IR_TI                          ((unsigned char)0x02)         /*!< 发送中断 */
+ #define  CAN_IR_EI                          ((unsigned char)0x04)         /*!< 错误中断 */
+ #define  CAN_IR_DOI                         ((unsigned char)0x08)         /*!< 数据溢出中断  */
+ #define  CAN_IR_WUI                         ((unsigned char)0x10)         /*!< 唤醒中断 */
+ #define  CAN_IR_EPI                         ((unsigned char)0x20)         /*!< 错误消极中断 */
+ #define  CAN_IR_ALI                         ((unsigned char)0x40)         /*!< 仲裁丢失中断 */
+ #define  CAN_IR_BEI                         ((unsigned char)0x80)         /*!< 总线错误中断  */
+ 
+/************************* CAN_IER 中断使能寄存器位定义************************/
+ #define  CAN_IER_RIE                         ((unsigned char)0x01)        /*!< 接收中断使能 */
+ #define  CAN_IER_TIE                         ((unsigned char)0x02)        /*!< 发送中断使能 */
+ #define  CAN_IER_EIE                         ((unsigned char)0x04)        /*!< 错误中断使能 */
+ #define  CAN_IER_DOIE                        ((unsigned char)0x08)        /*!< 数据溢出中断使能  */
+ #define  CAN_IER_WUIE                        ((unsigned char)0x10)        /*!< 唤醒中断使能 */
+ #define  CAN_IER_EPIE                        ((unsigned char)0x20)        /*!< 错误消极中断使能 */
+ #define  CAN_IER_ALIE                        ((unsigned char)0x40)        /*!< 仲裁丢失中断使能 */
+ #define  CAN_IER_BEIE                        ((unsigned char)0x80)        /*!< 总线错误中断使能  */
+ 
+typedef enum 
+{
+	LS1C_CAN1MBaud=0,    // 1 MBit/sec
+	LS1C_CAN800kBaud,    // 800 kBit/sec
+	LS1C_CAN500kBaud,    // 500 kBit/sec
+	LS1C_CAN250kBaud,    // 250 kBit/sec
+	LS1C_CAN125kBaud,    // 125 kBit/sec
+	LS1C_CAN100kBaud,    // 100 kBit/sec
+	LS1C_CAN50kBaud,     // 50 kBit/sec
+	LS1C_CAN40kBaud,     // 40 kBit/sec
+}Ls1c_CanBPS_t;
+
+typedef struct
+{
+   unsigned char MOD;
+   unsigned char CMR;
+   unsigned char SR;
+   unsigned char IR;
+   unsigned char IER;
+   unsigned char reserved0;
+   unsigned char BTR0;
+   unsigned char BTR1;
+   unsigned char OCR;
+   unsigned char reserved[2];
+   unsigned char ALC;
+   unsigned char ECC ;
+   unsigned char EMLR;
+   unsigned char RXERR;
+   unsigned char TXERR;
+   unsigned char IDE_RTR_DLC;
+   unsigned char ID[4];
+   unsigned char BUF[8];
+   unsigned char RMCR;
+   unsigned char CDR;
+} CAN_TypeDef;
+
+typedef struct
+{
+  unsigned char  CAN_Prescaler;    /* 波特率分频系数1 to 31. */  
+  unsigned char  CAN_Mode;         /*0x10:睡眠0x08:单,双滤波 0x40:正常工作0x20:只听 0x01:复位*/
+  unsigned char  CAN_SJW;          /*同步跳转宽度 */
+  unsigned char  CAN_BS1;          /*时间段1计数值*/
+  unsigned char  CAN_BS2;          /*时间段2计数值*/ 
+  
+} CAN_InitTypeDef;
+
+typedef struct
+{
+  unsigned char  IDE;        /*0: 使用标准标识符1: 使用扩展标识符*/
+  unsigned char  RTR;    /*0: 数据帧     1: 远程帧*/
+  unsigned char  MODE;        /* 0- 双滤波器模式;1-单滤波器模式*/
+  unsigned long  First_Data;    /*双滤波器模式下信息第一个数据字节*/
+  unsigned long  Data_Mask;    /*双滤波器模式下信息第一个数据字节屏蔽*/
+  unsigned long  ID;        /*验收代码*/
+  /*
+ 双滤波器-  扩展帧: 2个滤波器的前16位,分别放在ID 的前16位和 ID的后16位.
+ 双滤波器-  标准帧: 2个滤波器的11位,分别放在ID 的前16位和 ID的后16位,第1个滤波器同时使用First_Data和Data_Mask
+ 单滤波器-  扩展帧: 使用29位, 放在ID 的后29位.
+ 单滤波器-  标准帧: 使用11位, 放在ID 的后11位.
+  */
+  unsigned long  IDMASK;    /*验收屏蔽*/
+} CAN_FilterInitTypeDef;
+
+typedef struct
+{
+  unsigned long StdId;  /* 11位ID*/
+  unsigned long ExtId;  /*29位ID**/
+  unsigned char IDE;    /*IDE: 标识符选择
+                                     该位决定发送邮箱中报文使用的标识符类型
+                                     0: 使用标准标识符
+                                     1: 使用扩展标识符*/
+  unsigned char RTR;     /*远程发送请求
+                                       0: 数据帧
+                                       1: 远程帧*/
+  unsigned char DLC;     /*数据帧长度*/
+  unsigned char Data[8]; /*8字节数据*/
+} CanRxMsg;
+
+typedef struct
+{
+  unsigned long StdId;  /* 11位ID*/
+  unsigned long ExtId;  /*29位ID**/
+  unsigned char IDE;    /*IDE: 标识符选择
+                                     该位决定发送邮箱中报文使用的标识符类型
+                                     0: 使用标准标识符
+                                     1: 使用扩展标识符*/
+  unsigned char RTR;     /*远程发送请求
+                                       0: 数据帧
+                                       1: 远程帧*/
+  unsigned char DLC;     /*数据帧长度*/
+  unsigned char Data[8]; /*8字节数据*/
+} CanTxMsg;
+
+unsigned char CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct);
+unsigned char CAN_SetBps(CAN_TypeDef* CANx, Ls1c_CanBPS_t  Bps);
+unsigned char CAN_SetMode(CAN_TypeDef* CANx, unsigned char  mode);
+void CAN_FilterInit(CAN_TypeDef* CANx,  CAN_FilterInitTypeDef* CAN_FilterInitStruct);
+unsigned char CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage);
+void CAN_Receive(CAN_TypeDef* CANx,  CanRxMsg* RxMessage);
+
+unsigned char  set_reset_mode(CAN_TypeDef* CANx);
+unsigned char  set_start(CAN_TypeDef* CANx);
+
+#endif
+

+ 13 - 11
bsp/ls1cdev/libraries/ls1c_regs.h

@@ -1,4 +1,4 @@
-// Áúо1cÍâÉè¼Ä´æÆ÷
+// 龙芯1c外设寄存器
 
 
 #ifndef __OPENLOONGSON_LS1C_REGS_H
@@ -7,12 +7,12 @@
 
 
 
-// ʱÖÓÏà¹Ø¼Ä´æÆ÷µØÖ·
+// 时钟相关寄存器地�
 #define LS1C_START_FREQ                     (0xbfe78030)
 #define LS1C_CLK_DIV_PARAM                  (0xbfe78034)
 
 
-// gpioÏà¹Ø¼Ä´æÆ÷µØÖ·
+// gpio相关寄存器地�
 #define LS1C_GPIO_CFG0                      (0xbfd010c0)
 #define LS1C_GPIO_EN0                       (0xbfd010d0)
 #define LS1C_GPIO_IN0                       (0xbfd010e0)
@@ -35,7 +35,7 @@
 
 
 
-// ¸´ÓÃÏà¹Ø¼Ä´æÆ÷
+// �用相关寄存器
 #define LS1C_CBUS_FIRST0                    (0xbfd011c0)
 #define LS1C_CBUS_SECOND0                   (0xbfd011d0)
 #define LS1C_CBUS_THIRD0                    (0xbfd011e0)
@@ -61,20 +61,22 @@
 #define LS1C_CBUS_FIFTH3                    (0xbfd0120c)
 
 
-// PWM¼Ä´æÆ÷Æ«ÒÆ
+// PWM寄存器�移
 #define LS1C_PWM_CNTR                       (0x0)
 #define LS1C_PWM_HRC                        (0x4)
 #define LS1C_PWM_LRC                        (0x8)
 #define LS1C_PWM_CTRL                       (0xC)
-// PWM»ùµØÖ·
+// PWM基地�
 #define LS1C_REG_BASE_PWM0                  (0xbfe5c000)
 #define LS1C_REG_BASE_PWM1                  (0xbfe5c010)
 #define LS1C_REG_BASE_PWM2                  (0xbfe5c020)
 #define LS1C_REG_BASE_PWM3                  (0xbfe5c030)
 
+//CAN基地�
+#define  LS1C_REG_BASE_CAN0				    (0xbfe50000)
+#define  LS1C_REG_BASE_CAN1					(0xbfe54000)
 
-
-// ÖжÏÅäÖüĴæÆ÷
+// 中断�置寄存器
 #define LS1C_INT0_SR                        (0xbfd01040)
 #define LS1C_INT0_EN                        (0xbfd01044)
 #define LS1C_INT0_SET                       (0xbfd01048)
@@ -111,18 +113,18 @@
 #define LS1C_INT4_EDGE                      (0xbfd010b4)
 
 
-// I2C¼Ä´æÆ÷
+// I2C寄存器
 #define LS1C_I2C0_BASE                      (0xbfe58000)
 #define LS1C_I2C1_BASE                      (0xbfe68000)
 #define LS1C_I2C2_BASE                      (0xbfe70000)
 
 
-// SPI¼Ä´æÆ÷
+// SPI寄存器
 #define LS1C_SPI0_BASE                      (0xbfe80000)
 #define LS1C_SPI1_BASE                      (0xbfec0000)
 
 
-// ´®¿Ú¼Ä´æÆ÷
+// 串�寄存器
 #define LS1C_UART0_BASE                     (0xbfe40000)
 #define LS1C_UART1_BASE                     (0xbfe44000)
 #define LS1C_UART2_BASE                     (0xbfe48000)