目次
前
次
マイコン選定
2007年から死蔵になっているマイコンMSP430を使います。
トランジスタ技術2007年1月号の付録に、TIのマイコン
MSP430F4270が同梱されていました。
シリアルインタフェースがないというので、放置でしたが
テスト基板を半田付けして使います。
WindowsXPマシンでクロスコンパイルした後、JTAGを使い
gdbによるファームウエアのダウンロードが必要とわかり
インタフェースを作成。
半田付けした基板は、以下。
トランジスタ技術で紹介されていたJTAGのインタフェース
回路では、74HC244を利用。
74HC244の手持ちがなかったので、74LS367を使いました。
電源は、外付けにします。
74HC244は、ピンの並び方が嫌いなので、最も使いたくない
ICということもあります。
1990年頃からマイコンを扱っていれば、+5V電源は
ありふれていて、手持ちがあったので電源を外付けに。
回路図は、以下。
電源には、Zennerダイオードと整流ダイオードを利用した
簡易タイプとしています。
トランジスタ技術の回路では、74HC244を利用して電源電圧を
生成していました。この種類の回路では、不安定で動作しない
経験をしているので、外部電源を使う仕様に。
3.3V電源は、MSP430のJTAGで使うので外部電源5Vから
簡易回路で生成しています。
動作テスト用に作成したプログラムは、以下。
#include "hardware.h"
void init_io(void);
void main(void)
{
/* initialize I/O */
init_io();
/* enter LPM0 and enable global interrupt (loop) */
_BIS_SR(LPM0_bits | GIE);
}
/* Interrupt Service Routine(Timer A0) */
interrupt (TIMERA0_VECTOR) Timer_A(void)
{
P5OUT ^= 0x01; /* inverse */
}
void init_io(void)
{
/* stop WDT */
WDTCTL = WDTPW | WDTHOLD;
/* output -> P5.0 (pin number 26) */
P5DIR |= 0x01 ;
/* 0 -> P5.0 (pin number 26) */
P5OUT &= ~0x01 ;
/* enable CCR0 interrupt */
CCTL0 = CCIE;
/* initialize compare match register 0 */
CCR0 = 20000;
/*
clock source : ACLK
mode : up counter
*/
TACTL = TASSEL_1 | MC_1;
}
トランジスタ技術の記事を参考にしましたが、出力レジスタ、方向レジスタ
の使い方で?と思うところがあり、自分がいつも使っているスタイルで記述
しました。
組込み関係のプログラムは、初期化後、無限ループに入り
割込みによるイベントで、必要な仕事を実現するのが定石。
MSP430では、無限ループのかわりに、LowPowerModeに入り
割込みによるイベントで、必要な仕事を実現するのが定石
のようです。
レジスタの指定ビットをセット、リセットして、論理和で
結合ではなく、和で計算というのが定石のよう。
レジスタの指定ビットのセット、リセットの後には
論理和で合成という方式に慣れているので、いつも
の論理和を使いました。
タイマーAのコンペアマッチ割込みで、割込みハンドラである
関数Timer_Aを起動。関数Timer_Aの中で、出力値を反転して
LEDの点滅を例としてます。
Timer_Aは、アップカウントモードとし、カウント値が
レジスタCCR0と一致したなら、リセットと割込み発生
になるようにしました。
MSP430のカウンタは、3モードをもち、その中のひとつ
アップカウントを利用しました。
割込み発生で、Low Power Modeの状態から6usで起動し
関数Timer_Aを実行します。割込みハンドラでの作業が
終了すると、再びLow Power Modeの状態に遷移。
P5.0(26番ピン)に、抵抗を介してLEDを接続。
LEDの点滅で、動作を確認できました。
ソースコードには、ヘッダファイルが含まれてます。
ヘッダファイルの内容は、以下。
#ifndef HARDWARE_H
#define HARDWARE_H
#include <io.h>
#include <signal.h>
#include <iomacros.h>
#endif //HARDWARE_H
Unix系のコンパイラでは、割込みはsignalで処理するので
そのためのヘッダファイルを指定。レジスタのアドレスや
よく利用する定数等は、io、iomacrosのヘッダファイルで
指定しています。
コンパイル、リンクは、最初、次のmakefileを定義し
makeを入力しましたが、うまくいきませんでした。
tst0.elf : tst0.o
msp430-gcc -mmcu=msp430x4270 -o tst0.elf tst0.o
tst0.o : tst0.c hardware.h
msp430-gcc -g -O0 -mmcu=msp430x4270 -Wno-main -c tst0.c
WindowsのDOS窓を利用しているので、バッチファイルで対応。
バッチファイルの内容は、以下。
del *.o
del *.elf
msp430-gcc -g -O0 -mmcu=msp430x4270 -Wno-main -c tst0.c
msp430-gcc -mmcu=msp430x4270 -o tst0.elf tst0.o
コンパイルのオプションで「-g」を入れて、デバッグのgdbを
使えるようにしています。
どんなアセンブリ言語に変換されるのかを、コンパイルオプション「-S」
で指定して、生成させてみました。
.file "tst0.c"
.arch msp430x4270
.text
.p2align 1,0
.global main
.type main,@function
/***********************
* Function `main'
***********************/
main:
/* prologue: frame size = 0 */
.L__FrameSize_main=0x0
.L__FrameOffset_main=0x4
mov #(__stack-0), r1
mov r1,r4
/* prologue end (size=3) */
call #init_io
/* #APP */
bis #llo(24), r2
/* #NOAPP */
/* epilogue: frame size=0 */
br #__stop_progExec__
/* epilogue end (size=4) */
/* function main size 11 (4) */
.Lfe1:
.size main,.Lfe1-main
/********* End of function ******/
.p2align 1,0
.global Timer_A
.global vector_ffec
.type Timer_A,@function
/***********************
* Interrupt Service Routine `Timer_A' at 0xffec
***********************/
vector_ffec:
Timer_A:
/* prologue: frame size = 0 */
.L__FrameSize_Timer_A=0x0
.L__FrameOffset_Timer_A=0x4
push r5
push r4
/* prologue end (size=2) */
xor.b #llo(1), &0x0031
/* epilogue: frame size=0 */
pop r4
pop r5
reti
/* epilogue end (size=3) */
/* function Timer_A size 7 (2) */
.Lfe2:
.size Timer_A,.Lfe2-Timer_A
/********* End of function ******/
.p2align 1,0
.global init_io
.type init_io,@function
/***********************
* Function `init_io'
***********************/
init_io:
/* prologue: frame size = 0 */
.L__FrameSize_init_io=0x0
.L__FrameOffset_init_io=0x4
push r5
push r4
/* prologue end (size=2) */
mov #llo(23168), &0x0120
bis.b #llo(1), &0x0032
bic.b #llo(1),&0x0031
mov #llo(16), &0x0162
mov #llo(20000), &0x0172
mov #llo(272), &0x0160
/* epilogue: frame size=0 */
pop r4
pop r5
ret
/* epilogue end (size=3) */
/* function init_io size 21 (16) */
.Lfe3:
.size init_io,.Lfe3-init_io
/********* End of function ******/
/*********************************************************************
* File tst0.c: code size: 39 words (0x27)
* incl. words in prologues: 7, epilogues: 10
*********************************************************************/
アセンブリ言語の内容から、Cで利用するフレーム領域には
レジスタr4、r5を割り当て。この2つのレジスタをフレーム
ポインタに使用と理解できます。
コンパイラの生成するアセンブリ言語コードは、コンパクトで
プロセッサの特徴を活用した、SRAMの容量が少なくても動作に
支障がないとわかります。
gdbを起動する前に、msp430-gdbproxyを起動させるという
Unix系のデバッガでは「お約束」の操作で動きました。
msp430-gdbproxyは、DOSプロンプトから起動。
msp430-gdbproxy msp430 LPT1{enter}
msp430-gdbも、DOSプロンプトから起動。
msp430-gdb tst0.elf{enter}
JTAGインタフェースとMSP430の基板は、16ピンケーブルで
接続し、PCとJTAGインタフェースは、パラレルケーブルで
接続しています。
MSP430のファームウエアをダウンロードするため
gdbの方で次のコマンドを入力。
gdbでは、他に次の4コマンドを加えると、大抵の
デバッグができます。
- s (step)
- n (next)
- b (set break point)
- p (print)
gdb、gdb-proxyによりMSP430の内部レジスタの値を参照できるので
Program Counter、Stack Pointer、Status等を見れば、どんなこと
が起きたのかを確認できます。
break pointをソースコード上で指定できる他、ステップ動作で1行
1行の処理結果を確認して、不具合がどこで発生しているのか特定
しやすくなりました。
古いマイコン基板でも、充分動くことが
わかったので、次の作業に移ります。
MSP430F4270は、ROMが16kバイト、RAMが256バイトで
RAM容量が少ない印象です。
目次
前
次