📄 spi_flash_test.c
字号:
/*******************************************************************
Analog Devices, Inc. All Rights Reserved.
This software is proprietary and confidential. By using this software
you agree to the terms of the associated Analog Devices License Agreement.
Project Name: Power_On_Self_Test
Hardware: ADSP-BF518F EZ-Board
Description: This file tests the SPI flash on the EZ-Board.
*******************************************************************/
/*******************************************************************
* include files
*******************************************************************/
#include <cdefbf518.h>
#include <defbf518.h>
#include <stdlib.h>
#include <drivers\flash\util.h> /* library struct includes */
#include <drivers\flash\Errors.h> /* error type includes */
#include <drivers\flash\m25p16.h> /* flash includes */
#define MAN_CODE 0x20 /* Numonyx */
#define DEV_CODE 0x15 /* M25P16 (16Mbit SPI flash) */
#define NUM_SECTORS 32 /* sectors */
/*******************************************************************
* function prototypes
*******************************************************************/
int CheckForCFISupport_Spi(void);
/*******************************************************************
* Function: TEST_SPIFLASH
* Description: This test will test the SPI flash on the EZ-Board.
* Since an image may live in the start of SPI flash
* we will not erase the entire flash during this test.
* We will first verify the manufacturer and vendor IDs
* then we will perform operations on the last 32KB
* of flash only.
*******************************************************************/
int TEST_SPI_FLASH(void)
{
int i, j; /* indexes */
unsigned int iPassed = 0; /* pass flag */
ERROR_CODE Result = NO_ERR; /* result */
COMMAND_STRUCT pCmdBuffer; /* command buffer */
unsigned short usRd = 0, usWr = 0; /* storage for data */
int nManCode = 0, nDevCode = 0; /* man and device ids */
/* sectors to be tested: we chose one sector from a few different banks, making
sure we don't overwrite any sector of flash where the boot image lives */
int pnTestSectors[] = { 30, /* 0x000xx000 */
31, /* 0x000xx000 */
-1}; /* must end with -1 */
/* open the SPI flash */
Result = m25p16_Open();
if (Result != NO_ERR)
{
return 0;
}
/* get the codes */
pCmdBuffer.SGetCodes.pManCode = (unsigned long *)&nManCode;
pCmdBuffer.SGetCodes.pDevCode = (unsigned long *)&nDevCode;
pCmdBuffer.SGetCodes.ulFlashStartAddr = 0x0;
Result = m25p16_Control( CNTRL_GET_CODES, &pCmdBuffer );
/* if codes don't match what we expect then we should fail */
if ( (MAN_CODE != nManCode) || (DEV_CODE != nDevCode) )
{
return 0;
}
/* we also show how to determine if this part supports the Common Flash Interface (CFI) and
if so, we will attempt to get the CFI data */
if (!CheckForCFISupport_Spi())
{
/* this means there was a failure not that the device does not support CFI, so
therefore we return failure */
return 0;
}
/* for each test sector */
for ( usWr = 0x1234, j = 0; pnTestSectors[j] != -1; j++ )
{
/* make sure it's a valid sector */
if ( (pnTestSectors[j] < 0) || (pnTestSectors[j] >= NUM_SECTORS) )
return 0;
/* erase the sector */
pCmdBuffer.SEraseSect.ulFlashStartAddr = 0x0;
pCmdBuffer.SEraseSect.nSectorNum = pnTestSectors[j];
Result = m25p16_Control( CNTRL_ERASE_SECT, &pCmdBuffer );
/* if the erase passed, continue */
if(NO_ERR == Result)
{
/* write some data */
for( i = 0; i < 0x8; i+=1, usWr+= 0x1111 )
{
unsigned long ulOffset;
/* calculate offset based on sector */
ulOffset = pnTestSectors[j]*64*1024 + i; /* 64KB sectors */
/* write a value to the flash */
Result = m25p16_Write( &usWr, ulOffset, 0x1);
if(NO_ERR == Result)
{
iPassed = 1;
/* now do a read */
Result = m25p16_Read( &usRd, ulOffset, 0x1);
if(NO_ERR == Result)
{
/* compare the data */
if( (usRd & 0xff) != (usWr & 0xff) )
{
iPassed = 0;
break;
}
}
}
}
}
/* if erase failed, break out */
else
break;
/* at this point the sector test passed, erase it again */
Result = m25p16_Control( CNTRL_ERASE_SECT, &pCmdBuffer );
}
/* close driver and return result */
Result = m25p16_Close();
return iPassed;
}
/*******************************************************************
* Function: CheckForCFISupport_Spi
* Description: Checks if the devices supports the Common Flash Interface
* (CFI) and if so gets the CFI data.
*******************************************************************/
int CheckForCFISupport_Spi(void)
{
ERROR_CODE Result = NO_ERR; /* result from driver */
COMMAND_STRUCT pCmdBuffer; /* command buffer union */
bool bSupportsCFI = false; /* see if this device supports CFI */
int nFlashWidth = 0x0; /* flash width */
char pCFIData[128*2]; /* provide enough for 16-bit wide flashes */
char *pQRY = NULL; /* ptr to QRY string within CFI data */
unsigned short usPrimary = 0x0; /* primary pointer within CFI data */
unsigned short usDeviceSize = 0x0; /* device size (2^n) within CFI data */
unsigned short usMajVerASCII = 0x0; /* major version in ASCII within CFI data */
unsigned short usMinVerASCII = 0x0; /* minor version in ASCII within CFI data */
/* see if this device support CFI */
pCmdBuffer.SSupportsCFI.pbSupportsCFI = &bSupportsCFI;
Result = m25p16_Control( CNTRL_SUPPORTS_CFI, &pCmdBuffer );
if (Result == UNKNOWN_COMMAND)
{
return 1; /* not a failure, but the driver doesn't even support this command */
}
else if (Result != NO_ERR)
{
return 0;
}
/* if it supports CFI we can read the CFI data */
if ( bSupportsCFI )
{
/* first check on the device width so we know how large the CFI data will be and
how to interpret it */
pCmdBuffer.SGetFlashWidth.pnFlashWidth = &nFlashWidth;
Result = m25p16_Control( CNTRL_GET_FLASH_WIDTH, &pCmdBuffer );
if (Result == UNKNOWN_COMMAND)
{
return 1; /* not a failure, but the driver doesn't even support this command */
}
else if (Result != NO_ERR)
{
return 0;
}
/* now get the CFI data, make sure enough memory is allocated for the flash width
which is 128 bytes per 8-bit width */
pCmdBuffer.SGetCFIData.pCFIData = pCFIData;
pCmdBuffer.SGetCFIData.ulFlashStartAddr = 0x0;
Result = m25p16_Control( CNTRL_GET_CFI_DATA, &pCmdBuffer );
if (Result == UNKNOWN_COMMAND)
{
return 1; /* not a failure, but the driver doesn't even support this command */
}
else if (Result != NO_ERR)
{
return 0;
}
/* take a look at some of the CFI data, for example according to the CFI spec, the
string "QRY" should be at offset 0x10, note the byte offset always gets multiplied
by nFlashWidth, so for x16 devices the offset 0x10 becomes byte offset 0x20 */
/* if not x8 or x16 we won't check the data, we only allocated enough for up to x16 */
if ( (_FLASH_WIDTH_8 == nFlashWidth) || (_FLASH_WIDTH_16 == nFlashWidth) )
{
/* check QRY string, note x16 devices will have a NULL after each character, check the
CFI spec for details on other architectures */
pQRY = &pCFIData[0x10 * nFlashWidth];
/* check the primary (P) offset, this is used to offset into the extended area */
usPrimary = pCFIData[0x15 * nFlashWidth];
/* versions are some of the things stored in the extended area */
usMajVerASCII = pCFIData[(usPrimary+0x3) * nFlashWidth];
usMinVerASCII = pCFIData[(usPrimary+0x4) * nFlashWidth];
}
}
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -