Files
stair56e_uart/component/boot2/bsp/bsp_spi_master.c
T
2026-08-05 19:07:52 +08:00

512 lines
15 KiB
C

/*----------------------------------------------------------------------------------------------------
INCLUDE HEADE FILES
----------------------------------------------------------------------------------------------------*/
#include "Includes.h"
/*----------------------------------------------------------------------------------------------------
SPI COMMAND
-----------------------------------------------------------------------------------------------------*/
#define CMD_RDID 0x9F
#define CMD_PAGE_ERASE 0x81
#define CMD_READ_STATUS2 0x35
#define CMD_WRITE_STATUS 0x01
#define CMD_READ_DATA 0x03
#define CMD_READ_STATUS 0x05
#define CMD_CHIP_ERASE 0xc7
#define CMD_WRITE_ENABLE 0x06
#define CMD_PAGE_PROGRAM 0x02
#define CMD_BLOCK_ERASE 0xD8
#define CMD_SECTOR_ERASE 0x20
#define CMD_RELEASE_PWRDWN 0xAB
#define CMD_PWRDWN 0xB9
#define CMD_ID 0x4B
#define PACKET_FULL_LEN FLASH_PAGE_SIZE
static uint8_t __attribute__((aligned(4))) txbuff[(PACKET_FULL_LEN+4)];
static uint8_t __attribute__((aligned(4))) rxbuff[(PACKET_FULL_LEN+4)];
/* ---------------------------------------------------------------------------------------------------
- 函数名称: Init_spi_master
- 函数功能: 初始化spi主模式
- 创建日期: 2015-09-14
----------------------------------------------------------------------------------------------------*/
void Init_spi_master(uint32_t ch, uint32_t freq)
{
uint32_t val;
__write_hw_reg32(CPR_SPIx_MCLK_CTL(ch), 0x110010);//1分频 //- spi(x)_mclk = 32Mhz(When TXCO=32Mhz).
__write_hw_reg32(CPR_CTLAPBCLKEN_GRCTL , (0x1000100<<ch)); //- 打开spi(x) pclk.
__read_hw_reg32(CPR_SSI_CTRL, val);
val |= (ch==0)? 0x01: 0x30;
__write_hw_reg32(CPR_SSI_CTRL, val);
__write_hw_reg32(SSIx_EN(ch), 0x00);
__write_hw_reg32(SSIx_IE(ch), 0x00);
__write_hw_reg32(SSIx_CTRL0(ch) , 0x7); /* 16bit SPI data */
__write_hw_reg32(SSIx_SE(ch), 0x01);
__write_hw_reg32(SSIx_BAUD(ch), freq); //- spix_mclk 分频.
__write_hw_reg32(SSIx_RXFTL(ch), 0x00);
__write_hw_reg32(SSIx_TXFTL(ch), 0x00);
}
void close_ssi0(void)
{
__write_hw_reg32(CPR_SPIx_MCLK_CTL(0), 0x110000);//close ssi0 mclk
__write_hw_reg32(CPR_CTLAPBCLKEN_GRCTL , (0x1000000)); //close ssi0 pclk
__write_hw_reg32(CPR_RSTCTL_SUBRST_SW , 0x040000); //复位ssi0
__write_hw_reg32(CPR_RSTCTL_SUBRST_SW , 0x040004); //复位ssi0
}
#ifdef QUAD_ENABLE
void spi_flash_quad_en(void)
{
uint32_t bWk, cWk;
__read_hw_reg32(SSI0_CTRL0 , bWk);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_DMAS , 0x00);
__write_hw_reg32(SSI0_CTRL0 , 0x07); /* 8bit SPI data */
__write_hw_reg32(SSI0_EN , 0x01);
__write_hw_reg32(SSI0_DATA, CMD_WRITE_STATUS);
__write_hw_reg32(SSI0_DATA, 0);
__write_hw_reg32(SSI0_DATA, 0x02);
do {
__read_hw_reg32(SSI0_STS, cWk);
}while((cWk&0x05) != 0x04);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_CTRL0 , bWk);
}
uint8_t spi_flash_read_stat(void)
{
uint32_t bWk, cWk;
uint8_t s8_15;
__read_hw_reg32(SSI0_CTRL0 , bWk);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_DMAS , 0x00);
__write_hw_reg32(SSI0_CTRL0 , 0x07); /* 8bit SPI data */
__write_hw_reg32(SSI0_EN , 0x01);
__write_hw_reg32(SSI0_DATA, CMD_READ_STATUS2);
__write_hw_reg32(SSI0_DATA, 0xff);
do {
__read_hw_reg32(SSI0_STS, cWk);
}while((cWk&0x05) != 0x04);
cWk=*SSI0_DATA;//no use
s8_15=*SSI0_DATA;
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_CTRL0 , bWk);
return s8_15;
}
#endif
uint32_t spi_flash_read_identific(void)
{
uint32_t bWk, cWk;
uint8_t manufact,memory_type,capacity;
__read_hw_reg32(SSI0_CTRL0 , bWk);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_DMAS , 0x00);
__write_hw_reg32(SSI0_CTRL0 , 0x07); /* 8bit SPI data */
__write_hw_reg32(SSI0_EN , 0x01);
__write_hw_reg32(SSI0_DATA, CMD_RDID);
__write_hw_reg32(SSI0_DATA, 0xff);
__write_hw_reg32(SSI0_DATA, 0xff);
__write_hw_reg32(SSI0_DATA, 0xff);
do {
__read_hw_reg32(SSI0_STS, cWk);
}while((cWk&0x05) != 0x04);
cWk=*SSI0_DATA;//no use
manufact=*SSI0_DATA;
memory_type=*SSI0_DATA;
capacity=*SSI0_DATA;
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_CTRL0 , bWk);
return (CMD_RDID<<24)|(manufact<<16)|(memory_type<<8)|(capacity<<0);
}
/* ---------------------------------------------------------------------------------------------------
- 函数名称: spi_flash_write_Sector
- 函数功能: 向SPI FLASH指定扇区写入数据
- 创建日期: 2019.04.08
- 作 者:陈俊伟
---------------------------------------------------------------*/
extern void spi_flash_write_sPages(uint32_t WriteAddR, uint8_t *buff)
{
uint8_t i=0,j=PAGES_SIZE/FLASH_PAGE_SIZE;
uint8_t buf;
for (int k = 0; k < 1024; k += 4)
{
// printf("i:%d\n",i);
buf = buff[k];
buff[k] = buff[k + 3];
buff[k + 3] = buf;
buf = buff[k + 1];
buff[k + 1] = buff[k + 2];
buff[k + 2] = buf;
}
for(i=0;i<j;i++)
{
spi_flash_write_enable();
spi_flash_write_page(WriteAddR,buff);
while(spi_flash_wait_till_ready());
WriteAddR+=FLASH_PAGE_SIZE;
buff+=FLASH_PAGE_SIZE;
}
}
/* ---------------------------------------------------------------------------------------------------
- 函数名称: spi_flash_chip_erase
- 函数功能: 擦除整个芯片的内容
- 创建日期: 2015-09-16
----------------------------------------------------------------------------------------------------*/
extern void spi_flash_chip_erase(void)
{
uint32_t bWk, cWk;
__read_hw_reg32(SSI0_CTRL0 , bWk);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_DMAS , 0x00);
__write_hw_reg32(SSI0_CTRL0 , 0x07); /* 8bit SPI data */
__write_hw_reg32(SSI0_EN , 0x01);
__write_hw_reg32(SSI0_DATA, CMD_CHIP_ERASE);
do {
__read_hw_reg32(SSI0_STS, cWk);
}while((cWk&0x05) != 0x04);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_CTRL0 , bWk);
}
__RAM_CODE void spi_flash_Read_Page(uint32_t addr, uint8_t *buff)
{
uint32_t iWK = 0;
txbuff[1] = (uint8_t)(addr>>16);
txbuff[0] = CMD_READ_DATA;
txbuff[3] = (uint8_t)(addr);
txbuff[2] = (uint8_t)(addr>>8);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_DMAS , 0x03);
__write_hw_reg32(SSI0_DMATDL, 0x4); //-
__write_hw_reg32(SSI0_DMARDL, 0x4); //- 1/4 FIFO
__write_hw_reg32(SSI0_EN , 0x01);
//- RX Channel
__write_hw_reg32(DMAS_CHx_SAR(10) , 0x40013060);
__write_hw_reg32(DMAS_CHx_DAR(10) , (uint32_t)rxbuff);
__write_hw_reg32(DMAS_CHx_CTL1(10) ,((2 << 8)| 0));
__write_hw_reg32(DMAS_CHx_CTL0(10) ,(PACKET_FULL_LEN+4));
__write_hw_reg32(DMAS_EN , 10);
//- TX Channel
__write_hw_reg32(DMAS_CHx_SAR(2) , (uint32_t)txbuff);
__write_hw_reg32(DMAS_CHx_DAR(2) , 0x40013060);
__write_hw_reg32(DMAS_CHx_CTL1(2) ,((2 << 8)| 0));
__write_hw_reg32(DMAS_CHx_CTL0(2) ,(PACKET_FULL_LEN+4));
__write_hw_reg32(DMAS_EN , 2);
do {
__read_hw_reg32(DMAS_INT_RAW , iWK);
}while((iWK&0x404) != 0x404);
__write_hw_reg32(DMAS_INT_RAW, 0x404);
__write_hw_reg32(DMAS_CLR , 10);
__write_hw_reg32(DMAS_CLR , 2);
__write_hw_reg32(SSI0_EN , 0x00);
for(int i=0;i<PACKET_FULL_LEN;i++){
buff[i]=rxbuff[i+4];
}
}
void spi_flash_write_page(uint32_t PageAddR, uint8_t *buff)
{
uint32_t addr = PageAddR;
uint32_t iWK = 0;
uint32_t i;
for(i=0; i<PACKET_FULL_LEN; i++){
txbuff[i+4] = buff[i];
}
txbuff[1] = (uint8_t)(addr>>16);
txbuff[0] = CMD_PAGE_PROGRAM;
txbuff[3] = (uint8_t)(addr);
txbuff[2] = (uint8_t)(addr>>8);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_DMAS , 0x03);
__write_hw_reg32(SSI0_DMATDL, 0x4); //-
__write_hw_reg32(SSI0_DMARDL, 0x4); //- 1/2FIFO
__write_hw_reg32(SSI0_EN , 0x01);
//- RX Channel
__write_hw_reg32(DMAS_CHx_SAR(10), 0x40013060);
__write_hw_reg32(DMAS_CHx_DAR(10), (uint32_t)rxbuff);
__write_hw_reg32(DMAS_CHx_CTL1(10),((2 << 8)| 0));
__write_hw_reg32(DMAS_CHx_CTL0(10),(PACKET_FULL_LEN+4));
__write_hw_reg32(DMAS_EN, 10);
//- TX Channel
__write_hw_reg32(DMAS_CHx_SAR(2), (uint32_t)txbuff);
__write_hw_reg32(DMAS_CHx_DAR(2), 0x40013060);
__write_hw_reg32(DMAS_CHx_CTL1(2),((2 << 8)| 0));
__write_hw_reg32(DMAS_CHx_CTL0(2),(PACKET_FULL_LEN+4));
__write_hw_reg32(DMAS_EN, 2);
do {
__read_hw_reg32(DMAS_INT_RAW , iWK);
}while((iWK&0x404) != 0x404);
__write_hw_reg32(DMAS_INT_RAW, 0x404);
__write_hw_reg32(DMAS_CLR , 10);
__write_hw_reg32(DMAS_CLR , 2);
__write_hw_reg32(SSI0_EN , 0x00);
}
//void spi_flash_page_erase(uint32_t addr)
//{
// uint32_t bWk, cWk;
// __read_hw_reg32(SSI0_CTRL0 , bWk);
// __write_hw_reg32(SSI0_EN , 0x00);
// __write_hw_reg32(SSI0_DMAS , 0x00);
// __write_hw_reg32(SSI0_CTRL0 , 0x07); /* 8bit SPI data */
// __write_hw_reg32(SSI0_EN , 0x01);
// __write_hw_reg32(SSI0_DATA, CMD_PAGE_ERASE);
// __write_hw_reg32(SSI0_DATA, (uint8_t)(addr>>16));
// __write_hw_reg32(SSI0_DATA, (uint8_t)(addr>>8));
// __write_hw_reg32(SSI0_DATA, (uint8_t)(addr));
// do {
// __read_hw_reg32(SSI0_STS, cWk);
// }while((cWk&0x05) != 0x04);
// __write_hw_reg32(SSI0_EN , 0x00);
// __write_hw_reg32(SSI0_CTRL0 , bWk);
//}
void spi_flash_sector_erase(uint32_t addr)
{
// if((addr>=(4096+param_backup_addr))&&(addr<(8192+param_backup_addr))) return; //forbid erase the calibration parameter area
uint32_t bWk, cWk;
__read_hw_reg32(SSI0_CTRL0 , bWk);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_DMAS , 0x00);
__write_hw_reg32(SSI0_CTRL0 , 0x07); /* 8bit SPI data */
__write_hw_reg32(SSI0_EN , 0x01);
__write_hw_reg32(SSI0_DATA, CMD_SECTOR_ERASE);
__write_hw_reg32(SSI0_DATA, (uint8_t)(addr>>16));
__write_hw_reg32(SSI0_DATA, (uint8_t)(addr>>8));
__write_hw_reg32(SSI0_DATA, (uint8_t)(addr));
do {
__read_hw_reg32(SSI0_STS, cWk);
}while((cWk&0x05) != 0x04);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_CTRL0 , bWk);
}
void spi_flash_block_erase(uint32_t addr)
{
uint32_t bWk, cWk;
__read_hw_reg32(SSI0_CTRL0 , bWk);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_DMAS , 0x00);
__write_hw_reg32(SSI0_CTRL0 , 0x07); /* 8bit SPI data */
__write_hw_reg32(SSI0_EN , 0x01);
__write_hw_reg32(SSI0_DATA, CMD_BLOCK_ERASE);
__write_hw_reg32(SSI0_DATA, (uint8_t)(addr>>16));
__write_hw_reg32(SSI0_DATA, (uint8_t)(addr>>8));
__write_hw_reg32(SSI0_DATA, (uint8_t)(addr));
do {
__read_hw_reg32(SSI0_STS, cWk);
}while((cWk&0x05) != 0x04);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_CTRL0 , bWk);
}
void spi_flash_write_enable(void)
{
uint32_t bWk, cWk;
__read_hw_reg32(SSI0_CTRL0 , bWk);
__write_hw_reg32(SSI0_EN, 0x00);
__write_hw_reg32(SSI0_DMAS , 0x00);
__write_hw_reg32(SSI0_CTRL0 , 0x07); /* 8bit SPI data */
__write_hw_reg32(SSI0_EN, 0x01);
__write_hw_reg32(SSI0_DATA, CMD_WRITE_ENABLE);
do {
__read_hw_reg32(SSI0_STS, cWk);
}while((cWk&0x05) != 0x04);
__write_hw_reg32(SSI0_EN, 0x00);
__write_hw_reg32(SSI0_CTRL0, bWk);
}
void spi_flash_Release_powerdown(void)
{
uint32_t bWk, cWk;
__read_hw_reg32(SSI0_CTRL0, bWk);
__write_hw_reg32(SSI0_EN, 0x00);
__write_hw_reg32(SSI0_DMAS, 0x00);
__write_hw_reg32(SSI0_CTRL0, 0x07); /* 8bit SPI data */
__write_hw_reg32(SSI0_EN, 0x01);
__write_hw_reg32(SSI0_DATA, CMD_RELEASE_PWRDWN);
do {
__read_hw_reg32(SSI0_STS, cWk);
}while((cWk&0x05) != 0x04);
__write_hw_reg32(SSI0_EN, 0x00);
__write_hw_reg32(SSI0_CTRL0, bWk);
}
void spi_flash_Enter_powerdown(void)
{
uint32_t bWk, cWk;
__read_hw_reg32(SSI0_CTRL0, bWk);
__write_hw_reg32(SSI0_EN, 0x00);
__write_hw_reg32(SSI0_DMAS, 0x00);
__write_hw_reg32(SSI0_CTRL0, 0x07); /* 8bit SPI data */
__write_hw_reg32(SSI0_EN, 0x01);
__write_hw_reg32(SSI0_DATA, CMD_PWRDWN);
do {
__read_hw_reg32(SSI0_STS, cWk);
}while((cWk&0x05) != 0x04);
__write_hw_reg32(SSI0_EN, 0x00);
__write_hw_reg32(SSI0_CTRL0, bWk);
}
uint8_t spi_flash_wait_till_ready (void)
{
uint16_t cmd = (CMD_READ_STATUS<<8);
uint32_t iWK,bWk;
uint16_t dWK = 0;
__read_hw_reg32(SSI0_CTRL0 , bWk);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_CTRL0 , 0x0F); /* 16bit SPI data */
__write_hw_reg32(SSI0_DMAS , 0x00); /* turn off dma*/
__write_hw_reg32(SSI0_DMATDL, 0x0); //-
__write_hw_reg32(SSI0_DMARDL, 0x0); //-
__write_hw_reg32(SSI0_EN , 0x01);
__write_hw_reg32(SSI0_DATA , cmd);
do {
__read_hw_reg32(SSI0_STS, iWK);
}while((iWK&0x05) != 0x04);
__read_hw_reg32(SSI0_DATA , dWK);
__write_hw_reg32(SSI0_EN , 0x00);
__write_hw_reg32(SSI0_CTRL0 , bWk);
return (uint8_t)(dWK&0x01);
}
#ifdef TEST_SPI_FLASH
void test_spi_master(void)
{
spi_flash_Release_powerdown();
#ifdef QUAD_ENABLE
if((spi_flash_read_stat()&0x02)==0)
{
printf("\n@@ QUAD ENABLE @@\n");
spi_flash_write_enable();
spi_flash_quad_en();
while(spi_flash_wait_till_ready());
}
printf("s15_8=%#X\n",spi_flash_read_stat());
#endif
uint8_t tx_arr[256];
uint8_t rx_arr[256];
static uint8_t flag=0;
printf("capacity=%#X\n",spi_flash_read_identific());
/*read a page*/
spi_flash_Read_Page(0*4096,rx_arr);
for(int i=0;i<256;i++) printf("%02x ",rx_arr[i]);
printf("\n*****************#*******************\n");
if(flag){
flag=0;
for(int i=0; i<256; i++) tx_arr[i]=i;
}else{
for(int i=0; i<256; i++) tx_arr[i]=255-i;
flag=1;
}
/*erase a page/sector*/
spi_flash_write_enable();
spi_flash_sector_erase(31*4096); //spi_flash_page_erase(31*4096);
while(spi_flash_wait_till_ready());
/*write a page*/
spi_flash_write_enable();
spi_flash_write_page(31*4096,tx_arr);
while(spi_flash_wait_till_ready());
/*read a page*/
spi_flash_Read_Page(31*4096,rx_arr);
for(int i=0;i<256;i++) printf("%02x ",rx_arr[i]);
printf("\n*****************@*******************\n");
//
spi_flash_Enter_powerdown();
}
#endif