| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748 |
- /**************************************************************************//**
- *
- * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-4-27 Wayne First version
- *
- ******************************************************************************/
- #include <rtconfig.h>
- #if defined(BSP_USING_CANFD)
- #include <rtdevice.h>
- #include <rthw.h>
- #include "NuMicro.h"
- #include "nu_bitutil.h"
- #define LOG_TAG "drv.canfd"
- #undef DBG_ENABLE
- #define DBG_SECTION_NAME LOG_TAG
- #define DBG_LEVEL LOG_LVL_ERROR
- #define DBG_COLOR
- #include <rtdbg.h>
- /* Private Define ---------------------------------------------------------------*/
- #define IS_CAN_STDID(STDID) ((STDID) <= 0x7FFU)
- #define IS_CAN_EXTID(EXTID) ((EXTID) <= 0x1FFFFFFFU)
- #define IS_CAN_DLC(DLC) ((DLC) <= 8U)
- /* Default config for serial_configure structure */
- #define NU_CANFD_CONFIG_DEFAULT \
- { \
- CAN1MBaud, /* 1M bits/s */ \
- RT_CANMSG_BOX_SZ, /* message box max size */ \
- RT_CANSND_BOX_NUM, /* message box number */ \
- RT_CAN_MODE_NORMAL, /* Normal mode */ \
- 0, /* privmode */ \
- 0, /* reserved */ \
- 100, /* Timeout Tick */ \
- }
- enum
- {
- CANFD_START = -1,
- #if defined(BSP_USING_CANFD0)
- CANFD0_IDX,
- #endif
- #if defined(BSP_USING_CANFD1)
- CANFD1_IDX,
- #endif
- #if defined(BSP_USING_CANFD2)
- CANFD2_IDX,
- #endif
- #if defined(BSP_USING_CANFD3)
- CANFD3_IDX,
- #endif
- CANFD_CNT
- };
- /* Private Typedef --------------------------------------------------------------*/
- struct nu_canfd
- {
- struct rt_can_device dev;
- char *name;
- CANFD_T *base;
- uint32_t rstidx;
- IRQn_Type irqn0;
- IRQn_Type irqn1;
- uint32_t int_flag;
- CANFD_FD_T sCANFD_Config;
- };
- typedef struct nu_canfd *nu_canfd_t;
- /* Private functions ------------------------------------------------------------*/
- static rt_err_t nu_canfd_configure(struct rt_can_device *can, struct can_configure *cfg);
- static rt_err_t nu_canfd_control(struct rt_can_device *can, int cmd, void *arg);
- static int nu_canfd_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno);
- static int nu_canfd_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno);
- static void nu_canfd_isr(nu_canfd_t can);
- static struct nu_canfd nu_canfd_arr[] =
- {
- #if defined(BSP_USING_CANFD0)
- {
- .name = "canfd0",
- .base = CANFD0,
- .rstidx = CANFD0_RST,
- .irqn0 = CANFD00_IRQn,
- .irqn1 = CANFD01_IRQn,
- },
- #endif
- #if defined(BSP_USING_CANFD1)
- {
- .name = "canfd1",
- .base = CANFD1,
- .rstidx = CANFD1_RST,
- .irqn0 = CANFD10_IRQn,
- .irqn1 = CANFD11_IRQn,
- },
- #endif
- #if defined(BSP_USING_CANFD2)
- {
- .name = "canfd2",
- .base = CANFD2,
- .rstidx = CANFD2_RST,
- .irqn0 = CANFD20_IRQn,
- .irqn1 = CANFD21_IRQn,
- },
- #endif
- #if defined(BSP_USING_CANFD3)
- {
- .name = "canfd3",
- .base = CANFD3,
- .rstidx = CANFD3_RST,
- .irqn0 = CANFD30_IRQn,
- .irqn1 = CANFD31_IRQn,
- },
- #endif
- }; /* struct nu_can */
- /* Public functions ------------------------------------------------------------*/
- /* Private variables ------------------------------------------------------------*/
- static const struct rt_can_ops nu_canfd_ops =
- {
- .configure = nu_canfd_configure,
- .control = nu_canfd_control,
- .sendmsg = nu_canfd_sendmsg,
- .recvmsg = nu_canfd_recvmsg,
- };
- static const struct can_configure nu_canfd_default_config = NU_CANFD_CONFIG_DEFAULT;
- /* Interrupt Handle Function ----------------------------------------------------*/
- #if defined(BSP_USING_CANFD0)
- /* CAN0 interrupt entry */
- void CANFD00_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- nu_canfd_isr(&nu_canfd_arr[CANFD0_IDX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- void CANFD01_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- nu_canfd_isr(&nu_canfd_arr[CANFD0_IDX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #if defined(BSP_USING_CANFD1)
- void CANFD10_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- nu_canfd_isr(&nu_canfd_arr[CANFD1_IDX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- void CANFD11_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- nu_canfd_isr(&nu_canfd_arr[CANFD1_IDX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #if defined(BSP_USING_CANFD2)
- void CANFD20_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- nu_canfd_isr(&nu_canfd_arr[CANFD2_IDX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- void CANFD21_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- nu_canfd_isr(&nu_canfd_arr[CANFD2_IDX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- #if defined(BSP_USING_CANFD3)
- void CANFD30_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- nu_canfd_isr(&nu_canfd_arr[CANFD3_IDX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- void CANFD31_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- nu_canfd_isr(&nu_canfd_arr[CANFD3_IDX]);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif
- /* Private Variables ------------------------------------------------------------*/
- const char *szIR[] =
- {
- "CANFD_IR_RF0N - Rx FIFO 0 New Message",
- "CANFD_IR_RF0W - Rx FIFO 0 Watermark Reached",
- "CANFD_IR_RF0F - Rx FIFO 0 Full",
- "CANFD_IR_RF0L - Rx FIFO 0 Message Lost",
- "CANFD_IR_RF1N - Rx FIFO 1 New Message",
- "CANFD_IR_RF1W - Rx FIFO 1 Watermark Reached",
- "CANFD_IR_RF1F - Rx FIFO 1 Full",
- "CANFD_IR_RF1L - Rx FIFO 1 Message Lost",
- "CANFD_IR_HPM - High Priority Message",
- "CANFD_IR_TC - Transmission Completed",
- "CANFD_IR_TCF - Transmission Cancellation Finished",
- "CANFD_IR_TFE - Tx FIFO Empty",
- "CANFD_IR_TEFN - Tx Event FIFO New Entry",
- "CANFD_IR_TEFW - Tx Event FIFO Watermark Reached",
- "CANFD_IR_TEFF - Tx Event FIFO Full",
- "CANFD_IR_TEFL - Tx Event FIFO Event Lost",
- "CANFD_IR_TSW - Timestamp Wraparound",
- "CANFD_IR_MRAF - Message RAM Access Failure",
- "CANFD_IR_TOO - Timeout Occurred",
- "CANFD_IR_DRX - Message stored to Dedicated Rx Buffer",
- "BIT20",
- "BIT21",
- "CANFD_IR_ELO - Error Logging Overflow",
- "CANFD_IR_EP - Error Passive",
- "CANFD_IR_EW - Warning Status",
- "CANFD_IR_BO - Bus_Off Status",
- "CANFD_IR_WDI - Watchdog",
- "CANFD_IR_PEA - Protocol Error in Arbitration Phase",
- "CANFD_IR_PED - Protocol Error in Data Phase",
- "CANFD_IR_ARA - Access to Reserved Address",
- "BIT30",
- "BIT31"
- };
- static void dump_interrupt_event(uint32_t u32Status)
- {
- uint32_t idx;
- while ((idx = nu_ctz(u32Status)) < 32) // Count Trailing Zeros ==> Find First One
- {
- LOG_D("[%s]", szIR[idx]);
- u32Status &= ~(1 << idx);
- }
- }
- static void nu_canfd_isr(nu_canfd_t psNuCANFD)
- {
- /* Get base address of CAN register */
- CANFD_T *base = psNuCANFD->base;
- /* Get interrupt status */
- uint32_t u32Status = base->IR;
- CANFD_ClearStatusFlag(base, u32Status);
- /* Dump IR event */
- dump_interrupt_event(u32Status);
- /* Check Status Interrupt Flag (Error status Int and Status change Int) */
- /**************************/
- /* Status Change interrupt*/
- /**************************/
- if (u32Status & CANFD_IR_TC_Msk)
- {
- if (psNuCANFD->int_flag & RT_DEVICE_FLAG_INT_TX)
- {
- rt_hw_can_isr(&psNuCANFD->dev, RT_CAN_EVENT_TX_DONE);
- }
- }
- if (u32Status & (CANFD_IR_RF0N_Msk | CANFD_IR_RF1N_Msk))
- {
- if (psNuCANFD->int_flag & RT_DEVICE_FLAG_INT_RX)
- {
- rt_hw_can_isr(&psNuCANFD->dev, RT_CAN_EVENT_RX_IND);
- }
- }
- if (u32Status & (CANFD_IR_RF0L_Msk | CANFD_IR_RF1L_Msk))
- {
- rt_hw_can_isr(&psNuCANFD->dev, RT_CAN_EVENT_RXOF_IND);
- }
- if (u32Status & (CANFD_IR_TEFF_Msk | CANFD_IR_TOO_Msk))
- {
- rt_hw_can_isr(&psNuCANFD->dev, RT_CAN_EVENT_TX_FAIL);
- }
- /**************************/
- /* Error Status interrupt */
- /**************************/
- if (u32Status & CANFD_IR_EW_Msk)
- {
- LOG_E("[%s]EWARN", psNuCANFD->name) ;
- }
- if (u32Status & CANFD_IR_BO_Msk)
- {
- LOG_E("[%s]BUSOFF", psNuCANFD->name) ;
- /* To release busoff pin */
- }
- if (u32Status & CANFD_IR_PED_Msk)
- {
- LOG_E("[%s] LEC: %03x\n", psNuCANFD->name, base->PSR & CANFD_PSR_LEC_Msk) ;
- }
- }
- static void nu_canfd_ie(nu_canfd_t psNuCANFD)
- {
- uint32_t u32CanFDIE = CANFD_IE_BOE_Msk;
- if (psNuCANFD->int_flag & (RT_DEVICE_FLAG_INT_RX))
- {
- /* Rx FIFO 0 New Message Interrupt */
- u32CanFDIE |= (CANFD_IE_RF0NE_Msk | CANFD_IE_RF1NE_Msk);
- }
- if (psNuCANFD->int_flag & (RT_DEVICE_FLAG_INT_TX))
- {
- /* Transmission Completed Interrupt */
- /* Timeout Occurred Interrupt */
- u32CanFDIE |= (CANFD_IE_TCE_Msk | CANFD_IE_TEFNE_Msk);
- }
- if (psNuCANFD->int_flag & RT_DEVICE_CAN_INT_ERR)
- {
- /* Bus_Off Status Interrupt */
- /* Warning Status Interrupt */
- /* Error Passive Interrupt */
- /* Error Logging Overflow Interrupt */
- /* Protocol Error in Data Phase interrupt Indicator */
- u32CanFDIE |= (CANFD_IE_EPE_Msk | CANFD_IE_EWE_Msk | CANFD_IE_ELOE_Msk | CANFD_IE_TOOE_Msk | CANFD_IR_PED_Msk);
- }
- //u32CanFDIE = 0xffffffff;
- CANFD_EnableInt(psNuCANFD->base, u32CanFDIE, 0,
- (psNuCANFD->int_flag & (RT_DEVICE_FLAG_INT_TX)) ? CANFD_TXBTIE_TIEn_Msk : 0,
- (psNuCANFD->int_flag & (RT_DEVICE_FLAG_INT_TX)) ? CANFD_TXBCIE_CFIEn_Msk : 0);
- }
- static rt_err_t nu_canfd_configure(struct rt_can_device *can, struct can_configure *cfg)
- {
- nu_canfd_t psNuCANFD = (nu_canfd_t)can;
- CANFD_FD_T *psCANFDConf;
- RT_ASSERT(can);
- RT_ASSERT(cfg);
- psCANFDConf = &psNuCANFD->sCANFD_Config;
- /* Get base address of CAN register */
- CANFD_T *base = psNuCANFD->base;
- CANFD_GetDefaultConfig(psCANFDConf, CANFD_OP_CAN_MODE);
- LOG_I("Message Ram Size: %d @%08x ~ %08x", psCANFDConf->u32MRamSize, CANFD_SRAM_BASE_ADDR(base), psCANFDConf->u32MRamSize + CANFD_SRAM_BASE_ADDR(base));
- LOG_I("SIDFC: %d @%08x Size:%d", psCANFDConf->sElemSize.u32SIDFC, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32SIDFC_FLSSA, psCANFDConf->sElemSize.u32SIDFC * sizeof(CANFD_STD_FILTER_T));
- LOG_I("XIDFC: %d @%08x Size:%d", psCANFDConf->sElemSize.u32XIDFC, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32XIDFC_FLESA, psCANFDConf->sElemSize.u32XIDFC * sizeof(CANFD_EXT_FILTER_T));
- LOG_I("RxFifo0: %d @%08x Size:%d", psCANFDConf->sElemSize.u32RxFifo0, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32RXF0C_F0SA, psCANFDConf->sElemSize.u32RxFifo0 * sizeof(CANFD_BUF_T));
- LOG_I("RxFifo1: %d @%08x Size:%d", psCANFDConf->sElemSize.u32RxFifo1, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32RXF1C_F1SA, psCANFDConf->sElemSize.u32RxFifo1 * sizeof(CANFD_BUF_T));
- LOG_I("RxBuf: %d @%08x Size:%d", psCANFDConf->sElemSize.u32RxBuf, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32RXBC_RBSA, psCANFDConf->sElemSize.u32RxBuf * sizeof(CANFD_BUF_T));
- LOG_I("TxEventFifo: %d @%08x Size:%d", psCANFDConf->sElemSize.u32TxEventFifo, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32TXEFC_EFSA, psCANFDConf->sElemSize.u32TxEventFifo * sizeof(CANFD_EXT_FILTER_T));
- LOG_I("TxBuf: %d @%08x Size:%d", psCANFDConf->sElemSize.u32TxBuf, CANFD_SRAM_BASE_ADDR(base) + psCANFDConf->sMRamStartAddr.u32TXBC_TBSA, psCANFDConf->sElemSize.u32TxBuf * sizeof(CANFD_BUF_T));
- psCANFDConf->sBtConfig.sNormBitRate.u32BitRate = cfg->baud_rate;
- psCANFDConf->sBtConfig.sDataBitRate.u32BitRate = 0;
- LOG_I("CAN Baud rate: %d bps", cfg->baud_rate);
- switch (cfg->mode)
- {
- case RT_CAN_MODE_NORMAL: // Normal
- psCANFDConf->sBtConfig.evTestMode = eCANFD_NORMAL;
- break;
- case RT_CAN_MODE_LISTEN: // Bus monitor Mode, can't start a transmission
- psCANFDConf->sBtConfig.evTestMode = eCANFD_BUS_MONITOR;
- break;
- case RT_CAN_MODE_LOOPBACK: // Test - Internal loopback
- psCANFDConf->sBtConfig.evTestMode = eCANFD_LOOPBACK_INTERNAL;
- break;
- case RT_CAN_MODE_LOOPBACKANLISTEN:
- default:
- rt_kprintf("Unsupported Operating mode\n");
- goto exit_nu_canfd_configure;
- }
- /*Set the CAN Bit Rate and Operating mode*/
- CANFD_Open(base, psCANFDConf);
- /* Set FIFO policy */
- #if defined(RT_CAN_USING_HDR)
- /* Whitelist filtering */
- CANFD_SetGFC(base, eCANFD_REJ_NON_MATCH_FRM, eCANFD_REJ_NON_MATCH_FRM, 0, 0);
- #else
- /* Blacklist filtering. */
- CANFD_SetGFC(base, eCANFD_ACC_NON_MATCH_FRM_RX_FIFO0, eCANFD_ACC_NON_MATCH_FRM_RX_FIFO0, 0, 0);
- #endif
- /* Enable interrupt */
- nu_canfd_ie(psNuCANFD);
- //LOG_HEX("canfd", 16, (void *)base, sizeof(CANFD_T));
- /* Lock protected registers & Run */
- CANFD_RunToNormal(base, TRUE);
- return RT_EOK;
- exit_nu_canfd_configure:
- CANFD_Close(base);
- return -(RT_ERROR);
- }
- static rt_err_t nu_canfd_control(struct rt_can_device *can, int cmd, void *arg)
- {
- rt_uint32_t argval = (rt_uint32_t)arg;
- nu_canfd_t psNuCANFD = (nu_canfd_t)can;
- RT_ASSERT(can);
- switch (cmd)
- {
- case RT_DEVICE_CTRL_SET_INT:
- psNuCANFD->int_flag |= argval;
- return nu_canfd_configure(can, &can->config);
- case RT_DEVICE_CTRL_CLR_INT:
- psNuCANFD->int_flag &= ~argval;
- return nu_canfd_configure(can, &can->config);
- #if defined(RT_CAN_USING_HDR)
- case RT_CAN_CMD_SET_FILTER:
- {
- struct rt_can_filter_config *filter_cfg = (struct rt_can_filter_config *)arg;
- RT_ASSERT(filter_cfg);
- for (int i = 0; i < filter_cfg->count; i++)
- {
- uint32_t u32FEC = (filter_cfg->items[i].mode == RT_CAN_MODE_PRIV) ? eCANFD_FLTR_ELEM_SET_PRI_STO_FIFO0 : eCANFD_FLTR_ELEM_STO_FIFO0;
- /* Set the filter rule */
- if (filter_cfg->items[i].ide == RT_CAN_STDID)
- {
- /* for 11-bit */
- CANFD_STD_FILTER_T sStdFilter;
- if (i >= CANFD_MAX_11_BIT_FTR_ELEMS) // Check filter entry limitation
- return -(RT_ERROR);
- sStdFilter.SFID2 = filter_cfg->items[i].mask; /*!<Standard Filter ID 2. */ //mask
- sStdFilter.SFID1 = filter_cfg->items[i].id; /*!<Standard Filter ID 1. */ //filter
- sStdFilter.SFEC = u32FEC; /*!<Standard Filter Element Configuration */ //001b: Store in Rx FIFO 0 if filter matches
- sStdFilter.SFT = eCANFD_SID_FLTR_TYPE_CLASSIC; /*!<Standard Filter Type */ //10b: Classic filter: SFID1 = filter, SFID2 = mask
- CANFD_SetSIDFltr(psNuCANFD->base, i, sStdFilter.VALUE);
- }
- else
- {
- /* for 29-bit */
- CANFD_EXT_FILTER_T sXidFilter;
- if (i >= CANFD_MAX_29_BIT_FTR_ELEMS) // Check filter entry limitation
- return -(RT_ERROR);
- sXidFilter.EFID1 = filter_cfg->items[i].mask; /*!<Extended Filter ID 2. */ //mask
- sXidFilter.EFID2 = filter_cfg->items[i].id; /*!<Extended Filter ID 1. */ //filter
- sXidFilter.EFEC = u32FEC; /*!<Extended Filter Element Configuration */ //001b: Store in Rx FIFO 0 if filter matches
- sXidFilter.EFT = eCANFD_XID_FLTR_TYPE_CLASSIC; /*!<Extended Filter Type */ //10b: Classic filter: SFID1 = filter, SFID2 = mask
- CANFD_SetXIDFltr(psNuCANFD->base, i, sXidFilter.LOWVALUE, sXidFilter.HIGHVALUE);
- }
- } //for (int i = 0; i < filter_cfg->count; i++)
- }
- break;
- #endif
- case RT_CAN_CMD_SET_MODE:
- if ((argval == RT_CAN_MODE_NORMAL) ||
- (argval == RT_CAN_MODE_LISTEN) ||
- (argval == RT_CAN_MODE_LOOPBACK) ||
- (argval == RT_CAN_MODE_LOOPBACKANLISTEN))
- {
- if (argval != can->config.mode)
- {
- can->config.mode = argval;
- return nu_canfd_configure(can, &can->config);
- }
- }
- else
- {
- return -(RT_ERROR);
- }
- break;
- case RT_CAN_CMD_SET_BAUD:
- {
- if ((argval == CAN1MBaud) ||
- (argval == CAN800kBaud) ||
- (argval == CAN500kBaud) ||
- (argval == CAN250kBaud) ||
- (argval == CAN125kBaud) ||
- (argval == CAN100kBaud) ||
- (argval == CAN50kBaud) ||
- (argval == CAN20kBaud) ||
- (argval == CAN10kBaud))
- {
- if (argval != can->config.baud_rate)
- {
- can->config.baud_rate = argval;
- return nu_canfd_configure(can, &can->config);
- }
- }
- else
- {
- return -(RT_ERROR);
- }
- }
- break;
- case RT_CAN_CMD_SET_PRIV:
- if (argval != RT_CAN_MODE_PRIV &&
- argval != RT_CAN_MODE_NOPRIV)
- {
- return -(RT_ERROR);
- }
- if (argval != can->config.privmode)
- {
- can->config.privmode = argval;
- return nu_canfd_configure(can, &can->config);
- }
- break;
- case RT_CAN_CMD_GET_STATUS:
- {
- rt_uint32_t u32ErrCounter = psNuCANFD->base->ECR;
- rt_uint32_t u32ProtocolStatus = psNuCANFD->base->PSR;
- RT_ASSERT(arg);
- /*Receive Error Counter, return value is with Receive Error Passive.*/
- can->status.rcverrcnt = ((u32ErrCounter & CANFD_ECR_REC_Msk) >> CANFD_ECR_REC_Pos);
- /*Transmit Error Counter*/
- can->status.snderrcnt = ((u32ErrCounter & CANFD_ECR_TEC_Msk) >> CANFD_ECR_TEC_Pos);
- /*Last Error Type*/
- can->status.lasterrtype = ((u32ProtocolStatus & CANFD_PSR_LEC_Msk) >> CANFD_PSR_LEC_Pos);
- /*Status error code*/
- can->status.errcode = (u32ProtocolStatus & CANFD_PSR_EW_Msk) ? 1 :
- (u32ProtocolStatus & CANFD_PSR_EP_Msk) ? 2 :
- (u32ProtocolStatus & CANFD_PSR_BO_Msk) ? 3 :
- 0;
- rt_memcpy(arg, &can->status, sizeof(struct rt_can_status));
- }
- break;
- default:
- return -(RT_EINVAL);
- }
- return RT_EOK;
- }
- static int nu_canfd_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno)
- {
- CANFD_FD_MSG_T sTxMsg;
- struct rt_can_msg *pmsg;
- nu_canfd_t psNuCANFD = (nu_canfd_t)can;
- RT_ASSERT(can);
- RT_ASSERT(buf);
- pmsg = (struct rt_can_msg *) buf;
- if (pmsg->ide == RT_CAN_STDID && IS_CAN_STDID(pmsg->id))
- {
- /* Standard ID (11 bits)*/
- sTxMsg.u32Id = pmsg->id;
- sTxMsg.eIdType = eCANFD_SID;
- }
- else if (pmsg->ide == RT_CAN_EXTID && IS_CAN_EXTID(pmsg->id))
- {
- /* Extended ID (29 bits)*/
- sTxMsg.u32Id = pmsg->id;
- sTxMsg.eIdType = eCANFD_XID;
- }
- else
- {
- goto exit_nu_canfd_sendmsg;
- }
- sTxMsg.bBitRateSwitch = 0;
- if (pmsg->rtr == RT_CAN_DTR)
- {
- /* Data frame */
- sTxMsg.eFrmType = eCANFD_DATA_FRM;
- }
- else if (pmsg->rtr == RT_CAN_RTR)
- {
- /* Remote frame */
- sTxMsg.eFrmType = eCANFD_REMOTE_FRM;
- }
- else
- {
- goto exit_nu_canfd_sendmsg;
- }
- /* Check the parameters */
- if (IS_CAN_DLC(pmsg->len))
- {
- sTxMsg.u32DLC = pmsg->len;
- }
- else
- {
- goto exit_nu_canfd_sendmsg;
- }
- if (pmsg->len > 0)
- {
- rt_memcpy(&sTxMsg.au8Data[0], pmsg->data, pmsg->len);
- }
- if (!CANFD_TransmitTxMsg(psNuCANFD->base, 0, &sTxMsg))
- {
- goto exit_nu_canfd_sendmsg;
- }
- return RT_EOK;
- exit_nu_canfd_sendmsg:
- return -(RT_ERROR);
- }
- static int nu_canfd_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno)
- {
- CANFD_FD_MSG_T sRxMsg;
- struct rt_can_msg *pmsg;
- nu_canfd_t psNuCANFD = (nu_canfd_t)can;
- RT_ASSERT(can);
- RT_ASSERT(buf);
- pmsg = (struct rt_can_msg *) buf;
- /* get data */
- if (CANFD_ReadRxFifoMsg(psNuCANFD->base, 0, &sRxMsg) == FALSE)
- {
- rt_kprintf("No available RX Msg.\n");
- return -(RT_ERROR);
- }
- #ifdef RT_CAN_USING_HDR
- /* Hardware filter messages are valid */
- pmsg->hdr = boxno;
- can->hdr[pmsg->hdr].connected = 1;
- #endif
- pmsg->ide = (sRxMsg.eIdType == eCANFD_SID) ? RT_CAN_STDID : RT_CAN_EXTID;
- pmsg->rtr = (sRxMsg.eFrmType == eCANFD_DATA_FRM) ? RT_CAN_DTR : RT_CAN_RTR;
- pmsg->id = sRxMsg.u32Id;
- pmsg->len = sRxMsg.u32DLC;
- if (pmsg->len > 0)
- rt_memcpy(&pmsg->data[0], &sRxMsg.au8Data[0], pmsg->len);
- return RT_EOK;
- }
- /**
- * Hardware CAN Initialization
- */
- static int rt_hw_canfd_init(void)
- {
- int i;
- rt_err_t ret = RT_EOK;
- for (i = (CANFD_START + 1); i < CANFD_CNT; i++)
- {
- nu_canfd_arr[i].dev.config = nu_canfd_default_config;
- #ifdef RT_CAN_USING_HDR
- nu_canfd_arr[i].dev.config.maxhdr = RT_CANMSG_BOX_SZ;
- #endif
- /* Register can device */
- ret = rt_hw_can_register(&nu_canfd_arr[i].dev, nu_canfd_arr[i].name, &nu_canfd_ops, NULL);
- RT_ASSERT(ret == RT_EOK);
- /* Unmask interrupt. */
- NVIC_EnableIRQ(nu_canfd_arr[i].irqn0);
- NVIC_EnableIRQ(nu_canfd_arr[i].irqn1);
- }
- return (int)ret;
- }
- INIT_DEVICE_EXPORT(rt_hw_canfd_init);
- #endif //#if defined(BSP_USING_CANFD)
|