・SH7216用Arduino互換ライブラリプロジェクトRev 1.0・SH7216用Ardunoライブラリの互換情報
▼コチラからダウンロードできます!http://japan.renesasrulz.com/partner_tools/marutsu/m/sh7216_board/default.aspx
この投稿の表題も含めてArduino「互換」ライブラリであるというこは徹底されたほうがよいと思います。
あと著作権と利用ライセンスについても明らかにされたほうが良い気がしますね。
このライブラリはこれで使えるのでしょうか?
japan.renesas.com/.../sh_arduino_ws.jsp
fujita様
アドバイスありがとうございます。
Forum名とライセンスなどの情報を修正、追加していきます。(7月中旬頃を予定)
chobichan様
はい、使えます。
SuperH発売20周年記念スペシャルワークショップ続編「Arduinoでさっくりアプリ開発・ワークショップ」ぜひ参加をご検討ください。
KPIT の GNUSH v13.01 Windows Tool Chain (ELF) をダウンロードし、プロジェクト中の Release ビルドと同じコンパイルオプション ‘-m2a -D RELEASE -Os -fno-function-cse -funit-at-a-time -falign-jumps -fdata-sections -ffunction-sections -nostdinc’ を指定して core/arduino/digitalio.cpp をコンパイルしてみたところ、digitalWrite() の
*(unsigned short *)(_PORT_DR_BASE + offset) &= ~bits;
のポートへのビットをリセットする箇所が
28: 62 81 mov.w @r8,r2 2a: 63 11 mov.w @r1,r3 2c: 62 27 not r2,r2 2e: a0 03 bra 38 <_digitalWrite+0x38> 30: 22 39 and r3,r2 38: 21 21 mov.w r2,@r1
というコードに、同じく
*(unsigned short *)(_PORT_DR_BASE + offset) |= bits;
セットする箇所が
32: 63 11 mov.w @r1,r3 34: 62 81 mov.w @r8,r2 36: 22 3b or r3,r2 38: 21 21 mov.w r2,@r1
という 1 命令でポートへの操作が完了しないコードにコンパイルされました。
digitalWrite() はユーザーのプログラムや割り込み処理からも呼び出される関数ですが、同一のポートへの操作がかち合った場合、おかしな動作になってしまうと思います。
Arduinoプロジェクトをダウンロードし、KPITからGNUC v13をインストールし、HEW上からプロジェクトを開いてビルドしたのですが、1488個のエラーが発生しています。
エラーメッセージを見るとRXのツールチェインを呼んでいるみたいで、Arduino.hwpを開いてみるとやはりRXのツールチェインを指定しています。
そちらではビルド通ったのでしょうか?
sh-elf-gcc で直にコマンドラインでコンパイルしました。HEW は使ってません。
HEW で C:/WorkSpace/ 以下に SH7216_Arduino/ を展開してワークスペースを開いてみました。
ワークスペース中の arduino_gcc をアクティブプロジェクトに設定して Debug でビルドしたところ core/arduino/LiquidCrystal.cpp のビルドで
sh-elf-gcc-wrapper.exe は動作を停止しました
というエラーが出た他は凡そコンパイルは問題ない感じでした。但し上のコンパイルが通らないのでリンク成功まで行きません。
Release でビルドするにはインクルードパスにワークスペース以下のディレクトリが登録されておらずうまくいかない感じです。HEW のメニューの「ビルド(B)」→「KPIT GNUSH[ELF] Toolchain…」を開いてインクルードパスの設定を Debug と同様に設定すると概ねコンパイルは通るようです。但し、core/arduino/Arduino.cpp のコンパイルで
C:\WorkSpace\SH7216_Arduino\core\arduino\Arduino.cppPrePhase failed
とエラーになるみたいなのでやっぱりリンク成功まで行かないですね。
Release ビルドで core/arduino/Arduino.cpp のコンパイルに失敗するのは include/arduino/WString.h の中で stdlib.h をインクルードしているにもかかわらず HEW でのコンパイルオプションに ‘-nostdinc’ が指定されているためと判明。外し方が分からん。
外し方が分からん。
KPIT~ の設定で Category: Other の中の ‘Do not search standardなんちゃら’ のチェックを外すと ‘-nostdinc’ が外せることが判明。但しビルドでは相変わらずエラーになる不思議。コマンドラインで直なら問題ないのだがこれだから IDE は謎が多いな。
アクティブプロジェクトの変更をしていませんでした。arduino_gccにしたらコンパイルは通ります。
arduinoが展開されていてarduino_gccがある事に気づかなかった。
avastが一々「怪しいプログラムが起動した!」ってチェックに行っちゃうから、えらい時間が掛かる(笑)。
と、ここでようやく周回遅れのビット操作の話ですが、ビットフィールドを指定してもRead Modify Writeになってしまいますね。
SH2Aからはビット操作命令が追加になっているのですが、例えばBSETまたはBSET,Bの場合、該当レジスタまたはメモリのLSBの8bitのみが操作対象なので、
ちょっと”いやーん”な感じです。
某アーキテクチャみたいにビットバンディングとか、某マイコンみたいにSET/RESET専用レジスタとか有れば、、、
arduino.hwpのツールチェインはなんでSHCではなくRXだったんだろう???(今更)
GCC が SH-2A 用に BSET 命令を吐いてくれることを期待して
void bset(volatile char* port, int bit) { switch (bit) { case 0: *port |= 0x01; break; case 1: *port |= 0x02; break; case 2: *port |= 0x04; break; case 3: *port |= 0x08; break; case 4: *port |= 0x10; break; case 5: *port |= 0x20; break; case 6: *port |= 0x40; break; case 7: *port |= 0x80; break; } }
というコードを試してみたら、
$ sh-elf-gcc -Wall -W -m2a -Os -c bset.c && sh-elf-objdump -d bset.o bset.o: file format elf32-sh Disassembly of section .text: 00000000 <_bset>: 0: e1 07 mov #7,r1 2: 35 16 cmp/hi r1,r5 4: 89 19 bt 3a <_bset+0x3a> 6: 61 40 mov.b @r4,r1 8: c7 01 mova 10 <_bset+0x10>,r0 a: 05 5c mov.b @(r0,r5),r5 c: 05 23 braf r5 e: 61 1e exts.b r1,r1 10: 08 0c mov.b @(r0,r0),r8 12: 10 14 mov.l r1,@(16,r0) 14: 18 1c mov.l r1,@(48,r8) 16: 20 24 mov.b r2,@-r0 18: a0 0e bra 38 <_bset+0x38> 1a: 86 18 bset #0,r1 1c: a0 0c bra 38 <_bset+0x38> 1e: 86 19 bset #1,r1 20: a0 0a bra 38 <_bset+0x38> 22: 86 1a bset #2,r1 24: a0 08 bra 38 <_bset+0x38> 26: 86 1b bset #3,r1 28: a0 06 bra 38 <_bset+0x38> 2a: 86 1c bset #4,r1 2c: a0 04 bra 38 <_bset+0x38> 2e: 86 1d bset #5,r1 30: a0 02 bra 38 <_bset+0x38> 32: 86 1e bset #6,r1 34: e2 80 mov #-128,r2 36: 21 2b or r2,r1 38: 24 10 mov.b r1,@r4 3a: 00 6b rts/n
ポインタの指すメモリに対して直接 BSET してくれないわ、ビット 7 に対してはなんでか OR 命令吐いてくれるわでガッカリなので、期待したコードを吐かせるには
void bset(volatile char* port, int bit) { switch (bit) { case 0: __asm __volatile("bset.b #0, @(0, %0)\n" :: "r" (port)); break; case 1: __asm __volatile("bset.b #1, @(0, %0)\n" :: "r" (port)); break; case 2: __asm __volatile("bset.b #2, @(0, %0)\n" :: "r" (port)); break; case 3: __asm __volatile("bset.b #3, @(0, %0)\n" :: "r" (port)); break; case 4: __asm __volatile("bset.b #4, @(0, %0)\n" :: "r" (port)); break; case 5: __asm __volatile("bset.b #5, @(0, %0)\n" :: "r" (port)); break; case 6: __asm __volatile("bset.b #6, @(0, %0)\n" :: "r" (port)); break; case 7: __asm __volatile("bset.b #7, @(0, %0)\n" :: "r" (port)); break; } }
とかすればいいのかな?
$ sh-elf-gcc -Wall -W -m2a -Os -c bset.c && sh-elf-objdump -d bset.o bset.o: file format elf32-sh Disassembly of section .text: 00000000 <_bset>: 0: e1 07 mov #7,r1 2: 35 16 cmp/hi r1,r5 4: 89 1f bt 46 <_bset+0x46> 6: c7 02 mova 10 <_bset+0x10>,r0 8: 05 5c mov.b @(r0,r5),r5 a: 05 23 braf r5 c: 00 09 nop e: 00 09 nop 10: 0a 10 16 1c movi20 #71196,r10 14: 22 28 tst r2,r2 16: 2e 34 mov.b r3,@-r14 18: 34 09 10 00 bset.b #0,@(0,r4) 1c: 00 6b rts/n 1e: 34 19 10 00 bset.b #1,@(0,r4) 22: 00 6b rts/n 24: 34 29 10 00 bset.b #2,@(0,r4) 28: 00 6b rts/n 2a: 34 39 10 00 bset.b #3,@(0,r4) 2e: 00 6b rts/n 30: 34 49 10 00 bset.b #4,@(0,r4) 34: 00 6b rts/n 36: 34 59 10 00 bset.b #5,@(0,r4) 3a: 00 6b rts/n 3c: 34 69 10 00 bset.b #6,@(0,r4) 40: 00 6b rts/n 42: 34 79 10 00 bset.b #7,@(0,r4) 46: 00 6b rts/n
それでもポートに対してはビット 7 までしか使えないなら機能不足か。
『SH7214グループ、SH7216グループ ユーザーズマニュアル ハードウェア編』見るとポートなんとか・IO レジスタ H とか L とかはアクセスサイズが 8 も可能と書かれていますが、奇数番地アクセスすると上位ビットが操作できたりはしないんですか?