mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-22 17:12:55 +08:00
441 lines
7.1 KiB
C
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;
|
|
} |