xilisf: Created new minor version.

This patch deprecates the xilisf_v5_2 and created new
minor version xilisf_v5_3.

Signed-off-by: P L Sai Krishna <lakshmis@xilinx.com>
This commit is contained in:
P L Sai Krishna 2015-05-29 13:00:04 +05:30 committed by Nava kishore Manne
parent 159e188d9d
commit dbff6b1fe4
31 changed files with 19632 additions and 0 deletions

View file

@ -0,0 +1,58 @@
###############################################################################
#
# Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
#
# Modification History
#
# Ver Who Date Changes
# ----- ---- -------- -----------------------------------------------
# 2.04a sdm 08/01/11 Added new parameter for Numonyx quad flash devices.
# 3.00a srt 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
# Added support to SST flash.
# 3.00a srt 02/06/13 Changed the serial flash family options to include
# Spansion flash (CR 696379).
# 5.1 sb 12/23/14 Added Micron to the serial flash family options.
#
##############################################################################
OPTION psf_version = 2.1;
BEGIN LIBRARY xilisf
OPTION drc = isf_drc;
OPTION copyfiles = all;
OPTION REQUIRES_OS = (standalone xilkernel);
OPTION APP_LINKER_FLAGS = "-Wl,--start-group,-lxilisf,-lxil,-lgcc,-lc,--end-group";
OPTION desc = "Xilinx In-system and Serial Flash Library";
OPTION VERSION = 5.3;
OPTION NAME = xilisf;
PARAM name = serial_flash_family, desc = "Indicates the Serial Flash family type. Enter 1 for ATMEL. 2 for INTEL. 3 for STM (M25PXX). 4 for Winbond. 5 for Spansion / Micron. 6 for SST Flash", type = int, default = 1;
PARAM name = serial_flash_interface, desc = "Indicates the Serial Flash Interface. Enter 1 for AXI SPI. 2 for PS SPI. 3 for PS QSPI.", type = int, default = 1;
END LIBRARY

View file

@ -0,0 +1,191 @@
###############################################################################
#
# Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
#
# Modification History
#
# Ver Who Date Changes
# ----- ---- -------- -----------------------------------------------
# 2.01a sdm 06/17/10 Updated to support axi_spi
# 2.02a sdm 09/24/10 updated to use Tcl commands instead of unix commands
# 2.03a sdm 04/17/11 Updated to support axi_quad_spi
# 2.04a sdm 08/01/11 Added new parameter for Numonyx quad flash devices.
# 3.00a srt 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
# Added support to SST flash.
# 3.02a srt 05/13/13 Removed compiler errors when not selecting proper
# interface for Zynq. (CR 716451)
#
##############################################################################
#---------------------------------------------
# ISF_drc - check system configuration and make sure
# all components to run ISF are available.
#---------------------------------------------
proc isf_drc {libhandle} {
puts "Running DRC for XilIsf library... \n"
# find the list of xps or opb spi cores
set sw_processor [hsi::get_sw_processor]
set processor [hsi::get_cells [common::get_property HW_INSTANCE $sw_processor]]
set spi_periphs_list [get_spi_periphs $processor]
if { [llength $spi_periphs_list] == 0 } {
set cpuname [common::get_property NAME $processor]
error "ERROR: No SPI core is addressable from processor $cpuname. \
XilIsf library requires a SPI Core \n"
return
}
}
proc get_spi_periphs {processor} {
set periphs_list [::hsi::utils::get_proc_slave_periphs $processor]
set spi_periphs_list {}
global spi_periphs_name_list
set spi_periphs_name_list {}
foreach periph $periphs_list {
set periphname [common::get_property IP_NAME $periph]
if {$periphname == "xps_spi"
|| $periphname == "opb_spi"
|| $periphname == "xps_insystem_flash"
|| $periphname == "axi_spi"
|| $periphname == "axi_quad_spi"
|| $periphname == "ps7_spi"
|| $periphname == "ps7_qspi"} {
lappend spi_periphs_list $periph
lappend spi_periphs_name_list $periphname
}
}
return $spi_periphs_list
}
#--------
# Check the following h/w requirements for XilIsf:
#--------
proc isf_hw_drc {libhandle spi_list} {
}
# SPI hw requirements
proc isf_spi_hw_drc {libhandle spi} {
}
proc generate {libhandle} {
}
#-------
# post_generate: called after generate called on all libraries
#-------
proc post_generate {libhandle} {
xgen_opts_file $libhandle
}
#-------
# execs_generate: called after BSP's, libraries and drivers have been compiled
# This procedure builds the libisf.a library
#-------
proc execs_generate {libhandle} {
}
proc xgen_opts_file {libhandle} {
# Open xparameters.h file
set file_handle [::hsi::utils::open_include_file "xparameters.h"]
# -----------------------------
# Generate Flash options
# -----------------------------
puts $file_handle "/* Xilinx EDK In-system and Serial Flash Library (XilIsf) User Settings */"
set serial_flash_family [common::get_property CONFIG.serial_flash_family $libhandle]
puts $file_handle "\#define XPAR_XISF_FLASH_FAMILY $serial_flash_family"
set serial_flash_interface [common::get_property CONFIG.serial_flash_interface $libhandle]
set ifaceselect 0
set ps7qspi 0
global spi_periphs_name_list
foreach periph $spi_periphs_name_list {
if {$periph == "axi_spi" || $periph == "axi_quad_spi"
|| $periph == "opb_spi"
|| $periph == "xps_insystem_flash"
|| $periph == "xps_spi"} {
if {$serial_flash_interface == 1} {
puts $file_handle "\#define XPAR_XISF_INTERFACE_AXISPI 1"
set ifaceselect 1
}
} elseif {$periph == "ps7_spi" &&
$serial_flash_interface == 2} {
puts $file_handle "\#define XPAR_XISF_INTERFACE_PSSPI 1"
set ifaceselect 1
} elseif {$periph == "ps7_qspi" &&
$serial_flash_interface == 3} {
puts $file_handle "\#define XPAR_XISF_INTERFACE_PSQSPI 1"
set ifaceselect 1
} elseif {$periph == "ps7_qspi"} {
set ps7qspi 1
}
}
if {$ps7qspi == 1 && $ifaceselect == 0} {
puts "WARN: Improper Flash Interface from BSP Settings!!!! Defaulting on 'ps7_qspi' interface"
puts $file_handle "\#define XPAR_XISF_INTERFACE_PSQSPI 1"
}
puts $file_handle ""
close $file_handle
# Copy the include files to the include directory
set srcdir [file join src include]
set dstdir [file join .. .. include]
# Create dstdir if it does not exist
if { ! [file exists $dstdir] } {
file mkdir $dstdir
}
# Get list of files in the srcdir
set sources [glob -join $srcdir *.h]
# Copy each of the files in the list to dstdir
foreach source $sources {
file copy -force $source $dstdir
}
}

View file

@ -0,0 +1,556 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xilisf_atmel_buffer_rdwr_example.c
*
*
* This file contains a design example using the Xilinx In-system and Serial
* Flash Library (XilIsf). This example shows the Buffer Write, Buffer to Page
* Program with Built-in Erase, Page to Buffer Transfer and Buffer Read features.
*
* This example
* - Writes to a SRAM page buffer using Buffer Write feature
* - Erase a Page and data is transferred to this page from the SRAM page buffer
* using the Buffer to Page Program with Built-in Erase feature.
* - Transfers the data to a SRAM Page using Page to Buffer Transfer feature.
* - Reads back the Buffer that is written using the Buffer Read feature and
* compares the data.
*
* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash
* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is 264 for
* Default addressing mode and 256 in Power-of-2 addressing mode.
*
* For AT45DB161D/AT45DB321D the Bytes Per Page (ISF_PAGE_SIZE) is 528 for
* Default addressing mode and 512 in Power-Of-2 addressing mode.
*
* For AT45DB642D the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default
* addressing mode and 1024 in Power-Of-2 addressing mode.
*
* The ISF_PAGE_SIZE should be defined by the user according to the Device used.
*
* For further details of each device refer to the Spartan-3AN Serial Flash User
* Guide and data sheets of Atmel AT45XXXD .
*
* This example has been tested with the In-system Flash Memory available on the
* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board.
*
* @note
*
* None.
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- ---------------------------------------------------
* 1.00a ksu/sdm 03/22/08 First release
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Serial Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Page size of the Serial Flash.
*/
#define ISF_PAGE_SIZE 264
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define TEST_ADDRESS 0xA3600
#define ISF_TEST_BYTE 0x28 /* Test Byte offset value written to Serial
Flash */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy();
static int SetupInterruptSystem(XSpi *SpiPtr);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that the
* are initialized to zero each time the program runs.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress; /* State of Spi Transfer */
static int ErrorCount; /* Errors occurred during Spi transfers */
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
/*****************************************************************************/
/**
*
* Main function to execute the Atmel Serial Flash Buffer Read/Write example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
u16 Index;
XIsf_BufferWriteParam BufferWriteParam;
XIsf_BufferToFlashWriteParam BufferToFlashWriteParam;
XIsf_FlashToBufTransferParam FlashToBufTransferParam;
XIsf_BufferReadParam BufferReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
Status = XSpi_Start(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Initialize the In-system and Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* Set the
* - SRAM page buffer number where the data is to be written.
* - Byte offset within SRAM page buffer where the data is to be written
* - The number of bytes to be written.
* - The Write Buffer with the data to be written.
*/
BufferWriteParam.BufferNum = XISF_PAGE_BUFFER1;
BufferWriteParam.ByteOffset = 0;
BufferWriteParam.NumBytes = ISF_PAGE_SIZE;
BufferWriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
BufferWriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Write to SRAM Page buffer.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_BUFFER_WRITE, (void*) &BufferWriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Set the
* - SRAM page buffer number from where the data is to be written.
* - Page Address in the Serial Flash where the data is to be written.
*/
BufferToFlashWriteParam.BufferNum = XISF_PAGE_BUFFER1;
BufferToFlashWriteParam.Address = TEST_ADDRESS;
/*
* Perform Erase then Write to Serial Flash from the SRAM page buffer.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_BUF_TO_PAGE_WRITE_WITH_ERASE,
(void*) &BufferToFlashWriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready to accept next command.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - SRAM page buffer number to which the data is to be read.
* - Set the Page Address from where the data is to be transferred.
*/
FlashToBufTransferParam.BufferNum = XISF_PAGE_BUFFER1;
FlashToBufTransferParam.Address = TEST_ADDRESS;
/*
* Transfer data from the Serial Flash to the SRAM page buffer.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_PAGE_TO_BUF_TRANS,
(void*) &FlashToBufTransferParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready to accept next command.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - SRAM page buffer number where the data is to be read.
* - Byte offset within SRAM page buffer where the data is to be read.
* - The number of bytes to be read.
* - The Read Buffer to which with the data is to be read.
*/
BufferReadParam.BufferNum = XISF_PAGE_BUFFER1;
BufferReadParam.ByteOffset = 0;
BufferReadParam.NumBytes = ISF_PAGE_SIZE;
BufferReadParam.ReadPtr = ReadBuffer;
/*
* Read data from SRAM page buffer.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_BUFFER_READ, (void*) &BufferReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Atmel Serial Flash is ready to accept next
* command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
static int IsfWaitForFlashNotBusy()
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the Serial Flash is ready to accept the next
* command. If so break.
*/
StatusReg = ReadBuffer[1];
if(StatusReg & XISF_SR_IS_READY_MASK) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specify real mode so that the SPI
* can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,331 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xilisf_atmel_rdwr_polled_example.c
*
* This file contains a design example using the In-system and Serial Flash
* Library (XilIsf) with the Spi driver in polled mode of operation. This example
* shows the Erase, Read and Write features.
*
* This example
* - Erases a Page
* - Writes to the erased Page
* - Reads back the Page that is written and compares the data
*
* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash
* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is
* 264 for Default addressing mode and 256 in Power-of-2 addressing mode.
*
* For AT45DB161D/AT45DB321D devices the Bytes Per Page (ISF_PAGE_SIZE) is
* 528 for Default addressing mode and 512 in Power-Of-2 addressing mode.
*
* For AT45DB642D device the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default
* addressing mode and 1024 in Power-Of-2 addressing mode.
*
* The ISF_PAGE_SIZE should be defined by the user according to the Device used.
*
* For further details of each device refer to the Spartan-3AN Serial Flash User
* Guide and data sheets of Atmel AT45XXXD .
*
* This example has been tested with the In-System Flash Memory available on the
* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board.
*
* @note
*
* None.
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- ---------------------------------------------------
* 1.00a sdm 04/02/08 First release
* 2.00a ktn 11/22/09 The Spi Driver APIs have changed. Replaced the call
* to XSpi_mIntrGlobalDisable with XSpi_IntrGlobalDisable.
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xilisf.h" /* Serial Flash Library header file */
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
/*
* The following constant defines the slave select signal that is used to
* select the Serial Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Page size of the Serial Flash.
*/
#define ISF_PAGE_SIZE 264
/*
* Address within the page of the Serial Flash to perform Erase, Write and Read
* operations.
*/
#define TEST_ADDRESS 0xA2400
#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy();
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs.
*/
static XIsf Isf;
static XSpi Spi;
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
/*****************************************************************************/
/**
*
* Main function to execute the Atmel Serial Flash Read/Write polled example.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int main(void)
{
int Status;
u16 Index;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
u32 Address;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that the device is enabled.
*/
Status = XSpi_Start(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Disable Global interrupt to use the Spi driver in polled mode
* operation.
*/
XSpi_IntrGlobalDisable(&Spi);
/*
* Initialize the In-system and Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = TEST_ADDRESS;
/*
* Perform the Page Erase operation.
*/
Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - The number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the Read operation.
*/
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Compare the Data Read with the Data Written to the Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadParam.ReadPtr[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Serial Flash is ready to accept next command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
static int IsfWaitForFlashNotBusy()
{
int Status;
u8 StatusReg;
u8 ReadBuffer[2];
while(1) {
/*
* Get the Status Register.
*/
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Check if the Serial Flash is ready to accept the next
* command. If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if(StatusReg & XISF_SR_IS_READY_MASK) {
break;
}
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,515 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xilisf_atmel_read_write_example.c
*
* This file contains a design example using the In-system and Serial Flash
* Library (XilIsf). This example shows the Erase, Read and Write features.
*
* This example
* - Erases a Page
* - Writes to the erased Page
* - Reads back the Page that is written and compares the data.
*
* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash
* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is
* 264 for Default addressing mode and 256 in Power-of-2 addressing mode.
*
* For AT45DB161D/AT45DB321D devices the Bytes Per Page (ISF_PAGE_SIZE) is
* 528 for Default addressing mode and 512 in Power-Of-2 addressing mode.
*
* For AT45DB642D device the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default
* addressing mode and 1024 in Power-Of-2 addressing mode.
*
* The ISF_PAGE_SIZE should be defined by the user according to the Device used.
*
* For further details of each device refer to the Spartan-3AN Serial Flash User
* Guide and data sheets of Atmel AT45XXXD .
*
* This example has been tested with the In-System Flash Memory available on the
* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board.
*
* @note
*
* None.
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- ---------------------------------------------------
* 1.00a mta/ksu 03/20/08 First release
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* select the Serial Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Page size of the Serial Flash.
*/
#define ISF_PAGE_SIZE 264
/*
* Address within the page of the Serial Flash to perform Erase, Write and Read
* operations.
*/
#define TEST_ADDRESS 0xA2400
#define ISF_TEST_BYTE 0x30 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy();
static int SetupInterruptSystem(XSpi *SpiPtr);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress; /* State of Spi Transfer */
static int ErrorCount; /* Errors occurred during Spi transfers */
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
/*****************************************************************************/
/**
*
* Main function to execute the Atmel Serial Flash Read/Write example.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int main(void)
{
int Status;
u16 Index;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
u32 Address;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
Status = XSpi_Start(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Initialize the In-system and Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = TEST_ADDRESS;
/*
* Perform the Page Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - The number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the Read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the Data Read with the Data Written to the Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadParam.ReadPtr[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Serial Flash is ready to accept next command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
static int IsfWaitForFlashNotBusy()
{
int Status;
u8 StatusReg;
u8 ReadBuffer[2];
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the Serial Flash is ready to accept the next
* command. If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if(StatusReg & XISF_SR_IS_READY_MASK) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that it's ready to use
* specify the device ID that is generated in xparameters.h.
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device.
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specify real mode so that the SPI
* can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,786 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xilisf_atmel_spr_example.c
*
*
* This file contains a design example using the In-system and Serial Flash
* Library (XilIsf). This example shows all the features related to Sector
* Protection.
*
* This example
* - Writes to the Sector Protection Register
* - Reads the Sector Protection Register and compares with the data that was
* written
* - Erases the Sector Protection Register
* - Erases a Page and writes the data to the Page
* - Enables the Sector Protection so that all the sectors are Write protected
* - Erases a Page (This should not happen as the Sectors are Write protected
* - Reads back the Page that is written and compares the data.
*
* The example works for AT45DB011D/AT45DB021D/AT45DB041D/AT45DB081D Serial Flash
* devices. The bytes per page (ISF_PAGE_SIZE) in these devices is
* 264 for Default addressing mode and 256 in Power-of-2 addressing mode.
*
* For AT45DB161D/AT45DB321D devices the Bytes Per Page (ISF_PAGE_SIZE) is
* 528 for Default addressing mode and 512 in Power-Of-2 addressing mode.
*
* For AT45DB642D device the Bytes Per Page (ISF_PAGE_SIZE) is 1056 for Default
* addressing mode and 1024 in Power-Of-2 addressing mode.
*
* The ISF_PAGE_SIZE should be defined by the user according to the Device used.
*
* For further details of each device refer to the Spartan-3AN Serial Flash User
* Guide and data sheets of Atmel AT45XXXD .
*
* This example has been tested with the In-System Flash Memory available on the
* Spartan-3AN on a Xilinx Spartan-3AN Starter Kit board.
*
* @note
*
* None.
*
*<pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- -----------------------------------------------------
* 1.00a mta/ksu 03/20/08 First release
* 1.00a ktn 09/08/09 Updated this example such that every SPR write should
* be preceded by an erase as per the atmel datasheet.
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
*</pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* select the Serial Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Page size of the Serial Flash.
*/
#define ISF_PAGE_SIZE 264
/*
* Address within the page of the Serial Flash to perform Erase, Write and Read
* operations.
*/
#define TEST_ADDRESS 0xA2400
#define ISF_TEST_BYTE 0x36 /* Test Byte offset value */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy();
static int SetupInterruptSystem(XSpi *SpiPtr);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress; /* State of Spi Transfer */
static int ErrorCount; /* Errors occurred during Spi transfers */
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES] ; /* Read Buffer. */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer. */
/*****************************************************************************/
/**
*
* Main function to execute the Atmel Serial Flash SPR example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
u16 Index;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
Status = XSpi_Start(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Initialize the In-system and Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* Perform the SPR erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_ERASE, NULL);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the SPR read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the values read back from the SPR with the values written
* during SPR erase operation. Return if error.
*/
for(Index = 0; Index < Isf.NumOfSectors; Index++) {
if((ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] & 0xFF) !=
0xFF) {
return XST_FAILURE;
}
}
/*
* Prepare the values to be written to the Sector Protect Register
* (SPR).
*/
for(Index = 0; Index < Isf.NumOfSectors; Index++) {
WriteBuffer[Index] = 0x00;
}
/*
* Perform the SPR write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the SPR read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the values read back from the SPR with the values written
* during SPR write operation. Return if error.
*/
for(Index = 0; Index < Isf.NumOfSectors; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] != 0x00) {
return XST_FAILURE;
}
}
/*
* Perform the SPR erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_ERASE, NULL);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
ErrorCount = 0;
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the SPR read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the values read from the SPR, are all 0xFF after performing
* the SPR erase operation.
*/
for(Index = XISF_CMD_SEND_EXTRA_BYTES; Index < (Isf.NumOfSectors +
XISF_CMD_SEND_EXTRA_BYTES); Index++) {
if(ReadBuffer[Index] != 0xFF) {
return XST_FAILURE;
}
}
/*
* Perform the SP disable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SP_DISABLE, NULL);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Page Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, TEST_ADDRESS);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - The number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = TEST_ADDRESS;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the SP enable operation. This should enable protection for
* all sectors since a SP erase operation has been performed earlier.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SP_ENABLE, NULL);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Page Erase operation. The Page Erase operation should not
* work since SP is enabled.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_PAGE_ERASE, TEST_ADDRESS);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the SP disable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SP_DISABLE, NULL);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Serial Flash is ready.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = TEST_ADDRESS;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the read operation. The values read should be same as the
* values written earlier.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadParam.ReadPtr[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Serial Flash is ready to accept next command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
static int IsfWaitForFlashNotBusy()
{
int Status;
u8 StatusReg;
u8 ReadBuffer[2];
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the Serial Flash is ready to accept the next
* command. If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if(StatusReg & XISF_SR_IS_READY_MASK) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that it's ready to use
* specify the device ID that is generated in xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that the SPI
* can cause interrupts thru the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,511 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_intel_otp_rdwr_example.c
*
* This file contains a design example using the Xilinx In-system and Serial
* Flash Library (XilIsf). This example shows the One-Time Programmable (OTP)
* Read/Write features.
*
* This example
* - Writes a Byte to OTP region
* - Reads back the Byte written to the OTP region and compares the data
*
* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33)
* on a S3A-DSP starter kit. For further details about the S33 Flash device refer
* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets.
*
*
* @note
*
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sdm 03/24/08 First release
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes to be written to the OTP area of the Serial Flash.
*/
#define ISF_OTP_WRITE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_OTP_TEST_ADDRESS 0x0225;
#define ISF_TEST_BYTE 0x30 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
static int SetupInterruptSystem(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress; /* State of Spi Transfer */
static int ErrorCount; /* Errors occurred during Spi transfers */
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_OTP_WRITE_SIZE + XISF_OTP_RDWR_EXTRA_BYTES];
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[ISF_OTP_WRITE_SIZE + XISF_OTP_RDWR_EXTRA_BYTES]; /* Read Buffer */
u8 WriteBuffer[ISF_OTP_WRITE_SIZE]; /* Write Buffer */
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Intel OTP Read/Write Flash example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Address;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Initialize the In-system and Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* Specify the address in the OTP region of the Serial Flash for the
* Write/Read operations.
*/
Address = ISF_OTP_TEST_ADDRESS;
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the OTP region of the Serial Flash where the data is
* to be written.
* - The number of bytes to be written to the Serial Flash, this is
* always 1 as only 1 byte can be written.
* - Write Buffer which contains the data to be written to the OTP
* region of the Serial Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_OTP_WRITE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* the OTP region of the Serial Flash.
*/
WriteParam.WritePtr[BYTE1] = ISF_TEST_BYTE;
/*
* Perform the OTP Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_OTP_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address in the OTP region of the Serial Flash where the data is to
* be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_OTP_WRITE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the OTP read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_OTP_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
if(ReadBuffer[BYTE1 + XISF_OTP_RDWR_EXTRA_BYTES] !=
(u8)(ISF_TEST_BYTE)) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Intel serial Flash is ready to accept the next
* command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the Status Register of the Serial Flash and
* waits till the WIP bit of the Status Register becomes 0.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for any errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the flash is ready to accept the next command.
* If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
/*
* If there were errors return XST_FAILURE.
*/
if (StatusReg & (XISF_SR_PROG_FAIL_MASK |
XISF_SR_ERASE_FAIL_MASK)) {
return XST_FAILURE;
}
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specify real mode so that
* the SPI can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,425 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_intel_rdwr_polled_example.c
*
* This file contains a design example using the Xilinx In-system and Serial
* Flash Library (XilIsf) with the Spi driver in polled mode of operation.
* This example shows the Sector Protection Register Read, Sector Protection
* Register Write, Sector Erase, Read and Write features.
*
* This example
* - Disables the Sector Protection for all the Sectors
* - Erases a Sector
* - Writes to a Page within the Erased Sector
* - Reads back the Page that is written and compares the data.
*
* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33)
* on a S3A-DSP starter kit. For further details about the S33 Flash device refer
* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a sdm 04/02/08 First release
* 2.00a ktn 11/22/09 The Spi Driver APIs have changed. Replaced the call
* to XSpi_mIntrGlobalDisable with XSpi_IntrGlobalDisable.
*
* </pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xilisf.h" /* Serial Flash Library header file */
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes per page in the flash device.
*/
#define ISF_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_TEST_ADDRESS 0x010000;
#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XSpi Spi;
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Intel Serial Flash Read/Write polled example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that device is enabled.
*/
XSpi_Start(&Spi);
/*
* Disable Global interrupt to use the Spi driver in polled mode
* operation.
*/
XSpi_IntrGlobalDisable(&Spi);
/*
* Initialize the In-system and Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* The following code Disables the Sector Protection for all the Blocks
* in the Intel Serial Flash.
*/
/*
* Perform the Write Enable operation.
*/
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is Not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read the Sector Protection Register.
*/
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Clear all the Block protection bits in the Sector Protection
* Register.
*/
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
(~(XISF_SR_BLOCK_PROTECT_MASK));
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = ISF_TEST_ADDRESS;
/*
* The following code Erases a Sector in the Intel Serial Flash.
*/
/*
* Perform the Write Enable operation.
*/
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation.
*/
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* The following code Writes data to a Page in the Intel Serial Flash.
*/
/*
* Perform the Write Enable operation.
*/
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* - Set the address within the Serial Flash where the data is to be
* written.
* - Set the number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* The following code Reads data from a Page in the Intel Serial Flash.
*/
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the read operation.
*/
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Intel Serial Flash is ready to accept next
* command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the Status Register of the Serial Flash and
* waits till the WIP bit of the Status Register becomes 0.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Check if the flash is ready to accept the next command.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
/*
* If there were errors return XST_FAILURE.
*/
if (StatusReg & (XISF_SR_PROG_FAIL_MASK |
XISF_SR_ERASE_FAIL_MASK)) {
return XST_FAILURE;
}
break;
}
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,655 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_intel_read_write_example.c
*
* This file contains a design example using the Xilinx In-system and Serial
* Flash Library (XilIsf). This example shows the Sector Protection Register
* Read, Sector Protection Register Write, Sector Erase, Read and Write features.
*
* This example
* - Disables the Sector Protection for all the Sectors
* - Erases a Sector
* - Writes to a Page within the Erased Sector
* - Reads back the Page that is written and compares the data.
*
* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33)
* on a S3A-DSP starter kit. For further details about the S33 Flash device refer
* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sdm 03/17/08 First release
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
*
* </pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes per page in the flash device.
*/
#define ISF_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_TEST_ADDRESS 0x010000;
#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
static int SetupInterruptSystem(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress; /* State of Spi Transfer */
static int ErrorCount; /* Errors occurred during Spi transfers */
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Intel Serial Flash Read/Write example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Initialize the In-system and Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* The following code Disables the Sector Protection for all the Blocks
* in the Intel Serial Flash.
*/
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is Not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read the Sector Protection Register.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Clear all the Block protection bits in the Sector Protection
* Register.
*/
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
(~(XISF_SR_BLOCK_PROTECT_MASK));
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = ISF_TEST_ADDRESS;
/*
* The following code Erases a Sector in the Intel Serial Flash.
*/
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* The following code Writes data to a Page in the Intel Serial Flash.
*/
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* - Set the address within the Serial Flash where the data is to be
* written.
* - Set the number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* The following code Reads data from a Page in the Intel Serial Flash.
*/
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Intel Serial Flash is ready to accept next
* command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the Status Register of the Serial Flash and
* waits till the WIP bit of the Status Register becomes 0.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is in progress.
*/
while(TransferInProgress);
/*
* Check if there are any errors in the transaction.
*/
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the flash is ready to accept the next command.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
/*
* If there were errors return XST_FAILURE.
*/
if (StatusReg & (XISF_SR_PROG_FAIL_MASK |
XISF_SR_ERASE_FAIL_MASK)) {
return XST_FAILURE;
}
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specify real mode so that
* the SPI can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,925 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_intel_spr_example.c
*
* This file contains a design example using the Xilinx In-system and Serial
* Flash Library (XilIsf). This example shows the usage of Sector Erase, Sector
* Protection, Read and Write features.
* This example
* - Disables the Sector Protection for all the Sectors
* - Erases a Sector
* - Writes to a Page within the erased Sector
* - Enables the Sector Protection so that all the sectors are Write protected
* - Erases the Sector (This should not happen as the Sectors are Write protected
* - Reads the Status Register and checks if the Erase Fail Flag is set
* - Clears the Status Register Fail Flags
* - Reads back the Page that is written and compares the data.
*
* This example has been tested with Intel (Numonyx) Serial Flash Memory (S33)
* on a S3A-DSP starter kit. For further details about the S33 Flash device refer
* to the Intel (Numonyx) Serial Flash Memory (S33) Data sheets.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sdm 03/17/08 First release
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include "xspi.h" /* SPI device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Serial Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes per page in the Serial Flash.
*/
#define ISF_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_TEST_ADDRESS 0x010000;
#define ISF_TEST_BYTE 0x20 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
static int SetupInterruptSystem(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress;
/*
* The following variable tracks any errors that occur during interrupt
* processing.
*/
static int ErrorCount;
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
u8 WriteBuffer[ISF_PAGE_SIZE];
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Intel Serial Flash SPR example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
u8 StatusReg;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Initialize the Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read the sector protection register.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Clear all the block protection bits in the sector protection register
* value read above.
*/
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
(~(XISF_SR_BLOCK_PROTECT_MASK));
/*
* Write this value to the sector protection register to disable the
* sector protection.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = ISF_TEST_ADDRESS;
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* - Set the address within the Serial Flash where the data is to be
* written.
* - Set the number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read the sector protection register.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Set all the block protection bits in the sector protection register
* value read above and write it back to the sector protection register.
*/
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] |
(XISF_SR_BLOCK_PROTECT_MASK);
/*
* Enable the sector protection.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation. This should not work as writes to
* the Serial Flash are disabled.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is in progress.
*/
while(TransferInProgress);
/*
* Check if there are any errors in the transaction.
*/
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the erase fail flag is set in the status register. This flag
* should be set as a sector erase operation was attempted when sector
* protection was enabled.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_ERASE_FAIL_MASK) == 0) {
return XST_FAILURE;
}
/*
* Clear the status register fail flags in the Serial Flash status
* register.
*/
TransferInProgress = TRUE;
Status = XIsf_Ioctl(&Isf, XISF_IOCTL_CLEAR_SR_FAIL_FLAGS);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is in progress.
*/
while(TransferInProgress);
/*
* Check if there are any errors in the transaction.
*/
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the erase fail flag is clear in the status register. This
* flag should be clear as a 'Clear SR Fail Flags' command has been
* executed.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_ERASE_FAIL_MASK) != 0) {
return XST_FAILURE;
}
/*
* Read the sector protection register.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Clear all the block protection bits in the sector protection register
* value read above and write it back to the sector protection register
* to disable sector protection for all sectors.
*/
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
~(XISF_SR_BLOCK_PROTECT_MASK);
/*
* Disable the sector protection.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* The following code Reads data from a Page in the Intel Serial Flash.
*/
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the STM serial Flash is ready to accept next command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Serial Flash and
waits till the WIP bit of the status register becomes 0.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is in progress.
*/
while(TransferInProgress);
/*
* Check if there are any errors in the transaction.
*/
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the flash is ready to accept the next command.
* If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the SPI can cause interrupts thru the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,864 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xilisf_qspips_flash_intr_example.c
*
*
* This file contains a design example using the XILISF Library in
* interrupt mode with a serial FLASH device. This examples performs
* some transfers in Auto mode and Manual start mode, to illustrate the modes
* available.
* The hardware which this example runs on, must have a serial FLASH (Numonyx
* N25Q, Winbond W25Q, or Spansion S25FL) for it to run. This example has been
* tested with the Numonyx Serial Flash (N25Q128).
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 srt 06/20/12 First release
* 1.01 srt 04/26/13 Modified Erase function to perform Write Enable operation
* for each sector erase.
* 1.01 srt 08/28/13 Fixed the CR 731919, by setting the proper QSPI options.
* 5.0 sb 08/05/14 Added support for greater than 128MB flash operations.
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /**< EDK generated parameters */
#include "xscugic.h" /**< Interrupt controller device driver */
#include "xil_exception.h"
#include "xil_printf.h"
#include <xilisf.h> /**< Serial Flash Library header file */
/************************** Constant Definitions *****************************/
/** @name Device ID's
*
* @{
*/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define QSPI_INTR_ID XPAR_XQSPIPS_0_INTR
/*@}*/
/**
* The following constants define the offsets within a FlashBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the QSPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define DATA_OFFSET 4 /**< Start of Data for Read/Write */
#define DUMMY_OFFSET 4 /**< Dummy byte offset for fast, dual
and quad reads */
#define DUMMY_SIZE 1 /**< Number of dummy bytes for fast,
dual and quad reads */
/**
* The following constants specify the page size, sector size, and number of
* pages and sectors for the FLASH. The page size specifies a max number of
* bytes that can be written to the FLASH with a single transfer.
*/
#define NUM_PAGES 0x10000 /**< Number of Pages in the flash */
#define PAGE_SIZE 256 /**< Page Size for Read/Write Operation */
/**
* Number of flash pages to be written.
*/
#define PAGE_COUNT 16 /**< Number of Pages for
Read/Write Operation */
/**
* Flash address to which data is to be written.
*/
#define TEST_ADDRESS 0x00080000 /**< Test Address in the flash */
#define UNIQUE_VALUE 0x05 /**< Unique Value for Test */
/**
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the FLASH.
*/
#define MAX_DATA PAGE_COUNT * PAGE_SIZE /**< Max Data Calculated by
multiplying Page count and Page Size*/
/**
* The following constant defines the slave select signal that is used to
* to select the FLASH device on the QSPI bus, this signal is typically
* connected to the chip select of the device
*/
#define FLASH_QSPI_SELECT 0x00
#define INTR_MODE 1 /**< Interrupt Mode Enable */
#define FAST_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for Fast Read*/
#define DUAL_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for Dual Read */
#define QUAD_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for Quad Read */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int QspiSetupIntrSystem(XScuGic *IntcInstancePtr,
XQspiPs *QspiInstancePtr, u16 QspiIntrId);
static void QspiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 QspiIntrId);
void XilIsf_Handler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount);
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount);
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
int QspiFlashIntrExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr,
u16 QspiDeviceId, u16 QspiIntrId);
u32 SectorMask(u32 SectorSize);
/************************** Variable Definitions *****************************/
/**
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XScuGic IntcInstance;
static XQspiPs QspiInstance;
static XIsf Isf;
/**
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile int TransferInProgress;
/**
* The following variable tracks any errors that occur during interrupt
* processing
*/
int ErrorCount;
/**
* The following variable allows a test value to be added to the values that
* are written to the FLASH such that unique values can be generated to
* guarantee the writes to the FLASH were successful
*/
int Test = 5;
/**
* The following variables are used to read and write to the eeprom and they
* are global to avoid having large buffers on the stack
*/
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET]; /**< Write Buffer */
u8 IsfWriteBuffer[PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];/**< IsfWrite Buffer
used in XilISF Initialization */
/**
* The following defines are for dual flash stacked mode interface.
*/
#define LQSPI_CR_FAST_QUAD_READ 0x0000006B /**< Fast Quad Read output */
#define LQSPI_CR_1_DUMMY_BYTE 0x00000100 /**< 1 Dummy Byte between
address and return data */
#define DUAL_STACK_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
LQSPI_CR_1_DUMMY_BYTE | \
LQSPI_CR_FAST_QUAD_READ)/**< Fast Quad Read output */
#define DUAL_QSPI_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
XQSPIPS_LQSPI_CR_SEP_BUS_MASK | \
LQSPI_CR_1_DUMMY_BYTE | \
LQSPI_CR_FAST_QUAD_READ)/**< Fast Quad Read output */
/*****************************************************************************/
/**
*
* Main function to call the QSPI Flash example.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("QSPI FLASH Interrupt Example Test \r\n");
/*
* Run the Qspi Interrupt example.
*/
Status = QspiFlashIntrExample(&IntcInstance, &QspiInstance,
QSPI_DEVICE_ID, QSPI_INTR_ID);
if (Status != XST_SUCCESS) {
xil_printf("QSPI FLASH Interrupt Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran QSPI FLASH Interrupt Example Test\r\n");
return XST_SUCCESS;
}
/****************************************************************************/
/**
* The purpose of this function is to illustrate how to use the XQspiPs
* device driver in interrupt mode. This function writes and reads data
* from a serial FLASH.
*
* @param IntcInstancePtr is the instance of the interrupt
* @param QspiInstancePtr is the Pointer to the qspi driver instance
* @param QspiDeviceId is the Device ID of qspi
* @param QspiIntrId is the interrupt ID for QSPI driver
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
*
* This function calls other functions which contain loops that may be infinite
* if interrupts are not working such that it may not return. If the device
* slave select is not correct and the device is not responding on bus it will
* read a status of 0xFF for the status register as the bus is pulled up.
*
*****************************************************************************/
int QspiFlashIntrExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr,
u16 QspiDeviceId, u16 QspiIntrId)
{
int Status;
u8 *BufferPtr;
u8 UniqueValue;
int Count;
int Page;
XQspiPs_Config *ConfigPtr; /* Pointer to Configuration ROM data */
u32 Options;
/*
* Lookup the device configuration in the temporary CROM table. Use this
* configuration info down below when initializing this component.
*/
ConfigPtr = XQspiPs_LookupConfig(QspiDeviceId);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
Status = XQspiPs_CfgInitialize(QspiInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the QSPI options
*/
Options = XQSPIPS_FORCE_SSELECT_OPTION |
XQSPIPS_MANUAL_START_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION;
Status = XIsf_SetSpiConfiguration(&Isf, QspiInstancePtr,
Options, XISF_SPI_PRESCALER);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_STACKED) {
/*
* Enable two flash memories, Shared bus (NOT separate bus),
* L_PAGE selected by default
*/
XQspiPs_SetLqspiConfigReg(QspiInstancePtr,
DUAL_STACK_CONFIG_WRITE);
}
if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_PARALLEL) {
/*
* Enable two flash memories on separate buses
*/
XQspiPs_SetLqspiConfigReg(QspiInstancePtr,
DUAL_QSPI_CONFIG_WRITE);
}
/* Initialize the XILISF Library */
XIsf_Initialize(&Isf, QspiInstancePtr, FLASH_QSPI_SELECT,
IsfWriteBuffer);
XIsf_SetTransferMode(&Isf, XISF_INTERRUPT_MODE);
/*
* Connect the Qspi device to the interrupt subsystem such that
* interrupts can occur. This function is application specific
*/
Status = QspiSetupIntrSystem(IntcInstancePtr, QspiInstancePtr,
QspiIntrId);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the QSPI that will be called from the
* interrupt context when an QSPI status occurs, specify a pointer to
* the QSPI driver instance as the callback reference so the handler is
* able to access the instance data
*/
XIsf_SetStatusHandler(&Isf, QspiInstancePtr,
(XQspiPs_StatusHandler) XilIsf_Handler);
/*
* Initialize the write buffer for a pattern to write to the FLASH
* and the read buffer to zero so it can be verified after the read,
* the test value that is added to the unique value allows the value
* to be changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
Count++, UniqueValue++) {
WriteBuffer[Count] = (u8)(UniqueValue + Test);
}
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
Status = FlashErase(&Isf, TEST_ADDRESS, MAX_DATA);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
/*
* Write the data in the write buffer to the serial FLASH a page at a
* time, starting from TEST_ADDRESS
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
FlashWrite(&Isf, (Page * PAGE_SIZE) + TEST_ADDRESS,
PAGE_SIZE, XISF_WRITE);
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
* command
*/
FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = ReadBuffer;
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Fast Read
* command
*/
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_FAST_READ);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = ReadBuffer;
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using DUAL IO
* Fast Read command
*/
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_DUAL_OP_FAST_READ);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = ReadBuffer;
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using QUAD OP
* Fast Read command
*/
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_QUAD_OP_FAST_READ);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = ReadBuffer;
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
QspiDisableIntrSystem(IntcInstancePtr, QspiIntrId);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function is the handler which performs processing for the QSPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of QSPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle QSPI interrupts but is
* application specific.
*
* @param CallBackRef is a reference passed to the handler.
* @param StatusEvent is the status of the QSPI .
* @param ByteCount is the number of bytes transferred.
*
* @return None
*
* @note None.
*
******************************************************************************/
void XilIsf_Handler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount)
{
/*
* Indicate the transfer on the QSPI bus is no longer in progress
* regardless of the status event
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function writes to the serial FLASH connected to the QSPI interface.
* The FLASH contains a 256 byte write buffer which can be filled and then a
* write is automatically performed by the device. All the data put into the
* buffer must be in the same page of the device with page boundaries being on
* 256 byte boundaries.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address to write data to in the FLASH.
* @param ByteCount contains the number of bytes to write.
* @param Command is the command used to write data to the flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
{
XIsf_WriteParam WriteParam;
int Status;
WriteParam.Address = Address;
WriteParam.NumBytes = ByteCount;
WriteParam.WritePtr = WriteBuffer;
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, Command, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function reads from the serial FLASH connected to the
* QSPI interface.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address to read data from in the FLASH.
* @param ByteCount contains the number of bytes to read.
* @param Command is the command used to read data from the flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
{
XIsf_ReadParam ReadParam;
int Status;
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ByteCount;
ReadParam.ReadPtr = ReadBuffer;
if(Command == XISF_FAST_READ){
ReadParam.NumDummyBytes = FAST_READ_NUM_DUMMY_BYTES;
}
else if(Command == XISF_DUAL_OP_FAST_READ){
ReadParam.NumDummyBytes = DUAL_READ_NUM_DUMMY_BYTES;
}
else{
ReadParam.NumDummyBytes = QUAD_READ_NUM_DUMMY_BYTES;
}
/*
* Perform the Read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, Command, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function erases the sectors in the serial FLASH connected to the
* QSPI interface.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address of the first sector which needs to
* be erased.
* @param ByteCount contains the total size to be erased.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount)
{
int Status;
int Sector;
u32 NumSect;
u32 SectorSize;
u32 NumSectors;
u32 Sector_Mask;
SectorSize = Isf.SectorSize;
NumSectors = Isf.NumSectors;
/* Get the sector mask value */
Sector_Mask = SectorMask(SectorSize);
/*
* If erase size is same as the total size of the flash, use bulk erase
* command
*/
if (ByteCount == (NumSectors * SectorSize)) {
/*
* Perform the Bulk Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(InstancePtr, XISF_BULK_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there
* are any errors in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
}
/*
* Calculate no. of sectors to erase based on byte count
*/
NumSect = ByteCount/SectorSize + 1;
/*
* If ByteCount to k sectors,
* but the address range spans from N to N+k+1 sectors, then
* increment no. of sectors to be erased
*/
if( ((Address + ByteCount) & Sector_Mask) ==
((Address + (NumSect * SectorSize)) &
Sector_Mask) ) {
NumSect++;
}
/*
* If the erase size is less than the total size of the flash, use
* sector erase command
*/
for (Sector = 0; Sector < NumSect; Sector++) {
/*
* Perform the Bulk Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there
* are any errors in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
Address += SectorSize;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system for an Qspi device.
*
* @param IntcInstancePtr is a pointer to the instance of the Intc device.
* @param QspiInstancePtr is a pointer to the instance of the Qspi device.
* @param QspiIntrId is the interrupt Id for an QSPI device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None.
*
******************************************************************************/
static int QspiSetupIntrSystem(XScuGic *IntcInstancePtr,
XQspiPs *QspiInstancePtr, u16 QspiIntrId)
{
int Status;
XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */
Xil_ExceptionInit();
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
IntcInstancePtr);
/*
* Connect the device driver handler that will be called when an
* interrupt for the device occurs, the handler defined above performs
* the specific interrupt processing for the device.
*/
Status = XScuGic_Connect(IntcInstancePtr, QspiIntrId,
(Xil_ExceptionHandler)XQspiPs_InterruptHandler,
(void *)QspiInstancePtr);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Enable the interrupt for the Qspi device.
*/
XScuGic_Enable(IntcInstancePtr, QspiIntrId);
/*
* Enable interrupts in the Processor.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function disables the interrupts that occur for the Qspi device.
*
* @param IntcInstancePtr is the pointer to an INTC instance.
* @param QspiIntrId is the interrupt Id for an QSPI device.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void QspiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 QspiIntrId)
{
/*
* Disable the interrupt for the QSPI device.
*/
XScuGic_Disable(IntcInstancePtr, QspiIntrId);
/*
* Disconnect and disable the interrupt for the Qspi device.
*/
XScuGic_Disconnect(IntcInstancePtr, QspiIntrId);
}
/*****************************************************************************/
/**
*
* This function calculates the sector mask based upon the sector size value
*
*
* @param SectorSize is the size of the sector of the flash
* available on the board.
*
* @return will return the sector mask after calculation.
*
* @note None.
*
******************************************************************************/
u32 SectorMask(u32 SectorSize){
u32 Mask;
switch(SectorSize){
case 0x10000:
Mask = 0xFFFF0000;
break;
case 0x20000:
Mask = 0xFFFE0000;
break;
case 0x40000:
Mask = 0xFFFC0000;
break;
case 0x80000:
Mask = 0xFFF80000;
break;
default:
break;
}
return Mask;
}

View file

@ -0,0 +1,727 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xilisf_qspips_flash_polled_example.c
*
*
* This file contains a design example using the XILISF Library in
* interrupt mode with a serial FLASH device. This examples performs
* some transfers in Auto mode and Manual start mode, to illustrate the modes
* available.
* The hardware which this example runs on, must have a serial FLASH (Numonyx
* N25Q, Winbond W25Q, or Spansion S25FL) for it to run. This example has been
* tested with the Numonyx Serial Flash (N25Q128).
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 srt 06/20/12 First release
* 1.01 srt 04/26/13 Modified Erase function to perform Write Enable operation
* for each sector erase.
* 1.01 srt 08/28/13 Fixed the CR 731919, by setting the proper QSPI options.
* 5.0 sb 08/05/14 Added support for greater than 128MB flash operations.
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xscugic.h" /* Interrupt controller device driver */
#include "xil_exception.h"
#include "xil_printf.h"
#include "xilisf.h" /* Serial Flash Library header file */
/************************** Constant Definitions *****************************/
/** @name Device ID's
*
* @{
*/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define QSPI_INTR_ID XPAR_XQSPIPS_0_INTR
/*@}*/
/**
* The following constants define the offsets within a FlashBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the QSPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define DATA_OFFSET 4 /**< Start of Data for Read/Write */
#define DUMMY_OFFSET 4 /**< Dummy byte offset for fast, dual and quad
reads */
#define DUMMY_SIZE 1 /**< Number of dummy bytes for fast, dual and
quad reads */
/**
* The following constants specify the page size and number of
* pages for the FLASH. The page size specifies a max number of
* bytes that can be written to the FLASH with a single transfer.
*/
#define NUM_PAGES 0x10000 /**< Number of Pages in the flash */
#define PAGE_SIZE 256 /**< Page Size for Read/Write Operation */
/**
* Number of flash pages to be written.
*/
#define PAGE_COUNT 32 /**< Number of Pages for r/w Operation */
/**
* Flash address to which data is ot be written.
*/
#define TEST_ADDRESS 0x00090000 /**< Test Address in the flash */
#define UNIQUE_VALUE 0x08 /**< Unique Value for Test */
/**
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the FLASH.
*/
#define MAX_DATA PAGE_COUNT * PAGE_SIZE /**< Max Data Calculated by
multiplying Page count and Page Size */
/**
* The following constant defines the slave select signal that is used to
* to select the FLASH device on the QSPI bus, this signal is typically
* connected to the chip select of the device
*/
#define FLASH_QSPI_SELECT 0x00 /**< Interrupt Mode Enable */
#define FAST_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for
Fast Read */
#define DUAL_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for
Dual Read */
#define QUAD_READ_NUM_DUMMY_BYTES 1 /**< Number Dummy Bytes for
Quad Read */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount);
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount,
u8 Command);
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount,
u8 Command);
int QspiFlashPollExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr,
u16 QspiDeviceId, u16 QspiIntrId);
static u32 SectorMask(u32 SectorSize);
/************************** Variable Definitions *****************************/
/**
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XScuGic IntcInstance;
static XQspiPs QspiInstance;
static XIsf Isf;
static XQspiPs_Config *ConfigPtr; /**< Pointer to Configuration ROM data */
/**
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile int TransferInProgress;
/**
* The following variable allows a test value to be added to the values that
* are written to the FLASH such that unique values can be generated to
* guarantee the writes to the FLASH were successful
*/
int Test_Polled = 7;
/**
* The following variables are used to read and write to the eeprom and they
* are global to avoid having large buffers on the stack
*/
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET]; /**< Write Buffer */
u8 IsfWriteBuffer[PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];/**< IsfWrite Buffer
used in XilISF Initialization */
/**
* The following defines are for dual flash stacked mode interface.
*/
#define LQSPI_CR_FAST_QUAD_READ 0x0000006B /**< Fast Quad Read output */
#define LQSPI_CR_1_DUMMY_BYTE 0x00000100 /**< 1 Dummy Byte between
address and return data */
#define DUAL_STACK_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
LQSPI_CR_1_DUMMY_BYTE | \
LQSPI_CR_FAST_QUAD_READ) /**< Fast Quad Read output */
#define DUAL_QSPI_CONFIG_WRITE (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \
XQSPIPS_LQSPI_CR_SEP_BUS_MASK | \
LQSPI_CR_1_DUMMY_BYTE | \
LQSPI_CR_FAST_QUAD_READ) /**< Fast Quad Read output */
/*****************************************************************************/
/**
*
* Main function to call the QSPI Flash example.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("QSPI FLASH Polling Example Test \r\n");
/*
* Run the Qspi Interrupt example.
*/
Status = QspiFlashPollExample(&IntcInstance, &QspiInstance,
QSPI_DEVICE_ID, QSPI_INTR_ID);
if (Status != XST_SUCCESS) {
xil_printf("QSPI FLASH Polling Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran QSPI FLASH Polling Example Test\r\n");
return XST_SUCCESS;
}
/****************************************************************************/
/**
* The purpose of this function is to illustrate how to use the XQspiPs
* device driver in interrupt mode. This function writes and reads data
* from a serial FLASH.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
*
* This function calls other functions which contain loops that may be infinite
* if interrupts are not working such that it may not return. If the device
* slave select is not correct and the device is not responding on bus it will
* read a status of 0xFF for the status register as the bus is pulled up.
*
*****************************************************************************/
int QspiFlashPollExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr,
u16 QspiDeviceId, u16 QspiIntrId)
{
u8 *BufferPtr;
u8 UniqueValue;
int Count;
int Page;
int Status;
u32 Options;
/*
* Lookup the device configuration in the temporary CROM table. Use this
* configuration info down below when initializing this component.
*/
ConfigPtr = XQspiPs_LookupConfig(QspiDeviceId);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
Status = XQspiPs_CfgInitialize(QspiInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the QSPI options
*/
Options = XQSPIPS_FORCE_SSELECT_OPTION |
XQSPIPS_MANUAL_START_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION;
XIsf_SetSpiConfiguration(&Isf, QspiInstancePtr, Options,
XISF_SPI_PRESCALER);
if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_STACKED) {
/*
* Enable two flash memories, Shared bus
* (NOT separate bus), L_PAGE selected by default
*/
XQspiPs_SetLqspiConfigReg(QspiInstancePtr,
DUAL_STACK_CONFIG_WRITE);
}
if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_PARALLEL) {
/*
* Enable two flash memories on separate buses
*/
XQspiPs_SetLqspiConfigReg(QspiInstancePtr,
DUAL_QSPI_CONFIG_WRITE);
}
/* Initialize the XILISF Library */
XIsf_Initialize(&Isf, QspiInstancePtr, FLASH_QSPI_SELECT,
IsfWriteBuffer);
/*
* Initialize the write buffer for a pattern to write to the FLASH
* and the read buffer to zero so it can be verified after the read,
* the test value that is added to the unique value allows the value
* to be changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
Count++, UniqueValue++) {
WriteBuffer[Count] = (u8)(UniqueValue + Test_Polled);
}
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
Status = FlashErase(&Isf, TEST_ADDRESS, MAX_DATA);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
/*
* Write the data in the write buffer to the serial FLASH a page at a
* time, starting from TEST_ADDRESS
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
Status = FlashWrite(&Isf,
(Page * PAGE_SIZE) + TEST_ADDRESS, PAGE_SIZE,
XISF_QUAD_IP_PAGE_WRITE);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
}
/******************************************************
**********************NORMAL READ*********************
******************************************************/
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
* command
*/
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = ReadBuffer;
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
return XST_FAILURE;
}
}
/******************************************************
**********************FAST READ***********************
******************************************************/
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Fast Read
* command
*/
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA,
XISF_FAST_READ);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = ReadBuffer;
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
return XST_FAILURE;
}
}
/******************************************************
******************DUAL OP FAST READ*******************
******************************************************/
/*
* Read the contents of the FLASH from TEST_ADDRESS, using DUAL OP
* Fast Read command
*/
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA,
XISF_DUAL_OP_FAST_READ);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = ReadBuffer;
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
return XST_FAILURE;
}
}
/******************************************************
******************QUAD IO FAST READ*******************
******************************************************/
/*
* Read the contents of the FLASH from TEST_ADDRESS, using QUAD IO
* Fast Read command
*/
Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA,
XISF_QUAD_OP_FAST_READ);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = ReadBuffer;
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function writes to the serial FLASH connected to the QSPI interface.
* The FLASH contains a 256 byte write buffer which can be filled and then a
* write is automatically performed by the device. All the data put into the
* buffer must be in the same page of the device with page boundaries being on
* 256 byte boundaries.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address to write data to in the FLASH.
* @param ByteCount contains the number of bytes to write.
* @param Command is the command used to write data to the flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount,
u8 Command)
{
XIsf_WriteParam WriteParam;
int Status;
WriteParam.Address = Address;
WriteParam.NumBytes = ByteCount;
WriteParam.WritePtr = WriteBuffer;
/*
* Perform the Write operation.
*/
Status = XIsf_Write(&Isf, Command, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function reads from the serial FLASH connected to the
* QSPI interface.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address to read data from in the FLASH.
* @param ByteCount contains the number of bytes to read.
* @param Command is the command used to read data from the flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
{
XIsf_ReadParam ReadParam;
int Status;
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes ReadParam.NumDummyBytesto be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ByteCount;
ReadParam.ReadPtr = ReadBuffer;
if(Command == XISF_FAST_READ){
ReadParam.NumDummyBytes = FAST_READ_NUM_DUMMY_BYTES;
}
else if(Command == XISF_DUAL_OP_FAST_READ){
ReadParam.NumDummyBytes = DUAL_READ_NUM_DUMMY_BYTES;
}
else{
ReadParam.NumDummyBytes = QUAD_READ_NUM_DUMMY_BYTES;
}
/*
* Perform the Read operation.
*/
Status = XIsf_Read(&Isf, Command, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function erases the sectors in the serial FLASH connected to the
* QSPI interface.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address of the first sector which needs to
* be erased.
* @param ByteCount contains the total size to be erased.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount)
{
int Status;
int Sector;
u32 LqspiCr;
u32 NumSect;
u32 SectorSize;
u32 NumSectors;
u32 Sector_Mask;
/*
* Get the value of Sector Size and Number of Sectors for the flash
*/
SectorSize = Isf.SectorSize;
NumSectors = Isf.NumSectors;
/* Get the sector mask value */
Sector_Mask = SectorMask(SectorSize);
/*
* If erase size is same as the total size of the flash, use bulk erase
* command
*/
if (ByteCount == (NumSectors * SectorSize)) {
#ifdef XPAR_XQSPIPS_0_DEVICE_ID
if(ConfigPtr->ConnectionMode ==
XQSPIPS_CONNECTION_MODE_STACKED){
/*
* Get the current LQSPI configuration register value
*/
LqspiCr =
XQspiPs_GetLqspiConfigReg(InstancePtr->SpiInstPtr);
/*
* Set selection to L_PAGE
*/
XQspiPs_SetLqspiConfigReg(InstancePtr->SpiInstPtr,
LqspiCr & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK));
/*
* Assert the Flash chip select.
*/
XQspiPs_SetSlaveSelect(InstancePtr->SpiInstPtr);
}
#endif /*XPAR_XQSPIPS_0_DEVICE_ID*/
/*
* Call Bulk erase
*/
Status = XIsf_Erase(InstancePtr,
XISF_BULK_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
#ifdef XPAR_XQSPIPS_0_DEVICE_ID
/*
* If stacked mode, bulk erase second flash
*/
if(ConfigPtr->ConnectionMode ==
XQSPIPS_CONNECTION_MODE_STACKED){
/*
* Get the current LQSPI configuration register value
*/
LqspiCr =
XQspiPs_GetLqspiConfigReg(InstancePtr->SpiInstPtr);
/*
* Set selection to U_PAGE
*/
XQspiPs_SetLqspiConfigReg(InstancePtr->SpiInstPtr,
LqspiCr | XQSPIPS_LQSPI_CR_U_PAGE_MASK);
/*
* Assert the Flash chip select.
*/
XQspiPs_SetSlaveSelect(InstancePtr->SpiInstPtr);
/*
* Call Bulk erase
*/
Status = XIsf_Erase(InstancePtr,
XISF_BULK_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
}
#endif /*XPAR_XQSPIPS_0_DEVICE_ID*/
return Status;
}
/*
* Calculate no. of sectors to erase based on byte count
*/
NumSect = ByteCount/SectorSize + 1;
/*
* If ByteCount to k sectors,
* but the address range spans from N to N+k+1 sectors, then
* increment no. of sectors to be erased
*/
if( ((Address + ByteCount) & Sector_Mask) ==
((Address + (NumSect * SectorSize)) &
Sector_Mask) ) {
NumSect++;
}
/*
* If the erase size is less than the total size of the flash, use
* sector erase command
*/
for (Sector = 0; Sector < NumSect; Sector++) {
/*
* Perform the Sector Erase operation.
*/
Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Address += SectorSize;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function calculates the sector mask based upon the sector size value
*
*
* @param SectorSize is the size of the sector of the flash
* available on the board.
*
* @return will return the sector mask after calculation.
*
* @note None.
*
******************************************************************************/
u32 SectorMask(u32 SectorSize){
u32 Mask;
switch(SectorSize){
case 0x10000:
Mask = 0xFFFF0000;
break;
case 0x20000:
Mask = 0xFFFE0000;
break;
case 0x40000:
Mask = 0xFFFC0000;
break;
case 0x80000:
Mask = 0xFFF80000;
break;
default:
break;
}
return Mask;
}

View file

@ -0,0 +1,717 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xilisf_spips_flash_intr_example.c
*
*
* This file contains a design example using the XILISF Library in
* interrupt mode with a serial FLASH device. This examples performs
* some transfers in Auto mode and Manual start mode, to illustrate the modes
* available.
* The hardware which this example runs on, must have a serial FLASH (Numonyx
* N25Q, Winbond W25Q, SST or Spansion S25FL) for it to run. This example has
* been tested with the SST Flash.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 srt 06/20/12 First release
* 3.01 srt 03/03/13 Modified the flash write, erase and read logic.
* Ensured flash blocks are unprotected befor a flash erase
* or write operation. (CR 703816)
* 3.02 srt 04/26/13 Modified Erase function to perform Write Enable operation
* for each sector erase.
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xscugic.h" /* Interrupt controller device driver */
#include "xil_exception.h"
#include "xil_printf.h"
#include <xilisf.h>
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define SPI_INTR_ID XPAR_XSPIPS_1_INTR
/*
* The following constants define the offsets within a FlashBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the SPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define DATA_OFFSET 4 /* Start of Data for Read/Write */
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and
quad reads */
/*
* The following constants specify the page size, sector size, and number of
* pages and sectors for the FLASH. The page size specifies a max number of
* bytes that can be written to the FLASH with a single transfer.
*/
#define SECTOR_SIZE 0x1000
#define NUM_SECTORS 0x100
/*
* Flash address to which data is to be written.
*/
#define TEST_ADDRESS 0x00
#define UNIQUE_VALUE 0x05
/*
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the FLASH.
*/
#define MAX_DATA SECTOR_SIZE * NUM_SECTORS
/*
* The following constant defines the slave select signal that is used to
* to select the FLASH device on the SPI bus, this signal is typically
* connected to the chip select of the device
*/
#define FLASH_SPI_SELECT 0x01
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int SpiSetupIntrSystem(XScuGic *IntcInstancePtr,
XSpiPs *SpiInstancePtr, u16 SpiIntrId);
static void SpiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 SpiIntrId);
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount);
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount);
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
int WriteEnable(XIsf *InstancePtr);
int SpiFlashIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr,
u16 SpiDeviceId, u16 SpiIntrId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XScuGic IntcInstance;
static XSpiPs SpiInstance;
static XIsf Isf;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile int TransferInProgress;
/*
* The following variable tracks any errors that occur during interrupt
* processing
*/
int ErrorCount;
/*
* The following variables are used to read and write to the eeprom and they
* are global to avoid having large buffers on the stack
*/
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[MAX_DATA + DATA_OFFSET];
u8 IsfWriteBuffer[XISF_CMD_SEND_EXTRA_BYTES + 1];
/*****************************************************************************/
/**
*
* Main function to call the SPI Flash example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("SPI FLASH Interrupt Example Test \r\n");
/*
* Run the Spi Interrupt example.
*/
Status = SpiFlashIntrExample(&IntcInstance, &SpiInstance,
SPI_DEVICE_ID, SPI_INTR_ID);
if (Status != XST_SUCCESS) {
xil_printf("SPI FLASH Interrupt Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran SPI FLASH Interrupt Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpiPs
* device driver in interrupt mode. This function writes and reads data
* from a serial FLASH.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
*
* This function calls other functions which contain loops that may be infinite
* if interrupts are not working such that it may not return. If the device
* slave select is not correct and the device is not responding on bus it will
* read a status of 0xFF for the status register as the bus is pulled up.
*
*****************************************************************************/
int SpiFlashIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr,
u16 SpiDeviceId, u16 SpiIntrId)
{
int Status;
u8 *BufferPtr;
u8 UniqueValue;
u32 Count;
XSpiPs_Config *ConfigPtr; /* Pointer to Configuration ROM data */
u32 TempAddress;
/*
* Lookup the device configuration in the temporary CROM table. Use this
* configuration info down below when initializing this component.
*/
ConfigPtr = XSpiPs_LookupConfig(SpiDeviceId);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
XSpiPs_CfgInitialize(SpiInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
/* Initialize the XILISF Library */
XIsf_Initialize(&Isf, SpiInstancePtr, FLASH_SPI_SELECT,
IsfWriteBuffer);
XIsf_SetTransferMode(&Isf, XISF_INTERRUPT_MODE);
/*
* Connect the Spi device to the interrupt subsystem such that
* interrupts can occur. This function is application specific
*/
Status = SpiSetupIntrSystem(IntcInstancePtr, SpiInstancePtr,
SpiIntrId);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the
* interrupt context when an SPI status occurs, specify a pointer to
* the SPI driver instance as the callback reference so the handler is
* able to access the instance data
*/
XIsf_SetStatusHandler(&Isf, SpiInstancePtr,
(XSpiPs_StatusHandler) SpiHandler);
memset(WriteBuffer, 0x00, sizeof(WriteBuffer));
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/* Unprotect Sectors */
FlashWrite(&Isf, 0, 0, XISF_WRITE_STATUS_REG);
FlashErase(&Isf, TEST_ADDRESS, MAX_DATA);
/*
* Initialize the write buffer for a pattern to write to the FLASH
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
TempAddress = TEST_ADDRESS;
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++, TempAddress++) {
WriteBuffer[0] = (u8)(UniqueValue);
FlashWrite(&Isf, TempAddress, 1, XISF_WRITE);
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
* command
*/
FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue)) {
return XST_FAILURE;
}
}
SpiDisableIntrSystem(IntcInstancePtr, SpiIntrId);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the STM Serial Flash is ready to accept next command.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Serial Flash and
waits till the WIP bit of the status register becomes 0.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is in progress.
*/
while(TransferInProgress);
/*
* Check if there are any errors in the transaction.
*/
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the flash is ready to accept the next command.
* If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}
/******************************************************************************
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts but is
* application specific.
*
* @param CallBackRef is a reference passed to the handler.
* @param StatusEvent is the status of the SPI .
* @param ByteCount is the number of bytes transferred.
*
* @return None
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/******************************************************************************
*
*
* This function writes to the serial FLASH connected to the SPI interface.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address to write data to in the FLASH.
* @param ByteCount contains the number of bytes to write.
* @param Command is the command used to write data to the flash. SPI
* device supports Byte Program command to write data to the
* flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
{
XIsf_WriteParam WriteParam;
int Status;
WriteEnable(InstancePtr);
WriteParam.Address = Address;
WriteParam.NumBytes = ByteCount;
WriteParam.WritePtr = WriteBuffer;
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, Command, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/******************************************************************************
*
* This function reads from the serial FLASH connected to the
* SPI interface.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address to read data from in the FLASH.
* @param ByteCount contains the number of bytes to read.
* @param Command is the command used to read data from the flash. SPI
* device supports one of the Read, Fast Read, Dual Read and Fast
* Read commands to read data from the flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
{
XIsf_ReadParam ReadParam;
int Status;
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ByteCount;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the Read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, Command, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/******************************************************************************
*
*
* This function erases the sectors in the serial FLASH connected to the SPI
* interface.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address of the first sector which needs to
* be erased.
* @param ByteCount contains the total size to be erased.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount)
{
int Status;
int Sector;
/*
* If the erase size is less than the total size of the flash, use
* sector erase command
*/
for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) {
/*
* Write enable instruction has to be executed prior to
* any Write operation.
*/
WriteEnable(InstancePtr);
/*
* Perform the Sector Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Address += SECTOR_SIZE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function performs the write enable operation.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
*
******************************************************************************/
int WriteEnable(XIsf *InstancePtr)
{
int Status;
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system for an Spi device.
*
* @param IntcInstancePtr is a pointer to the instance of the Intc device.
* @param SpiInstancePtr is a pointer to the instance of the Spi device.
* @param SpiIntrId is the interrupt Id for an SPI device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None.
*
******************************************************************************/
static int SpiSetupIntrSystem(XScuGic *IntcInstancePtr,
XSpiPs *SpiInstancePtr, u16 SpiIntrId)
{
int Status;
XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */
Xil_ExceptionInit();
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
IntcInstancePtr);
/*
* Connect the device driver handler that will be called when an
* interrupt for the device occurs, the handler defined above performs
* the specific interrupt processing for the device.
*/
Status = XScuGic_Connect(IntcInstancePtr, SpiIntrId,
(Xil_ExceptionHandler)XSpiPs_InterruptHandler,
(void *)SpiInstancePtr);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Enable the interrupt for the Spi device.
*/
XScuGic_Enable(IntcInstancePtr, SpiIntrId);
/*
* Enable interrupts in the Processor.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function disables the interrupts that occur for the Spi device.
*
* @param IntcInstancePtr is the pointer to an INTC instance.
* @param SpiIntrId is the interrupt Id for an SPI device.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void SpiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 SpiIntrId)
{
/*
* Disable the interrupt for the SPI device.
*/
XScuGic_Disable(IntcInstancePtr, SpiIntrId);
/*
* Disconnect and disable the interrupt for the Spi device.
*/
XScuGic_Disconnect(IntcInstancePtr, SpiIntrId);
}

View file

@ -0,0 +1,480 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xilisf_spips_flash_polled_example.c
*
* This file contains a design example using the XILISF Library in
* interrupt mode with a serial FLASH device. This examples performs
* some transfers in Auto mode and Manual start mode, to illustrate the modes
* available.
* The hardware which this example runs on, must have a serial FLASH (Numonyx
* N25Q, Winbond W25Q, SST or Spansion S25FL) for it to run. This example has
* been tested with the SST Flash.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 srt 06/20/12 First release
* 3.01 srt 03/03/13 Modified the flash write, erase and read logic.
* Ensured flash blocks are unprotected befor a flash erase
* or write operation. (CR 703816)
* 3.02 srt 04/26/13 Modified Erase function to perform Write Enable operation
* for each sector erase.
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xscugic.h" /* Interrupt controller device driver */
#include "xil_exception.h"
#include "xil_printf.h"
#include <xilisf.h>
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID
/*
* The following constants define the offsets within a FlashBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the SPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define DATA_OFFSET 4 /* Start of Data for Read/Write */
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and
quad reads */
/*
* The following constants specify the page size, sector size, and number of
* pages and sectors for the FLASH. The page size specifies a max number of
* bytes that can be written to the FLASH with a single transfer.
*/
#define SECTOR_SIZE 0x1000
#define NUM_SECTORS 0x100
/*
* Flash address to which data is to be written.
*/
#define TEST_ADDRESS 0x00
#define UNIQUE_VALUE 0x05
/*
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the FLASH.
*/
#define MAX_DATA SECTOR_SIZE * NUM_SECTORS
/*
* The following constant defines the slave select signal that is used to
* to select the FLASH device on the SPI bus, this signal is typically
* connected to the chip select of the device
*/
#define FLASH_SPI_SELECT 0x01
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount);
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
int WriteEnable(XIsf *InstancePtr);
int SpiFlashPolledExample(XSpiPs *SpiInstancePtr, u16 SpiDeviceId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XSpiPs SpiInstance;
static XIsf Isf;
/*
* The following variables are used to read and write to the eeprom and they
* are global to avoid having large buffers on the stack
*/
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[MAX_DATA + DATA_OFFSET];
u8 IsfWriteBuffer[XISF_CMD_SEND_EXTRA_BYTES + 1];
/*****************************************************************************/
/**
*
* Main function to call the SPI Flash example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("SPI FLASH Polled Example Test \r\n");
/*
* Run the Spi Interrupt example.
*/
Status = SpiFlashPolledExample(&SpiInstance,SPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("SPI FLASH Polled Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran SPI FLASH Polled Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpiPs
* device driver in interrupt mode. This function writes and reads data
* from a serial FLASH.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
*
* This function calls other functions which contain loops that may be infinite
* if interrupts are not working such that it may not return. If the device
* slave select is not correct and the device is not responding on bus it will
* read a status of 0xFF for the status register as the bus is pulled up.
*
*****************************************************************************/
void FlashWriteSPI(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command);
int SpiFlashPolledExample(XSpiPs *SpiInstancePtr,
u16 SpiDeviceId)
{
u8 *BufferPtr;
u8 UniqueValue;
u32 Count;
XSpiPs_Config *ConfigPtr; /* Pointer to Configuration ROM data */
u32 TempAddress;
/*
* Lookup the device configuration in the temporary CROM table. Use this
* configuration info down below when initializing this component.
*/
ConfigPtr = XSpiPs_LookupConfig(SpiDeviceId);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
XSpiPs_CfgInitialize(SpiInstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
/* Initialize the XILISF Library */
XIsf_Initialize(&Isf, SpiInstancePtr, FLASH_SPI_SELECT,
IsfWriteBuffer);
memset(WriteBuffer, 0x00, sizeof(WriteBuffer));
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/* Unprotect Sectors */
FlashWrite(&Isf, 0, 0, XISF_WRITE_STATUS_REG);
FlashErase(&Isf, TEST_ADDRESS, MAX_DATA);
/*
* Initialize the write buffer for a pattern to write to the FLASH
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
TempAddress = TEST_ADDRESS;
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++, TempAddress++) {
WriteBuffer[0] = (u8)(UniqueValue);
FlashWrite(&Isf, TempAddress, 1, XISF_WRITE);
}
/*
* Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
* command
*/
FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Serial Flash is ready to accept next command.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Serial Flash and
waits till the WIP bit of the status register becomes 0.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Check if the flash is ready to accept the next command.
* If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}
/******************************************************************************
*
*
* This function writes to the serial FLASH connected to the SPI interface.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address to write data to in the FLASH.
* @param ByteCount contains the number of bytes to write.
* @param Command is the command used to write data to the flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashWrite(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
{
XIsf_WriteParam WriteParam;
int Status;
WriteEnable(InstancePtr);
WriteParam.Address = Address;
WriteParam.NumBytes = ByteCount;
WriteParam.WritePtr = WriteBuffer;
/*
* Perform the Write operation.
*/
Status = XIsf_Write(&Isf, Command, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/******************************************************************************
*
* This function reads from the serial FLASH connected to the
* SPI interface.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address to read data from in the FLASH.
* @param ByteCount contains the number of bytes to read.
* @param Command is the command used to read data from the flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashRead(XIsf *InstancePtr, u32 Address, u32 ByteCount, u8 Command)
{
XIsf_ReadParam ReadParam;
int Status;
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ByteCount;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the Read operation.
*/
Status = XIsf_Read(&Isf, Command, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/******************************************************************************
*
*
* This function erases the sectors in the serial FLASH connected to the
* SPI interface.
*
* @param InstancePtr is a pointer to the XIsf component to use.
* @param Address contains the address of the first sector which needs to
* be erased.
* @param ByteCount contains the total size to be erased.
*
* @return None.
*
* @note None.
*
******************************************************************************/
int FlashErase(XIsf *InstancePtr, u32 Address, u32 ByteCount)
{
int Status;
int Sector;
/*
* If the erase size is less than the total size of the flash, use
* sector erase command
*/
for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) {
/*
* Write enable instruction has to be executed prior to
* any Write operation.
*/
WriteEnable(InstancePtr);
/*
* Perform the Sector Erase operation.
*/
Status = XIsf_Erase(InstancePtr, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Address += SECTOR_SIZE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function performs the write enable operation.
*
* @param InstancePtr is a pointer to the XIsf component to use.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
*
******************************************************************************/
int WriteEnable(XIsf *InstancePtr)
{
int Status;
/*
* Perform the Write Enable operation.
*/
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,972 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_stm_quad_flash_example.c
*
* This file contains a design example using the In-system and Serial Flash
* Library (XilIsf) for Reading/Writing to a STM (Numonyx) N25QXX Quad Serial
* Flash Device. This example shows the Erase, Dual/Quad Read and Dual/Quad
* Write features.
*
* This example
* - Erases a Sector
* - Writes to a Page within the Erased Sector
* - Reads back the Page that is written and compares the data
*
* This example has been tested with a Numonyx Serial Flash Memory (N25Q128) on
* a Xilinx KC705 board. For further details about the Flash device refer the
* Numonyx Serial Flash Memory (N25Q128) data sheet.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 2.04a sdm 08/25/11 First release
* 3.02a adk 07/08/13 Fixed the CR 721229, by setting the proper QSPI options.
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes per page in the flash device.
*/
#define ISF_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_TEST_ADDRESS 0x010000;
#define ISF_TEST_BYTE 0x03 /* Test Byte value written */
/*
* The following definitions specify the number of dummy bytes associated with
* various Read commands and the number of dummy bytes to ignore in the data
* read from the flash, through those Read commands. This is apart from the
* dummy bytes returned in response to the command and address transmitted.
*/
/*
* After transmitting Dual Read command and address on DIO0, the quad spi
* device configures DIO0 and DIO1 in input mode and receives data on both
* DIO0 and DIO1 for 8 dummy clock cycles. So we end up with 16 dummy bits
* in DRR. The same logic applies for Dual IO Read (8 dummy clock cycles =
* 16 dummy bits), Quad Read command (8 dummy clock cycles = 32 dummy bits)
* and Quad IO Read command (10 dummy clock cycles = 40 dummy bits)
*/
/*
* The number of dummy cycles is configurable in the flash device. Please refer
* to the flash datasheet for more details.
*/
#define DUAL_READ_DUMMY_BYTES 2
#define DUAL_IO_READ_DUMMY_BYTES 2
#define QUAD_READ_DUMMY_BYTES 4
#define QUAD_IO_READ_DUMMY_BYTES 5
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
static int SetupInterruptSystem(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress; /* State of Spi Transfer */
static int ErrorCount; /* Errors occurred during Spi transfers */
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during Read/Write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 5]; /* Read Buffer */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Numonyx Quad Serial Flash Read/Write example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Set the QSPI options
*/
Status = XIsf_SetSpiConfiguration(&Isf, &Spi,
XSP_MASTER_OPTION | XSP_MANUAL_SSELECT_OPTION,
XISF_SPI_PRESCALER);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Initialize the Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = ISF_TEST_ADDRESS;
/*
* The following code Erases a Sector in the Numonyx Serial Flash.
*/
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - Number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_DUAL_IP_PAGE_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read from the flash using Dual Output Fast Read command.
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
* - Number of dummy bytes for the read command.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
ReadParam.NumDummyBytes = DUAL_READ_DUMMY_BYTES;
/*
* Clear the read Buffer.
*/
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
DUAL_READ_DUMMY_BYTES; Index++) {
ReadBuffer[Index] = 0x0;
}
/*
* Perform the read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_DUAL_OP_FAST_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
DUAL_READ_DUMMY_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Move to the next page in the flash.
*/
Address += ISF_PAGE_SIZE;
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - Number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_DUAL_IP_EXT_PAGE_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read from the flash using Dual Input/Output Fast Read command.
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
* - Number of dummy bytes for the read command.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
ReadParam.NumDummyBytes = DUAL_IO_READ_DUMMY_BYTES;
/*
* Clear the read Buffer.
*/
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
DUAL_IO_READ_DUMMY_BYTES; Index++) {
ReadBuffer[Index] = 0x0;
}
/*
* Perform the read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_DUAL_IO_FAST_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
DUAL_IO_READ_DUMMY_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Move to the next page in the flash.
*/
Address += ISF_PAGE_SIZE;
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - Number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_QUAD_IP_PAGE_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read from the flash using Quad Output Fast Read command.
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
* - Number of dummy bytes for the read command.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
ReadParam.NumDummyBytes = QUAD_READ_DUMMY_BYTES;
/*
* Clear the read Buffer.
*/
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
QUAD_READ_DUMMY_BYTES; Index++) {
ReadBuffer[Index] = 0x0;
}
/*
* Perform the read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_QUAD_OP_FAST_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
QUAD_READ_DUMMY_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Move to the next page in the flash.
*/
Address += ISF_PAGE_SIZE;
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - Number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_QUAD_IP_EXT_PAGE_WRITE,
(void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read from the flash using Quad Input/Output Fast Read command.
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
* - Number of dummy bytes for the read command.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
ReadParam.NumDummyBytes = QUAD_IO_READ_DUMMY_BYTES;
/*
* Clear the read Buffer.
*/
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
QUAD_IO_READ_DUMMY_BYTES; Index++) {
ReadBuffer[Index] = 0x0;
}
/*
* Perform the read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_QUAD_IO_FAST_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
QUAD_IO_READ_DUMMY_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Numonyx serial Flash is ready to accept next
* command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Serial Flash and
* waits till the Serial Flash is ready to accept next command.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the Serial Flash is ready to accept the next
* command. If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specify real mode so that
* the SPI can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,383 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_stm_rdwr_polled_example.c
*
* This file contains a design example using the In-system and Serial Flash
* Library (XilIsf) for Reading/Writing to a STM (Numonyx) M25P16 Serial Flash
* Device with the Spi driver in polled mode of operation. This example shows
* the Erase, Read and Write features.
*
* This example
* - Erases a Sector
* - Writes to a Page within the Erased Sector
* - Reads back the Page that is written and compares the data.
*
* This example has been tested with a STM (Numonyx) M25P16 device on a Xilinx
* Spartan-3A Starter Kit board and AC701 board with a Micron flash N25Q256A
* (32MB, supporting 4 Byte addressing mode).
*
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a sdm 04/02/08 First release
* 2.00a ktn 11/22/09 The Spi Driver APIs have changed. Replaced the call
* to XSpi_mIntrGlobalDisable with XSpi_IntrGlobalDisable.
* 5.2 asa 05/12/15 Added support for Micron N25Q256A flash part which
* supports 4 byte addressing.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xilisf.h" /* Serial Flash Library header file */
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes per page in the flash device.
*/
#define ISF_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_TEST_ADDRESS 0x010000;
#define ISF_TEST_BYTE 0x36 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XSpi Spi;
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
* For 4 byte addressing mode support, to account for the extra address bye
* the buffer size is incremented by 1.
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1];
/*
* Buffers used during Read/Write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1]; /* Read Buffer */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the STM Serial Flash Read/Write polled example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that the device is enabled.
*/
XSpi_Start(&Spi);
/*
* Disable Global interrupt to use the Spi driver in polled mode
* operation.
*/
XSpi_IntrGlobalDisable(&Spi);
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = ISF_TEST_ADDRESS;
/*
* Check is the flash part is micron in which case, switch to 4 byte
* addressing mode.
*/
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
XIsf_MicronFlashEnter4BAddMode(&Isf);
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
}
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - Number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written. For Micron flash
* which supports 4 Byte mode, comparison should take care of the extra
* address byte.
*/
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
} else {
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
}
/*
* For micron flash part supporting 4 byte ddressing mode, exit from
* 4 Byte mode.
*/
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
XIsf_MicronFlashExit4BAddMode(&Isf);
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the STM serial Flash is ready to accept next command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Serial Flash and
* waits till the Serial Flash is ready to accept next command.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Check if the Serial Flash is ready to accept the next
* command. If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,585 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_stm_read_write_example.c
*
* This file contains a design example using the In-system and Serial Flash
* Library (XilIsf) for Reading/Writing to a STM (Numonyx) M25P16 Serial Flash
* Device. This example shows the Erase, Read and Write features.
*
* This example
* - Erases a Sector
* - Writes to a Page within the Erased Sector
* - Reads back the Page that is written and compares the data
*
* This example has been tested with a STM (Numonyx) M25P16 device on Xilinx
* Spartan-3A Starter Kit board.
*
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sdm 03/17/08 First release
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
* 5.2 asa 05/12/15 Added support for Micron N25Q256A flash.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes per page in the flash device.
*/
#define ISF_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_TEST_ADDRESS 0x010000;
#define ISF_TEST_BYTE 0x05 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
static int SetupInterruptSystem(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress; /* State of Spi Transfer */
static int ErrorCount; /* Errors occurred during Spi transfers */
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1];
/*
* Buffers used during Read/Write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 1]; /* Read Buffer */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the STM Serial Flash Read/Write example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Initialize the Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = ISF_TEST_ADDRESS;
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Check is the flash part is micron in which case, switch to 4 byte
* addressing mode.
*/
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
TransferInProgress = TRUE;
XIsf_MicronFlashEnter4BAddMode(&Isf);
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
}
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - Number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
} else {
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
}
if (Isf.ManufacturerID == XISF_MANUFACTURER_ID_MICRON) {
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
TransferInProgress = TRUE;
XIsf_MicronFlashExit4BAddMode(&Isf);
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the STM serial Flash is ready to accept next command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Serial Flash and
* waits till the Serial Flash is ready to accept next command.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the Serial Flash is ready to accept the next
* command. If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specify real mode so that
* the SPI can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,754 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_stm_spr_example.c
*
* This file contains a design example using the Xilinx In-system and Serial
* Flash Library (XilIsf). This example shows the usage of Sector Erase, Sector
* Protection, Read and Write features.
* This example
* - Erases a Sector
* - Writes to a Page within the erased Sector
* - Enables the Sector Protection so that all the sectors are Write protected
* - Erases a Page (This should not happen as the Sectors are Write protected
* - Reads back the Page that is written and compares the data.
*
* This example has been tested with a STM (Numonyx) Serial Flash Memory
* (M25P16) on a Xilinx Spartan-3A Starter Kit board. For further details about
* the Flash device refer to the STM (Numonyx) Serial Flash Memory (M25P16)
* data sheet.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sdm 03/17/08 First release
* 2.00a ktn 11/22/09 Updated to use HAL processor APIs.
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include "xspi.h" /* SPI device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Serial Flash on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes per page in the Serial Flash.
*/
#define ISF_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_TEST_ADDRESS 0x010000;
#define ISF_TEST_BYTE 0x15 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
static int SetupInterruptSystem(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress;
/*
* The following variable tracks any errors that occur during interrupt
* processing.
*/
static int ErrorCount;
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
u8 WriteBuffer[ISF_PAGE_SIZE];
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the STM Serial Flash SPR example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Initialize the Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = ISF_TEST_ADDRESS;
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - Number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data that needs to be written
* to the Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read the sector protection register.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Set all the block protection bits in the sector protection register
* value read above and write it back to the sector protection register
* to disable protection for all sectors.
*/
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] |
(XISF_SR_BLOCK_PROTECT_MASK);
/*
* Enable the sector protection.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation. This should not work as sector
* protection is enabled for all the sectors.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read the sector protection register.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Clear all the block protection bits in the sector protection register
* value read above and write it back to the sector protection register
* to disable protection for all sectors.
*/
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
~(XISF_SR_BLOCK_PROTECT_MASK);
/*
* Disable the sector protection.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the Read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the STM Serial Flash is ready to accept next command.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Serial Flash and
waits till the WIP bit of the status register becomes 0.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is in progress.
*/
while(TransferInProgress);
/*
* Check if there are any errors in the transaction.
*/
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the flash is ready to accept the next command.
* If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the SPI can cause interrupts thru the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,849 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_winbond_quad_flash_example.c
*
* This file contains a design example using the In-system and Serial Flash
* Library (XilIsf) for Reading/Writing to a Winbond W25QXX Quad Serial Flash
* Device. This example shows the Erase, Dual/Quad Read and Quad Write
* features.
*
* This example
* - Erases a Sector
* - Writes to a Page within the Erased Sector
* - Reads back the Page that is written and compares the data
*
* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on
* a Xilinx SP605 board. For further details about the Flash device refer the
* Winbond Serial Flash Memory (W25Q64) data sheet.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 2.04a sdm 08/25/11 First release
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes per page in the flash device.
*/
#define ISF_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_TEST_ADDRESS 0x010000;
#define ISF_TEST_BYTE 0x03 /* Test Byte value written */
/*
* The following definitions specify the number of dummy bytes to ignore in the
* data read from the flash, through various Read commands. This is apart from
* the dummy bytes returned in reponse to the command and address transmitted.
*/
/*
* After transmitting Dual Read command and address on DIO0, the quad spi device
* configures DIO0 and DIO1 in input mode and receives data on both DIO0 and
* DIO1 for 8 dummy clock cycles. So we end up with 16 dummy bits in DRR. The
* same logic applies Quad read command, so we end up with 4 dummy bytes in that
* case.
*/
/*
* Please refer to the flash datasheet for more details about the number of dummy
* cycles associated with each command.
*/
#define DUAL_READ_DUMMY_BYTES 2
#define QUAD_READ_DUMMY_BYTES 4
#define DUAL_IO_READ_DUMMY_BYTES 1
#define QUAD_IO_READ_DUMMY_BYTES 3
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
static int SpiFlashQuadEnable(void);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
static int SetupInterruptSystem(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress; /* State of Spi Transfer */
static int ErrorCount; /* Errors occurred during Spi transfers */
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during Read/Write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES + 4]; /* Read Buffer */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Winbond Quad Serial Flash Read/Write example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Initialize the Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = ISF_TEST_ADDRESS;
/*
* The following code Erases a Sector in the Winbond Serial Flash.
*/
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the Quad Enable (QE) bit in the flash device, so that Quad
* operations can be perfomed on the flash.
*/
Status = SpiFlashQuadEnable();
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - Number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_QUAD_IP_PAGE_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read from the flash using Dual Output Fast Read command.
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
* - Number of dummy bytes for the read command.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
ReadParam.NumDummyBytes = DUAL_READ_DUMMY_BYTES;
/*
* Clear the read Buffer.
*/
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
DUAL_READ_DUMMY_BYTES; Index++) {
ReadBuffer[Index] = 0x0;
}
/*
* Perform the read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_DUAL_OP_FAST_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
DUAL_READ_DUMMY_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
/*
* Enable High Performance Mode so that data can be read from the flash
* using DIO and QIO read commands.
*/
TransferInProgress = TRUE;
Status = XIsf_Ioctl(&Isf, XISF_IOCTL_ENABLE_HI_PERF_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read from the flash using Dual Input/Output Fast Read command.
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
* - Number of dummy bytes for the read command.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
ReadParam.NumDummyBytes = DUAL_IO_READ_DUMMY_BYTES;
/*
* Clear the read Buffer.
*/
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
DUAL_IO_READ_DUMMY_BYTES; Index++) {
ReadBuffer[Index] = 0x0;
}
/*
* Perform the read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_DUAL_IO_FAST_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
DUAL_IO_READ_DUMMY_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
/*
* Read from the flash using Quad Output Fast Read command.
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
* - Number of dummy bytes for the read command.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
ReadParam.NumDummyBytes = QUAD_READ_DUMMY_BYTES;
/*
* Clear the read Buffer.
*/
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
QUAD_READ_DUMMY_BYTES; Index++) {
ReadBuffer[Index] = 0x0;
}
/*
* Perform the read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_QUAD_OP_FAST_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
QUAD_READ_DUMMY_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
/*
* Read from the flash using Quad Input/Output Fast Read command.
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
* - Number of dummy bytes for the read command.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
ReadParam.NumDummyBytes = QUAD_IO_READ_DUMMY_BYTES;
/*
* Clear the read Buffer.
*/
for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
QUAD_IO_READ_DUMMY_BYTES; Index++) {
ReadBuffer[Index] = 0x0;
}
/*
* Perform the read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_QUAD_IO_FAST_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
QUAD_IO_READ_DUMMY_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Winbond serial Flash is ready to accept next
* command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Serial Flash and
* waits till the Serial Flash is ready to accept next command.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the Serial Flash is ready to accept the next
* command. If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function sets the QuadEnable bit in Winbond flash.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
static int SpiFlashQuadEnable(void)
{
int Status;
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = 0x00;
WriteBuffer[BYTE2] = 0x02; /* QE = 1 */
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_WRITE_STATUS_REG2, (void*) WriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specify real mode so that
* the SPI can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,355 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_winbond_rdwr_polled_example.c
*
* This file contains a design example using the In-system and Serial Flash
* Library (XilIsf) for Reading/Writing to a Winbond W25QXX/W25XX Serial Flash
* Device with the Spi driver in polled mode of operation. This example shows
* the Erase, Read and Write features.
*
* This example
* - Erases a Sector
* - Writes to a Page within the Erased Sector
* - Reads back the Page that is written and compares the data
*
* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on
* a Xilinx SP605 board. For further details about the Flash device refer the
* Winbond Serial Flash Memory (W25Q64) data sheet.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 2.01a sdm 03/17/10 First release
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xilisf.h" /* Serial Flash Library header file */
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes per page in the flash device.
*/
#define ISF_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_TEST_ADDRESS 0x010000;
#define ISF_TEST_BYTE 0x36 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XSpi Spi;
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during Read/Write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Winbond Serial Flash Read/Write polled example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that the device is enabled.
*/
XSpi_Start(&Spi);
/*
* Disable Global interrupt to use the Spi driver in polled mode
* operation.
*/
XSpi_IntrGlobalDisable(&Spi);
/*
* Initialize the Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = ISF_TEST_ADDRESS;
/*
* The following code Erases a Sector in the Winbond Serial Flash.
*/
/*
* Perform the Write Enable operation.
*/
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation.
*/
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - Number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the read operation.
*/
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Winbond serial Flash is ready to accept next
* command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Serial Flash and
* waits till the Serial Flash is ready to accept next command.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Check if the Serial Flash is ready to accept the next
* command. If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,555 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_winbond_read_write_example.c
*
* This file contains a design example using the In-system and Serial Flash
* Library (XilIsf) for Reading/Writing to a Winbond W25QXX/W25XX Serial Flash
* Device. This example shows the Erase, Read and Write features.
*
* This example
* - Erases a Sector
* - Writes to a Page within the Erased Sector
* - Reads back the Page that is written and compares the data
*
* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on
* a Xilinx SP605 board. For further details about the Flash device refer the
* Winbond Serial Flash Memory (W25Q64) data sheet.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 2.01a sdm 03/17/10 First release
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Flash device on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes per page in the flash device.
*/
#define ISF_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_TEST_ADDRESS 0x010000;
#define ISF_TEST_BYTE 0x05 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
static int SetupInterruptSystem(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress; /* State of Spi Transfer */
static int ErrorCount; /* Errors occurred during Spi transfers */
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during Read/Write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES]; /* Read Buffer */
u8 WriteBuffer[ISF_PAGE_SIZE]; /* Write buffer */
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Winbond Serial Flash Read/Write example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Initialize the Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = ISF_TEST_ADDRESS;
/*
* The following code Erases a Sector in the Winbond Serial Flash.
*/
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - Number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data need to be written into
* Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data Written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Winbond serial Flash is ready to accept next
* command.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Serial Flash and
* waits till the Serial Flash is ready to accept next command.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check for errors.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the Serial Flash is ready to accept the next
* command. If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specify real mode so that
* the SPI can cause interrupts through the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,754 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************
*
* @file xilisf_winbond_spr_example.c
*
* This file contains a design example using the Xilinx In-system and Serial
* Flash Library (XilIsf). This example shows the usage of Sector Erase, Sector
* Protection, Read and Write features on a Winbond W25QXX/W25XX Serial Flash
* Device.
* This example
* - Erases a Sector
* - Writes to a Page within the erased Sector
* - Enables the Sector Protection so that all the sectors are Write protected
* - Erases a Page (This should not happen as the Sectors are Write protected
* - Reads back the Page that is written and compares the data
*
* This example has been tested with a Winbond Serial Flash Memory (W25Q64) on
* a Xilinx SP605 board. For further details about the Flash device refer the
* Winbond Serial Flash Memory (W25Q64) data sheet.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 2.01a sdm 03/17/10 First release
* 5.0 sb 08/05/14 Registering to Xilisf Interrupt handler
* instead of driver handler.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xintc.h" /* Interrupt controller device driver */
#include "xspi.h" /* SPI device driver */
#include <xilisf.h> /* Serial Flash Library header file */
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_SPI_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#define SPI_INTR_ID XPAR_INTC_0_SPI_0_VEC_ID
/*
* The following constant defines the slave select signal that is used to
* to select the Serial Flash on the SPI bus, this signal is typically
* connected to the chip select of the device.
*/
#define ISF_SPI_SELECT 0x01
/*
* Number of bytes per page in the Serial Flash.
*/
#define ISF_PAGE_SIZE 256
/*
* Address of the page to perform Erase, Write and Read operations.
*/
#define ISF_TEST_ADDRESS 0x010000;
#define ISF_TEST_BYTE 0x15 /* Test Byte offset value written */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int IsfWaitForFlashNotBusy(void);
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount);
static int SetupInterruptSystem(XSpi *SpiPtr);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XIsf Isf;
static XIntc InterruptController;
static XSpi Spi;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile static int TransferInProgress;
/*
* The following variable tracks any errors that occur during interrupt
* processing.
*/
static int ErrorCount;
/*
* The user needs to allocate a buffer to be used by the In-system and Serial
* Flash Library to perform any read/write operations on the Serial Flash
* device.
* User applications must pass the address of this memory to the Library in
* Serial Flash Initialization function, for the Library to work.
* For Write operations:
* - The size of this buffer should be equal to the Number of bytes to be
* written to the Serial Flash + XISF_CMD_MAX_EXTRA_BYTES.
* - The size of this buffer should be large enough for usage across all the
* applications that use a common instance of the Serial Flash.
* - A minimum of one byte and a maximum of ISF_PAGE_SIZE bytes can be written
* to the Serial Flash, through a single Write operation.
* The size of this buffer should be equal to XISF_CMD_MAX_EXTRA_BYTES, if the
* application only reads from the Serial Flash (no write operations).
*/
u8 IsfWriteBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
/*
* Buffers used during read and write transactions.
*/
u8 ReadBuffer[ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES];
u8 WriteBuffer[ISF_PAGE_SIZE];
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* Main function to execute the Winbond Serial Flash SPR example.
*
* @param None
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main()
{
int Status;
u32 Index;
u32 Address;
XIsf_WriteParam WriteParam;
XIsf_ReadParam ReadParam;
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the SPI driver to the interrupt subsystem such that
* interrupts can occur. This function is application specific.
*/
Status = SetupInterruptSystem(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the interrupt
* context when an SPI status occurs, specify a pointer to the SPI
* driver instance as the callback reference so the handler is able to
* access the instance data.
*/
XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
/*
* Initialize the Serial Flash Library.
*/
Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set The transfer Mode to Interrupt
*/
XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);
/*
* Specify the address in the Serial Flash for the Erase/Write/Read
* operations.
*/
Address = ISF_TEST_ADDRESS;
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address within the Serial Flash where the data is to be written.
* - Number of bytes to be written to the Serial Flash.
* - Write Buffer which contains the data to be written to the Serial
* Flash.
*/
WriteParam.Address = Address;
WriteParam.NumBytes = ISF_PAGE_SIZE;
WriteParam.WritePtr = WriteBuffer;
/*
* Prepare the write buffer. Fill in the data that needs to be written
* to the Serial Flash.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
}
/*
* Perform the Write operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Write(&Isf, XISF_WRITE, (void*) &WriteParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read the sector protection register.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Set all the block protection bits in the sector protection register
* value read above and write it back to the sector protection register
* to disable protection for all sectors.
*/
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] |
(XISF_SR_BLOCK_PROTECT_MASK);
/*
* Enable the sector protection.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Write Enable operation.
*/
TransferInProgress = TRUE;
Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform the Sector Erase operation. This should not work as sector
* protection is enabled for all the sectors.
*/
TransferInProgress = TRUE;
Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Read the sector protection register.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_READ, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Clear all the block protection bits in the sector protection register
* value read above and write it back to the sector protection register
* to disable protection for all sectors.
*/
WriteBuffer[BYTE1] = ReadBuffer[BYTE2] &
~(XISF_SR_BLOCK_PROTECT_MASK);
/*
* Disable the sector protection.
*/
TransferInProgress = TRUE;
Status = XIsf_SectorProtect(&Isf, XISF_SPR_WRITE, WriteBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Wait till the Flash is not Busy.
*/
Status = IsfWaitForFlashNotBusy();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the
* - Address in the Serial Flash where the data is to be read from.
* - Number of bytes to be read from the Serial Flash.
* - Read Buffer to which the data is to be read.
*/
ReadParam.Address = Address;
ReadParam.NumBytes = ISF_PAGE_SIZE;
ReadParam.ReadPtr = ReadBuffer;
/*
* Perform the Read operation.
*/
TransferInProgress = TRUE;
Status = XIsf_Read(&Isf, XISF_READ, (void*) &ReadParam);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is complete and check if there are any errors
* in the transaction.
*/
while(TransferInProgress);
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Compare the data read against the data written.
*/
for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES] !=
(u8)(Index + ISF_TEST_BYTE)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function waits till the Winbond Serial Flash is ready to accept the next
* command.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This function reads the status register of the Serial Flash and
waits till the WIP bit of the status register becomes 0.
*
******************************************************************************/
int IsfWaitForFlashNotBusy(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register.
*/
TransferInProgress = TRUE;
Status = XIsf_GetStatus(&Isf, ReadBuffer);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait till the Transfer is in progress.
*/
while(TransferInProgress);
/*
* Check if there are any errors in the transaction.
*/
if(ErrorCount != 0) {
return XST_FAILURE;
}
/*
* Check if the flash is ready to accept the next command.
* If so break.
*/
StatusReg = ReadBuffer[BYTE2];
if((StatusReg & XISF_SR_IS_READY_MASK) == 0) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts and
* is application specific.
*
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param StatusEvent is the event that just occurred.
* @param ByteCount is the number of bytes transferred up until the event
* occurred.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, u16 ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event.
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error.
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
ErrorCount++;
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system such that interrupts can occur
* for the Spi device. This function is application specific since the actual
* system may or may not have an interrupt controller. The Spi device could be
* directly connected to a processor without an interrupt controller. The
* user should modify this function to fit the application.
*
* @param SpiPtr is a pointer to the instance of the Spi device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
static int SetupInterruptSystem(XSpi *SpiPtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that
* it's ready to use, specify the device ID that is generated in
* xparameters.h.
*/
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device.
*/
Status = XIntc_Connect(&InterruptController,
SPI_INTR_ID,
(XInterruptHandler)XSpi_InterruptHandler,
(void *)SpiPtr);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the SPI can cause interrupts thru the interrupt controller.
*/
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the SPI.
*/
XIntc_Enable(&InterruptController, SPI_INTR_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XIntc_InterruptHandler,
&InterruptController);
/*
* Enable non-critical exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,89 @@
###############################################################################
#
# Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I${INCLUDEDIR}
ISF_DIR = .
LIB_SRCS = $(ISF_DIR)/xilisf.c \
$(ISF_DIR)/xilisf_read.c \
$(ISF_DIR)/xilisf_erase.c \
$(ISF_DIR)/xilisf_write.c \
$(ISF_DIR)/xilisf_spr.c
# create ISF_SRCS based on configured options
ISF_SRCS = $(LIB_SRCS)
ISF_OBJS = $(ISF_SRCS:%.c=%.o)
EXPORT_INCLUDE_FILES = $(ISF_DIR)/include/xilisf.h \
$(ISF_DIR)/include/xilisf_atmel.h \
$(ISF_DIR)/include/xilisf_intelstm.h
libs: libxilisf.a
cp libxilisf.a $(RELEASEDIR)
make clean
include:
@for i in $(EXPORT_INCLUDE_FILES); do \
echo ${CP} -r $$i ${INCLUDEDIR}; \
${CP} -r $$i ${INCLUDEDIR}; \
done
clean:
rm -rf obj/*.o
rmdir obj
rm libxilisf.a
libxilisf.a: obj_dir print_msg_isf_base $(ISF_OBJS)
@echo "Creating archive $@"
$(ARCHIVER) rc $@ obj/*.o
obj_dir:
mkdir obj
print_msg_isf_base:
@echo "Compiling XilIsf Library"
.c.o:
$(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) -c $< -o obj/$(@F)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,268 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xilisf_atmel.h
*
* This file contains the definitions to be used when accessing the Atmel
* AT45XXXD Serial Flash.
* If any new definitions are added to this file, check if they need to be
* added to the xilisf_intelstm.h file too.
*
* @note None
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- -----------------------------------------------
* 1.00a ksu/sdm 03/03/08 First release
*
* </pre>
*
******************************************************************************/
#ifndef XILISF_ATMEL_H /* prevent circular inclusions */
#define XILISF_ATMEL_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
/************************** Constant Definitions *****************************/
/**
* The following definitions specify the Device Id for the different Atmel
* AT45XXXD Serial Flash Devices.
*/
#define XISF_ATMEL_DEV_AT45DB011D 0x22 /**< Device ID of AT45DB011D */
#define XISF_ATMEL_DEV_AT45DB021D 0x23 /**< Device ID of AT45DB027D */
#define XISF_ATMEL_DEV_AT45DB041D 0x24 /**< Device ID of AT45DB041D */
#define XISF_ATMEL_DEV_AT45DB081D 0x25 /**< Device ID of AT45DB081D */
#define XISF_ATMEL_DEV_AT45DB161D 0x26 /**< Device ID of AT45DB161D */
#define XISF_ATMEL_DEV_AT45DB321D 0x27 /**< Device ID of AT45DB321D */
#define XISF_ATMEL_DEV_AT45DB642D 0x28 /**< Device ID of AT45DB642D */
/**
* Definitions of Atmel Serial Flash Device geometry.
*/
#define XISF_BYTES256_PER_PAGE 256 /**< 256 Bytes per Page */
#define XISF_BYTES264_PER_PAGE 264 /**< 264 Bytes per Page */
#define XISF_BYTES512_PER_PAGE 512 /**< 512 Bytes per Page */
#define XISF_BYTES528_PER_PAGE 528 /**< 528 Bytes per Page */
#define XISF_BYTES1024_PER_PAGE 1024 /**< 1024 Bytes per Page */
#define XISF_BYTES1056_PER_PAGE 1056 /**< 1056 Bytes per Page */
#define XISF_PAGES8_PER_BLOCK 8 /**< Pages per Block */
#define XISF_BLOCKS16_PER_SECTOR 16 /**< 16 Blocks per Sector */
#define XISF_BLOCKS32_PER_SECTOR 32 /**< 32 Blocks per Sector */
#define XISF_NUM_OF_SECTORS4 4 /**< 4 Sectors */
#define XISF_NUM_OF_SECTORS8 8 /**< 8 Sectors */
#define XISF_NUM_OF_SECTORS16 16 /**< 16 Sectors */
#define XISF_NUM_OF_SECTORS32 32 /**< 32 Sectors */
#define XISF_NUM_OF_SECTORS64 64 /**< 64 Sectors */
/**
* Definitions of Bit masks used for calculating device address from a
* linear address in the case of Default Addressing mode .
*/
#define XISF_BYTES256_PER_PAGE_MASK 0x0FF /**< Byte mask for devices with
* 256 or less bytes per page
*/
#define XISF_BYTES512_PER_PAGE_MASK 0x1FF /**< Byte mask for devices with
* more than 256 bytes per
* page */
#define XISF_BYTES1024_PER_PAGE_MASK 0x3FF /**< Byte mask for devices with
* more than 512 bytes per
* page */
#define XISF_BYTES2048_PER_PAGE_MASK 0x7FF /**< Byte mask for devices with
* more than 1024 bytes per
* page */
/**
* Definitions of Read commands.
*/
#define XISF_CMD_RANDOM_READ 0x03 /**< Random Read command */
#define XISF_CMD_FAST_READ 0x0B /**< Fast Read command */
#define XISF_CMD_ISFINFO_READ 0x9F /**< Device Info command */
#define XISF_CMD_PAGETOBUF1_TRANS 0x53 /**< Transfer contents of a Page
* to the Buffer 1 command */
#define XISF_CMD_PAGETOBUF2_TRANS 0x55 /**< Transfer contents of a Page
* to the Buffer 2 command */
#define XISF_CMD_BUF1_READ 0xD1 /**< Buffer 1 Read command */
#define XISF_CMD_BUF2_READ 0xD3 /**< Buffer 2 Read command */
#define XISF_CMD_FAST_BUF1_READ 0xD4 /**< Fast Buffer 1 Read Cmd */
#define XISF_CMD_FAST_BUF2_READ 0xD6 /**< Fast Buffer 2 Read Cmd */
#define XISF_CMD_STATUSREG_READ 0xD7 /**< Status Greg Read Cmd */
/**
* Definitions of Write commands.
*/
#define XISF_CMD_PAGEPROG_WRITE 0x82 /**< Page Program command */
#define XISF_CMD_AUTOPAGE_WRITE 0x58 /**< Auto write command */
#define XISF_CMD_BUFFER1_WRITE 0x84 /**< Buffer1 write command */
#define XISF_CMD_BUFFER2_WRITE 0x87 /**< Buffer2 write command */
#define XISF_CMD_ERASE_BUF1TOPAGE_WRITE 0x83 /**< Erase page first then write
* buffer 1 to the page
* command */
#define XISF_CMD_ERASE_BUF2TOPAGE_WRITE 0x86 /**< Erase page first then write
* buffer2 to the page
* command */
#define XISF_CMD_BUF1TOPAGE_WRITE 0x88 /**< Write buffer1 to the page
* command without Erase */
#define XISF_CMD_BUF2TOPAGE_WRITE 0x89 /**< Write buffer2 to the page
* command without Erase */
/**
* Definitions of Erase commands.
*/
#define XISF_CMD_PAGE_ERASE 0x81 /**< Page Erase command */
#define XISF_CMD_BLOCK_ERASE 0x50 /**< Block erase command */
#define XISF_CMD_SECTOR_ERASE 0x7C /**< Sector Erase command */
/**
* Definitions of commands used for
* - Erasing SPR
* - Programming SPR
* - Enabling/Disabling SPR.
*/
#define XISF_CMD_SPR_BYTE1 0x3D /**< SPR command byte1 */
#define XISF_CMD_SPR_BYTE2 0x2A /**< SPR command byte2 */
#define XISF_CMD_SPR_BYTE3 0x7F /**< SPR command byte3 */
#define XISF_CMD_SPR_BYTE4_ERASE 0xCF /**< SPR erase command */
#define XISF_CMD_SPR_BYTE4_PROGRAM 0xFC /**< SPR program command */
#define XISF_CMD_SPR_BYTE4_ENABLE 0xA9 /**< SPR enable command */
#define XISF_CMD_SPR_BYTE4_DISABLE 0x9A /**< SPR disable command */
/**
* Definitions of command used for reading SPR.
*/
#define XISF_CMD_SPR_READ 0x32 /**< SPR read command */
/**
* The following definitions specify the buffer number of Atmel Serial Flash.
*/
#define XISF_PAGE_BUFFER1 1 /**< Buffer 1 */
#define XISF_PAGE_BUFFER2 2 /**< Buffer 2 */
/**
* The following definitions specify the Status Register bit definitions of
* Atmel Serial Flash.
*/
#define XISF_SR_ADDR_MODE_MASK 0x01 /**< Address mode mask */
#define XISF_SR_COMPARE_MASK 0x40 /**< Compare mask */
#define XISF_SR_IS_READY_MASK 0x80 /**< Ready mask */
#define XISF_SR_DEVID_MASK 0x2C /**< Device ID mask */
#define XISF_SR_DEVID_SHIFT_MASK 0x02 /**< Device ID shift mask */
/**
* The following definitions determine the addressing mode of the Atmel Serial
* Flash.
*/
#define XISF_POWEROFTWO_ADDRESS 0x01 /**< Pow-Of-2 address mask */
#define XISF_DEFAULT_ADDRESS 0x00 /**< Default address mask */
/**
* This definitions specify the extra bytes in each of the Write command, Read
* command, Erase command, commands operating on SPR, auto page write, page to
* buffer and buffer to page transfer commands. This count includes
* Command byte, address bytes and any don't care bytes needed.
*/
#define XISF_CMD_SEND_EXTRA_BYTES 4 /**< Command extra bytes */
/**
* This definition specifies the extra bytes in each of the Write/Read/Erase
* commands, commands operating on SPR, auto page write, page to
* buffer and buffer to page transfer commands in 4 bytes addressing mode.
* This count includes Command byte, Address bytes and any
* don't care bytes needed.
*/
#define XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE 5 /**< Command extra bytes */
/**
* This definitions specify the extra bytes in Fast read Fast buffer read
* commands. This count includes Command byte, address bytes and any don't care
* bytes needed.
*/
#define XISF_CMD_FAST_READ_EXTRA_BYTES 5 /**< Fast read and Fast buffer
* read extra bytes */
/**
* The following definitions specify the total bytes in some of the commands.
* This count includes Command byte and any don't care bytes needed.
*/
#define XISF_STATUS_RDWR_BYTES 2 /**< Status Read/Write bytes
* count */
#define XISF_INFO_READ_BYTES 5 /**< Flash Info Read bytes
* count */
#define XISF_INFO_EXTRA_BYTES 1 /**< Flash Info Read Extra
* bytes */
#define XISF_CMD_MAX_EXTRA_BYTES 5 /**< Max extra bytes for
* all commands */
#define XISF_DUMMYBYTE 0xFF /**< Dummy byte to fill */
/**
* Address Shift Masks.
*/
#define XISF_ADDR_SHIFT16 16 /**< 16 bit Shift */
#define XISF_ADDR_SHIFT8 8 /**< 8 bit Shift */
/**
* Byte Positions.
*/
#define BYTE1 0 /**< Byte 1 position */
#define BYTE2 1 /**< Byte 2 position */
#define BYTE3 2 /**< Byte 3 position */
#define BYTE4 3 /**< Byte 4 position */
#define BYTE5 4 /**< Byte 5 position */
/**************************** Type Definitions *******************************/
/************************** Variable Definitions *****************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,365 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xilisf_intelstm.h
*
* This file contains the definitions to be used when accessing the Intel, STM,
* Winbond and Spansion Serial Flash.
* If any new definitions are added to this file, check if they need to be
* added to the xilisf_atmel.h file too.
*
* @note None
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- -----------------------------------------------
* 1.00a ksu/sdm 03/03/08 First release
* 2.01a sdm 01/04/10 Added Support for Winbond W25QXX/W25XX devices
* 2.04a sdm 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
* flash memories
* 3.00a srt 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
* Added support to SST flash on SPI PS interface.
* 3.02a srt 04/26/13 Modified SECTOR and BLOCK Erase commands for
* SST flash (CR 703816).
* 5.2 asa 05/12/15 Added macros for 4 byte commands.
* </pre>
*
******************************************************************************/
#ifndef XILISF_INTELSTM_H /* prevent circular inclusions */
#define XILISF_INTELSTM_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
/************************** Constant Definitions *****************************/
/**
* The following definitions specify the Device Id for the different
* Intel (Numonyx) S33 Serial Flash devices.
*/
#define XISF_INTEL_DEV_S3316MBIT 0x11 /**< Device ID for 16Mbit */
#define XISF_INTEL_DEV_S3332MBIT 0x12 /**< Device ID for 32Mbit */
#define XISF_INTEL_DEV_S3364MBIT 0x13 /**< Device ID for 64Mbit */
/**
* The following definitions specify the Device Id for the different
* STM (Numonyx) M25PXX Serial Flash devices.
*/
#define XISF_STM_DEV_M25P05_A 0x2010 /**< Device ID for M25P05-A */
#define XISF_STM_DEV_M25P10_A 0x2011 /**< Device ID for M25P10-A */
#define XISF_STM_DEV_M25P20 0x2012 /**< Device ID for M25P20 */
#define XISF_STM_DEV_M25P40 0x2013 /**< Device ID for M25P40 */
#define XISF_STM_DEV_M25P80 0x2014 /**< Device ID for M25P80 */
#define XISF_STM_DEV_M25P16 0x2015 /**< Device ID for M25P16 */
#define XISF_STM_DEV_M25P32 0x2016 /**< Device ID for M25P32 */
#define XISF_STM_DEV_M25P64 0x2017 /**< Device ID for M25P64 */
#define XISF_STM_DEV_M25P128 0x2018 /**< Device ID for M25P128 */
/**
* The following definitions specify the Device Id (memory type/capacity)
* for the different Winbond W25QX/W25XX Serial Flash devices.
*/
#define XISF_WB_DEV_W25Q80 0x4014 /**< Device ID for W25Q80 */
#define XISF_WB_DEV_W25Q16 0x4015 /**< Device ID for W25Q16 */
#define XISF_WB_DEV_W25Q32 0x4016 /**< Device ID for W25Q32 */
#define XISF_WB_DEV_W25Q64 0x4017 /**< Device ID for W25Q64 */
#define XISF_WB_DEV_W25Q128 0x4018 /**< Device ID for W25Q128 */
#define XISF_WB_DEV_W25X10 0x3011 /**< Device ID for W25X10 */
#define XISF_WB_DEV_W25X20 0x3012 /**< Device ID for W25X20 */
#define XISF_WB_DEV_W25X40 0x3013 /**< Device ID for W25X40 */
#define XISF_WB_DEV_W25X80 0x3014 /**< Device ID for W25X80 */
#define XISF_WB_DEV_W25X16 0x3015 /**< Device ID for W25X16 */
#define XISF_WB_DEV_W25X32 0x3016 /**< Device ID for W25X32 */
#define XISF_WB_DEV_W25X64 0x3017 /**< Device ID for W25X64 */
/**
* The following definitions specify the Device Id (memory type/capacity)
* for the different STM (Numonyx) N25QXX Serial Flash devices.
*/
#define XISF_NM_DEV_N25Q32 0xBA16 /**< Device ID for N25Q32 */
#define XISF_NM_DEV_N25Q64 0xBA17 /**< Device ID for N25Q64 */
#define XISF_NM_DEV_N25Q128 0xBA18 /**< Device ID for N25Q128 */
#define XISF_MIC_DEV_N25Q128 0xBB18 /**< Device ID for N25Q128 */
#define XISF_MIC_DEV_N25Q256_3V0 0xBA19
#define XISF_MIC_DEV_N25Q256_1V8 0xBB19
/**
* The following definitions specify the Device Id for the different
* Spansion S25FLXX Serial Flash devices.
*/
#define XISF_SPANSION_DEV_S25FL004 0x0212 /**< Device ID for S25FL004 */
#define XISF_SPANSION_DEV_S25FL008 0x0213 /**< Device ID for S25FL008 */
#define XISF_SPANSION_DEV_S25FL016 0x0214 /**< Device ID for S25FL016 */
#define XISF_SPANSION_DEV_S25FL032 0x0215 /**< Device ID for S25FL032 */
#define XISF_SPANSION_DEV_S25FL064 0x0216 /**< Device ID for S25FL064 */
#define XISF_SPANSION_DEV_S25FL128 0x2018 /**< Device ID for S25FL128
* and S25FL129 */
/**
* The following definitions specify the Device Id for the different
* SST Serial Flash device.
*/
#define XISF_SST_DEV_SST25WF080 0x2505 /**< Device ID for SST25WF080 */
/**
* Definitions for Intel, STM, Winbond and Spansion Serial Flash Device
* geometry.
*/
#define XISF_BYTES256_PER_PAGE 256 /**< 256 Bytes per Page */
#define XISF_PAGES16_PER_SECTOR 16 /**< 16 Pages per Sector */
#define XISF_PAGES128_PER_SECTOR 128 /**< 128 Pages per Sector */
#define XISF_PAGES256_PER_SECTOR 256 /**< 256 Pages per Sector */
#define XISF_PAGES1024_PER_SECTOR 1024 /**< 1024 Pages per Sector */
#define XISF_NUM_OF_SECTORS2 2 /**< 2 Sectors */
#define XISF_NUM_OF_SECTORS4 4 /**< 4 Sectors */
#define XISF_NUM_OF_SECTORS8 8 /**< 8 Sector */
#define XISF_NUM_OF_SECTORS16 16 /**< 16 Sectors */
#define XISF_NUM_OF_SECTORS32 32 /**< 32 Sectors */
#define XISF_NUM_OF_SECTORS64 64 /**< 64 Sectors */
#define XISF_NUM_OF_SECTORS128 128 /**< 128 Sectors */
#define XISF_NUM_OF_SECTORS256 256 /**< 256 Sectors */
#define XISF_NUM_OF_SECTORS512 512 /**< 512 Sectors */
#define XISF_NUM_OF_SECTORS1024 1024 /**< 1024 Sectors */
#define XISF_NUM_OF_SECTORS2048 2048 /**< 2048 Sectors */
#define XISF_NUM_OF_SECTORS4096 4096 /**< 4096 Sectors */
/**
* Definitions of Read commands.
*/
#define XISF_CMD_RANDOM_READ 0x03 /**< Random Read command */
#define XISF_CMD_RANDOM_READ_4BYTE 0x13 /**< Random 4 byte Read command */
#define XISF_CMD_FAST_READ 0x0B /**< Fast Read command */
#define XISF_CMD_FAST_READ_4BYTE 0x0C /**< 4 byte Fast Read command */
#define XISF_CMD_ISFINFO_READ 0x9F /**< Device Info command */
#define XISF_CMD_STATUSREG_READ 0x05 /**< Status Reg Read command */
#define XISF_CMD_STATUSREG2_READ 0x35 /**< Status Reg2 Read command */
#define XISF_CMD_DUAL_OP_FAST_READ 0x3B /**< Dual output fast read */
#define XISF_CMD_DUAL_OP_FAST_READ_4B 0x3C /**< 4 byte Dual output fast read */
#define XISF_CMD_DUAL_IO_FAST_READ 0xBB /**< Dual i/o fast read */
#define XISF_CMD_DUAL_IO_FAST_READ_4B 0xBC /**< 4 byte Dual i/o fast read */
#define XISF_CMD_QUAD_OP_FAST_READ 0x6B /**< Quad output fast read */
#define XISF_CMD_QUAD_OP_FAST_READ_4B 0x6C /**< 4 byte Quad output fast read */
#define XISF_CMD_QUAD_IO_FAST_READ 0xEB /**< Quad i/o fast read */
#define XISF_CMD_QUAD_IO_FAST_READ_4B 0xEC /**< 4 byte Quad i/o fast read */
/**
* Definitions of Write commands.
*/
#define XISF_CMD_PAGEPROG_WRITE 0x02 /**< Page Program command */
#define XISF_CMD_PAGEPROG_WRITE_4BYTE 0x12 /**< 4 byte Page Program command */
#define XISF_CMD_STATUSREG_WRITE 0x01 /**< Status Reg Write Command */
#define XISF_CMD_DUAL_IP_PAGE_WRITE 0xA2 /**< Dual input fast page write
*/
#define XISF_CMD_DUAL_IP_EXT_PAGE_WRITE 0xD2 /**< Dual input extended fast
* page write */
#define XISF_CMD_QUAD_IP_PAGE_WRITE 0x32 /**< Quad input fast page write
*/
#define XISF_CMD_QUAD_IP_EXT_PAGE_WRITE 0x12 /**< Dual input extended fast
* page write */
/**
* Definitions of Erase commands.
*/
#define XISF_CMD_BULK_ERASE 0xC7 /**< Bulk Erase command */
#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \
(XPAR_XISF_FLASH_FAMILY == SPANSION))
#define XISF_CMD_SECTOR_ERASE 0xD8 /**< Sector Erase command */
#define XISF_CMD_SUB_SECTOR_ERASE 0x20 /**< Sub-sector Erase command.
* only for N25QXX */
#define XISF_CMD_4BYTE_SECTOR_ERASE 0xDC
#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL)||(XPAR_XISF_FLASH_FAMILY == STM) ||
(XPAR_XISF_FLASH_FAMILY == SPANSION)) */
#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == SST))
#define XISF_CMD_BLOCK_ERASE 0xD8 /**< Block Erase command */
#define XISF_CMD_SECTOR_ERASE 0x20 /**< Sector Erase command */
#endif
/**
* Definitions of commands used for
* - Write Enable/Disable.
* - Deep Power Down mode Enter/Release.
* - Switch to 4 byte addressing
*/
#define XISF_CMD_ENABLE_WRITE 0x06 /**< Write enable command */
#define XISF_CMD_DISABLE_WRITE 0x04 /**< Write disable command */
#define XISF_CMD_DEEP_POWER_DOWN 0xB9 /**< Enter DPD mode command */
#define XISF_CMD_RELEASE_FROM_DPD 0xAB /**< Release DPD mode command */
#define XISF_CMD_ENABLE_HPM 0xA3 /**< Enable high performance
* mode */
#if (XPAR_XISF_FLASH_FAMILY == SPANSION)
#define XISF_CMD_ENTER_4BYTE_ADDR_MODE 0xB7
#define XISF_CMD_EXIT_4BYTE_ADDR_MODE 0xE9
#endif
#if (XPAR_XISF_FLASH_FAMILY == INTEL)
/**
* Definitions of commands which are only supported in Intel Serial Flash.
*/
#define XISF_CMD_OTP_READ 0x4B /**< OTP data read command */
#define XISF_CMD_OTP_WRITE 0x42 /**< OTP write command */
#define XISF_CMD_PARAM_BLOCK_ERASE 0x40 /**< Parameter Block Erase
* command */
#define XISF_CMD_CLEAR_SRFAIL_FLAGS 0x30 /**< Clear SR fail bits Cmd */
#define XISF_OTP_RDWR_EXTRA_BYTES 0x05 /**< OTP Read/Write
* extra bytes */
#endif /* INTEL */
/**
* The following definitions specify the Status Register bit definitions of
* Intel, STM, Winbond and Spansion Serial Flash.
*/
#define XISF_SR_IS_READY_MASK 0x01 /**< Ready mask */
#define XISF_SR_WRITE_ENABLE_MASK 0x02 /**< Write Enable latch mask */
#define XISF_SR_BLOCK_PROTECT_MASK 0x1C /**< Block Protect mask */
#define XISF_SR_WRITE_PROTECT_MASK 0x80 /**< Status Reg write
* protect mask */
#define XISF_SR_BLOCK_PROTECT_SHIFT 2 /**< Block protect bits shift */
#if (XPAR_XISF_FLASH_FAMILY == INTEL)
#define XISF_SR_PROG_FAIL_MASK 0x40 /**< Program Fail bit mask */
#define XISF_SR_ERASE_FAIL_MASK 0x20 /**< Erase Fail bit mask */
#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */
#if (XPAR_XISF_FLASH_FAMILY == WINBOND)
#define XISF_SR_TB_PROTECT_MASK 0x20 /**< Top/Bottom Write Protect */
#define XISF_SR_SECTOR_PROTECT_MASK 0x40 /**< Sector Protect mask */
#endif /* (XPAR_XISF_FLASH_FAMILY == WINBOND) */
/**
* The definition specifies the total bytes in Bulk Erase commands.
* This count includes Command byte and any don't care bytes needed.
*/
#define XISF_BULK_ERASE_BYTES 0x01 /**< Bulk erase extra bytes */
/**
* The following definitions specify the Write Enable and Disable operation
* arguments to be passed to the XIsf_WriteEnable API.
*/
#define XISF_WRITE_ENABLE 1 /**< Write enable */
#define XISF_WRITE_DISABLE 0 /**< Write disable */
/**
* This definition specifies the extra bytes in each of the Write Enable/Disable
* commands. This count includes Command byte, address bytes and any don't care
* bytes needed.
*/
#define XISF_CMD_WRITE_ENABLE_DISABLE_BYTES 1 /**< Write enable/disable
* command extra bytes */
/**
* This definition specifies the extra bytes in 4 byte addr mode enter and exit
* commands. This count refers to the Command byte.
*/
#define XISF_CMD_4BYTE_ADDR_ENTER_EXIT_BYTES 1 /**< Four byte addr mode
* command extra bytes */
/**
* This definition specifies the extra bytes in each of the Write/Read/Erase
* commands, commands operating on SPR, auto page write, page to
* buffer and buffer to page transfer commands. This count includes
* Command byte, Address bytes and any don't care bytes needed.
*/
#define XISF_CMD_SEND_EXTRA_BYTES 4 /**< Command extra bytes */
/**
* This definition specifies the extra bytes in each of the Write/Read/Erase
* commands, commands operating on SPR, auto page write, page to
* buffer and buffer to page transfer commands in 4 bytes addressing mode.
* This count includes Command byte, Address bytes and any
* don't care bytes needed.
*/
#define XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE 5 /**< Command extra bytes */
/**
* This definition specifies the extra bytes in Fast Read and Fast Buffer Read
* commands. This count includes Command byte, address bytes and any don't care
* bytes needed.
*/
#define XISF_CMD_FAST_READ_EXTRA_BYTES 5 /**< Fast read and Fast buffer
* read extra bytes */
/**
* The following definitions specify the total bytes in some of the commands.
* This count includes Command byte and any don't care bytes needed.
*/
#define XISF_STATUS_RDWR_BYTES 2 /**< Status Read/Write bytes
* count */
#define XISF_INFO_READ_BYTES 5 /**< Serial Flash Info read
* bytes count */
#define XISF_INFO_EXTRA_BYTES 1 /**< Serial Flash Info extra
* bytes */
#define XISF_IOCTL_BYTES 1 /**< Serial Flash IOCTL bytes */
#define XISF_HPM_BYTES 4 /**< Serial Flash HPM bytes */
#define XISF_CMD_MAX_EXTRA_BYTES 5 /**< Max extra bytes for
* all commands */
#define XISF_DUMMYBYTE 0xFF /**< Dummy byte to fill */
/**
* Address Shift Masks.
*/
#define XISF_ADDR_SHIFT24 24 /**< 24 bit Shift */
#define XISF_ADDR_SHIFT16 16 /**< 16 bit Shift */
#define XISF_ADDR_SHIFT8 8 /**< 8 bit Shift */
/**
* Byte Positions.
*/
#define BYTE1 0 /**< Byte 1 position */
#define BYTE2 1 /**< Byte 2 position */
#define BYTE3 2 /**< Byte 3 position */
#define BYTE4 3 /**< Byte 4 position */
#define BYTE5 4 /**< Byte 5 position */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,597 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xilisf_erase.c
*
* This file contains the library functions to Erase the Serial Flash.
* Refer xilisf.h for a detailed description.
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- -----------------------------------------------
* 1.00a ksu/sdm 03/03/08 First release
* 2.01a sdm 01/04/10 Added Support for Winbond W25QXX/W25XX devices
* 2.04a sdm 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
* flash memories
* 3.02a srt 04/25/13 Added Bulk Erase command support for SST and
* Spansion flashes.
* 5.0 sb 08/05/14 Updated support for > 128 MB flash for PSQSPI
* interface.
* New API:
* DieErase()
* Changed API:
* SectorErase()
* BulkErase()
* 5.2 asa 05/12/15 Added support for Micron (N25Q256A) flash part
* which supports 4 byte addressing.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "include/xilisf.h"
/************************** Constant Definitions *****************************/
#define SIXTEENMB 0x1000000 /**< Sixteen MB */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr,
u32 ByteCount);
extern u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
extern int SendBankSelect(XIsf *InstancePtr, u32 BankSel);
#endif
static int PageErase(XIsf *InstancePtr, u32 Address);
static int BlockErase(XIsf *InstancePtr, u32 Address);
static int SectorErase(XIsf *InstancePtr, u32 Address);
static int BulkErase(XIsf *InstancePtr);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
static int DieErase(XIsf *InstancePtr);
#endif
/************************** Variable Definitions *****************************/
extern u32 XIsf_StatusEventInfo;
extern unsigned int XIsf_ByteCountInfo;
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* This API erases the contents of the specified memory in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Operation is the type of Erase operation to be performed on the
* Serial Flash.
* The different operations are
* - XISF_PAGE_ERASE: Page Erase
* - XISF_BLOCK_ERASE: Block Erase
* - XISF_SECTOR_ERASE: Sector Erase
- XISF_BULK_ERASE: Bulk Erase
* @param Address is the address of the Page/Block/Sector to be erased.
* The address can be either Page address, Block address or Sector
* address based on the Erase operation to be performed.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - The erased bytes will read as 0xFF.
* - For Intel, STM, Winbond or Spansion Serial Flash the user
* application must call XIsf_WriteEnable() API by passing
* XISF_WRITE_ENABLE as an argument before calling XIsf_Erase()
* API.
* - Atmel Serial Flash support Page/Block/Sector Erase
- operations.
* - Intel, Winbond, Numonyx (N25QXX) and Spansion Serial Flash
* support Sector/Block/Bulk Erase operations.
* - STM (M25PXX) Serial Flash support Sector/Bulk Erase
* operations.
*
******************************************************************************/
int XIsf_Erase(XIsf *InstancePtr, XIsf_EraseOperation Operation, u32 Address)
{
int Status = (int)(XST_FAILURE);
u8 Mode;
if (InstancePtr == NULL) {
return (int)(XST_FAILURE);
}
if (InstancePtr->IsReady != TRUE) {
return (int)(XST_FAILURE);
}
switch (Operation) {
case XISF_PAGE_ERASE:
Status = PageErase(InstancePtr, Address);
break;
case XISF_BLOCK_ERASE:
Status = BlockErase(InstancePtr, Address);
break;
case XISF_SECTOR_ERASE:
Status = SectorErase(InstancePtr, Address);
break;
case XISF_BULK_ERASE:
Status = BulkErase(InstancePtr);
break;
default:
break;
}
/*
* Get the Transfer Mode
*/
Mode = XIsf_GetTransferMode(InstancePtr);
if(Mode == XISF_INTERRUPT_MODE){
InstancePtr->StatusHandler(InstancePtr,
XIsf_StatusEventInfo, XIsf_ByteCountInfo);
}
return Status;
}
/*****************************************************************************/
/**
*
* This function erases the contents of the specified Page in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address of Page to be erased. This can be any
* address in the Page to be erased. The Byte address values in
* this address are ignored.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - The erased bytes will read as 0xFF.
* - This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int PageErase(XIsf *InstancePtr, u32 Address)
{
int Status = (int)(XST_FAILURE);
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Address != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_PAGE_ERASE;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) XISF_DUMMYBYTE;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
NULL, XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function erases the contents of the specified Block in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address of the Block to be erased. This can be
* any address in the Block to be erased. The Page/Byte address
* values in this address are ignored.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - The erased bytes will read as 0xFF.
* - This operation is supported for Atmel, Intel, Winbond,
* Numonyx (N25QXX), and Spansion Serial Flash.
*
******************************************************************************/
static int BlockErase(XIsf *InstancePtr, u32 Address)
{
int Status = (int)(XST_FAILURE);
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Address != 0);
#if ((XPAR_XISF_FLASH_FAMILY == ATMEL) || (XPAR_XISF_FLASH_FAMILY == INTEL) \
|| (XPAR_XISF_FLASH_FAMILY == WINBOND))
#if ((XPAR_XISF_FLASH_FAMILY == ATMEL) || (XPAR_XISF_FLASH_FAMILY == WINBOND))
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BLOCK_ERASE;
#else
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_PARAM_BLOCK_ERASE;
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) XISF_DUMMYBYTE;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
NULL, XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#endif /* ((XPAR_XISF_FLASH_FAMILY==ATMEL)||(XPAR_XISF_FLASH_FAMILY==INTEL)) */
return Status;
}
/*****************************************************************************/
/**
*
* This function erases the contents of the specified Sector in Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address of the Sector to be erased. This can be
* any address in the Sector to be erased.
* The Block/Page/Byte address values in this address are ignored.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - The erased bytes will read as 0xFF.
* - This operation is supported for Atmel, Intel, STM, Winbond
* and Spansion Serial Flash.
*
******************************************************************************/
static int SectorErase(XIsf *InstancePtr, u32 Address)
{
int Status = (int)(XST_FAILURE);
u8 Mode;
u32 BankSel;
u32 RealAddr;
u8* NULLPtr = NULL;
u8 FlagStatus[2] = {0};
u8 FlashStatus[2] = {0};
u8 ReadStatusCmdBuf[] = { READ_STATUS_CMD, 0 };
u8 ReadFlagSRCmd[] = {READ_FLAG_STATUS_CMD, 0};
#ifdef XPAR_XISF_INTERFACE_PSQSPI
u32 FlashMake = InstancePtr->ManufacturerID;
#endif
Xil_AssertNonvoid(NULLPtr == NULL);
/*
* Translate address based on type of connection
* If stacked assert the slave select based on address
*/
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, Address);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* Initial bank selection
*/
if(InstancePtr->DeviceIDMemSize > 0x18U) {
/*
* Get the Transfer Mode
*/
Mode = XIsf_GetTransferMode(InstancePtr);
/*
* Seting the transfer mode to Polled Mode before
* performing the Bank Select operation.
*/
XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
/*
* Calculate initial bank
*/
BankSel = RealAddr/SIXTEENMB;
/*
* Select bank
*/
Status = SendBankSelect(InstancePtr, BankSel);
/*
* Restoring the transfer mode back
*/
XIsf_SetTransferMode(InstancePtr, Mode);
if(Status!=(int)(XST_SUCCESS)){
return (int)XST_FAILURE;
}
}
#endif
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
if (InstancePtr->FourByteAddrMode == TRUE) {
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SECTOR_ERASE;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE5] = (u8) (RealAddr);
} else {
#endif
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SECTOR_ERASE;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr);
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
}
#endif
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* Enable write before transfer
*/
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif
if (InstancePtr->FourByteAddrMode == TRUE) {
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
NULLPtr, XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE);
} else {
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
NULLPtr, XISF_CMD_SEND_EXTRA_BYTES);
}
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#ifdef XPAR_XISF_INTERFACE_PSQSPI
if((InstancePtr->NumDie > (u8)1) &&
(FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) {
Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
(u32)sizeof(ReadFlagSRCmd));
}
/*
* Wait for the sector erase command to the Flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
Status = XIsf_Transfer(InstancePtr, ReadStatusCmdBuf,
FlashStatus,
(u32)sizeof(ReadStatusCmdBuf));
/*
* If the status indicates the write is done, then stop
* waiting, if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
if((InstancePtr->NumDie > (u8)1) &&
(FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) {
Status =
XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
(u32)sizeof(ReadFlagSRCmd));
}
#endif
return Status;
}
/*****************************************************************************/
/**
*
* This function erases the content of an entire Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - The erased bytes will read as 0xFF.
* - This operation is supported for Intel, STM, Winbond,
* Spansion and SST Serial Flashes.
*
******************************************************************************/
static int BulkErase(XIsf *InstancePtr)
{
int Status = (int)(XST_FAILURE);
u8* NULLPtr = NULL;
#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \
(XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == SST) \
|| (XPAR_XISF_FLASH_FAMILY == SPANSION))
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* If the number of die is greater than 1 call die erase
*/
if(InstancePtr->NumDie > 1){
Status = DieErase(InstancePtr);
}
else{
#endif
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BULK_ERASE;
/*
* Enable write before transfer
*/
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
Xil_AssertNonvoid(NULLPtr == NULL);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr,
NULLPtr, XISF_BULK_ERASE_BYTES);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
}
#endif
#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL)||(XPAR_XISF_FLASH_FAMILY==STM)) \
(XPAR_XISF_FLASH_FAMILY == WINBOND) ||
(XPAR_XISF_FLASH_FAMILY == SST) ||
(XPAR_XISF_FLASH_FAMILY == SPANSION)) */
return Status;
}
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*****************************************************************************/
/**
*
* This function erases the content of a Die of Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - This operation is supported for Winbond,
* Spansion and Micron Serial Flashes.
*
******************************************************************************/
static int DieErase(XIsf *InstancePtr)
{
int Status = (int)(XST_FAILURE);
u8* NULLPtr = NULL;
#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
(XPAR_XISF_FLASH_FAMILY == SPANSION))
u8 DieCnt;
u8 ReadFlagSRCmd[] = { READ_FLAG_STATUS_CMD, 0 };
u8 FlagStatus[2] = {0};
for(DieCnt = 0; DieCnt < InstancePtr->NumDie; DieCnt++) {
/*
* Select bank - the lower of the 2 banks in each die
* This is specific to Micron flash
*/
Status = SendBankSelect(InstancePtr, DieCnt*2);
/*
* Setup the write command with the specified address and data
* for the Flash
*/
/*
* This ensures 3B address is sent to flash even with address
* greater than 128Mb.
* The address is the start address of die - MSB bits will be
* derived from bank select by the flash
*/
InstancePtr->WriteBufPtr[BYTE1] = DIE_ERASE_CMD;
InstancePtr->WriteBufPtr[BYTE2] = 0x00;
InstancePtr->WriteBufPtr[BYTE3] = 0x00;
InstancePtr->WriteBufPtr[BYTE4] = 0x00;
/*
* Enable write before transfer
*/
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
Xil_AssertNonvoid(NULLPtr == NULL);
/*
* Send the sector erase command and address; no receive buffer
* is specified since there is nothing to receive
*/
Status =
XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr,
DIE_ERASE_SIZE);
/*
* Wait for the sector erase command to Flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
Status =
XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
(u32)sizeof(ReadFlagSRCmd));
/*
* If the status indicates the write is done, then stop
* waiting, if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlagStatus[1] & (u8)0x80) == (u8)0x80) {
break;
}
}
}
#endif /* ((XPAR_XISF_FLASH_FAMILY == WINBOND) || \
(XPAR_XISF_FLASH_FAMILY == SPANSION)) */
return Status;
}
#endif

View file

@ -0,0 +1,978 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xilisf_read.c
*
* This file contains the library functions to read data from the Serial Flash
* devices. Refer xilisf.h for detailed description.
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- -----------------------------------------------
* 1.00a ksu/sdm 03/03/08 First release
* 2.01a sdm 01/04/10 Added Support for Winbond W25QXX/W25XX devices
* 2.04a sdm 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
* flash memories
* 5.0 sb 08/05/14 Updated support for > 128 MB flash for PSQSPI
* interface.
* Changed API:
* ReadData()
* FastReadData()
*
* 5.2 asa 05/12/15 Added support for Micron (N25Q256A) flash part
* which supports 4 byte addressing.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "include/xilisf.h"
/************************** Constant Definitions *****************************/
#define FAST_READ_NUM_DUMMY_BYTES 1
#define SIXTEENMB 0x1000000 /**< Sixteen MB */
#define BANKMASK 0xF000000 /**< Bank mask */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr,
u32 ByteCount);
extern u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
extern int SendBankSelect(XIsf *InstancePtr, u32 BankSel);
#endif
static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr,
u32 ByteCount);
static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address,
u8 *ReadPtr,
u32 ByteCount, int NumDummyBytes);
static int FlashToBufTransfer(XIsf *InstancePtr, u8 BufferNum, u32 Address);
static int BufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
u32 ByteOffset, u32 NumBytes);
static int FastBufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
u32 ByteOffset, u32 NumBytes);
static int ReadOTPData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr,
u32 ByteCount);
/************************** Variable Definitions *****************************/
extern u32 XIsf_StatusEventInfo;
extern unsigned int XIsf_ByteCountInfo;
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* This API reads the data from the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Operation is the type of the read operation to be performed on
* the Serial Flash.
* The different operations are
- XISF_READ: Normal Read
* - XISF_FAST_READ: Fast Read
* - XISF_PAGE_TO_BUF_TRANS: Page to Buffer Transfer
* - XISF_BUFFER_READ: Buffer Read
* - XISF_FAST_BUFFER_READ: Fast Buffer Read
* - XISF_OTP_READ: One Time Programmable Area (OTP) Read
* - XISF_DUAL_OP_FAST_READ: Dual Output Fast Read
* - XISF_DUAL_IO_FAST_READ: Dual Input/Output Fast Read
* - XISF_QUAD_OP_FAST_READ: Quad Output Fast Read
* - XISF_QUAD_IO_FAST_READ: Quad Input/Output Fast Read
* @param OpParamPtr is the pointer to structure variable which contains
* operational parameter of specified Operation. This parameter
* type is dependant on the type of Operation to be performed.
*
* - Normal Read (XISF_READ), Fast Read (XISF_FAST_READ),
* One Time Programmable Area Read(XISF_OTP_READ), Dual Output
* Fast Read (XISF_CMD_DUAL_OP_FAST_READ), Dual Input/Output
* Fast Read (XISF_CMD_DUAL_IO_FAST_READ), Quad Output Fast Read
* (XISF_CMD_QUAD_OP_FAST_READ) and Quad Input/Output Fast Read
* (XISF_CMD_QUAD_IO_FAST_READ):
* The OpParamPtr must be of type struct XIsf_ReadParam.
* OpParamPtr->Address is start address in the Serial Flash.
* OpParamPtr->ReadPtr is a pointer to the memory where the data
* read from the Serial Flash is stored.
* OpParamPtr->NumBytes is number of bytes to read.
* OpParamPtr->NumDummyBytes is the number of dummy bytes to be
* transmitted for the Read command. This parameter is only used
* in case of Dual and Quad reads.
* Normal Read and Fast Read operations are supported for Atmel,
* Intel, STM, Winbond and Spansion Serial Flash.
* Dual and quad reads are supported for Winbond (W25QXX), Numonyx
* (N25QXX) and Spansion (S25FL129) quad flash.
* OTP Read operation is only supported in Intel Serial Flash.
*
* - Page To Buffer Transfer (XISF_PAGE_TO_BUF_TRANS):
* The OpParamPtr must be of type struct
* XIsf_FlashToBufTransferParam .
* OpParamPtr->BufferNum specifies the internal SRAM Buffer of
* the Serial Flash. The valid values are XISF_PAGE_BUFFER1
* or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case
* of AT45DB011D Flash as it contains a single buffer.
* OpParamPtr->Address is start address in the Serial Flash.
* This operation is only supported in Atmel Serial Flash.
*
* - Buffer Read (XISF_BUFFER_READ) and Fast Buffer Read
* (XISF_FAST_BUFFER_READ):
* The OpParamPtr must be of type struct XIsf_BufferReadParam.
* OpParamPtr->BufferNum specifies the internal SRAM Buffer of
* the Serial Flash. The valid values are XISF_PAGE_BUFFER1
* or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
* AT45DB011D Flash as it contains a single buffer.
* OpParamPtr->ReadPtr is pointer to the memory where data read
* from the SRAM buffer is to be stored.
* OpParamPtr->ByteOffset is byte offset in the SRAM buffer from
* where the first byte is read.
* OpParamPtr->NumBytes is the number of bytes to be read from the
* Buffer.
* These operations are supported only in Atmel Serial Flash.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - Application must fill the structure elements of the third
* argument and pass its pointer by type casting it with void
* pointer.
* - The valid data is available from the fourth location pointed
* to by the ReadPtr for Normal Read and Buffer Read operations.
* - The valid data is available from fifth location pointed to
* by the ReadPtr for Fast Read, Fast Buffer Read and OTP Read
* operations.
* - The valid data is available from the (4 + NumDummyBytes)th
* location pointed to by ReadPtr for Dual/Quad Read operations.
*
******************************************************************************/
int XIsf_Read(XIsf *InstancePtr, XIsf_ReadOperation Operation,
void *OpParamPtr)
{
int Status = (int)(XST_FAILURE);
u8 Mode;
XIsf_ReadParam *ReadParamPtr;
XIsf_FlashToBufTransferParam *FlashToBufTransferParamPtr;
XIsf_BufferReadParam *BufferReadParamPtr;
if (InstancePtr == NULL) {
return (int)(XST_FAILURE);
}
if (InstancePtr->IsReady != TRUE) {
return (int)(XST_FAILURE);
}
if (NULL == OpParamPtr) {
return (int)(XST_FAILURE);
}
switch (Operation) {
case XISF_READ:
ReadParamPtr = (XIsf_ReadParam*) OpParamPtr;
Status = ReadData(InstancePtr,
ReadParamPtr->Address,
ReadParamPtr->ReadPtr,
ReadParamPtr->NumBytes);
break;
case XISF_FAST_READ:
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(ReadParamPtr != NULL);
Status = FastReadData(InstancePtr,
XISF_CMD_FAST_READ,
ReadParamPtr->Address,
ReadParamPtr->ReadPtr,
ReadParamPtr->NumBytes,
ReadParamPtr->NumDummyBytes);
break;
case XISF_PAGE_TO_BUF_TRANS:
FlashToBufTransferParamPtr =
(XIsf_FlashToBufTransferParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(FlashToBufTransferParamPtr != NULL);
Status = FlashToBufTransfer(InstancePtr,
FlashToBufTransferParamPtr->BufferNum,
FlashToBufTransferParamPtr->Address);
break;
case XISF_BUFFER_READ:
BufferReadParamPtr =
(XIsf_BufferReadParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(BufferReadParamPtr != NULL);
Status = BufferRead(InstancePtr,
BufferReadParamPtr->BufferNum,
BufferReadParamPtr->ReadPtr,
BufferReadParamPtr->ByteOffset,
BufferReadParamPtr->NumBytes);
break;
case XISF_FAST_BUFFER_READ:
BufferReadParamPtr =
(XIsf_BufferReadParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(BufferReadParamPtr != NULL);
Status = FastBufferRead(InstancePtr,
BufferReadParamPtr->BufferNum,
BufferReadParamPtr->ReadPtr,
BufferReadParamPtr->ByteOffset,
BufferReadParamPtr->NumBytes);
break;
case XISF_OTP_READ:
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(ReadParamPtr != NULL);
Status = ReadOTPData(InstancePtr,
ReadParamPtr->Address,
ReadParamPtr->ReadPtr,
ReadParamPtr->NumBytes);
break;
#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == STM) \
|| (XPAR_XISF_FLASH_FAMILY == SPANSION))
case XISF_DUAL_OP_FAST_READ:
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(ReadParamPtr != NULL);
Status = FastReadData(InstancePtr,
XISF_CMD_DUAL_OP_FAST_READ,
ReadParamPtr->Address,
ReadParamPtr->ReadPtr,
ReadParamPtr->NumBytes,
ReadParamPtr->NumDummyBytes);
break;
case XISF_DUAL_IO_FAST_READ:
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(ReadParamPtr != NULL);
Status = FastReadData(InstancePtr,
XISF_CMD_DUAL_IO_FAST_READ,
ReadParamPtr->Address,
ReadParamPtr->ReadPtr,
ReadParamPtr->NumBytes,
ReadParamPtr->NumDummyBytes);
break;
case XISF_QUAD_OP_FAST_READ:
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(ReadParamPtr != NULL);
Status = FastReadData(InstancePtr,
XISF_CMD_QUAD_OP_FAST_READ,
ReadParamPtr->Address,
ReadParamPtr->ReadPtr,
ReadParamPtr->NumBytes,
ReadParamPtr->NumDummyBytes);
break;
case XISF_QUAD_IO_FAST_READ:
ReadParamPtr = (XIsf_ReadParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(ReadParamPtr != NULL);
Status = FastReadData(InstancePtr,
XISF_CMD_QUAD_IO_FAST_READ,
ReadParamPtr->Address,
ReadParamPtr->ReadPtr,
ReadParamPtr->NumBytes,
ReadParamPtr->NumDummyBytes);
break;
#endif /*((XPAR_XISF_FLASH_FAMILY == WINBOND) ||
(XPAR_XISF_FLASH_FAMILY == STM) ||
(XPAR_XISF_FLASH_FAMILY == SPANSION))*/
default:
break;
}
/*
* Get the Transfer Mode
*/
Mode = XIsf_GetTransferMode(InstancePtr);
if(Mode == XISF_INTERRUPT_MODE){
InstancePtr->StatusHandler(InstancePtr,
XIsf_StatusEventInfo, XIsf_ByteCountInfo);
}
return Status;
}
/*****************************************************************************/
/**
*
* This function reads data from the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the starting address in the Serial Flash from where
* the data is to be read.
* @param ReadPtr is a pointer to the memory where the data read from
* the Serial Flash is stored.
* @param ByteCount is the number of bytes to be read from the Serial
* Flash.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - This operation is supported for Atmel, Intel, STM, Winbond
* and Spansion Serial Flash.
* - Minimum of one byte and a maximum of an entire Serial Flash
* Array can be read.
* - The valid data is available from the fourth location pointed
* to by the ReadPtr.
*
******************************************************************************/
static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, u32 ByteCount)
{
u8 Mode;
u32 BankSel;
u32 RealAddr;
int Status;
u32 RealByteCnt;
u32 BufferIndex;
u8 ShiftSize;
u32 TotalByteCnt = ByteCount;
u32 LocalByteCnt = ByteCount;
u32 LocalAddress = Address;
u8 WriteBuffer[10] = {0};
if (LocalByteCnt <= 0 ) {
return (int)XST_FAILURE;
}
if (ReadPtr == NULL) {
return (int)XST_FAILURE;
}
while(((s32)(LocalByteCnt)) > 0) {
/*
* Translate address based on type of connection
* If stacked assert the slave select based on address
*/
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, LocalAddress);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
if(InstancePtr->DeviceIDMemSize > 0x18U) {
/*
* Get the Transfer Mode
*/
Mode = XIsf_GetTransferMode(InstancePtr);
/*
* Seting the transfer mode to Polled Mode before
* performing the Bank Select operation.
*/
XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
BankSel = RealAddr/SIXTEENMB;
(void)SendBankSelect(InstancePtr, BankSel);
/*
* Restoring the transfer mode back
*/
XIsf_SetTransferMode(InstancePtr, Mode);
}
/*
* If data to be read spans beyond the current bank, then
* calculate RealByteCnt in current bank. Else
* RealByteCnt is the same as ByteCount
*/
if((RealAddr & BANKMASK) != ((RealAddr+LocalByteCnt) & BANKMASK)) {
RealByteCnt = ((RealAddr & BANKMASK) + SIXTEENMB) - RealAddr;
}
else {
#endif
RealByteCnt = LocalByteCnt;
#ifdef XPAR_XISF_INTERFACE_PSQSPI
}
#endif
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
if (InstancePtr->FourByteAddrMode == TRUE) {
WriteBuffer[BYTE1] = XISF_CMD_RANDOM_READ_4BYTE;
WriteBuffer[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24);
WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
WriteBuffer[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
WriteBuffer[BYTE5] = (u8) (RealAddr);
} else {
#endif
WriteBuffer[BYTE1] = XISF_CMD_RANDOM_READ;
WriteBuffer[BYTE2] = (u8)((RealAddr & 0xFF0000) >> XISF_ADDR_SHIFT16);
WriteBuffer[BYTE3] = (u8)((RealAddr & 0xFF00) >> XISF_ADDR_SHIFT8);
WriteBuffer[BYTE4] = (u8)(RealAddr & 0xFF);
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
}
#endif
if (InstancePtr->FourByteAddrMode == TRUE) {
Status = XIsf_Transfer(InstancePtr, WriteBuffer,
&(ReadPtr[TotalByteCnt - LocalByteCnt]),
RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE);
} else {
Status = XIsf_Transfer(InstancePtr, WriteBuffer,
&(ReadPtr[TotalByteCnt - LocalByteCnt]),
RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES);
}
if (Status != (int)(XST_SUCCESS)) {
return (int)XST_FAILURE;
}
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* To discard the first 4 dummy bytes, shift the data in read buffer
*/
ShiftSize = XISF_CMD_SEND_EXTRA_BYTES;
BufferIndex = (TotalByteCnt - LocalByteCnt);
for(;
BufferIndex < ((TotalByteCnt - LocalByteCnt) + RealByteCnt);
BufferIndex++) {
ReadPtr[BufferIndex] = ReadPtr[BufferIndex + ShiftSize];
}
/*
* Increase address to next bank
*/
LocalAddress = (LocalAddress & BANKMASK) + SIXTEENMB;
#endif
/*
* Decrease byte count by bytes already read.
*/
LocalByteCnt = LocalByteCnt - RealByteCnt;
}
return (int)XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function reads data from the Serial Flash at a higher speed than normal
* Read operation.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Command is the fast read command used to read data from the
* flash. It could be one of XISF_CMD_DUAL/QUAD_*_FAST_READ or
* XISF_CMD_FAST_READ.
* @param Address is the starting address in the Serial Flash from where
* the data is to be read.
* @param ReadPtr is a pointer to the memory where the data read from
* the Serial Flash is stored.
* @param ByteCount is the number of bytes to be read from the Serial
* Flash.
* @param NumDummyBytes is the number of dummy bytes associated with the
* fast read commands.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - XISF_CMD_FAST_READ operation is supported for Atmel, Intel,
* STM, Winbond and Spansion Serial Flash.
* - XISF_CMD_DUAL/QUAD_*_FAST_READ operations are supported on
* Winbond (W25QXX), Numonyx (N25QXX) and Spansion (S25FL129)
* quad flash devices.
* - Minimum of one byte and a maximum of an entire Serial Flash
* Array can be read.
* - The valid data is available from the (4 + NumDummyBytes)th
* location pointed to by the ReadPtr.
*
******************************************************************************/
static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address,
u8 *ReadPtr, u32 ByteCount, int NumDummyBytes)
{
u8 Mode;
int Index;
int Status;
u32 BankSel;
u32 RealAddr;
u32 RealByteCnt;
u32 BufferIndex;
u8 ShiftSize;
u32 TotalByteCnt = ByteCount;
u32 LocalByteCnt = ByteCount;
u32 LocalAddress = Address;
u8 WriteBuffer[5]= {0};
if (LocalByteCnt <= 0 ) {
return (int)XST_FAILURE;
}
if (ReadPtr == NULL) {
return (int)(XST_FAILURE);
}
if (NumDummyBytes <= 0) {
return (int)(XST_FAILURE);
}
while(((s32)(LocalByteCnt)) > 0) {
/*
* Translate address based on type of connection
* If stacked assert the slave select based on address
*/
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, LocalAddress);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
if(InstancePtr->DeviceIDMemSize > 0x18U) {
/*
* Get the Transfer Mode
*/
Mode = XIsf_GetTransferMode(InstancePtr);
/*
* Seting the transfer mode to Polled Mode before
* performing the Bank Select operation.
*/
XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
BankSel = RealAddr/SIXTEENMB;
(void)SendBankSelect(InstancePtr, BankSel);
/*
* Restoring the transfer mode back
*/
XIsf_SetTransferMode(InstancePtr, Mode);
}
/*
* If data to be read spans beyond the current bank, then
* calculate RealByteCnt in current bank. Else
* RealByteCnt is the same as ByteCount
*/
if((RealAddr & BANKMASK) != ((RealAddr+LocalByteCnt) & BANKMASK)) {
RealByteCnt = ((RealAddr & BANKMASK) + SIXTEENMB) - RealAddr;
}
else {
#endif
RealByteCnt = LocalByteCnt;
#ifdef XPAR_XISF_INTERFACE_PSQSPI
}
#endif
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
if (InstancePtr->FourByteAddrMode == TRUE) {
WriteBuffer[BYTE1] = Command;
WriteBuffer[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24);
WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
WriteBuffer[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
WriteBuffer[BYTE5] = (u8) RealAddr;
for (Index = 0; Index < NumDummyBytes; Index++) {
WriteBuffer[Index + BYTE5 + 1] = (u8) (XISF_DUMMYBYTE);
}
} else {
#endif
WriteBuffer[BYTE1] = Command;
WriteBuffer[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
WriteBuffer[BYTE4] = (u8) RealAddr;
for (Index = 0; Index < NumDummyBytes; Index++) {
WriteBuffer[Index + BYTE5] = (u8) (XISF_DUMMYBYTE);
}
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
}
#endif
RealByteCnt += NumDummyBytes;
if (InstancePtr->FourByteAddrMode == TRUE) {
Status = (int)XIsf_Transfer(InstancePtr, WriteBuffer,
&(ReadPtr[TotalByteCnt - LocalByteCnt]),
RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE);
} else {
Status = (int)XIsf_Transfer(InstancePtr, WriteBuffer,
&(ReadPtr[TotalByteCnt - LocalByteCnt]),
RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES);
}
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* To discard the first 5 dummy bytes, shift the data in read buffer
*/
ShiftSize = XISF_CMD_SEND_EXTRA_BYTES + (u8)NumDummyBytes;
BufferIndex = (TotalByteCnt - LocalByteCnt);
for(;
BufferIndex < ((TotalByteCnt - LocalByteCnt) + RealByteCnt);
BufferIndex++) {
ReadPtr[BufferIndex] = ReadPtr[BufferIndex + ShiftSize];
}
/*
* Increase address to next bank
*/
LocalAddress = (LocalAddress & BANKMASK) + SIXTEENMB;
#endif
/*
* Decrease byte count by bytes already read.
*/
LocalByteCnt = LocalByteCnt - (RealByteCnt - NumDummyBytes);
}
return (int)XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function copies the data from the Serial Flash to the specified SRAM
* buffer.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param BufferNum specifies the internal SRAM Buffer to which the data
* from Serial Flash is to be transferred. The valid values are
* XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is
* not valid in the case of AT45DB011D Flash as it contains a
* single buffer.
* @param Address specifies any address within the Page of the Serial
* Flash from where the Page of data is to be copied.
* Byte address in this Address is ignored as an entire Page of
* data is transferred/copied.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - This operation is only supported in Atmel Serial Flash.
* - This function reads one complete Page from the Serial Flash.
* - Read the Spartan-3AN In-system Flash User Guide/Atmel
* AT45XXXD Data sheets for more information.
*
******************************************************************************/
static int FlashToBufTransfer(XIsf *InstancePtr, u8 BufferNum, u32 Address)
{
int Status = (int)(XST_FAILURE);
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Address != 0);
Xil_AssertNonvoid(BufferNum != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/*
* Check whether the buffer number is valid or not.
*/
if ((BufferNum == XISF_PAGE_BUFFER1) ||
(BufferNum == XISF_PAGE_BUFFER2)) {
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
(BufferNum != XISF_PAGE_BUFFER1)) {
return (int)(XST_FAILURE);
}
} else {
return (int)(XST_FAILURE);
}
if (BufferNum == XISF_PAGE_BUFFER1) {
/*
* Page to Buffer 1 Transfer.
*/
InstancePtr->WriteBufPtr[BYTE1] =
XISF_CMD_PAGETOBUF1_TRANS;
} else {
/*
* Page to Buffer 2 Transfer.
*/
InstancePtr->WriteBufPtr[BYTE1] =
XISF_CMD_PAGETOBUF2_TRANS;
}
InstancePtr->WriteBufPtr[BYTE2] = (u8)(Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8)(Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8)(XISF_DUMMYBYTE);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function reads the data available in the SRAM buffer of Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param BufferNum specifies the internal SRAM Buffer from which data
* is to be read. The valid values are XISF_PAGE_BUFFER1 or
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
* AT45DB011D Flash as it contains a single buffer.
* @param ReadPtr is a pointer to the memory where the data read from the
* SRAM buffer is stored.
* @param ByteOffset is the byte offset in the buffer from where the
* first byte is read.
* @param NumBytes is the number of bytes to be read from the Buffer.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - This operation is only supported in Atmel Serial Flash.
* - This function reads a Minimum of one Byte and a Maximum of an
* entire SRAM buffer (1 Page) from the Serial Flash.
* - The valid data is available from the fourth location pointed
* to by the ReadPtr.
* - Read the Spartan-3AN In-system Flash User Guide/Atmel
* AT45XXXD Data sheets for more information.
*
******************************************************************************/
static int BufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
u32 ByteOffset, u32 NumBytes)
{
int Status = (int)(XST_FAILURE);
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(BufferNum != 0);
Xil_AssertNonvoid(ReadPtr != NULL);
Xil_AssertNonvoid(ByteOffset != 0);
Xil_AssertNonvoid(NumBytes != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/*
* Check if the buffer number is valid or not.
*/
if ((BufferNum == XISF_PAGE_BUFFER1) ||
(BufferNum == XISF_PAGE_BUFFER2)) {
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
(BufferNum != XISF_PAGE_BUFFER1)) {
return (int)(XST_FAILURE);
}
} else {
return (int)(XST_FAILURE);
}
if (ReadPtr == NULL) {
return (int)(XST_FAILURE);
}
if (ByteOffset > InstancePtr->BytesPerPage){
return (int)(XST_FAILURE);
}
if ((NumBytes <= 0) || (NumBytes > InstancePtr->BytesPerPage)) {
return (int)(XST_FAILURE);
}
if (BufferNum == XISF_PAGE_BUFFER1) {
ReadPtr[BYTE1] = XISF_CMD_BUF1_READ; /* Buffer 1 Read. */
} else {
ReadPtr[BYTE1] = XISF_CMD_BUF2_READ; /* Buffer 2 Read.*/
}
ReadPtr[BYTE2] = (u8) (0x00);
ReadPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8);
ReadPtr[BYTE4] = (u8) ByteOffset;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr,
NumBytes + XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function reads the data from the internal SRAM page buffer of the Serial
* Flash memory at higher speed than normal Buffer Read operation.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param BufferNum specifies the internal SRAM Buffer from which data
* is to be read. The valid values are XISF_PAGE_BUFFER1 or
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
* AT45DB011D Flash as it contains a single buffer.
* @param ReadPtr is a pointer to the memory where the data read from the
* SRAM buffer is stored.
* @param ByteOffset is the byte offset in the buffer from where the
* first byte is read.
* @param NumBytes is the number of bytes to be read from the Buffer.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - This operation is only supported in Atmel Serial Flash.
* - This function reads a Minimum of one Byte and a Maximum of an
* entire SRAM buffer (1 Page) from the Serial Flash.
* - The valid data is available from the fifth location pointed
* to by the ReadPtr.
* - Read the Spartan-3AN In-system Flash User Guide/Atmel
* AT45XXXD Data sheets for more information.
*
******************************************************************************/
static int FastBufferRead(XIsf *InstancePtr, u8 BufferNum, u8 *ReadPtr,
u32 ByteOffset, u32 NumBytes)
{
int Status = (int)(XST_FAILURE);
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(BufferNum != 0);
Xil_AssertNonvoid(ReadPtr != NULL);
Xil_AssertNonvoid(ByteOffset != 0);
Xil_AssertNonvoid(NumBytes != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/*
* Check if the buffer number is valid or not.
*/
if ((BufferNum == XISF_PAGE_BUFFER1) ||
(BufferNum == XISF_PAGE_BUFFER2)) {
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
(BufferNum != XISF_PAGE_BUFFER1)) {
return (int)(XST_FAILURE);
}
} else {
return (int)(XST_FAILURE);
}
if (ReadPtr == NULL) {
return (int)(XST_FAILURE);
}
if (ByteOffset > InstancePtr->BytesPerPage){
return (int)(XST_FAILURE);
}
if ((NumBytes <= 0) || (NumBytes > InstancePtr->BytesPerPage)) {
return (int)(XST_FAILURE);
}
if (BufferNum == XISF_PAGE_BUFFER1) {
/*
* Buffer 1 Fast Read.
*/
ReadPtr[BYTE1] = XISF_CMD_FAST_BUF1_READ;
} else {
/*
* Buffer 2 Fast Read.
*/
ReadPtr[BYTE1] = XISF_CMD_FAST_BUF2_READ;
}
ReadPtr[BYTE2] = (u8) (0x00);
ReadPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8);
ReadPtr[BYTE4] = (u8) ByteOffset;
ReadPtr[BYTE5] = (u8) (XISF_DUMMYBYTE);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr,
NumBytes + XISF_CMD_FAST_READ_EXTRA_BYTES);
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function reads the data from OTP area of the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the starting address in OTP area of the Serial Flash
* from which the data is to be read.
* @param ReadPtr is a pointer to the memory where the data read from the
* Serial Flash is stored.
* @param ByteCount is the number of bytes to be read from the Serial
* Flash.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - This operation is only supported for Intel Serial Flash.
* - Minimum of one byte and a maximum of an entire Serial Flash
* array can be read.
******************************************************************************/
static int ReadOTPData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr,
u32 ByteCount)
{
int Status = (int)(XST_FAILURE);
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Address != 0);
Xil_AssertNonvoid(ReadPtr != NULL);
Xil_AssertNonvoid(ByteCount != 0);
#if (XPAR_XISF_FLASH_FAMILY == INTEL)
if (ByteCount <= 0 ) {
return (int)(XST_FAILURE);
}
if (ReadPtr == NULL) {
return (int)(XST_FAILURE);
}
ReadPtr[BYTE1] = XISF_CMD_OTP_READ;
ReadPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
ReadPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
ReadPtr[BYTE4] = (u8) Address;
ReadPtr[BYTE5] = (u8) (XISF_DUMMYBYTE);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, ReadPtr, ReadPtr,
ByteCount + XISF_OTP_RDWR_EXTRA_BYTES);
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */
return Status;
}

View file

@ -0,0 +1,411 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xilisf_spr.c
*
* This file contains the library functions to operate on Sector Protection
* feature of the Serial Flash. Refer xilisf.h for a detailed description.
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- -----------------------------------------------
* 1.00a ksu/sdm 03/03/08 First release
* 2.01a sdm 01/04/10 Added Support for Winbond W25QXX/W25XX devices
* 2.04a sdm 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
* flash memories
* 5.0 sb 08/05/14 Added Call back to lib interrupt handler
* after XIsf_Transfer Calls.
* Changed API:
* - XIsf_SectorProtect()
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "include/xilisf.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr,
u32 ByteCount);
extern int XIsf_GetStatus(XIsf *InstancePtr, u8 *ReadPtr);
static int SprRead(XIsf *InstancePtr, u8 *ReadPtr);
static int SprProgram(XIsf *InstancePtr, u8 *BufferPtr);
static int SprErase(XIsf *InstancePtr);
static int SpEnable(XIsf *InstancePtr);
static int SpDisable(XIsf *InstancePtr);
/************************** Variable Definitions *****************************/
extern u32 XIsf_StatusEventInfo;
extern unsigned int XIsf_ByteCountInfo;
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* This API is used for performing Sector Protect related operations.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Operation is the type of Sector Protect operation to be
* performed on the Serial Flash.
* The different operations are
* - XISF_SPR_READ: Read Sector Protection Register
* - XISF_SPR_WRITE: Write Sector Protection Register
* - XISF_SPR_ERASE: Erase Sector Protection Register
* - XISF_SP_ENABLE: Enable Sector Protection
* - XISF_SP_DISABLE: Disable Sector Protection
* @param BufferPtr is a pointer to the memory where the SPR content is
* read to/written from. This argument can be NULL if the
* Operation is SprErase, SpEnable and SpDisable.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - The SPR content is stored at the fourth location pointed
* by the BufferPtr when performing XISF_SPR_READ operation.
* - For Intel, STM, Winbond and Spansion Serial Flash, the user
* application must call the XIsf_WriteEnable() API by passing
* XISF_WRITE_ENABLE as an argument, before calling the
* XIsf_SectorProtect() API, for Sector Protect Register Write
* (XISF_SPR_WRITE) operation.
* - Atmel Flash supports all these Sector Protect operations.
* - Intel, STM, Winbond and Spansion Flash support only Sector
* Protect Read and Sector Protect Write operations.
*
******************************************************************************/
int XIsf_SectorProtect(XIsf *InstancePtr, XIsf_SpOperation Operation,
u8 *BufferPtr)
{
int Status = (int)(XST_FAILURE);
u8 Mode;
switch (Operation) {
case XISF_SPR_READ:
Status = SprRead(InstancePtr, BufferPtr);
break;
case XISF_SPR_WRITE:
Status = SprProgram(InstancePtr, BufferPtr);
break;
case XISF_SPR_ERASE:
Status = SprErase(InstancePtr);
break;
case XISF_SP_ENABLE:
Status = SpEnable(InstancePtr);
break;
case XISF_SP_DISABLE:
Status = SpDisable(InstancePtr);
break;
default:
/* Added Comment for MISRA C */
break;
}
/*
* Get the Transfer Mode
*/
Mode = XIsf_GetTransferMode(InstancePtr);
if(Mode == XISF_INTERRUPT_MODE){
InstancePtr->StatusHandler(InstancePtr,
XIsf_StatusEventInfo, XIsf_ByteCountInfo);
}
return Status;
}
/*****************************************************************************/
/**
*
* This function reads the content of the Sector Protection Register(SPR).
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param ReadPtr is a pointer to the memory where the SPR content is
* copied.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - This operation is supported for Atmel, Intel, STM, Winbond
* and Spansion Serial Flash.
* - The SPR content is stored at the fourth location pointed
* by the ReadPtr for Atmel Serial Flash and at second location
* for STM/Intel/Winbond/Spansion Serial Flash.
*
******************************************************************************/
static int SprRead(XIsf *InstancePtr, u8 *ReadPtr)
{
int Status;
Xil_AssertNonvoid(InstancePtr != NULL);
if (ReadPtr == NULL) {
return (int)(XST_FAILURE);
}
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
u32 Index;
/*
* Prepare the Write Buffer.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_READ;
for(Index = 1; Index < (InstancePtr->NumOfSectors +
XISF_CMD_SEND_EXTRA_BYTES); Index++) {
InstancePtr->WriteBufPtr[Index] = XISF_DUMMYBYTE;
}
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, ReadPtr,
InstancePtr->NumOfSectors +
XISF_CMD_SEND_EXTRA_BYTES);
#else
Status = XIsf_GetStatus(InstancePtr, ReadPtr);
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
return (int)(XST_SUCCESS);
}
/*****************************************************************************/
/**
*
* This function writes to the Sector Protection Register(SPR).
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param BufferPtr is the pointer to the data to be written to SPR.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This operation is supported for Atmel, Intel, STM, Winbond and
* Spansion Serial Flash.
*
******************************************************************************/
static int SprProgram(XIsf *InstancePtr, u8 *BufferPtr)
{
int Status;
Xil_AssertNonvoid(InstancePtr != NULL);
if (BufferPtr == NULL) {
return (int)(XST_FAILURE);
}
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
u32 Index;
/*
* Prepare the Write Buffer.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1;
InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2;
InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3;
InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_PROGRAM;
for(Index = 4; Index < (InstancePtr->NumOfSectors +
XISF_CMD_SEND_EXTRA_BYTES); Index++) {
InstancePtr->WriteBufPtr[Index] = *BufferPtr++;
}
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
InstancePtr->NumOfSectors +
XISF_CMD_SEND_EXTRA_BYTES);
#else
Status = XIsf_Write(InstancePtr, XISF_WRITE_STATUS_REG,
(void*) BufferPtr);
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
return (int)(XST_SUCCESS);
}
/*****************************************************************************/
/**
*
* This function erases the content of the Sector Protection Register(SPR).
*
* @param InstancePtr is a pointer to the XIsf instance.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int SprErase(XIsf *InstancePtr)
{
int Status = (int)(XST_FAILURE);
Xil_AssertNonvoid(InstancePtr != NULL);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/*
* Prepare the Write Buffer.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1;
InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2;
InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3;
InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_ERASE;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function enables Sector Protection. Sectors specified for protection in
* the Sector Protection Register are protected by using this operation.
*
* @param InstancePtr is a pointer to the XIsf instance.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int SpEnable(XIsf *InstancePtr)
{
int Status = (int)(XST_FAILURE);
Xil_AssertNonvoid(InstancePtr != NULL);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/*
* Prepare the Write Buffer.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1;
InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2;
InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3;
InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_ENABLE;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function Disables Sector Protection.
*
* @param InstancePtr is a pointer to the XIsf instance.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int SpDisable(XIsf *InstancePtr)
{
int Status = (int)(XST_FAILURE);
Xil_AssertNonvoid(InstancePtr != NULL);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/*
* Prepare the Write Buffer.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SPR_BYTE1;
InstancePtr->WriteBufPtr[BYTE2] = XISF_CMD_SPR_BYTE2;
InstancePtr->WriteBufPtr[BYTE3] = XISF_CMD_SPR_BYTE3;
InstancePtr->WriteBufPtr[BYTE4] = XISF_CMD_SPR_BYTE4_DISABLE;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)(XST_SUCCESS)) {
return (int)(XST_FAILURE);
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}

View file

@ -0,0 +1,975 @@
/******************************************************************************
*
* Copyright (C) 2012 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xilisf_write.c
*
* This file contains the library functions to write to the Serial Flash
* devices. Refer xilisf.h for detailed description.
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- -----------------------------------------------
* 1.00a ksu/sdm 03/03/08 First release
* 2.01a sdm 01/04/10 Added Support for Winbond W25QXX/W25XX devices
* 2.04a sdm 08/17/10 Updated to support Numonyx (N25QXX) and Spansion
* flash memories
* 3.00a srt 06/20/12 Updated to support interfaces SPI PS and QSPI PS.
* Added support to SST flash on SPI PS interface.
* 5.0 sb 08/05/14 Updated support for > 128 MB flash for PSQSPI
* interface.
* Changed API:
* WriteData()
* XIsf_Write()
* 5.2 asa 05/12/15 Added support for Micron (N25Q256A) flash part
* which supports 4 byte addressing.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "include/xilisf.h"
/************************** Constant Definitions *****************************/
#define SIXTEENMB 0x1000000 /**< Sixteen MB */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
extern int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr,
u32 ByteCount);
extern u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
extern int SendBankSelect(XIsf *InstancePtr, u32 BankSel);
#endif
static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address,
const u8 *BufferPtr, u32 ByteCount);
static int AutoPageWrite(XIsf *InstancePtr, u32 Address);
static int BufferWrite(XIsf *InstancePtr, u8 BufferNum, const u8 *WritePtr,
u32 ByteOffset, u32 NumBytes);
static int BufferToFlashWriteWithErase(XIsf *InstancePtr, u8 BufferNum,
u32 Address);
static int BufferToFlashWriteWithoutErase(XIsf *InstancePtr, u8 BufferNum,
u32 Address);
static int WriteSR(XIsf *InstancePtr, u8 SRData);
static int WriteSR2(XIsf *InstancePtr, u8 *SRData);
static int WriteOTPData(XIsf *InstancePtr, u32 Address, const u8 *BufferPtr);
/************************** Variable Definitions *****************************/
extern u32 XIsf_StatusEventInfo;
extern unsigned int XIsf_ByteCountInfo;
/************************** Function Definitions ******************************/
/*****************************************************************************/
/**
*
* This API writes the data to the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Operation is the type of write operation to be performed on the
* Serial Flash.
* The different operations are
* - XISF_WRITE: Normal Write
* - XISF_DUAL_IP_PAGE_WRITE: Dual Input Fast Program
* - XISF_DUAL_IP_EXT_PAGE_WRITE: Dual Input Extended Fast Program
* - XISF_QUAD_IP_PAGE_WRITE: Quad Input Fast Program
* - XISF_QUAD_IP_EXT_PAGE_WRITE: Quad Input Extended Fast Program
* - XISF_AUTO_PAGE_WRITE: Auto Page Write
* - XISF_BUFFER_WRITE: Buffer Write
* - XISF_BUF_TO_PAGE_WRITE_WITH_ERASE: Buffer to Page Transfer
* with Erase
* - XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE: Buffer to Page Transfer
* without Erase
* - XISF_WRITE_STATUS_REG: Status Register Write
* - XISF_WRITE_STATUS_REG2: 2 byte Status Register Write
* - XISF_OTP_WRITE: OTP Write.
*
* @param OpParamPtr is pointer to a structure variable which contains
* operational parameters of the specified operation.
* This parameter type is dependant on value of first argument
* (Operation).
*
* - Normal Write (XISF_WRITE), Dual Input Fast Program
* (XISF_DUAL_IP_PAGE_WRITE), Dual Input Extended Fast Program
* (XISF_DUAL_IP_EXT_PAGE_WRITE), Quad Input Fast Program
* (XISF_QUAD_IP_PAGE_WRITE), Quad Input Extended Fast Program
* (XISF_QUAD_IP_EXT_PAGE_WRITE):
* The OpParamPtr must be of type struct XIsf_WriteParam.
* OpParamPtr->Address is the start address in the Serial Flash.
* OpParamPtr->WritePtr is a pointer to the data to be written to
* the Serial Flash.
* OpParamPtr->NumBytes is the number of bytes to be written to
* Serial Flash.
* This operation is supported for Atmel, Intel, STM, Winbond and
* Spansion Serial Flash.
*
* - Auto Page Write (XISF_AUTO_PAGE_WRITE):
* The OpParamPtr must be of 32 bit unsigned integer variable.
* This is the address of page number in the Serial Flash which is
* to be refreshed.
* This operation is only supported for Atmel Serial Flash.
*
* - Buffer Write (XISF_BUFFER_WRITE):
* The OpParamPtr must be of type struct
* XIsf_BufferToFlashWriteParam.
* OpParamPtr->BufferNum specifies the internal SRAM Buffer of the
* Serial Flash. The valid values are XISF_PAGE_BUFFER1 or
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
* AT45DB011D Flash as it contains a single buffer.
* OpParamPtr->WritePtr is a pointer to the data to be written to
* the Serial Flash SRAM Buffer.
* OpParamPtr->ByteOffset is byte offset in the buffer from where
* the data is to be written.
* OpParamPtr->NumBytes is number of bytes to be written to the
* Buffer.
* This operation is supported only for Atmel Serial Flash.
*
* - Buffer To Memory Write With Erase
* (XISF_BUF_TO_PAGE_WRITE_WITH_ERASE)/
* Buffer To Memory Write Without Erase
* (XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE):
* The OpParamPtr must be of type struct
* XIsf_BufferToFlashWriteParam.
* OpParamPtr->BufferNum specifies the internal SRAM Buffer of the
* Serial Flash. The valid values are XISF_PAGE_BUFFER1 or
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
* AT45DB011D Flash as it contains a single buffer.
* OpParamPtr->Address is starting address in the Serial Flash
* memory from where the data is to be written.
* These operations are only supported for Atmel Serial Flash.
*
* - Write Status Register (XISF_WRITE_STATUS_REG):
* The OpParamPtr must be of type of 8 bit unsigned integer
* variable. This is the value to be written to the Status
* Register.
* This operation is only supported for Intel, STM Winbond and
* Spansion Serial Flash.
*
* - Write Status Register2 (XISF_WRITE_STATUS_REG2):
* The OpParamPtr must be of type (u8 *) and should point to two
* 8 bit unsigned integer values. This is the value to be written
* to the 16 bit Status Register.
* This operation is only supported in Winbond (W25Q) Serial Flash.
*
* - One Time Programmable Area Write (XISF_OTP_WRITE):
* The OpParamPtr must be of type struct XIsf_WriteParam.
* OpParamPtr->Address is the address in the SRAM Buffer of the
* Serial Flash to which the data is to be written.
* OpParamPtr->WritePtr is a pointer to the data to be written to
* the Serial Flash.
* OpParamPtr->NumBytes should be set to 1 when performing
* OTPWrite operation.
* This operation is only supported for Intel Serial Flash.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - Application must fill the structure elements of the third
* argument and pass its pointer by type casting it with void
* pointer.
* - For Intel, STM, Winbond and Spansion Serial Flash, the user
* application must call the XIsf_WriteEnable() API by passing
* XISF_WRITE_ENABLE as an argument, before calling the
* XIsf_Write() API.
*
******************************************************************************/
int XIsf_Write(XIsf *InstancePtr, XIsf_WriteOperation Operation,
void *OpParamPtr)
{
int Status = (int)XST_FAILURE;
u8 Mode;
XIsf_WriteParam *WriteParamPtr;
XIsf_BufferWriteParam *BufferWriteParamPtr;
XIsf_BufferToFlashWriteParam *BufferToFlashWriteParamPtr;
if (InstancePtr == NULL) {
return (int)XST_FAILURE;
}
if (InstancePtr->IsReady != TRUE) {
return (int)XST_FAILURE;
}
if (NULL == OpParamPtr) {
return (int)XST_FAILURE;
}
switch (Operation) {
case XISF_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
Status = WriteData(InstancePtr,
XISF_CMD_PAGEPROG_WRITE,
WriteParamPtr->Address,
WriteParamPtr->WritePtr,
WriteParamPtr->NumBytes);
break;
case XISF_AUTO_PAGE_WRITE:
Status = AutoPageWrite(InstancePtr,
*((u32*)(void *) OpParamPtr));
break;
case XISF_BUFFER_WRITE:
BufferWriteParamPtr = (XIsf_BufferWriteParam*)
(void *) OpParamPtr;
Xil_AssertNonvoid(BufferWriteParamPtr != NULL);
Status = BufferWrite(InstancePtr,
BufferWriteParamPtr->BufferNum,
BufferWriteParamPtr->WritePtr,
BufferWriteParamPtr->ByteOffset,
BufferWriteParamPtr->NumBytes);
break;
case XISF_BUF_TO_PAGE_WRITE_WITH_ERASE:
BufferToFlashWriteParamPtr =
(XIsf_BufferToFlashWriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(BufferToFlashWriteParamPtr != NULL);
Status = BufferToFlashWriteWithErase(InstancePtr,
BufferToFlashWriteParamPtr->BufferNum,
BufferToFlashWriteParamPtr->Address);
break;
case XISF_BUF_TO_PAGE_WRITE_WITHOUT_ERASE:
BufferToFlashWriteParamPtr =
(XIsf_BufferToFlashWriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(BufferToFlashWriteParamPtr != NULL);
Status = BufferToFlashWriteWithoutErase(InstancePtr,
BufferToFlashWriteParamPtr->BufferNum,
BufferToFlashWriteParamPtr->Address);
break;
case XISF_WRITE_STATUS_REG:
Status = WriteSR(InstancePtr,
*((u8*)(void *) OpParamPtr));
break;
case XISF_OTP_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
if (1 == WriteParamPtr->NumBytes) {
Status = WriteOTPData(InstancePtr,
WriteParamPtr->Address,
WriteParamPtr->WritePtr);
}
break;
case XISF_WRITE_STATUS_REG2:
Status = WriteSR2(InstancePtr,
(u8*)(void *) OpParamPtr);
break;
#if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == STM) \
|| (XPAR_XISF_FLASH_FAMILY == SPANSION))
case XISF_QUAD_IP_PAGE_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
Status = WriteData(InstancePtr,
XISF_CMD_QUAD_IP_PAGE_WRITE,
WriteParamPtr->Address,
WriteParamPtr->WritePtr,
WriteParamPtr->NumBytes);
break;
#endif /*((XPAR_XISF_FLASH_FAMILY == WINBOND) ||
(XPAR_XISF_FLASH_FAMILY == STM) ||
(XPAR_XISF_FLASH_FAMILY == SPANSION))*/
#if (XPAR_XISF_FLASH_FAMILY == STM)
case XISF_DUAL_IP_PAGE_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
Status = WriteData(InstancePtr,
XISF_CMD_DUAL_IP_PAGE_WRITE,
WriteParamPtr->Address,
WriteParamPtr->WritePtr,
WriteParamPtr->NumBytes);
break;
case XISF_DUAL_IP_EXT_PAGE_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
Status = WriteData(InstancePtr,
XISF_CMD_DUAL_IP_EXT_PAGE_WRITE,
WriteParamPtr->Address,
WriteParamPtr->WritePtr,
WriteParamPtr->NumBytes);
break;
case XISF_QUAD_IP_EXT_PAGE_WRITE:
WriteParamPtr = (XIsf_WriteParam*)(void *) OpParamPtr;
Xil_AssertNonvoid(WriteParamPtr != NULL);
Status = WriteData(InstancePtr,
XISF_CMD_QUAD_IP_EXT_PAGE_WRITE,
WriteParamPtr->Address,
WriteParamPtr->WritePtr,
WriteParamPtr->NumBytes);
break;
#endif /* (XPAR_XISF_FLASH_FAMILY == STM) */
default:
break;
}
Mode = XIsf_GetTransferMode(InstancePtr);
if(Mode == XISF_INTERRUPT_MODE){
InstancePtr->StatusHandler(InstancePtr,
XIsf_StatusEventInfo, XIsf_ByteCountInfo);
}
return Status;
}
/*****************************************************************************/
/**
*
* This function writes the data to the specified address locations in Serial
* Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address in the Serial Flash memory, where the
* data is to be written.
* @param BufferPtr is a pointer to the data to be written to Serial
* Flash.
* @param ByteCount is the number of bytes to be written.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - A minimum of one byte and a maximum of one Page can be
* written using this function.
* - This operation is supported for Atmel, Intel, STM, Winbond
* and Spansion Serial Flash.
*
******************************************************************************/
static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address,
const u8 *BufferPtr, u32 ByteCount)
{
u8 Mode;
u32 Index;
u32 BankSel;
u32 RealAddr;
int Status;
u8 FlagStatus[2] = {0};
u8 FlashStatus[2] = {0};
u8 * NULLPtr = NULL;
const u8 * LocalBufPtr = BufferPtr;
#ifdef XPAR_XISF_INTERFACE_PSQSPI
u32 FlashMake = InstancePtr->ManufacturerID;
#endif
u8 ReadStatusCmdBuf[] = { READ_STATUS_CMD, 0 };
u8 ReadFlagSRCmd[] = {READ_FLAG_STATUS_CMD, 0};
if ((ByteCount <= 0) || (ByteCount > InstancePtr->BytesPerPage)) {
return (int)XST_FAILURE;
}
if (LocalBufPtr == NULL) {
return (int)XST_FAILURE;
}
/*
* Translate address based on type of connection
* If stacked assert the slave select based on address
*/
RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, Address);
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* 0x18 is the DeviceIDMemSize for different make of
* flashes of size 16MB
*/
if(InstancePtr->DeviceIDMemSize > 0x18) {
/*
* Get the Transfer Mode
*/
Mode = XIsf_GetTransferMode(InstancePtr);
/*
* Seting the transfer mode to Polled Mode before
* performing the Bank Select operation.
*/
XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
/*
* Calculate bank
*/
BankSel = RealAddr/SIXTEENMB;
/*
* Select bank
*/
(void)SendBankSelect(InstancePtr, BankSel);
/*
* Restoring the transfer mode back
*/
XIsf_SetTransferMode(InstancePtr, Mode);
}
#endif
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
if (InstancePtr->FourByteAddrMode == TRUE) {
InstancePtr->WriteBufPtr[BYTE1] = Command;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT24);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE5] = (u8) (RealAddr);
for(Index = 5U; Index < (ByteCount + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE);
Index++) {
InstancePtr->WriteBufPtr[Index] = *LocalBufPtr;
LocalBufPtr += 1;
}
} else {
#endif
InstancePtr->WriteBufPtr[BYTE1] = Command;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr);
for(Index = 4U; Index < (ByteCount + XISF_CMD_SEND_EXTRA_BYTES);
Index++) {
InstancePtr->WriteBufPtr[Index] = *LocalBufPtr;
LocalBufPtr += 1;
}
#if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \
(!defined(XPAR_XISF_INTERFACE_PSQSPI)))
}
#endif
#ifdef XPAR_XISF_INTERFACE_PSQSPI
/*
* Enable write before transfer
*/
Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE);
#endif
if (InstancePtr->FourByteAddrMode == TRUE) {
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr,
(ByteCount + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE));
} else {
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr,
(ByteCount + XISF_CMD_SEND_EXTRA_BYTES));
}
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#ifdef XPAR_XISF_INTERFACE_PSQSPI
if((InstancePtr->NumDie > 1) &&
(FlashMake == XISF_MANUFACTURER_ID_MICRON)) {
Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
(u32)sizeof(ReadFlagSRCmd));
if(Status != (int)XST_SUCCESS){
return (int)XST_FAILURE;
}
}
/*
* Wait for the write command to the Flash to be completed, it takes
* some time for the data to be written
*/
while (1) {
/*
* Poll the status register of the Flash to determine when it
* completes, by sending a read status command and receiving
* status byte
*/
Status = XIsf_Transfer(InstancePtr, ReadStatusCmdBuf,
FlashStatus, (u32)sizeof(ReadStatusCmdBuf));
if(Status != (int)XST_SUCCESS){
return (int)XST_FAILURE;
}
/*
* If status indicates the write is done, then stop waiting,
* if a value of 0xFF in the status byte is read from the
* device and this loop never exits, the device slave select is
* possibly incorrect such that the device status is not being
* read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
if((InstancePtr->NumDie > 1) &&
(FlashMake == XISF_MANUFACTURER_ID_MICRON)) {
Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus,
(u32)sizeof(ReadFlagSRCmd));
if(Status != (int)XST_SUCCESS){
return (int)XST_FAILURE;
}
}
#endif
return Status;
}
/*****************************************************************************/
/**
*
* This function Auto rewrites the contents of a Page in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address of the page to be refreshed.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int AutoPageWrite(XIsf *InstancePtr, u32 Address)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Address != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_AUTOPAGE_WRITE;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (XISF_DUMMYBYTE);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function writes data to the specified SRAM buffer of the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param BufferNum specifies the internal SRAM Buffer of the Serial
* Flash. The valid values are XISF_PAGE_BUFFER1 or
* XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2 is not valid in case of
* Atmel AT45DB011D Serial Flash as it contains a single buffer.
* @param WritePtr is the pointer to the data to be written to the
* Serial Flash SRAM Buffer.
* @param ByteOffset is the byte offset in the buffer from where the
* data is to be written.
* @param NumBytes is the number of bytes to be written to the Buffer.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - A minimum of one byte and a maximum of one SRAM buffer can be
* written using this function.
* - This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int BufferWrite(XIsf *InstancePtr, u8 BufferNum, const u8 *WritePtr,
u32 ByteOffset, u32 NumBytes)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(BufferNum != 0);
Xil_AssertNonvoid(WritePtr != NULL);
Xil_AssertNonvoid(ByteOffset != 0);
Xil_AssertNonvoid(NumBytes != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
u16 Index;
/*
* Check buffer number is valid or not.
*/
if ((BufferNum == XISF_PAGE_BUFFER1) ||
(BufferNum == XISF_PAGE_BUFFER2)) {
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
(BufferNum != XISF_PAGE_BUFFER1)) {
return (int)XST_FAILURE;
}
}
else{
return (int)XST_FAILURE;
}
if (WritePtr == NULL) {
return (int)XST_FAILURE;
}
if (ByteOffset > InstancePtr->BytesPerPage) {
return (int)XST_FAILURE;
}
if ((NumBytes <= 0) || (NumBytes > InstancePtr->BytesPerPage)) {
return (int)XST_FAILURE;
}
if (BufferNum == XISF_PAGE_BUFFER1) {
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUFFER1_WRITE;
}
else{
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUFFER2_WRITE;
}
InstancePtr->WriteBufPtr[BYTE2] = (u8) (0x00);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (ByteOffset >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) ByteOffset;
for(Index = 4; Index < NumBytes + XISF_CMD_SEND_EXTRA_BYTES; Index++) {
InstancePtr->WriteBufPtr[Index] = *WritePtr++;
}
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
(NumBytes + XISF_CMD_SEND_EXTRA_BYTES));
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function first erases a page and then writes data from the specified
* internal SRAM buffer to the specified locations in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param BufferNum specifies the internal SRAM Buffer, from which the
* data needs to be written to the Serial Flash. The valid values
* are XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2
* is not valid in the case of Atmel AT45DB011D Serial Flash as it
* contains a single buffer.
* @param Address is the starting address in the Serial Flash where
* the data has to be written. Byte address in this address is
* ignored as an entire Page is transferred using this API.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - A minimum of one Page and a maximum of one Page can be
* written using this function.
* - This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int BufferToFlashWriteWithErase(XIsf *InstancePtr, u8 BufferNum,
u32 Address)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(BufferNum != 0);
Xil_AssertNonvoid(Address != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/*
* Check whether the buffer number is valid or not.
*/
if ((BufferNum == XISF_PAGE_BUFFER1) ||
(BufferNum == XISF_PAGE_BUFFER2)) {
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
(BufferNum != XISF_PAGE_BUFFER1)) {
return (int)XST_FAILURE;
}
}
else {
return (int)XST_FAILURE;
}
if (BufferNum == XISF_PAGE_BUFFER1) {
/*
* Buffer 1 to Page Program With Erase.
*/
InstancePtr->WriteBufPtr[BYTE1] =
XISF_CMD_ERASE_BUF1TOPAGE_WRITE;
} else {
/*
* Buffer 2 to Page Program With Erase.
*/
InstancePtr->WriteBufPtr[BYTE1] =
XISF_CMD_ERASE_BUF2TOPAGE_WRITE;
}
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) (XISF_DUMMYBYTE);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function writes data from the specified internal SRAM buffer to the
* specified locations in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param BufferNum specifies the internal SRAM Buffer, from which the
* data needs to be written to the Serial Flash. The valid values
* are XISF_PAGE_BUFFER1 or XISF_PAGE_BUFFER2. XISF_PAGE_BUFFER2
* is not valid in the case of Atmel AT45DB011D Serial Flash as it
* contains a single buffer.
* @param Address is the starting address in the Serial Flash where
* data has to be written. Byte address in this address will be
* ignored as an entire page of data is transferred using this
* operation.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* - A minimum of one Page and a maximum of one Page can be
* written using this function.
* - This operation is only supported for Atmel Serial Flash.
*
******************************************************************************/
static int BufferToFlashWriteWithoutErase(XIsf *InstancePtr, u8 BufferNum,
u32 Address)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(BufferNum != 0);
Xil_AssertNonvoid(Address != 0);
#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
/*
* Check whether the buffer number is valid or not.
*/
if ((BufferNum == XISF_PAGE_BUFFER1) ||
(BufferNum == XISF_PAGE_BUFFER2)) {
if ((InstancePtr->DeviceCode == XISF_ATMEL_DEV_AT45DB011D) &&
(XISF_PAGE_BUFFER1 != 1)) {
return (int)XST_FAILURE;
}
}
else {
return (int)XST_FAILURE;
}
if (BufferNum == XISF_PAGE_BUFFER1) {
/*
* Buffer 1 to Page Program Without Erase.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUF1TOPAGE_WRITE;
}
else {
/*
* Buffer 2 to Page Program Without Erase.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_BUF2TOPAGE_WRITE;
}
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) (XISF_DUMMYBYTE);
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_CMD_SEND_EXTRA_BYTES);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */
return Status;
}
/*****************************************************************************/
/**
*
* This function writes data to the Status Register of the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param SRData is the value to be written to the Status Register
* of the Serial Flash.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This operation is only supported in Intel, STM, Winbond and
* Spansion Serial Flash. This is the write of Status Register 1
* for Winbond devices, write of Status Register 2 is handled by
* WriteSR2.
*
******************************************************************************/
static int WriteSR(XIsf *InstancePtr, u8 SRData)
{
int Status = XST_FAILURE;
#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \
(XPAR_XISF_FLASH_FAMILY == WINBOND) || \
(XPAR_XISF_FLASH_FAMILY == SPANSION) || (XPAR_XISF_FLASH_FAMILY == SST))
/*
* Prepare the Write Buffer.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_WRITE;
InstancePtr->WriteBufPtr[BYTE2] = SRData;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_STATUS_RDWR_BYTES);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \\
(XPAR_XISF_FLASH_FAMILY == WINBOND) ||
(XPAR_XISF_FLASH_FAMILY == SPANSION)) */
return Status;
}
/*****************************************************************************/
/**
*
* This function writes data to Status Register of the Serial Flash. This API
* should be used to write to the 16 bit status register in Winbond Quad Flash
* (W25QXX).
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param SRData is of type (u8*) and points to the 16 bit value to be
* written to the Status Register of the Serial Flash.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note This operation is only supported in Winbond (W25QXX) Serial
* Flash.
*
******************************************************************************/
static int WriteSR2(XIsf *InstancePtr, u8 *SRData)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(SRData != NULL);
#if (XPAR_XISF_FLASH_FAMILY == WINBOND)
/*
* Prepare the Write Buffer.
*/
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_WRITE;
InstancePtr->WriteBufPtr[BYTE2] = *SRData++;
InstancePtr->WriteBufPtr[BYTE3] = *SRData;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_STATUS_RDWR_BYTES + 1);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == WINBOND) */
return Status;
}
/*****************************************************************************/
/**
*
* This function writes one byte of data to the OTP area in the Serial Flash.
*
* @param InstancePtr is a pointer to the XIsf instance.
* @param Address is the address in the OTP area, where to write data.
* @param BufferPtr is the pointer to the data to be written into OTP
* region of Serial Flash.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
* - A minimum of one byte and a maximum of one byte can be
* written using this function.
* - This operation is supported only for Intel Serial Flash.
*
******************************************************************************/
static int WriteOTPData(XIsf *InstancePtr, u32 Address, const u8 *BufferPtr)
{
int Status = (int)XST_FAILURE;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Address != 0);
Xil_AssertNonvoid(BufferPtr != NULL);
#if (XPAR_XISF_FLASH_FAMILY == INTEL)
if (BufferPtr == NULL) {
return (int)XST_FAILURE;
}
InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_OTP_WRITE;
InstancePtr->WriteBufPtr[BYTE2] = (u8) (Address >> XISF_ADDR_SHIFT16);
InstancePtr->WriteBufPtr[BYTE3] = (u8) (Address >> XISF_ADDR_SHIFT8);
InstancePtr->WriteBufPtr[BYTE4] = (u8) Address;
InstancePtr->WriteBufPtr[BYTE5] = *BufferPtr;
/*
* Initiate the Transfer.
*/
Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULL,
XISF_OTP_RDWR_EXTRA_BYTES);
if (Status != (int)XST_SUCCESS) {
return (int)XST_FAILURE;
}
#endif /* (XPAR_XISF_FLASH_FAMILY == INTEL) */
return Status;
}