bs_bcu_app/drv/drv_stm32f4xx/drv_can.c

425 lines
14 KiB
C
Raw Normal View History

2024-11-07 17:24:19 +08:00
#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[kCanInterrupt_End];
CAN_TypeDef* reg;
}Stm32CanProp;
static KitResult drv_can_set_clock_gpio(CanDev dev, uint16_t rx_io, uint16_t tx_io);
static KitIrqCall can_irq_call[kCanDev_End][kCanInterrupt_End];
static const Stm32CanProp stm32_can[kCanDev_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(CanDev dev)
{
uint8_t mailbox = 0xFF;
KIT_ASSERT_PARAM(dev < kCanDev_End);
if(dev < kCanDev_End)
mailbox = can_mailbox_tab[(stm32_can[dev].reg->TSR >> 26) & 0x07];
return mailbox;
}
KitResult drv_can_send(CanDev dev, CanMsg *msg)
{
uint8_t id_move = 3, mailbox;
KitResult res = kKitResult_ParamErr;
CAN_TypeDef *can_reg;
KIT_ASSERT_PARAM(msg != NULL);
KIT_ASSERT_PARAM(dev < kCanDev_End);
if((dev < kCanDev_End) && (msg != NULL))
{
can_reg = stm32_can[dev].reg;
mailbox = can_mailbox_tab[(can_reg->TSR >> 26) & 0x07];
if (mailbox != 0xFF)
{
if (msg->ide == kCanIde_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 = kKitResult_Ok;
}
else
{
res = kKitResult_OverFlow;
}
}
return res;
}
KitResult drv_can_receive(CanDev dev, CanMsg* msg)
{
KitResult res = kKitResult_ParamErr;
CAN_FIFOMailBox_TypeDef fifo;
KIT_ASSERT_PARAM(msg != NULL);
KIT_ASSERT_PARAM(dev < kCanDev_End);
if((dev < kCanDev_End) && (msg != NULL))
{
fifo = stm32_can[dev].reg->sFIFOMailBox[0];
/* Get the Id */
msg->rtr = (CanRtr)(0x00000001 & fifo.RIR >> 1);
msg->ide = (CanIde)(0x00000001 & fifo.RIR >> 2);
if (msg->ide == kCanIde_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 = kKitResult_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 KitResult drv_can_set_clock_gpio(CanDev dev, uint16_t rx_idx, uint16_t tx_idx)
{
KitResult res = kKitResult_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 kCanDev_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 = kKitResult_ParamErr;
break;
#if defined(STM32F10X_CL) || defined(STM32F40_41xxx) || defined(STM32F429_439xx)
//使用CAN2接收需要使能CAN1时钟
case kCanDev_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
res = kKitResult_ParamErr;
break;
#endif
default:
res = kKitResult_ParamErr;
break;
}
return res;
}
//默认全部关联到FIFO0
void can_set_list_filter(uint8_t channel, CanIde 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 < kCanIde_End);
KIT_ASSERT_PARAM(rtr < kCanRtr_End);
bit = KIT_CREAT_BIT(channel);
CAN1->FMR |= CAN_FMR_FINIT; //进入CAN配置模式
CAN1->FM1R |= bit; //列表模式
CAN1->FS1R |= bit; //32位数据长度
id_move = 3;
if(ide == kCanIde_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, CanIde 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 < kCanIde_End);
KIT_ASSERT_PARAM(rtr < kCanRtr_End);
bit = KIT_CREAT_BIT(channel);
CAN1->FMR |= CAN_FMR_FINIT; //进入CAN配置模式
CAN1->FM1R &= ~bit; //屏蔽模式
CAN1->FS1R |= bit; //32位数据长度
id_move = 3;
if(ide == kCanIde_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倍数,50036M的APB1Periph时钟频率计算5kbps时在(SJW_1tq, BS1_6tq, BS2_1tq)900, 900 / (baud_rate/5)
*使CAN2必须使能CAN1时钟
*CAN初始化同步到总线使用时间根据情况而定
*使FIFO0FIFO0
*CAN1过滤器起始地址为014CAN2为14共有14个
*01
*
----------------------------------------------------------------------------------------------------------------------------------------*/
KitResult drv_can_init(CanDev dev, uint32_t baud_rate, uint16_t rx_io, uint16_t tx_io)
{
uint32_t tmp;
KitResult res;
CAN_TypeDef *can_reg;
KIT_ASSERT_PARAM(dev < kCanDev_End);
KIT_ASSERT_PARAM(((baud_rate % 5) == 0) && (baud_rate <= 500));
res = drv_can_set_clock_gpio(dev, rx_io, tx_io);
if(res == kKitResult_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_CREAT_BIT(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[kCanInterrupt_End] = {0x02, 0x01};
KitResult drv_can_set_interrupt(CanDev dev, CanInterrupt it_type, uint16_t priority, KitIrqCall call)
{
KitResult res;
KIT_ASSERT_PARAM((dev < kCanDev_End) && (it_type < kCanInterrupt_End) && (call != NULL));
if((dev < kCanDev_End) && (it_type < kCanInterrupt_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 = kKitResult_Ok;
}
else
{
res = kKitResult_ParamErr;
}
return res;
}
KitResult drv_can_ctrl_interrupt(CanDev dev, CanInterrupt it_type, bool is_enable)
{
KitResult res;
KIT_ASSERT_PARAM((dev < kCanDev_End) && (it_type < kCanInterrupt_End));
if((dev < kCanDev_End) && (it_type < kCanInterrupt_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 = kKitResult_Ok;
}
else
{
res = kKitResult_ParamErr;
}
return res;
}
void drv_can_rx_irq_handler(CanDev dev)
{
CanMsg msg;
if(can_irq_call[dev][kCanInterrupt_Rx] != NULL)
{
while((stm32_can[dev].reg->RF0R & 0x03) != 0)
{
drv_can_receive(dev, &msg);
can_irq_call[dev][kCanInterrupt_Rx](kKitResult_Ok, &msg);
}
}
else
{
//清除中断标志,防止一直进中断
stm32_can[dev].reg->RF0R |= CAN_RF0R_RFOM0;
}
}
void drv_can_tx_irq_handler(CanDev dev)
{
stm32_can[dev].reg->TSR |= 0x00010101;
if(can_irq_call[dev][kCanInterrupt_Tx] != NULL)
{
can_irq_call[dev][kCanInterrupt_Tx](kKitResult_Ok, NULL);
}
}
void CAN1_RX0_IRQHandler(void)
{
drv_can_rx_irq_handler(kCanDev_1);
}
void CAN1_TX_IRQHandler (void)
{
drv_can_tx_irq_handler(kCanDev_1);
}
#if defined(STM32F10X_CL) || defined(STM32F40_41xxx) || defined(STM32F429_439xx)
void CAN2_RX0_IRQHandler(void)
{
drv_can_rx_irq_handler(kCanDev_2);
}
void CAN2_TX_IRQHandler (void)
{
drv_can_tx_irq_handler(kCanDev_2);
}
#endif