組込みとともに -61ページ目

AVR Studio リテラル文字列取扱注意 Part 2

前回の日記で扱ったリテラル文字列の処理は不完全でした。

http://ameblo.jp/elementor/entry-10192030215.html  (←前回の日記)


ポイント1

リテラル文字列容易のROM配置指定のマクロがありました

PSTR


ポイント2

読込みにもprogram(ROM)領域を意識する必要があります


ポイント3

昨日の疑問なぜRAMにリテラルを配置するか分りました。

AVRではROM(program)領域とRAM(data)領域はアドレス空間自体が異なっています。

そのため通常変数として扱う場合はdata領域に配置していなければなりません。

program領域に配置した変数は特別な操作(*)をしないとデータを読み込めません。

CPUの構造による制約だったわけです。

*:LPM


そういうわけでコードを書き直すと次のようになります。


~定義部~
#include <avr/pgmspace.h>
#define ERRMSG_BAD_COMMAND PSTR("E1")
#define ERRMSG_BAD_PARAMETER PSTR("E2")

~関数内~
SendMsg_P(ERRMSG_BAD_COMMAND);


/* SendMsg実装 */

void SendMsg_P(PGM_P buf){
char c;
while((c = pgm_read_byte(buf)) != (char)0)

{
UART_write(c);
buf++;
}

UART_write('\r'); /* 改行コード */
UART_write('\n'); /* 改行コード */
}

/*----ここまで----*/

PSTRを使ったことで幾分シンプルになりましたね。


AVR Studio リテラル文字列取扱注意

AVR Studioでリテラル文字列扱うときは注意が必要です。

例えば
~定義部~
#define ERRMSG_BAD_COMMAND "E1"
#define ERRMSG_BAD_PARAMETER "E2"

~関数内~
SendMsg(ERRMSG_BAD_ COMMAND);

とした場合
文字列"E1"はdata(RAM)領域に配置されます。

ATTINY2313ではRAMが非常に小さく128バイトしかないなめリテラル文字列をRAMには配置させたくありません。

この対策にはAVR Studio固有の定義PROGMEMという定義を使います
使い方
~定義部~
#include
#define ERRMSG_BAD_COMMAND "E1"
#define ERRMSG_BAD_PARAMETER "E2"


const char Errmsg_Bad_Command[] PROGMEM = ERRMSG_BAD_COMMAND;
const char Errmsg_Bad_Parameter[] PROGMEM = ERRMSG_BAD_PARAMETER;

~関数内~
SendMsg(Errmsg_Bad_ Command);

シミュレータやマップファイルで確認するとちゃんとprogram (ROM)領域に配置されたことを確認できます


複数モジュール(ファイル)で共通のリテラルを使用する場合はPROGMEM変数は1つのモジュール(ファイル)で実体を定義し、定義部にはextern宣言で使用すると良いと思う(未確認)


SPLINTを使用する場合PROGMEMはSPLINTで解釈出来ないので無視する様に設定する必要があります。


それにしてもどうしてこんな仕様にしてるんだろう?

ソフトバンク通信モジュール

組み込み用通信モジュールのDoPa、FOMAは数年前から使ってました。

auからも同様のモジュールがあったのは知ってましたが、ソフトバンクからもでてたんですね。

NI-01S(ネットインデックス社製)
あまり聞いたこと無い会社ですね

FOMAモジュールとの違いは、音声通話、SMSにも対応しているところ

FOMAの場合は専用線かmoperaへ接続する利用法だがソフトバンクの場合はどうなんだろ、ソフトバンクだけに通信コストが安そうなイメージがあるので時間の有るときに詳しく調べたい。

単価も気になります。