当前位置:网站首页>Framework - SPI four modes + general device driver implementation - source code

Framework - SPI four modes + general device driver implementation - source code

2020-11-08 16:10:19 Li Zhuming


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


版权声明
本文为[Li Zhuming]所创,转载请带上原文链接,感谢