#include "drv_clk.h" #include "drv_can.h" #include "drv_gpio.h" #include "drv_misc.h" #include "kit_debug.h" #define CAN_INIT_TIMEOUT (0xFFF0u) #define CAN_SJW_1tq (0u) #define CAN_BS2_1tq (0u) #define CAN_BS2_2tq (1u) #define CAN_BS1_4tq (3u) #define CAN_BS1_6tq (5u) #define CAN_BS1_13tq (12u) #define CAN_BS1_16tq (15u) #define CAN_RTR_DATA (0u) #define GPIO_REMAP1_CAN1 ((uint32_t)0x00004000) #define GPIO_REMAP2_CAN1 ((uint32_t)0x00006000) #define GPIO_REMAP_CAN2 ((uint32_t)0x00400000) typedef struct { uint8_t irq[kcan_interrupt_e_End]; CAN_TypeDef* reg; }Stm32CanProp; static kit_ret_e drv_can_set_clock_gpio(can_dev_e dev, uint16_t rx_io, uint16_t tx_io); static KitIrqCall can_irq_call[kcan_dev_e_End][kcan_interrupt_e_End]; static const Stm32CanProp stm32_can[kcan_dev_e_End] = { #if defined(STM32F10X_CL) || defined(STM32F40_41xxx) || defined(STM32F429_439xx) {{CAN1_RX0_IRQn, CAN1_TX_IRQn}, CAN1}, {{CAN2_RX0_IRQn, CAN2_TX_IRQn}, CAN2}, #else {{USB_LP_CAN1_RX0_IRQn, USB_HP_CAN1_TX_IRQn}, CAN1}, #endif }; const uint8_t can_mailbox_tab[8] = {0xFF, 0, 1, 0, 2, 0, 1, 0}; uint8_t drv_can_get_mailbox(can_dev_e dev) { uint8_t mailbox = 0xFF; KIT_ASSERT_PARAM(dev < kcan_dev_e_End); if(dev < kcan_dev_e_End) mailbox = can_mailbox_tab[(stm32_can[dev].reg->TSR >> 26) & 0x07]; return mailbox; } kit_ret_e drv_can_send(can_dev_e dev, CanMsg *msg) { uint8_t id_move = 3, mailbox; kit_ret_e res = kKit_Ret_ParamErr; CAN_TypeDef *can_reg; KIT_ASSERT_PARAM(msg != NULL); KIT_ASSERT_PARAM(dev < kcan_dev_e_End); if((dev < kcan_dev_e_End) && (msg != NULL)) { can_reg = stm32_can[dev].reg; mailbox = can_mailbox_tab[(can_reg->TSR >> 26) & 0x07]; if (mailbox != 0xFF) { if (msg->ide == kcan_frame_type_e_Std) { id_move = 21; } //write identifier can_reg->sTxMailBox[mailbox].TIR = (msg->id.value << id_move) | (msg->ide << 2) | (msg->rtr << 1); //write length can_reg->sTxMailBox[mailbox].TDTR = msg->len & 0x0F; //write data can_reg->sTxMailBox[mailbox].TDLR = msg->data.value[0]; can_reg->sTxMailBox[mailbox].TDHR = msg->data.value[1]; //request send can_reg->sTxMailBox[mailbox].TIR |= 0x00000001; res = kKit_Ret_Ok; } else { res = kKit_Ret_OverFlow; } } return res; } kit_ret_e drv_can_receive(can_dev_e dev, CanMsg* msg) { kit_ret_e res = kKit_Ret_ParamErr; CAN_FIFOMailBox_TypeDef fifo; KIT_ASSERT_PARAM(msg != NULL); KIT_ASSERT_PARAM(dev < kcan_dev_e_End); if((dev < kcan_dev_e_End) && (msg != NULL)) { fifo = stm32_can[dev].reg->sFIFOMailBox[0]; /* Get the Id */ msg->rtr = (CanRtr)(0x00000001 & fifo.RIR >> 1); msg->ide = (can_frame_type_e)(0x00000001 & fifo.RIR >> 2); if (msg->ide == kcan_frame_type_e_Std) msg->id.value = (uint32_t)0x000007FF & (fifo.RIR >> 21); else msg->id.value = (uint32_t)0x1FFFFFFF & (fifo.RIR >> 3); msg->len = (uint8_t)0x0F & fifo.RDTR; msg->data.value[0] = fifo.RDLR; msg->data.value[1] = fifo.RDHR; /* Release the FIFO */ stm32_can[dev].reg->RF0R |= CAN_RF0R_RFOM0; res = kKit_Ret_Ok; } return res; } /********************************************************************************** * Func CAN1_REMAP0 CAN1_REMAP1 CAN1_REMAP2 CAN2_REMAP0 CAN2_REMAP1 * CAN_RX PA11 PB8 PD0 PB12 PB5 * CAN_TX PA12 PB9 PD1 PB13 PB6 **********************************************************************************/ static kit_ret_e drv_can_set_clock_gpio(can_dev_e dev, uint16_t rx_idx, uint16_t tx_idx) { kit_ret_e res = kKit_Ret_Ok; uint32_t rx_io = drv_gpio_get_actual_io(rx_idx); uint32_t tx_io = drv_gpio_get_actual_io(tx_idx); switch (dev) { case kcan_dev_e_1: RCC->APB1ENR |= RCC_APB1Periph_CAN1; if((rx_io == GPIO_PORT_PIN(kGpioPort_A, 11)) && (tx_io == GPIO_PORT_PIN(kGpioPort_A, 12))) { drv_gpio_set_af(kGpioPort_A, 11, 9); drv_gpio_set_af(kGpioPort_A, 12, 9); } else if((rx_io == GPIO_PORT_PIN(kGpioPort_B, 8)) && (tx_io == GPIO_PORT_PIN(kGpioPort_B, 9))) { drv_gpio_set_af(kGpioPort_B, 8, 9); drv_gpio_set_af(kGpioPort_B, 9, 9); } else if((rx_io == GPIO_PORT_PIN(kGpioPort_D, 0)) && (tx_io == GPIO_PORT_PIN(kGpioPort_D, 1))) { drv_gpio_set_af(kGpioPort_D, 0, 9); drv_gpio_set_af(kGpioPort_D, 1, 9); } else res = kKit_Ret_ParamErr; break; #if defined(STM32F10X_CL) || defined(STM32F40_41xxx) || defined(STM32F429_439xx) //使用CAN2接收需要使能CAN1时钟 case kcan_dev_e_2: RCC->APB1ENR |= RCC_APB1Periph_CAN1; RCC->APB1ENR |= RCC_APB1Periph_CAN2; if((rx_io == GPIO_PORT_PIN(kGpioPort_B, 12)) && (tx_io == GPIO_PORT_PIN(kGpioPort_B, 13))) { drv_gpio_set_af(kGpioPort_B, 12, 9); drv_gpio_set_af(kGpioPort_B, 13, 9); } else if((rx_io == GPIO_PORT_PIN(kGpioPort_B, 5)) && (tx_io == GPIO_PORT_PIN(kGpioPort_B, 6))) { drv_gpio_set_af(kGpioPort_B, 5, 9); drv_gpio_set_af(kGpioPort_B, 6, 9); } else if((rx_io == GPIO_PORT_PIN(kGpioPort_D, 0)) && (tx_io == GPIO_PORT_PIN(kGpioPort_D, 1))) { drv_gpio_set_af(kGpioPort_D, 0, 9); drv_gpio_set_af(kGpioPort_D, 1, 9); } else res = kKit_Ret_ParamErr; break; #endif default: res = kKit_Ret_ParamErr; break; } return res; } //默认全部关联到FIFO0 void can_set_list_filter(uint8_t channel, can_frame_type_e ide, CanRtr rtr, uint32_t rcv_id1, uint32_t rcv_id2) { uint8_t id_move = 3; uint32_t bit; KIT_ASSERT_PARAM(channel < 28); KIT_ASSERT_PARAM(ide < kcan_frame_type_e_End); KIT_ASSERT_PARAM(rtr < kCanRtr_End); bit = KIT_BIT_MASK_32(channel); CAN1->FMR |= CAN_FMR_FINIT; //进入CAN配置模式 CAN1->FM1R |= bit; //列表模式 CAN1->FS1R |= bit; //32位数据长度 id_move = 3; if(ide == kcan_frame_type_e_Std) { id_move = 21; } CAN1->sFilterRegister[channel].FR1 = (rcv_id1 << id_move) | (ide << 2) | (rtr << 1); CAN1->sFilterRegister[channel].FR2 = (rcv_id2 << id_move) | (ide << 2) | (rtr << 1); CAN1->FA1R |= bit; CAN1->FMR &= ~CAN_FMR_FINIT; } //屏蔽位模式 0不关心 1必须匹配 void can_set_mask_filter(uint8_t channel, can_frame_type_e ide, CanRtr rtr, uint32_t rcv_id, uint32_t mask_id) { uint8_t id_move; uint32_t bit; KIT_ASSERT_PARAM(channel < 28); KIT_ASSERT_PARAM(ide < kcan_frame_type_e_End); KIT_ASSERT_PARAM(rtr < kCanRtr_End); bit = KIT_BIT_MASK_32(channel); CAN1->FMR |= CAN_FMR_FINIT; //进入CAN配置模式 CAN1->FM1R &= ~bit; //屏蔽模式 CAN1->FS1R |= bit; //32位数据长度 id_move = 3; if(ide == kcan_frame_type_e_Std) { id_move = 21; } CAN1->sFilterRegister[channel].FR1 = (rcv_id << id_move) | (ide << 2) | CAN_RTR_DATA; CAN1->sFilterRegister[channel].FR2 = (mask_id << id_move) | (ide << 2) | CAN_RTR_DATA; CAN1->FA1R |= bit; CAN1->FMR &= ~CAN_FMR_FINIT; } /*----------------------------------------STM32F10x MCR(master control register)寄存器--------------------------------------------------- | Bit | 16 | 15 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ----------------------------------------------------------------------------------------------------------------------------------------- | Item | DBF | RESET | TTCM | ABOM | AWUM | NART | RFLM | TXFP | SLEEP | INRQ | ----------------------------------------------------------------------------------------------------------------------------------------- | DEF | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | ----------------------------------------------------------------------------------------------------------------------------------------- | Value |1 调试时冻结 |0 不复位 |0 禁用时间触发模式|1 硬件控制Buf off|1 硬件唤醒|0 自动重发|1 满停止接收|1 按顺序发送| | | *软件通过置位SLEEP来请求进入睡眠模式,置位后CAN在当前活动完成后将立即进入睡眠模式,当AWUM置位后,也可以被硬件唤醒清零 *CAN波特率=APB总线频率/BRP分频器/(1+tBS1+tBS2) 5kbps = 42000/900/(1+6+1) *波特率必须是5kbps倍数,小于500,以36M的APB1Periph时钟频率计算,5kbps时在(SJW_1tq, BS1_6tq, BS2_1tq)预分频为900, 其他波特率分频计算 900 / (baud_rate/5) *使用CAN2必须使能CAN1时钟 *CAN初始化同步到总线使用时间根据情况而定,设备较多,有报文需要等待的时间较长 *本驱动只使用FIFO0,滤波器都关联到FIFO0 *CAN1过滤器起始地址为0,共有14个,CAN2为14共有14个 *0表示不过滤,1表示对应位要过滤 *配置过滤器时必须处于初始化模式 ----------------------------------------------------------------------------------------------------------------------------------------*/ kit_ret_e drv_can_init(can_dev_e dev, uint32_t baud_rate, uint16_t rx_io, uint16_t tx_io) { uint32_t tmp; kit_ret_e res; CAN_TypeDef *can_reg; KIT_ASSERT_PARAM(dev < kcan_dev_e_End); KIT_ASSERT_PARAM(((baud_rate % 5) == 0) && (baud_rate <= 500)); res = drv_can_set_clock_gpio(dev, rx_io, tx_io); if(res == kKit_Ret_Ok) { can_reg = stm32_can[dev].reg; // leave sleep mode can_reg->MCR &= (~(uint32_t)CAN_MCR_SLEEP); // request init mode can_reg->MCR |= CAN_MCR_INRQ ; // wait init acknowledge res |= kit_wait_flag(&can_reg->MSR, CAN_MSR_INAK, CAN_INIT_TIMEOUT); //cfg main register 自动退出离线 | 多个报文同时等待发送由请求顺序决定 | 自动重发 tmp = (CAN_MCR_ABOM | CAN_MCR_TXFP | CAN_MCR_RFLM); can_reg->MCR |= tmp; //Baud rate prescaler BRP = CLOCK_PCLK1_FREQ / (SJW + BS1 + BS2) / baud_rate - 1 switch(baud_rate) { case 125: case 250: can_reg->BTR = ((uint32_t)CAN_SJW_1tq << 24) | ((uint32_t)CAN_BS1_6tq << 16) | ((uint32_t)CAN_BS2_1tq << 20) | (CLOCK_PCLK1_FREQ / 8000 / baud_rate - 1); break; case 500: case 1000: can_reg->BTR = ((uint32_t)CAN_SJW_1tq << 24) | ((uint32_t)CAN_BS1_4tq << 16) | ((uint32_t)CAN_BS2_1tq << 20) | (CLOCK_PCLK1_FREQ / 6000 / baud_rate - 1); break; default: can_reg->BTR = ((uint32_t)CAN_SJW_1tq << 24) | ((uint32_t)CAN_BS1_6tq << 16) | ((uint32_t)CAN_BS2_1tq << 20) | (CLOCK_PCLK1_FREQ / 8000 / 250 - 1); break; } //leave init mode can_reg->MCR &= ~(uint32_t)CAN_MCR_INRQ; // Wait the normal acknowledge,当总线有报文时等待时间会较长 res |= kit_wait_flag(&can_reg->MSR, CAN_MSR_INAK, CAN_INIT_TIMEOUT); //默认接收任何ID的扩展帧和标准帧 dev *= 14; //通道2起始过滤器为14 CAN1->FMR |= CAN_FMR_FINIT; //进入CAN配置模式 CAN1->FM1R = 0; //所有过滤器组工作在屏蔽位模式 CAN1->FA1R |= KIT_BIT_MASK_32(dev); CAN1->sFilterRegister[dev].FR1 = 0; //所有位不关心 CAN1->sFilterRegister[dev].FR2 = 0; CAN1->FMR &= ~CAN_FMR_FINIT; } KIT_ASSERT_RES(dev, res); return res; } const uint8_t can_interrupt_bit[kcan_interrupt_e_End] = {0x02, 0x01}; kit_ret_e drv_can_set_interrupt(can_dev_e dev, can_interrupt_e it_type, uint16_t priority, KitIrqCall call) { kit_ret_e res; KIT_ASSERT_PARAM((dev < kcan_dev_e_End) && (it_type < kcan_interrupt_e_End) && (call != NULL)); if((dev < kcan_dev_e_End) && (it_type < kcan_interrupt_e_End) && (call != NULL)) { can_irq_call[dev][it_type] = call; drv_misc_set_nvic(stm32_can[dev].irq[it_type], priority); stm32_can[dev].reg->IER |= can_interrupt_bit[it_type]; res = kKit_Ret_Ok; } else { res = kKit_Ret_ParamErr; } return res; } kit_ret_e drv_can_ctrl_interrupt(can_dev_e dev, can_interrupt_e it_type, bool is_enable) { kit_ret_e res; KIT_ASSERT_PARAM((dev < kcan_dev_e_End) && (it_type < kcan_interrupt_e_End)); if((dev < kcan_dev_e_End) && (it_type < kcan_interrupt_e_End)) { if (is_enable == true) stm32_can[dev].reg->IER |= can_interrupt_bit[it_type]; else stm32_can[dev].reg->IER &= ~can_interrupt_bit[it_type]; res = kKit_Ret_Ok; } else { res = kKit_Ret_ParamErr; } return res; } void drv_can_rx_irq_handler(can_dev_e dev) { CanMsg msg; if(can_irq_call[dev][kcan_interrupt_e_Rx] != NULL) { while((stm32_can[dev].reg->RF0R & 0x03) != 0) { drv_can_receive(dev, &msg); can_irq_call[dev][kcan_interrupt_e_Rx](kKit_Ret_Ok, &msg); } } else { //清除中断标志,防止一直进中断 stm32_can[dev].reg->RF0R |= CAN_RF0R_RFOM0; } } void drv_can_tx_irq_handler(can_dev_e dev) { stm32_can[dev].reg->TSR |= 0x00010101; if(can_irq_call[dev][kcan_interrupt_e_Tx] != NULL) { can_irq_call[dev][kcan_interrupt_e_Tx](kKit_Ret_Ok, NULL); } } void CAN1_RX0_IRQHandler(void) { drv_can_rx_irq_handler(kcan_dev_e_1); } void CAN1_TX_IRQHandler(void) { drv_can_tx_irq_handler(kcan_dev_e_1); } #if defined(STM32F10X_CL) || defined(STM32F40_41xxx) || defined(STM32F429_439xx) void CAN2_RX0_IRQHandler(void) { drv_can_rx_irq_handler(kcan_dev_e_2); } void CAN2_TX_IRQHandler(void) { drv_can_tx_irq_handler(kcan_dev_e_2); } #endif