nios-spi进阶实验:SPI环路用NIOS处理器生成激励数据发送、接收并验证
实验要求:
本次实验是在上一次spi自环和nios软核练习实验基础上的进阶实验。在nios软核和de0开发板之间建立spi通讯自环,用NIOS处理器生成激励数据(发送),并且用NIOS处理器读取结果数据(接收),每次发送一个数据同时接受一个数据,用软件进行验证读写是否正确。
实验的核心思想与主要问题:
本次实验的核心思想与大体架构并不复杂。只要使用nios软核充当master部分,并用IDE为nios软核写一个自动收发激励数据的c程序,连接上一次实验编译的myspi作为从机部分,构建spi通讯环路即可。然而,在实验进行过程中慢慢发现有很多难点和问题,以下是一些主要的问题:
1在实验前我查阅了很多有关spi读写通讯的博客和书籍资料,主要有stm32、sd卡等硬件设备作为从机的spi读写实验。然而这些实验都有一个共同点——每次连续发送多个数据并保存在该从机设备中,读取时也是一次性读取从机中存储的多个数据。这意味着这些实验在发送或者接受时,无需考虑时序问题。而本实验发一个数据就读一个数据就要考虑何时发送何时读取的问题。这需要使用中断来发送接收数据,或者使用nios-spi的状态寄存器来控制数据的收发,本次实验使用了后一种方法。
2使用nios作为master部分,就必须要考虑nios里sdram的clk与cpu的clk的时钟相位差。这是由于硬件本身布线造成的不可忽视的时延问题,其他实验的从机使用的大都为sd卡或stm32,而本实验使用的是de0开发板,从机硬件的不同pll的设置也不同,这直接影响nios的发送、接受数据寻址是否正确。同时nios里的spi使用何种输入clk也是一个关键问题。本次实验参考了alter友晶提供的sdramDEMO,里面给出了了de0开发板sdram与cup的时钟相位差,同时nios里的spi使用cpu-clk而非sdram-clk。
3主机与从机连接也会出现一些问题。本实验一开始用SOPC builder创建主机部分后使用block diagram文件连接从机构建自环,然后配置管脚,发现数据传输和编译都会报错。最后本实验使用Verilog代码写了一个.v文件来例化主机本分与从机部分,然后使用该例化文件直接使用Verilog代码配置管脚(管脚的配置需参考de0开发板使用手册)。
以上就是本次实验出现的一些主要问题。这些问题第一是缺乏指导资料和对应本实验要求的具体demo,不容易发现问题的原因和找寻解决方法;第二归根到底还是对nios手册和avalon-mm总线协议手册理解和学习得不够透彻导致的。所以即便本实验成功之后,仍有很多需要思考和继续改进的部分。
实验具体过程:
我们希望最终构建的spi环路如上图所示。本实验主要分为硬件设计和软件设计两大部分。硬件部分包括SOPC设计和从机主机连接、管脚分配。软件部分包括设计nios软核的自动生成激励数据并进行发送接收和验证。
一、硬件部分设计
1创建SOPC系统,生成nios软核
本实验的SOPC主要包括:CPU、 JTAG_UART、 SDRAM Controller、EPCS SerialFlash Controller、PIO、SPI、sysid、PLL。
SDRAM Controller的“presets”选择“custom”,“data widths”选择“16bits”,“addressess widths”选择12Row、8column。
CPU的“reset vector”选择“epcs controller”,“exception vector”选择“sdram”。
Pll-c0的“output clock frequency”设为“50Mhz”,“clock phase shift”设为“0ps”。
Pll-c1的“output clock frequency”设为“50Mhz”,“clock phase shift”设为“-60deg”。
本实验参考了de0的sdram-demo的SOPC设计。最终的设计如下图所示:
2建立系统顶层模块,构建spi自环并分配关键
在.v文件中分别例化nios软核和myspi从机部分,使用代码为其分配管脚和连接。(注意,连接nios与从机部分的信号必须为wire类型)。并将该文件作为工程的顶层文件。
构建完成后进行编译,此时管脚已经正确分配,查看RTL视图发现结构符合预期。
具体的Verilog代码将附在文末。
二、软件部分设计
硬件部分相对来说比较容易,只要按照de0的demo配置正确基本不会有什么问题。而软件部分设计出现的问题更多,也是本次实验耗费时间和精力的主要部分。
最开始,我只是简单地设计了一个循环来生成发送数据并进行发送和读取,然后比较两个数据验证读写是否正确,发现结果一直报错。这时我才意识到要考虑发送和接收数据的时序问题,即何时应该发送数据?何时应该读取数据?通过思考和查阅资料发现,主流的解决方法主要为两种:一是发送数据时进入中断,发送完成后等待TX发送完成中断号结束中断,然后等待RX发送接收中断后进入接收状态,等接收完成后结束中断;二是通过spi的状态寄存器控制读写。本次实验最终选择了后一种方法。
Nios-spi自带状态寄存器。其中TRDY置为1时表示TX为空,可以写入新的发送数据,此时让nios发送这一次send_data。RRDY置为1时表示RX为满,等待读取该接收数据,此时读取这一次从机发送过来的recive_data。TMT置为1时表示移位寄存器为空,程序没有进行新的发送或接收操作。参考spi手册后按照nios-spi的位域定义一个spi的结构体,可以观察发送寄存器、接收寄存器和状态寄存器各位的值。此时发送数据一直正确,然而发现接收寄存器每三次读取同一次数据,第四次读取为0,第五次才更新为上一次发送的数据。如下所示:
这个问题我的理解是,因为de0从机硬件设计中包含大量的D触发器,导致主机发送数据给从机接收时,从机需经过一段时延后才能正确读取,然后再把该数据自环发送给主机。于是我根据已经得到的时延规律,每个周期里发送四次同一数据(仍然是发送一个数据就读取一个数据),前两次读取的数据和第四次读取的数据舍弃,只保留第三次的数据作为接收数据进行验证。得到结果正确。
以上就是本次实验。然而仍有两个遗留问题没有解决:
1在通过编写的spi结构体观察寄存器状态时,发现“SPI_ADC->CONTROL.BITS.IRRDY”和“SPI_ADC->RXDATA”始终读不到数据,而通过IORD()函数来读取对应寄存器则可以正确读取。
2就是上文提到的时延问题。本实验虽然通过规律改进读写得到了正确结果,但如果只一次发送一次读取,那应该如何根据时延进行软件设计呢?改换到其他硬件设备作为从机时这个时延又会如何影响读写呢?
这就需要进一步加深对avalon-mm总线协议手册和nios-spi手册的学习和认识。希望能在接下来的学习实验过程中彻底解决以上遗留问题。
参考文献及博客:
Nios-spi手册:https://wenku.baidu.com/view/cd289d6925c52cc58bd6be50.html
用nios读写串行flash-M25P16:http://bbs.eeworld.com.cn/thread-294856-1-1.html
nios自带spi核如何编程:https://www.amobbs.com/thread-3914691-1-1.html
具体实验代码如下:
Verilog部分:
module DE0_TOP
(
//////////////////// Clock Input ////////////////////
CLOCK_50, // 50 MHz
CLOCK_50_2, // 50 MHz
//////////////////// Push Button ////////////////////
BUTTON, // Pushbutton[2:0]
//////////////////// DPDT Switch ////////////////////
SW, // Toggle Switch[9:0]
//////////////////// 7-SEG Dispaly ////////////////////
HEX0_D, // Seven Segment Digit 0
HEX0_DP, // Seven Segment Digit DP 0
HEX1_D, // Seven Segment Digit 1
HEX1_DP, // Seven Segment Digit DP 1
HEX2_D, // Seven Segment Digit 2
HEX2_DP, // Seven Segment Digit DP 2
HEX3_D, // Seven Segment Digit 3
HEX3_DP, // Seven Segment Digit DP 3
//////////////////////// LED ////////////////////////
LEDG, // LED Green[9:0]
//////////////////////// UART ////////////////////////
UART_TXD, // UART Transmitter
UART_RXD, // UART Receiver
UART_CTS, // UART Clear To Send
UART_RTS, // UART Request To Send
///////////////////// SDRAM Interface ////////////////
DRAM_DQ, // SDRAM Data bus 16 Bits
DRAM_ADDR, // SDRAM Address bus 13 Bits
DRAM_LDQM, // SDRAM Low-byte Data Mask
DRAM_UDQM, // SDRAM High-byte Data Mask
DRAM_WE_N, // SDRAM Write Enable
DRAM_CAS_N, // SDRAM Column Address Strobe
DRAM_RAS_N, // SDRAM Row Address Strobe
DRAM_CS_N, // SDRAM Chip Select
DRAM_BA_0, // SDRAM Bank Address 0
DRAM_BA_1, // SDRAM Bank Address 1
DRAM_CLK, // SDRAM Clock
DRAM_CKE, // SDRAM Clock Enable
//////////////////// Flash Interface ////////////////
FL_DQ, // FLASH Data bus 16 Bits
FL_ADDR, // FLASH Address bus 22 Bits
FL_WE_N, // FLASH Write Enable
FL_RST_N, // FLASH Reset
FL_OE_N, // FLASH Output Enable
FL_CE_N, // FLASH Chip Enable
FL_WP_N, // FLASH Hardware Write Protect
FL_BYTE_N, // FLASH Selects 8/16-bit mode
FL_RY, // FLASH Ready/Busy
//////////////////// LCD Module 16X2 ////////////////
LCD_BLON, // LCD Back Light ON/OFF
LCD_RW, // LCD Read/Write Select, 0 = Write, 1 = Read
LCD_EN, // LCD Enable
LCD_RS, // LCD Command/Data Select, 0 = Command, 1 =Data
LCD_DATA, // LCD Data bus 8 bits
//////////////////// SD_Card Interface ////////////////
SD_DAT, // SD Card Data
SD_CMD, // SD Card Command Signal
SD_CLK, // SD Card Clock
SD_WP_N, // SD Card Write Protect
//////////////////// PS2 ////////////////////////////
PS2_KBDAT, // PS2 Keyboard Data
PS2_KBCLK, // PS2 Keyboard Clock
PS2_MSDAT, // PS2 Mouse Data
PS2_MSCLK, // PS2 Mouse Clock
//////////////////// VGA ////////////////////////////
VGA_HS, // VGA H_SYNC
VGA_VS, // VGA V_SYNC
VGA_R, // VGA Red[3:0]
VGA_G, // VGA Green[3:0]
VGA_B, // VGA Blue[3:0]
//////////////////// GPIO ////////////////////////////
SS_N,SCK,MISO,MOSI,
/////////////////////////////////////////////////////////////////
GPIO0_CLKIN, // GPIO Connection 0 Clock In Bus
GPIO0_CLKOUT, // GPIO Connection 0 Clock Out Bus
GPIO0_D, // GPIO Connection 0 Data Bus
GPIO1_CLKIN, // GPIO Connection 1 Clock In Bus
GPIO1_CLKOUT, // GPIO Connection 1 Clock Out Bus
GPIO1_D // GPIO Connection 1 Data Bus
);
//////////////////////// Clock Input ////////////////////////
input CLOCK_50; // 50 MHz
input CLOCK_50_2; // 50 MHz
//////////////////////// Push Button (low-active) ////////////////////////
input [2:0] BUTTON; // Pushbutton[2:0]
//////////////////////// DPDT Switch ////////////////////////
input [9:0] SW; // Toggle Switch[9:0]
//////////////////////// 7-SEG Dispaly ////////////////////////
output [6:0] HEX0_D; // Seven Segment Digit 0
output HEX0_DP; // Seven Segment Digit DP 0
output [6:0] HEX1_D; // Seven Segment Digit 1
output HEX1_DP; // Seven Segment Digit DP 1
output [6:0] HEX2_D; // Seven Segment Digit 2
output HEX2_DP; // Seven Segment Digit DP 2
output [6:0] HEX3_D; // Seven Segment Digit 3
output HEX3_DP; // Seven Segment Digit DP 3
//////////////////////////// LED ////////////////////////////
output [9:0] LEDG; // LED Green[9:0]
//////////////////////////// UART ////////////////////////////
output UART_TXD; // UART Transmitter
input UART_RXD; // UART Receiver
output UART_CTS; // UART Clear To Send
input UART_RTS; // UART Request To Send
/////////////////////// SDRAM Interface ////////////////////////
inout [15:0] DRAM_DQ; // SDRAM Data bus 16 Bits
output [12:0] DRAM_ADDR; // SDRAM Address bus 13 Bits
output DRAM_LDQM; // SDRAMLow-byte Data Mask
output DRAM_UDQM; // SDRAM High-byte Data Mask
output DRAM_WE_N; // SDRAM Write Enable
output DRAM_CAS_N; // SDRAM Column Address Strobe
output DRAM_RAS_N; // SDRAM Row Address Strobe
output DRAM_CS_N; // SDRAM Chip Select
output DRAM_BA_0; // SDRAM Bank Address 0
output DRAM_BA_1; // SDRAM Bank Address 1
output DRAM_CLK; // SDRAM Clock
output DRAM_CKE; // SDRAM Clock Enable
//////////////////////// Flash Interface ////////////////////////
inout [15:0] FL_DQ; // FLASH Data bus 16 Bits
output [21:0] FL_ADDR; // FLASH Address bus 22 Bits
output FL_WE_N; // FLASH Write Enable
output FL_RST_N; // FLASH Reset
output FL_OE_N; // FLASH Output Enable
output FL_CE_N; // FLASH Chip Enable
output FL_WP_N; // FLASH Hardware Write Protect
output FL_BYTE_N; // FLASH Selects 8/16-bit mode
input FL_RY; // FLASH Ready/Busy
//////////////////// LCD Module 16X2 ////////////////////////////
inout [7:0] LCD_DATA; // LCD Data bus 8 bits
output LCD_BLON; // LCD Back Light ON/OFF
output LCD_RW; // LCD Read/Write Select, 0 = Write, 1 = Read
output LCD_EN; // LCD Enable
output LCD_RS; // LCD Command/Data Select, 0 = Command, 1 =Data
//////////////////// SD Card Interface ////////////////////////
inout SD_DAT; // SDCard Data 0
inout SD_CMD; // SD Card Command Signal
output SD_CLK; // SD Card Clock
input SD_WP_N; // SD Card Write Protect
//////////////////////// PS2 ////////////////////////////////
inout PS2_KBDAT; // PS2 Keyboard Data
inout PS2_KBCLK; // PS2 Keyboard Clock
inout PS2_MSDAT; // PS2 Mouse Data
inout PS2_MSCLK; // PS2 Mouse Clock
//////////////////////// VGA ////////////////////////////
output VGA_HS; // VGA H_SYNC
output VGA_VS; // VGA V_SYNC
output [3:0] VGA_R; // VGA Red[3:0]
output [3:0] VGA_G; // VGA Green[3:0]
output [3:0] VGA_B; // VGA Blue[3:0]
//////////////////////// GPIO ////////////////////////////////
input [1:0] GPIO0_CLKIN; // GPIO Connection 0 Clock In Bus
output [1:0] GPIO0_CLKOUT; // GPIO Connection 0 Clock Out Bus
inout [31:0] GPIO0_D; // GPIO Connection 0 Data Bus
input [1:0] GPIO1_CLKIN; // GPIO Connection 1 Clock In Bus
output [1:0] GPIO1_CLKOUT; // GPIO Connection 1 Clock Out Bus
inout [31:0] GPIO1_D; // GPIO Connection 1 Data Bus
output SS_N,SCK,MISO,MOSI;
//=======================================================
// REG/WIRE declarations
//=======================================================
//=======================================================
// Structural coding
//=======================================================
wire system_reset_n;
assign system_reset_n = 1'b1;
assign FL_RST_N = system_reset_n;
assign FL_WP_N = 1'b1; // notwrite protect
assign FL_BYTE_N = 1'b1; // 16-bitmode
wire FLASH_16BIT_IP_A0;
wire SS_N_W,SCK_W;
wire MISO_W,MOSI_W;
assign SS_N = SS_N_W;
assign SCK = SCK_W;
assign MISO = MISO_W;
assign MOSI = MOSI_W;
DE0_SOPC DE0_SOPC_inst(
// 1) global signals:
.clk(CLOCK_50),
.pll_cpu(),
.pll_sdram(DRAM_CLK),
.reset_n(system_reset_n),
// the_buttons
.in_port_to_the_buttons(BUTTON),
// the_switches
.in_port_to_the_switches(SW),
// the_seg7
.out_port_from_the_seg7({HEX3_DP, HEX3_D, HEX2_DP, HEX2_D, HEX1_DP,HEX1_D, HEX0_DP, HEX0_D}),
// the_lcd
.LCD_E_from_the_lcd(LCD_EN),
.LCD_RS_from_the_lcd(LCD_RS),
.LCD_RW_from_the_lcd(LCD_RW),
.LCD_data_to_and_from_the_lcd(LCD_DATA),
.out_port_from_the_lcd_light(LCD_BLON),
// the_leds
.out_port_from_the_leds(LEDG),
// the_sd_clk
.out_port_from_the_sd_clk(SD_CLK),
// the_sd_cmd
.bidir_port_to_and_from_the_sd_cmd(SD_CMD),
// the_sd_dat
.bidir_port_to_and_from_the_sd_dat(SD_DAT),
// the_sd_wp_n
.in_port_to_the_sd_wp_n(SD_WP_N),
// the_sdram
.zs_addr_from_the_sdram(DRAM_ADDR),
.zs_ba_from_the_sdram({DRAM_BA_1,DRAM_BA_0}),
.zs_cas_n_from_the_sdram(DRAM_CAS_N),
.zs_cke_from_the_sdram(DRAM_CKE),
.zs_cs_n_from_the_sdram(DRAM_CS_N),
.zs_dq_to_and_from_the_sdram(DRAM_DQ),
.zs_dqm_from_the_sdram({DRAM_UDQM,DRAM_LDQM}),
.zs_ras_n_from_the_sdram(DRAM_RAS_N),
.zs_we_n_from_the_sdram(DRAM_WE_N),
//the_tristate_bridge_avalon_slave (16-bit mode)
.address_to_the_cfi_flash({FL_ADDR, FLASH_16BIT_IP_A0}),
.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),
// the_uart
.cts_n_to_the_uart(UART_CTS),
.rts_n_from_the_uart(UART_RTS),
.rxd_to_the_uart(UART_RXD),
.txd_from_the_uart(UART_TXD),
// the_spi
.MOSI_from_the_spi(MOSI_W),
.SCLK_from_the_spi(SCK_W),
.SS_n_from_the_spi(SS_N_W),
.MISO_to_the_spi(MISO_W)
);
MYSPI SPI_SLAYER(
.nrst(system_reset_n),
.clk(CLOCK_50),
.ncs(SS_N_W),
.mosi(MOSI_W),
.miso(MISO_W),
.sck(SCK_W)
);
endmodule
module MYSPI(
nrst ,
clk ,
ncs ,
mosi ,
miso ,
sck );
input clk, nrst;
input ncs, mosi, sck;
output miso;
reg[2:0] sck_edge;
reg[7:0] byte_received;
reg[3:0] bit_received_cnt;
reg rec_flag;
reg[1:0] rec_status; //SPI接收部分状态机
reg[7:0] rec_data;
reg[2:0] rec_flag_width; //SPI接收完成标志位脉冲宽度寄存器
reg miso;
reg sending_flag; //正在发送标志位
reg[7:0] byte_sended; //发送移位寄存器
reg[3:0] bit_sended_cnt; //SPI发送位计数器
reg[1:0] send_status; //SPI发送部分状态机
wire sck_riseedge,sck_falledge;
assign sck_riseedge =(sck_edge[2:1] == 2'b01); //检测到SCK由0变成1,则认为发现上跳沿
assign sck_falledge = (sck_edge[2:1]== 2'b10); //检测到SCK由1变成0,则认为发现下跳沿
always @ (posedge clk or negedgenrst) begin
if(~nrst) begin
sck_edge <= 3'b000;
end
else begin
sck_edge <= {sck_edge[1:0],sck};
end
end
always @ (posedge clk or negedgenrst) begin
if(~nrst) begin
byte_received <= 8'h00;
bit_received_cnt <= 4'h0;
rec_flag <= 1'b0;
rec_status <= 2'b00;
rec_flag_width <= 3'b000;
end
else begin
if(~ncs) begin
if(~sending_flag) begin
case (rec_status)
2'b00: begin
if(sck_riseedge) begin
byte_received <={byte_received[6:0], mosi};
if(bit_received_cnt ==4'b0111) begin
bit_received_cnt <=4'b0000;
rec_status <=2'b01;
end
else begin
bit_received_cnt <=bit_received_cnt+1;
end
end
end
2'b01: begin
rec_data <=byte_received;
rec_flag <= 1'b1;
if(rec_flag_width==3'b100)begin
rec_flag_width <=3'b000;
rec_status <=2'b11;
end
else begin
rec_flag_width <=rec_flag_width+1;
end
end
2'b11: begin
rec_flag <= 1'b0;
rec_status <= 2'b00;
end
endcase
end
end
end
end
always @ (posedge clk or negedgenrst) begin
if(~nrst) begin
byte_sended <= 8'h00;
bit_sended_cnt <= 4'b0000;
send_status <= 2'b00;
sending_flag <= 1'b0;
end
else begin
if(~ncs)
begin
case (send_status)
2'b00: begin
if(rec_flag== 1'b1) begin
sending_flag<= 1'b1;
byte_sended <= rec_data;
send_status <=2'b01;
end
end
2'b01: begin
if(sck_riseedge) begin
//miso <=byte_sended[7];
send_status <=2'b11;
end
end
2'b11: begin
miso<= byte_sended[7];
if(sck_falledge) begin
byte_sended <={byte_sended[6:0], 1'b0};
if(bit_sended_cnt ==4'b0111) begin
send_status <=2'b10;
bit_sended_cnt <=4'b0000;
sending_flag <=1'b0;
end
else begin
bit_sended_cnt <=bit_sended_cnt+1;
//send_status <=2'b01;
end
end
end
2'b10: begin
//sending_flag<= 1'b0;
send_status <= 2'b00;
miso <= 1'b0;
end
endcase
end
end
end
endmodule
c语言部分:
#include"stdio.h"
#include"unistd.h"
#include"system.h"
#include"io.h"
#include"altera_avalon_spi.h"
#include"altera_avalon_pio_regs.h"
#include"altera_avalon_spi_regs.h" //定义了SPI寄存器的基本信息
#include"alt_types.h" //Altera自定义的一些数据类型
#include"string.h"
typedefstruct{
volatileunsignedlongint RXDATA;
volatileunsignedlongint TXDATA;
union{
struct{
volatileunsignedlongint NC :3;
volatileunsignedlongint ROE :1;
volatileunsignedlongint TOE :1;
volatileunsignedlongint TMT :1;
volatileunsignedlongint TRDY :1;
volatileunsignedlongint RRDY :1;
volatileunsignedlongint E :1;
volatileunsignedlongint NC1 :23;
}BITS;
volatileunsignedlongint WORD;
}STATUS;
union{
struct{
volatileunsignedlongint NC :3;
volatileunsignedlongint IROE :1;
volatileunsignedlongint ITOE :1;
volatileunsignedlongint NC1 :1;
volatileunsignedlongint ITRDY :1;
volatileunsignedlongint IRRDY :1;
volatileunsignedlongint IE :1;
volatileunsignedlongint NC2 :1;
volatileunsignedlongint SSO :21;
}BITS;
volatileunsignedlongint CONTROL;
}CONTROL;
unsignedlongint RESERVED0;
unsignedlongint SLAVE_SELECT;
}SPI_ADC_T;
#define SPI_ADC ((SPI_ADC_T *) SPI_BASE)//SPI_ADC_BASE是在system.h里产生的地址
void send_data(alt_u8 data)
{
while(!SPI_ADC->STATUS.BITS.TRDY);
//printf("0x%x\n",SPI_ADC->TXDATA);
IOWR(SPI_BASE, 5, 1);
IOWR(SPI_BASE , 1, data);
while(!SPI_ADC->STATUS.BITS.TMT);
//printf("SENDDATA=0x%x\n",SPI_ADC->TXDATA);
IOWR(SPI_BASE, 5, 0);
}
alt_u8 read_data()
{
alt_u8 data;
while(!(IORD(SPI_BASE, 2)&0x80));
IOWR(SPI_BASE, 5, 1);
data = IORD(SPI_BASE, 0);
//printf("READDATA=0x%x\n",data);
//printf("RXDATA=0x%x\n",SPI_ADC->RXDATA);
IOWR(SPI_BASE, 5, 0);
return data;
}
int main(void)
{
alt_u8 i;
alt_u8 buf;
alt_u8 check;
// IOWR(SPI_BASE, 5, 1);
// IOWR(SPI_BASE , 1, 0xc7);
// IOWR(SPI_BASE, 5, 0);
printf("--------start spi!----------\n");
for(i=0;i<63;i++)
{
int cnt = 500;
alt_u8 status;
status = IORD(SPI_BASE, 2);
printf("status = 0x%x\n",status);
buf = (alt_u8)i+1;
int j;
for(j = 0;j < 2;j++)
{
send_data(buf);
status = IORD(SPI_BASE, 0);
printf("false_read = 0x%x\n",status);
}
send_data(buf);
status = IORD(SPI_BASE, 2);
printf("status = 0x%x\n",status);
//printf("RRDY=%d\n",SPI_ADC->STATUS.BITS.RRDY);
check = read_data();
while(cnt--);
if(check == buf)
{
printf("----time %d is right! buf = %d,check = %d!----\n",i,buf,check);
}
else
{
printf("----time %d is false! buf = %d,check = %d!----\n",i,buf,check);
}
send_data(buf);
check = read_data();
}
return 0;
}