425 lines
14 KiB
C
425 lines
14 KiB
C
#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倍数,小于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表示对应位要过滤
|
||
*配置过滤器时必须处于初始化模式
|
||
----------------------------------------------------------------------------------------------------------------------------------------*/
|
||
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
|
||
|
||
|