Preface
- SPI Introduce In order to collect baidu information + Personal understanding
- The rest are original ( Please correct if there is any mistake )
- Four models in one
- demo use MX25L64 Of FLASH chip
bsp_spi.c
/**
******************************************************************************
* @file bsp_spi.c
* @author lzm
* @version V1.0
* @date 2020-09-26
* @brief use Software SPI
* @attention
*
* The experiment platform :LZM
*
******************************************************************************
*/
#include "bsp_spi.h"
/*
*********************************************************************************************************
* DEFINE STATIC FUNCTION (API)
*********************************************************************************************************
*/
/* basic */
#define spiOutHi(gpio, pin) {gpio->BSRR=pin;} // The output is high level
#define spiOutLo(gpio, pin) {gpio->BRR=pin;} // The output is low level
#define spiOut(gpio, pin, lev) (lev)?(gpio->BSRR=pin):(gpio->BRR=pin)
#define spiIn(gpio, pin) GPIO_ReadInputDataBit(gpio, pin)
/* top */
/* spi For the pointer */
#define spiCsOutHi(spi) spiOutHi(spi->csGpiox, spi->csPin)
#define spiCsOutLo(spi) spiOutLo(spi->csGpiox, spi->csPin)
#define spiSckOutHi(spi) spiOutHi(spi->sckGpiox, spi->sckPin)
#define spiSckOutLo(spi) spiOutLo(spi->sckGpiox, spi->sckPin)
#define spiMosiOutHi(spi) spiOutHi(spi->mosiGpiox, spi->mosiPin)
#define spiMosiOutLo(spi) spiOutLo(spi->mosiGpiox, spi->mosiPin)
#define spiMisoIn(spi) spiIn(spi->misoGpiox, spi->misoPin)
/*
*********************************************************************************************************
* DEFINE
*********************************************************************************************************
*/
// spi Driving elements ( The driver table )
spi_t spiDriverElem[spiSPI_DRIVER_COUNT];
/**
* @brief Choose the clock signal line
* @param
* @retval
* @author lzm
*/
static uint32_t __selectClkByGpio(const uint32_t addr)
{
switch(addr)
{
case GPIOA_BASE:
return RCC_APB2Periph_GPIOA;
case GPIOB_BASE:
return RCC_APB2Periph_GPIOB;
case GPIOC_BASE:
return RCC_APB2Periph_GPIOC;
case GPIOD_BASE:
return RCC_APB2Periph_GPIOD;
case GPIOE_BASE:
return RCC_APB2Periph_GPIOE;
case GPIOF_BASE:
return RCC_APB2Periph_GPIOF;
case GPIOG_BASE:
return RCC_APB2Periph_GPIOG;
}
return NULL;
}
/**
* @brief initialization SPI Pin
* @param
* @retval
* @author lzm
*/
void spiGpioInit(eSPI_ID id)
{
GPIO_InitTypeDef GPIO_InitStructure; // Defining structure
uint32_t csGpioClk;
uint32_t sckGpioClk;
uint32_t mosiGpioClk;
uint32_t misoGpioClk;
const spi_t * spi = &spiDriverElem[id];
csGpioClk = __selectClkByGpio((uint32_t)(spi->csGpiox));
sckGpioClk = __selectClkByGpio((uint32_t)(spi->sckGpiox));
mosiGpioClk = __selectClkByGpio((uint32_t)(spi->csGpiox));
misoGpioClk = __selectClkByGpio((uint32_t)(spi->misoGpiox));
RCC_APB2PeriphClockCmd(csGpioClk | sckGpioClk | mosiGpioClk | misoGpioClk, ENABLE); // Turn on the clock
GPIO_InitStructure.GPIO_Pin = spi->csPin; // Configure ports and pins ( Specify the direction )
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(spi->csGpiox, &GPIO_InitStructure); // Initialize port ( Heading in the right direction )
GPIO_InitStructure.GPIO_Pin = spi->sckPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(spi->sckGpiox, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = spi->mosiPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(spi->mosiGpiox, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = spi->misoPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(spi->misoGpiox, &GPIO_InitStructure);
spiCsOutHi(spi);
}
/**
* @brief SPI send out
* @param
* @retval
* @author lzm
*/
void spiWriteOneByte(eSPI_ID id, unsigned char data)
{
unsigned char i;
const spi_t * spi = &spiDriverElem[id];
if(spi->CPHA){
spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL);
}
// spi->delayUsFun(spi->readDelayUsCnt);
for(i=0; i<8; i++)
{
spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL != spi->CPHA));
if(data & 0x80){
spiMosiOutHi(spi);
}
else{
spiMosiOutLo(spi);
}
data <<= 1;
spi->delayUsFun(spi->readDelayUsCnt);
spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL == spi->CPHA));
}
if(!(spi->CPHA)){
spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL);
}
}
/**
* @brief SPI Read
* @param
* @retval
* @author lzm
*/
unsigned char spiReadOneByte(eSPI_ID id)
{
unsigned char i;
unsigned char ret;
const spi_t * spi = &spiDriverElem[id];
for(i=0; i<8; i++)
{
spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL != spi->CPHA));
ret <<= 1;
if(spiMisoIn(spi))
ret |= 0x01;
else
ret &= 0xfe;
spi->delayUsFun(spi->readDelayUsCnt);
spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL == spi->CPHA));
}
spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL);
return ret;
}
/**
* @brief SPI Reading and writing
* @param
* @retval
* @author lzm
*/
unsigned char spiRWOneByte(eSPI_ID id, unsigned char data)
{
unsigned char i;
unsigned char ret;
const spi_t * spi = &spiDriverElem[id];
if(spi->CPHA){
spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL);
}
for(i=0; i<8; i++)
{
spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL != spi->CPHA));
if(data & 0x80){
spiMosiOutHi(spi);
}
else{
spiMosiOutLo(spi);
}
data <<= 1;
spi->delayUsFun(spi->readDelayUsCnt);
spiOut(spi->sckGpiox, spi->sckPin, (spi->CPOL == spi->CPHA));
ret <<= 1;
if(spiMisoIn(spi))
ret |= 0x01;
else
ret &= 0xfe;
spi->delayUsFun(spi->readDelayUsCnt);
}
if(!(spi->CPHA)){
spiOut(spi->sckGpiox, spi->sckPin, spi->CPOL);
}
}
/**
* @brief SPI The selection enables
* @param
* @retval
* @author lzm
*/
void spiCSOut(eSPI_ID id, unsigned char lev)
{
const spi_t * spi = &spiDriverElem[id];
spiOut(spi->csGpiox, spi->csPin, lev);
}
/*
*********************************************************************************************************
* DEFINE [API] FUNCTION
*********************************************************************************************************
*/
/**
* @brief register SPI equipment
* spiDriverElem[spiID].id = spiID; // Keep the subscript and ID equal , You can directly locate , The time complexity of implementation is O(1);
* @param
* @retval
* @author lzm
*/
void REGISTER_SPI_DEV(spi_t * spi)
{
if(spi->id >= espiSPI_DRIVER_COUNT)
return;
spiDriverElem[spi->id].id = spi->id;
spiDriverElem[spi->id].method = spi->method;
spiDriverElem[spi->id].CPOL = spi->CPOL;
spiDriverElem[spi->id].CPHA = spi->CPHA;
spiDriverElem[spi->id].readDelayUsCnt = spi->readDelayUsCnt;
spiDriverElem[spi->id].delayUsFun = spi->delayUsFun;
spiDriverElem[spi->id].csGpiox = spi->csGpiox;
spiDriverElem[spi->id].csPin = spi->csPin;
spiDriverElem[spi->id].sckGpiox = spi->sckGpiox;
spiDriverElem[spi->id].sckPin = spi->sckPin;
spiDriverElem[spi->id].mosiGpiox = spi->mosiGpiox;
spiDriverElem[spi->id].mosiPin = spi->mosiPin;
spiDriverElem[spi->id].misoGpiox = spi->misoGpiox;
spiDriverElem[spi->id].misoPin = spi->misoPin;
}
bsp_spi.h
/**
******************************************************************************
* @file bsp_spi.h
* @author lzm
* @version V1.0
* @date 2020-09-26
* @brief use Hardware SPI
* @attention
*
* The experiment platform :LZM
*
******************************************************************************
*/
#ifndef _BSP_SPI_H_
#define _BSP_SPI_H_
#include "LssAppConfig.h"
/*
*********************************************************************************************************
* CONFIG API
*********************************************************************************************************
*/
// [ notes ][spi] Real time modification
// spi Number of equipment
#define spiSPI_DRIVER_COUNT 1
/* spi id. */
typedef enum
{
espiFLASH_A = 0,
espiSPI_DRIVER_COUNT,
}eSPI_ID;
/* spi mode. */
typedef enum
{
espiHARDWARE = 0,
espiSOFTWARE,
}eSPI_METHOD;
/*
*********************************************************************************************************
* BASIC
*********************************************************************************************************
*/
/* spi */
struct SPI_T{
/* id */
eSPI_ID id;
/* software spi */
/* method */
eSPI_METHOD method;
/* CPOL CPHA : 00 01 10 11*/
/* cpol */
unsigned char CPOL;
/* cpha */
unsigned char CPHA;
/* delay */
/* cnt */
unsigned int readDelayUsCnt;
/* function */
void ( *delayUsFun )(int cnt);
/* hardware spi */
SPI_TypeDef* SPIx;
/* pin */
GPIO_TypeDef * csGpiox;
uint16_t csPin;
GPIO_TypeDef * sckGpiox;
uint16_t sckPin;
GPIO_TypeDef * mosiGpiox;
uint16_t mosiPin;
GPIO_TypeDef * misoGpiox;
uint16_t misoPin;
};
typedef struct SPI_T spi_t;
/*
*********************************************************************************************************
* BROADCAST
*********************************************************************************************************
*/
/* device table */
extern spi_t spiDriverElem[spiSPI_DRIVER_COUNT];
/* function */
void spiGpioInit(eSPI_ID id);
void spiWriteOneByte(eSPI_ID id, unsigned char data);
unsigned char spiReadOneByte(eSPI_ID id);
void spiCSOut(eSPI_ID id, unsigned char lev);
void REGISTER_SPI_DEV(spi_t * spi);
#endif
bsp_flash.c
/**
******************************************************************************
* @file bsp_flash.c
* @author lzm
* @version V1.0
* @date 2020-10-29
* @brief
* @attention
*
* The experiment platform :LZM
*
******************************************************************************
*/
#include "bsp_flash.h"
#include "lss_IO.h"
#include "boardInfo.h"
/*
*********************************************************************************************************
* DEFINE
*********************************************************************************************************
*/
// flash Device elements ( Equipment list )
flash_t flashDeviceElem[flashFLASH_DEVICE_COUNT];
/**
* @brief Write a byte to the plug Flash
* @param id : flash equipment id
* @param data : Data to be written
* @retval
* @author lzm
*/
void flashWriteByte(eFLASH_ID id, unsigned char data)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiWriteOneByte(spiid, data);
}
/**
* @brief From the outside flash Reads a byte in
* @param id : flash equipment id
* @param data : Data to be written
* @retval
* @author lzm
*/
unsigned char flashReadByte(eFLASH_ID id)
{
unsigned char ch;
eSPI_ID spiid = flashDeviceElem[id].spiID;
ch = spiReadOneByte(spiid);
return ch;
}
/*
*********************************************************************************************************
* [ Business ]
*********************************************************************************************************
*/
/**
* @brief Read flash Status register
* @brief BIT7 6 5 4 3 2 1 0
* @brief SPR RV TB BP2 BP1 BP0 WEL BUSY
* @brief SPR: Default 0, Status register protection bit , coordination WP Use
* @brief TB,BP2,BP1,BP0:FLASH Zone write protection settings
* @brief WEL: Write enable lock
* @brief BUSY: Busy flag bit (1, busy ;0, Free )
* @brief Default :0x00
* @param id : flash equipment id
* @author lzm
*/
unsigned char mx25lxxReadSR(eFLASH_ID id)
{
unsigned char ch;
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxREAD_STATUS_REG);
ch = spiReadOneByte(spiid);
spiCSOut(spiid, 1);
return ch;
}
/**
* @brief Write flash Status register
* @brief Only SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2) Can write !!!
* @param id : flash equipment id
* @author lzm
*/
void mx25lxxWriteSR(eFLASH_ID id, unsigned char data)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxWRITE_STATUS_REG);
spiWriteOneByte(spiid, data);
spiCSOut(spiid, 1);
}
/**
* @brief Waiting for leisure
* @param id : flash equipment id
* @author lzm
*/
void mx25lxxWaitBusy(eFLASH_ID id)
{
while((mx25lxxReadSR(id)&0x01)==0x01); // wait for BUSY Bit empty
}
/**
* @brief Write enable
* @param id : flash equipment id
* @author lzm
*/
void mx25lxxWriteEnable(eFLASH_ID id)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxWRITE_ENABLE);
spiCSOut(spiid, 1);
}
/**
* @brief Write No
* @param id : flash equipment id
* @author lzm
*/
void mx25lxxWriteDisable(eFLASH_ID id)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxWRITE_DISABLE);
spiCSOut(spiid, 1);
}
/**
* @brief Read chip ID
* @param id : flash equipment id
* @retval 0Xxx13, Indicates that the chip model is W25Q80
* @retval 0Xxx14, Indicates that the chip model is W25Q16
* @retval 0Xxx15, Indicates that the chip model is W25Q32
* @retval 0Xxx16, Indicates that the chip model is W25Q64
* @retval 0Xxx17, Indicates that the chip model is W25Q128
* @author lzm
*/
unsigned int mx25lxxReadID(eFLASH_ID id)
{
unsigned int ret;
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, 0x90);
spiWriteOneByte(spiid, 0x00);
spiWriteOneByte(spiid, 0x00);
spiWriteOneByte(spiid, 0x00);
ret |= spiReadOneByte(spiid)<<8;
ret |= spiReadOneByte(spiid);
spiCSOut(spiid, 1);
return ret;
}
/**
* @brief Start reading data of specified length at the specified address
* @param id : flash equipment id
* @param readAddr : Address to start reading (24bit)
* @param pReadBuff : Data storage area
* @param size : Number of bytes
* @author lzm
*/
void mx25lxxReadBytes(eFLASH_ID id, uint32_t readAddr, uint8_t * pReadBuff, uint16_t size)
{
uint16_t i;
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxREAD_DATA);
spiWriteOneByte(spiid, (u8)((readAddr)>>16));
spiWriteOneByte(spiid, (u8)((readAddr)>>8));
spiWriteOneByte(spiid, (u8)readAddr);
for(i=0;i<size;i++)
{
pReadBuff[i]=spiReadOneByte(spiid); // Cycle reading
}
spiCSOut(spiid, 1);
}
/**
* @brief Write maximum at the specified address 256 Bytes of data
* @param id : flash equipment id
* @param writeAddr : Address to start writing (24bit)
* @param pReadBuff : Data storage area
* @param size : Number of bytes
* @author lzm
*/
void mx25lxxWriteBytes(eFLASH_ID id, uint32_t writeAddr, uint8_t * pWriteBuff, uint16_t size)
{
uint16_t i;
eSPI_ID spiid = flashDeviceElem[id].spiID;
mx25lxxWriteEnable(id);
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxPAGE_PROGRAM);
spiWriteOneByte(spiid, (u8)((writeAddr)>>16));
spiWriteOneByte(spiid, (u8)((writeAddr)>>8));
spiWriteOneByte(spiid, (u8)writeAddr);
for(i=0;i<size;i++)
{
spiWriteOneByte(spiid,pWriteBuff[i]); // Cycle reading
}
spiCSOut(spiid, 1);
}
/**
* @brief Write without test SPI FLASH
* @brief You must make sure that the data in the address range you write is 0XFF, Otherwise, in Africa 0XFF Data written at will fail !
* @brief It has the function of automatic page change
* @brief Write data at the specified length , But make sure the address doesn't cross the line !
* @param id : flash equipment id
* @param readAddr : Address to start reading (24bit)
* @param pReadBuff : Data storage area
* @param size : Number of bytes
* @author lzm
*/
void mx25lxxWriteNoCheck(eFLASH_ID id, uint32_t writeAddr, uint8_t * pWriteBuff, uint16_t size)
{
uint16_t residueSize;
residueSize = 0xFF - writeAddr%0XFF;
if(size<=residueSize) residueSize=size;// No more than 256 Bytes
while(1)
{
mx25lxxWriteBytes(id, writeAddr, pWriteBuff, residueSize);
if(size==residueSize)
break;// The writing is over
else //size>pageremain
{
pWriteBuff+=residueSize;
writeAddr+=residueSize;
size-=residueSize; // Subtract the number of bytes that have been written
if(size>256)residueSize=256; // You can write... At one time 256 Bytes
else residueSize=size; // Not enough 256 The bytes
}
}
}
/**
* @brief Erase a sector ( Minimum time to erase a sector :150ms)
* @param id : flash equipment id
* @param eraseAddr : Sector address Set according to the actual capacity
* @author lzm
*/
void mx25lxxEraseSector(eFLASH_ID id, uint32_t eraseAddr)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
eraseAddr*=4096;
mx25lxxWriteEnable(id); //SET WEL
mx25lxxWaitBusy(id);
spiCSOut(spiid, 0); // Enabling devices
spiWriteOneByte(spiid, mx25lxxSECTOR_ERASE); // Send sector erase command
spiWriteOneByte(spiid, (u8)((eraseAddr)>>16)); // send out 24bit Address
spiWriteOneByte(spiid, (u8)((eraseAddr)>>8));
spiWriteOneByte(spiid, (u8)eraseAddr);
spiCSOut(spiid, 1); // Cancel the selection
mx25lxxWaitBusy(id); // Wait for erasure to complete
}
/**
* @brief Enter power down mode
* @param id : flash equipment id
* @author lzm
*/
void mx25lxxPowerDown(eFLASH_ID id)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0); // Enabling devices
spiWriteOneByte(spiid, mx25lxxPOWER_DOWN); // Send a power down command
spiCSOut(spiid, 1); // Cancel the selection
}
/**
* @brief Wake up the
* @param id : flash equipment id
* @author lzm
*/
void mx25lxxWakeUp(eFLASH_ID id)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0); // Enabling devices
spiWriteOneByte(spiid, mx25lxxRELEASE_POWER_DOWN); // Send a power down command
spiCSOut(spiid, 1); // Cancel the selection
}
/**
* @brief Erasing is actually writing 1
* @param id : flash equipment id
* @param eraseAddr : Address to start writing (24bit)
* @param pEraseBuff : Data storage area
* @param size : Number of bytes
* @author lzm
*/
uint8_t mx25lxxBUFFER[4096];
void mx25lxxEraseBytes(eFLASH_ID id, uint32_t eraseAddr, uint8_t * pEraseBuff, uint16_t size)
{
uint16_t i;
uint32_t secAddr; // Sector address
uint16_t secOff; // Offset within a sector
uint16_t secResidueSize; // The size of the remaining space in the sector
u8 * mx25lxxBUF;
mx25lxxBUF = mx25lxxBUFFER;
secAddr=eraseAddr/4096;// Sector address
secOff=eraseAddr%4096;// Offset within a sector
secResidueSize=4096-secOff;// The size of the remaining space in the sector
if(size<=secResidueSize)secResidueSize=size;// No more than 4096 Bytes
while(1)
{
mx25lxxReadBytes(id, secAddr*4096, mx25lxxBUFFER, 4096);// Read the entire sector
for(i=0;i<secResidueSize;i++)// Check the data
{
if(mx25lxxBUF[secOff+i]!=0XFF)break;// Need to erase
}
if(i<secResidueSize)// Need to erase
{
mx25lxxEraseSector(id, secAddr); // Erase this sector
for(i=0;i<secResidueSize;i++) // Copy
{
mx25lxxBUF[i+secOff]=pEraseBuff[i];
}
mx25lxxWriteNoCheck(id,secAddr*4096,mx25lxxBUF,4096);// Write the entire sector
}
else
mx25lxxWriteNoCheck(id,eraseAddr,pEraseBuff,secResidueSize);// Write what has been erased , Write directly to the rest of the sector .
if(size==secResidueSize)
break;// The writing is over
else// Writing is not finished
{
secAddr++;// Sector address increase 1
secOff=0;// The offset is 0
pEraseBuff+=secResidueSize; // Pointer offset
eraseAddr+=secResidueSize; // Write address offset
size-=secResidueSize; // Bytes decrement
if(size>4096)
secResidueSize=4096;// I can't finish writing the next sector
else
secResidueSize=size; // The next sector can be written
}
};
}
/**
* @brief Erase the whole chip ( Longer time )
* @param id : flash equipment id
* @author lzm
*/
void ITC_MX25LXX_EraseChip(eFLASH_ID id)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
mx25lxxWriteEnable(id); //SET WEL
mx25lxxWaitBusy(id);
spiCSOut(spiid, 0); // Enabling devices
spiWriteOneByte(spiid, mx25lxxCHIP_ERASE); // Send chip erase command
spiCSOut(spiid, 1); // Cancel the selection
mx25lxxWaitBusy(id); // Wait for the chip erase to finish
}
/**
* @brief All the plug-ins FLASH Device initialization
* @param
* @retval
* @author lzm
*/
void flashInit(void)
{
uint8_t flashID;
spi_t spi;
unsigned int devID;
// To register first SPI drive
spi.id = espiFLASH_A;
spi.method = espiSOFTWARE;
spi.CPOL = 1;
spi.CPHA = 1;
spi.readDelayUsCnt = 1;
spi.delayUsFun = dwtDelayUs;
spi.csGpiox = mx25lxxFLASH_SPI_CS_PORT;
spi.csPin = mx25lxxFLASH_SPI_CS_PIN;
spi.sckGpiox = mx25lxxFLASH_SPI_SCK_PORT;
spi.sckPin = mx25lxxFLASH_SPI_SCK_PIN;
spi.mosiGpiox = mx25lxxFLASH_SPI_MOSI_PORT;
spi.mosiPin = mx25lxxFLASH_SPI_MOSI_PIN;
spi.misoGpiox = mx25lxxFLASH_SPI_MISO_PORT;
spi.misoPin = mx25lxxFLASH_SPI_MISO_PIN;
REGISTER_SPI_DEV(&spi);
// register FLASH Device and bind i2c
REGISTER_FLASH_DEV(eMX25lXX_1, espiFLASH_A);
for (flashID = 0; flashID < flashFLASH_DEVICE_COUNT; flashID++)
{
// initialization I2C
spiGpioInit( (eSPI_ID)(espiFLASH_A + flashID) );
devID = mx25lxxReadID((eFLASH_ID)flashID);
if(devID == 0XFFFF)
{
printf("\r\n[flashInit] [faild] and error devID is [%d]", devID);
}
else
{
printf("\r\n[flashInit] [successful] devID is [%d]", devID);
}
}
}
bsp_flash.h
/**
******************************************************************************
* @file flash.h
* @author lzm
* @version V1.0
* @date 2020-10-29
* @brief
* @attention
*
* The experiment platform :ITC
*
******************************************************************************
*/
#ifndef _BSP_FLASH_H_
#define _BSP_FLASH_H_
#include "LssAppConfig.h"
#include "bsp_spi.h"
/*
*********************************************************************************************************
* MX25L64 Instruction list [ Business ]
*********************************************************************************************************
*/
#define mx25lxxWRITE_ENABLE 0x06
#define mx25lxxWRITE_DISABLE 0x04
#define mx25lxxREAD_STATUS_REG 0x05
#define mx25lxxWRITE_STATUS_REG 0x01
#define mx25lxxREAD_DATA 0x03
#define mx25lxxFAST_READ_DATA 0x0B
#define mx25lxxFAST_READ_DUAL 0x3B
#define mx25lxxPAGE_PROGRAM 0x02
#define mx25lxxBLOCK_ERASE 0xD8
#define mx25lxxSECTOR_ERASE 0x20
#define mx25lxxCHIP_ERASE 0xC7
#define mx25lxxPOWER_DOWN 0xB9
#define mx25lxxRELEASE_POWER_DOWN 0xAB
#define mx25lxxDEVICE_ID 0xAB
#define mx25lxxMANUFACT_DEVICE_ID 0x90
#define mx25lxxJEDCE_DEVICE_ID 0x9F
/*
*********************************************************************************************************
* CONFIG API
*********************************************************************************************************
*/
/* [ notes ][flash] Real time modification */
// flash Number of equipment
#define flashFLASH_DEVICE_COUNT 1
/* flash id. */
typedef enum
{
eMX25lXX_1 = 0, //
eflashFLASH_DEVICE_COUNT,
}eFLASH_ID;
/*
*********************************************************************************************************
* BASIC
*********************************************************************************************************
*/
/* flash */
struct FLASH_T{
/* id */
eFLASH_ID ID;
/* spi id */
eSPI_ID spiID;
};
typedef struct FLASH_T flash_t;
/*
*********************************************************************************************************
* DEFINE [API] FUNCTION
*********************************************************************************************************
*/
/**
* @brief register IIC equipment
* @param
* @retval
* @author lzm
*/
#define REGISTER_FLASH_DEV(flashid, spicid) \
{ \
flashDeviceElem[flashid].ID = flashid; \
flashDeviceElem[flashid].spiID = spicid; \
}
/*
*********************************************************************************************************
* BROADCAST
*********************************************************************************************************
*/
/* device table */
extern flash_t flashDeviceElem[flashFLASH_DEVICE_COUNT];
/* function */
unsigned char mx25lxxReadSR(eFLASH_ID id);
void mx25lxxWriteSR(eFLASH_ID id, unsigned char data);
void mx25lxxWaitBusy(eFLASH_ID id);
void mx25lxxWriteEnable(eFLASH_ID id);
void mx25lxxWriteDisable(eFLASH_ID id);
unsigned int mx25lxxReadID(eFLASH_ID id);
void mx25lxxReadBytes(eFLASH_ID id, uint32_t readAddr, uint8_t * pReadBuff, uint16_t size);
void mx25lxxWriteBytes(eFLASH_ID id, uint32_t writeAddr, uint8_t * pWriteBuff, uint16_t size);
void mx25lxxWriteNoCheck(eFLASH_ID id, uint32_t writeAddr, uint8_t * pWriteBuff, uint16_t size);
void mx25lxxEraseBytes(eFLASH_ID id, uint32_t eraseAddr, uint8_t * pEraseBuff, uint16_t size);
void mx25lxxEraseSector(eFLASH_ID id, uint32_t eraseAddr);
void mx25lxxPowerDown(eFLASH_ID id);
void flashInit(void);
#endif