Files
castelion_radar_alinx_kintex/vitis/radar/src/config_flash.c

491 lines
11 KiB
C
Executable File

#include <stdarg.h>
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "xspi.h"
#include "project.h"
#include "config_flash.h"
static XSpi Spi;
#define SPI_SELECT 0x01
/*
* Definitions of the commands shown in this example.
*/
#define COMMAND_PAGE_PROGRAM 0x02 /* Page Program command */
#define COMMAND_QUAD_WRITE 0x32 /* Quad Input Fast Program */
#define COMMAND_RANDOM_READ 0x03 /* Random read command */
#define COMMAND_DUAL_READ 0x3B /* Dual Output Fast Read */
#define COMMAND_DUAL_IO_READ 0xBB /* Dual IO Fast Read */
#define COMMAND_QUAD_READ 0x6B /* Quad Output Fast Read */
#define COMMAND_QUAD_IO_READ 0xEB /* Quad IO Fast Read */
#define COMMAND_WRITE_ENABLE 0x06 /* Write Enable command */
#define COMMAND_SECTOR_ERASE 0xD8 /* Sector Erase command */
#define COMMAND_BULK_ERASE 0xC7 /* Bulk Erase command */
#define COMMAND_STATUSREG_READ 0x05 /* Status read command */
/**
* This definitions specify the EXTRA bytes in each of the command
* transactions. This count includes Command byte, address bytes and any
* don't care bytes needed.
*/
#define READ_WRITE_EXTRA_BYTES 4 /* Read/Write extra bytes */
#define WRITE_ENABLE_BYTES 1 /* Write Enable bytes */
#define SECTOR_ERASE_BYTES 4 /* Sector erase extra bytes */
#define BULK_ERASE_BYTES 1 /* Bulk erase extra bytes */
#define STATUS_READ_BYTES 2 /* Status read bytes count */
#define STATUS_WRITE_BYTES 2 /* Status write bytes count */
/*
* Flash not busy mask in the status register of the flash device.
*/
#define FLASH_SR_IS_READY_MASK 0x01 /* Ready mask */
/*
* Number of bytes per page in the flash device.
*/
#define PAGE_SIZE 256
/*
* 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 */
#define BYTE6 5 /* Byte 6 position */
#define BYTE7 6 /* Byte 7 position */
#define BYTE8 7 /* Byte 8 position */
#define DUAL_READ_DUMMY_BYTES 2
#define QUAD_READ_DUMMY_BYTES 4
#define DUAL_IO_READ_DUMMY_BYTES 2
#define QUAD_IO_READ_DUMMY_BYTES 5
void config_flash_spi_handler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount);
volatile static int TransferInProgress;
static int ErrorCount;
static u8 ReadBuffer[PAGE_SIZE + READ_WRITE_EXTRA_BYTES + 4];
static u8 WriteBuffer[PAGE_SIZE + READ_WRITE_EXTRA_BYTES];
int config_flash_get_status(XSpi *SpiPtr)
{
int Status;
/*
* Prepare the Write Buffer.
*/
WriteBuffer[BYTE1] = COMMAND_STATUSREG_READ;
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, ReadBuffer,
STATUS_READ_BYTES);
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) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
int config_flash_wait_for_ready(void)
{
int Status;
u8 StatusReg;
while(1) {
/*
* Get the Status Register. The status register content is
* stored at the second byte pointed by the ReadBuffer.
*/
Status = config_flash_get_status(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Check if the flash is ready to accept the next command.
* If so break.
*/
StatusReg = ReadBuffer[1];
if((StatusReg & FLASH_SR_IS_READY_MASK) == 0) {
break;
}
}
// xil_printf("Flash Ready\r\n");
return XST_SUCCESS;
}
int config_flash_write_enable(XSpi *SpiPtr)
{
int Status;
/*
* Wait while the Flash is busy.
*/
Status = config_flash_wait_for_ready();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = COMMAND_WRITE_ENABLE;
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(SpiPtr, WriteBuffer, NULL,
WRITE_ENABLE_BYTES);
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) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
int config_flash_sector_erase(u32 Addr)
{
int Status;
/*
* Perform the Write Enable operation.
*/
Status = config_flash_write_enable(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait while the Flash is busy.
*/
Status = config_flash_wait_for_ready();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = COMMAND_SECTOR_ERASE;
WriteBuffer[BYTE2] = (u8) (Addr >> 16);
WriteBuffer[BYTE3] = (u8) (Addr >> 8);
WriteBuffer[BYTE4] = (u8) (Addr);
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(&Spi, WriteBuffer, NULL,
SECTOR_ERASE_BYTES);
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) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
int config_flash_write(u32 Addr, u8 * data, u32 ByteCount)
{
u32 Index;
int Status;
/*
* Perform the Write Enable operation.
*/
Status = config_flash_write_enable(&Spi);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait while the Flash is busy.
*/
Status = config_flash_wait_for_ready();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Prepare the WriteBuffer.
*/
WriteBuffer[BYTE1] = COMMAND_PAGE_PROGRAM;
WriteBuffer[BYTE2] = (u8) (Addr >> 16);
WriteBuffer[BYTE3] = (u8) (Addr >> 8);
WriteBuffer[BYTE4] = (u8) Addr;
/*
* Fill in the TEST data that is to be written into the Numonyx Serial
* Flash device.
*/
for(Index = 4; Index < ByteCount + READ_WRITE_EXTRA_BYTES; Index++) {
// WriteBuffer[Index] = (u8)((Index - 4) + TestByte);
WriteBuffer[Index] = data[Index - 4];
}
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer(&Spi, WriteBuffer, NULL,
(ByteCount + READ_WRITE_EXTRA_BYTES));
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) {
ErrorCount = 0;
return XST_FAILURE;
}
return XST_SUCCESS;
}
int config_flash_read(u32 Addr, u8 * data, u32 ByteCount)
{
int Status;
/*
* Wait while the Flash is busy.
*/
Status = config_flash_wait_for_ready();
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Prepare the WriteBuffer.
*/
u8 ReadCmd = COMMAND_RANDOM_READ;
WriteBuffer[BYTE1] = ReadCmd;
WriteBuffer[BYTE2] = (u8) (Addr >> 16);
WriteBuffer[BYTE3] = (u8) (Addr >> 8);
WriteBuffer[BYTE4] = (u8) Addr;
if (ReadCmd == COMMAND_DUAL_READ) {
ByteCount += DUAL_READ_DUMMY_BYTES;
} else if (ReadCmd == COMMAND_DUAL_IO_READ) {
ByteCount += DUAL_READ_DUMMY_BYTES;
} else if (ReadCmd == COMMAND_QUAD_IO_READ) {
ByteCount += QUAD_IO_READ_DUMMY_BYTES;
} else if (ReadCmd==COMMAND_QUAD_READ) {
ByteCount += QUAD_READ_DUMMY_BYTES;
}
/*
* Initiate the Transfer.
*/
TransferInProgress = TRUE;
Status = XSpi_Transfer( &Spi, WriteBuffer, ReadBuffer,
(ByteCount + READ_WRITE_EXTRA_BYTES));
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) {
ErrorCount = 0;
return XST_FAILURE;
}
for(int i = 0; i < ByteCount; i++) {
data[i] = ReadBuffer[i + READ_WRITE_EXTRA_BYTES];
}
return XST_SUCCESS;
}
int config_flash_read_config(void) {
int Status;
u8 offset = 0x40;
config_flash_sector_erase(CONFIG_BASE_ADDRESS);
//
// /*
// * Write the data to the Page using Page Program command.
// */
// xil_printf("Flash Write\r\n");
// u8 data[PAGE_SIZE];
// for(int i = 0; i < PAGE_SIZE; i++) {
// data[i] = i + offset;
// }
//
// Status = config_flash_write(CONFIG_BASE_ADDRESS, data, PAGE_SIZE);
// if(Status != XST_SUCCESS) {
// return XST_FAILURE;
// }
//
// /*
// * Clear the read Buffer.
// */
// for(int Index = 0; Index < PAGE_SIZE + READ_WRITE_EXTRA_BYTES; Index++) {
// ReadBuffer[Index] = 0x0;
// }
//
// /*
// * Read the data from the Page using Random Read command.
// */
// xil_printf("Flash Read\r\n");
// Status = config_flash_read(CONFIG_BASE_ADDRESS, data, PAGE_SIZE);
// if(Status != XST_SUCCESS) {
// return XST_FAILURE;
// }
//
// /*
// * Compare the data read against the data written.
// */
// for(int Index = 0; Index < PAGE_SIZE; Index++) {
// if(data[Index ] != (u8)(Index + offset)) {
// return XST_FAILURE;
// }
// }
//
// xil_printf("Data Matches\r\n");
return XST_SUCCESS;
}
int config_flash_init(void) {
int Status;
XSpi_Config *ConfigPtr; /* Pointer to Configuration data */
/*
* Initialize the SPI driver so that it's ready to use,
* specify the device ID that is generated in xparameters.h.
*/
ConfigPtr = XSpi_LookupConfig(XPAR_QSPI_FLASH_DEVICE_ID);
if (ConfigPtr == NULL) {
return XST_DEVICE_NOT_FOUND;
}
Status = XSpi_CfgInitialize(&Spi, ConfigPtr,
ConfigPtr->BaseAddress);
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.
*/
xPortInstallInterruptHandler(XPAR_MICROBLAZE_0_AXI_INTC_QSPI_FLASH_IP2INTC_IRPT_INTR, (XInterruptHandler)XSpi_InterruptHandler, (void *)&Spi);
vPortEnableInterrupt(XPAR_MICROBLAZE_0_AXI_INTC_QSPI_FLASH_IP2INTC_IRPT_INTR);
// 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.
*/
XSpi_SetStatusHandler(&Spi, &Spi, (XSpi_StatusHandler)config_flash_spi_handler);
/*
* Set the SPI device as a master and in manual slave select mode such
* that the slave select signal does not toggle for every byte of a
* transfer, this must be done before the slave select is set.
*/
Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION |
XSP_MANUAL_SSELECT_OPTION);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Select the quad flash device on the SPI bus, so that it can be
* read and written using the SPI bus.
*/
Status = XSpi_SetSlaveSelect(&Spi, SPI_SELECT);
if(Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Start the SPI driver so that interrupts and the device are enabled.
*/
XSpi_Start(&Spi);
// config_flash_read_config();
return XST_SUCCESS;
}
void config_flash_spi_handler(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++;
}
}