From 63bdb26915eb9a253fb774f863073adf09e12c1d Mon Sep 17 00:00:00 2001 From: Chun-Chieh Li Date: Wed, 10 Apr 2024 14:13:29 +0800 Subject: [PATCH 1/4] NUVOTON: CAN: Fix filter mask NOTE: This fix only targets CAN (M453/M487), not CAN-FD (M467). NOTE: NUC472 CAN doesn't support filter. --- targets/TARGET_NUVOTON/TARGET_M451/can_api.c | 2 +- targets/TARGET_NUVOTON/TARGET_M480/can_api.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/TARGET_NUVOTON/TARGET_M451/can_api.c b/targets/TARGET_NUVOTON/TARGET_M451/can_api.c index fa2e7c2e21e..678de11109d 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/can_api.c @@ -294,7 +294,7 @@ int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t { numask = (mask << 18); } - numask = (numask | CAN_IF_MASK2_MDIR_Msk | CAN_IF_MASK2_MXTD_Msk); + numask = (numask | ((CAN_IF_MASK2_MDIR_Msk | CAN_IF_MASK2_MXTD_Msk) << 16)); return CAN_SetRxMsgAndMsk((CAN_T *)NU_MODBASE(obj->can), handle, (uint32_t)format, id, numask); } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c index 771cb6d9ff8..00a840b98f0 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c @@ -341,7 +341,7 @@ int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t { numask = (mask << 18); } - numask = (numask | CAN_IF_MASK2_MDIR_Msk | CAN_IF_MASK2_MXTD_Msk); + numask = (numask | ((CAN_IF_MASK2_MDIR_Msk | CAN_IF_MASK2_MXTD_Msk) << 16)); return CAN_SetRxMsgAndMsk((CAN_T *)NU_MODBASE(obj->can), handle, (uint32_t)format, id, numask); } From bfd4ceb20bc7d939b44c9f5331589efcfeb5c1a6 Mon Sep 17 00:00:00 2001 From: Chun-Chieh Li Date: Mon, 8 Apr 2024 11:16:49 +0800 Subject: [PATCH 2/4] NUVOTON: CAN: Fix Rx interrupt doesn't work Major modifications: 1. Handle Rx interrupt based on Message Object interrupt (CAN_IIDR=0x0001~0x0020) instead of CAN_STATUS.RxOK 2. Also handle Tx interrupt following above for consistency Other related modifications: 1. Fix signature type error in CAN_CLR_INT_PENDING_BIT() 2. Add CAN_CLR_INT_PENDING_ONLY_BIT() which doesn't clear NewDat flag so that user can fetch received message in thread context NOTE: This fix only targets CAN (NUC472/M453/M487), not CAN-FD (M467). --- targets/TARGET_NUVOTON/TARGET_M451/can_api.c | 12 +++++-- .../TARGET_M451/device/StdDriver/m451_can.c | 15 ++++++++- .../TARGET_M451/device/StdDriver/m451_can.h | 2 +- targets/TARGET_NUVOTON/TARGET_M480/can_api.c | 31 ++++++++++++------- .../device/StdDriver/inc/m480_can.h | 2 +- .../device/StdDriver/src/m480_can.c | 20 +++++++++++- .../TARGET_NUVOTON/TARGET_NUC472/can_api.c | 29 +++++++++++------ .../device/StdDriver/nuc472_can.c | 24 +++++++++++++- .../device/StdDriver/nuc472_can.h | 2 +- 9 files changed, 109 insertions(+), 28 deletions(-) diff --git a/targets/TARGET_NUVOTON/TARGET_M451/can_api.c b/targets/TARGET_NUVOTON/TARGET_M451/can_api.c index 678de11109d..42d2975b2db 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/can_api.c @@ -34,6 +34,8 @@ static uintptr_t can_irq_contexts[CAN_NUM] = {0}; static can_irq_handler can0_irq_handler; +extern uint32_t CAN_IsNewDataReceived(CAN_T *tCAN, uint8_t u8MsgObj); +extern void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum); static const struct nu_modinit_s can_modinit_tab[] = { {CAN_0, CAN0_MODULE, 0, 0, CAN0_RST, CAN0_IRQn, NULL}, @@ -125,12 +127,10 @@ static void can_irq(CANName name, int id) /**************************/ if(can->STATUS & CAN_STATUS_RXOK_Msk) { can->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ - can0_irq_handler(can_irq_contexts[id], IRQ_RX); } if(can->STATUS & CAN_STATUS_TXOK_Msk) { can->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ - can0_irq_handler(can_irq_contexts[id], IRQ_TX); } /**************************/ @@ -143,6 +143,14 @@ static void can_irq(CANName name, int id) if(can->STATUS & CAN_STATUS_BOFF_Msk) { can0_irq_handler(can_irq_contexts[id], IRQ_BUS); } + } else if (u8IIDRstatus >= 1 && u8IIDRstatus <= 32) { + if (CAN_IsNewDataReceived(can, u8IIDRstatus - 1)) { + can0_irq_handler(can_irq_contexts[id], IRQ_RX); + CAN_CLR_INT_PENDING_ONLY_BIT(can, (u8IIDRstatus -1)); + } else { + can0_irq_handler(can_irq_contexts[id], IRQ_TX); + CAN_CLR_INT_PENDING_BIT(can, (u8IIDRstatus -1)); + } } else if (u8IIDRstatus!=0) { can0_irq_handler(can_irq_contexts[id], IRQ_OVERRUN); diff --git a/targets/TARGET_NUVOTON/TARGET_M451/device/StdDriver/m451_can.c b/targets/TARGET_NUVOTON/TARGET_M451/device/StdDriver/m451_can.c index 7cc61939cf8..8afa0731b2c 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/device/StdDriver/m451_can.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/device/StdDriver/m451_can.c @@ -981,7 +981,7 @@ int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg) * * @details An interrupt remains pending until the application software has cleared it. */ -void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum) +void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum) { uint32_t u32MsgIfNum; @@ -994,6 +994,19 @@ void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum) ReleaseIF(tCAN, u32MsgIfNum); } +/* Clone of CAN_CLR_INT_PENDING_BIT() with NewDat not cleared */ +void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum) +{ + uint32_t u32MsgIfNum; + + if((u32MsgIfNum = LockIF_TL(tCAN)) == 2) + u32MsgIfNum = 0; + + tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_CLRINTPND_Msk; + tCAN->IF[u32MsgIfNum].CREQ = 1 + u32MsgNum; + + ReleaseIF(tCAN, u32MsgIfNum); +} /*@}*/ /* end of group CAN_EXPORTED_FUNCTIONS */ diff --git a/targets/TARGET_NUVOTON/TARGET_M451/device/StdDriver/m451_can.h b/targets/TARGET_NUVOTON/TARGET_M451/device/StdDriver/m451_can.h index d2427af227b..91af3197039 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/device/StdDriver/m451_can.h +++ b/targets/TARGET_NUVOTON/TARGET_M451/device/StdDriver/m451_can.h @@ -148,7 +148,7 @@ typedef struct uint32_t CAN_SetBaudRate(CAN_T *tCAN, uint32_t u32BaudRate); uint32_t CAN_Open(CAN_T *tCAN, uint32_t u32BaudRate, uint32_t u32Mode); void CAN_Close(CAN_T *tCAN); -void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum); +void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum); void CAN_EnableInt(CAN_T *tCAN, uint32_t u32Mask); void CAN_DisableInt(CAN_T *tCAN, uint32_t u32Mask); int32_t CAN_Transmit(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg); diff --git a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c index 00a840b98f0..d16e3ef15bd 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c @@ -43,6 +43,7 @@ extern void CAN_EnterInitMode(CAN_T *tCAN, uint8_t u8Mask); extern void CAN_LeaveInitMode(CAN_T *tCAN); extern void CAN_LeaveTestMode(CAN_T *tCAN); extern void CAN_EnterTestMode(CAN_T *tCAN, uint8_t u8TestMask); +extern void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum); static const struct nu_modinit_s can_modinit_tab[] = { {CAN_0, CAN0_MODULE, 0, 0, CAN0_RST, CAN0_IRQn, NULL}, @@ -139,19 +140,10 @@ static void can_irq(CANName name, int id) /**************************/ if(can->STATUS & CAN_STATUS_RXOK_Msk) { can->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ - if(id) - can1_irq_handler(can_irq_contexts[id], IRQ_RX); - else - can0_irq_handler(can_irq_contexts[id], IRQ_RX); } if(can->STATUS & CAN_STATUS_TXOK_Msk) { can->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ - if(id) - can1_irq_handler(can_irq_contexts[id], IRQ_TX); - else - can0_irq_handler(can_irq_contexts[id], IRQ_TX); - } /**************************/ @@ -170,6 +162,24 @@ static void can_irq(CANName name, int id) else can0_irq_handler(can_irq_contexts[id], IRQ_BUS); } + } else if (u8IIDRstatus >= 1 && u8IIDRstatus <= 32) { + if (CAN_IsNewDataReceived(can, u8IIDRstatus - 1)) { + if (id) { + can1_irq_handler(can_irq_contexts[id], IRQ_RX); + } + else { + can0_irq_handler(can_irq_contexts[id], IRQ_RX); + } + CAN_CLR_INT_PENDING_ONLY_BIT(can, (u8IIDRstatus -1)); + } else { + if (id) { + can1_irq_handler(can_irq_contexts[id], IRQ_TX); + } + else { + can0_irq_handler(can_irq_contexts[id], IRQ_TX); + } + CAN_CLR_INT_PENDING_BIT(can, (u8IIDRstatus -1)); + } } else if (u8IIDRstatus!=0) { if(id) @@ -178,7 +188,6 @@ static void can_irq(CANName name, int id) can0_irq_handler(can_irq_contexts[id], IRQ_OVERRUN); CAN_CLR_INT_PENDING_BIT(can, ((can->IIDR) -1)); /* Clear Interrupt Pending */ - } else if(can->WU_STATUS == 1) { can->WU_STATUS = 0; /* Write '0' to clear */ @@ -293,6 +302,7 @@ int can_read(can_t *obj, CAN_Message *msg, int handle) int can_mode(can_t *obj, CanMode mode) { int success = 0; + switch (mode) { case MODE_RESET: CAN_LeaveTestMode((CAN_T*)NU_MODBASE(obj->can)); @@ -326,7 +336,6 @@ int can_mode(can_t *obj, CanMode mode) } - return success; } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/inc/m480_can.h b/targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/inc/m480_can.h index 0aca5fd8471..552f0a78d17 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/inc/m480_can.h +++ b/targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/inc/m480_can.h @@ -155,7 +155,7 @@ typedef struct uint32_t CAN_SetBaudRate(CAN_T *tCAN, uint32_t u32BaudRate); uint32_t CAN_Open(CAN_T *tCAN, uint32_t u32BaudRate, uint32_t u32Mode); void CAN_Close(CAN_T *tCAN); -void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum); +void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum); void CAN_EnableInt(CAN_T *tCAN, uint32_t u32Mask); void CAN_DisableInt(CAN_T *tCAN, uint32_t u32Mask); int32_t CAN_Transmit(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T* pCanMsg); diff --git a/targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/src/m480_can.c b/targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/src/m480_can.c index f2993436175..3930e570df4 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/src/m480_can.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/src/m480_can.c @@ -1264,7 +1264,7 @@ int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T* pCanMsg) * * @details An interrupt remains pending until the application software has cleared it. */ -void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum) +void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum) { uint32_t u32MsgIfNum; @@ -1282,6 +1282,24 @@ void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum) ReleaseIF(tCAN, u32MsgIfNum); } +/* Clone of CAN_CLR_INT_PENDING_BIT() with NewDat not cleared */ +void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum) +{ + uint32_t u32MsgIfNum; + + if((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul) + { + u32MsgIfNum = 0ul; + } + else + { + } + + tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_CLRINTPND_Msk; + tCAN->IF[u32MsgIfNum].CREQ = 1ul + u32MsgNum; + + ReleaseIF(tCAN, u32MsgIfNum); +} /*@}*/ /* end of group CAN_EXPORTED_FUNCTIONS */ diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c b/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c index 7ea08e771eb..c9408489648 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c @@ -35,6 +35,8 @@ static can_irq_handler can0_irq_handler; static can_irq_handler can1_irq_handler; + extern uint32_t CAN_IsNewDataReceived(CAN_T *tCAN, uint8_t u8MsgObj); + extern void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum); static const struct nu_modinit_s can_modinit_tab[] = { {CAN_0, CAN0_MODULE, 0, 0, CAN0_RST, CAN0_IRQn, NULL}, @@ -133,19 +135,10 @@ static void can_irq(CANName name, int id) /**************************/ if(can->STATUS & CAN_STATUS_RXOK_Msk) { can->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ - if(id) - can1_irq_handler(can_irq_contexts[id] , IRQ_RX); - else - can0_irq_handler(can_irq_contexts[id], IRQ_RX); } if(can->STATUS & CAN_STATUS_TXOK_Msk) { can->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ - if(id) - can1_irq_handler(can_irq_contexts[id] , IRQ_TX); - else - can0_irq_handler(can_irq_contexts[id], IRQ_TX); - } /**************************/ @@ -164,6 +157,24 @@ static void can_irq(CANName name, int id) else can0_irq_handler(can_irq_contexts[id], IRQ_BUS); } + } else if (u8IIDRstatus >= 1 && u8IIDRstatus <= 32) { + if (CAN_IsNewDataReceived(can, u8IIDRstatus - 1)) { + if (id) { + can1_irq_handler(can_irq_contexts[id], IRQ_RX); + } + else { + can0_irq_handler(can_irq_contexts[id], IRQ_RX); + } + CAN_CLR_INT_PENDING_ONLY_BIT(can, (u8IIDRstatus -1)); + } else { + if (id) { + can1_irq_handler(can_irq_contexts[id], IRQ_TX); + } + else { + can0_irq_handler(can_irq_contexts[id], IRQ_TX); + } + CAN_CLR_INT_PENDING_BIT(can, (u8IIDRstatus -1)); + } } else if (u8IIDRstatus!=0) { if(id) diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_can.c b/targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_can.c index 673d8846973..0464aa509e0 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_can.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_can.c @@ -716,7 +716,7 @@ int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg) * @return None * */ -void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum) +void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum) { uint32_t u32MsgIfNum = 0; uint32_t u32IFBusyCount = 0; @@ -738,6 +738,28 @@ void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum) } +/* Clone of CAN_CLR_INT_PENDING_BIT() with NewDat not cleared */ +void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum) +{ + uint32_t u32MsgIfNum = 0; + uint32_t u32IFBusyCount = 0; + + while(u32IFBusyCount < 0x10000000) { + if((tCAN->IF[0].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0) { + u32MsgIfNum = 0; + break; + } else if((tCAN->IF[1].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0) { + u32MsgIfNum = 1; + break; + } + + u32IFBusyCount++; + } + + tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_CLRINTPND_Msk; + tCAN->IF[u32MsgIfNum].CREQ = 1 + u32MsgNum; + +} /*@}*/ /* end of group NUC472_442_CAN_EXPORTED_FUNCTIONS */ diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_can.h b/targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_can.h index 65e63fa7474..3601586a162 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_can.h +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_can.h @@ -143,7 +143,7 @@ uint32_t CAN_SetBaudRate(CAN_T *tCAN, uint32_t u32BaudRate); uint32_t CAN_Open(CAN_T *tCAN, uint32_t u32BaudRate, uint32_t u32Mode); int32_t CAN_Transmit(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg); int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg); -void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum); +void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum); void CAN_EnableInt(CAN_T *tCAN, uint32_t u32Mask); void CAN_DisableInt(CAN_T *tCAN, uint32_t u32Mask); int32_t CAN_SetMultiRxMsg(CAN_T *tCAN, uint32_t u32MsgNum , uint32_t u32MsgCount, uint32_t u32IDType, uint32_t u32ID); From 989a694c5a1eeab76d9582beb2fcb90a96dc1f55 Mon Sep 17 00:00:00 2001 From: Chun-Chieh Li Date: Fri, 12 Apr 2024 13:41:20 +0800 Subject: [PATCH 3/4] NUVOTON: CAN: Fix Message Object number for Tx and recognition of Rx interrupt 1. The same Message Object number cannot use for both Tx and Rx simultaneously. For Tx, Message Object number 31 is reserved instead of 0. For Rx, Message Object numbers 0~30 are used and for filters. 2. NewDat bit (CAN_IsNewDataReceived()) isn't exclusive to Rx. Recognize Rx interrupt by Message Object number other than 31. NOTE: This fix only targets CAN (NUC472/M453/M487), not CAN-FD (M467). --- targets/TARGET_NUVOTON/TARGET_M451/can_api.c | 26 ++++++++++++++++--- targets/TARGET_NUVOTON/TARGET_M480/can_api.c | 25 ++++++++++++++++-- .../TARGET_NUVOTON/TARGET_NUC472/can_api.c | 26 ++++++++++++++++--- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/targets/TARGET_NUVOTON/TARGET_M451/can_api.c b/targets/TARGET_NUVOTON/TARGET_M451/can_api.c index 42d2975b2db..5c4e0f34bc8 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/can_api.c @@ -27,14 +27,24 @@ #include "nu_miscutil.h" #include "nu_bitutil.h" #include "mbed_critical.h" + #include "mbed_error.h" #define NU_CAN_DEBUG 0 #define CAN_NUM 1 + /* Reserve Message Object number 31 for Tx */ +#define NU_CAN_MSG_OBJ_NUM_TX 31 + +/* Max number of message ID filter handle */ +#define NU_CAN_MAXNUM_HNDL NU_CAN_MSG_OBJ_NUM_TX + +/* Convert to string literal */ +#define NU_STR_(X) #X +#define NU_STR(X) NU_STR_(X) + static uintptr_t can_irq_contexts[CAN_NUM] = {0}; static can_irq_handler can0_irq_handler; -extern uint32_t CAN_IsNewDataReceived(CAN_T *tCAN, uint8_t u8MsgObj); extern void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum); static const struct nu_modinit_s can_modinit_tab[] = { @@ -144,7 +154,7 @@ static void can_irq(CANName name, int id) can0_irq_handler(can_irq_contexts[id], IRQ_BUS); } } else if (u8IIDRstatus >= 1 && u8IIDRstatus <= 32) { - if (CAN_IsNewDataReceived(can, u8IIDRstatus - 1)) { + if ((u8IIDRstatus - 1) != NU_CAN_MSG_OBJ_NUM_TX) { can0_irq_handler(can_irq_contexts[id], IRQ_RX); CAN_CLR_INT_PENDING_ONLY_BIT(can, (u8IIDRstatus -1)); } else { @@ -221,6 +231,9 @@ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable) int can_write(can_t *obj, CAN_Message msg, int cc) { + /* Unused */ + (void) cc; + STR_CANMSG_T CMsg; CMsg.IdType = (uint32_t)msg.format; @@ -229,7 +242,7 @@ int can_write(can_t *obj, CAN_Message msg, int cc) CMsg.DLC = msg.len; memcpy((void *)&CMsg.Data[0],(const void *)&msg.data[0], (unsigned int)8); - return CAN_Transmit((CAN_T *)NU_MODBASE(obj->can), cc, &CMsg); + return CAN_Transmit((CAN_T *)NU_MODBASE(obj->can), NU_CAN_MSG_OBJ_NUM_TX, &CMsg); } int can_read(can_t *obj, CAN_Message *msg, int handle) @@ -293,6 +306,13 @@ int can_mode(can_t *obj, CanMode mode) int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) { + /* Check validity of filter handle */ + if (handle < 0 || handle >= NU_CAN_MAXNUM_HNDL) { + /* NOTE: 0 is ambiguous, error or filter handle 0. */ + error("Support max " NU_STR(NU_CAN_MAXNUM_HNDL) " CAN filters"); + return 0; + } + uint32_t numask = mask; if( numask == 0x0000 ) { diff --git a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c index d16e3ef15bd..4312ff12053 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c @@ -30,10 +30,21 @@ #include "nu_miscutil.h" #include "nu_bitutil.h" #include "mbed_critical.h" +#include "mbed_error.h" #define NU_CAN_DEBUG 0 #define CAN_NUM 2 +/* Reserve Message Object number 31 for Tx */ +#define NU_CAN_MSG_OBJ_NUM_TX 31 + +/* Max number of message ID filter handle */ +#define NU_CAN_MAXNUM_HNDL NU_CAN_MSG_OBJ_NUM_TX + +/* Convert to string literal */ +#define NU_STR_(X) #X +#define NU_STR(X) NU_STR_(X) + static uintptr_t can_irq_contexts[CAN_NUM] = {0}; static can_irq_handler can0_irq_handler; static can_irq_handler can1_irq_handler; @@ -163,7 +174,7 @@ static void can_irq(CANName name, int id) can0_irq_handler(can_irq_contexts[id], IRQ_BUS); } } else if (u8IIDRstatus >= 1 && u8IIDRstatus <= 32) { - if (CAN_IsNewDataReceived(can, u8IIDRstatus - 1)) { + if ((u8IIDRstatus - 1) != NU_CAN_MSG_OBJ_NUM_TX) { if (id) { can1_irq_handler(can_irq_contexts[id], IRQ_RX); } @@ -272,6 +283,9 @@ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable) int can_write(can_t *obj, CAN_Message msg, int cc) { + /* Unused */ + (void) cc; + STR_CANMSG_T CMsg; CMsg.IdType = (uint32_t)msg.format; @@ -280,7 +294,7 @@ int can_write(can_t *obj, CAN_Message msg, int cc) CMsg.DLC = msg.len; memcpy((void *)&CMsg.Data[0],(const void *)&msg.data[0], (unsigned int)8); - return CAN_Transmit((CAN_T *)(NU_MODBASE(obj->can)), cc, &CMsg); + return CAN_Transmit((CAN_T *)(NU_MODBASE(obj->can)), NU_CAN_MSG_OBJ_NUM_TX, &CMsg); } int can_read(can_t *obj, CAN_Message *msg, int handle) @@ -341,6 +355,13 @@ int can_mode(can_t *obj, CanMode mode) int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) { + /* Check validity of filter handle */ + if (handle < 0 || handle >= NU_CAN_MAXNUM_HNDL) { + /* NOTE: 0 is ambiguous, error or filter handle 0. */ + error("Support max " NU_STR(NU_CAN_MAXNUM_HNDL) " CAN filters"); + return 0; + } + uint32_t numask = mask; if( numask == 0x0000 ) { diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c b/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c index c9408489648..3a258a98435 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c @@ -27,15 +27,25 @@ #include "nu_miscutil.h" #include "nu_bitutil.h" #include "mbed_critical.h" + #include "mbed_error.h" #define NU_CAN_DEBUG 0 #define CAN_NUM 2 + /* Reserve Message Object number 31 for Tx */ +#define NU_CAN_MSG_OBJ_NUM_TX 31 + +/* Convert to string literal */ +#define NU_STR_(X) #X +#define NU_STR(X) NU_STR_(X) + +/* Max number of message ID filter handle */ +#define NU_CAN_MAXNUM_HNDL NU_CAN_MSG_OBJ_NUM_TX + static uintptr_t can_irq_contexts[CAN_NUM] = {0}; static can_irq_handler can0_irq_handler; static can_irq_handler can1_irq_handler; - extern uint32_t CAN_IsNewDataReceived(CAN_T *tCAN, uint8_t u8MsgObj); extern void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum); static const struct nu_modinit_s can_modinit_tab[] = { @@ -158,7 +168,7 @@ static void can_irq(CANName name, int id) can0_irq_handler(can_irq_contexts[id], IRQ_BUS); } } else if (u8IIDRstatus >= 1 && u8IIDRstatus <= 32) { - if (CAN_IsNewDataReceived(can, u8IIDRstatus - 1)) { + if ((u8IIDRstatus - 1) != NU_CAN_MSG_OBJ_NUM_TX) { if (id) { can1_irq_handler(can_irq_contexts[id], IRQ_RX); } @@ -274,6 +284,9 @@ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable) int can_write(can_t *obj, CAN_Message msg, int cc) { + /* Unused */ + (void) cc; + STR_CANMSG_T CMsg; CMsg.IdType = (uint32_t)msg.format; @@ -282,7 +295,7 @@ int can_write(can_t *obj, CAN_Message msg, int cc) CMsg.DLC = msg.len; memcpy((void *)&CMsg.Data[0],(const void *)&msg.data[0], (unsigned int)8); - return CAN_Transmit((CAN_T *)NU_MODBASE(obj->can), cc, &CMsg); + return CAN_Transmit((CAN_T *)NU_MODBASE(obj->can), NU_CAN_MSG_OBJ_NUM_TX, &CMsg); } int can_read(can_t *obj, CAN_Message *msg, int handle) @@ -346,6 +359,13 @@ int can_mode(can_t *obj, CanMode mode) int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) { + /* Check validity of filter handle */ + if (handle < 0 || handle >= NU_CAN_MAXNUM_HNDL) { + /* NOTE: 0 is ambiguous, error or filter handle 0. */ + error("Support max " NU_STR(NU_CAN_MAXNUM_HNDL) " CAN filters"); + return 0; + } + return CAN_SetRxMsg((CAN_T *)NU_MODBASE(obj->can), handle , (uint32_t)format, id); } From c1c9550539507b717e356727b204146fbaed882d Mon Sep 17 00:00:00 2001 From: Chun-Chieh Li Date: Thu, 18 Apr 2024 13:29:24 +0800 Subject: [PATCH 4/4] NUVOTON: CAN: Fix filter mask being zero On mask being zero, it means any match, not exact match. NOTE: This fix only targets CAN (M453/M487), not CAN-FD (M467). NOTE: NUC472 CAN doesn't support filter. --- targets/TARGET_NUVOTON/TARGET_M451/can_api.c | 4 ---- targets/TARGET_NUVOTON/TARGET_M480/can_api.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/targets/TARGET_NUVOTON/TARGET_M451/can_api.c b/targets/TARGET_NUVOTON/TARGET_M451/can_api.c index 5c4e0f34bc8..d8254406de8 100644 --- a/targets/TARGET_NUVOTON/TARGET_M451/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M451/can_api.c @@ -314,10 +314,6 @@ int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t } uint32_t numask = mask; - if( numask == 0x0000 ) - { - return CAN_SetRxMsg((CAN_T *)NU_MODBASE(obj->can), handle, (uint32_t)format, id); - } if( format == CANStandard ) { numask = (mask << 18); diff --git a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c index 4312ff12053..c4910180c5e 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/can_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/can_api.c @@ -363,10 +363,6 @@ int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t } uint32_t numask = mask; - if( numask == 0x0000 ) - { - return CAN_SetRxMsg((CAN_T *)NU_MODBASE(obj->can), handle, (uint32_t)format, id); - } if( format == CANStandard ) { numask = (mask << 18);