複数メールボックスの利用
以前の実装では、送信も受信も1つのメールボックスを使っていたが、少なくとも「受信」では、1つの受信時、割り込み処理で、メールボックスから、フレームを取り出してバッファに積む間に、別の ID を受信していると、そのフレームをロストしてしまう。
そこで、複数のメールボックスを利用するように修正した。
送信側も複数のメールボックスを利用するように修正。
can_io テンプレートのプロトタイプは以下のようになった。
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
/*!
@brief CAN 制御クラス
@param[in] CAN CAN 定義クラス
@param[in] RBF 受信バッファクラス (utils::fixed_fifo<can_frame, N>)
@param[in] TBF 送信バッファクラス (utils::fixed_fifo<can_frame, N>)
@param[in] PSEL ポート候補
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
template <class CAN, class RBF, class TBF, port_map::option PSEL = port_map::option::FIRST>
class can_io : public can_io_def {
アプリケーションからは、以下のように「typedef」して使う。
// CAN 受信バッファの定義
typedef utils::fixed_fifo<device::can_frame, 256> CAN_RXB;
// CAN 送信バッファの定義
typedef utils::fixed_fifo<device::can_frame, 128> CAN_TXB;
typedef device::can_io<device::CAN0, CAN_RXB, CAN_TXB, CAN0_PORT> CAN0;
CAN0 can0_;
CAN/ID の収集と解析
とりあえず、「can_io」クラスは、送信、受信が行えるようになったので、CAN バスの解析機能を実装してみた。
新規に「can_analize」テンプレートクラスを追加して、内部で、CAN/ID を動的に収集して、表示する。
ID の収集には、「boost/unordered_map.hpp」を利用したが、標準で用意されている「std::unordered_map」は、関連クラスの関係でリンクが難しい事が判った為だ。
boost の方が小回りが利く。
※この利用では、何故か、浮動小数点ライブラリをリンクする必要があるようだ・・・
ID を動的にソートして収集するには「std::map」が良いが、「std::map」は、ツリー式で、件数が増えるとメモリの肥大化が問題になると思われる。
※計測はしていないが、経験的にハッシュを使う「unordered_map」の方が高速で省メモリなのではと思う。
※使用メモリも、件数によると思う、これも調査していないので何とも言えない。
※また、たとえば、車の CAN、工作機械などの CAN などで、標準的に利用している ID の数も、今はまだ理解していない。
※コード的には、コンテナの扱いが同等なので、どちらでも利用出来る。
typedef boost::unordered_map<uint32_t, info_t> MAP;
// typedef std::map<uint32_t, info_t> MAP;
- どちらかを有効にする。
- 実行ファイルは、「std::map」の方が若干大きくなる。
解析機能は、CAN0 側にのみ付けているので(両方付ける事も出来る)、ループ接続で実験する際は、CAN1 側から送信する必要がある。
これらの機能実装は、C++ ならではで、組み込みマイコンでも、boost がまともに動くのは、便利としか言いようが無いw
送信と受信の様子:
Start CAN sample for 'RX64M' 120[MHz]
CAN0: SPEED: 1000000 [bps], BRP: 3, TSEG1: 12, TSEG2: 7, SJW: 4
RX Interrupt level: 1, TX Interrupt level: 1
CAN1: SPEED: 1000000 [bps], BRP: 3, TSEG1: 12, TSEG2: 7, SJW: 4
RX Interrupt level: 1, TX Interrupt level: 1
# ch 1
# send 0x100 1 2 3
# map
1 S:x0000100 (256)
Total = 1
# dump 256
1 S:x0000100 (256)
ID: std 0x100 (256)
DATA(3): 01 02 03
TS: 11269
# send 123 5 6 7
# send 500 67 90 200
# send 300 100 99 100
# map
1 S:x000012C (300)
1 S:x00001F4 (500)
1 S:x000007B (123)
1 S:x0000100 (256)
Total = 4
# dump 500
1 S:x00001F4 (500)
ID: std 0x1F4 (500)
DATA(3): 43 5A C8
TS: 14498
# send 500 0x8A 0xcb 0xfe 0x24
# map
1 S:x000012C (300)
2 S:x00001F4 (500)
1 S:x000007B (123)
1 S:x0000100 (256)
Total = 4
# dump 500
2 S:x00001F4 (500)
ID: std 0x1F4 (500)
DATA(4): 8A CB FE 24
TS: 9925
#
「send_loop」コマンドを追加。
ランダムなデータを送信するテストを行った:
# ch 1
# send_loop 100
# map
1 S:x00002A4 (676)
1 S:x0000301 (769)
...
1 S:x000013D (317)
2 S:x0000260 (608)
1 S:x0000015 (21)
1 S:x000031D (797)
1 S:x00000D6 (214)
1 S:x0000228 (552)
Total ID = 92 / Total count = 100, Total Record = 367
# send_loop 100
# map
1 S:x000008A (138)
1 S:x000026E (622)
1 S:x0000028 (40)
1 S:x0000116 (278)
1 S:x00001BD (445)
1 S:x00001AC (428)
...
2 S:x00000F7 (247)
1 S:x00000DB (219)
1 S:x000013D (317)
1 S:x00002E9 (745)
1 S:x00000A6 (166)
1 S:x0000228 (552)
Total ID = 170 / Total count = 200, Total Record = 678
# send_loop 50
# map
1 S:x000012E (302)
1 S:x00000C8 (200)
1 S:x0000070 (112)
1 S:x0000077 (119)
1 S:x00000DA (218)
...
2 S:x00000F7 (247)
1 S:x000013D (317)
1 S:x00002E9 (745)
1 S:x0000228 (552)
Total ID = 210 / Total count = 250, Total Record = 853
#
とりあえず、ちゃんと動いているようだ。
ch CH-no set current CAN channel (CH-no: 0, 1)
send CAN-ID [data...] send data frame
stat MB-no stat mail-box (MB-no: 0 to 31)
list MB-no list mail-box (MB-no: 0 to 31)
map [CAN-ID] Display all collected IDs
clear clear map
dump CAN-ID dump frame data
send_loop NUM random ID, random DATA, send loop
help command list (this)
新しいコマンドを追加したサンプルはプッシュ済み
今回はここまで。