SPI_flash代码分析以下是主函数intmain(void){Xuint8send_data[16],recv_data[16];Xuint8error,SF_sr;Xuint16sector_select,page_select;Xuint32i,j;xil_printf(SerialFlashTest\r\n);/*初始化FLASH_SPI控制器*///1、初始化SPI//2、设这控制寄存器CR为主MASTERtransactioninhibitdisable,人工选择从设备以及设置SPI为master//3、初始化SSR(从设备选择寄存器)为不选择任何一个从设备。Initialize_Spi_Controller(XPAR_SPI_FLASH_BASEADDR);/*使能SPI控制器*///Description:设置SPICR寄存器的SPISystemEnable位//1、设置SPE=1,SPISYSTEMENABLEXSpi_Set_Enable(XPAR_SPI_FLASH_BASEADDR);/*设置FLASH的WRSR寄存器,设置成功说明FLASH控制已经OK*/do{//设置FLASH以使FLASH任何一部分都受保护protectedSF_write_status_register(XPAR_SPI_FLASH_BASEADDR,0x7c);SF_sr=SF_read_status_register(XPAR_SPI_FLASH_BASEADDR);}while(SF_sr!=0x7C);/*设置FLASH的WRSR寄存器,使能Allsector可写*/do{//设置FLASH以使FLASH任何一部分都不受保护protectedSF_write_status_register(XPAR_SPI_FLASH_BASEADDR,0x00);SF_sr=SF_read_status_register(XPAR_SPI_FLASH_BASEADDR);}while(SF_sr!=0x00);/*整片擦除*/xil_printf(\r\nChipEraseStarting\r\n);SF_bulk_erase(XPAR_SPI_FLASH_BASEADDR);xil_printf(ChipEraseComplete-verifying\r\n);/*整片校验看是不是全0XFF*/SF_start_read(XPAR_SPI_FLASH_BASEADDR,0x00,0x00,0x00,SCK_FASTER_THAN_20MHz);error=0;for(i=0;iSF_BYTES/16;i++){/*每次接收16个字节校验*/spi_transfer(XPAR_SPI_FLASH_BASEADDR,send_data,recv_data,16);for(j=0;j16;j++){if(recv_data[j]!=0xFF){xil_printf(Errorati=%x,j=%x\r\n,i,j);j=16;i=SF_BYTES;error=1;}}}if(!error)xil_printf(Eraseverified\r\n);SF_end_read(XPAR_SPI_FLASH_BASEADDR);/*SPIFLASHpage编程*/xil_printf(\r\nDatabeingwritten\r\n);for(sector_select=0;sector_selectSF_SECTORS;sector_select++)for(page_select=0;page_selectSF_PAGES_PER_SECTOR;page_select++){/*发送page编程命令*/SF_start_page_program(XPAR_SPI_FLASH_BASEADDR,sector_select,page_select,0x00);for(i=0;iSF_BYTES_PER_PAGE;i+=16){for(j=0;j16;j++)send_data[j]=i+j;/*每次发送16个字节*/spi_transfer(XPAR_SPI_FLASH_BASEADDR,send_data,recv_data,16);}SF_end_page_program(XPAR_SPI_FLASH_BASEADDR);}xil_printf(TestDataWritten;readingback\r\n,i);/*SPIFLASH读取数据进行验证*/SF_start_read(XPAR_SPI_FLASH_BASEADDR,0x00,0x00,0x00,SCK_FASTER_THAN_20MHz);error=0;for(i=0;iSF_BYTES;i+=16){/*每次读取16个字节进行验证*/spi_transfer(XPAR_SPI_FLASH_BASEADDR,send_data,recv_data,16);for(j=0;j16;j++){if(recv_data[j]!=((i+j)&0xFF)){xil_printf(Errorati=%x,j=%x\r\n,i,j);xil_printf(Datareadwas%x\r\n,recv_data[j]);xil_printf(Exp.datawas%x\r\n,(i+j));j=16;i=SF_BYTES;error=1;}}}if(!error)xil_printf(FlashTestPASSED!\r\n);elsexil_printf(Flashtestfailed!\r\n);SF_end_read(XPAR_SPI_FLASH_BASEADDR);return0;}接下来我们一句一句话分析主函数main()1、Initialize_Spi_Controller(XPAR_SPI_FLASH_BASEADDR);以下是这个函数的定义#defineInitialize_Spi_Controller(BaseAddress)\{\XSpi_WriteReg(BaseAddress,XSP_SRR_OFFSET,XSP_SRR_RESET_MASK);\XSpi_WriteReg(BaseAddress,XSP_CR_OFFSET,INIT_CREG);\XSpi_WriteReg(BaseAddress,XSP_SSR_OFFSET,SPI_NONE_SELECT);\}这三句话分别代表的含义是:XSpi_WriteReg(BaseAddress,XSP_SRR_OFFSET,XSP_SRR_RESET_MASK);代表初始化FPGA内部SPI接口的resetregister,即重置FPGA内部SPI接口。以下是关于寄存器SRR的描述。通过文档《xps_spi.pdf》有关SRR的描述,只能向SRR中写入0x0000000A.XSpi_WriteReg(BaseAddress,XSP_CR_OFFSET,INIT_CREG);代表初始化FPGA内部的SPI接口中的控制寄存器controlregister,以下是关于CR控制寄存器的描述写入的值为#defineINIT_CREG(XSP_CR_TRANS_INHIBIT_MASK|XSP_CR_MANUAL_SS_MASK|XSP_CR_MASTER_MODE_MASK)代表禁止FPGA内部的SPI接口传输数据,人工选择从设备,FPGA内部的SPI接口为主设备masterXSpi_WriteReg(BaseAddress,XSP_SSR_OFFSET,SPI_NONE_SELECT);以下是SSR寄存器的描述。:初始化FPGA内部的SPI接口中的slaveselectregister,写入的值为不选择任何一个从设备。2、XSpi_Set_Enable(XPAR_SPI_FLASH_BASEADDR);以下是该函数的定义#defineXSpi_Set_Enable(BaseAddress)\{\Xuint16Control;\Control=XSpi_ReadReg(BaseAddress,XSP_CR_OFFSET);\Control|=XSP_CR_ENABLE_MASK;\XSpi_WriteReg(BaseAddress,XSP_CR_OFFSET,Control);\}该函数代表重新初始化Controlregister,以使能FPGA内部的SPI接口可用即将控制寄存器CR中的SPE位置1。3、do{//设置FLASH以使FLASH任何一部分都受保护protectedSF_write_status_register(XPAR_SPI_FLASH_BASEADDR,0x7c);SF_sr=SF_read_status_register(XPAR_SPI_FLASH_BASEADDR);}while(SF_sr!=0x7C);首先分析SF_write_status_register(XPAR_SPI_FLASH_BASEADDR,0x7c);该函数的定义为:voidSF_write_status_register(Xuint32BaseAddress,Xuint8data){Xuint8op_code[2],bogus_data[2];//设置SPIFlash的写使能SF_write_enable(BaseAddress);//选中第一个设备使能SPI_FLASH_CS_LOW();//写SPIFLASH的状态寄存器op_code[0]=WRSR;op_code[1]=data;spi_transfer(BaseAddress,op_code,bogus_data,2);//关闭选中设备以使任何一个设备都没有选中SPI_FLASH_CS_HIGH();//等待写寄存器/编程/擦除命令操作结束poll_until_complete(BaseAddress);//设置SPIFlash的写不使能SF_write_disable(BaseAddress);}这个函数的功能主要是要将data的值写入到STATUSREGISTER中去。下面是有关WRSR指令的描述和时序,从中可以看出,在执行WRSR之前,必须首先要执行一下WREN指令,然后将ChipSelect选中置0,这样之后才能执行,等将指令发送到FLASH后就得将具ChipSelect置1以使flash无效,进入自身的theself-timedwritestatusregistercycle。具体的查看其数据手册。接下来分析函数SF_write_enable(BaseAddress);该函数的定义为:voidSF_write_enable(Xuint32BaseAddress){Xuint8op_code=WREN,bogus_data;//选中第一个设备使能。SPI_FLASH_CS_LOW();//发送写使能命令spi_transfer(BaseAddress,&op_code,&bogus_data,1);//关闭选中设备以使任何一个设备都没有选中SPI_FLASH_CS_HIGH();}首先该函数选中第一个从设备也就是我们这个FLASH。接下来我们分析函数spi_transfer(BaseAddress,&op_code,&bogus_data,1);该函数的定义为:voidspi_transfer(Xuint32BaseAddress,Xuint8*send,Xuint8*recv,Xuint8num_bytes){Xuint8NumBytesRcvd=0;Xuint8NumBytesSent=0;//把发送的数据写入到SPI控制器的发送FIFO中while(num_bytes--){XSpi_WriteReg(BaseAddress,XSP_DTR_OFFSET,*send++);NumBytesSent++;}//设置SPICR