Skip to content

Commit 2c45596

Browse files
committed
2 parents 7c8c722 + 48fc1aa commit 2c45596

File tree

8 files changed

+242
-64
lines changed

8 files changed

+242
-64
lines changed

libraries/mbed/api/CAN.h

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -162,31 +162,33 @@ class CAN {
162162
* generated.
163163
*
164164
* @param fptr A pointer to a void function, or 0 to set as none
165+
* @param event Which can interrupt to attach the member function to (CAN::IRQ_RX, CAN::IRQ_TX, CAN::IRQ_ERROR, CAN::IRQ_OVERRUN, CAN::IRQ_WAKEUP, CAN::IRQ_PASSIVE, CAN::IRQ_ARB, CAN::IRQ_BUS, CAN::IRQ_READY) - Note that not every event is supported by all hardware
165166
*/
166-
void attach(void (*fptr)(void));
167+
void attach(void (*fptr)(void), can_irq_event event=IRQ_RX);
167168

168169
/** Attach a member function to call whenever a CAN frame received interrupt
169170
* is generated.
170171
*
171172
* @param tptr pointer to the object to call the member function on
172173
* @param mptr pointer to the member function to be called
174+
* @param event Which can interrupt to attach the member function to (CAN::IRQ_RX, CAN::IRQ_TX, CAN::IRQ_ERROR, CAN::IRQ_OVERRUN, CAN::IRQ_WAKEUP, CAN::IRQ_PASSIVE, CAN::IRQ_ARB, CAN::IRQ_BUS, CAN::IRQ_READY) - Note that not every event is supported by all hardware
173175
*/
174176
template<typename T>
175-
void attach(T* tptr, void (T::*mptr)(void)) {
177+
void attach(T* tptr, void (T::*mptr)(void), can_irq_event event=IRQ_RX) {
176178
if((mptr != NULL) && (tptr != NULL)) {
177-
_rxirq.attach(tptr, mptr);
178-
setup_interrupt();
179-
} else {
180-
remove_interrupt();
179+
_irq[event].attach(tptr, mptr);
180+
can_irq_set(&_can, event, 1);
181+
}
182+
else {
183+
can_irq_set(&_can, event, 0);
181184
}
182185
}
183186

184-
private:
185-
can_t _can;
186-
FunctionPointer _rxirq;
187+
static void _irq_handler(uint32_t id, can_irq_event event);
187188

188-
void setup_interrupt(void);
189-
void remove_interrupt(void);
189+
protected:
190+
can_t _can;
191+
FunctionPointer _irq[9];
190192
};
191193

192194
} // namespace mbed

libraries/mbed/common/CAN.cpp

Lines changed: 11 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ namespace mbed {
2323

2424
CAN::CAN(PinName rd, PinName td) {
2525
can_init(&_can, rd, td);
26+
can_irq_init(&_can, (&CAN::_irq_handler), (uint32_t)this);
2627
}
2728

2829
CAN::~CAN() {
2930
can_free(&_can);
31+
can_irq_free(&_can);
3032
}
3133

3234
int CAN::frequency(int f) {
@@ -57,61 +59,18 @@ void CAN::monitor(bool silent) {
5759
can_monitor(&_can, (silent) ? 1 : 0);
5860
}
5961

60-
static FunctionPointer* can_obj[2] = { NULL };
61-
62-
// Have to check that the CAN block is active before reading the Interrupt
63-
// Control Register, or the mbed hangs
64-
void can_irq(void) {
65-
uint32_t icr;
66-
67-
if(LPC_SC->PCONP & (1 << 13)) {
68-
icr = LPC_CAN1->ICR;
69-
70-
if(icr && (can_obj[0] != NULL)) {
71-
can_obj[0]->call();
72-
}
73-
}
74-
75-
if(LPC_SC->PCONP & (1 << 14)) {
76-
icr = LPC_CAN2->ICR;
77-
if(icr && (can_obj[1] != NULL)) {
78-
can_obj[1]->call();
79-
}
80-
}
81-
82-
}
83-
84-
void CAN::setup_interrupt(void) {
85-
switch ((int)_can.dev) {
86-
case CAN_1: can_obj[0] = &_rxirq; break;
87-
case CAN_2: can_obj[1] = &_rxirq; break;
88-
}
89-
_can.dev->MOD |= 1;
90-
_can.dev->IER |= 1;
91-
_can.dev->MOD &= ~1;
92-
NVIC_SetVector(CAN_IRQn, (uint32_t) &can_irq);
93-
NVIC_EnableIRQ(CAN_IRQn);
94-
}
95-
96-
void CAN::remove_interrupt(void) {
97-
switch ((int)_can.dev) {
98-
case CAN_1: can_obj[0] = NULL; break;
99-
case CAN_2: can_obj[1] = NULL; break;
100-
}
101-
102-
_can.dev->IER &= ~(1);
103-
if ((can_obj[0] == NULL) && (can_obj[1] == NULL)) {
104-
NVIC_DisableIRQ(CAN_IRQn);
62+
void CAN::attach(void (*fptr)(void), can_irq_event event) {
63+
if (fptr) {
64+
_irq[event].attach(fptr);
65+
can_irq_set(&_can, event, 1);
66+
} else {
67+
can_irq_set(&_can, event, 0);
10568
}
10669
}
10770

108-
void CAN::attach(void (*fptr)(void)) {
109-
if (fptr != NULL) {
110-
_rxirq.attach(fptr);
111-
setup_interrupt();
112-
} else {
113-
remove_interrupt();
114-
}
71+
void CAN::_irq_handler(uint32_t id, can_irq_event event) {
72+
CAN *handler = (CAN*)id;
73+
handler->_irq[event].call();
11574
}
11675

11776
} // namespace mbed

libraries/mbed/hal/can_api.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,30 @@
2828
extern "C" {
2929
#endif
3030

31+
typedef enum {
32+
IRQ_RX,
33+
IRQ_TX,
34+
IRQ_ERROR,
35+
IRQ_OVERRUN,
36+
IRQ_WAKEUP,
37+
IRQ_PASSIVE,
38+
IRQ_ARB,
39+
IRQ_BUS,
40+
IRQ_READY
41+
} can_irq_event;
42+
43+
typedef void (*can_irq_handler)(uint32_t id, can_irq_event event);
44+
3145
typedef struct can_s can_t;
3246

3347
void can_init (can_t *obj, PinName rd, PinName td);
3448
void can_free (can_t *obj);
3549
int can_frequency(can_t *obj, int hz);
50+
51+
void can_irq_init (can_t *obj, can_irq_handler handler, uint32_t id);
52+
void can_irq_free (can_t *obj);
53+
void can_irq_set (can_t *obj, can_irq_event irq, uint32_t enable);
54+
3655
int can_write (can_t *obj, CAN_Message, int cc);
3756
int can_read (can_t *obj, CAN_Message *msg);
3857
void can_reset (can_t *obj);

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC176X/can_api.c

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <math.h>
2323
#include <string.h>
2424

25+
#define CAN_NUM 2
26+
2527
/* Acceptance filter mode in AFMR register */
2628
#define ACCF_OFF 0x01
2729
#define ACCF_BYPASS 0x02
@@ -61,6 +63,9 @@ struct CANMsg {
6163
};
6264
typedef struct CANMsg CANMsg;
6365

66+
static uint32_t can_irq_ids[CAN_NUM] = {0};
67+
static can_irq_handler irq_handler;
68+
6469
static uint32_t can_disable(can_t *obj) {
6570
uint32_t sm = obj->dev->MOD;
6671
obj->dev->MOD |= 1;
@@ -73,6 +78,96 @@ static inline void can_enable(can_t *obj) {
7378
}
7479
}
7580

81+
static inline void can_irq(uint32_t icr, uint32_t index) {
82+
uint32_t i;
83+
84+
for(i = 0; i < 8; i++)
85+
{
86+
if((can_irq_ids[index] != 0) && (icr & (1 << i)))
87+
{
88+
switch (i) {
89+
case 0: irq_handler(can_irq_ids[index], IRQ_RX); break;
90+
case 1: irq_handler(can_irq_ids[index], IRQ_TX); break;
91+
case 2: irq_handler(can_irq_ids[index], IRQ_ERROR); break;
92+
case 3: irq_handler(can_irq_ids[index], IRQ_OVERRUN); break;
93+
case 4: irq_handler(can_irq_ids[index], IRQ_WAKEUP); break;
94+
case 5: irq_handler(can_irq_ids[index], IRQ_PASSIVE); break;
95+
case 6: irq_handler(can_irq_ids[index], IRQ_ARB); break;
96+
case 7: irq_handler(can_irq_ids[index], IRQ_BUS); break;
97+
case 8: irq_handler(can_irq_ids[index], IRQ_READY); break;
98+
}
99+
}
100+
}
101+
}
102+
103+
// Have to check that the CAN block is active before reading the Interrupt
104+
// Control Register, or the mbed hangs
105+
void can_irq_n() {
106+
uint32_t icr;
107+
108+
if(LPC_SC->PCONP & (1 << 13)) {
109+
icr = LPC_CAN1->ICR & 0x1FF;
110+
can_irq(icr, 0);
111+
}
112+
113+
if(LPC_SC->PCONP & (1 << 14)) {
114+
icr = LPC_CAN2->ICR & 0x1FF;
115+
can_irq(icr, 1);
116+
}
117+
}
118+
119+
// Register CAN object's irq handler
120+
void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) {
121+
irq_handler = handler;
122+
can_irq_ids[obj->index] = id;
123+
}
124+
125+
// Unregister CAN object's irq handler
126+
void can_irq_free(can_t *obj) {
127+
obj->dev->IER &= ~(1);
128+
can_irq_ids[obj->index] = 0;
129+
130+
if ((can_irq_ids[0] == 0) && (can_irq_ids[1] == 0)) {
131+
NVIC_DisableIRQ(CAN_IRQn);
132+
}
133+
}
134+
135+
// Clear or set a irq
136+
void can_irq_set(can_t *obj, can_irq_event event, uint32_t enable) {
137+
uint32_t ier;
138+
139+
switch (event) {
140+
case IRQ_RX: ier = (1 << 0); break;
141+
case IRQ_TX: ier = (1 << 1); break;
142+
case IRQ_ERROR: ier = (1 << 2); break;
143+
case IRQ_OVERRUN: ier = (1 << 3); break;
144+
case IRQ_WAKEUP: ier = (1 << 4); break;
145+
case IRQ_PASSIVE: ier = (1 << 5); break;
146+
case IRQ_ARB: ier = (1 << 6); break;
147+
case IRQ_BUS: ier = (1 << 7); break;
148+
case IRQ_READY: ier = (1 << 8); break;
149+
default: return;
150+
}
151+
152+
obj->dev->MOD |= 1;
153+
if(enable == 0) {
154+
obj->dev->IER &= ~ier;
155+
}
156+
else {
157+
obj->dev->IER |= ier;
158+
}
159+
obj->dev->MOD &= ~(1);
160+
161+
// Enable NVIC if at least 1 interrupt is active
162+
if(LPC_CAN1->IER | LPC_CAN2->IER != 0) {
163+
NVIC_SetVector(CAN_IRQn, (uint32_t) &can_irq_n);
164+
NVIC_EnableIRQ(CAN_IRQn);
165+
}
166+
else {
167+
NVIC_DisableIRQ(CAN_IRQn);
168+
}
169+
}
170+
76171
static int can_pclk(can_t *obj) {
77172
int value = 0;
78173
switch ((int)obj->dev) {
@@ -166,7 +261,12 @@ void can_init(can_t *obj, PinName rd, PinName td) {
166261

167262
pinmap_pinout(rd, PinMap_CAN_RD);
168263
pinmap_pinout(td, PinMap_CAN_TD);
169-
264+
265+
switch ((int)obj->dev) {
266+
case CAN_1: obj->index = 0; break;
267+
case CAN_2: obj->index = 1; break;
268+
}
269+
170270
can_reset(obj);
171271
obj->dev->IER = 0; // Disable Interrupts
172272
can_frequency(obj, 100000);

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC176X/objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ struct dac_s {
5959

6060
struct can_s {
6161
LPC_CAN_TypeDef *dev;
62+
int index;
6263
};
6364

6465
struct i2c_s {

libraries/tests/mbed/can/main.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include "mbed.h"
2+
3+
Ticker ticker;
4+
DigitalOut led1(LED1);
5+
DigitalOut led2(LED2);
6+
CAN can1(p9, p10);
7+
CAN can2(p30, p29);
8+
char counter = 0;
9+
10+
void printmsg(char *title, CANMessage *msg) {
11+
printf("%s [%03X]", title, msg->id);
12+
for(char i = 0; i < msg->len; i++) {
13+
printf(" %02X", msg->data[i]);
14+
}
15+
printf("\n");
16+
}
17+
18+
void send() {
19+
printf("send()\n");
20+
CANMessage msg = CANMessage(1337, &counter, 1);
21+
if(can1.write(msg)) {
22+
printmsg("Tx message:", &msg);
23+
counter++;
24+
}
25+
led1 = !led1;
26+
}
27+
28+
int main() {
29+
printf("main()\n");
30+
ticker.attach(&send, 1);
31+
CANMessage msg;
32+
while(1) {
33+
printf("loop()\n");
34+
if(can1.read(msg)) {
35+
printmsg("Rx message:", &msg);
36+
led2 = !led2;
37+
}
38+
wait(0.2);
39+
}
40+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include "mbed.h"
2+
3+
Ticker ticker;
4+
DigitalOut led1(LED1);
5+
DigitalOut led2(LED2);
6+
CAN can1(p9, p10);
7+
CAN can2(p30, p29);
8+
char counter = 0;
9+
10+
void printmsg(char *title, CANMessage *msg) {
11+
printf("%s [%03X]", title, msg->id);
12+
for(char i = 0; i < msg->len; i++) {
13+
printf(" %02X", msg->data[i]);
14+
}
15+
printf("\n");
16+
}
17+
18+
void send() {
19+
printf("send()\n");
20+
CANMessage msg = CANMessage(1337, &counter, 1);
21+
if(can1.write(msg)) {
22+
printmsg("Tx message:", &msg);
23+
counter++;
24+
}
25+
led1 = !led1;
26+
}
27+
28+
void read() {
29+
CANMessage msg;
30+
printf("rx()\n");
31+
if(can1.read(msg)) {
32+
printmsg("Rx message:", &msg);
33+
led2 = !led2;
34+
}
35+
}
36+
37+
int main() {
38+
printf("main()\n");
39+
ticker.attach(&send, 1);
40+
can1.attach(&read);
41+
while(1) {
42+
printf("loop()\n");
43+
wait(1);
44+
}
45+
}

0 commit comments

Comments
 (0)