| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673 |
- /*
- * Copyright (c) 2006-2024, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-22 QT-one first version
- */
- #include <rtdbg.h>
- #include "drv_can.h"
- #include "ht32_can_config.h"
- #ifdef BSP_USING_CAN
- #if !defined(BSP_USING_CAN)
- #error "Please define at least one BSP_USING_CAN"
- #endif
- #define CAN_UMASK_MODE 0
- #define CAN_MASK_MODE 1
- struct ht32_can_msg_type
- {
- CAN_MSG_TypeDef cfg_msg;
- uint32_t data_len;
- uint8_t data[8];
- };
- /* Baud rate mapping structure */
- struct ht32_baud_rate
- {
- enum CANBAUD rt_baud_rate;
- uint32_t us_baus_rate;
- };
- /* CAN Filter Table Configuration Structure */
- struct ht32_can_filter_config
- {
- /* Each bit represents a message;1: the message is occupied;0: the message is not occupied */
- uint32_t filter_flag;
- /* Filter table configuration information */
- CAN_MSG_TypeDef filter_mag[MSG_OBJ_TOTAL_NUM];
- };
- /* CAN Object Structures */
- struct ht32_can
- {
- char *name; /* Equipment name */
- HT_CAN_TypeDef *can_x; /* peripheral base address */
- struct can_configure cfg; /* CAN Configuration Structure */
- struct rt_can_device device; /* Inherited device options */
- struct ht32_can_filter_config filter_cfg; /* Filter Table Configuration */
- };
- /* CAN Baud Rate Mapping Table */
- static const struct ht32_baud_rate can_baud_rate_tab[] =
- {
- {CAN1MBaud, 1000000},
- {CAN800kBaud, 800000},
- {CAN500kBaud, 500000},
- {CAN250kBaud, 250000},
- {CAN125kBaud, 125000},
- {CAN100kBaud, 100000},
- {CAN50kBaud, 50000},
- {CAN20kBaud, 20000},
- {CAN10kBaud, 10000},
- };
- /* CAN Object Information */
- static struct ht32_can ht32_can_config =
- {
- .name = BSP_USING_CAN_NAME,
- .can_x = HT_CAN0,
- .cfg = {0},
- .device = RT_NULL,
- .filter_cfg = {0},
- };
- /**
- * @brief Default Filter Table Configuration
- * @param can_instance:CAN object
- * @retval
- */
- static rt_uint32_t cfg_can_default_filter(struct ht32_can *can_instance)
- {
- uint8_t filter_num = BSP_USING_CAN_MSG_NUM;
- can_instance->filter_cfg.filter_flag |= 1 << filter_num;
- can_instance->filter_cfg.filter_mag[filter_num].MsgNum = filter_num + 1;
- can_instance->filter_cfg.filter_mag[filter_num].IdType = (CAN_IdType_Enum)BSP_USING_CAN_ID_MODE;
- can_instance->filter_cfg.filter_mag[filter_num].IdMask = BSP_USING_CAN_MASK;
- can_instance->filter_cfg.filter_mag[filter_num].FrameType = (CAN_FrameType_Enum)BSP_USING_CAN_FRAME_MODE;
- can_instance->filter_cfg.filter_mag[filter_num].Id = BSP_USING_CAN_ID;
- CAN_SetRxMsg(can_instance->can_x, &can_instance->filter_cfg.filter_mag[filter_num], 1);
- return RT_EOK;
- }
- /**
- * @brief Get baud rate mapping parameters for CAN
- * @info This function is mainly used to convert the baud rate of RTT format to HT32 format baud rate
- * @param baud:CAN baud rate in RTT format
- * @retval Returns the CAN baud rate in HT32 format.
- */
- static rt_uint32_t get_can_baud_index(rt_uint32_t baud)
- {
- rt_uint32_t len, index;
- len = sizeof(can_baud_rate_tab) / sizeof(can_baud_rate_tab[0]);
- for (index = 0; index < len; index++)
- {
- if (can_baud_rate_tab[index].rt_baud_rate == baud)
- return can_baud_rate_tab[index].us_baus_rate;
- }
- return 0;
- }
- /**
- * @brief Configuring CAN Structures
- * @info This function depends on the ht32_can_config.h file
- * @param can_ck:System clock for CAN
- * @param can_buad:CAN baud rate to be configured
- * @param mode:Modes of CAN
- * @param nart:enable or disable the no automatic retransmission
- * @param CAN_InitStruct:Structures to be configured
- * @retval 1:success;0:error
- */
- static rt_uint32_t config_can_struct(uint32_t can_ck,
- uint32_t can_buad,
- uint8_t mode,
- ControlStatus nart,
- CAN_InitTypeDef* CAN_InitStruct)
- {
- uint8_t cf0_nbt = 0;
- uint32_t nominal_bit_time = 0;
- for (cf0_nbt = 25; cf0_nbt > 8; cf0_nbt--)
- {
- if ((can_ck / can_buad / cf0_nbt) > 0)
- {
- if (((can_ck / (can_ck / can_buad / cf0_nbt)) / cf0_nbt) <= can_buad)
- {
- nominal_bit_time = cf0_nbt;
- break;
- }
- }
- }
- if (cf0_nbt < 8)
- {
- return 0;
- }
- CAN_InitStruct->CAN_BRPrescaler = (can_ck / (can_buad * nominal_bit_time));
- CAN_InitStruct->CAN_SJW = HTCFG_CAN_CF0_BIT_TIME_SJW;
- CAN_InitStruct->CAN_TSEG1 = (nominal_bit_time - (nominal_bit_time * HTCFG_CAN_CF0_SAMPLE_POINT) / 100);
- CAN_InitStruct->CAN_TSEG0 = (nominal_bit_time - 1 - CAN_InitStruct->CAN_TSEG1);
- CAN_InitStruct->CAN_NART = nart;
- CAN_InitStruct->CAN_Mode = mode;
- return 1;
- }
- /**
- * @brief CAN Configuration Functions
- * @param
- * @retval
- */
- static rt_err_t ht32_can_configure(struct rt_can_device *can, struct can_configure *cfg)
- {
- CKCU_PeripClockConfig_TypeDef CKCUClock = {{ 0 }};
- struct ht32_can *can_instance = RT_NULL;
- rt_uint32_t can_baud = 0;
- rt_uint8_t can_mode = 0;
- CAN_InitTypeDef CAN_InitStruct = {0};
- RT_ASSERT(can);
- RT_ASSERT(cfg);
- can_instance = (struct ht32_can *)can->parent.user_data;
- RT_ASSERT(can_instance != RT_NULL);
- CKCUClock.Bit.AFIO = 1;
- CKCUClock.Bit.CAN0 = 1;
- CKCU_PeripClockConfig(CKCUClock, ENABLE);
- ht32_can_gpio_init(can_instance->can_x);
- /* Get baud rate */
- can_baud = get_can_baud_index(cfg->baud_rate);
- if (can_baud == 0)
- {
- return -RT_ERROR;
- }
- can_instance->cfg.baud_rate = cfg->baud_rate;
- can_instance->cfg.mode = cfg->mode;
- /* Configuring the operating mode of CAN */
- switch (cfg->mode)
- {
- case RT_CAN_MODE_NORMAL:
- can_mode = CAN_MODE_NORMAL;
- break;
- case RT_CAN_MODE_LISTEN:
- can_mode = CAN_MODE_SILENT;
- break;
- case RT_CAN_MODE_LOOPBACK:
- can_mode = CAN_MODE_LBACK;
- break;
- case RT_CAN_MODE_LOOPBACKANLISTEN:
- can_mode = CAN_MODE_SILENT | CAN_MODE_LBACK;
- break;
- default:
- return -RT_ERROR;
- }
- if (0 == (config_can_struct(_HTCFG_CF0_CK_CAN, can_baud, can_mode, DISABLE, &CAN_InitStruct)))
- {
- return -RT_ERROR;
- }
- /* Reset CAN */
- CAN_DeInit(can_instance->can_x);
- /* Initialising CAN */
- CAN_Init(can_instance->can_x, &CAN_InitStruct);
- /* Configuring the Default Filter for CAN */
- cfg_can_default_filter(can_instance);
- return RT_EOK;
- }
- /**
- * @brief CAN Control Functions
- * @param
- * @retval
- */
- rt_err_t ht32_can_control(struct rt_can_device *can, int cmd, void *arg)
- {
- rt_uint32_t argval;
- struct ht32_can *can_instance;
- struct rt_can_filter_config *filter_cfg;
- RT_ASSERT(can != RT_NULL);
- can_instance = (struct ht32_can *)can->parent.user_data;
- RT_ASSERT(can_instance != RT_NULL);
- switch (cmd)
- {
- case RT_DEVICE_CTRL_CLR_INT:/* Clear Interrupt */
- {
- argval = (rt_uint32_t) arg;
- if (argval == RT_DEVICE_FLAG_INT_RX) /* receive interruptions */
- {
- if (CAN_GetFlagStatus(can_instance->can_x, CAN_FLAG_RXOK))
- {
- /* Clear RXOK Flag */
- CAN_ClearFlag(can_instance->can_x, CAN_FLAG_RXOK);
- }
- }
- else if (argval == RT_DEVICE_FLAG_INT_TX) /* Send Interrupt */
- {
- if (CAN_GetFlagStatus(can_instance->can_x, CAN_FLAG_TXOK))
- {
- /* Clear TXOK flag*/
- CAN_ClearFlag(can_instance->can_x, CAN_FLAG_TXOK);
- }
- }
- else if (argval == RT_DEVICE_CAN_INT_ERR) /* false interruption */
- {
- /* Error Process*/
- CAN_LastErrorCode_TypeDef lec = CAN_GetLastErrorCode(can_instance->can_x);
- if (lec != NO_ERROR)
- {
- LOG_W("LEC: %d\r\n", lec);
- }
- if (CAN_GetFlagStatus(can_instance->can_x, CAN_FLAG_BOFF))
- {
- /* Recover from Bus off state.*/
- CAN_BusOffRecovery(can_instance->can_x);
- }
- }
- break;
- }
- case RT_DEVICE_CTRL_SET_INT:/* Setting Up Interruptions */
- {
- argval = (rt_uint32_t) arg;
- if (argval == RT_DEVICE_FLAG_INT_RX) /* interrupt receive mode */
- {
- LOG_W("Configuring Receive Interrupts!\r\n");
- CAN_IntConfig(can_instance->can_x, CAN_INT_EIE | CAN_INT_SIE | CAN_INT_IE, ENABLE);
- NVIC_EnableIRQ(CAN0_IRQn);
- }
- else if (argval == RT_DEVICE_FLAG_INT_TX) /* interrupt transmission mode */
- {
- LOG_W("Configuring Transmit Interrupts!\r\n");
- }
- else if (argval == RT_DEVICE_CAN_INT_ERR) /* false interruption */
- {
- LOG_W("Configuration error interrupt!\r\n");
- }
- break;
- }
- case RT_CAN_CMD_SET_FILTER:/* Configuring the Hardware Filter Table */
- {
- int i = 0;
- uint8_t filter_num = 0;
- uint32_t idmask = 0;
- if (RT_NULL == arg)
- {
- /* default filter config */
- cfg_can_default_filter(can_instance);
- }
- else
- {
- filter_cfg = (struct rt_can_filter_config *)arg;
- if (filter_cfg->count > MSG_OBJ_TOTAL_NUM)
- {
- LOG_W("Filter list length exceeds the limit(max 32)!");
- return -RT_ERROR;
- }
- for (i = 0; i < filter_cfg->count; i++)
- {
- /* Specify the filter table number or no */
- if (filter_cfg->items[i].hdr_bank == -1)
- {
- filter_num = i;
- }
- else
- {
- if (filter_cfg->items[i].hdr_bank > MSG_OBJ_TOTAL_NUM)
- {
- LOG_W("Filter List Number Out of Limits(1-32)!");
- return -RT_ERROR;
- }
- else
- {
- filter_num = filter_cfg->items[i].hdr_bank;
- }
- }
- if (can_instance->filter_cfg.filter_flag & (1 << filter_num))
- {
- LOG_W("This filter channel will be changed(num:%d)!", filter_num);
- rt_kprintf("This filter channel will be changed(num:%d)!", filter_num);
- }
- can_instance->filter_cfg.filter_flag |= 1 << filter_num;
- can_instance->filter_cfg.filter_mag[filter_num].MsgNum = filter_num + 1;
- /* Standard or Extended Frames */
- if (filter_cfg->items[i].ide == RT_CAN_STDID)
- {
- can_instance->filter_cfg.filter_mag[filter_num].IdType = CAN_STD_ID;
- idmask = 0x7FF;
- }
- else if (filter_cfg->items[i].ide == RT_CAN_EXTID)
- {
- can_instance->filter_cfg.filter_mag[filter_num].IdType = CAN_EXT_ID;
- idmask = 0x1FFFFFFF;
- }
- else
- {
- LOG_W("Frame pattern error(CAN_STD_ID/CAN_EXT_ID)!");
- return -RT_ERROR;
- }
- /* Whether to use MASK mode */
- if (filter_cfg->items[i].mode == CAN_UMASK_MODE)
- {
- can_instance->filter_cfg.filter_mag[filter_num].IdMask = idmask;
- }
- else if (filter_cfg->items[i].mode == CAN_MASK_MODE)
- {
- can_instance->filter_cfg.filter_mag[filter_num].IdMask = filter_cfg->items[i].mask;
- }
- else
- {
- LOG_W("MASK mode error(CAN_UMASK_MODE/CAN_MASK_MODE)!");
- return -RT_ERROR;
- }
- /* Remote frames or data frames */
- if (filter_cfg->items[i].rtr == RT_CAN_RTR)
- {
- can_instance->filter_cfg.filter_mag[filter_num].FrameType = CAN_REMOTE_FRAME;
- }
- else if (filter_cfg->items[i].rtr == RT_CAN_DTR)
- {
- can_instance->filter_cfg.filter_mag[filter_num].FrameType = CAN_DATA_FRAME;
- }
- /* Setting ID */
- can_instance->filter_cfg.filter_mag[filter_num].Id = filter_cfg->items[i].id;
- /* Setting up the CAN filter table */
- CAN_SetRxMsg(can_instance->can_x, &can_instance->filter_cfg.filter_mag[filter_num], 1);
- }
- }
- break;
- }
- case RT_CAN_CMD_SET_BAUD:/* Setting the baud rate */
- {
- argval = (rt_uint32_t) arg;
- if (argval != CAN1MBaud &&
- argval != CAN800kBaud &&
- argval != CAN500kBaud &&
- argval != CAN250kBaud &&
- argval != CAN125kBaud &&
- argval != CAN100kBaud &&
- argval != CAN50kBaud &&
- argval != CAN20kBaud &&
- argval != CAN10kBaud)
- {
- return -RT_ERROR;
- }
- if (argval != can_instance->cfg.baud_rate)
- {
- can_instance->cfg.baud_rate = argval;
- return ht32_can_configure(&can_instance->device, &can_instance->cfg);
- }
- break;
- }
- case RT_CAN_CMD_SET_MODE:/* Setting the CAN Operating Mode */
- {
- argval = (rt_uint32_t) arg;
- if (argval != RT_CAN_MODE_NORMAL &&
- argval != RT_CAN_MODE_LISTEN &&
- argval != RT_CAN_MODE_LOOPBACK &&
- argval != RT_CAN_MODE_LOOPBACKANLISTEN)
- {
- return -RT_ERROR;
- }
- if (argval != can_instance->cfg.mode)
- {
- can_instance->cfg.mode = argval;
- return ht32_can_configure(&can_instance->device, &can_instance->cfg);
- }
- break;
- }
- case RT_CAN_CMD_GET_STATUS:/* Get CAN device status */
- {
- rt_uint32_t errtype;
- errtype = can_instance->can_x->ECR;
- can_instance->device.status.rcverrcnt = ((errtype >> 8) & 0x7f);
- can_instance->device.status.snderrcnt = (errtype & 0xff);
- errtype = can_instance->can_x->SR;
- can_instance->device.status.lasterrtype = (errtype & 0x07);
- can_instance->device.status.errcode = ((errtype >> 5) & 0x07);
- rt_memcpy(arg, &can_instance->device.status, sizeof(can_instance->device.status));
- break;
- }
- default:
- return -RT_ERROR;
- }
- return RT_EOK;
- }
- /**
- * @brief CAN sends data
- * @param
- * @retval
- */
- rt_ssize_t ht32_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno)
- {
- struct ht32_can *can_instance = RT_NULL;
- struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
- struct ht32_can_msg_type tx_msg = {0};
- RT_ASSERT(can != RT_NULL);
- can_instance = (struct ht32_can *)can->parent.user_data;
- RT_ASSERT(can_instance != RT_NULL);
- /* Standard and Extended Frames */
- if (CAN_STD_ID == pmsg->ide)
- {
- tx_msg.cfg_msg.IdType = CAN_STD_ID;
- tx_msg.cfg_msg.Id = pmsg->id;
- }
- else if (CAN_EXT_ID == pmsg->ide)
- {
- tx_msg.cfg_msg.IdType = CAN_EXT_ID;
- tx_msg.cfg_msg.Id = pmsg->id;
- }
- else
- {
- LOG_W("Frame pattern error(CAN_STD_ID/CAN_EXT_ID)!");
- return -RT_ERROR;
- }
- /* Teleframes and data frames */
- if (RT_CAN_RTR == pmsg->rtr)
- {
- tx_msg.cfg_msg.FrameType = CAN_REMOTE_FRAME;
- }
- else if (RT_CAN_DTR == pmsg->rtr)
- {
- tx_msg.cfg_msg.FrameType = CAN_DATA_FRAME;
- }
- else
- {
- LOG_W("Remote frame setting error(CAN_REMOTE_FRAME/CAN_DATA_FRAME)!");
- return -RT_ERROR;
- }
- /* Length of sent data */
- tx_msg.data_len = pmsg->len & 0x0FU;
- /* data being sent */
- tx_msg.data[0] = pmsg->data[0];
- tx_msg.data[1] = pmsg->data[1];
- tx_msg.data[2] = pmsg->data[2];
- tx_msg.data[3] = pmsg->data[3];
- tx_msg.data[4] = pmsg->data[4];
- tx_msg.data[5] = pmsg->data[5];
- tx_msg.data[6] = pmsg->data[6];
- tx_msg.data[7] = pmsg->data[7];
- /* Waiting tx Msg idle */
- while (CAN_TransmitStatus(can_instance->can_x, &tx_msg.cfg_msg) == 0);
- /* Loopback data */
- CAN_Transmit(can_instance->can_x, &tx_msg.cfg_msg, tx_msg.data, tx_msg.data_len);
- return RT_EOK;
- }
- /**
- * @brief CAN receive data
- * @param
- * @retval
- */
- rt_ssize_t ht32_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno)
- {
- uint8_t i = 0;
- uint32_t msgnum = 0;
- CAN_RxStatus_TypeDef rx_status;
- struct ht32_can_msg_type rx_msg = {0};
- struct ht32_can *can_instance = RT_NULL;
- struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
- RT_ASSERT(can != RT_NULL);
- RT_ASSERT(pmsg != RT_NULL);
- can_instance = (struct ht32_can *)can->parent.user_data;
- RT_ASSERT(can_instance != RT_NULL);
- msgnum = can_instance->filter_cfg.filter_flag;
- for (i = 0; i < MSG_OBJ_TOTAL_NUM; i++)
- {
- if ((msgnum & 1) == 1)
- {
- rx_status = CAN_Receive(can_instance->can_x, &can_instance->filter_cfg.filter_mag[i], rx_msg.data, &rx_msg.data_len);
- if (rx_status == MSG_OVER_RUN)
- {
- LOG_W("ID[%X] rx message over run\r\n", can_instance->filter_cfg.filter_mag[i].Id);
- }
- else if (rx_status == MSG_OBJ_NOT_SET)
- {
- LOG_W("rx message not set \r\n");
- }
- else if (rx_status == MSG_RX_FINISH)
- {
- LOG_W("rx ok \r\n");
- pmsg->data[0] = rx_msg.data[0];
- pmsg->data[1] = rx_msg.data[1];
- pmsg->data[2] = rx_msg.data[2];
- pmsg->data[3] = rx_msg.data[3];
- pmsg->data[4] = rx_msg.data[4];
- pmsg->data[5] = rx_msg.data[5];
- pmsg->data[6] = rx_msg.data[6];
- pmsg->data[7] = rx_msg.data[7];
- pmsg->len = rx_msg.data_len;
- if (can_instance->filter_cfg.filter_mag[i].IdType == CAN_EXT_ID)
- {
- pmsg->id = can_instance->filter_cfg.filter_mag[i].Id;
- pmsg->ide = RT_CAN_EXTID;
- }
- else if (can_instance->filter_cfg.filter_mag[i].IdType == CAN_STD_ID)
- {
- pmsg->id = can_instance->filter_cfg.filter_mag[i].Id;
- pmsg->ide = RT_CAN_EXTID;
- }
- if (can_instance->filter_cfg.filter_mag[i].FrameType == CAN_DATA_FRAME)
- {
- pmsg->rtr = RT_CAN_DTR;
- }
- else if (can_instance->filter_cfg.filter_mag[i].FrameType == CAN_REMOTE_FRAME)
- {
- pmsg->rtr = RT_CAN_RTR;
- }
- return RT_EOK;
- }
- }
- msgnum = msgnum >> 1;
- if (msgnum == 0)
- {
- return -1;
- }
- }
- return -1;
- }
- /* Mapping CAN interfaces */
- static const struct rt_can_ops ht32_can_ops =
- {
- .configure = ht32_can_configure, /* CAN Configuration Functions */
- .control = ht32_can_control, /* CAN Control Functions */
- .sendmsg = ht32_can_sendmsg, /* CAN Transmit Data */
- .recvmsg = ht32_can_recvmsg, /* CAN Receive Data */
- };
- int rt_hw_can_init(void)
- {
- struct can_configure config = CANDEFAULTCONFIG;
- config.mode = BSP_USING_CAN_MODE;
- config.baud_rate = BSP_USING_CAN_BAUD;
- config.privmode = RT_CAN_MODE_NOPRIV;
- config.ticks = 50;
- #ifdef RT_CAN_USING_HDR
- config.maxhdr = 14;
- #endif
- ht32_can_config.device.config = config;
- /* Registration of CAN devices */
- rt_hw_can_register(&ht32_can_config.device,
- ht32_can_config.name,
- &ht32_can_ops,
- &ht32_can_config);
- return RT_EOK;
- }
- INIT_BOARD_EXPORT(rt_hw_can_init);
- void CAN0_IRQHandler(void)
- {
- CAN_LastErrorCode_TypeDef lec;
- rt_interrupt_enter();
- /* Recover from Bus off state. */
- if (CAN_GetFlagStatus(ht32_can_config.can_x, CAN_FLAG_BOFF))
- {
- CAN_BusOffRecovery(ht32_can_config.can_x);
- }
- /* Transmit message finished */
- if (CAN_GetFlagStatus(ht32_can_config.can_x, CAN_FLAG_TXOK))
- {
- rt_hw_can_isr(&ht32_can_config.device, RT_CAN_EVENT_TX_DONE);
- CAN_ClearFlag(ht32_can_config.can_x, CAN_FLAG_TXOK);
- }
- /* Message received. */
- if (CAN_GetFlagStatus(ht32_can_config.can_x, CAN_FLAG_RXOK))
- {
- /* Clear all message objects' interrupt pending flag */
- CAN_ClearAllMsgPendingFlag(ht32_can_config.can_x);
- rt_hw_can_isr(&ht32_can_config.device, RT_CAN_EVENT_RX_IND);
- CAN_ClearFlag(ht32_can_config.can_x, CAN_FLAG_RXOK);
- }
- lec = CAN_GetLastErrorCode(ht32_can_config.can_x);
- if (lec != NO_ERROR)
- {
- switch (lec)
- {
- case NO_ERROR:
- break;
- case STUFF_ERROR:
- ht32_can_config.device.status.bitpaderrcnt++;
- break;
- case FORM_ERROR:
- ht32_can_config.device.status.formaterrcnt++;
- break;
- case ACK_ERROR:
- ht32_can_config.device.status.ackerrcnt++;
- break;
- case BIT1_EROR:
- case BIT0_ERROR:
- ht32_can_config.device.status.biterrcnt++;
- break;
- case CRC_ERROR:
- ht32_can_config.device.status.crcerrcnt++;
- break;
- case NO_CHANGE:
- break;
- }
- ht32_can_config.device.status.lasterrtype = lec;
- ht32_can_config.device.status.rcverrcnt = CAN_GetReceiveErrorCounter(ht32_can_config.can_x);
- ht32_can_config.device.status.snderrcnt = CAN_GetLSBTransmitErrorCounter(ht32_can_config.can_x);
- ht32_can_config.device.status.errcode = lec;
- }
- rt_interrupt_leave();
- }
- #endif /* BSP_USING_CAN */
|