豊四季Tiny BASIC for Arduino(オリジナル版)のSRAM消費を軽減する修正を行ってみました。
Arduino UNOでは、SRAMが2kバイトしかありません。
オリジナル版のまま利用した場合、グローバル変数が1481バイト(72%)を利用しており、
残りが567バイトです。機能拡張するにはちょっと辛いです。
そこで、キーワード、エラーメッセージ等のグローバルな固定データをフラッシュメモリ上に
配置する修正をおこない、SRAMの消費を少々押さえました。
参考にしたサイト
・Arduinoで遊ぶページ - Arduino Uno編 - メモリの種類
・武蔵野電波 - Arduino 日本語リファレンス - PROGMEMとFマクロ
・Arduino - PROGMEM
良く知られているテクニックですが、
Arduino(AVRマイコン)でPROGMEMキーワードを使って変数の宣言を行うことで、
SRAMではなく、フラッシュメモリ上にデータを配置することが出来ます。
ただし、データの参照がちょっと面倒で、専用の参照を行う関数を利用する必要があります。
データ構造にも制約があり、キーワードテーブル等で使う2次元配列は対応されていません。
入れ子になる1次元配列を定義してから、その一次元配列のアドレスを配列として宣言して
2次元配列っぽい構造を作成します。
修正前のキーワードテーブル(オリジナル版よりソースを引用しています)
// Keyword table
const char *kwtbl[] = {
"GOTO", "GOSUB", "RETURN",
"FOR", "TO", "STEP", "NEXT",
"IF", "REM", "STOP",
"INPUT", "PRINT", "LET",
",", ";",
"-", "+", "*", "/", "(", ")",
">=", "#", ">", "=", "<=", "<",
"@", "RND", "ABS", "SIZE",
"LIST", "RUN", "NEW"
};
修正したキーワードテーブル
// Keyword table
#define KW(k,s) const char k[] PROGMEM=s // キーワード定義マクロ
KW(k000,"GOTO"); KW(k001,"GOSUB"); KW(k002,"RETURN");
KW(k003,"FOR"); KW(k004,"TO"); KW(k005,"STEP"); KW(k006,"NEXT");
KW(k007,"IF"); KW(k008,"REM"); KW(k009,"STOP");
KW(k010,"INPUT"); KW(k011,"PRINT"); KW(k012,"LET");
KW(k013,","); KW(k014,";");
KW(k015,"-"); KW(k016,"+"); KW(k017,"*"); KW(k018,"/"); KW(k019,"("); KW(k020,")");
KW(k021,">=");KW(k022,"#"); KW(k023,">"); KW(k024,"="); KW(k025,"<="); KW(k026,"<");
KW(k027,"@"); KW(k028,"RND"); KW(k029,"ABS"); KW(k030,"SIZE");
KW(k031,"LIST"); KW(k032,"RUN"); KW(k033,"NEW");
const char* const kwtbl[] PROGMEM = {
k000,k001,k002,
k003,k004,k005,k006,
k007,k008,k009,
k010,k011,k012,
k013,k014,
k015,k016,k017,k018,k019,k020,
k021,k022,k023,k024,k025,k026,
k027,k028,k029,k030,
k031,k032,k033,
};
KW()マクロは、
const char k000[] PROGMEM="GOTO";
const char k001[] PROGMEM="GOSUB";
と定義するのを省略するのに利用しています。
テーブルの参照はちょっと面倒です。
キーワード比較を行う部分は、一旦、SRAM上のメモリーにコピーして利用しています。
char* pkw = 0; //ひとつのキーワードの内部を指すポインタ
char kwtbl_str[16]; // コマンド比較用
// オリジナル
pkw = (char *)kwtbl[i]; //キーワードの先頭を指す
// 修正版
pkw = strcpy_P(kwtbl_str, (char*)pgm_read_word(&(kwtbl[i])));
ARM cortex-M系のgccでは、
constキーワードを付ければ、
フラッシュメモリ上に配置してくれて、かつ参照はSRAMと同等に行えるのと比べると
ちょっと面倒ですね。
とりあえず、この修正によりSRAM消費量を712バイト抑えることが出来ました。
SRAMは1279バイトほど余っているので、ちょっとした機能追加は出来ると思います。
もしかしたら、もっと効率の良いやり方があるかもしれませんが、これで良しとします。

ちょっといじった感じでは、オリジナル版と同じ感じで動いています。

この修正版は、下記にて公開いたいます。
https://github.com/Tamakichi/ttbasic_arduino_uno
最近のコメント