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/