技術コラム

Efinix / Sapphire SoC Config用SPI Flashのアクセス方法

作成者:mou-mou

本記事の情報はEfinity 2022.2.322.2.14およびEfinity RISC-V Embedded Software IDE v2022.2.3の使用を前提に書いております。

ポイント

・Config用SPI Flashへアクセスするには

  - コンパイル時に「Config後にFlashをPower Downにしない」設定をする

  - あるいは、Flashアクセス時にPower Downを解除する必要がある

・SPIのポートはRegister Optionを有効にしてかつポートにdelay制約を与える

では、詳細について説明していきます。

Efinix Efinityにおいて、Sapphire SoC IPを生成すると、色々なデモ用のプロジェクトが生成されます。その中に、spiWriteFlashDemoとspiReadFlashDemoがあります。

spiReadFlashDemoは0x380000番地から124*1024バイトの領域をリードしてコンソール(UART)へ出力しています。

spiWriteFlashDemoは0x380000番地から256バイトの領域に0x00から0xFFを書き込んでいます。

そこでReadのサイズは大きすぎるのでWriteとあわせて256byteに変更して、spiReadFlashDemoとspiWriteFlashDemoを順に実行してみました。

spiReadFlashDemoのmain.cを修正

//#define ReadSize      124*1024
#define ReadSize        256

spiWriteFlashDemoを実行

spi 0 flash write start !
Time out
WR Addr 00380000 := 00000000
WR Addr 00380001 := 00000001
WR Addr 00380002 := 00000002
WR Addr 00380003 := 00000003
WR Addr 00380004 := 00000004
・
・
・
・
WR Addr 003800fc := 000000fc
WR Addr 003800fd := 000000fd
WR Addr 003800fe := 000000fe
WR Addr 003800ff := 000000ff
Time out
spi 0 flash write end !

spiReadFlashDemoを実行

spi 0 flash read start !
Addr 00380000 := 000000ff
Addr 00380001 := 000000ff
Addr 00380002 := 000000ff
Addr 00380003 := 000000ff
・
・
・
・
Addr 003800fc := 000000ff
Addr 003800fd := 000000ff
Addr 003800fe := 000000ff
Addr 003800ff := 000000ff
spi 0 flash read end !

書き込めていないように見えます。

Efinityのプロジェクトを確認してみます。File -> Edit Project から Bitstream Generation タブを開くと Power down flash after programmingにディフォルトで☑がついています。

Configが終わると、FlashはPower Downモードに移行する設定となっています。

チェックを外してコンパイルしたものを書き込むと、今度はRead -> Writeが正常にできました。

spiReadFlashDemo -> spiWriteFlashDemo を再度実行

spi 0 flash read start !
Addr 00380000 := 00000000
Addr 00380001 := 00000001
Addr 00380002 := 00000002
Addr 00380003 := 00000003
・
・
・
・
Addr 003800fc := 000000fc
Addr 003800fd := 000000fd
Addr 003800fe := 000000fe
Addr 003800ff := 000000ff
spi 0 flash read end !

読み出しデータが化けている場合は、SPIポートの制約漏れの可能性があります。Sapphire SoCのIP生成時T120F324_devkitのサンプルプロジェクトを出力します。

Sapphire SoC IP Configuration

constraints.sdc

#SPI Constraints
#################
set_output_delay -clock io_systemClk -max -4.700 [get_ports {system_spi_0_io_sclk_write}]
set_output_delay -clock io_systemClk -min -2.571 [get_ports {system_spi_0_io_sclk_write}]
set_output_delay -clock io_systemClk -max -4.700 [get_ports {system_spi_0_io_ss}]
set_output_delay -clock io_systemClk -min -2.571 [get_ports {system_spi_0_io_ss}]
set_input_delay -clock io_systemClk -max 6.168 [get_ports {system_spi_0_io_data_0_read}]
set_input_delay -clock io_systemClk -min 3.084 [get_ports {system_spi_0_io_data_0_read}]
set_output_delay -clock io_systemClk -max -4.700 [get_ports {system_spi_0_io_data_0_write}]
set_output_delay -clock io_systemClk -min -2.571 [get_ports {system_spi_0_io_data_0_write}]
set_output_delay -clock io_systemClk -max -4.707 [get_ports {system_spi_0_io_data_0_writeEnable}]
set_output_delay -clock io_systemClk -min -2.567 [get_ports {system_spi_0_io_data_0_writeEnable}]
set_input_delay -clock io_systemClk -max 6.168 [get_ports {system_spi_0_io_data_1_read}]
set_input_delay -clock io_systemClk -min 3.084 [get_ports {system_spi_0_io_data_1_read}]
set_output_delay -clock io_systemClk -max -4.700 [get_ports {system_spi_0_io_data_1_write}]
set_output_delay -clock io_systemClk -min -2.571 [get_ports {system_spi_0_io_data_1_write}]
set_output_delay -clock io_systemClk -max -4.707 [get_ports {system_spi_0_io_data_1_writeEnable}]
set_output_delay -clock io_systemClk -min -2.567 [get_ports {system_spi_0_io_data_1_writeEnable}]

生成されたサンプルプロジェクトを開くとSDCファイルがふくまれており、SPIに関連するポートの制約が記述されておりますので、これと同じ制約を与えます。

また、それだけではset_input_delayとset_output_delayは有効になりません。Interface designerで上記の制約を与えたポートに対してRegister Optionを”Register”に、そしてClockをSapphire SoCのクロックに設定します。

Interface Designer

アクセスする頻度が少ないなら、都度Power Downモードを解除して、Read/Write後に再びPower Downモード に移行する方法もあります。

spiWriteFlashDemoのmain.c に Release power down処理 と Power down 処理を追加

void ReleasePowerDown(void)
{
    spi_select(SPI, 0);
    //Release power down
    spi_write(SPI, 0xAB);
    spi_diselect(SPI, 0);
}

void PowerDown(void)
{
    spi_select(SPI, 0);
    //Power down
    spi_write(SPI, 0xB9);
    spi_diselect(SPI, 0);
}

void main() {
    init();
    int i,len;
    len = ReadSize;

    bsp_printf("spi 0 flash read start ! \r\n");
    ReleasePowerDown();
    bsp_uDelay(5);
    for(i=StartAddress;i<StartAddress+len;i++)
    {
    	・
    	・
    	・
    }
    PowerDown();
    bsp_printf("spi 0 flash read end ! \r\n");
    while(1){}
}

spiReadFlashDemoのmain.c に Release power down 処理と Power down 処理を追加

void ReleasePowerDown(void)
{
    spi_select(SPI, 0);
    //Release power down
    spi_write(SPI, 0xAB);
    spi_diselect(SPI, 0);
}

void PowerDown(void)
{
    spi_select(SPI, 0);
    //Power down
    spi_write(SPI, 0xB9);
    spi_diselect(SPI, 0);
}

void main() {
    init();
    int i,len;
    u8 out;
    //page write
    len =256;   
    bsp_printf("spi 0 flash write start ! \r\n");
    ReleasePowerDown();
    bsp_uDelay(5);
    GlobalUnlock();
    	・
    	・
    	・
    	・
    GlobalLock();
    PowerDown();
    bsp_printf("spi 0 flash write end ! \r\n");
    while(1){}
}

Winbond社のデータシートに tRES1 : 3us(min)とあるので、Power Down解除後に5usのウエイトをいれています。

トラックバックURL

URL:https://rightxlight.co.jp/technical/efinix-spi-flash/trackback/

よく読まれている記事はこちら

ソフトウェアからハードウェアまで、
まずはお気軽にご相談下さい。

お電話はこちら

お電話はこちら 06-6309-7782

受付時間:9:00~18:00(土日祝は除く)

メールフォームからはこちら

お問い合わせお問い合わせ

Copyright (C) Since 2011 RIGHTxLIGHT Co., Ltd. All Rights Reserved.

PAGE TOP