单片机裸机开发中会经常遇到外设速度过慢,长时间读忙等待,但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;
}
}