TRZ1104A (11) Natural Tiny Shell (NT-Shell) を使ってみる (2)2012年12月04日 21時01分40秒

NT-Shell
NT-Shell を実装するためにドキュメントを読んでいると、必要なのは getchar/putchar に相当する関数ではなくて read/write に相当する関数であることがわかった。
さっそく UARTReceive を作成する。
int UARTReceive(char *buf, int cnt, void *extobj)
{
    int i;

    for (i = 0; i < cnt; i++)
        buf[i] = UARTReceiveByte();
    return 0;
}


UARTSend も若干修正。
int UARTSend(const char *BufferPtr, int Length, void *extobj)
{
  while ( Length != 0 ) {
    /* THRE status, contain valid data */
#if !TX_INTERRUPT
    while ( !(LPC_UART->LSR & LSR_THRE) );
    LPC_UART->THR = *BufferPtr;
#else
    /* Below flag is set inside the interrupt handler when THRE occurs. */
    while ( !(UARTTxEmpty & 0x01) );
    LPC_UART->THR = *BufferPtr;
    UARTTxEmpty = 0;	/* not empty in the THR until it shifts out */
#endif
    BufferPtr++;
    Length--;
  }
  return 0;
}


callback はダミーにしておこう。
static int func_callback(const char *text, void *extobj)
{
    xprintf("%s\r\n",text);
    return 0;
}


コンパイル・リンク・フラッシュライト
起動と同時にプロンプトが出てくる。
いいね~。

文字列を打ち込んでみる。
バックスペースで修正
ヒストリー機能も使ってみる
callback が printf だけなので今の所ここまでだ。
ただ不便なのは一度ヒストリー機能を使うとコマンドラインに文字列が残ってしまうことだ。DOS プロンプトのように何もない状態にすることができない。

さて、これだけじゃ面白くないので NT-Monitor も動かしてみる。
その前にメモリ情報を実装しておこう。残念ながらこれが有効なのは scroll だけだ。

 


立ち上がりは NT-Shell と同じだ。
HELP を見ると
(Debug commands)
 Read    : RB|RW|RL [ADDR]
 Write   : WB|WW|WL [ADDR] [DATA]
 Dump    : DB|DW|DL [ADDR] (LEN)
 Fill    : FB|FW|FL [ADDR] [LEN] [DATA|TYPE]  (TYPE: inc, dec, rand, bitwalk)
 Copy    : CB|CW|CL [ADDR-SRC] [ADDR-DES] [LEN]
 Verify  : VB|VW|VL [ADDR-SRC] [ADDR-SRC] [LEN]
 Scroll  : SB|SW|SL (ADDR)
(Number formats)
 Binary      : b01010101 or 01010101b
 Octal       : o01234567 or 01234567o
 Decimal     : d12345678 or 12345678d
 Hexadecimal : h1234ABCD or 1234ABCDh
いろいろできるようだ。

NT-Monitor
使ってみると、ドキュメントにも書いてあるように Shell が弱い。NT-Shell と合体させるのがいいようだ。しかし、サイズは巨大になる。NT-Shell と NT-Monitor でフラッシュのほぼ全てが埋まってしまう。

もう一点、 Scroll を実行すると後はReset を実行するしかない。コマンドラインに戻れないのだ。これは深刻な問題なのでぜひ何とかしたい。

あ!、さらにもう一点ある。 Scroll を実行すると受信バッファがすぐに overflow してしまう。実害はないものの何とかしたいところだ。これは NT-Monitor の実装のせいもあるが UARTSend/UARTReceive の問題でもある。


そうそう、割り込みハンドラの部分を忘れていた。( uart.c )
volatile int32_t  UARTfp;
volatile int32_t  UARTlp;

void UART_IRQHandler(void)
{
    :
    :

  {
    /* Receive Data Available */
    UARTBuffer[UARTfp++] = LPC_UART->RBR;
    UARTfp %= BUFSIZE;
    if (UARTfp == UARTlp)
        GPIOSetValue( LED_PORT, LED_BIT, LED_ON );	/* buffer overflow */
    if((UARTCount = (UARTfp - UARTlp)) < 0)
        UARTCount += BUFSIZE;
  }

    :
    :
オーバーフローすると LED が点灯する。


参照:CuBeatSystems
    CQ出版社インターフェース2013年1月号P174「FM3マイコンで試す! メモリ・ダンプ・モニタの作成」

環境:TRZ1104A (LPC1114/301)
    + code.bundle.lpc11xx.keil.zip (V1.04)
    + Natural Tiny Shell (NT-Shell Version 0.2.0)
    + Natural Tiny Monitor (NT-Monitor Version 0.2.0)
    + TeraTerm Version 4.69
    + Keil MDK-ARM V4.53
    + GCC Sourcery CodeBench Lite 2012.09-63
    + KPIT Cummins GNU-Archive Editor v1.1
    + KPIT Cummins GNU-Map Viewer v1.0

TRZ1104A (10) Natural Tiny Shell (NT-Shell) を使ってみる (1)2012年12月02日 22時30分02秒

Interface 2013年1月号に「 FM3マイコンで試す!メモリ・ダンプ・モニタの作成」というのがあった。
さっそく私も試してみたくなった。

まず、Natural Tiny Shell (NT-Shell Version 0.2.0)をダウンロード。
ついでに Natural Tiny Monitor (NT-Monitor Version 0.2.0) もダウンロード。

次に、組み合わせるCPUを選ばなくてはならない。
FRK-FM3 (MB9BF618T)
CQ-LM3S3748
CQ-FRK-NXP-ARM (LPC2388)
SH7085
FRK-RX62N
FRK-SH2A (SH2A-7262)
TRZ1104A (LPC1114/301)
TRZ1002H (H8SX-1655)
AKI-SH2/7045F
BTC050 (SH-7045F)
CQ-STARM (STM32F103VBT6)
こうやって書き出してみるとずいぶんたくさん持っているものだ。 もちろんこれが全てではない。
この中では TRZ1104A が手ごろのような気がするのでこれで進める。
ベースのサンプルは code.bundle.lpc11xx.keil.zip の UART でいいだろう。
と、始めてみたものの uart.c の中に getchar に相当する関数がない。
putchar に相当する関数もないが、これは以前 printf のテストで作成したので問題ない。
最悪なのは UART バッファーが FIFO 形式になっていないことだ。この部分は修正しよう。
まずは UARTSendByte からだ。
int UARTSendByte(char c)
{
#if CONFIG_UART_ENABLE_TX_INTERRUPT==1
      /* Below flag is set inside the interrupt handler when THRE occurs. */
      while ( !(UARTTxEmpty & 0x01) );
      LPC_UART->THR = c;
      UARTTxEmpty = 0;	/* not empty in the THR until it shifts out */
#else
      while ( !(LPC_UART->LSR & LSR_THRE) );
      LPC_UART->THR = c;
#endif
      return 1;
}

次に UARTReceiveByte 。この部分はバッファーからキャラクタを取り出すだけにする。
int UARTReceiveByte(void)
{
  int chr;

  while (UARTfp == UARTlp) ;
  LPC_UART->IER = IER_THRE | IER_RLS;		/* Disable RBR */
  chr = UARTBuffer[UARTlp++];
  UARTlp %= BUFSIZE;
  UARTCount--;
  LPC_UART->IER = IER_THRE | IER_RLS | IER_RBR;	/* Re-enable RBR */
  return chr;
}

後は割り込みハンドラの部分だが、今日はここまでにしておこう。

参照:CuBeatSystems
    CQ出版社インターフェース2013年1月号P174「FM3マイコンで試す!メモリ・ダンプ・モニタの作成」

環境:TRZ1104A (LPC1114/301)
    + code.bundle.lpc11xx.keil.zip (V1.04)
    + Natural Tiny Shell (NT-Shell Version 0.2.0)
    + Keil MDK-ARM V4.53
    + GCC Sourcery CodeBench Lite 2012.09-63
    + KPIT Cummins GNU-Archive Editor v1.1
    + KPIT Cummins GNU-Map Viewer v1.0

FRK-FM3 (6) FLASH USB DIRECT Programmer2012年11月20日 22時08分09秒

USB デバイスが認識されません
書き込み速度が遅くて使う気になれない FRK-FM3 を片付ける前にもう一度動かしてみようと、以前作ったプロジェクトをコンパイル。

Build target 'arm-none-eabi-gcc-4_6'
linking...
arm-none-eabi-gcc: error: unrecognized command line option '-Wl'
Target not created
エラーだ。
どうして次から次へと問題が出てくるのだ。
今までこんな所でエラーになったことは無い。コンパイラの解釈が変わったのか?

toolchain を Sourcery gcc 4.5.1 に戻すと問題ない。そういえば先日 gcc-4.6.3 を gcc-4.7.2 に変更したばかりだった。

-Wl がなければ問題ないが µVision4 では built-in なので削除できない。
何かいい方法は無いかといろいろやっていて、Map file を作成する事がこのエラーから逃れられる唯一の方法であることがわかった。これからは µVision4 を使う限り Map file の作成が必須だ。

さて、何をしようとしていたんだっけ? コンパイルができたので FRK-FM3 を接続し書き込もうとすると

USB デバイスが認識されません

おいおい、これもか?

RESET を実行してもだめ。
USB ケーブルを抜き差ししてもだめ。
FUJITSU USB DIRECT Programmer を新規インストールしても認識しないのでドライバのインストールすらできない。
数えるほどしか使ってないのに壊れたのか?
片付けるために USB コネクタを外そうとすると「ピコン!」あの懐かしい音がした。
どうやらコネクタの接触不良のようだ。何回か抜き差ししているうちに安定してきた。

USB DIRECT Programmer で書き込んでみる 67.02秒 (1112bytes) 以前と変わらぬ遅さだ。
専用のライターソフトを作れば問題ないだろうが私にそんな力は無い。
また、富士通も力を入れてないので使い勝手のいいライターを期待するのは無理だろう。
そこで、現在の環境のまま書き込みのスピードアップを図ることにする。
何とかして短いプログラムは短時間で書き込みたい。それではとデバイスの設定を MB9BF616S/T にしてみると 39.86秒。
おお!!これか?
さらに MB9BF311L/M/N にすると 18.16秒。
これ以下は無いので自分で作成してみた。
C:\Program Files\Fujitsu\FUJITSU USB DIRECT Programmer\chipdef.ini
[MB9BF618S/T_16k]
DownloadFile=m_flash.9a314
LoadAddress=0x20000000
StartAddress=0x000000,0x100000
EndAddress=0x003FFF,0x100001
FlashSize=0x004000,0x000002
Clock=4MHz,48MHz
Baud=9600,9600
Baud2=115200,115200
16kの設定だ。14.53秒
書き込みはすぐ終わるがイレースに時間がかかる。これ以上の短縮は難しそうだ。m_flash.9a314 の変更ができればまだ短縮はできるかも知れないが MB9BF311L/M/N までにしておこう。
ちなみにフラッシュのサイズは以下のようになっているので書き込むサイズに応じてデバイスを選択しよう。(手間のかかるライターだ。)
Part Number	Flash Size
MB9AF311L/M/N	64k  (0x10000)
MB9AF312L/M/N	128k (0x20000)
MB9AF314L/M/N	256k (0x40000)
MB9AF315M/N	384k (0x60000)
MB9BF616S/T	512k (0x80000)
MB9BF617S/T	768k (0xC0000)
MB9BF618S/T	1M   (0x100000)

これでやっと我慢できるレベルになった。
なんてったってテストだから短いプログラムばかりだ。60秒以上待たされたのではやる気も失せる。

環境:FRK-FM3 (MB9BF618T)
    + FUJITSU USB DIRECT Programmer V01L07
    + Keil MDK-ARM V4.53
    + GCC Sourcery CodeBench Lite 2012.09-63
    + KPIT Cummins GNU-Archive Editor v1.1
    + KPIT Cummins GNU-Map Viewer v1.0

CQ-LM3S3748 (15) Ride7 Project2012年11月18日 16時27分56秒

Ride7 blinky
先日 Ride7 用に Startup を作成したがまだ動作は確認してなかった。簡単なプログラムで確認してみよう。

新規プロジェクトの作成
①LM3S3748 を選択して新規プロジェクトを作成する。
②Project Properties で Application Options を設定する。
Directories
	Output  Directory	$(ApplicationDir)\out
	Listing Directory	$(ApplicationDir)\out
③Project Properties で Advanced ARM Options を設定する。
Debug environment
	Debug tool		Simulator SIM-ARM
	Start Mode		Reset address
④Project Properties で LD Linker を設定する。
General
	Output file format	binary
Scripts
	Starter Kit limited	No
More
	More options		-Wl,--section-start -Xlinker .isr_vector=0x00001800
⑤blinky.c を Add Item で追加する。(blinky.c
⑥Make all project でコンパイル。
リンカースクリプトも予定通りできている。 Startup のリンクも問題ない。いい感じだ。
⑦LM Flash Programmer でプログラム。

LED が点滅している。問題ないようだ。
しかし、この環境で気に入らないのは外部 tool を Windows のメニューから起動しなくてはならないことだ。うまい方法は無いものだろうか?

おっと、忘れる所だった。以下の二つも所定のディレクトリに必要だ。
C:\Program Files\Raisonance\Ride\lib\ARM\crt0_LM3S3748.o
C:\Program Files\Raisonance\Ride\lib\ARM\include\lm3s3748.h
Startup は crt0_LM3Sx.o として兼用にしたほうがよかったかもしれない。

LM3S3748_Ride7.zip

環境:CQ-LM3S3748
    + Ride7 version 7.30.10.0169
    + RKit-ARM version 1.30.10.0356
    + GCC Sourcery CodeBench Lite 2012.09-63

CQ-LM3S3748 (14) CMSIS (3)2012年11月17日 08時41分34秒

さて、core_cm3.c (version: V1.10) がコンパイルエラーになった件。
コンパイラのバージョンを Sourcery gcc 4.5.1 に変えるとうまくいった。その後の調査で No Optimization でコンパイルしても問題ないことがわかった。
ならば最新の arm-2012.09-63-arm-none-eabi.exe (gcc-4.7.2) では修正されているかもしれないと思い試してみた。
Error: registers may not be the same -- `strexb r0,r0,[r1]'
Error: registers may not be the same -- `strexh r0,r0,[r1]'
やはりだめだ。こんな時は Google さんに聞くに限る。と聞いてみると、バグらしい。しかも、昨年夏にはわかっていたようだ。解決策も書いてある。
知らなかったのは私だけか?

そして、この際なので新しいコンパイラ GCC Sourcery CodeBench Lite 2012.09-63 にした。

環境:CQ-LM3S3748
    + Keil MDK-ARM V4.53
    + GCC Sourcery CodeBench Lite 2012.09-63
    + KPIT Cummins GNU-Archive Editor v1.1
    + KPIT Cummins GNU-Map Viewer v1.0

CQ-LM3S3748 (13) USB printf (2)2012年11月13日 21時12分18秒

フルバッファード I/O (_IOFBF)
「printf がおかしい」の続き。
今までに無い経験だった。もしや、と思ってUSBputc() をやめて全て printf を使ってみた。
正常に表示できる。

ためしに setvbuf(stdout, NULL, _IOFBF, 0); を指定すると(上右図)あらあら悲惨な結果だ。
この結果から _IOLBF がデフォルトということになる。

以前聞いた事があるのは「 Buffered I/O と Unbuffered I/O を混在させてはいけない。」ということだった。不具合に遭遇したことがなかったので今まで意識することはなかったがこれからは気をつけよう。
では具体的にどうすればよいのだろう?

①全て高水準関数(Buffered I/O)を使う。
② setvbuf で _IONBF を設定する。

①は意識しないとなかなか難しい。②は非効率的ということになる。
今回は①の方法で解決することにする。(USBputc() を putchar() に変更)
何とか解決はしたがもっと他にいい方法は無いのだろうか?

環境:CQ-LM3S3748
    + Keil MDK-ARM V4.53
    + GCC Sourcery CodeBench Lite 2012.03-56
    + KPIT Cummins GNU-Archive Editor v1.1
    + KPIT Cummins GNU-Map Viewer v1.0

CQ-LM3S3748 (12) USB printf (1)2012年11月12日 22時42分10秒

Memory dump
先日の rprintf はうまくいったので今度は newlib の printf を使ってみる。syscall.c は CQ-FRK-NXP-ARM printf の時使ったものにする。(オリジナルは WinARMの中のlpc213x_lpc214x_examples_20061205.zip

コンパイル・・・・・特に問題はない。
ラン
まず、LED をトグル・・・問題ない。
Dump ・・・・あれ!おかしい。
16進表示とキャラクター表示の位置が逆だ。
Stack_Size と Heap_Size を 0x3000 にしてみる・・・変化なし
rprintf の時からこの部分は変更してないのに...

解決策が思い浮かばない。
今日のところはこの辺で勘弁しておいてやろう。

そういえば Sourcery CodeBench Lite が 2012.09-63 になっていた。

環境:CQ-LM3S3748
    + Keil MDK-ARM V4.53
    + GCC Sourcery CodeBench Lite 2012.03-56
    + KPIT Cummins GNU-Archive Editor v1.1
    + KPIT Cummins GNU-Map Viewer v1.0

CQ-LM3S3748 (11) NVIC_VTABLE2012年11月08日 21時40分22秒

NVIC_VTABLE
STM32 では USB DFU bootloader を使う時 NVIC_SetVectorTable() で Offset を指定する必要があった。今回の LM3S3748 ではそのような設定をしていないが動いている。そこで先日作成したプログラム(仮想 COM Port に Dump 出力)でレジスタを見てみることにする。

NVIC_VTABLE が 0x00001800 に設定されている。アプリケーションでは記述して無いので USB DFU bootloader が書き換えたのだろう。この方が使いやすいね。

ところで、ここで使った Memory Dump は最初 strtol() で引数を変換していたがどうしてもうまくいかなかった。調べてみると返す値が long 型だったのだ。アドレスは unsigned long 型なので仕方なく atox() を作った。手抜きをしているのでどんな文字でも強制的に変換する。また使うときがあるかもしれないのでメモしておこう。
unsigned long atox(char *str)
{
    unsigned long ret = 0;

    while(*str){
        ret = ret << 4;
        ret |= 0xf & ((*str >= 'A') ? (*str++ - '7') : *str++);
    }
    return ret;
}


ついでに dump もメモしておこう。これは rprintf とセットにしてよく使う関数だ。
void dump(unsigned long adr,unsigned int size)
{
    unsigned char *ad, data[16];
    int i, j, k;

    k = size / 16 + ((size % 16) ? 1 : 0);
    USBrprintf("\r\n");
    for(j = 0, ad = (unsigned char*)adr; j < k; j++){
        USBrprintf("%08X", (unsigned long)ad);
        for(i = 0; i < 16; i++, ad++)
            USBrprintf(" %02X", data[i] = *ad);
        USBputch(' ');
        for(i = 0; i < 16; i++)
            (data[i] >= 0x20 && data[i] < 0x80) ? USBputch(data[i]) : USBputch('.');
        USBrprintf("\r\n");
    }
}


ここで USBrprintf は rprintf の名前を変えただけ USBputch は以下のとおり。
int USBputch(int c)
{
    while(USBBufferSpaceAvailable(&g_psTxBuffer[1]) < 2);
    USBBufferWrite(&g_psTxBuffer[1], (const unsigned char *)&c, 1);
    return c;
}


環境:CQ-LM3S3748
    + Keil MDK-ARM V4.53
    + GCC Sourcery CodeBench Lite 2012.03-56
    + KPIT Cummins GNU-Archive Editor v1.1
    + KPIT Cummins GNU-Map Viewer v1.0

CQ-LM3S3748 (10) Keil µVision4 + GCC に Startup を追加2012年11月06日 21時59分42秒

LM3S3748 Ride7
Luminary Micro のスタートアップは以前作った startup_LM3Sx.s で済ませる予定だった。しかし、 CQ-LM3S3748 が手に入り、ひんぱんに新規プロジェクトを作ることになったので専用のスタートアップ startup_LM3S3748.s を用意することにする。
と思っていたら TI-CMSIS-Devices-8636.exe の中にそのものがあった。以下のハンドラを削除し(削除しなくてもいいけどね)、名前を startup_LM3S3748.s に変更して DeviceDatabase に登録しよう。
ADC1SS0_Handler
ADC1SS1_Handler
ADC1SS2_Handler
ADC1SS3_Handler
I2S0_Handler
EPI0_Handler
GPIOJ_Handler

さて、簡単に終わってしまったので今度は Raisonance Ride7 用の Startup も作ることにする。これもベースがあるのでそんなに手間ではない。

crt0_LM3S3748.s

 



あとはスクリプトを若干変更してと言いたい所だが Raisonance の FAQ に DO NOT modify the files in ....とあるのでここに出すのはやめておこう。

環境:CQ-LM3S3748
    + TI-CMSIS-Devices-8636.exe
    + Keil MDK-ARM V4.53
    + GCC Sourcery CodeBench Lite 2012.03-56
    + KPIT Cummins GNU-Archive Editor v1.1
    + KPIT Cummins GNU-Map Viewer v1.0

    + Ride7 version 7.30.10.0169
    + RKit-ARM version 1.30.10.0356

CQ-LM3S3748 (9) USB サンプルを動かしてみる2012年11月04日 17時18分26秒

USB COM PORT
デバッガが無いのでレジスタなどの値を見たいときに見ることができない。そこで printf の登場だ。
CQ-LM3S3748 の場合簡単に接続できるのは USB なので仮想 COM Port として使いそこへ出力することにする。もちろん最初から作るのは大変なのでサンプルを利用する。
使用するサンプルは SW-EK-LM3S3748-9453.exe の中の boards\ek-lm3s3748\usb_dev_cserial がちょうどよいだろう。

必要なファイル
boards\ek-lm3s3748\usb_dev_cserial
  startup_gcc.c
  usb_dev_cserial.c
  usb_dev_cserial.ld
  usb_structs.c
  usb_structs.h
  ustdlib.c
usblib\gcc-cm3
  libusb-cm3.a
driverlib\gcc-cm3
  libdriver-cm3.a
CQ-FRK-NXP-ARM (5) printf (6)ここのものを使う
  rprintf.c
  rprintf.h

Command line が用意されているので Dump を追加しメモリを見ることができるようにした。もちろんLED は port.f0 を port.g2 に変更しなければならない。あとは今回必要ない LCD への表示も削除した。

コンパイル/書き込み

LED ON/OFF 問題ない
Dump アドレスによってはフリーズする。
System Mode か何かでないとアクセスできない所があったっけ?
まあ、このくらいで勘弁しておいてやろう。

あ、そういえば先日用意した CMSIS は結局使わなかった。はっきりいってライブラリとの相性が悪いので使うのが大変だ。

環境:CQ-LM3S3748
    + TI-CMSIS-Devices-8636.exe
    + Keil MDK-ARM V4.53
    + GCC Sourcery CodeBench Lite 2012.03-56
    + KPIT Cummins GNU-Archive Editor v1.1
    + KPIT Cummins GNU-Map Viewer v1.0