Skip to content

Commit bfd4ceb

Browse files
committed
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).
1 parent 63bdb26 commit bfd4ceb

File tree

9 files changed

+109
-28
lines changed

9 files changed

+109
-28
lines changed

targets/TARGET_NUVOTON/TARGET_M451/can_api.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
static uintptr_t can_irq_contexts[CAN_NUM] = {0};
3535
static can_irq_handler can0_irq_handler;
3636

37+
extern uint32_t CAN_IsNewDataReceived(CAN_T *tCAN, uint8_t u8MsgObj);
38+
extern void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum);
3739

3840
static const struct nu_modinit_s can_modinit_tab[] = {
3941
{CAN_0, CAN0_MODULE, 0, 0, CAN0_RST, CAN0_IRQn, NULL},
@@ -125,12 +127,10 @@ static void can_irq(CANName name, int id)
125127
/**************************/
126128
if(can->STATUS & CAN_STATUS_RXOK_Msk) {
127129
can->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/
128-
can0_irq_handler(can_irq_contexts[id], IRQ_RX);
129130
}
130131

131132
if(can->STATUS & CAN_STATUS_TXOK_Msk) {
132133
can->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/
133-
can0_irq_handler(can_irq_contexts[id], IRQ_TX);
134134
}
135135

136136
/**************************/
@@ -143,6 +143,14 @@ static void can_irq(CANName name, int id)
143143
if(can->STATUS & CAN_STATUS_BOFF_Msk) {
144144
can0_irq_handler(can_irq_contexts[id], IRQ_BUS);
145145
}
146+
} else if (u8IIDRstatus >= 1 && u8IIDRstatus <= 32) {
147+
if (CAN_IsNewDataReceived(can, u8IIDRstatus - 1)) {
148+
can0_irq_handler(can_irq_contexts[id], IRQ_RX);
149+
CAN_CLR_INT_PENDING_ONLY_BIT(can, (u8IIDRstatus -1));
150+
} else {
151+
can0_irq_handler(can_irq_contexts[id], IRQ_TX);
152+
CAN_CLR_INT_PENDING_BIT(can, (u8IIDRstatus -1));
153+
}
146154
} else if (u8IIDRstatus!=0) {
147155

148156
can0_irq_handler(can_irq_contexts[id], IRQ_OVERRUN);

targets/TARGET_NUVOTON/TARGET_M451/device/StdDriver/m451_can.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,7 @@ int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg)
981981
*
982982
* @details An interrupt remains pending until the application software has cleared it.
983983
*/
984-
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum)
984+
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum)
985985
{
986986
uint32_t u32MsgIfNum;
987987

@@ -994,6 +994,19 @@ void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum)
994994
ReleaseIF(tCAN, u32MsgIfNum);
995995
}
996996

997+
/* Clone of CAN_CLR_INT_PENDING_BIT() with NewDat not cleared */
998+
void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum)
999+
{
1000+
uint32_t u32MsgIfNum;
1001+
1002+
if((u32MsgIfNum = LockIF_TL(tCAN)) == 2)
1003+
u32MsgIfNum = 0;
1004+
1005+
tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_CLRINTPND_Msk;
1006+
tCAN->IF[u32MsgIfNum].CREQ = 1 + u32MsgNum;
1007+
1008+
ReleaseIF(tCAN, u32MsgIfNum);
1009+
}
9971010

9981011
/*@}*/ /* end of group CAN_EXPORTED_FUNCTIONS */
9991012

targets/TARGET_NUVOTON/TARGET_M451/device/StdDriver/m451_can.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ typedef struct
148148
uint32_t CAN_SetBaudRate(CAN_T *tCAN, uint32_t u32BaudRate);
149149
uint32_t CAN_Open(CAN_T *tCAN, uint32_t u32BaudRate, uint32_t u32Mode);
150150
void CAN_Close(CAN_T *tCAN);
151-
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum);
151+
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum);
152152
void CAN_EnableInt(CAN_T *tCAN, uint32_t u32Mask);
153153
void CAN_DisableInt(CAN_T *tCAN, uint32_t u32Mask);
154154
int32_t CAN_Transmit(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg);

targets/TARGET_NUVOTON/TARGET_M480/can_api.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ extern void CAN_EnterInitMode(CAN_T *tCAN, uint8_t u8Mask);
4343
extern void CAN_LeaveInitMode(CAN_T *tCAN);
4444
extern void CAN_LeaveTestMode(CAN_T *tCAN);
4545
extern void CAN_EnterTestMode(CAN_T *tCAN, uint8_t u8TestMask);
46+
extern void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum);
4647

4748
static const struct nu_modinit_s can_modinit_tab[] = {
4849
{CAN_0, CAN0_MODULE, 0, 0, CAN0_RST, CAN0_IRQn, NULL},
@@ -139,19 +140,10 @@ static void can_irq(CANName name, int id)
139140
/**************************/
140141
if(can->STATUS & CAN_STATUS_RXOK_Msk) {
141142
can->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/
142-
if(id)
143-
can1_irq_handler(can_irq_contexts[id], IRQ_RX);
144-
else
145-
can0_irq_handler(can_irq_contexts[id], IRQ_RX);
146143
}
147144

148145
if(can->STATUS & CAN_STATUS_TXOK_Msk) {
149146
can->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/
150-
if(id)
151-
can1_irq_handler(can_irq_contexts[id], IRQ_TX);
152-
else
153-
can0_irq_handler(can_irq_contexts[id], IRQ_TX);
154-
155147
}
156148

157149
/**************************/
@@ -170,6 +162,24 @@ static void can_irq(CANName name, int id)
170162
else
171163
can0_irq_handler(can_irq_contexts[id], IRQ_BUS);
172164
}
165+
} else if (u8IIDRstatus >= 1 && u8IIDRstatus <= 32) {
166+
if (CAN_IsNewDataReceived(can, u8IIDRstatus - 1)) {
167+
if (id) {
168+
can1_irq_handler(can_irq_contexts[id], IRQ_RX);
169+
}
170+
else {
171+
can0_irq_handler(can_irq_contexts[id], IRQ_RX);
172+
}
173+
CAN_CLR_INT_PENDING_ONLY_BIT(can, (u8IIDRstatus -1));
174+
} else {
175+
if (id) {
176+
can1_irq_handler(can_irq_contexts[id], IRQ_TX);
177+
}
178+
else {
179+
can0_irq_handler(can_irq_contexts[id], IRQ_TX);
180+
}
181+
CAN_CLR_INT_PENDING_BIT(can, (u8IIDRstatus -1));
182+
}
173183
} else if (u8IIDRstatus!=0) {
174184

175185
if(id)
@@ -178,7 +188,6 @@ static void can_irq(CANName name, int id)
178188
can0_irq_handler(can_irq_contexts[id], IRQ_OVERRUN);
179189

180190
CAN_CLR_INT_PENDING_BIT(can, ((can->IIDR) -1)); /* Clear Interrupt Pending */
181-
182191
} else if(can->WU_STATUS == 1) {
183192

184193
can->WU_STATUS = 0; /* Write '0' to clear */
@@ -293,6 +302,7 @@ int can_read(can_t *obj, CAN_Message *msg, int handle)
293302
int can_mode(can_t *obj, CanMode mode)
294303
{
295304
int success = 0;
305+
296306
switch (mode) {
297307
case MODE_RESET:
298308
CAN_LeaveTestMode((CAN_T*)NU_MODBASE(obj->can));
@@ -326,7 +336,6 @@ int can_mode(can_t *obj, CanMode mode)
326336

327337
}
328338

329-
330339
return success;
331340
}
332341

targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/inc/m480_can.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ typedef struct
155155
uint32_t CAN_SetBaudRate(CAN_T *tCAN, uint32_t u32BaudRate);
156156
uint32_t CAN_Open(CAN_T *tCAN, uint32_t u32BaudRate, uint32_t u32Mode);
157157
void CAN_Close(CAN_T *tCAN);
158-
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum);
158+
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum);
159159
void CAN_EnableInt(CAN_T *tCAN, uint32_t u32Mask);
160160
void CAN_DisableInt(CAN_T *tCAN, uint32_t u32Mask);
161161
int32_t CAN_Transmit(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T* pCanMsg);

targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/src/m480_can.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1264,7 +1264,7 @@ int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum, STR_CANMSG_T* pCanMsg)
12641264
*
12651265
* @details An interrupt remains pending until the application software has cleared it.
12661266
*/
1267-
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum)
1267+
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum)
12681268
{
12691269
uint32_t u32MsgIfNum;
12701270

@@ -1282,6 +1282,24 @@ void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum)
12821282
ReleaseIF(tCAN, u32MsgIfNum);
12831283
}
12841284

1285+
/* Clone of CAN_CLR_INT_PENDING_BIT() with NewDat not cleared */
1286+
void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum)
1287+
{
1288+
uint32_t u32MsgIfNum;
1289+
1290+
if((u32MsgIfNum = LockIF_TL(tCAN)) == 2ul)
1291+
{
1292+
u32MsgIfNum = 0ul;
1293+
}
1294+
else
1295+
{
1296+
}
1297+
1298+
tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_CLRINTPND_Msk;
1299+
tCAN->IF[u32MsgIfNum].CREQ = 1ul + u32MsgNum;
1300+
1301+
ReleaseIF(tCAN, u32MsgIfNum);
1302+
}
12851303

12861304
/*@}*/ /* end of group CAN_EXPORTED_FUNCTIONS */
12871305

targets/TARGET_NUVOTON/TARGET_NUC472/can_api.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
static can_irq_handler can0_irq_handler;
3636
static can_irq_handler can1_irq_handler;
3737

38+
extern uint32_t CAN_IsNewDataReceived(CAN_T *tCAN, uint8_t u8MsgObj);
39+
extern void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum);
3840

3941
static const struct nu_modinit_s can_modinit_tab[] = {
4042
{CAN_0, CAN0_MODULE, 0, 0, CAN0_RST, CAN0_IRQn, NULL},
@@ -133,19 +135,10 @@ static void can_irq(CANName name, int id)
133135
/**************************/
134136
if(can->STATUS & CAN_STATUS_RXOK_Msk) {
135137
can->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/
136-
if(id)
137-
can1_irq_handler(can_irq_contexts[id] , IRQ_RX);
138-
else
139-
can0_irq_handler(can_irq_contexts[id], IRQ_RX);
140138
}
141139

142140
if(can->STATUS & CAN_STATUS_TXOK_Msk) {
143141
can->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/
144-
if(id)
145-
can1_irq_handler(can_irq_contexts[id] , IRQ_TX);
146-
else
147-
can0_irq_handler(can_irq_contexts[id], IRQ_TX);
148-
149142
}
150143

151144
/**************************/
@@ -164,6 +157,24 @@ static void can_irq(CANName name, int id)
164157
else
165158
can0_irq_handler(can_irq_contexts[id], IRQ_BUS);
166159
}
160+
} else if (u8IIDRstatus >= 1 && u8IIDRstatus <= 32) {
161+
if (CAN_IsNewDataReceived(can, u8IIDRstatus - 1)) {
162+
if (id) {
163+
can1_irq_handler(can_irq_contexts[id], IRQ_RX);
164+
}
165+
else {
166+
can0_irq_handler(can_irq_contexts[id], IRQ_RX);
167+
}
168+
CAN_CLR_INT_PENDING_ONLY_BIT(can, (u8IIDRstatus -1));
169+
} else {
170+
if (id) {
171+
can1_irq_handler(can_irq_contexts[id], IRQ_TX);
172+
}
173+
else {
174+
can0_irq_handler(can_irq_contexts[id], IRQ_TX);
175+
}
176+
CAN_CLR_INT_PENDING_BIT(can, (u8IIDRstatus -1));
177+
}
167178
} else if (u8IIDRstatus!=0) {
168179

169180
if(id)

targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_can.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg)
716716
* @return None
717717
*
718718
*/
719-
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum)
719+
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum)
720720
{
721721
uint32_t u32MsgIfNum = 0;
722722
uint32_t u32IFBusyCount = 0;
@@ -738,6 +738,28 @@ void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum)
738738

739739
}
740740

741+
/* Clone of CAN_CLR_INT_PENDING_BIT() with NewDat not cleared */
742+
void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum)
743+
{
744+
uint32_t u32MsgIfNum = 0;
745+
uint32_t u32IFBusyCount = 0;
746+
747+
while(u32IFBusyCount < 0x10000000) {
748+
if((tCAN->IF[0].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0) {
749+
u32MsgIfNum = 0;
750+
break;
751+
} else if((tCAN->IF[1].CREQ & CAN_IF_CREQ_BUSY_Msk) == 0) {
752+
u32MsgIfNum = 1;
753+
break;
754+
}
755+
756+
u32IFBusyCount++;
757+
}
758+
759+
tCAN->IF[u32MsgIfNum].CMASK = CAN_IF_CMASK_CLRINTPND_Msk;
760+
tCAN->IF[u32MsgIfNum].CREQ = 1 + u32MsgNum;
761+
762+
}
741763

742764
/*@}*/ /* end of group NUC472_442_CAN_EXPORTED_FUNCTIONS */
743765

targets/TARGET_NUVOTON/TARGET_NUC472/device/StdDriver/nuc472_can.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ uint32_t CAN_SetBaudRate(CAN_T *tCAN, uint32_t u32BaudRate);
143143
uint32_t CAN_Open(CAN_T *tCAN, uint32_t u32BaudRate, uint32_t u32Mode);
144144
int32_t CAN_Transmit(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg);
145145
int32_t CAN_Receive(CAN_T *tCAN, uint32_t u32MsgNum , STR_CANMSG_T* pCanMsg);
146-
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint8_t u32MsgNum);
146+
void CAN_CLR_INT_PENDING_BIT(CAN_T *tCAN, uint32_t u32MsgNum);
147147
void CAN_EnableInt(CAN_T *tCAN, uint32_t u32Mask);
148148
void CAN_DisableInt(CAN_T *tCAN, uint32_t u32Mask);
149149
int32_t CAN_SetMultiRxMsg(CAN_T *tCAN, uint32_t u32MsgNum , uint32_t u32MsgCount, uint32_t u32IDType, uint32_t u32ID);

0 commit comments

Comments
 (0)