(1)can.c
#define CAN_BUS_ENABLE 1
#define CAN_BUS_DISABLE 0
#define CAN2_FILTER_S 14
typedef struct __can_gpio_pin_t{
uint32_t pin_bit;
uint32_t gpio_rcc;
GPIO_TypeDef *gpio_port;
}can_gpio_pin_t;
typedef struct __send_status_t{
uint8_t mbox_s;
}send_status_t;
typedef struct _can_cfg_t{
uint8_t can_dev_id;
uint8_t pin_map;
uint8_t fifo_no;
uint8_t filter_start;
can_gpio_pin_t r_pin;
can_gpio_pin_t t_pin;
uint32_t can_rcc;
CAN_TypeDef* can_ch;
send_status_t txs;
uint8_t irq;
uint8_t it_flag;
uint8_t res[2];
}can_cfg_t;
typedef struct __can_tq_t {
uint16_t can_baudrate;
uint16_t can_prescaler;
uint8_t can_syn_jump_width;
uint8_t can_time_bit_seg1;
uint8_t can_time_bit_seg2;
uint8_t can_res;
}can_tq_t;
static can_tq_t can_baud_array[] = {
{ 5, 400, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 10, 200, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 20, 100, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 40, 50, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 50, 40, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 80, 25, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 100, 20, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 125, 16, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 200, 10, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 250, 36, CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq },
{ 400, 5, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 500, 4, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 666, 3, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
{ 800, 11, CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq },
{ 1000, 9, CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq },
{ 0 },
};
static can_cfg_t can_cfg[CAN_DEV_CNT]={
[CAN_DEV1] = {
.can_dev_id = CAN_DEV1,
.fifo_no = CAN_Filter_FIFO0,
.t_pin = { GPIO_Pin_12, RCC_APB2Periph_GPIOA, GPIOA },
.r_pin = { GPIO_Pin_11, RCC_APB2Periph_GPIOA, GPIOA },
.pin_map = 0,
.can_rcc = RCC_APB1Periph_CAN1,
.can_ch = CAN1,
.filter_start = 0,
.irq = CAN1_RX0_IRQn,
.it_flag = CAN_IT_FMP0,
},
[CAN_DEV2] = {
.can_dev_id = CAN_DEV2,
.fifo_no = CAN_Filter_FIFO1,
.t_pin = { GPIO_Pin_13, RCC_APB2Periph_GPIOB, GPIOB },
.r_pin = { GPIO_Pin_12, RCC_APB2Periph_GPIOB, GPIOB },
.pin_map = 0,
.can_rcc = RCC_APB1Periph_CAN2,
.can_ch = CAN2,
.filter_start = CAN2_FILTER_S,
.irq = CAN2_RX1_IRQn,
.it_flag = CAN_IT_FMP1,
}
};
static can_tq_t *__get_tp(int br)
{
int i = 0;
while(can_baud_array[i].can_baudrate != 0){
if(can_baud_array[i].can_baudrate == br){
return &can_baud_array[i];
}
i++;
}
return NULL;
}
static void __can_enable(int can_dev, u32 val)
{
if(can_dev == CAN_DEV1){
if(val == CAN_BUS_ENABLE){
_debug(SYS_INFO, "CAN_1 bus enable\n");
pp_ctrl_set(PIN_CAN1_STB,0);
}else{
pp_ctrl_set(PIN_CAN1_STB,1);
}
}else if(can_dev == CAN_DEV2){
if(val == CAN_BUS_ENABLE){
_debug(SYS_INFO, "CAN_2 bus enable\n");
pp_ctrl_set(PIN_CAN2_STB,0);
}else{
pp_ctrl_set(PIN_CAN2_STB,1);
}
}
}
int can_dev_init(int can_dev, int can_mode, int brp)
{
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
can_cfg_t* pparam = &can_cfg[can_dev];
_debug(SYS_INFO, "CAN%d Init start\n", pparam->can_dev_id + 1);
CAN_DeInit(pparam->can_ch);
RCC_APB1PeriphClockCmd(pparam->can_rcc, ENABLE);
RCC_APB2PeriphClockCmd(pparam->r_pin.gpio_rcc | pparam->t_pin.gpio_rcc, ENABLE);
GPIO_InitStructure.GPIO_Pin = pparam->r_pin.pin_bit;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(pparam->r_pin.gpio_port, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = pparam->t_pin.pin_bit;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(pparam->t_pin.gpio_port, &GPIO_InitStructure);
u8 ret_can;
can_tq_t* pcan_baud = __get_tp(brp);
if (pcan_baud == NULL) {
_debug(SYS_INFO, "Setting BaudRate param is unqualified %d\n",brp);
return -1;
}
CAN_InitStructure.CAN_Prescaler = pcan_baud->can_prescaler;
CAN_InitStructure.CAN_SJW = pcan_baud->can_syn_jump_width;
CAN_InitStructure.CAN_BS1 = pcan_baud->can_time_bit_seg1;
CAN_InitStructure.CAN_BS2 = pcan_baud->can_time_bit_seg2;
_debug(SYS_INFO, "BaudRate = %dKHZ, can_prescaler = %d, CAN_SJW_%dtq, CAN_BS1_%dtq, CAN_BS2_%dtq \n",
pcan_baud->can_baudrate,
pcan_baud->can_prescaler,
pcan_baud->can_syn_jump_width + 1,
pcan_baud->can_time_bit_seg1 + 1,
pcan_baud->can_time_bit_seg2 + 1);
CAN_InitStructure.CAN_Mode = can_mode;
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = ENABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;
ret_can = CAN_Init(pparam->can_ch, &CAN_InitStructure);
if (ret_can == 0) {
_debug(SYS_INFO, "CAN%d Initialize is failed \n", pparam->can_dev_id + 1);
return -1;
}
#if 1
CAN_ITConfig(pparam->can_ch, pparam->it_flag, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = pparam->irq;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
_debug(SYS_INFO, "CAN%d Init end\n", pparam->can_dev_id + 1);
return 0;
}
int p_can_open(int can_dev,int bps)
{
int ret = can_dev_init(can_dev,CAN_Mode_Normal,bps);
if(ret == 0){
__can_enable(can_dev,CAN_BUS_ENABLE);
}
return ret;
}
void p_can_close(int can_dev)
{
NVIC_InitTypeDef NVIC_InitStructure = {0};
can_cfg_t* pparam = &can_cfg[can_dev];
__can_enable(can_dev,CAN_BUS_DISABLE);
CAN_ITConfig(pparam->can_ch, pparam->it_flag, DISABLE);
NVIC_InitStructure.NVIC_IRQChannel = pparam->irq;
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
NVIC_Init(&NVIC_InitStructure);
CAN_DeInit(pparam->can_ch);
}
int p_can_read(int can_dev, can_msg_t* msg)
{
can_cfg_t* pparam = &can_cfg[can_dev];
CanRxMsg RxMessage;
if (CAN_MessagePending(pparam->can_ch, CAN_FIFO0)) {
CAN_Receive(pparam->can_ch, CAN_FIFO0, &RxMessage);
} else if (CAN_MessagePending(pparam->can_ch, CAN_FIFO1)) {
CAN_Receive(pparam->can_ch, CAN_FIFO1, &RxMessage);
} else {
_error("read error can msg");
return 0;
}
if(CAN_Id_Standard == RxMessage.IDE){
msg->id_type = CAN_ID_ST;
msg->id = RxMessage.StdId;
_debug(SYS_INFO, "CAN%d FIFO0 receive msg Std_id = 0x%x ...\n", pparam->can_dev_id + 1, RxMessage.StdId);
}else{
msg->id_type = CAN_ID_EX;
msg->id = RxMessage.ExtId;
_debug(SYS_INFO, "CAN%d FIFO1 receive msg EXT_id = 0x%x ...\n", pparam->can_dev_id + 1, RxMessage.ExtId);
}
if(CAN_RTR_Data == RxMessage.RTR){
msg->id_frame = CAN_FR_DATA;
}else{
msg->id_frame = CAN_FR_REMOTE;
}
msg->len = RxMessage.DLC;
memcpy(msg->data,RxMessage.Data, RxMessage.DLC);
return RxMessage.DLC;
}
int p_can_send(int can_dev, can_msg_t* msg)
{
can_cfg_t* pparam = &can_cfg[can_dev];
CanTxMsg TxMsg = {0};
if(msg->id_type == CAN_ID_ST){
TxMsg.IDE = CAN_Id_Standard;
TxMsg.StdId = msg->id;
}else{
TxMsg.IDE = CAN_Id_Extended;
TxMsg.ExtId = msg->id;
}
if(msg->id_frame == CAN_FR_DATA){
TxMsg.RTR = CAN_RTR_Data;
}else{
TxMsg.RTR = CAN_RTR_Remote;
}
TxMsg.DLC = msg->len;
memcpy(TxMsg.Data,msg->data,TxMsg.DLC);
pparam->txs.mbox_s = CAN_TxStatus_NoMailBox;
uint8_t tx_mbox = CAN_Transmit(pparam->can_ch, &TxMsg);
if (tx_mbox == CAN_TxStatus_NoMailBox) {
_debug(SYS_INFO, "CAN Transmit Status is No MailBox\n");
return -1;
}
pparam->txs.mbox_s = tx_mbox;
return 0;
}
int p_can_send_ok(int can_dev)
{
can_cfg_t* pparam = &can_cfg[can_dev];
if(pparam->txs.mbox_s == CAN_TxStatus_NoMailBox){
return -1;
}
if(CAN_TransmitStatus(pparam->can_ch, pparam->txs.mbox_s) == CAN_TxStatus_Failed){
return 0;
}
return 1;
}
#define CAN_ID_STD_STD CAN_ID_ST
#define CAN_ID_EXT_EXT CAN_ID_EX
#define CAN_ID_STD_EXT 2
#define CAN_ID_EXT_STD 3
static int __genc_ids(int format,uint32_t *ids,uint32_t *pout)
{
switch (format) {
case CAN_ID_STD_STD:
pout[0] = (ids[0] << 21) | CAN_Id_Standard;
pout[1] = (ids[1] << 21) | CAN_Id_Standard;
break;
case CAN_ID_STD_EXT:
pout[0] = (ids[0] << 21) | CAN_Id_Standard;
pout[1] = (ids[1] << 3) | CAN_Id_Extended;
break;
case CAN_ID_EXT_STD:
pout[0] = (ids[0] << 3) | CAN_Id_Extended;
pout[1] = (ids[1] << 21) | CAN_Id_Standard;
break;
case CAN_ID_EXT_EXT:
pout[0] = (ids[0] << 3) | CAN_Id_Extended;
pout[1] = (ids[1] << 3) | CAN_Id_Extended;
break;
default: {
return -1;
}
}
return 0;
}
static int __p_can_set_filter_list(int filter_id, int fifo_no, int format, uint32_t id1, uint32_t id2)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure = { 0 };
uint32_t in_ids[2] = {id1,id2};
uint32_t out_ids[2] = {0};
if(__genc_ids(format,in_ids,out_ids)){
_debug(SYS_INFO, "CAN geting id is failed \n");
return -1;
}
_debug(SYS_INFO, "filter_Id = 0x%x 0x%x, filter_number = %d, CAN_Filter_FIFO = %d\n",\
out_ids[0], out_ids[1], filter_id, fifo_no);
CAN_FilterInitStructure.CAN_FilterNumber = filter_id;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = (out_ids[0] >> 16) & 0xffff;
CAN_FilterInitStructure.CAN_FilterIdLow = out_ids[0] & 0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (out_ids[1] >> 16) & 0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = out_ids[1] & 0xffff;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = fifo_no;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
return 0;
}
static int __p_can_set_filter_mask(int filter_id, int fifo_no, int format, uint32_t id, uint32_t mask)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure = { 0 };
uint32_t in_ids[2] = {id,mask};
uint32_t out_ids[2] = {0};
if(__genc_ids(format,in_ids,out_ids)){
_debug(SYS_INFO, "CAN geting id is successed ...\n");
return -1;
}
_debug(SYS_INFO, "------ filter_Id = 0x%x 0x%x, filter_number = %d, CAN_Filter_FIFO = %d ----------\n",\
out_ids[0], out_ids[1], filter_id, fifo_no);
CAN_FilterInitStructure.CAN_FilterNumber = filter_id;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = (out_ids[0] >> 16) & 0xffff;
CAN_FilterInitStructure.CAN_FilterIdLow = out_ids[0] & 0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (out_ids[1] >> 16) & 0xffff;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = out_ids[1] & 0xffff;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = fifo_no;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
return 0;
}
int p_can_set_filter(int can_dev, int filter_mode, int format, uint32_t* ids, int id_cnt)
{
int i;
can_cfg_t* pparam = &can_cfg[can_dev];
uint32_t r_ids[28] = {0};
CAN_SlaveStartBank(CAN2_FILTER_S);
if (id_cnt & 1) {
for(i = 0; i < id_cnt; i++){
r_ids[i] = ids[i];
}
if(filter_mode == FILTER_LIST){
r_ids[i] = r_ids[i-1];
}else{
r_ids[i] = 0xffffffff;
}
id_cnt++;
}else{
for(i = 0; i < id_cnt; i++){
r_ids[i] = ids[i];
}
}
if (filter_mode == FILTER_LIST) {
for (i = 0; i < id_cnt / 2; i++) {
__p_can_set_filter_list(pparam->filter_start + i, pparam->fifo_no, format, r_ids[2*i], r_ids[2*i + 1]);
}
} else {
for (i = 0; i < id_cnt / 2; i++) {
__p_can_set_filter_mask(pparam->filter_start + i, pparam->fifo_no, format, r_ids[2*i], r_ids[2*i + 1]);
}
}
return 0;
}
(2)can.h
#ifndef __p_can_h__
#define __p_can_h__
#if 0
.word CAN2_TX_IRQHandler
.word CAN2_RX0_IRQHandler
.word CAN2_RX1_IRQHandler
.word CAN2_SCE_IRQHandler
#define CAN_Id_Standard ((uint32_t)0x00000000)
#define CAN_Id_Extended ((uint32_t)0x00000004)
#endif
typedef enum {
CAN_DEV1,
CAN_DEV2,
CAN_DEV_CNT
} CAN_DEV_E;
#define CAN_ID_ST 0
#define CAN_ID_EX 1
#define CAN_FR_DATA 0
#define CAN_FR_REMOTE 1
#define FILTER_LIST 0
#define FILTER_MASK 1
typedef struct _can_msg_t {
uint8_t id_type;
uint8_t id_frame;
uint8_t len;
uint8_t res;
uint32_t id;
uint8_t data[8];
} can_msg_t;
int can_dev_init(int can_dev, int can_mode, int brp);
int p_can_open(int can_dev,int bps);
void p_can_close(int can_dev);
int p_can_read(int can_dev,can_msg_t *msg);
int p_can_send(int can_dev,can_msg_t *msg);
int p_can_set_filter(int can_dev, int filter_mode, int format, uint32_t* ids, int id_cnt);
void p_can_task_start(int can_dev);
void p_can_task_stop(int can_dev);
void p_can_task(void);
#endif