2022-03-28 17:19:25 +08:00

441 lines
7.1 KiB
C

#include "wm_spi_flash.h"
static SPI_HandleTypeDef hspi;
static uint32_t total_size = 0;
static uint8_t cache[SECTOR_SIZE];
static int fls_drv_read_id(uint8_t *id)
{
uint8_t cmd = EXFLASH_ID;
uint8_t rx[3];
int err;
if (id == NULL)
{
return HAL_ERROR;
}
__HAL_SPI_SET_CS_LOW(&hspi);
err = HAL_SPI_Transmit(&hspi, &cmd, 1, 100);
if (err != HAL_OK)
{
__HAL_SPI_SET_CS_HIGH(&hspi);
return err;
}
err = HAL_SPI_Receive(&hspi, rx, 3, 100);
if (err != HAL_OK)
{
__HAL_SPI_SET_CS_HIGH(&hspi);
return err;
}
__HAL_SPI_SET_CS_HIGH(&hspi);
memcpy(id, rx, 3);
return HAL_OK;
}
static int fls_drv_init(void)
{
uint8_t buf[3];
int err;
hspi.Instance = SPI;
hspi.Init.Mode = SPI_MODE_MASTER;
hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi.Init.NSS = SPI_NSS_SOFT;
hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
if (HAL_SPI_Init(&hspi) != HAL_OK)
{
return HAL_ERROR;
}
err = fls_drv_read_id(buf);
if (err != HAL_OK)
{
return err;
}
if (buf[2])
{
total_size = (1 << buf[2]);
}
else
{
return HAL_ERROR;
}
return HAL_OK;
}
static int fls_drv_write_enable(void)
{
uint8_t cmd;
int err;
cmd = EXFLASH_WRITE_ENABLE;
__HAL_SPI_SET_CS_LOW(&hspi);
err = HAL_SPI_Transmit(&hspi, (uint8_t *)&cmd, 1, 100);
__HAL_SPI_SET_CS_HIGH(&hspi);
if (err != HAL_OK)
{
return err;
}
return HAL_OK;
}
static int fls_drv_wait_write_enable(void)
{
uint8_t cmd, sr = 0;
int err;
cmd = EXFLASH_READ_SR1;
do {
__HAL_SPI_SET_CS_LOW(&hspi);
err = HAL_SPI_Transmit(&hspi, (uint8_t *)&cmd, 1, 100);
if (err != HAL_OK)
{
__HAL_SPI_SET_CS_HIGH(&hspi);
return err;
}
err = HAL_SPI_Receive(&hspi, (uint8_t *)&sr, 1, 100);
if (err != HAL_OK)
{
__HAL_SPI_SET_CS_HIGH(&hspi);
return err;
}
__HAL_SPI_SET_CS_HIGH(&hspi);
if (sr & EXFLASH_STATUS_WEL)
{
break;
}
} while (1);
return HAL_OK;
}
static int fls_drv_wait_flash_ready(void)
{
uint8_t cmd, sr = 0;
int err;
cmd = EXFLASH_READ_SR1;
do {
__HAL_SPI_SET_CS_LOW(&hspi);
err = HAL_SPI_Transmit(&hspi, (uint8_t *)&cmd, 1, 100);
if (err != HAL_OK)
{
__HAL_SPI_SET_CS_HIGH(&hspi);
return err;
}
err = HAL_SPI_Receive(&hspi, (uint8_t *)&sr, 1, 100);
if (err != HAL_OK)
{
__HAL_SPI_SET_CS_HIGH(&hspi);
return err;
}
__HAL_SPI_SET_CS_HIGH(&hspi);
if ((sr & EXFLASH_STATUS_BUSY) == 0x00)
{
break;
}
} while (1);
return HAL_OK;
}
static int fls_drv_read(uint32_t addr, uint8_t *buf, uint32_t len)
{
uint32_t cmd = 0;
int err;
cmd |= EXFLASH_READ_DATA;
cmd |= (swap32(addr) & 0xFFFFFF00);
__HAL_SPI_SET_CS_LOW(&hspi);
err = HAL_SPI_Transmit(&hspi, (uint8_t *)&cmd, 4, 100);
if (err != HAL_OK)
{
__HAL_SPI_SET_CS_HIGH(&hspi);
return err;
}
err = HAL_SPI_Receive(&hspi, buf, len, 1000);
if (err != HAL_OK)
{
__HAL_SPI_SET_CS_HIGH(&hspi);
return err;
}
__HAL_SPI_SET_CS_HIGH(&hspi);
return HAL_OK;
}
static int fls_drv_page_write(uint32_t page, uint8_t *buf)
{
uint32_t cmd = 0;
int err;
err = fls_drv_write_enable();
if (err != HAL_OK)
{
return err;
}
err = fls_drv_wait_write_enable();
if (err != HAL_OK)
{
return err;
}
cmd |= EXFLASH_PAGE_PROGRAM;
cmd |= (swap32(page * PAGE_SIZE) & 0xFFFFFF00);
__HAL_SPI_SET_CS_LOW(&hspi);
err = HAL_SPI_Transmit(&hspi, (uint8_t *)&cmd, 4, 100);
if (err != HAL_OK)
{
__HAL_SPI_SET_CS_HIGH(&hspi);
return err;
}
err = HAL_SPI_Transmit(&hspi, buf, PAGE_SIZE, 1000);
if (err != HAL_OK)
{
__HAL_SPI_SET_CS_HIGH(&hspi);
return err;
}
__HAL_SPI_SET_CS_HIGH(&hspi);
err = fls_drv_wait_flash_ready();
if (err != HAL_OK)
{
return err;
}
return HAL_OK;
}
static int fls_drv_erase(uint32_t sector)
{
uint32_t cmd = 0;
int err;
err = fls_drv_write_enable();
if (err != HAL_OK)
{
return err;
}
err = fls_drv_wait_write_enable();
if (err != HAL_OK)
{
return err;
}
cmd |= EXFLASH_SECTOR_ERASE;
cmd |= (swap32(sector * SECTOR_SIZE) & 0xFFFFFF00);
__HAL_SPI_SET_CS_LOW(&hspi);
err = HAL_SPI_Transmit(&hspi, (uint8_t *)&cmd, 4, 100);
__HAL_SPI_SET_CS_HIGH(&hspi);
if (err != HAL_OK)
{
return err;
}
err = fls_drv_wait_flash_ready();
if (err != HAL_OK)
{
return err;
}
return HAL_OK;
}
static int fls_drv_chip_erase(void)
{
uint32_t cmd = 0;
int err;
err = fls_drv_write_enable();
if (err != HAL_OK)
{
return err;
}
err = fls_drv_wait_write_enable();
if (err != HAL_OK)
{
return err;
}
cmd = EXFLASH_CIHP_ERASE;
__HAL_SPI_SET_CS_LOW(&hspi);
err = HAL_SPI_Transmit(&hspi, (uint8_t *)&cmd, 1, 100);
__HAL_SPI_SET_CS_HIGH(&hspi);
if (err != HAL_OK)
{
return err;
}
err = fls_drv_wait_flash_ready();
if (err != HAL_OK)
{
return err;
}
return HAL_OK;
}
int SPIFLS_Init(void)
{
int err;
err = fls_drv_init();
if (err != HAL_OK)
{
return err;
}
return HAL_OK;
}
int SPIFLS_Read_ID(uint8_t *id)
{
uint8_t rx[3];
int err;
err = fls_drv_read_id(rx);
if (err != HAL_OK)
{
return err;
}
*id = rx[0];
return HAL_OK;
}
int SPIFLS_Page_Write(uint32_t page, uint8_t *buf, uint32_t page_cnt)
{
int i = 0;
int err;
for (i = 0; i < page_cnt; i++)
{
err = fls_drv_page_write(page + i, buf + i * PAGE_SIZE);
if (err != HAL_OK)
{
return err;
}
}
return HAL_OK;
}
int SPIFLS_Read(uint32_t addr, uint8_t *buf, uint32_t len)
{
int err;
if ((addr > total_size) || (buf == NULL) || (len == 0) || ((addr + len) > total_size))
{
return HAL_ERROR;
}
err = fls_drv_read(addr, buf, len);
if (err != HAL_OK)
{
return err;
}
return HAL_OK;
}
int SPIFLS_Write(uint32_t addr, uint8_t *buf, uint32_t len)
{
uint32_t sector_addr, sector_num, i, j;
int err;
if ((addr > total_size) || (buf == NULL) || (len == 0) || ((addr + len) > total_size))
{
return HAL_ERROR;
}
sector_addr = addr / SECTOR_SIZE;
sector_num = (addr + len - 1) / SECTOR_SIZE - sector_addr + 1;
for (i = 0; i < sector_num; i++)
{
err = fls_drv_read((sector_addr + i) * SECTOR_SIZE, cache, SECTOR_SIZE);
if (err != HAL_OK)
{
return err;
}
if (sector_num == 1)
{
memcpy(cache + (addr % SECTOR_SIZE), buf, len);
buf += len;
len = 0;
}
else
{
if (i == 0)
{
memcpy(cache + (addr % SECTOR_SIZE), buf, SECTOR_SIZE - (addr % SECTOR_SIZE));
buf += (SECTOR_SIZE - (addr % SECTOR_SIZE));
len -= (SECTOR_SIZE - (addr % SECTOR_SIZE));
}
else if (i == (sector_num - 1))
{
memcpy(cache, buf, len);
buf += len;
len = 0;
}
else
{
memcpy(cache, buf, SECTOR_SIZE);
buf += SECTOR_SIZE;
len -= SECTOR_SIZE;
}
}
err = fls_drv_erase(sector_addr + i);
if (err != HAL_OK)
{
return err;
}
for (j = 0; j < (SECTOR_SIZE / PAGE_SIZE); j++)
{
err = fls_drv_page_write((sector_addr + i) * (SECTOR_SIZE / PAGE_SIZE) + j, cache + j * PAGE_SIZE);
if (err != HAL_OK)
{
return err;
}
}
}
return HAL_OK;
}
int SPIFLS_Erase(uint32_t sector)
{
int err;
if (sector > (total_size / SECTOR_SIZE))
{
return HAL_ERROR;
}
err = fls_drv_erase(sector);
if (err != HAL_OK)
{
return err;
}
return HAL_OK;
}
int SPIFLS_Chip_Erase(void)
{
int err;
err = fls_drv_chip_erase();
if (err != HAL_OK)
{
return err;
}
return HAL_OK;
}