前言
bsp_spi.c
#include "bsp_spi.h"
#define spiOutHi(gpio, pin) {gpio->BSRR=pin;}
#define spiOutLo(gpio, pin) {gpio->BRR=pin;}
#define spiOut(gpio, pin, lev) (lev)?(gpio->BSRR=pin):(gpio->BRR=pin)
#define spiIn(gpio, pin) GPIO_ReadInputDataBit(gpio, pin)
#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)
spi_t spiDriverElem[spiSPI_DRIVER_COUNT];
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;
}
void spiGpioInit(eSPI_ID id)
{
GPIO_InitTypeDef GPIO_InitStructure;
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);
GPIO_InitStructure.GPIO_Pin = spi->csPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(spi->csGpiox, &GPIO_InitStructure);
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);
}
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);
}
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);
}
}
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;
}
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);
}
}
void spiCSOut(eSPI_ID id, unsigned char lev)
{
const spi_t * spi = &spiDriverElem[id];
spiOut(spi->csGpiox, spi->csPin, lev);
}
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
#ifndef _BSP_SPI_H_
#define _BSP_SPI_H_
#include "LssAppConfig.h"
#define spiSPI_DRIVER_COUNT 1
typedef enum
{
espiFLASH_A = 0,
espiSPI_DRIVER_COUNT,
}eSPI_ID;
typedef enum
{
espiHARDWARE = 0,
espiSOFTWARE,
}eSPI_METHOD;
struct SPI_T{
eSPI_ID id;
eSPI_METHOD method;
unsigned char CPOL;
unsigned char CPHA;
unsigned int readDelayUsCnt;
void ( *delayUsFun )(int cnt);
SPI_TypeDef* SPIx;
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;
extern spi_t spiDriverElem[spiSPI_DRIVER_COUNT];
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
#include "bsp_flash.h"
#include "lss_IO.h"
#include "boardInfo.h"
flash_t flashDeviceElem[flashFLASH_DEVICE_COUNT];
void flashWriteByte(eFLASH_ID id, unsigned char data)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiWriteOneByte(spiid, data);
}
unsigned char flashReadByte(eFLASH_ID id)
{
unsigned char ch;
eSPI_ID spiid = flashDeviceElem[id].spiID;
ch = spiReadOneByte(spiid);
return ch;
}
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;
}
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);
}
void mx25lxxWaitBusy(eFLASH_ID id)
{
while((mx25lxxReadSR(id)&0x01)==0x01);
}
void mx25lxxWriteEnable(eFLASH_ID id)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxWRITE_ENABLE);
spiCSOut(spiid, 1);
}
void mx25lxxWriteDisable(eFLASH_ID id)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxWRITE_DISABLE);
spiCSOut(spiid, 1);
}
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;
}
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);
}
spiCSOut(spiid, 1);
}
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]);
}
spiCSOut(spiid, 1);
}
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;
while(1)
{
mx25lxxWriteBytes(id, writeAddr, pWriteBuff, residueSize);
if(size==residueSize)
break;
else
{
pWriteBuff+=residueSize;
writeAddr+=residueSize;
size-=residueSize;
if(size>256)residueSize=256;
else residueSize=size;
}
}
}
void mx25lxxEraseSector(eFLASH_ID id, uint32_t eraseAddr)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
eraseAddr*=4096;
mx25lxxWriteEnable(id);
mx25lxxWaitBusy(id);
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxSECTOR_ERASE);
spiWriteOneByte(spiid, (u8)((eraseAddr)>>16));
spiWriteOneByte(spiid, (u8)((eraseAddr)>>8));
spiWriteOneByte(spiid, (u8)eraseAddr);
spiCSOut(spiid, 1);
mx25lxxWaitBusy(id);
}
void mx25lxxPowerDown(eFLASH_ID id)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxPOWER_DOWN);
spiCSOut(spiid, 1);
}
void mx25lxxWakeUp(eFLASH_ID id)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxRELEASE_POWER_DOWN);
spiCSOut(spiid, 1);
}
uint8_t mx25lxxBUFFER[4096];
void mx25lxxEraseBytes(eFLASH_ID id, uint32_t eraseAddr, uint8_t * pEraseBuff, uint16_t size)
{
uint16_t i;
uint32_t secAddr;
uint16_t secOff;
uint16_t secResidueSize;
u8 * mx25lxxBUF;
mx25lxxBUF = mx25lxxBUFFER;
secAddr=eraseAddr/4096;
secOff=eraseAddr%4096;
secResidueSize=4096-secOff;
if(size<=secResidueSize)secResidueSize=size;
while(1)
{
mx25lxxReadBytes(id, secAddr*4096, mx25lxxBUFFER, 4096);
for(i=0;i<secResidueSize;i++)
{
if(mx25lxxBUF[secOff+i]!=0XFF)break;
}
if(i<secResidueSize)
{
mx25lxxEraseSector(id, secAddr);
for(i=0;i<secResidueSize;i++)
{
mx25lxxBUF[i+secOff]=pEraseBuff[i];
}
mx25lxxWriteNoCheck(id,secAddr*4096,mx25lxxBUF,4096);
}
else
mx25lxxWriteNoCheck(id,eraseAddr,pEraseBuff,secResidueSize);
if(size==secResidueSize)
break;
else
{
secAddr++;
secOff=0;
pEraseBuff+=secResidueSize;
eraseAddr+=secResidueSize;
size-=secResidueSize;
if(size>4096)
secResidueSize=4096;
else
secResidueSize=size;
}
};
}
void ITC_MX25LXX_EraseChip(eFLASH_ID id)
{
eSPI_ID spiid = flashDeviceElem[id].spiID;
mx25lxxWriteEnable(id);
mx25lxxWaitBusy(id);
spiCSOut(spiid, 0);
spiWriteOneByte(spiid, mx25lxxCHIP_ERASE);
spiCSOut(spiid, 1);
mx25lxxWaitBusy(id);
}
void flashInit(void)
{
uint8_t flashID;
spi_t spi;
unsigned int devID;
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_DEV(eMX25lXX_1, espiFLASH_A);
for (flashID = 0; flashID < flashFLASH_DEVICE_COUNT; flashID++)
{
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
#ifndef _BSP_FLASH_H_
#define _BSP_FLASH_H_
#include "LssAppConfig.h"
#include "bsp_spi.h"
#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
#define flashFLASH_DEVICE_COUNT 1
typedef enum
{
eMX25lXX_1 = 0,
eflashFLASH_DEVICE_COUNT,
}eFLASH_ID;
struct FLASH_T{
eFLASH_ID ID;
eSPI_ID spiID;
};
typedef struct FLASH_T flash_t;
#define REGISTER_FLASH_DEV(flashid, spicid) \
{ \
flashDeviceElem[flashid].ID = flashid; \
flashDeviceElem[flashid].spiID = spicid; \
}
extern flash_t flashDeviceElem[flashFLASH_DEVICE_COUNT];
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
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现