SpiFlash同步/异步读写单片机裸机实例

 单片机裸机开发中会经常遇到外设速度过慢,长时间读忙等待,但CPU又不能长时间阻塞的问题。
这种问题可以通过实现一个状态机来异步处理。

异步状态机代码结构示例:

enum
{
	eIDLE = 0,
	eSTART,
	eWAIT,
	eSUCCESS
};

static uint8_t stage = 0;
//启动异步处理	
void DoSomethingRequest()
{
	if(stage != eIDLE)
	{
		printf("AsyncMachine is busy!!!,return\n");
		return;
	}
	SomethingReq = TRUE;
}
//异步处理任务
void AsyncMachine()
{
	
	switch(stage)
	{
		case eIDLE:
			if(SomethingReq)
			{
				stage = eSTART;
				printf("A task will be start\n");
			}
			break;
		case eSTART: 
			do_something();
			stage = eWAIT;
			printf("do something\n");
			break;
		case eWAIT: 
			if(something_state() == OK)
			{
				stage = eSUCCESS;
			}
			printf("Wait...\n");
			break;
		case eSUCCESS: 
			stage = eIDLE;
			printf("task exec success\n");
			break;
	}
}

通过把阻塞的任务单独分离出来,交给一个状态机子任务来处理。则应用程序只需要调用一个处理请求而无需原地死等,状态机处理完成后,可以异步回调来通知应用程序任务已完成。

下面附上SPI FLASH 同步/异步读写实例。

//SPI状态机状态
typedef enum 
{
	eFLASH_STATE_IDLE = 0,
	eFLASH_STATE_WRITE = 1, 
	eFLASH_STATE_READ = 2,
	eFLASH_STATE_BUSY = 3,
	eFLASH_STATE_ERASE_CHIP = 4,
	eFLASH_STATE_ERASE = 5,
}FlashState_e;
//SPI设备结构体
typedef struct SpiDevice_s {
	SPI_TypeDef *spiHandle;//SPI物理属性
	uint8_t *pTxBuffer;//异步发送缓存
	uint32_t uTxDstAddr;//异步发送目地地址
	uint16_t wTxLen;//异步发送长度
	uint16_t wTxOffset; //异步当前缓存已发送偏移 
	uint8_t *pRxBuffer;
	uint32_t uRxSrcAddr;
	uint16_t wRxLen;
	uint16_t wRxOffset; 
	void (*pWriteAsyncNotifyCallback)(); //异步写完成回调通知
	void (*pEraseChipAsyncNotifyCallback)();//异不擦除回调通知
	struct {
		FlashState_e eStage;//当前状态机状态
		//BOOL bTxBusy:1;   //发送忙
		BOOL bTxReq:1;     //发送请求
		BOOL bTxCompleted:1;//发送完成
		//BOOL bRxBusy:1;  //读忙
		BOOL bRxReq:1;    //读请求
		BOOL bEraseChipReq:1;//擦整片请求
		BOOL bEraseSectorReq:1;//擦扇区请求
		BOOL bEraseSuccess:1; //擦成功
	}tState;
	void (*Init)(void);
	uint8_t (*EraseChip)(void);//同步擦
	void (*Read)(uint8_t* pBuffer,uint32_t uReadAddr,uint16_t wNumByteToRead);//同步读
	uint32_t (*WriteByte)(uint8_t Byte, uint32_t uWriteAddr);//同步写字节
	uint32_t (*Write)(uint8_t* pBuffer,uint32_t uWriteAddr, uint16_t wNumByteToWrite);//同步写
	BOOL (*WriteAsync)(uint8_t* pBuffer,uint32_t uWriteAddr, uint16_t wNumByteToWrite);//异步写
	BOOL (*EraseChipAsync)(void);//异步整片擦
	BOOL (*EraseAsync)(uint32_t uAddr, uint16_t wlen);//奶步擦
	void (*WriteAsyncNotifyCallbackRegister)(void* pfn);//异步写完成回调注册
	void (*EraseChipAsyncNotifyCallbackRegister)(void *pfn);//异步擦完成回调注册
}SpiDevice_t;

实例化

//SPI设备初始化
/*
*异步方式用于非阻塞SPI操作
*SPI_FlashAsyncProcTask任务负责具体读写请求的异步处理
*/
SpiDevice_t g_tSpiDevice = 
{
	SPI2,
	g_aTxBuffer,
	0,0,0,
	g_aRxBuffer,
	0,0,0,
	0,0,
	{0,0},
	Spi_Init,
	SPI_Flash_Erase_Chip,	//同步整片擦
	SPI_Flash_Read,				//同步读
	SPI_Flash_WriteByte,	//同步写字节
	SPI_Flash_Write,			//同步写
	SPI_FlashWriteAsync,	//异步写
	SPI_FlashEraseChipAsync,	//异步整片擦除
	SPI_FlashEraseAsync,
	SPI_WriteAsyncNotifyCallbackRegister,//写状态异步通知回调
	SPI_EraseChipAsyncNotifyCallbackRegister,//擦除状态异步通知回调
};

.h源文件


#ifndef _SPI_FLASH_H
#define _SPI_FLASH_H

#include "stm32f0xx.h"
#include "common.h"

#ifdef __cplusplus
 extern "C" {
#endif
	 	 
#define DUMMY            0xff  //虚设数据
#define WR_EN            0x06  //写使能
#define RE_STAREG        0x05  //读状态寄存器1
#define WR_STAREG        0x01  //写状态寄存器1
#define DEVICE_ID        0x90  //获取设备ID
#define CHIP_ERASE       0x60  //擦除芯片
#define READ_DATA        0x03  //读数据
#define PAGE_PRG         0x02  //页编程
#define SECTOR_ERASE  	 0x20  //4K分区擦除
#define BLOCK_ERASE_32K  0x52  //32K块擦除
#define BLOCK_ERASE_64K  0xD8  //64K块擦除  

#define SECTOR_SIZE      4096
#define PAGE_SIZE        256 	 
#define FLASH_RX_BUFFER_SIZE 256
#define FLASH_TX_BUFFER_SIZE 256
//#define SPI_DMA_ENABLE	 
//SPI设备状态
typedef enum 
{
	eFLASH_STATE_IDLE = 0,
	eFLASH_STATE_WRITE = 1, 
	eFLASH_STATE_READ = 2,
	eFLASH_STATE_BUSY = 3,
	eFLASH_STATE_ERASE_CHIP = 4,
	eFLASH_STATE_ERASE = 5,
}FlashState_e;
//SPI设备初始化
/*
*异步方式用于非阻塞SPI操作
*SPI_FlashAsyncProcTask任务负责具体读写请求的异步处理
*/
typedef struct SpiDevice_s {
	SPI_TypeDef *spiHandle;
	uint8_t *pTxBuffer;
	uint32_t uTxDstAddr;
	uint16_t wTxLen;
	uint16_t wTxOffset; //当前发送偏移 
	uint8_t *pRxBuffer;
	uint32_t uRxSrcAddr;
	uint16_t wRxLen;
	uint16_t wRxOffset; //当前接收偏移 
	void (*pWriteAsyncNotifyCallback)();
	void (*pEraseChipAsyncNotifyCallback)();
	struct {
		FlashState_e eStage;
		//BOOL bTxBusy:1;
		BOOL bTxReq:1;
		BOOL bTxCompleted:1;
		//BOOL bRxBusy:1;
		BOOL bRxReq:1;
		BOOL bEraseChipReq:1;
		BOOL bEraseSectorReq:1;
		BOOL bEraseSuccess:1;
	}tState;
	void (*Init)(void);
	uint8_t (*EraseChip)(void);//同步整片擦
	void (*Read)(uint8_t* pBuffer,uint32_t uReadAddr,uint16_t wNumByteToRead);//同步整片擦
	uint32_t (*WriteByte)(uint8_t Byte, uint32_t uWriteAddr);//同步写字节
	uint32_t (*Write)(uint8_t* pBuffer,uint32_t uWriteAddr, uint16_t wNumByteToWrite);//同步写
	BOOL (*WriteAsync)(uint8_t* pBuffer,uint32_t uWriteAddr, uint16_t wNumByteToWrite);//异步写
	BOOL (*EraseChipAsync)(void);//异步整片擦除
	BOOL (*EraseAsync)(uint32_t uAddr, uint16_t wlen);
	void (*WriteAsyncNotifyCallbackRegister)(void* pfn);//写状态异步通知回调
	void (*EraseChipAsyncNotifyCallbackRegister)(void *pfn);//擦除状态异步通知回调
}SpiDevice_t;

//typedef enum {FALSE =0, TRUE = 1}BOOL_L;
	
void Spi_Init(void);
unsigned char SPI_Flash_Erase_Chip(void);
void SPI_Flash_Read(unsigned char* pBuffer,unsigned int ReadAddr,unsigned short int NumByteToRead);  
uint32_t SPI_Flash_WriteByte(unsigned char Byte,unsigned int WriteAddr);
uint32_t SPI_Flash_Write(unsigned char* pBuffer,unsigned int WriteAddr,unsigned short int NumByteToWrite);
	 
	 
extern SpiDevice_t g_tSpiDevice;
#ifdef __cplusplus
}
#endif	 

#endif /*_SPI_FLASH_H*/

 .c 源文件

/************************************************
			spi flash操作模块
************************************************/
#include <string.h>
#include <stdio.h>
#include "stm32f0xx.h"
#include "stm32f0xx_conf.h"
#include "stm32f0xx_spi.h"
#include "stm32f0xx_rcc.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_dma.h"
#include "stm32f0xx_iwdg.h"
#include "stm32f0xx_misc.h"
#include "spi_flash.h"
#include "timer.h"
#include "uart.h"
#include "debug.h"
#include "task.h"

void Spi_Init(void);
void SPI_Flash_Read(unsigned char* pBuffer,unsigned int ReadAddr,unsigned short int NumByteToRead);  
uint32_t SPI_Flash_WriteByte(unsigned char Byte,unsigned int WriteAddr);
uint32_t SPI_Flash_Write(unsigned char* pBuffer,unsigned int WriteAddr,unsigned short int NumByteToWrite);
void SPI_FlashAsyncProcTask(void);
BOOL SPI_FlashEraseChipAsync(void);
BOOL SPI_FlashEraseAsync(uint32_t uAddr, uint16_t wlen);
BOOL SPI_FlashWriteAsync(uint8_t* pBuffer,uint32_t uWriteAddr, uint16_t wNumByteToWrite);
void SPI_WriteAsyncNotifyCallbackRegister(void *pfn);
void SPI_EraseChipAsyncNotifyCallbackRegister(void *pfn);
/*
*异步读写BUFFER
*/
static uint8_t g_aTxBuffer[FLASH_TX_BUFFER_SIZE];
static uint8_t g_aRxBuffer[FLASH_RX_BUFFER_SIZE];

//SPI设备初始化
/*
*异步方式用于非阻塞SPI操作
*SPI_FlashAsyncProcTask任务负责具体读写请求的异步处理
*/
SpiDevice_t g_tSpiDevice = 
{
	SPI2,
	g_aTxBuffer,
	0,0,0,
	g_aRxBuffer,
	0,0,0,
	0,0,
	{0,0},
	Spi_Init,
	SPI_Flash_Erase_Chip,	//同步整片擦
	SPI_Flash_Read,				//同步读
	SPI_Flash_WriteByte,	//同步写字节
	SPI_Flash_Write,			//同步写
	SPI_FlashWriteAsync,	//异步写
	SPI_FlashEraseChipAsync,	//异步整片擦除
	SPI_FlashEraseAsync,
	SPI_WriteAsyncNotifyCallbackRegister,//写状态异步通知回调
	SPI_EraseChipAsyncNotifyCallbackRegister,//擦除状态异步通知回调
};

#ifdef SPI_DMA_ENABLE
void Spi_DMAInit(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

	DMA_DeInit(DMA1_Channel4);
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&g_tSpiDevice.spiHandle->DR;
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)g_tSpiDevice.pRxBuffer;
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	DMA_InitStructure.DMA_BufferSize = SPI_TX_BUFFER_SIZE;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel4, &DMA_InitStructure);


	DMA_DeInit(DMA1_Channel5);
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&g_tSpiDevice.spiHandle->DR;
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)g_tSpiDevice.pTxBuffer;
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
	DMA_InitStructure.DMA_BufferSize = 256;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel5, &DMA_InitStructure);

	DMA_Cmd (DMA1_Channel4,DISABLE/*ENABLE*/);
	DMA_Cmd (DMA1_Channel5,DISABLE/*ENABLE*/);

	DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
 
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_5_6_7_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}
#endif
/*****************************************************************************************                    									       	
函数名称:Spi_Init
函数描述:
输入参数:                                  
输出参数:                                                        
函数返回: 
******************************************************************************************/
void Spi_Init(void)
{
	SPI_InitTypeDef  SPI_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
#ifdef SPI_DMA_ENABLE	
	//Spi_DMAInit();
#endif			
	/* Enable SPI2 clocks */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
			
	/* Configure SPI2 pins:MISO and MOSI */
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_14 |GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType 	= GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_0);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_0);  
	/* Configure SPI2 pins: SCK */
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_13 ;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType 	= GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_0); 
	//SPI2 NSS
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType 	= GPIO_OType_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB, GPIO_Pin_12);  
	/* SPI2 configuration */
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;      //双线全双工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                           //spi主机
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                       //SPI 8bit 位宽
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                             //空闲时置高
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                            //第二个时钟沿采集数据
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                               //NSS 软件控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;      //时钟预分频
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                      //高位先传
	SPI_InitStructure.SPI_CRCPolynomial = 7;                                //CRC
	SPI_Init(SPI2, &SPI_InitStructure);
	//1: RXNE event is generated if the FIFO level is greater than or equal to 1/4 (8-bit)
	SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_QF);
	/* Enable SPI1  */
	SPI_Cmd(SPI2, ENABLE);  


	SysTask_Add((TASK_FUNC)SPI_FlashAsyncProcTask, 0);
}


/*片选使能*/
void SPI_CS_LOW(void)
{
	GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}

/*片选去使能*/
void SPI_CS_HIGH(void)
{
	GPIO_SetBits(GPIOB, GPIO_Pin_12);
}

/*FLASH读写函数*/
unsigned char SPI_Flash_ReadWrite_Byte(unsigned char byte)
{
	  /*unsigned char cnt=0;
	
    while((SPI2->SR&1<<1)==0)        
    {
        cnt++;
        if(cnt>200)
				{
					return FALSE;
				}
    }                          
    SPI_SendData8(SPI2,byte);                   
    cnt=0;
    while((SPI2->SR&1<<0)==0)  
    {
       cnt++;
       if(cnt>200)
			 {
				 return FALSE;
			 }
    }                                                             
    return SPI_ReceiveData8(SPI2);*/
 /* Loop while DR register in not emplty */
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);

  /* Send byte through the SPI1 peripheral */
	SPI_SendData8(SPI2,byte);

  /* Wait to receive a byte */
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

  /* Return the byte read from the SPI bus */
  return SPI_ReceiveData8(SPI2);
		
}

unsigned short int SPI_Flash_Read_DEVICEID(void)
{
	unsigned short int ID=0;
	
	SPI_CS_LOW();
	SPI_Flash_ReadWrite_Byte(DEVICE_ID);
	SPI_Flash_ReadWrite_Byte(DUMMY);
	SPI_Flash_ReadWrite_Byte(DUMMY);
	SPI_Flash_ReadWrite_Byte(0x00);
	
	ID |= (SPI_Flash_ReadWrite_Byte(DUMMY)<<8);
	ID |= SPI_Flash_ReadWrite_Byte(DUMMY);
	SPI_CS_HIGH();
	
	return ID;
}

/*写使能*/
void SPI_FLASH_Write_Enable(void)
{
	SPI_CS_LOW();
	SPI_Flash_ReadWrite_Byte(WR_EN);
	SPI_CS_HIGH();
}

/**********************
读取flash状态
BIT7  6   5   4   3   2   1   0
SPR   RV  TB BP2 BP1 BP0 WEL BUSY
BUSY:   //忙标志  1:忙 0:空闲
WEL:    //写使能  1:使能 0:不使能
BP0~3:  //块保护bit
TB:     //top/bottom保护位
SRP0:   //状态寄存在保护位
***********************/
unsigned char SPI_Flash_Read_SR(void)
{
	unsigned char reg;
	SPI_CS_LOW();
	SPI_Flash_ReadWrite_Byte(RE_STAREG);
	reg = SPI_Flash_ReadWrite_Byte(DUMMY);
	SPI_CS_HIGH();
	
	return reg;
}

/*等待flash空闲*/
void SPI_Flash_Wait_Busy(void) 
{  
     while ((SPI_Flash_Read_SR()&0x01)==0x01)
		 {	
		   IWDG->KR = (uint16_t)0xAAAA;//等待时喂狗
		 }
}

/*****************
擦除一个扇区
0~511
******************/
unsigned char SPI_Flash_Erase_Sector(unsigned int Dst_Addr)  
{  
	  unsigned char cnt=0; 
	
    SPI_FLASH_Write_Enable();                  //SET WEL           
    while((SPI_Flash_Read_SR()&0x2)!=0x2) 
		{
			cnt ++;
			if(cnt >200)
				return FALSE;
		}   
    SPI_CS_LOW();                            
    SPI_Flash_ReadWrite_Byte(SECTOR_ERASE);      
    SPI_Flash_ReadWrite_Byte((unsigned char)((Dst_Addr)>>16));   
    SPI_Flash_ReadWrite_Byte((unsigned char)((Dst_Addr)>>8));  
    SPI_Flash_ReadWrite_Byte((unsigned char)Dst_Addr); 
    SPI_CS_HIGH();                                         
    SPI_Flash_Wait_Busy();  
		return TRUE;
} 

/*64K Flash空间擦除*/
unsigned char SPI_Flash_Erase_64k(unsigned int Dst_Addr)  
{  
	  unsigned char cnt=0;
	
    SPI_FLASH_Write_Enable();                  //SET WEL           
    while((SPI_Flash_Read_SR()&0x2)!=0x2) 
		{
			cnt ++;
			if(cnt >200)
				return FALSE;
		} 
    SPI_CS_LOW();                            
    SPI_Flash_ReadWrite_Byte(BLOCK_ERASE_64K);      
    SPI_Flash_ReadWrite_Byte((unsigned char)((Dst_Addr)>>16));   
    SPI_Flash_ReadWrite_Byte((unsigned char)((Dst_Addr)>>8));  
    SPI_Flash_ReadWrite_Byte((unsigned char)Dst_Addr); 
    SPI_CS_HIGH();                                         
    SPI_Flash_Wait_Busy(); 
		return TRUE;
} 

/*擦除芯片*/
unsigned char SPI_Flash_Erase_Chip(void)  
{   
		unsigned char cnt=0;     
		
    SPI_FLASH_Write_Enable();                  //SET WEL
    while((SPI_Flash_Read_SR()&0x2)!=0x2) 
		{
			cnt ++;
			if(cnt >200)
				return FALSE;
		}
    SPI_CS_LOW();                             
    SPI_Flash_ReadWrite_Byte(CHIP_ERASE);        
    SPI_CS_HIGH();                                         
    SPI_Flash_Wait_Busy();  
		return TRUE;
}  

/*指定地址读取指定长度数据*/
void SPI_Flash_Read(unsigned char* pBuffer,unsigned int ReadAddr,unsigned short int NumByteToRead)  
{
    unsigned short int index; 
	
    SPI_CS_LOW();                            
    SPI_Flash_ReadWrite_Byte(READ_DATA);         
    /*赋值地址*/
    SPI_Flash_ReadWrite_Byte((unsigned char)((ReadAddr)>>16));   
    SPI_Flash_ReadWrite_Byte((unsigned char)((ReadAddr)>>8));  
    SPI_Flash_ReadWrite_Byte((unsigned char)ReadAddr);
          
    for(index=0;index<NumByteToRead;index++)
    {
			pBuffer[index]=SPI_Flash_ReadWrite_Byte(DUMMY); 
    }
    SPI_CS_HIGH();                                        
} 

/*Flash空间擦除检测*/
unsigned char SPI_Flash_Check(unsigned int CheckAddr)
{	
	unsigned int index;
	unsigned char buff=0;
	unsigned int addr =CheckAddr;
	
		for(index=0; index <0x10000;index++)
		{
			SPI_Flash_Read(&buff,addr++,1);
			if(buff!=0xff)
			{
				SPI_Flash_Erase_64k(CheckAddr);
				return FALSE;  //不是所有地址都擦除完成
			}
		}
		return TRUE;  //全部擦除完成
}

uint32_t SPI_Flash_WriteByte(unsigned char Byte,unsigned int WriteAddr)
{
		unsigned char cnt=0;
	
		SPI_FLASH_Write_Enable();                  //SET WEL           
    while((SPI_Flash_Read_SR()&0x2)!=0x2) 
		{
			cnt ++;
			if(cnt >200)
				return FALSE;   /*返回写失败*/
		} 
		SPI_CS_LOW();                            
    SPI_Flash_ReadWrite_Byte(PAGE_PRG);      
    SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>16));   
    SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>8));  
    SPI_Flash_ReadWrite_Byte((unsigned char)WriteAddr);
		SPI_Flash_ReadWrite_Byte(Byte);
		SPI_CS_HIGH();                                         
    SPI_Flash_Wait_Busy();
		return TRUE;
		
}

uint32_t SPI_Flash_Write(unsigned char* pBuffer,unsigned int WriteAddr,unsigned short int NumByteToWrite)
{
	unsigned short int pageoffset=PAGE_SIZE-(WriteAddr%PAGE_SIZE);  /*计算该页中还有多少剩余空间*/
	unsigned char cnt=0;
	unsigned short int index;
	unsigned int pagenum =WriteAddr/PAGE_SIZE;  /*本次写入的页数*/
	unsigned int Addr;
	
	if(pageoffset >= NumByteToWrite)  //剩余空间大于要写的数量
	{
    SPI_FLASH_Write_Enable();                  //SET WEL           
    while((SPI_Flash_Read_SR()&0x2)!=0x2) 
		{
			cnt ++;
			if(cnt >200)
				return FALSE;   /*返回写失败*/
		} 
		SPI_CS_LOW();                            
    SPI_Flash_ReadWrite_Byte(PAGE_PRG);      
    SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>16));   
    SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>8));  
    SPI_Flash_ReadWrite_Byte((unsigned char)WriteAddr); 
		for(index=0; index<NumByteToWrite;index++)
		{
			SPI_Flash_ReadWrite_Byte(*(pBuffer+index)); 
		}
    SPI_CS_HIGH();                                         
    SPI_Flash_Wait_Busy(); 
		return TRUE;
	}
	else
	{
		/*先将该页填满*/
		SPI_FLASH_Write_Enable();                  //SET WEL           
    while((SPI_Flash_Read_SR()&0x2)!=0x2) 
		{
			cnt ++;
			if(cnt >200)
				return FALSE;   /*返回写失败*/
		} 
		SPI_CS_LOW();                            
    SPI_Flash_ReadWrite_Byte(PAGE_PRG);      
    SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>16));   
    SPI_Flash_ReadWrite_Byte((unsigned char)((WriteAddr)>>8));  
    SPI_Flash_ReadWrite_Byte((unsigned char)WriteAddr); 
		for(index=0; index<pageoffset;index++)
		{
			SPI_Flash_ReadWrite_Byte(*(pBuffer+index)); 
		}
    SPI_CS_HIGH();                                         
    SPI_Flash_Wait_Busy(); 
		
		NumByteToWrite -=pageoffset;  /*长度减去写入数据*/
		pagenum++;
		Addr = pagenum*PAGE_SIZE;  //获取下一页的起始地址
		
		while(NumByteToWrite >0)
		{
			if(NumByteToWrite > PAGE_SIZE)  //仍然大于一页
			{
				SPI_FLASH_Write_Enable();                  //SET WEL           
				while((SPI_Flash_Read_SR()&0x2)!=0x2) 
				{
					cnt ++;
					if(cnt >200)
					return FALSE;   /*返回写失败*/
				} 
				SPI_CS_LOW();                            
				SPI_Flash_ReadWrite_Byte(PAGE_PRG);      
				SPI_Flash_ReadWrite_Byte((unsigned char)((Addr)>>16));   
				SPI_Flash_ReadWrite_Byte((unsigned char)((Addr)>>8));  
				SPI_Flash_ReadWrite_Byte((unsigned char)Addr); 
				for(index=0; index<PAGE_SIZE;index++)
				{
					SPI_Flash_ReadWrite_Byte(*(pBuffer+index+pageoffset)); 
				}
				SPI_CS_HIGH();                                         
				SPI_Flash_Wait_Busy();
				NumByteToWrite -=PAGE_SIZE;
				pageoffset +=PAGE_SIZE;
				pagenum++;
		    Addr = pagenum*PAGE_SIZE;  //获取下一页的起始地址
			}
			else
			{
				SPI_FLASH_Write_Enable();                  //SET WEL           
				while((SPI_Flash_Read_SR()&0x2)!=0x2) 
				{
					cnt ++;
					if(cnt >200)
					return FALSE;   /*返回写失败*/
				} 
				SPI_CS_LOW();                            
				SPI_Flash_ReadWrite_Byte(PAGE_PRG);      
				SPI_Flash_ReadWrite_Byte((unsigned char)((Addr)>>16));   
				SPI_Flash_ReadWrite_Byte((unsigned char)((Addr)>>8));  
				SPI_Flash_ReadWrite_Byte((unsigned char)Addr); 
				for(index=0; index<NumByteToWrite;index++)
				{
					SPI_Flash_ReadWrite_Byte(*(pBuffer+index+pageoffset)); 
				}
				SPI_CS_HIGH();                                         
				SPI_Flash_Wait_Busy();
				NumByteToWrite =0;
			}
		}
		return TRUE;
	}
}
/***********************************************************************************************
 *SPI 异步读写
 *************************************************************************************************/

/*****************************************************************************************                    									       	
函数名称:SPI_FlashWriteAsync
函数描述:异步写
输入参数:                                  
输出参数:                                                        
函数返回: 
******************************************************************************************/
BOOL SPI_FlashWriteAsync(uint8_t* pBuffer,uint32_t uWriteAddr, uint16_t wNumByteToWrite)
{
	if(wNumByteToWrite > FLASH_TX_BUFFER_SIZE)
	{
		return FALSE;
	}
	if(g_tSpiDevice.tState.eStage != eFLASH_STATE_IDLE)
	{
		Debug(eDBUG_LEVEL_ERROR,"[%d]Flash_Write:busy,return\r\n", GetTicks());
		return FALSE;
	}
	memcpy(g_tSpiDevice.pTxBuffer, pBuffer, wNumByteToWrite);
	g_tSpiDevice.wTxLen = wNumByteToWrite;
	g_tSpiDevice.uTxDstAddr = uWriteAddr;
	g_tSpiDevice.wTxOffset = 0;
	g_tSpiDevice.tState.bTxReq = TRUE; //发送请求
	g_tSpiDevice.tState.bTxCompleted = FALSE;
	//g_tSpiDevice.tState.bTxBusy = TRUE;
	return TRUE;
}
/*****************************************************************************************                    									       	
函数名称:SPI_FlashWriteAsync
函数描述:异步擦整片
输入参数:                                  
输出参数:                                                        
函数返回: 
******************************************************************************************/
BOOL SPI_FlashEraseChipAsync(void)
{
	//unsigned char cnt=0;     
	
	if(g_tSpiDevice.tState.eStage != eFLASH_STATE_IDLE)
	{
		Debug(eDBUG_LEVEL_ERROR,"[%d]Flash_earse:busy,return\r\n", GetTicks());
		return FALSE;
	}
	

	g_tSpiDevice.tState.bEraseChipReq = TRUE;
	return TRUE;	
}
/*****************************************************************************************                    									       	
函数名称:SPI_FlashWriteAsync
函数描述:异步擦指定地址
输入参数:                                  
输出参数:                                                        
函数返回: 
******************************************************************************************/
BOOL SPI_FlashEraseAsync(uint32_t uAddr, uint16_t wlen)
{
	//unsigned char cnt=0;     
	
	if(g_tSpiDevice.tState.eStage != eFLASH_STATE_IDLE)
	{
		Debug(eDBUG_LEVEL_ERROR,"[%d]Flash_earse:busy,return\r\n", GetTicks());
		return FALSE;
	}
	
	g_tSpiDevice.wTxLen = wlen;
	g_tSpiDevice.uTxDstAddr = uAddr;
	g_tSpiDevice.wTxOffset = 0;
	g_tSpiDevice.tState.bEraseSectorReq = TRUE;
	return TRUE;	
}

void SPI_WriteAsyncNotifyCallbackRegister(void *pfn)
{
	g_tSpiDevice.pWriteAsyncNotifyCallback = (void (*)())pfn;
}
void SPI_EraseChipAsyncNotifyCallbackRegister(void *pfn)
{
	g_tSpiDevice.pEraseChipAsyncNotifyCallback = (void (*)())pfn;
}



//判断SPI FLASH 忙
static BOOL SPI_FlashBusyCheck(void)
{
	if((SPI_Flash_Read_SR()&0x01)==0x01)
	{
		return TRUE;
	} 
	else 
	{
		return FALSE;
	}
}
//写一页
static BOOL __SPI_FlashWritePage(uint32_t uWriteAddr, uint8_t *pData, uint16_t wWriteLen)
{
	uint8_t  cnt;
	uint16_t index;
	SPI_FLASH_Write_Enable();                  //SET WEL           
	while((SPI_Flash_Read_SR()&0x2)!=0x2) 
	{
		cnt ++;
		if(cnt >200)
			return FALSE;   /*返回写失败*/
	} 
	SPI_CS_LOW();                            
	SPI_Flash_ReadWrite_Byte(PAGE_PRG);      
	SPI_Flash_ReadWrite_Byte((unsigned char)((uWriteAddr)>>16));   
	SPI_Flash_ReadWrite_Byte((unsigned char)((uWriteAddr)>>8));  
	SPI_Flash_ReadWrite_Byte((unsigned char)uWriteAddr); 
	for(index=0; index < wWriteLen; index++)
	{
		SPI_Flash_ReadWrite_Byte(*(pData+index)); 
	}
	SPI_CS_HIGH();
	return TRUE;
}
//异步写处理子任务
static int32_t __SPI_FlashWrite(void)
{
	uint16_t wWriteRemainNum = g_tSpiDevice.wTxLen - g_tSpiDevice.wTxOffset;
	uint8_t *pData = g_tSpiDevice.pTxBuffer + g_tSpiDevice.wTxOffset;
	uint32_t uWriteAddr = g_tSpiDevice.uTxDstAddr + g_tSpiDevice.wTxOffset;
	uint16_t wPageRemain = PAGE_SIZE - (uWriteAddr % PAGE_SIZE);

	//判断写完成
	if(wWriteRemainNum == 0)
	{
		//写完成
		g_tSpiDevice.tState.bTxCompleted = TRUE;
		//g_tSpiDevice.tState.bRxBusy = FALSE;
		g_tSpiDevice.tState.bTxReq = FALSE;
		g_tSpiDevice.tState.eStage = eFLASH_STATE_IDLE; //写完成 转空闲
		if(g_tSpiDevice.pWriteAsyncNotifyCallback)
		{
			//TODO 异步通知回调 供调用者实现
			g_tSpiDevice.pWriteAsyncNotifyCallback();
		}
		return eSUCCESS;
	}		

	
	//小于一页剩余可写字节
	if(wWriteRemainNum <= wPageRemain)
	{
		__SPI_FlashWritePage(uWriteAddr, pData, wWriteRemainNum);
		g_tSpiDevice.wTxOffset += wWriteRemainNum;
		//写完剩余
	}
	else 
	{
		__SPI_FlashWritePage(uWriteAddr, pData, wPageRemain);
		g_tSpiDevice.wTxOffset += wPageRemain;
		//写一整页,
	}
	//异步读忙
	g_tSpiDevice.tState.eStage = eFLASH_STATE_BUSY;
	return eSUCCESS;
}
//异步读忙子任务
static void __SPI_FlashBusy(void)
{
	//读忙 非阻塞
	if(SPI_FlashBusyCheck())
	{
		return ;
	}
	//SPI上次操作已完成
	//TX process
	if(g_tSpiDevice.tState.bTxReq == TRUE)
	{
		g_tSpiDevice.tState.eStage = eFLASH_STATE_WRITE;
	}
	//RX process
	// TODO 擦除已完成
	if(g_tSpiDevice.tState.bEraseChipReq == TRUE)
	{
		g_tSpiDevice.tState.eStage = eFLASH_STATE_ERASE_CHIP;
	}
	if(g_tSpiDevice.tState.bEraseSectorReq == TRUE)
	{
		g_tSpiDevice.tState.eStage = eFLASH_STATE_ERASE;
	}
}
//异步擦除子任务 整片
static int32_t __SPI_FlashEraseChip(void)
{
	uint8_t cnt = 0;
	SPI_FLASH_Write_Enable();                  //SET WEL
	if(g_tSpiDevice.tState.bEraseSuccess == TRUE)
	{
		g_tSpiDevice.tState.bEraseSuccess = FALSE;
		g_tSpiDevice.tState.bEraseChipReq = FALSE;
		g_tSpiDevice.tState.eStage = eFLASH_STATE_IDLE;//写完成 转空闲
		if(g_tSpiDevice.pEraseChipAsyncNotifyCallback)
		{
			////TODO 异步通知回调 供调用者实现
			g_tSpiDevice.pEraseChipAsyncNotifyCallback();
		}
		return TRUE;
	}
	while((SPI_Flash_Read_SR()&0x2)!=0x2) 
	{
		cnt ++;
		if(cnt >200)
			return FALSE;
	}
	SPI_CS_LOW();                             
	SPI_Flash_ReadWrite_Byte(CHIP_ERASE);        
	SPI_CS_HIGH();                                         
	//SPI_Flash_Wait_Busy(); 
	g_tSpiDevice.tState.eStage = eFLASH_STATE_BUSY;//异步读忙
	return TRUE;
}
//异步擦除子任务 
static int32_t __SPI_FlashErase(void)
{
	uint8_t cnt = 0;	
	//uint32_t uSectorIdxFirst = g_tSpiDevice.uTxDstAddr/SECTOR_SIZE;
	uint32_t uSectorIdxTail = (g_tSpiDevice.uTxDstAddr+g_tSpiDevice.wTxLen)/SECTOR_SIZE;
	uint32_t uCurrentSectorIdx = (g_tSpiDevice.uTxDstAddr + g_tSpiDevice.wTxOffset)/SECTOR_SIZE;
	
	if(uCurrentSectorIdx > uSectorIdxTail)
	{
		g_tSpiDevice.tState.bEraseSectorReq = FALSE;
		g_tSpiDevice.tState.bEraseSuccess = TRUE;
		g_tSpiDevice.tState.eStage = eFLASH_STATE_IDLE;//写完成 转空闲
		if(g_tSpiDevice.pEraseChipAsyncNotifyCallback)
		{
			////TODO 异步通知回调 供调用者实现
			g_tSpiDevice.pEraseChipAsyncNotifyCallback();
		}
		return TRUE;
	}
	SPI_FLASH_Write_Enable();                  //SET WEL
	while((SPI_Flash_Read_SR()&0x2)!=0x2) 
	{
		cnt ++;
		if(cnt >200)
			return FALSE;
	}
	SPI_CS_LOW();                            
	SPI_Flash_ReadWrite_Byte(SECTOR_ERASE);      
	SPI_Flash_ReadWrite_Byte((unsigned char)((uCurrentSectorIdx*SECTOR_SIZE)>>16));   
	SPI_Flash_ReadWrite_Byte((unsigned char)((uCurrentSectorIdx*SECTOR_SIZE)>>8));  
	SPI_Flash_ReadWrite_Byte((unsigned char)(uCurrentSectorIdx*SECTOR_SIZE)); 
	SPI_CS_HIGH(); 
	g_tSpiDevice.wTxOffset += SECTOR_SIZE;
	//SPI_Flash_Wait_Busy(); 
	g_tSpiDevice.tState.eStage = eFLASH_STATE_BUSY;//异步读忙
	return TRUE;
}
//空闲处理子任务
static void __SPI_FlashIdle(void)
{
	//启动各项任务
	if(g_tSpiDevice.tState.bTxReq == TRUE)
	{
		g_tSpiDevice.tState.eStage = eFLASH_STATE_WRITE;
	} 
	else if(g_tSpiDevice.tState.bRxReq == TRUE)
	{
		g_tSpiDevice.tState.eStage = eFLASH_STATE_READ;
	} 
	else if(g_tSpiDevice.tState.bEraseChipReq == TRUE)
	{
		g_tSpiDevice.tState.eStage = eFLASH_STATE_ERASE_CHIP;
	}
	else if(g_tSpiDevice.tState.bEraseSectorReq == TRUE)
	{
		g_tSpiDevice.tState.eStage = eFLASH_STATE_ERASE;
	}
}
//SPI异步操作处理总任务
void SPI_FlashAsyncProcTask(void)
{
	switch(g_tSpiDevice.tState.eStage)
	{
		case eFLASH_STATE_IDLE:
			__SPI_FlashIdle();
			break;
		case eFLASH_STATE_WRITE:
			__SPI_FlashWrite();
			break;
		case eFLASH_STATE_READ:
			//TODO
			break;
		case eFLASH_STATE_BUSY:
			__SPI_FlashBusy();
			break;
		case eFLASH_STATE_ERASE_CHIP:
			__SPI_FlashEraseChip();
			break;
		case eFLASH_STATE_ERASE:
			__SPI_FlashErase();
			break;
		default:
			break;
	}
	
}
	







评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值