"Spartan6でmicroblaze mcs を動かす②SDK編"までの手順を行うと、シリアルポートからhellow worldを喋るテンプレートが生成されます。
hellow worldを喋ったところで何もうれしくないので、プログラムを少し変更してみます。
#プログラムの動作仕様
- 最初にスタートメッセージを発する
- メインループは何もしない
- UART受信割り込みを検出したら、割り込みハンドラに飛ぶ
- 割り込みハンドラ内で受信した文字(押したキー)を判定する
- エンターキーを押した場合、8bitのLED(GPO)をインクリメントする
- バックスペースキーを押した場合、8bitのLED(GPO)をデクリメントする
- UART受信文字をエコーバック(そのままUART送信に返す)
以上の動作を満たすCのコードを書いてみます。
Cソース
#include "platform.h" //とりあえず必要
#include "mb_interface.h" //とりあえず必要
#include "ADR_MAP.h" //自前のヘッダファイル
//ASCIIコードのバイナリ定義
#define BS 0x08 //バックスペース
#define CR 0x0D //復帰
#define LF 0x0A //改行
#define ESC 0x1B //エスケープ
//-----------------------------
//グローバル変数
//-----------------------------
unsigned char g_led=0;
//-------------------------------------------------------------------------------
//割込みハンドラ
//-------------------------------------------------------------------------------
void Int_Handl(void) {
unsigned char msg;
//割り込みフラグ落とす
IRQ_ACK = 0xFFFFFFFF;
//受信文字を持ってくる
msg=UART_RX;
//エコーバック
xil_printf("%c",msg);
//受信文字に応じた処理
switch(msg){
case CR://エンター
//LEDをインクリメント
g_led++;
GPO1=g_led;
break;
case BS://バックスペース
//LEDをデクリメント
g_led--;
GPO1=g_led;
break;
default://
//なにもしない
break;
}//switch
}
//============================================================
//メインループ
//============================================================
void main()
{
//ハードの初期化
init_platform();
//割込みハンドラの登録
microblaze_register_handler((XInterruptHandler)Int_Handl,(void*)0);
//使用する割込み選択(bit[2]⇒UART割り込み)
IRQ_ENABLE = 0x00000004;
//割り込みを有効にする
microblaze_enable_interrupts();
xil_printf("*******************\r");
xil_printf("Start!!!!!\r");
xil_printf("*******************\r");
//メインループ
while(1){
}
}
ヘッダーファイル
今回使用しているレジスタは、UART_RX
と GPO1
だけです。
#ifndef ADR_MAP_H_
#define ADR_MAP_H_
#define UART_RX (*(volatile unsigned int *) 0x80000000)
#define UART_TX (*(volatile unsigned int *) 0x80000004)
#define UART_STATUS (*(volatile unsigned int *) 0x80000008)
#define GPO1 (*(volatile unsigned int *) 0x80000010)
// #define GPO2 (*(volatile unsigned int *) 0x80000014)
// #define GPO3 (*(volatile unsigned int *) 0x80000018)
// #define GPO4 (*(volatile unsigned int *) 0x8000001C)
#define GPI1 (*(volatile unsigned int *) 0x80000020)
// #define GPI2 (*(volatile unsigned int *) 0x80000024)
// #define GPI3 (*(volatile unsigned int *) 0x80000028)
// #define GPI4 (*(volatile unsigned int *) 0x8000002C)
#define IRQ_STATUS (*(volatile unsigned int *) 0x80000030)
#define IRQ_ENABLE (*(volatile unsigned int *) 0x80000038)
#define IRQ_ACK (*(volatile unsigned int *) 0x8000003C)
//MicroBraze_mcs のIOバスは 0xC000_0000 が先頭アドレス
#endif
ビルド
SDK でctrl+B を押すとプログラムをビルドします。
Debug
フォルダにelfファイルが生成されます。
#プログラムの書き込み時の注意事項
いよいよプログラムを書き込みます。
今回使用しているSpartan6 ATLYSボードは、FPGAの書き込みデータ(bitファイル)をimpactで書き込む際に "PROG"と表記されているUSBコネクタから書き込みできます。
しかし、SDKからプログラムのアップロードをする場合には、エラーになってしまいます。(私の環境では)
XilinxのFPGAライター(Platform Cable USB Ⅱ)を使用している場合は問題なく書き込みできています。
#プログラムの書き込み
Program FPGA
ボタンを押します
項目|指定するデータ
---|---|---
Bitstream|ISEで生成したbitファイルを指定します
BMM File|SDKのワークディレクトリ内に作成したハードウェアプロジェクトディレクトリにあるもの(LOC情報を追記したもの)を指定します
ELF File|SDKでビルド完了後に生成されたelfファイルを指定します
あとは "Program"ボタンを押すと、回路データ(bitファイル)とソフトウェア(elfファイル)を合成したデータがFPGAに転送され、
プログラムが走ります。
動作確認
Tera Termを使用しシリアルポートを立ち上げておきます。
ATLYSボードでは"UART"と書いてあるJ17コネクタにmicro USBを接続することでCOMポートとして認識します。
TeraTermからエンターやバックスペースを押すと無事にLED点灯位置が応答していました。