feat(spi_flash): Add feature to support flash address and memory address no align writing

This commit is contained in:
Dong Heng
2018-07-10 19:51:12 +08:00
parent cb0c5ee5fc
commit f8c69be477
2 changed files with 99 additions and 50 deletions

View File

@ -30,6 +30,8 @@ extern "C" {
#define SPI_FLASH_SEC_SIZE 4096 /**< SPI Flash sector size */ #define SPI_FLASH_SEC_SIZE 4096 /**< SPI Flash sector size */
#define SPI_READ_BUF_MAX 64
#ifdef CONFIG_ENABLE_FLASH_MMAP #ifdef CONFIG_ENABLE_FLASH_MMAP
/** /**
* @brief Enumeration which specifies memory space requested in an mmap call * @brief Enumeration which specifies memory space requested in an mmap call

View File

@ -100,6 +100,9 @@
#define FLASH_ALIGN_BYTES 4 #define FLASH_ALIGN_BYTES 4
#define FLASH_ALIGN(addr) ((((size_t)addr) + (FLASH_ALIGN_BYTES - 1)) & (~(FLASH_ALIGN_BYTES - 1))) #define FLASH_ALIGN(addr) ((((size_t)addr) + (FLASH_ALIGN_BYTES - 1)) & (~(FLASH_ALIGN_BYTES - 1)))
#define FLASH_ALIGN_BEFORE(addr) (FLASH_ALIGN(addr) - 4)
#define NOT_ALIGN(addr) (((size_t)addr) & (FLASH_ALIGN_BYTES - 1))
#define IS_ALIGN(addr) (NOT_ALIGN(addr) == 0)
enum GD25Q32C_status { enum GD25Q32C_status {
GD25Q32C_STATUS1=0, GD25Q32C_STATUS1=0,
@ -129,6 +132,7 @@ extern uint32_t esp_get_time();
bool IRAM_ATTR spi_user_cmd(spi_cmd_dir_t mode, spi_cmd_t *p_cmd); bool IRAM_ATTR spi_user_cmd(spi_cmd_dir_t mode, spi_cmd_t *p_cmd);
bool special_flash_read_status(uint8_t command, uint32_t* status, int len); bool special_flash_read_status(uint8_t command, uint32_t* status, int len);
bool special_flash_write_status(uint8_t command, uint32_t status, int len, bool write_en); bool special_flash_write_status(uint8_t command, uint32_t status, int len, bool write_en);
esp_err_t spi_flash_read(size_t src_addr, void *dest, size_t size);
uint8_t en25q16x_read_sfdp(); uint8_t en25q16x_read_sfdp();
extern void pp_soft_wdt_feed(void); extern void pp_soft_wdt_feed(void);
@ -148,7 +152,7 @@ uint8_t FlashIsOnGoing = 0;
const char *TAG = "spi_flash"; const char *TAG = "spi_flash";
static esp_err_t IRAM_ATTR SPIWrite(uint32_t target, uint32_t *src_addr, size_t len) esp_err_t IRAM_ATTR SPIWrite(uint32_t target, uint32_t *src_addr, size_t len)
{ {
uint32_t page_size; uint32_t page_size;
uint32_t pgm_len, pgm_num; uint32_t pgm_len, pgm_num;
@ -481,17 +485,30 @@ static esp_err_t IRAM_ATTR spi_flash_write_raw(size_t dest_addr, const void *src
esp_err_t IRAM_ATTR spi_flash_write(size_t dest_addr, const void *src, size_t size) esp_err_t IRAM_ATTR spi_flash_write(size_t dest_addr, const void *src, size_t size)
{ {
#undef FLASH_WRITE
#define FLASH_WRITE(dest, src, size) \ #define FLASH_WRITE(dest, src, size) \
{ \ { \
ret = spi_flash_write_raw(dest, src, size); \ ret = spi_flash_write_raw(dest, src, size); \
pp_soft_wdt_feed(); \ pp_soft_wdt_feed(); \
if (ret) \ if (ret) { \
goto exit; \ return ret; \
} \
}
#undef FLASH_READ
#define FLASH_READ(dest, src, size) \
{ \
ret = spi_flash_read(dest, src, size); \
if (ret) { \
return ret; \
} \
} }
esp_err_t ret = ESP_ERR_FLASH_OP_FAIL; esp_err_t ret = ESP_ERR_FLASH_OP_FAIL;
uint32_t *tmp; uint8_t *tmp = (uint8_t *)src;
size_t before_wbytes, align_wbytes;
if (!size)
return ESP_OK;
if (src == NULL) { if (src == NULL) {
return ESP_ERR_FLASH_OP_FAIL; return ESP_ERR_FLASH_OP_FAIL;
@ -501,41 +518,54 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dest_addr, const void *src, size_t si
return ESP_ERR_FLASH_OP_FAIL; return ESP_ERR_FLASH_OP_FAIL;
} }
if (IS_FLASH(src)) { if (NOT_ALIGN(dest_addr)
tmp = wifi_malloc(size, OSI_MALLOC_CAP_32BIT); || NOT_ALIGN(tmp)
if (!tmp) { || NOT_ALIGN(size)
return ESP_ERR_NO_MEM; || IS_FLASH(src)) {
uint8_t buf[SPI_READ_BUF_MAX];
if (NOT_ALIGN(dest_addr)) {
size_t r_addr = FLASH_ALIGN_BEFORE(dest_addr);
size_t c_off = dest_addr - r_addr;
size_t wbytes = FLASH_ALIGN_BYTES - c_off;
wbytes = wbytes > size ? size : wbytes;
FLASH_READ(r_addr, buf, FLASH_ALIGN_BYTES);
memcpy(&buf[c_off], tmp, wbytes);
FLASH_WRITE(r_addr, buf, FLASH_ALIGN_BYTES);
dest_addr += wbytes;
tmp += wbytes;
size -= wbytes;
} }
memcpy(tmp, src, size);
} else
tmp = (uint32_t *)src;
before_wbytes = FLASH_ALIGN(tmp) == (size_t)tmp ? 0 : FLASH_ALIGN(tmp) - (size_t)tmp; while (size > 0) {
align_wbytes = size - before_wbytes; size_t len = size >= SPI_READ_BUF_MAX ? SPI_READ_BUF_MAX : size;
size_t wlen = FLASH_ALIGN(len);
if (before_wbytes) { if (wlen != len) {
uint8_t load_buf[FLASH_ALIGN_BYTES]; size_t l_b = wlen - FLASH_ALIGN_BYTES;
memcpy(load_buf, tmp, before_wbytes); FLASH_READ(dest_addr + l_b, &buf[l_b], FLASH_ALIGN_BYTES);
FLASH_WRITE(dest_addr, load_buf, FLASH_ALIGN_BYTES); }
memcpy(buf, tmp, len);
FLASH_WRITE(dest_addr, buf, wlen);
dest_addr += len;
tmp += len;
size -= len;
}
} else {
FLASH_WRITE(dest_addr, src, size);
} }
if (align_wbytes) {
void *align_addr = (void *)FLASH_ALIGN(tmp);
if (align_wbytes % FLASH_ALIGN_BYTES)
align_wbytes = (align_wbytes / FLASH_ALIGN_BYTES + 1) * FLASH_ALIGN_BYTES;
FLASH_WRITE(dest_addr + before_wbytes, align_addr, align_wbytes);
}
exit:
if (IS_FLASH(src))
wifi_free(tmp);
return ret; return ret;
} }
/****************************************************************************** /******************************************************************************
* FunctionName : spi_flash_read_raw * FunctionName : spi_flash_read_raw
* Description : a * Description : a
@ -568,42 +598,59 @@ static esp_err_t IRAM_ATTR spi_flash_read_raw(size_t src_addr, void *dest, size_
esp_err_t IRAM_ATTR spi_flash_read(size_t src_addr, void *dest, size_t size) esp_err_t IRAM_ATTR spi_flash_read(size_t src_addr, void *dest, size_t size)
{ {
#undef FLASH_READ
#define FLASH_READ(addr, dest, size) \ #define FLASH_READ(addr, dest, size) \
{ \ { \
ret = spi_flash_read_raw(src_addr, dest, size); \ ret = spi_flash_read_raw(addr, dest, size); \
pp_soft_wdt_feed(); \ pp_soft_wdt_feed(); \
if (ret) \ if (ret) \
return ret; \ return ret; \
} }
esp_err_t ret; esp_err_t ret;
uint8_t load_buf[FLASH_ALIGN_BYTES]; uint8_t *tmp = (uint8_t *)dest;
size_t before_rbytes, after_rbytes, align_rbytes;
if (dest == NULL) { if (!size)
return ESP_OK;
if (tmp == NULL) {
return ESP_ERR_FLASH_OP_FAIL; return ESP_ERR_FLASH_OP_FAIL;
} }
before_rbytes = FLASH_ALIGN(dest) == (size_t)dest ? 0 : FLASH_ALIGN(dest) - (size_t)dest; if (NOT_ALIGN(src_addr)
after_rbytes = (size - before_rbytes) & (FLASH_ALIGN_BYTES - 1); || NOT_ALIGN(tmp)
align_rbytes = size - before_rbytes - after_rbytes; || NOT_ALIGN(size)) {
uint8_t buf[SPI_READ_BUF_MAX];
if (before_rbytes) { if (NOT_ALIGN(src_addr)) {
FLASH_READ(src_addr, load_buf, FLASH_ALIGN_BYTES); size_t r_addr = FLASH_ALIGN_BEFORE(src_addr);
memcpy(dest, &load_buf[FLASH_ALIGN_BYTES - before_rbytes], before_rbytes); size_t c_off = src_addr - r_addr;
} size_t wbytes = FLASH_ALIGN_BYTES - c_off;
if (align_rbytes) { wbytes = wbytes > size ? size : wbytes;
void *align_addr = (void *)FLASH_ALIGN(dest);
FLASH_READ(src_addr + before_rbytes, align_addr, align_rbytes); FLASH_READ(r_addr, buf, FLASH_ALIGN_BYTES);
} memcpy(tmp, &buf[c_off], wbytes);
if (after_rbytes) { tmp += wbytes;
void *after_addr = (void *)FLASH_ALIGN((char *)dest + size - after_rbytes); src_addr += wbytes;
size -= wbytes;
}
FLASH_READ(src_addr + before_rbytes + align_rbytes, load_buf, FLASH_ALIGN_BYTES); while (size) {
memcpy(after_addr, load_buf, after_rbytes); size_t len = size >= SPI_READ_BUF_MAX ? SPI_READ_BUF_MAX : size;
size_t wlen = FLASH_ALIGN(len);
FLASH_READ(src_addr, buf, wlen);
memcpy(tmp, buf, len);
src_addr += len;
tmp += len;
size -= len;
}
} else {
FLASH_READ(src_addr, tmp, size);
} }
return ESP_OK; return ESP_OK;