【真OO无双】如何在Nios II對Flash進行讀寫
Abstract
在DE2版子上,除了8MB的SDRAM最大外,排名第2的就是4MB的Flash,本文討論如何在Nios II對Flash進行讀寫。
Introduction
使用環境:Quartus II 8.0 + Nios II EDS 8.0 + DE2(Cyclone II EP2C35F627C6) or DE2-70 (Cyclone II EP2C70F896C6N)
我曾經在(原創) 如何在Nios II使用Zip File System? (IC Design) (Nios II) (DE2)與(原創) 如何讓Nios II一Power On就執行? (SOC) (Nios II) (SOPC Builder) (DE2) (DE2-70)討論對flash的使用,不過那只能算是『應用』,並未真的用HAL去存取過flash,剛好網友成電王超提到用HAL讀寫flash的問題,我就順手測試了一下。
以DE2_NIOS_Lite 1.2為範本
我使用(原創) DE2_NIOS_Lite 1.2 (SOC) (Nios II) (SOPC Builder) (DE2)為範本測試flash,這個SOPC已經將flash ip掛好,所以我們可以將重點放在HAL部分,不過考量有些人是自己建立SOPC系統,還是討論一下SOPC部分。
SOPC Builder部分
Step 1:
掛上Tristate Bridge與Flash Memory(CFI)
tep 2:
設定Flash Parameter & Timing
Top Module部分
DE2_NIOS_Lite.v / Verilog
1 /* 2 (C) OOMusou 2008 http://oomusou.cnblogs.com 3 4 Filename : DE2_NIOS_Lite.v 5 Compiler : Quartus II 8.0 + ModelSim-Altera 6.1g 6 Description : DE2_NIOS lite version 1.2 7 Release : 08/08/2008 1.0 8 */ 9 10 module DE2_NIOS_Lite ( 11 input CLOCK_50, // On Board 50 MHz 12 input [3:0] KEY, // Pushbutton[3:0] 13 input [17:0] SW, // Toggle Switch[17:0] 14 output [8:0] LEDG, // LED Green[8:0] 15 output [17:0] LEDR, // LED Red[17:0] 16 output [6:0] HEX0, // Seven Segment Digit 0 17 output [6:0] HEX1, // Seven Segment Digit 1 18 output [6:0] HEX2, // Seven Segment Digit 2 19 output [6:0] HEX3, // Seven Segment Digit 3 20 output [6:0] HEX4, // Seven Segment Digit 4 21 output [6:0] HEX5, // Seven Segment Digit 5 22 output [6:0] HEX6, // Seven Segment Digit 6 23 output [6:0] HEX7, // Seven Segment Digit 7 24 inout [15:0] DRAM_DQ, // SDRAM Data bus 16 Bits 25 output [11:0] DRAM_ADDR, // SDRAM Address bus 12 Bits 26 output DRAM_LDQM, // SDRAM Low-byte Data Mask 27 output DRAM_UDQM, // SDRAM High-byte Data Mask 28 output DRAM_WE_N, // SDRAM Write Enable 29 output DRAM_CAS_N, // SDRAM Column Address Strobe 30 output DRAM_RAS_N, // SDRAM Row Address Strobe 31 output DRAM_CS_N, // SDRAM Chip Select 32 output DRAM_BA_0, // SDRAM Bank Address 0 33 output DRAM_BA_1, // SDRAM Bank Address 0 34 output DRAM_CLK, // SDRAM Clock 35 output DRAM_CKE, // SDRAM Clock Enable 36 inout [7:0] FL_DQ, // FLASH Data bus 8 Bits 37 output [21:0] FL_ADDR, // FLASH Address bus 22 Bits 38 output FL_WE_N, // FLASH Write Enable 39 output FL_RST_N, // FLASH Reset 40 output FL_OE_N, // FLASH Output Enable 41 output FL_CE_N, // FLASH Chip Enable 42 inout [15:0] SRAM_DQ, // SRAM Data bus 16 Bits 43 output [17:0] SRAM_ADDR, // SRAM Address bus 18 Bits 44 output SRAM_UB_N, // SRAM Low-byte Data Mask 45 output SRAM_LB_N, // SRAM High-byte Data Mask 46 output SRAM_WE_N, // SRAM Write Enable 47 output SRAM_CE_N, // SRAM Chip Enable 48 output SRAM_OE_N // SRAM Output Enable 49 ); 50 51 wire CPU_CLK; 52 wire CPU_RESET; 53 54 assign FL_RST_N = 1'b1; 55 56 Reset_Delay u0 ( 57 .iRST(KEY[0]), 58 .iCLK(CLOCK_50), 59 .oRESET(CPU_RESET) 60 ); 61 62 SDRAM_PLL u1 ( 63 .inclk0(CLOCK_50), 64 .c0(DRAM_CLK), 65 .c1(CPU_CLK) 66 ); 67 68 nios_ii u2 ( 69 .clk(CPU_CLK), 70 .clk_50(CLOCK_50), 71 .reset_n(CPU_RESET), 72 // KEY 73 .in_port_to_the_key_pio(KEY), 74 // SW 75 .in_port_to_the_sw_pio(SW), 76 // LEDG 77 .out_port_from_the_ledg_pio(LEDG), 78 // LEDR 79 .out_port_from_the_ledr_pio(LEDR), 80 // SEG7 81 .oSEG0_from_the_seg7(HEX0), 82 .oSEG1_from_the_seg7(HEX1), 83 .oSEG2_from_the_seg7(HEX2), 84 .oSEG3_from_the_seg7(HEX3), 85 .oSEG4_from_the_seg7(HEX4), 86 .oSEG5_from_the_seg7(HEX5), 87 .oSEG6_from_the_seg7(HEX6), 88 .oSEG7_from_the_seg7(HEX7), 89 // SDRAM 90 .zs_addr_from_the_sdram(DRAM_ADDR), 91 .zs_ba_from_the_sdram({DRAM_BA_1,DRAM_BA_0}), 92 .zs_cas_n_from_the_sdram(DRAM_CAS_N), 93 .zs_cke_from_the_sdram(DRAM_CKE), 94 .zs_cs_n_from_the_sdram(DRAM_CS_N), 95 .zs_dq_to_and_from_the_sdram(DRAM_DQ), 96 .zs_dqm_from_the_sdram({DRAM_UDQM,DRAM_LDQM}), 97 .zs_ras_n_from_the_sdram(DRAM_RAS_N), 98 .zs_we_n_from_the_sdram(DRAM_WE_N), 99 // SRAM 100 .SRAM_ADDR_from_the_sram(SRAM_ADDR), 101 .SRAM_CE_N_from_the_sram(SRAM_CE_N), 102 .SRAM_DQ_to_and_from_the_sram(SRAM_DQ), 103 .SRAM_LB_N_from_the_sram(SRAM_LB_N), 104 .SRAM_OE_N_from_the_sram(SRAM_OE_N), 105 .SRAM_UB_N_from_the_sram(SRAM_UB_N), 106 .SRAM_WE_N_from_the_sram(SRAM_WE_N), 107 // FLASH 108 .address_to_the_cfi_flash(FL_ADDR), 109 .data_to_and_from_the_cfi_flash(FL_DQ), 110 .read_n_to_the_cfi_flash(FL_OE_N), 111 .select_n_to_the_cfi_flash(FL_CE_N), 112 .write_n_to_the_cfi_flash(FL_WE_N) 113 ); 114 115 endmodule
107行 // FLASH .address_to_the_cfi_flash(FL_ADDR), .data_to_and_from_the_cfi_flash(FL_DQ), .read_n_to_the_cfi_flash(FL_OE_N), .select_n_to_the_cfi_flash(FL_CE_N), .write_n_to_the_cfi_flash(FL_WE_N) 連接SOPC關於flash部分的接腳。 54行 assign FL_RST_N = 1'b1;
這是大家常忽略的,記得將FL_RST_N設為1'b1。
使用HAL對Flash做讀寫
hello_world.c / C
1 /* 2 (C) OOMusou 2008 http://oomusou.cnblogs.com 3 4 Filename : hello_world.c 5 Compiler : Nios II EDS 8.0 / ANSI C 6 Description : Demo how to read / write CFI-Flash 7 Release : 10/19/2008 1.0 8 */ 9 10 #include <stdio.h> 11 #include "system.h" // CFI_FLASH_NAME 12 #include "sys/alt_flash.h" // flash HAL 13 14 int main() { 15 alt_flash_fd *fd; 16 int i, j, return_code; 17 i = 10; 18 j = 9; 19 20 // open flash 21 fd = alt_flash_open_dev(CFI_FLASH_NAME); 22 23 if (!fd) { 24 printf("alt_flash_open_dev error\n"); 25 return -1; 26 } 27 28 // write flash 29 return_code = alt_write_flash(fd, 0, &i, sizeof(int)); 30 if (return_code) { 31 printf("alt_write_flash error\n"); 32 return -1; 33 } 34 35 // read flash 36 return_code = alt_read_flash(fd, 0, &j, sizeof(int)); 37 if (return_code) { 38 printf("alt_read_flash error\n"); 39 return -1; 40 } 41 42 // compare input & output 43 if (i == j) 44 printf("i=%d, j=%d, flash read / write OK\n", i, j); 45 else 46 printf("i=%d, j=%d, flash read / write error\n", i, j); 47 48 // close flash 49 alt_flash_close_dev(fd); 50 51 return 0; 52 } 53
執行結果
11行 #include "system.h" // CFI_FLASH_NAME #include "sys/alt_flash.h" // flash HAL system.h記載著SOPC周邊的資訊,sys/alt_flash.h則記載著存取flash的HAL。 20行 // open flash fd = alt_flash_open_dev(CFI_FLASH_NAME); 開啟flash。 28行 // write flash return_code = alt_write_flash(fd, 0, &i, sizeof(int)); 將變數i寫入flash。 35行 // read flash return_code = alt_read_flash(fd, 0, &j, sizeof(int)); 從flash讀出資料到變數j。 42行 // compare input & output if (i == j) printf("i=%d, j=%d, flash read / write OK\n", i, j); else printf("i=%d, j=%d, flash read / write error\n", i, j); 比較i與j的值是否相等,若相等表示read/write正常。 48行 // close flash alt_flash_close_dev(fd);
關閉flash。
完整程式碼下載
DE2_NIOS_Lite_12_flash.7z (for DE2)
DE2_70_NIOS_10_flash.7z (for DE2-70)
Conclusion
事實上Altera還提供了其他對flash存取的HAL,以Quartus II 8.0而言,位於C:\altera\80\nios2eds\components\altera_hal\HAL\inc\sys\alt_flash.h,讀者可自行參考。
DE2-70與DE2類似,就不另外討論,只有SOPC Builder的Flash paramters & timing不太一樣,只提供source code供讀者研究。
See Also
(原創) 如何在Nios II使用Zip File System? (IC Design) (Nios II) (DE2)
(原創) 如何讓Nios II一Power On就執行? (SOC) (Nios II) (SOPC Builder) (DE2) (DE2-70)
(原創) 如何解決No CFI table found at address的錯誤訊息? (SOC) (Nios II) (DE2)
Reference
徐光輝 等著 2006,基於FPGA的嵌入式開發與應用,電子工業出版社