From 989a694c5a1eeab76d9582beb2fcb90a96dc1f55 Mon Sep 17 00:00:00 2001 From: Chun-Chieh Li Date: Fri, 12 Apr 2024 13:41:20 +0800 Subject: [PATCH] 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 42d2975b2d..5c4e0f34bc 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 d16e3ef15b..4312ff1205 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 c940848964..3a258a9843 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); }