#概要
MbedOSでCAN通信で受信割り込みができない不具合について調べました。
#環境
- NUCLEO-F767ZI
- Mbed OS 6.15
状況
受信割り込みを設定しても全く受信しない。もしくはMutexロックがかかっていてエラーを吐く。
#原因
受信割り込み時にcan.read()
を使うとエラーを吐く。
この関数は読み込み時にMutexロックをするため、割り込みコンテクスト(割り込み時に実行される)では使用できない。
解決法?
-
mbed-os
フォルダ内のcan.h
を書き換える。
https://github.com/pilotak/NoMutexCAN
この記事のように、can.h
を継承し、CAN::read()
をオーバーライドすることでMutexを無効化する。 -
別スレッドで受信割り込みを処理する。
#include "mbed.h"
void onReceive();
void CANreceive();
CAN can(PB_5, PB_6, 500000);
Thread t(osPriorityNormal, 2000);
EventQueue queue(32 * EVENTS_EVENT_SIZE);
int main(void)
{
can.attach(onReceive, CAN::RxIrq);
t.start(callback(&queue, &EventQueue::dispatch_forever));
while (1)
{
printf("loop\n");
}
return 0;
}
void onReceive()
{
queue.call(CANreceive);
}
void CANreceive()
{
CANMessage msg;
if (can.read(msg))
{
printf("data: %s,id:%d\n", msg.data, msg.id);
}
}
ただし、これでもうまく行かないという報告もあります。
#まとめ
このエラーはMbed OS 5からずっと続いてるバグです。色々解決策が書かれていますが、どれもいまいち決め手に欠けます。
頑張って使えるようにするか、HALを使うのがいいのかもしれないです。
#参考文献
https://github.com/ARMmbed/mbed-os/issues/6714
https://forums.mbed.com/t/can-bus-interrupt-problem-mbed-5-15/10808/4
https://github.com/ARMmbed/mbed-os/issues/9495
https://github.com/pilotak/NoMutexCAN
https://qiita.com/noritan_org/items/172ca6c62fe4b36767d4
https://qiita.com/noritan_org/items/cc4a0ab2c6ff9c0aa5e
https://forums.mbed.com/t/can-attach-and-can-read-does-not-work-on-mbedos6/14720
(↑僕が質問しました)