Skip to content

Commit 8502c74

Browse files
authored
Merge pull request #15509 from OpenNuvoton/nuvoton_fix_can_interrupt
NUVOTON: CAN: Fix Rx interrupt and filter mask
2 parents 7ae592d + c1c9550 commit 8502c74

File tree

9 files changed

+175
-41
lines changed

9 files changed

+175
-41
lines changed

targets/TARGET_NUVOTON/TARGET_M451/can_api.c

+32-8
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,25 @@
2727
#include "nu_miscutil.h"
2828
#include "nu_bitutil.h"
2929
#include "mbed_critical.h"
30+
#include "mbed_error.h"
3031

3132
#define NU_CAN_DEBUG 0
3233
#define CAN_NUM 1
3334

35+
/* Reserve Message Object number 31 for Tx */
36+
#define NU_CAN_MSG_OBJ_NUM_TX 31
37+
38+
/* Max number of message ID filter handle */
39+
#define NU_CAN_MAXNUM_HNDL NU_CAN_MSG_OBJ_NUM_TX
40+
41+
/* Convert to string literal */
42+
#define NU_STR_(X) #X
43+
#define NU_STR(X) NU_STR_(X)
44+
3445
static uintptr_t can_irq_contexts[CAN_NUM] = {0};
3546
static can_irq_handler can0_irq_handler;
3647

48+
extern void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum);
3749

3850
static const struct nu_modinit_s can_modinit_tab[] = {
3951
{CAN_0, CAN0_MODULE, 0, 0, CAN0_RST, CAN0_IRQn, NULL},
@@ -125,12 +137,10 @@ static void can_irq(CANName name, int id)
125137
/**************************/
126138
if(can->STATUS & CAN_STATUS_RXOK_Msk) {
127139
can->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/
128-
can0_irq_handler(can_irq_contexts[id], IRQ_RX);
129140
}
130141

131142
if(can->STATUS & CAN_STATUS_TXOK_Msk) {
132143
can->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/
133-
can0_irq_handler(can_irq_contexts[id], IRQ_TX);
134144
}
135145

136146
/**************************/
@@ -143,6 +153,14 @@ static void can_irq(CANName name, int id)
143153
if(can->STATUS & CAN_STATUS_BOFF_Msk) {
144154
can0_irq_handler(can_irq_contexts[id], IRQ_BUS);
145155
}
156+
} else if (u8IIDRstatus >= 1 && u8IIDRstatus <= 32) {
157+
if ((u8IIDRstatus - 1) != NU_CAN_MSG_OBJ_NUM_TX) {
158+
can0_irq_handler(can_irq_contexts[id], IRQ_RX);
159+
CAN_CLR_INT_PENDING_ONLY_BIT(can, (u8IIDRstatus -1));
160+
} else {
161+
can0_irq_handler(can_irq_contexts[id], IRQ_TX);
162+
CAN_CLR_INT_PENDING_BIT(can, (u8IIDRstatus -1));
163+
}
146164
} else if (u8IIDRstatus!=0) {
147165

148166
can0_irq_handler(can_irq_contexts[id], IRQ_OVERRUN);
@@ -213,6 +231,9 @@ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable)
213231

214232
int can_write(can_t *obj, CAN_Message msg, int cc)
215233
{
234+
/* Unused */
235+
(void) cc;
236+
216237
STR_CANMSG_T CMsg;
217238

218239
CMsg.IdType = (uint32_t)msg.format;
@@ -221,7 +242,7 @@ int can_write(can_t *obj, CAN_Message msg, int cc)
221242
CMsg.DLC = msg.len;
222243
memcpy((void *)&CMsg.Data[0],(const void *)&msg.data[0], (unsigned int)8);
223244

224-
return CAN_Transmit((CAN_T *)NU_MODBASE(obj->can), cc, &CMsg);
245+
return CAN_Transmit((CAN_T *)NU_MODBASE(obj->can), NU_CAN_MSG_OBJ_NUM_TX, &CMsg);
225246
}
226247

227248
int can_read(can_t *obj, CAN_Message *msg, int handle)
@@ -285,16 +306,19 @@ int can_mode(can_t *obj, CanMode mode)
285306

286307
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle)
287308
{
288-
uint32_t numask = mask;
289-
if( numask == 0x0000 )
290-
{
291-
return CAN_SetRxMsg((CAN_T *)NU_MODBASE(obj->can), handle, (uint32_t)format, id);
309+
/* Check validity of filter handle */
310+
if (handle < 0 || handle >= NU_CAN_MAXNUM_HNDL) {
311+
/* NOTE: 0 is ambiguous, error or filter handle 0. */
312+
error("Support max " NU_STR(NU_CAN_MAXNUM_HNDL) " CAN filters");
313+
return 0;
292314
}
315+
316+
uint32_t numask = mask;
293317
if( format == CANStandard )
294318
{
295319
numask = (mask << 18);
296320
}
297-
numask = (numask | CAN_IF_MASK2_MDIR_Msk | CAN_IF_MASK2_MXTD_Msk);
321+
numask = (numask | ((CAN_IF_MASK2_MDIR_Msk | CAN_IF_MASK2_MXTD_Msk) << 16));
298322
return CAN_SetRxMsgAndMsk((CAN_T *)NU_MODBASE(obj->can), handle, (uint32_t)format, id, numask);
299323
}
300324

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

+14-1
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

+1-1
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

+43-17
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,21 @@
3030
#include "nu_miscutil.h"
3131
#include "nu_bitutil.h"
3232
#include "mbed_critical.h"
33+
#include "mbed_error.h"
3334

3435
#define NU_CAN_DEBUG 0
3536
#define CAN_NUM 2
3637

38+
/* Reserve Message Object number 31 for Tx */
39+
#define NU_CAN_MSG_OBJ_NUM_TX 31
40+
41+
/* Max number of message ID filter handle */
42+
#define NU_CAN_MAXNUM_HNDL NU_CAN_MSG_OBJ_NUM_TX
43+
44+
/* Convert to string literal */
45+
#define NU_STR_(X) #X
46+
#define NU_STR(X) NU_STR_(X)
47+
3748
static uintptr_t can_irq_contexts[CAN_NUM] = {0};
3849
static can_irq_handler can0_irq_handler;
3950
static can_irq_handler can1_irq_handler;
@@ -43,6 +54,7 @@ extern void CAN_EnterInitMode(CAN_T *tCAN, uint8_t u8Mask);
4354
extern void CAN_LeaveInitMode(CAN_T *tCAN);
4455
extern void CAN_LeaveTestMode(CAN_T *tCAN);
4556
extern void CAN_EnterTestMode(CAN_T *tCAN, uint8_t u8TestMask);
57+
extern void CAN_CLR_INT_PENDING_ONLY_BIT(CAN_T *tCAN, uint32_t u32MsgNum);
4658

4759
static const struct nu_modinit_s can_modinit_tab[] = {
4860
{CAN_0, CAN0_MODULE, 0, 0, CAN0_RST, CAN0_IRQn, NULL},
@@ -139,19 +151,10 @@ static void can_irq(CANName name, int id)
139151
/**************************/
140152
if(can->STATUS & CAN_STATUS_RXOK_Msk) {
141153
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);
146154
}
147155

148156
if(can->STATUS & CAN_STATUS_TXOK_Msk) {
149157
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-
155158
}
156159

157160
/**************************/
@@ -170,6 +173,24 @@ static void can_irq(CANName name, int id)
170173
else
171174
can0_irq_handler(can_irq_contexts[id], IRQ_BUS);
172175
}
176+
} else if (u8IIDRstatus >= 1 && u8IIDRstatus <= 32) {
177+
if ((u8IIDRstatus - 1) != NU_CAN_MSG_OBJ_NUM_TX) {
178+
if (id) {
179+
can1_irq_handler(can_irq_contexts[id], IRQ_RX);
180+
}
181+
else {
182+
can0_irq_handler(can_irq_contexts[id], IRQ_RX);
183+
}
184+
CAN_CLR_INT_PENDING_ONLY_BIT(can, (u8IIDRstatus -1));
185+
} else {
186+
if (id) {
187+
can1_irq_handler(can_irq_contexts[id], IRQ_TX);
188+
}
189+
else {
190+
can0_irq_handler(can_irq_contexts[id], IRQ_TX);
191+
}
192+
CAN_CLR_INT_PENDING_BIT(can, (u8IIDRstatus -1));
193+
}
173194
} else if (u8IIDRstatus!=0) {
174195

175196
if(id)
@@ -178,7 +199,6 @@ static void can_irq(CANName name, int id)
178199
can0_irq_handler(can_irq_contexts[id], IRQ_OVERRUN);
179200

180201
CAN_CLR_INT_PENDING_BIT(can, ((can->IIDR) -1)); /* Clear Interrupt Pending */
181-
182202
} else if(can->WU_STATUS == 1) {
183203

184204
can->WU_STATUS = 0; /* Write '0' to clear */
@@ -263,6 +283,9 @@ void can_irq_set(can_t *obj, CanIrqType irq, uint32_t enable)
263283

264284
int can_write(can_t *obj, CAN_Message msg, int cc)
265285
{
286+
/* Unused */
287+
(void) cc;
288+
266289
STR_CANMSG_T CMsg;
267290

268291
CMsg.IdType = (uint32_t)msg.format;
@@ -271,7 +294,7 @@ int can_write(can_t *obj, CAN_Message msg, int cc)
271294
CMsg.DLC = msg.len;
272295
memcpy((void *)&CMsg.Data[0],(const void *)&msg.data[0], (unsigned int)8);
273296

274-
return CAN_Transmit((CAN_T *)(NU_MODBASE(obj->can)), cc, &CMsg);
297+
return CAN_Transmit((CAN_T *)(NU_MODBASE(obj->can)), NU_CAN_MSG_OBJ_NUM_TX, &CMsg);
275298
}
276299

277300
int can_read(can_t *obj, CAN_Message *msg, int handle)
@@ -293,6 +316,7 @@ int can_read(can_t *obj, CAN_Message *msg, int handle)
293316
int can_mode(can_t *obj, CanMode mode)
294317
{
295318
int success = 0;
319+
296320
switch (mode) {
297321
case MODE_RESET:
298322
CAN_LeaveTestMode((CAN_T*)NU_MODBASE(obj->can));
@@ -326,22 +350,24 @@ int can_mode(can_t *obj, CanMode mode)
326350

327351
}
328352

329-
330353
return success;
331354
}
332355

333356
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle)
334357
{
335-
uint32_t numask = mask;
336-
if( numask == 0x0000 )
337-
{
338-
return CAN_SetRxMsg((CAN_T *)NU_MODBASE(obj->can), handle, (uint32_t)format, id);
358+
/* Check validity of filter handle */
359+
if (handle < 0 || handle >= NU_CAN_MAXNUM_HNDL) {
360+
/* NOTE: 0 is ambiguous, error or filter handle 0. */
361+
error("Support max " NU_STR(NU_CAN_MAXNUM_HNDL) " CAN filters");
362+
return 0;
339363
}
364+
365+
uint32_t numask = mask;
340366
if( format == CANStandard )
341367
{
342368
numask = (mask << 18);
343369
}
344-
numask = (numask | CAN_IF_MASK2_MDIR_Msk | CAN_IF_MASK2_MXTD_Msk);
370+
numask = (numask | ((CAN_IF_MASK2_MDIR_Msk | CAN_IF_MASK2_MXTD_Msk) << 16));
345371
return CAN_SetRxMsgAndMsk((CAN_T *)NU_MODBASE(obj->can), handle, (uint32_t)format, id, numask);
346372
}
347373

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

+1-1
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

+19-1
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

0 commit comments

Comments
 (0)