Skip to content

Commit 65a72c2

Browse files
committed
Added documentation for the implementation
1 parent ff01046 commit 65a72c2

File tree

3 files changed

+105
-0
lines changed

3 files changed

+105
-0
lines changed

drivers/include/drivers/RawCAN.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,53 @@
3131
namespace mbed {
3232
class RawCAN: public CAN {
3333
public:
34+
/** Creates an unlocked CAN interface connected to specific pins.
35+
*
36+
* @param rd read from transmitter
37+
* @param td transmit to transmitter
38+
*
39+
* Example:
40+
* @code
41+
* #include "mbed.h"
42+
*
43+
*
44+
* Ticker ticker;
45+
* DigitalOut led1(LED1);
46+
* DigitalOut led2(LED2);
47+
* //The constructor takes in RX, and TX pin respectively.
48+
* //These pins, for this example, are defined in mbed_app.json
49+
* RawCAN can1(MBED_CONF_APP_CAN1_RD, MBED_CONF_APP_CAN1_TD);
50+
* RawCAN can2(MBED_CONF_APP_CAN2_RD, MBED_CONF_APP_CAN2_TD);
51+
*
52+
* unsigned char counter = 0;
53+
*
54+
* void send() {
55+
* if(can1.write(CANMessage(1337U, &counter, 1))) {
56+
* printf("Message sent: %d\n", counter);
57+
* counter++;
58+
* }
59+
* led1 = !led1;
60+
* }
61+
*
62+
* int main() {
63+
* ticker.attach(&send, 1);
64+
* CANMessage msg;
65+
* while(1) {
66+
* if(can2.read(msg)) {
67+
* printf("Message received: %d\n\n", msg.data[0]);
68+
* led2 = !led2;
69+
* }
70+
* ThisThread::sleep_for(200);
71+
* }
72+
* }
73+
*
74+
* @endcode
75+
*/
76+
77+
/* Note: The can apis are unlocked hence using this when multiple
78+
* threads are accessing a single instance of CAN will lead to
79+
* race conditions, can be used in single threaded CAN.
80+
*/
3481
using CAN::CAN;
3582

3683

targets/TARGET_STM/README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,63 @@ For application that require optimized maximum performance, the recommendation i
470470
The SPI DMA transfer support shall be implemented on a case-by-case based on below example
471471
https://github.com/ABOSTM/mbed-os/tree/I2C_SPI_DMA_IMPLEMENTATION_FOR_STM32L4
472472

473+
### CAN receive interrupt problem due to mutex and resolution
474+
475+
In bxCAN and earlier versions the receive interrupt flags can be cleared only on performing a read operation in ST MCUs
476+
But can_read() cannot be used in interrupt context as it is gaurded by lock operation and mbed does not allow locks in
477+
interrupt context. Hence the Rx interrupt is disabled for a while and read is deferred to thread context, the interrupt is
478+
enabled on a successful read.
479+
480+
As an other option RawCAN (with unlocked CAN apis) is also available and can be used directly, if only one thread is accessing
481+
the CAN interface.
482+
483+
While using RxInterrupt with the CAN object the receive ISR callback registered should defer read to thread context.
484+
A simple example is as shown below:
485+
486+
#include "mbed.h"
487+
488+
Ticker ticker;
489+
Thread canReadThread;
490+
491+
DigitalOut led1(LED1);
492+
DigitalOut led2(LED2);
493+
DigitalOut led3(LED3);
494+
495+
CAN can1(PD_0 ,PD_1);
496+
497+
EventQueue queue(32 * EVENTS_EVENT_SIZE);
498+
499+
int counter = 0xABCD;
500+
CANMessage msg;
501+
502+
void canRead(){
503+
if(can1.read(msg)) {
504+
if(msg.id==1100)
505+
led2 = !led2;
506+
if(msg.id==1102){
507+
led3 = !led3;
508+
}
509+
}
510+
}
511+
512+
void canISR(){
513+
queue.call(canRead);
514+
led3 = !led3;
515+
}
516+
517+
int main() {
518+
519+
can1.frequency(100000);
520+
can1.mode(CAN::Normal);
521+
522+
can1.attach(canISR, CAN::RxIrq);
523+
524+
canReadThread.start(callback(&queue, &EventQueue::dispatch_forever));
525+
526+
while(1) {
527+
}
528+
}
529+
473530

474531
## Mbed OS Wiki pages
475532

targets/TARGET_STM/can_api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,7 @@ static void can_irq(CANName name, int id)
11871187
// In legacy can (bxCAN and earlier), reading is the only way to clear rx interrupt. But can_read has mutex locks
11881188
// since mutexes cannot be used in ISR context, rx interrupt is masked here to temporary disable it
11891189
// rx interrupts will be unamsked in read operation. reads must be deffered to thread context.
1190+
// refer to the CAN receive interrupt problem due to mutex and resolution section of README doc.
11901191
__HAL_CAN_DISABLE_IT(&CanHandle, CAN_IT_FMP0);
11911192

11921193
if ((tmp1 != 0) && tmp2) {

0 commit comments

Comments
 (0)