2013/01/19

[arduino]自作NFCライブラリを使うとスタックが足りないっぽい

Arduinoスターターキットに入っていた本を順番に試していくのもいいかと思っていたが、やっぱりNFCに関係したことをやるのが私らしいだろう。
まあ、ハードの勉強も一緒にやるさ。

そんなわけで、以前作っていたArduino用NFCライブラリ for RC-S620/Sを使ってみた。


InListPassiveTargetして、NFC-Fを検出したらLEDを点灯させる、というところは動いた。
スケッチも含めて一発で動いたので、さすがに驚いた。
さすが私!

 

では、とSNEP TargetでPUSHするスケッチを動かした。
これは・・・動かなかった。
そんなもんだ、私。。。


まどろみさんのところを見て、標準のUARTポートじゃないところを使う手段があることを知ったが、どういうやりかたで実現しているのか確認していないし、なによりも初心者ってこともあるので、まずは標準UARTポートを使っている。
Arduino+RC-S620/SでSoftwareSerial通信が上手くいかない

 

エラーになったら、自作Abort関数を呼び、Arduino上のLEDをちかちか無限ループさせるようにしている。
いるのだが、なぜか点灯したままになるのだ。
なして?

setup()のポート設定後くらいにAbortを呼んでも、同じ。
ってことは、どうもロジック的な問題じゃなさそうだ。

よくわからんので、Abort呼び出しの直後に、while(1){}、とそれから先に進まないようにした。
すると・・・LEDがちかちかし始めた。
ロジックは変わってないので、違う原因だ・・・。

スケッチのサイズを見ていて気付いたのだが、avr-gccはよくできていて、while(1){}以降の関数は呼び出されることがないため、リンクレベルで捨てていてサイズが小さくなっている。
なので、setup()直後でAbortとwhile(1)するとサイズが小さいのだが、それをどんどん後ろにずらしていくとスケッチサイズが増えていく。
そして、あるところから先になると、while(1)をしてもLEDが点灯しっぱなしになった。
そこはちょうど、SNEPの処理を始める部分だ。

 

ってことは、スタックが足りなくなってプログラムカウンタがどっかに吹っ飛んでるんだろうな。
SNEPの処理をやると、LLCPや、NFC-DEPまでリンクすることになってしまう。
FM3みたいにメモリが多い環境では動いていたのだが、Arduino Unoでは足りなかったようだ。

Arduino UnoのRAMは・・・2KBか。
2KBでは、汎用に作ったSNEPでは足りないように思う。
FLASHは32KBで余裕があるので、送受信バッファを共用しつつ、処理速度を犠牲にしていけばなんとか・・・。
と思わなくもないが、そこまでしてSNEPしたいか?というと、そうでもないかも。


やるかどうかは別として、MAPファイルで確認くらいはしておきたい。
MAPファイルの出力方法はわからなかったが、Documents and Settingsの下にELFファイルができていることに気付いた。
(Arduino IDEを起動したままTempフォルダの整理をしてばしばし削除した後にビルドすると「フォルダがない」というエラーが出たのでわかった)。
ELFの見方は、BINARY HACKSで調べた。
.BSS(グローバル変数の初期値無し)と.DATA(グローバル変数の初期値有り)を見ればいいのかな。

[/cygdrive/c/Documents and Settings/xxxx/Local Settings/Temp/build4506488131124712308.tmp]$ readelf -S SnepTarget.cpp.elf
There are 16 section headers, starting at offset 0x264c0:
 
Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .data             PROGBITS        00800100 003cf0 000bd8 00  WA  0   0  1
  [ 2] .text             PROGBITS        00000000 000094 003c5c 00  AX  0   0  2
  [ 3] .bss              NOBITS          00800cd8 0048c8 00047f 00  WA  0   0  1
  [ 4] .debug_aranges    PROGBITS        00000000 0048c8 000920 00      0   0  1
  [ 5] .debug_pubnames   PROGBITS        00000000 0051e8 001844 00      0   0  1
  [ 6] .debug_info       PROGBITS        00000000 006a2c 00bb4f 00      0   0  1
  [ 7] .debug_abbrev     PROGBITS        00000000 01257b 002c8f 00      0   0  1
  [ 8] .debug_line       PROGBITS        00000000 01520a 006325 00      0   0  1
  [ 9] .debug_frame      PROGBITS        00000000 01b530 000fc0 00      0   0  4
  [10] .debug_str        PROGBITS        00000000 01c4f0 003715 01  MS  0   0  1
  [11] .debug_loc        PROGBITS        00000000 01fc05 005f68 00      0   0  1
  [12] .debug_ranges     PROGBITS        00000000 025b6d 0008b0 00      0   0  1
  [13] .shstrtab         STRTAB          00000000 02641d 0000a2 00      0   0  1
  [14] .symtab           SYMTAB          00000000 026740 0019e0 10     15 220  4
  [15] .strtab           STRTAB          00000000 028120 0016c9 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

 

足すと、4183byte。
あっはっは、スタックどころかRAM自体が全然足りてないやん。。。。

さて、どうしたもんだか。
動いているときの状況でも、1600byte以上使っているので、もともと多いんだ。
そういえば、空っぽの場合はどのくらいなんだろう?
裏で動いているものもあるだろうから、調べておきたい。

[/cygdrive/c/Documents and Settings/xxxx/Local Settings/Temp/build4038602356621893896.tmp]$ readelf -S empty_sketch.cpp.elf
There are 15 section headers, starting at offset 0x1740:
 
Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000074 0001d2 00  AX  0   0  2
  [ 2] .bss              NOBITS          00800100 000246 000009 00  WA  0   0  1
  [ 3] .debug_aranges    PROGBITS        00000000 000246 000090 00      0   0  1
  [ 4] .debug_pubnames   PROGBITS        00000000 0002d6 0000cd 00      0   0  1
  [ 5] .debug_info       PROGBITS        00000000 0003a3 0005c5 00      0   0  1
  [ 6] .debug_abbrev     PROGBITS        00000000 000968 000271 00      0   0  1
  [ 7] .debug_line       PROGBITS        00000000 000bd9 000635 00      0   0  1
  [ 8] .debug_frame      PROGBITS        00000000 001210 0000c0 00      0   0  4
  [ 9] .debug_str        PROGBITS        00000000 0012d0 0001ec 01  MS  0   0  1
  [10] .debug_loc        PROGBITS        00000000 0014bc 00016d 00      0   0  1
  [11] .debug_ranges     PROGBITS        00000000 001629 000078 00      0   0  1
  [12] .shstrtab         STRTAB          00000000 0016a1 00009c 00      0   0  1
  [13] .symtab           SYMTAB          00000000 001998 000610 10     14  39  4
  [14] .strtab           STRTAB          00000000 001fa8 000372 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

9byteとは、お主なかなかやるな。

ここにdelay()を加えると、こうなる。

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000074 000290 00  AX  0   0  2
  [ 2] .bss              NOBITS          00800100 000304 000009 00  WA  0   0  1

RAMは変わらんけど、コード量が増えた。
複数のタイマを管理する、という必要がないからRAMは最初に1つ確保しておけばいいということか。
ふーむ。

 

とにかく、2KBのRAMをうまく使うためには、ライブラリにもそれなりの制約を設けないとだめだな。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。