Upload
takefumi-miyoshi
View
981
Download
5
Embed Size (px)
Citation preview
MicroBoardのSPI ROMからMicroBlazeのプログラムを読んで起動する話
イーツリーズ/わさらぼ三好 健文
やること1) MicroBlaze大きなプログラムを実行したい
← BlockRAMにのらない/外部メモリで実行2) プログラムは自動的に実行を開始したい
← ROMからプログラムを読んで実行したい3) MicroBoardにはQSPI FlashROMが載ってる4) Xilinx AR#55026にSPIからのブートローダが5) MicroBoardでも試してみよう
手順概要1) MicroBlazeシステムを構築2) QSPIをシステムに追加3) トップのHDLを作成.#HOLDの処置を追加4) UCFを記述5) ローダーとアプリケーションプログラムを用意6) ローダーをBlockRAMに埋め込む7) アプリケーションプログラムを分割8) MCSファイルを作る
MicroBlazeシステムを構築/概要● ISEからプロジェクトを作る● BSBで基本システムを作成
– 入力クロック66.666667MHz– CPU動作周波数66MHz– 使用デバイスを追加
● DDR3(後でLPDDRに設定するけど)● LED(GPIO出力)● DIPスイッチ(GPIO入力)● UART(ボーレート115200に)
● 細かなパラメタ調整
MicroBlazeシステムを構築(1)ISEプロジェクトを作成コンテクストメニューからNew Sourceを選択
New Sourceとして追加するのはEmbedded Processor名前はお好みで
XPS起動直後にBSB Wizardを使うか?と聞かれるので”YES”を選択
MicroBlazeシステムを構築(2)PLBじゃなくてAXIを使う(デフォルトのままいじらない)
周波数は66.666667MHzリセットはActive HIGH
● CPUの動作周波数は66MHz● 周辺デバイスに下記を追加
● MCB_DDR3● LED(GPIO, 4bit)● DIPスイッチ(GPIO, 4bit)● UART(115200, Interruptあり)
MicroBlazeシステムを構築(3)● 入出力ポートの設定
– LEDとDIPスイッチが8bitなので4bit([0:3])に修正– クロック入力は差動じゃないので削除して新規作成
BSBで4bitと指定したのに,[0:7]になっていたので[0:3]に修正
差動クロックは削除
新たにクロック入力ピンを生成clock_generator_0_CLKIN_pinになった
MicroBlazeシステムを構築(4)● MIGでメモリの設定
– DDR3をLPDDRにする– メモリはMT46H32M16XXXX-5を選択– ほかはデフォルトでOK
MCB_DDR3をダブルクリックしてMIGを起動
LPDDRを選択MT46H32M16XXXX-5を選択
MicroBlazeシステムを構築(5)● メモリ用のクロックを200MHzに設定する
clock_generator_0をダブルクリック
メモリの動作周波数が600MHzになっている
200MHzに設定する
MicroBlazeシステムを構築(6)● ブロックRAMのサイズを32KBにする
microblaze_0_d_bram_ctrlとmicroblaze_0_i_bram_ctrlのそれぞれの設定ダイアログを開いて
LMB BRAM High Addressを0x00007fffに設定
設定の確認は”Addresses”タブで
QSPI ROMをシステムに追加/概要● IP CatalogでAXI Quad SPI Interfaceを選択● FIFO Depthを16,SCK Ratioを2に設定● microblaze_0(作ったCPU)にぶら下げる● 外部クロックをCLKOUT2に設定● 必要なポートを外部ピンに設定する● ここまで完了したらNetlistを作る
QSPI ROMをシステムに追加(1)
AXI Quad SPI InterfaceIPコアを選択
名前をQSPI_FLASHに決めた(何でもいい)
microblaze_0に接続(デフォルト) モジュール(QSPI_FLASH)が追加できた
FIFO Depth=16,SCK Ratio=2に設定
QSPI ROMをシステムに追加(2)● SPIクロックのソースをCLKOUT2に設定● IOピンを外部に引き出す
“Ports”タブでポートの設定をする - EXT_SPI_CLKにclock_generator_0のCLKOUT2を接続 - SCK, SS, IO0, IO1, SPISELを外部ポートに指定
終わったら,確認がてらNetlistを作成しておく
トップのHDLを作成/概要● ISEに戻ってトップモジュールのHDLを生成● SSELは常に'1'にする● #HOLD用の信号を追加.常に'1'を出力
作成したEmbedded Processorを選択して
Create top HDL Sourceをダブルクリック
トップモジュール(のVHDLコード)がプロジェクトに追加された
トップのHDLを作成(1)● SSELは常に'1'にする
– 外部ポートのQSPI_FLASH_SPISEL_pinを削除– port map は QSPI_FLASH_SPISEL_pin => '1',
● #HOLD用の信号を追加.常に'1'を出力– QSPI_FLASH_HOLD : out std_logic を追加– QSPI_FLASH_HOLD <= '1'; とか
後述のbootloaderプログラムではSPIモードでROMにアクセスします#HOLD (D3)を'1'にしていないと,データが読めません!!
UCFの記述● いつも通り.メモリは書かなくていいから楽
NET RS232_Uart_1_sout LOC = T7 | IOSTANDARD = LVCMOS33;NET RS232_Uart_1_sin LOC = R7 | IOSTANDARD = LVCMOS33;NET RESET LOC = V4 | IOSTANDARD = LVCMOS33 | TIG | PULLDOWN;NET LEDS_TRI_O<0> LOC = P4 | IOSTANDARD = LVCMOS18;NET LEDS_TRI_O<1> LOC = L6 | IOSTANDARD = LVCMOS18;NET LEDS_TRI_O<2> LOC = F5 | IOSTANDARD = LVCMOS18;NET LEDS_TRI_O<3> LOC = C2 | IOSTANDARD = LVCMOS18;NET DIP_Switches_TRI_I<0> LOC = B3 | IOSTANDARD = LVCMOS33;NET DIP_Switches_TRI_I<1> LOC = A3 | IOSTANDARD = LVCMOS33;NET DIP_Switches_TRI_I<2> LOC = B4 | IOSTANDARD = LVCMOS33;NET DIP_Switches_TRI_I<3> LOC = A4 | IOSTANDARD = LVCMOS33;NET clock_generator_0_CLKIN_pin LOC = K15 | IOSTANDARD = LVCMOS33;NET QSPI_FLASH_SCK_pin LOC = R15 | IOSTANDARD = LVCMOS33;NET QSPI_FLASH_SS_pin LOC = V3 | IOSTANDARD = LVCMOS33;NET QSPI_FLASH_IO0_pin LOC = T13 | IOSTANDARD = LVCMOS33;NET QSPI_FLASH_IO1_pin LOC = R13 | IOSTANDARD = LVCMOS33;
NET QSPI_FLASH_HOLD LOC = V14 | IOSTANDARD = LVCMOS33;
NET "clock_generator_0_CLKIN_pin" TNM_NET = clock_generator_0_CLKIN_pin;TIMESPEC TS_clock_generator_0_CLKIN_pin = PERIOD clock_generator_0_CLKIN_pin 66666 kHz;
### Set Vccaux for S6LX9 MicroBoard to 3.3V ###CONFIG VCCAUX = "3.3" ;
ローダーとアプリケーションを用意● Xilinx #AR55026からいただいてくる● このローダーはアプリケーションプログラムの
サイズを埋め込む必要があるので注意– REST_SECTION_BYTE_NUM
● DDRメモリの名前が違うので修正– xparameters.hを参照– XPAR_DDR3_SDRAM_S_AXI_BASEADDR を
XPAR_MCB_DDR3_S0_AXI_BASEADDRに変更● ローダーは全セクションをBRAMに割り当てる
– lscript.ldでタブから選べばいい
ブートローダーの中身● SPIメモリにアクセスするための初期化● SPIメモリからプログラムを読んでDDRメモリ
に書く● 書き終わったら,DDRメモリの先頭(プログラ
ム開始アドレス)にジャンプする
ブートローダーの中身(抜粋).../* * Read the rest_section data from flash. */for(i=0; i<(REST_SECTION_BYTE_NUM/16)+1; i++){ Status = SpiFlashRead(&Spi, (REST_SECTION_START_ADDR+16*i), 16, COMMAND_RANDOM_READ); if(Status != XST_SUCCESS) { return XST_FAILURE; } for(k=0; k<16; k++) *destination_location++ = ReadBuffer[k+4];}/* * Read the vector_section data from flash. */for(i=0; i<(VECTOR_SECTION_BYTE_NUM/16)+1; i++){ Status = SpiFlashRead(&Spi, (VECTOR_SECTION_START_ADDR+16*i), 16, COMMAND_RANDOM_READ); if(Status != XST_SUCCESS) { return XST_FAILURE; } for(k=0; k<16; k++) *reset_location++ = ReadBuffer[k+4];}xil_printf("user application load succeed!\r\n");boot_app = (int (*) (void)) XPAR_DDR3_SDRAM_S_AXI_BASEADDR;boot_app();...
ローダーをBlockRAMに埋め込む● data2memを実行すればよい● SDKで作ったelfファイルをプロジェクトに登録してGenerate Programming FileでOK
elfをプロジェクトに登録
Generate Programming Fileを実行なお,初回登録時は”?”状態になるがelfを変更しても状態は変更ず生成済状態のままなので注意!!
内部ではdata2memが実行されるbitファイルは上書きではなく別に生成される.注意!!
アプリケーションを分割/概要● アプリケーションプログラムの空間はでかい
– ベクタ関連のセクション(0x00000000-0x0000004f)
– プログラムデータ(DDRのアドレス)● そのままだと大量の無駄な領域が必要● 分割して個別にバイナリイメージ化する
アプリケーションを分割(1)
C:\WORK\images>mb-objcopy -O binary -j .vectors.reset ^ -j .vectors.sw_exception -j .vectors.interrupt -j .vectors.hw_exception ^ user_application.elf vector_section.bin
● ISEなコマンドプロンプトシェルで作業– ベクタセクションだけをとりだす
– ベクタセクション以外を取り出す
– ここで作成したrest_section.binのサイズをbootloader.cのREST_SECTION_BYTE_NUMに設定
C:\WORK\images> mb-objcopy -O binary -R .vectors.reset ^ -R .vectors.sw_exception -R .vectors.interrupt -R .vectors.hw_exception ^ user_application.elf rest_section.bin
アプリケーションを分割(2)● 実行例
MCSファイルを作成/概要● FPGAのbitファイルとアプリケーションを
MCSにまとめる– FPGAのbitファイルは0番地から– アプリケーションプログラムは0xb00000から– ベクタ領域は0xc0000から– 開始位置を変更したければbootloader.cを修正
● iMPACTでもコマンドラインでもOK
MCSファイルを作成(1)
C:\WORK\images>promgen -spi ^ -w -p mcs -u 0 download.bit ^ -data_file up b00000 rest_section.bin^ -data_file up c00000 vector_section.bin
● 次のコマンドを実行すればよい
作ったらROMに書く
起動● 動いた.● 読み出しデータを表示してみたところ
まとめ● AR#55026をMicroBlazeで試してみた● 動いた,やったね!!● 今更ISE?
– まあSpartan6使わなきゃなこともあるし● 次は,
– 自己書き換え,かな– SDKのサンプルの様にS形式を解釈する?