| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215 |
- /*
- * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-xx-xx CDT first version
- */
- #include "drv_mcan.h"
- #include <drv_config.h>
- #include <board_config.h>
- #if defined(BSP_USING_MCAN)
- #define LOG_TAG "drv_mcan"
- /****************************************************************************************
- * Type definitions for MCAN RT driver
- ****************************************************************************************/
- typedef struct hc32_mcan_config_struct
- {
- char *name; /* MCAN instance name */
- CM_MCAN_TypeDef *instance; /* MCAN instance */
- stc_mcan_init_t init_para; /* MCAN initialisation parameters */
- uint32_t int0_sel;
- struct hc32_irq_config int0_cfg; /* MCAN interrupt line 0 configuration */
- #if defined(HC32F4A8)
- func_ptr_t irq_callback0;
- #endif
- } hc32_mcan_config_t;
- typedef struct hc32_mcan_driver_struct
- {
- hc32_mcan_config_t mcan; /* MCAN configuration */
- struct rt_can_device can_device; /* inherit from rt can device */
- uint32_t tx_box_num; /* current tx box number */
- } hc32_mcan_driver_t;
- typedef struct mcan_baud_rate_struct
- {
- rt_uint32_t baud_rate;
- rt_uint32_t baud_rate_fd;
- stc_mcan_bit_time_config_t ll_bt;
- } mcan_baud_rate_t;
- /****************************************************************************************
- * Parameter validity check
- ****************************************************************************************/
- #if defined(BSP_USING_MCAN1) || defined(BSP_USING_MCAN2)
- #define IS_RT_CAN_WORK_MODE(mode) ((mode) <= RT_CAN_MODE_LOOPBACKANLISTEN)
- #define IS_RT_CAN_PRIV_MODE(mode) (((mode) == RT_CAN_MODE_PRIV) || ((mode) == RT_CAN_MODE_NOPRIV))
- #define IS_MCAN_FD_MODE(mode) (((mode) >= MCAN_FD_ARG_MIN) && ((mode) <= MCAN_FD_ARG_MAX))
- #define IS_MCAN_CC_BAUD_RATE(baud) ((baud) == (CAN10kBaud) || \
- (baud) == (CAN20kBaud) || \
- (baud) == (CAN50kBaud) || \
- (baud) == (CAN100kBaud) || \
- (baud) == (CAN125kBaud) || \
- (baud) == (CAN250kBaud) || \
- (baud) == (CAN500kBaud) || \
- (baud) == (CAN800kBaud) || \
- (baud) == (CAN1MBaud))
- #define IS_MCAN_NOMINAL_BAUD_RATE(baud) ((baud) == (CAN500kBaud) || \
- (baud) == (CAN1MBaud))
- #define IS_MCAN_DATA_BAUD_RATE(baud) ((baud) == (CANFD_DATA_BAUD_1M) || \
- (baud) == (CANFD_DATA_BAUD_2M) || \
- (baud) == (CANFD_DATA_BAUD_4M) || \
- (baud) == (CANFD_DATA_BAUD_5M) || \
- (baud) == (CANFD_DATA_BAUD_8M))
- #define IS_CAN_VALID_ID(ide, id) ((((ide) == 0) && ((id) <= MCAN_STD_ID_MASK)) || \
- (((ide) == 1) && ((id) <= MCAN_EXT_ID_MASK)))
- /****************************************************************************************
- * Interrupt definitions
- ****************************************************************************************/
- #define MCAN_RX_INT (MCAN_INT_RX_FIFO0_NEW_MSG | MCAN_INT_RX_FIFO1_NEW_MSG | MCAN_INT_RX_BUF_NEW_MSG)
- #define MCAN_TX_INT (MCAN_INT_TX_CPLT)
- #define MCAN_ERR_INT (MCAN_INT_ARB_PHASE_ERROR | MCAN_INT_DATA_PHASE_ERROR | MCAN_INT_ERR_LOG_OVF | \
- MCAN_INT_ERR_PASSIVE | MCAN_INT_ERR_WARNING | MCAN_INT_BUS_OFF)
- #define MCAN_INT0_SEL (MCAN_RX_INT | MCAN_TX_INT | MCAN_ERR_INT)
- /****************************************************************************************
- * Baud rate(bit timing) configuration based on 80MHz clock
- ****************************************************************************************/
- #if defined(RT_CAN_USING_CANFD)
- static const mcan_baud_rate_t m_mcan_fd_baud_rate[] =
- {
- {CAN500kBaud, CANFD_DATA_BAUD_1M, MCAN_FD_CFG_500K_1M},
- {CAN500kBaud, CANFD_DATA_BAUD_2M, MCAN_FD_CFG_500K_2M},
- {CAN500kBaud, CANFD_DATA_BAUD_4M, MCAN_FD_CFG_500K_4M},
- {CAN500kBaud, CANFD_DATA_BAUD_5M, MCAN_FD_CFG_500K_5M},
- {CAN500kBaud, CANFD_DATA_BAUD_8M, MCAN_FD_CFG_500K_8M},
- {CAN1MBaud, CANFD_DATA_BAUD_1M, MCAN_FD_CFG_1M_1M},
- {CAN1MBaud, CANFD_DATA_BAUD_2M, MCAN_FD_CFG_1M_2M},
- {CAN1MBaud, CANFD_DATA_BAUD_4M, MCAN_FD_CFG_1M_4M},
- {CAN1MBaud, CANFD_DATA_BAUD_5M, MCAN_FD_CFG_1M_5M},
- {CAN1MBaud, CANFD_DATA_BAUD_8M, MCAN_FD_CFG_1M_8M},
- };
- #else
- static const mcan_baud_rate_t m_mcan_cc_baud_rate[] =
- {
- {CAN1MBaud, 0, MCAN_CC_CFG_1M},
- {CAN800kBaud, 0, MCAN_CC_CFG_800K},
- {CAN500kBaud, 0, MCAN_CC_CFG_500K},
- {CAN250kBaud, 0, MCAN_CC_CFG_250K},
- {CAN125kBaud, 0, MCAN_CC_CFG_125K},
- {CAN100kBaud, 0, MCAN_CC_CFG_100K},
- {CAN50kBaud, 0, MCAN_CC_CFG_50K},
- {CAN20kBaud, 0, MCAN_CC_CFG_20K},
- {CAN10kBaud, 0, MCAN_CC_CFG_10K},
- };
- #endif
- /****************************************************************************************
- * Constants
- ****************************************************************************************/
- static const uint8_t m_mcan_data_size[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64};
- static const rt_uint32_t m_mcan_tx_priv_mode[] = {MCAN_TX_FIFO_MD, MCAN_TX_QUEUE_MD};
- static const rt_uint32_t m_mcan_work_mode[] = {MCAN_MD_NORMAL, MCAN_MD_BUS_MON, MCAN_MD_EXTERN_LOOPBACK, MCAN_MD_INTERN_LOOPBACK};
- #if defined(RT_CAN_USING_CANFD)
- static const rt_uint32_t m_mcan_fd_mode[] = {MCAN_FRAME_CLASSIC, MCAN_FRAME_ISO_FD_NO_BRS, MCAN_FRAME_ISO_FD_BRS, \
- MCAN_FRAME_NON_ISO_FD_NO_BRS, MCAN_FRAME_NON_ISO_FD_BRS
- };
- #endif
- /****************************************************************************************
- * Driver instance list
- ****************************************************************************************/
- enum
- {
- #if defined(BSP_USING_MCAN1)
- MCAN1_INDEX,
- #endif
- #if defined(BSP_USING_MCAN2)
- MCAN2_INDEX,
- #endif
- MCAN_DEV_CNT,
- };
- static hc32_mcan_driver_t m_mcan_driver_list[] =
- {
- #if defined(BSP_USING_MCAN1)
- {
- {
- .name = MCAN1_NAME,
- .instance = CM_MCAN1,
- .init_para = {.stcBitTime = MCAN1_BAUD_RATE_CFG},
- .int0_sel = MCAN_INT0_SEL,
- .int0_cfg = {BSP_MCAN1_INT0_IRQ_NUM, BSP_MCAN1_INT0_IRQ_PRIO, INT_SRC_MCAN1_INT0},
- }
- },
- #endif
- #if defined(BSP_USING_MCAN2)
- {
- {
- .name = MCAN2_NAME,
- .instance = CM_MCAN2,
- .init_para = {.stcBitTime = MCAN2_BAUD_RATE_CFG},
- .int0_sel = MCAN_INT0_SEL,
- .int0_cfg = {BSP_MCAN2_INT0_IRQ_NUM, BSP_MCAN2_INT0_IRQ_PRIO, INT_SRC_MCAN2_INT0},
- }
- },
- #endif
- };
- #if defined(BSP_USING_MCAN1)
- static stc_mcan_filter_t m_mcan1_std_filters[MCAN1_STD_FILTER_NUM];
- static stc_mcan_filter_t m_mcan1_ext_filters[MCAN1_EXT_FILTER_NUM];
- #endif
- #if defined(BSP_USING_MCAN2)
- static stc_mcan_filter_t m_mcan2_std_filters[MCAN2_STD_FILTER_NUM];
- static stc_mcan_filter_t m_mcan2_ext_filters[MCAN2_EXT_FILTER_NUM];
- #endif
- /****************************************************************************************
- * Driver operations
- ****************************************************************************************/
- /**
- * @brief Configure CAN controller
- * @param [in/out] can CAN device pointer
- * @param [in] cfg CAN configuration pointer
- * @retval RT_EOK for valid configuration
- * @retval -RT_ERROR for invalid configuration
- */
- static rt_err_t mcan_configure(struct rt_can_device *device, struct can_configure *cfg);
- /**
- * @brief Control/Get CAN state
- * including:interrupt, mode, priority, baudrate, filter, status
- * @param [in/out] can CAN device pointer
- * @param [in] cmd Control command
- * @param [in/out] arg Argument pointer
- * @retval RT_EOK for valid control command and arg
- * @retval -RT_ERROR for invalid control command or arg
- */
- static rt_err_t mcan_control(struct rt_can_device *device, int cmd, void *arg);
- /**
- * @brief Send out CAN message
- * @param [in] can CAN device pointer
- * @param [in] buf CAN message buffer
- * @param [in] boxno Mailbox number, it is not used in this porting
- * @retval RT_EOK No error
- * @retval -RT_ETIMEOUT timeout happened
- * @retval -RT_EFULL Transmission buffer is full
- */
- static rt_ssize_t mcan_sendmsg(struct rt_can_device *device, const void *buf, rt_uint32_t boxno);
- /**
- * @brief Receive message from CAN
- * @param [in] can CAN device pointer
- * @param [out] buf CAN receive buffer
- * @param [in] boxno Mailbox Number, it is not used in this porting
- * @retval RT_EOK no error
- * @retval -RT_ERROR Error happened during reading receive FIFO
- * @retval -RT_EMPTY no data in receive FIFO
- */
- static rt_ssize_t mcan_recvmsg(struct rt_can_device *device, void *buf, rt_uint32_t boxno);
- #if defined(RT_CAN_USING_CANFD)
- static void mcan_copy_bt_to_cfg(struct can_configure *cfg, const stc_mcan_bit_time_config_t *ll_bt);
- #endif
- static const struct rt_can_ops m_mcan_ops =
- {
- mcan_configure,
- mcan_control,
- mcan_sendmsg,
- mcan_recvmsg,
- };
- /****************************************************************************************
- * mcan configure
- ****************************************************************************************/
- static rt_err_t mcan_configure(struct rt_can_device *device, struct can_configure *cfg)
- {
- rt_uint32_t i, len;
- rt_err_t rt_ret = RT_EOK;
- hc32_mcan_driver_t *driver;
- hc32_mcan_config_t *hard;
- stc_mcan_filter_t *std_filters, *ext_filters;
- RT_ASSERT(device);
- RT_ASSERT(cfg);
- driver = (hc32_mcan_driver_t *)device->parent.user_data;
- RT_ASSERT(driver);
- hard = &driver->mcan;
- RT_ASSERT(IS_RT_CAN_WORK_MODE(cfg->mode));
- RT_ASSERT(IS_RT_CAN_PRIV_MODE(cfg->privmode));
- hard->init_para.u32Mode = m_mcan_work_mode[cfg->mode];
- hard->init_para.u32FrameFormat = MCAN_FRAME_CLASSIC;
- hard->init_para.stcMsgRam.u32TxFifoQueueMode = m_mcan_tx_priv_mode[cfg->privmode];
- #if defined(RT_CAN_USING_CANFD)
- RT_ASSERT(IS_MCAN_FD_MODE(cfg->enable_canfd));
- hard->init_para.u32FrameFormat = m_mcan_fd_mode[cfg->enable_canfd];
- if (cfg->use_bit_timing)
- {
- hard->init_para.stcBitTime.u32NominalPrescaler = cfg->can_timing.prescaler;
- hard->init_para.stcBitTime.u32NominalTimeSeg1 = cfg->can_timing.num_seg1;
- hard->init_para.stcBitTime.u32NominalTimeSeg2 = cfg->can_timing.num_seg2;
- hard->init_para.stcBitTime.u32NominalSyncJumpWidth = cfg->can_timing.num_sjw;
- if (cfg->use_bit_timing >= 2)
- {
- hard->init_para.stcBitTime.u32DataPrescaler = cfg->canfd_timing.prescaler;
- hard->init_para.stcBitTime.u32DataTimeSeg1 = cfg->canfd_timing.num_seg1;
- hard->init_para.stcBitTime.u32DataTimeSeg2 = cfg->canfd_timing.num_seg2;
- hard->init_para.stcBitTime.u32DataSyncJumpWidth = cfg->canfd_timing.num_sjw;
- hard->init_para.stcBitTime.u32SspOffset = cfg->canfd_timing.num_sspoff;
- }
- cfg->use_bit_timing = 0;
- }
- else
- {
- RT_ASSERT(IS_MCAN_NOMINAL_BAUD_RATE(cfg->baud_rate));
- RT_ASSERT(IS_MCAN_DATA_BAUD_RATE(cfg->baud_rate_fd));
- len = sizeof(m_mcan_fd_baud_rate) / sizeof(m_mcan_fd_baud_rate[0]);
- for (i = 0; i < len; i++)
- {
- if ((cfg->baud_rate == m_mcan_fd_baud_rate[i].baud_rate) && \
- (cfg->baud_rate_fd == m_mcan_fd_baud_rate[i].baud_rate_fd))
- {
- hard->init_para.stcBitTime = m_mcan_fd_baud_rate[i].ll_bt;
- mcan_copy_bt_to_cfg(cfg, &m_mcan_fd_baud_rate[i].ll_bt);
- break;
- }
- }
- if (i >= len)
- {
- rt_ret = -RT_ERROR;
- }
- }
- #else
- RT_ASSERT(IS_MCAN_CC_BAUD_RATE(cfg->baud_rate));
- len = sizeof(m_mcan_cc_baud_rate) / sizeof(m_mcan_cc_baud_rate[0]);
- for (i = 0; i < len; i++)
- {
- if (cfg->baud_rate == m_mcan_cc_baud_rate[i].baud_rate)
- {
- hard->init_para.stcBitTime = m_mcan_cc_baud_rate[i].ll_bt;
- break;
- }
- }
- if (i >= len)
- {
- rt_ret = -RT_ERROR;
- }
- #endif
- if (rt_ret == RT_EOK)
- {
- std_filters = hard->init_para.stcFilter.pstcStdFilterList;
- ext_filters = hard->init_para.stcFilter.pstcExtFilterList;
- hard->init_para.stcFilter.pstcStdFilterList = NULL;
- hard->init_para.stcFilter.pstcExtFilterList = NULL;
- if (MCAN_Init(hard->instance, &hard->init_para) != LL_OK)
- {
- hard->init_para.stcFilter.pstcStdFilterList = std_filters;
- hard->init_para.stcFilter.pstcExtFilterList = ext_filters;
- return -RT_ERROR;
- }
- }
- hard->init_para.stcFilter.pstcStdFilterList = std_filters;
- hard->init_para.stcFilter.pstcExtFilterList = ext_filters;
- for (i = 0; i < hard->init_para.stcMsgRam.u32StdFilterNum; i++)
- {
- if (MCAN_FilterConfig(hard->instance, &hard->init_para.stcFilter.pstcStdFilterList[i]) != LL_OK)
- {
- return -RT_ERROR;
- }
- }
- for (i = 0; i < hard->init_para.stcMsgRam.u32ExtFilterNum; i++)
- {
- if (MCAN_FilterConfig(hard->instance, &hard->init_para.stcFilter.pstcExtFilterList[i]) != LL_OK)
- {
- return -RT_ERROR;
- }
- }
- struct can_configure pre_config = driver->can_device.config;
- rt_memcpy(&driver->can_device.config, cfg, sizeof(struct can_configure));
- /* restore unmodifiable member */
- if ((driver->can_device.parent.open_flag & RT_DEVICE_OFLAG_OPEN) == RT_DEVICE_OFLAG_OPEN)
- {
- driver->can_device.config.msgboxsz = pre_config.msgboxsz;
- driver->can_device.config.ticks = pre_config.ticks;
- }
- #if defined(RT_CAN_USING_HDR)
- driver->can_device.config.maxhdr = pre_config.maxhdr;
- #endif
- driver->can_device.config.sndboxnumber = pre_config.sndboxnumber;
- MCAN_Start(hard->instance);
- return RT_EOK;
- }
- /****************************************************************************************
- * mcan control
- ****************************************************************************************/
- static void mcan_control_set_int(hc32_mcan_driver_t *driver, int cmd, void *arg)
- {
- en_functional_state_t new_state = DISABLE;
- rt_uint32_t int_flag = (rt_uint32_t)arg;
- hc32_mcan_config_t *hard = &driver->mcan;
- rt_uint32_t tmp;
- if (cmd == RT_DEVICE_CTRL_SET_INT)
- {
- new_state = ENABLE;
- }
- switch (int_flag)
- {
- case RT_DEVICE_FLAG_INT_RX:
- if (MCAN_RX_INT & hard->int0_sel)
- {
- MCAN_IntCmd(hard->instance, MCAN_RX_INT & hard->int0_sel, MCAN_INT_LINE0, new_state);
- }
- break;
- case RT_DEVICE_FLAG_INT_TX:
- tmp = hard->init_para.stcMsgRam.u32TxBufferNum + hard->init_para.stcMsgRam.u32TxFifoQueueNum;
- if (tmp >= 32)
- {
- tmp = 0xFFFFFFFF;
- }
- else
- {
- tmp = (1UL << tmp) - 1;
- }
- MCAN_TxBufferNotificationCmd(hard->instance, tmp, MCAN_INT_TX_CPLT, ENABLE);
- if (MCAN_TX_INT & hard->int0_sel)
- {
- MCAN_IntCmd(hard->instance, MCAN_TX_INT & hard->int0_sel, MCAN_INT_LINE0, new_state);
- }
- break;
- case RT_DEVICE_CAN_INT_ERR:
- if (MCAN_ERR_INT & hard->int0_sel)
- {
- MCAN_IntCmd(hard->instance, MCAN_ERR_INT & hard->int0_sel, MCAN_INT_LINE0, new_state);
- }
- break;
- default:
- break;
- }
- }
- static rt_err_t mcan_control_set_filter(hc32_mcan_driver_t *driver, int cmd, void *arg)
- {
- rt_uint8_t sf_default_idx = 0, ef_default_idx = 0;
- stc_mcan_filter_t ll_filter;
- hc32_mcan_config_t *hard = &driver->mcan;
- struct rt_can_filter_config *device_filter = (struct rt_can_filter_config *)arg;
- for (int i = 0; i < device_filter->count; i++)
- {
- RT_ASSERT(IS_CAN_VALID_ID(device_filter->items[i].ide, device_filter->items[i].id));
- RT_ASSERT((device_filter->items[i].rxfifo == CAN_RX_FIFO0) || (device_filter->items[i].rxfifo == CAN_RX_FIFO1));
- if (device_filter->items[i].rxfifo == CAN_RX_FIFO1)
- {
- RT_ASSERT(hard->init_para.stcMsgRam.u32RxFifo1Num > 0);
- }
- /* rt filter mode: 0 - list; 1 - mask */
- static const rt_uint32_t mcan_filter_type[] = {MCAN_FILTER_RANGE, MCAN_FILTER_MASK};
- static const rt_uint32_t mcan_filter_config[] = {MCAN_FILTER_TO_RX_FIFO0, MCAN_FILTER_TO_RX_FIFO1};
- /* rt CAN filter to MCAN LL driver filter */
- ll_filter.u32IdType = device_filter->items[i].ide;
- ll_filter.u32FilterType = mcan_filter_type[device_filter->items[i].mode];
- ll_filter.u32FilterConfig = mcan_filter_config[device_filter->items[i].rxfifo];
- ll_filter.u32FilterId1 = device_filter->items[i].id;
- ll_filter.u32FilterId2 = device_filter->items[i].mask;
- if (device_filter->items[i].ide == RT_CAN_STDID)
- {
- ll_filter.u32FilterId1 &= MCAN_STD_ID_MASK;
- ll_filter.u32FilterId2 &= MCAN_STD_ID_MASK;
- if (device_filter->items[i].hdr_bank == -1)
- {
- ll_filter.u32FilterIndex = sf_default_idx;
- sf_default_idx++;
- }
- else
- {
- ll_filter.u32FilterIndex = device_filter->items[i].hdr_bank;
- }
- RT_ASSERT(ll_filter.u32FilterIndex < hard->init_para.stcMsgRam.u32StdFilterNum);
- hard->init_para.stcFilter.pstcStdFilterList[ll_filter.u32FilterIndex] = ll_filter;
- }
- else
- {
- ll_filter.u32FilterId1 &= MCAN_EXT_ID_MASK;
- ll_filter.u32FilterId2 &= MCAN_EXT_ID_MASK;
- if (device_filter->items[i].hdr_bank == -1)
- {
- ll_filter.u32FilterIndex = ef_default_idx;
- ef_default_idx++;
- }
- else
- {
- ll_filter.u32FilterIndex = device_filter->items[i].hdr_bank;
- }
- RT_ASSERT(ll_filter.u32FilterIndex < hard->init_para.stcMsgRam.u32ExtFilterNum);
- hard->init_para.stcFilter.pstcExtFilterList[ll_filter.u32FilterIndex] = ll_filter;
- }
- }
- return RT_EOK;
- }
- static rt_err_t mcan_control_set_mode(hc32_mcan_driver_t *driver, int cmd, void *arg, struct can_configure *cfg)
- {
- rt_uint32_t argval = (rt_uint32_t)arg;
- (void)cmd;
- RT_ASSERT(IS_RT_CAN_WORK_MODE(argval));
- if (!IS_RT_CAN_WORK_MODE(argval))
- {
- return -RT_ERROR;
- }
- if (argval == driver->can_device.config.mode)
- {
- return RT_EOK;
- }
- cfg->mode = argval;
- return RT_EOK;
- }
- static rt_err_t mcan_control_set_priv(hc32_mcan_driver_t *driver, int cmd, void *arg, struct can_configure *cfg)
- {
- rt_uint32_t argval = (rt_uint32_t)arg;
- (void)cmd;
- RT_ASSERT(IS_RT_CAN_PRIV_MODE(argval));
- if (!IS_RT_CAN_PRIV_MODE(argval))
- {
- return -RT_ERROR;
- }
- if (argval == driver->can_device.config.privmode)
- {
- return RT_EOK;
- }
- cfg->privmode = argval;
- return RT_EOK;
- }
- #if defined(RT_CAN_USING_CANFD)
- static void mcan_copy_bt_to_cfg(struct can_configure *cfg, const stc_mcan_bit_time_config_t *ll_bt)
- {
- cfg->can_timing.prescaler = ll_bt->u32NominalPrescaler;
- cfg->can_timing.num_seg1 = ll_bt->u32NominalTimeSeg1;
- cfg->can_timing.num_seg2 = ll_bt->u32NominalTimeSeg2;
- cfg->can_timing.num_sjw = ll_bt->u32NominalSyncJumpWidth;
- cfg->canfd_timing.prescaler = ll_bt->u32DataPrescaler;
- cfg->canfd_timing.num_seg1 = ll_bt->u32DataTimeSeg1;
- cfg->canfd_timing.num_seg2 = ll_bt->u32DataTimeSeg2;
- cfg->canfd_timing.num_sjw = ll_bt->u32DataSyncJumpWidth;
- cfg->canfd_timing.num_sspoff = ll_bt->u32SspOffset;
- }
- #endif
- static rt_err_t mcan_control_set_fd(hc32_mcan_driver_t *driver, int cmd, void *arg, struct can_configure *cfg)
- {
- rt_uint32_t i, len;
- rt_uint32_t argval = (rt_uint32_t)arg;
- #if defined(RT_CAN_USING_CANFD)
- struct rt_can_bit_timing_config *timing_configs = NULL;
- #endif
- switch (cmd)
- {
- #if defined(RT_CAN_USING_CANFD)
- case RT_CAN_CMD_SET_BAUD:
- default:
- RT_ASSERT(IS_MCAN_NOMINAL_BAUD_RATE(argval));
- if (!IS_MCAN_NOMINAL_BAUD_RATE(argval))
- {
- return -RT_ERROR;
- }
- if (driver->can_device.config.baud_rate == argval)
- {
- return RT_EOK;
- }
- len = sizeof(m_mcan_fd_baud_rate) / sizeof(m_mcan_fd_baud_rate[0]);
- for (i = 0; i < len; i++)
- {
- if ((argval == m_mcan_fd_baud_rate[i].baud_rate) && \
- (driver->can_device.config.baud_rate_fd == m_mcan_fd_baud_rate[i].baud_rate_fd))
- {
- cfg->baud_rate = argval;
- cfg->baud_rate_fd = driver->can_device.config.baud_rate_fd;
- mcan_copy_bt_to_cfg(cfg, &m_mcan_fd_baud_rate[i].ll_bt);
- return RT_EOK;
- }
- }
- return -RT_ERROR;
- case RT_CAN_CMD_SET_BAUD_FD:
- RT_ASSERT(IS_MCAN_DATA_BAUD_RATE(argval));
- if (!IS_MCAN_DATA_BAUD_RATE(argval))
- {
- return -RT_ERROR;
- }
- if (driver->can_device.config.baud_rate_fd == argval)
- {
- return RT_EOK;
- }
- len = sizeof(m_mcan_fd_baud_rate) / sizeof(m_mcan_fd_baud_rate[0]);
- for (i = 0; i < len; i++)
- {
- if ((argval == m_mcan_fd_baud_rate[i].baud_rate_fd) && \
- (driver->can_device.config.baud_rate == m_mcan_fd_baud_rate[i].baud_rate))
- {
- cfg->baud_rate_fd = argval;
- cfg->baud_rate = driver->can_device.config.baud_rate;
- mcan_copy_bt_to_cfg(cfg, &m_mcan_fd_baud_rate[i].ll_bt);
- return RT_EOK;
- }
- }
- return -RT_ERROR;
- case RT_CAN_CMD_SET_BITTIMING:
- timing_configs = (struct rt_can_bit_timing_config *)arg;
- RT_ASSERT(timing_configs != RT_NULL);
- RT_ASSERT(timing_configs->count == 1 || timing_configs->count == 2);
- if ((timing_configs == NULL) || ((timing_configs->count != 1) && (timing_configs->count != 2)))
- {
- return -RT_ERROR;
- }
- cfg->can_timing = timing_configs->items[0];
- if (timing_configs->count == 2)
- {
- cfg->canfd_timing = timing_configs->items[1];
- }
- cfg->use_bit_timing = timing_configs->count;
- return RT_EOK;
- case RT_CAN_CMD_SET_CANFD:
- RT_ASSERT(IS_MCAN_FD_MODE(argval));
- if (!IS_MCAN_FD_MODE(argval))
- {
- return -RT_ERROR;
- }
- if (argval == driver->can_device.config.enable_canfd)
- {
- return RT_EOK;
- }
- cfg->enable_canfd = argval;
- return RT_EOK;
- #else
- case RT_CAN_CMD_SET_BAUD:
- RT_ASSERT(IS_MCAN_CC_BAUD_RATE(argval));
- if (!IS_MCAN_CC_BAUD_RATE(argval))
- {
- return -RT_ERROR;
- }
- if (argval == driver->can_device.config.baud_rate)
- {
- return RT_EOK;
- }
- len = sizeof(m_mcan_cc_baud_rate) / sizeof(m_mcan_cc_baud_rate[0]);
- for (i = 0; i < len; i++)
- {
- if (argval == m_mcan_cc_baud_rate[i].baud_rate)
- {
- cfg->baud_rate = argval;
- return RT_EOK;
- }
- }
- return -RT_ERROR;
- default:
- return -RT_ERROR;
- #endif
- }
- }
- static void mcan_control_get_status(hc32_mcan_driver_t *driver, int cmd, void *arg)
- {
- stc_mcan_protocol_status_t mcan_st;
- stc_mcan_error_counter_t mcan_err;
- struct rt_can_status *rt_can_stat = (struct rt_can_status *)arg;
- MCAN_GetProtocolStatus(driver->mcan.instance, &mcan_st);
- MCAN_GetErrorCounter(driver->mcan.instance, &mcan_err);
- rt_can_stat->rcverrcnt = mcan_err.u8RxErrorCount;
- rt_can_stat->snderrcnt = mcan_err.u8TxErrorCount;
- rt_can_stat->lasterrtype = mcan_st.u8LastErrorCode;
- rt_can_stat->errcode = mcan_st.u8LastErrorCode;
- }
- static rt_err_t mcan_control(struct rt_can_device *device, int cmd, void *arg)
- {
- rt_err_t rt_ret = -RT_ERROR;
- struct can_configure new_cfg;
- hc32_mcan_driver_t *driver;
- RT_ASSERT(device);
- driver = (hc32_mcan_driver_t *)device->parent.user_data;
- RT_ASSERT(driver);
- new_cfg = device->config;
- switch (cmd)
- {
- case RT_DEVICE_CTRL_SET_INT:
- case RT_DEVICE_CTRL_CLR_INT:
- mcan_control_set_int(driver, cmd, arg);
- return RT_EOK;
- #if defined(RT_CAN_USING_HDR)
- case RT_CAN_CMD_SET_FILTER:
- rt_ret = mcan_control_set_filter(driver, cmd, arg);
- break;
- #endif
- case RT_CAN_CMD_SET_MODE:
- rt_ret = mcan_control_set_mode(driver, cmd, arg, &new_cfg);
- break;
- case RT_CAN_CMD_SET_PRIV:
- rt_ret = mcan_control_set_priv(driver, cmd, arg, &new_cfg);
- break;
- case RT_CAN_CMD_SET_BAUD:
- #if defined(RT_CAN_USING_CANFD)
- case RT_CAN_CMD_SET_CANFD:
- case RT_CAN_CMD_SET_BAUD_FD:
- case RT_CAN_CMD_SET_BITTIMING:
- #endif
- rt_ret = mcan_control_set_fd(driver, cmd, arg, &new_cfg);
- break;
- case RT_CAN_CMD_GET_STATUS:
- mcan_control_get_status(driver, cmd, arg);
- return RT_EOK;
- default:
- return -RT_EINVAL;
- }
- if (rt_ret == RT_EOK)
- {
- rt_ret = mcan_configure(device, &new_cfg);
- }
- return rt_ret;
- }
- /****************************************************************************************
- * mcan send message
- ****************************************************************************************/
- static rt_ssize_t mcan_sendmsg(struct rt_can_device *device, const void *buf, rt_uint32_t boxno)
- {
- hc32_mcan_driver_t *driver;
- hc32_mcan_config_t *hard;
- stc_mcan_tx_msg_t ll_tx_msg = {0};
- struct rt_can_msg *tx_msg;
- RT_ASSERT(device);
- driver = (hc32_mcan_driver_t *)device->parent.user_data;
- RT_ASSERT(driver);
- hard = &driver->mcan;
- driver->tx_box_num = boxno;
- RT_ASSERT(buf);
- tx_msg = (struct rt_can_msg *)buf;
- /* Parameter validity check */
- RT_ASSERT(IS_CAN_VALID_ID(tx_msg->ide, tx_msg->id));
- #if defined(RT_CAN_USING_CANFD)
- RT_ASSERT(tx_msg->len <= MCAN_DLC64);
- #else
- RT_ASSERT(tx_msg->len <= MCAN_DLC8);
- #endif
- /* rt CAN Tx message to MCAN LL driver Tx message */
- ll_tx_msg.ID = tx_msg->id;
- ll_tx_msg.IDE = tx_msg->ide;
- ll_tx_msg.RTR = tx_msg->rtr;
- ll_tx_msg.DLC = tx_msg->len;
- #if defined(RT_CAN_USING_CANFD)
- ll_tx_msg.FDF = tx_msg->fd_frame;
- ll_tx_msg.BRS = tx_msg->brs;
- #endif
- rt_memcpy(ll_tx_msg.au8Data, tx_msg->data, m_mcan_data_size[ll_tx_msg.DLC]);
- if (MCAN_AddMsgToTxFifoQueue(hard->instance, &ll_tx_msg) != LL_OK)
- {
- return -RT_ERROR;
- }
- return RT_EOK;
- }
- /****************************************************************************************
- * mcan receive message
- ****************************************************************************************/
- static rt_ssize_t mcan_recvmsg(struct rt_can_device *device, void *buf, rt_uint32_t boxno)
- {
- hc32_mcan_driver_t *driver;
- hc32_mcan_config_t *hard;
- stc_mcan_rx_msg_t ll_rx_msg = {0};
- struct rt_can_msg *rx_msg;
- rt_uint32_t rx_location;
- RT_ASSERT(device);
- driver = (hc32_mcan_driver_t *)device->parent.user_data;
- RT_ASSERT(driver);
- hard = &driver->mcan;
- RT_ASSERT(buf);
- rx_msg = (struct rt_can_msg *)buf;
- if (boxno == CAN_RX_FIFO0)
- {
- rx_location = MCAN_RX_FIFO0;
- }
- else if (boxno == CAN_RX_FIFO1)
- {
- rx_location = MCAN_RX_FIFO1;
- }
- else
- {
- rx_location = boxno;
- }
- if (MCAN_GetRxMsg(hard->instance, rx_location, &ll_rx_msg) != LL_OK)
- {
- rt_kprintf("No available message in the specified RX location.\n");
- return -(RT_ERROR);
- }
- /* MCAN LL driver Rx message to rt CAN Rx message */
- rx_msg->id = ll_rx_msg.ID;
- rx_msg->ide = ll_rx_msg.IDE;
- rx_msg->rtr = ll_rx_msg.RTR;
- rx_msg->len = ll_rx_msg.DLC;
- rx_msg->priv = 0;
- #if defined(RT_CAN_USING_HDR)
- /* Hardware filter messages are valid */
- rx_msg->hdr_index = ll_rx_msg.u32FilterIndex;
- device->hdr[rx_msg->hdr_index].connected = 1;
- #endif
- #if defined(RT_CAN_USING_CANFD)
- rx_msg->fd_frame = ll_rx_msg.FDF;
- rx_msg->brs = ll_rx_msg.BRS;
- #endif
- if (rx_msg->len > 0)
- {
- rt_memcpy(&rx_msg->data[0], &ll_rx_msg.au8Data[0], m_mcan_data_size[ll_rx_msg.DLC]);
- }
- return RT_EOK;
- }
- /****************************************************************************************
- * mcan isr
- ****************************************************************************************/
- static rt_uint32_t mcan_get_rx_buffer_num(rt_uint32_t new_data)
- {
- rt_uint32_t num = 0;
- while (new_data)
- {
- new_data = new_data & (new_data - 1);
- num++;
- }
- return num++;
- }
- rt_inline void mcan_isr(hc32_mcan_driver_t *driver, uint32_t int_sel)
- {
- struct rt_can_device *device = &driver->can_device;
- CM_MCAN_TypeDef *MCANx = driver->mcan.instance;
- uint32_t ir_status = MCANx->IR;
- uint32_t psr = MCANx->PSR;
- uint32_t ndat1 = MCANx->NDAT1;
- uint32_t ndat2 = MCANx->NDAT2;
- int rx_buf_index;
- int_sel &= ~(MCAN_FLAG_RX_FIFO0_NEW_MSG | MCAN_FLAG_RX_FIFO1_NEW_MSG | MCAN_FLAG_RX_BUF_NEW_MSG);
- if (0U != (ir_status & int_sel))
- {
- MCAN_ClearStatus(MCANx, ir_status & int_sel);
- }
- /* Check normal status flag */
- /* Transmission completed */
- if (ir_status & MCAN_FLAG_TX_CPLT)
- {
- rt_hw_can_isr(device, RT_CAN_EVENT_TX_DONE | (driver->tx_box_num << 8U));
- }
- /* Rx FIFO0 new message */
- if (ir_status & MCAN_FLAG_RX_FIFO0_NEW_MSG)
- {
- if (MCAN_GetRxFifoFillLevel(MCANx, MCAN_RX_FIFO0) <= 1)
- {
- MCAN_ClearStatus(MCANx, MCAN_FLAG_RX_FIFO0_NEW_MSG);
- }
- rt_hw_can_isr(device, RT_CAN_EVENT_RX_IND | (MCAN_RX_FIFO0 << 8));
- }
- /* Rx FIFO1 new message */
- if (ir_status & MCAN_FLAG_RX_FIFO1_NEW_MSG)
- {
- if (MCAN_GetRxFifoFillLevel(MCANx, MCAN_RX_FIFO1) <= 1)
- {
- MCAN_ClearStatus(MCANx, MCAN_FLAG_RX_FIFO1_NEW_MSG);
- }
- rt_hw_can_isr(device, RT_CAN_EVENT_RX_IND | (MCAN_RX_FIFO1 << 8));
- }
- /* Rx Buffer new message */
- if (ir_status & MCAN_FLAG_RX_BUF_NEW_MSG)
- {
- /* Set an invalid index. Then find out the first Rx buffer that received new message. */
- rx_buf_index = -1;
- if (ndat1 > 0)
- {
- rx_buf_index = __CLZ(__RBIT(ndat1));
- }
- else if (ndat2 > 0)
- {
- rx_buf_index = __CLZ(__RBIT(ndat2)) + 32;
- }
- else
- {
- /* rsvd */
- }
- ndat1 = mcan_get_rx_buffer_num(ndat1);
- ndat2 = mcan_get_rx_buffer_num(ndat2);
- if ((ndat1 + ndat2) <= 1)
- {
- MCAN_ClearStatus(MCANx, MCAN_FLAG_RX_BUF_NEW_MSG);
- }
- rt_hw_can_isr(device, RT_CAN_EVENT_RX_IND | (rx_buf_index << 8));
- }
- /* Rx FIFO0 lost message, handle as rx overflow */
- if (ir_status & MCAN_FLAG_RX_FIFO0_MSG_LOST)
- {
- rt_hw_can_isr(device, RT_CAN_EVENT_RXOF_IND | (MCAN_RX_FIFO0 << 8));
- }
- /* Rx FIFO1 lost message, handle as rx overflow */
- if (ir_status & MCAN_FLAG_RX_FIFO1_MSG_LOST)
- {
- rt_hw_can_isr(device, RT_CAN_EVENT_RXOF_IND | (MCAN_RX_FIFO1 << 8));
- }
- /* Error occurred during transmitting. Handle as tx failure. */
- if ((psr & MCAN_PSR_ACT) == MCAN_PSR_ACT)
- {
- #if defined(RT_CAN_USING_CANFD)
- if (ir_status & (MCAN_FLAG_ARB_PHASE_ERROR | MCAN_FLAG_DATA_PHASE_ERROR))
- {
- rt_hw_can_isr(device, RT_CAN_EVENT_TX_FAIL | (driver->tx_box_num << 8U));
- }
- #else
- if (ir_status & MCAN_FLAG_ARB_PHASE_ERROR)
- {
- rt_hw_can_isr(device, RT_CAN_EVENT_TX_FAIL | (driver->tx_box_num << 8U));
- }
- #endif
- }
- /* Check bus-off status flag */
- if (psr & MCAN_PSR_BO)
- {
- /* The node is in bus-off state. */
- /* If the device goes Bus_Off, it will set CCCR.INIT of its own accord, stopping all bus activities.
- The application should clear CCCR.INIT, then the device can resume normal operation.
- Once CCCR.INIT has been cleared by the CPU, the device will then wait for 129 occurrences of
- Bus Idle(129 * 11 consecutive recessive bits) before resuming normal operation. */
- MCAN_Start(MCANx);
- }
- }
- /****************************************************************************************
- * mcan irq handler
- ****************************************************************************************/
- #if defined(HC32F448) || defined(HC32F4A8) || defined(HC32F334)
- #if defined(BSP_USING_MCAN1)
- void MCAN1_INT0_Handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- mcan_isr(&m_mcan_driver_list[MCAN1_INDEX], m_mcan_driver_list[MCAN1_INDEX].mcan.int0_sel);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif /* BSP_USING_MCAN1 */
- #if defined(BSP_USING_MCAN2)
- void MCAN2_INT0_Handler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- mcan_isr(&m_mcan_driver_list[MCAN2_INDEX], m_mcan_driver_list[MCAN2_INDEX].mcan.int0_sel);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif /* BSP_USING_MCAN2 */
- #endif
- /****************************************************************************************
- * mcan initialization configurations
- ****************************************************************************************/
- static void mcan_irq_config(hc32_mcan_config_t *hard)
- {
- #if defined(HC32F448) || defined(HC32F334)
- if (hard->int0_sel != 0)
- {
- hc32_install_irq_handler(&hard->int0_cfg, RT_NULL, RT_TRUE);
- }
- #elif defined(HC32F4A8)
- if (hard->int0_sel != 0)
- {
- hc32_install_irq_handler(&hard->int0_cfg, hard->irq_callback0, RT_TRUE);
- }
- #endif
- }
- static void mcan_enable_periph_clock(void)
- {
- #if defined(HC32F448) || defined(HC32F4A8)
- #if defined(BSP_USING_MCAN1)
- FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_MCAN1, ENABLE);
- #endif
- #if defined(BSP_USING_MCAN2)
- FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_MCAN2, ENABLE);
- #endif
- #elif defined(HC32F334)
- #if defined(BSP_USING_MCAN1) || defined(BSP_USING_MCAN2)
- FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_MCAN1 | FCG1_PERIPH_MCAN2, ENABLE);
- #endif
- #endif
- }
- static void mcan_set_init_para(void)
- {
- struct rt_can_device *device;
- stc_mcan_init_t *hard_init;
- #if defined(BSP_USING_MCAN1)
- device = &m_mcan_driver_list[MCAN1_INDEX].can_device;
- hard_init = &m_mcan_driver_list[MCAN1_INDEX].mcan.init_para;
- device->config.mode = MCAN1_WORK_MODE;
- device->config.privmode = MCAN1_TX_PRIV_MODE;
- device->config.baud_rate = MCAN1_NOMINAL_BAUD_RATE;
- #if defined(RT_CAN_USING_HDR)
- device->config.maxhdr = MCAN_TOTAL_FILTER_NUM;
- #endif
- #if defined(RT_CAN_USING_CANFD)
- device->config.baud_rate_fd = MCAN1_DATA_BAUD_RATE;
- device->config.enable_canfd = MCAN1_FD_SEL;
- hard_init->u32FrameFormat = m_mcan_fd_mode[MCAN1_FD_SEL];
- #else
- hard_init->u32FrameFormat = MCAN_FRAME_CLASSIC;
- #endif
- hard_init->u32Mode = m_mcan_work_mode[device->config.mode];
- hard_init->u32AutoRetx = MCAN_AUTO_RETX_ENABLE;
- hard_init->u32TxPause = MCAN_TX_PAUSE_DISABLE;
- hard_init->u32ProtocolException = MCAN_PROTOCOL_EXP_ENABLE;
- /* Message RAM */
- hard_init->stcMsgRam.u32AddrOffset = 0U;
- hard_init->stcMsgRam.u32StdFilterNum = MCAN1_STD_FILTER_NUM;
- hard_init->stcMsgRam.u32ExtFilterNum = MCAN1_EXT_FILTER_NUM;
- hard_init->stcMsgRam.u32RxFifo0Num = MCAN1_RX_FIFO0_NUM;
- hard_init->stcMsgRam.u32RxFifo0DataSize = MCAN1_RX_FIFO0_DATA_FIELD_SIZE;
- hard_init->stcMsgRam.u32RxFifo1Num = 0U;
- hard_init->stcMsgRam.u32RxFifo1DataSize = 0U;
- hard_init->stcMsgRam.u32RxBufferNum = 0U;
- hard_init->stcMsgRam.u32RxBufferDataSize = 0U;
- hard_init->stcMsgRam.u32TxEventNum = 0U;
- hard_init->stcMsgRam.u32TxBufferNum = 0U;
- hard_init->stcMsgRam.u32TxFifoQueueNum = MCAN1_TX_FIFO_NUM;
- hard_init->stcMsgRam.u32TxFifoQueueMode = m_mcan_tx_priv_mode[device->config.privmode];
- hard_init->stcMsgRam.u32TxDataSize = MCAN1_TX_FIFO_DATA_FIELD_SIZE;
- /* Acceptance filter */
- hard_init->stcFilter.pstcStdFilterList = m_mcan1_std_filters;
- hard_init->stcFilter.pstcExtFilterList = m_mcan1_ext_filters;
- hard_init->stcFilter.u32StdFilterConfigNum = hard_init->stcMsgRam.u32StdFilterNum;
- hard_init->stcFilter.u32ExtFilterConfigNum = hard_init->stcMsgRam.u32ExtFilterNum;
- #endif
- #if defined(BSP_USING_MCAN2)
- device = &m_mcan_driver_list[MCAN2_INDEX].can_device;
- hard_init = &m_mcan_driver_list[MCAN2_INDEX].mcan.init_para;
- device->config.mode = MCAN2_WORK_MODE;
- device->config.privmode = MCAN2_TX_PRIV_MODE;
- device->config.baud_rate = MCAN2_NOMINAL_BAUD_RATE;
- #if defined(RT_CAN_USING_HDR)
- device->config.maxhdr = MCAN_TOTAL_FILTER_NUM;
- #endif
- #if defined(RT_CAN_USING_CANFD)
- device->config.baud_rate_fd = MCAN2_DATA_BAUD_RATE;
- device->config.enable_canfd = MCAN2_FD_SEL;
- hard_init->u32FrameFormat = m_mcan_fd_mode[MCAN2_FD_SEL];
- #else
- hard_init->u32FrameFormat = MCAN_FRAME_CLASSIC;
- #endif
- hard_init->u32Mode = m_mcan_work_mode[device->config.mode];
- hard_init->u32AutoRetx = MCAN_AUTO_RETX_ENABLE;
- hard_init->u32TxPause = MCAN_TX_PAUSE_DISABLE;
- hard_init->u32ProtocolException = MCAN_PROTOCOL_EXP_ENABLE;
- /* Message RAM */
- hard_init->stcMsgRam.u32AddrOffset = 0U;
- hard_init->stcMsgRam.u32StdFilterNum = MCAN2_STD_FILTER_NUM;
- hard_init->stcMsgRam.u32ExtFilterNum = MCAN2_EXT_FILTER_NUM;
- hard_init->stcMsgRam.u32RxFifo0Num = MCAN2_RX_FIFO0_NUM;
- hard_init->stcMsgRam.u32RxFifo0DataSize = MCAN2_RX_FIFO0_DATA_FIELD_SIZE;
- hard_init->stcMsgRam.u32RxFifo1Num = 0U;
- hard_init->stcMsgRam.u32RxFifo1DataSize = 0U;
- hard_init->stcMsgRam.u32RxBufferNum = 0U;
- hard_init->stcMsgRam.u32RxBufferDataSize = 0U;
- hard_init->stcMsgRam.u32TxEventNum = 0U;
- hard_init->stcMsgRam.u32TxBufferNum = 0U;
- hard_init->stcMsgRam.u32TxFifoQueueNum = MCAN2_TX_FIFO_NUM;
- hard_init->stcMsgRam.u32TxFifoQueueMode = m_mcan_tx_priv_mode[device->config.privmode];
- hard_init->stcMsgRam.u32TxDataSize = MCAN2_TX_FIFO_DATA_FIELD_SIZE;
- /* Acceptance filter */
- hard_init->stcFilter.pstcStdFilterList = m_mcan2_std_filters;
- hard_init->stcFilter.pstcExtFilterList = m_mcan2_ext_filters;
- hard_init->stcFilter.u32StdFilterConfigNum = hard_init->stcMsgRam.u32StdFilterNum;
- hard_init->stcFilter.u32ExtFilterConfigNum = hard_init->stcMsgRam.u32ExtFilterNum;
- #endif
- }
- static void init_can_cfg(hc32_mcan_driver_t *driver)
- {
- struct can_configure can_cfg = CANDEFAULTCONFIG;
- can_cfg.privmode = RT_CAN_MODE_NOPRIV;
- can_cfg.ticks = 50;
- #if defined(RT_CAN_USING_HDR)
- can_cfg.maxhdr = MCAN_TOTAL_FILTER_NUM;
- #endif
- #if defined(RT_CAN_USING_CANFD)
- can_cfg.baud_rate_fd = CANFD_DATA_BAUD_4M;
- can_cfg.enable_canfd = MCAN_FD_SEL;
- #endif
- can_cfg.sndboxnumber = MCAN_TX_FIFO_NUM;
- driver->can_device.config = can_cfg;
- }
- #if defined(HC32F4A8)
- /**
- * @brief This function gets mcan irq handle.
- * @param None
- * @retval None
- */
- static void mcan_get_irq_callback(void)
- {
- #if defined(BSP_USING_MCAN1)
- m_mcan_driver_list[MCAN1_INDEX].mcan.irq_callback0 = MCAN1_INT0_Handler;
- #endif
- #if defined(BSP_USING_MCAN2)
- m_mcan_driver_list[MCAN2_INDEX].mcan.irq_callback0 = MCAN2_INT0_Handler;
- #endif
- }
- #endif
- extern rt_err_t rt_hw_board_mcan_init(CM_MCAN_TypeDef *MCANx);
- extern void CanPhyEnable(void);
- static int rt_hw_mcan_init(void)
- {
- rt_uint32_t i, filter;
- rt_uint32_t tx_boxnum;
- hc32_mcan_config_t *hard;
- mcan_enable_periph_clock();
- mcan_set_init_para();
- #if defined(HC32F4A8)
- mcan_get_irq_callback();
- #endif
- for (i = 0; i < MCAN_DEV_CNT; i++)
- {
- hard = &m_mcan_driver_list[i].mcan;
- for (filter = 0; filter < hard->init_para.stcMsgRam.u32StdFilterNum; filter++)
- {
- hard->init_para.stcFilter.pstcStdFilterList[filter].u32IdType = MCAN_STD_ID;
- }
- for (filter = 0; filter < hard->init_para.stcMsgRam.u32ExtFilterNum; filter++)
- {
- hard->init_para.stcFilter.pstcExtFilterList[filter].u32IdType = MCAN_EXT_ID;
- }
- /* MCAN IRQ configuration */
- mcan_irq_config(hard);
- MCAN_Init(hard->instance, &hard->init_para);
- tx_boxnum = hard->init_para.stcMsgRam.u32TxBufferNum + hard->init_para.stcMsgRam.u32TxFifoQueueNum;
- if (tx_boxnum >= 32)
- {
- tx_boxnum = 0xFFFFFFFF;
- }
- else
- {
- tx_boxnum = (1UL << tx_boxnum) - 1;
- }
- MCAN_TxBufferNotificationCmd(hard->instance, tx_boxnum, MCAN_INT_TX_CPLT, ENABLE);
- MCAN_IntCmd(hard->instance, hard->int0_sel, MCAN_INT_LINE0, ENABLE);
- if (i > 0)
- {
- hard->init_para.stcMsgRam.u32AddrOffset = \
- m_mcan_driver_list[i - 1].mcan.init_para.stcMsgRam.u32AddrOffset + \
- m_mcan_driver_list[i - 1].mcan.init_para.stcMsgRam.u32AllocatedSize;
- }
- init_can_cfg(&m_mcan_driver_list[i]);
- /* GPIO initialization */
- rt_hw_board_mcan_init(hard->instance);
- /* Register CAN device */
- rt_hw_can_register(&m_mcan_driver_list[i].can_device,
- hard->name,
- &m_mcan_ops,
- &m_mcan_driver_list[i]);
- }
- /* Onboard CAN transceiver enable */
- CanPhyEnable();
- return RT_EOK;
- }
- INIT_DEVICE_EXPORT(rt_hw_mcan_init);
- #endif
- #endif /* BSP_USING_MCAN */
- /************************** end of file ******************/
|