评估板板载了一颗16Mbits的SST25VF016B来记录数据,去官网找了下资料,看样子快要停产了,不过Flash的操作方法有相似之处。
下面是芯片操作程序,分SPI和FLASH命令两部分。
SPI操作:参考原子的SPI驱动改写。
/*****************************************************************************//*!
* @brief Spi 3 init .
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SPI3_Init(void) {
u16 tempreg = 0;
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_SPI3_FORCE_RESET();
// SPI IO
GPIO_InitStruct.Pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_RCC_SPI3_RELEASE_RESET();
//SPI - SS IO PG10
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
//这里只针对SPI口初始化
RCC->APB2RSTR |= 1 << 20; //复位SPI3
RCC->APB2RSTR &= ~(1 << 20); //停止复位SPI3
tempreg |= 0 << 10; //全双工模式
tempreg |= 1 << 9; //软件nss管理
tempreg |= 1 << 8;
tempreg |= 1 << 2; //SPI主机
tempreg |= 0 << 11; //8位数据格式
tempreg |= 1 << 1; //空闲模式下SCK为1 CPOL=1
tempreg |= 1 << 0; //数据采样从第2个时间边沿开始,CPHA=1
//对SPI3属于APB2的外设.时钟频率最大为84Mhz频率.
tempreg |= 7 << 3; //Fsck=Fpclk1/256
tempreg |= 0 << 7; //MSB First
tempreg |= 1 << 6; //SPI启动
SPI3->CR1 = tempreg; //设置CR1
SPI3->I2SCFGR &= ~(1 << 11); //选择SPI模式
PGout(10) = 0;
SPI3_ReadWriteByte(0xff); //启动传输
PGout(10) = 1;
}
/*****************************************************************************//*!
* @brief spi3 speed set.
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SPI3_SetSpeed(u8 SpeedSet) {
SpeedSet &= 0X07; //限制范围
SPI3->CR1 &= 0XFFC7;
SPI3->CR1 |= SpeedSet << 3; //设置SPI3速度
SPI3->CR1 |= 1 << 6; //SPI设备使能
}
/*****************************************************************************//*!
* @brief spi3 write and read.
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
u8 SPI3_ReadWriteByte(u8 TxData) {
while ((SPI3->SR & 1 << 1) == 0); //等待发送区空
SPI3->DR = TxData; //发送一个byte
while ((SPI3->SR & 1 << 0) == 0); //等待接收完一个byte
return SPI3->DR; //返回收到的数据
}
Flash操作
/* ------------------------------------------------------------------------*
*
* ------------------------------------------------------------------------*/
#include "sst25_cmd.h"
#include "spi.h"
#include "pincfg.h"
uint8_t scs;
#define SST25Cs(x) x?(PGout(10)=1):(PGout(10)=0)
#define SpiRw(x) SPI3_ReadWriteByte(x)
#define SpiDmaRw(x,y,z)
// command list
#define SST25CMD_Read_Data 0x03
#define SST25CMD_Fast_Read 0x0B
#define SST25CMD_Sector_Erase 0x20
#define SST25CMD_Block_Erase_32K 0x52
#define SST25CMD_Block_Erase_64K 0xD8
#define SST25CMD_Chip_Erase 0x60
#define SST25CMD_Byte_Program 0x02
#define SST25CMD_AddrInc_Program 0xAD
#define SST25CMD_Read_Status 0x05
#define SST25CMD_SRWrite Enable 0x50
#define SST25CMD_Write_Status 0x01 //写入的空间保护位具有掉电记忆功能
#define SST25CMD_Write_Enable 0x06
#define SST25CMD_Write_Disable 0x04
#define SST25CMD_Read_ID 0x90
#define SST25CMD_Read_JEDEC_ID 0x9F
#define SST25CMD_So_Enable 0x70
#define SST25CMD_So_Disable 0x80
typedef union {
uint32_t Val;
struct {
uint8_t LB;
uint8_t HB;
uint8_t UB;
uint8_t MB;
}byte;
} UINT32_VAL;
void SST25Wait(uint8_t Cnt)
{
while(Cnt --){};
}
/*****************************************************************************//*!
* @brief read status.
* @param none
*
* @return statues
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
uint8_t SST25CmdStRead(void)
{
uint8_t St;
SST25Cs(0);
SpiRw( SST25CMD_Read_Status);
St = SpiRw( 0xFF);
SST25Cs(1);
return St;
}
void SST25CmdStWrite(uint8_t St){
while(SST25Busy()){}
while( SST25Q_ST_WRITE_EN != (SST25CmdStRead()&SST25Q_ST_WRITE_EN))
SST25CmdWriteEn();
SST25Cs(0);
SpiRw( SST25CMD_Write_Status);
St = SpiRw( St);
SST25Cs(1);
NOP20();
while(SST25Busy()){}
while( SST25Q_ST_WRITE_EN == (SST25CmdStRead()&SST25Q_ST_WRITE_EN))
SST25CmdWriteDis();
}
/*****************************************************************************//*!
* @brief read busy statues.
*
* @param none
*
* @return busy or not
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
uint8_t SST25Busy(void)
{
uint8_t FlashSt;
SST25Cs(0);
SpiRw( SST25CMD_Read_Status);
FlashSt = SpiRw( 0xFF);
SST25Cs(1);
return ((uint8_t)(FlashSt & SST25Q_ST_BUSY_MASK));
}
/*****************************************************************************//*!
* @brief write enable.
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25CmdWriteEn(void)
{
SST25Cs(0);
SpiRw( SST25CMD_Write_Enable);
SST25Cs(1);
}
/*****************************************************************************//*!
* @brief write disable.
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25CmdWriteDis(void)
{
SST25Cs(0);
SpiRw( SST25CMD_Write_Disable);
SST25Cs(1);
}
/*****************************************************************************//*!
* @brief Erase aector.
*
* @param addr: data address in chip
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25SectorErase(uint32_t addr)
{
UINT32_VAL Par;
//waiting for idle
while(SST25Busy()){}
while( SST25Q_ST_WRITE_EN != (SST25CmdStRead()&SST25Q_ST_WRITE_EN))
SST25CmdWriteEn();
SST25Cs(0);
Par.Val = addr;
SpiRw( SST25CMD_Sector_Erase);
SpiRw( Par.byte.UB);
SpiRw( Par.byte.HB);
SpiRw( Par.byte.LB);
SST25Cs(1);
NOP20();
while(SST25Busy()){}
}
/*****************************************************************************//*!
* @brief Erase block.
*
* @param addr: data address in chip
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25BlockErase(uint32_t addr)
{
UINT32_VAL Par;
//waiting for idle
while(SST25Busy()){}
while( SST25Q_ST_WRITE_EN != (SST25CmdStRead()&SST25Q_ST_WRITE_EN))
SST25CmdWriteEn();
SST25Cs(0);
Par.Val = addr;
SpiRw( SST25CMD_Block_Erase_32K);
SpiRw( Par.byte.UB);
SpiRw( Par.byte.HB);
SpiRw( Par.byte.LB);
SST25Cs(1);
NOP20();
while(SST25Busy()){}
}
/*****************************************************************************//*!
* @brief Erase chip.
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25ChipErase(void )
{
while(SST25Busy()){}
while( SST25Q_ST_WRITE_EN != (SST25CmdStRead()&SST25Q_ST_WRITE_EN))
SST25CmdWriteEn();
SST25Cs(0);
SpiRw( SST25CMD_Chip_Erase);
SST25Cs(1);
NOP20();
while(SST25Busy()){}
}
/*****************************************************************************//*!
* @brief read data.
*
* @param addr address in chip
* len length will be read
* des destination
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25Read(uint32_t addr,uint32_t Len,uint8_t *Des)
{
UINT32_VAL Par;
//waiting for idle
while(SST25Busy()){}
//
SST25Cs(0);
Par.Val = addr;
SpiRw( SST25CMD_Read_Data);
SpiRw( Par.byte.UB);
SpiRw( Par.byte.HB);
SpiRw( Par.byte.LB);
while(Len--)
{
*Des++ = SpiRw( 0x55 );
}
SST25Cs(1);
}
/*****************************************************************************//*!
* @brief write data ,must be in same page.
*
* @param addr address in chip
* len length will be read
* des source
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25Write(uint32_t addr,uint32_t Len,uint8_t *Src)
{
UINT32_VAL Par;
//waiting for idle
while(SST25Busy()){}
Par.Val = addr;
while(Len--){
SST25CmdWriteEn();
NOP20();
SST25Cs(0);
SpiRw( SST25CMD_Byte_Program);
SpiRw( Par.byte.UB);
SpiRw( Par.byte.HB);
SpiRw( Par.byte.LB);
SpiRw( *Src++);
SST25Cs(1);
Par.Val++;
while(SST25Busy()){}
}
NOP20();
while(SST25Busy()){}
}
评估板板载了一颗16Mbits的SST25VF016B来记录数据,去官网找了下资料,看样子快要停产了,不过Flash的操作方法有相似之处。
下面是芯片操作程序,分SPI和FLASH命令两部分。
SPI操作:参考原子的SPI驱动改写。
/*****************************************************************************//*!
* @brief Spi 3 init .
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SPI3_Init(void) {
u16 tempreg = 0;
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_SPI3_FORCE_RESET();
// SPI IO
GPIO_InitStruct.Pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_RCC_SPI3_RELEASE_RESET();
//SPI - SS IO PG10
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
//这里只针对SPI口初始化
RCC->APB2RSTR |= 1 << 20; //复位SPI3
RCC->APB2RSTR &= ~(1 << 20); //停止复位SPI3
tempreg |= 0 << 10; //全双工模式
tempreg |= 1 << 9; //软件nss管理
tempreg |= 1 << 8;
tempreg |= 1 << 2; //SPI主机
tempreg |= 0 << 11; //8位数据格式
tempreg |= 1 << 1; //空闲模式下SCK为1 CPOL=1
tempreg |= 1 << 0; //数据采样从第2个时间边沿开始,CPHA=1
//对SPI3属于APB2的外设.时钟频率最大为84Mhz频率.
tempreg |= 7 << 3; //Fsck=Fpclk1/256
tempreg |= 0 << 7; //MSB First
tempreg |= 1 << 6; //SPI启动
SPI3->CR1 = tempreg; //设置CR1
SPI3->I2SCFGR &= ~(1 << 11); //选择SPI模式
PGout(10) = 0;
SPI3_ReadWriteByte(0xff); //启动传输
PGout(10) = 1;
}
/*****************************************************************************//*!
* @brief spi3 speed set.
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SPI3_SetSpeed(u8 SpeedSet) {
SpeedSet &= 0X07; //限制范围
SPI3->CR1 &= 0XFFC7;
SPI3->CR1 |= SpeedSet << 3; //设置SPI3速度
SPI3->CR1 |= 1 << 6; //SPI设备使能
}
/*****************************************************************************//*!
* @brief spi3 write and read.
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
u8 SPI3_ReadWriteByte(u8 TxData) {
while ((SPI3->SR & 1 << 1) == 0); //等待发送区空
SPI3->DR = TxData; //发送一个byte
while ((SPI3->SR & 1 << 0) == 0); //等待接收完一个byte
return SPI3->DR; //返回收到的数据
}
Flash操作
/* ------------------------------------------------------------------------*
*
* ------------------------------------------------------------------------*/
#include "sst25_cmd.h"
#include "spi.h"
#include "pincfg.h"
uint8_t scs;
#define SST25Cs(x) x?(PGout(10)=1):(PGout(10)=0)
#define SpiRw(x) SPI3_ReadWriteByte(x)
#define SpiDmaRw(x,y,z)
// command list
#define SST25CMD_Read_Data 0x03
#define SST25CMD_Fast_Read 0x0B
#define SST25CMD_Sector_Erase 0x20
#define SST25CMD_Block_Erase_32K 0x52
#define SST25CMD_Block_Erase_64K 0xD8
#define SST25CMD_Chip_Erase 0x60
#define SST25CMD_Byte_Program 0x02
#define SST25CMD_AddrInc_Program 0xAD
#define SST25CMD_Read_Status 0x05
#define SST25CMD_SRWrite Enable 0x50
#define SST25CMD_Write_Status 0x01 //写入的空间保护位具有掉电记忆功能
#define SST25CMD_Write_Enable 0x06
#define SST25CMD_Write_Disable 0x04
#define SST25CMD_Read_ID 0x90
#define SST25CMD_Read_JEDEC_ID 0x9F
#define SST25CMD_So_Enable 0x70
#define SST25CMD_So_Disable 0x80
typedef union {
uint32_t Val;
struct {
uint8_t LB;
uint8_t HB;
uint8_t UB;
uint8_t MB;
}byte;
} UINT32_VAL;
void SST25Wait(uint8_t Cnt)
{
while(Cnt --){};
}
/*****************************************************************************//*!
* @brief read status.
* @param none
*
* @return statues
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
uint8_t SST25CmdStRead(void)
{
uint8_t St;
SST25Cs(0);
SpiRw( SST25CMD_Read_Status);
St = SpiRw( 0xFF);
SST25Cs(1);
return St;
}
void SST25CmdStWrite(uint8_t St){
while(SST25Busy()){}
while( SST25Q_ST_WRITE_EN != (SST25CmdStRead()&SST25Q_ST_WRITE_EN))
SST25CmdWriteEn();
SST25Cs(0);
SpiRw( SST25CMD_Write_Status);
St = SpiRw( St);
SST25Cs(1);
NOP20();
while(SST25Busy()){}
while( SST25Q_ST_WRITE_EN == (SST25CmdStRead()&SST25Q_ST_WRITE_EN))
SST25CmdWriteDis();
}
/*****************************************************************************//*!
* @brief read busy statues.
*
* @param none
*
* @return busy or not
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
uint8_t SST25Busy(void)
{
uint8_t FlashSt;
SST25Cs(0);
SpiRw( SST25CMD_Read_Status);
FlashSt = SpiRw( 0xFF);
SST25Cs(1);
return ((uint8_t)(FlashSt & SST25Q_ST_BUSY_MASK));
}
/*****************************************************************************//*!
* @brief write enable.
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25CmdWriteEn(void)
{
SST25Cs(0);
SpiRw( SST25CMD_Write_Enable);
SST25Cs(1);
}
/*****************************************************************************//*!
* @brief write disable.
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25CmdWriteDis(void)
{
SST25Cs(0);
SpiRw( SST25CMD_Write_Disable);
SST25Cs(1);
}
/*****************************************************************************//*!
* @brief Erase aector.
*
* @param addr: data address in chip
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25SectorErase(uint32_t addr)
{
UINT32_VAL Par;
//waiting for idle
while(SST25Busy()){}
while( SST25Q_ST_WRITE_EN != (SST25CmdStRead()&SST25Q_ST_WRITE_EN))
SST25CmdWriteEn();
SST25Cs(0);
Par.Val = addr;
SpiRw( SST25CMD_Sector_Erase);
SpiRw( Par.byte.UB);
SpiRw( Par.byte.HB);
SpiRw( Par.byte.LB);
SST25Cs(1);
NOP20();
while(SST25Busy()){}
}
/*****************************************************************************//*!
* @brief Erase block.
*
* @param addr: data address in chip
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25BlockErase(uint32_t addr)
{
UINT32_VAL Par;
//waiting for idle
while(SST25Busy()){}
while( SST25Q_ST_WRITE_EN != (SST25CmdStRead()&SST25Q_ST_WRITE_EN))
SST25CmdWriteEn();
SST25Cs(0);
Par.Val = addr;
SpiRw( SST25CMD_Block_Erase_32K);
SpiRw( Par.byte.UB);
SpiRw( Par.byte.HB);
SpiRw( Par.byte.LB);
SST25Cs(1);
NOP20();
while(SST25Busy()){}
}
/*****************************************************************************//*!
* @brief Erase chip.
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25ChipErase(void )
{
while(SST25Busy()){}
while( SST25Q_ST_WRITE_EN != (SST25CmdStRead()&SST25Q_ST_WRITE_EN))
SST25CmdWriteEn();
SST25Cs(0);
SpiRw( SST25CMD_Chip_Erase);
SST25Cs(1);
NOP20();
while(SST25Busy()){}
}
/*****************************************************************************//*!
* @brief read data.
*
* @param addr address in chip
* len length will be read
* des destination
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25Read(uint32_t addr,uint32_t Len,uint8_t *Des)
{
UINT32_VAL Par;
//waiting for idle
while(SST25Busy()){}
//
SST25Cs(0);
Par.Val = addr;
SpiRw( SST25CMD_Read_Data);
SpiRw( Par.byte.UB);
SpiRw( Par.byte.HB);
SpiRw( Par.byte.LB);
while(Len--)
{
*Des++ = SpiRw( 0x55 );
}
SST25Cs(1);
}
/*****************************************************************************//*!
* @brief write data ,must be in same page.
*
* @param addr address in chip
* len length will be read
* des source
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SST25Write(uint32_t addr,uint32_t Len,uint8_t *Src)
{
UINT32_VAL Par;
//waiting for idle
while(SST25Busy()){}
Par.Val = addr;
while(Len--){
SST25CmdWriteEn();
NOP20();
SST25Cs(0);
SpiRw( SST25CMD_Byte_Program);
SpiRw( Par.byte.UB);
SpiRw( Par.byte.HB);
SpiRw( Par.byte.LB);
SpiRw( *Src++);
SST25Cs(1);
Par.Val++;
while(SST25Busy()){}
}
NOP20();
while(SST25Busy()){}
}