1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu/esp32: fix periph_flash timing problems

While deleting multiple sectors in flash, interrupts were disabled over the whole time. Thus, deleting the entire flash led to the triggering of the watchdog timer and thus to a restart. Therefore, the interrupts and the cache are disabled only for the time of deleting a single sector. The same problem occurred for read and write large data sets.
This commit is contained in:
Gunar Schorcht 2019-08-20 01:51:05 +02:00
parent f483988ae9
commit 1c60e175ca

View File

@ -20,16 +20,12 @@
#if MODULE_MTD
#define ENABLE_DEBUG (0)
#include "debug.h"
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "esp_common.h"
#include "irq_arch.h"
#include "log.h"
#include "mtd.h"
#include "rom/cache.h"
@ -38,6 +34,9 @@
#include "esp_partition.h"
#include "esp_spi_flash.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define ESP_PART_TABLE_ADDR 0x8000 /* TODO configurable as used in Makefile.include */
#define ESP_PART_TABLE_SIZE 0xC00
#define ESP_PART_ENTRY_SIZE 0x20
@ -169,9 +168,6 @@ esp_err_t IRAM_ATTR spi_flash_read(size_t addr, void *buff, size_t size)
/* size must be within the flash address space */
CHECK_PARAM_RET (addr + size <= _flash_end, -EOVERFLOW);
/* prepare for write access */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
int result = ESP_ROM_SPIFLASH_RESULT_OK;
uint32_t len = size;
@ -182,9 +178,17 @@ esp_err_t IRAM_ATTR spi_flash_read(size_t addr, void *buff, size_t size)
uint32_t len_in_word = 4 - pos_in_word;
len_in_word = (len_in_word < len) ? len_in_word : len;
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
result = esp_rom_spiflash_read (word_addr, (uint32_t*)_flash_buf, 4);
memcpy(buff, _flash_buf + pos_in_word, len_in_word);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
buff = (uint8_t*)buff + len_in_word;
addr += len_in_word;
len -= len_in_word;
@ -198,9 +202,17 @@ esp_err_t IRAM_ATTR spi_flash_read(size_t addr, void *buff, size_t size)
len_full_words = ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM;
}
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
result |= esp_rom_spiflash_read (addr, (uint32_t*)_flash_buf, len_full_words);
memcpy(buff, _flash_buf, len_full_words);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
buff = (uint8_t*)buff + len_full_words;
addr += len_full_words;
len -= len_full_words;
@ -208,13 +220,17 @@ esp_err_t IRAM_ATTR spi_flash_read(size_t addr, void *buff, size_t size)
/* if there is some remaining, we need to prepare last word */
if (len && result == ESP_ROM_SPIFLASH_RESULT_OK) {
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
result |= esp_rom_spiflash_read (addr, (uint32_t*)_flash_buf, 4);
memcpy(buff, _flash_buf, len);
}
/* reset read access */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
}
/* return with the ESP-IDF error code that is mapped from ROM error code */
RETURN_WITH_ESP_ERR_CODE(result);
@ -230,8 +246,6 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t addr, const void *buff, size_t size)
CHECK_PARAM_RET (addr + size <= _flash_end, -EOVERFLOW);
/* prepare for write access */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
int result = esp_rom_spiflash_unlock();
uint32_t len = size;
@ -242,10 +256,18 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t addr, const void *buff, size_t size)
uint32_t len_in_word = 4 - pos_in_word;
len_in_word = (len_in_word < len) ? len_in_word : len;
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
result |= esp_rom_spiflash_read (word_addr, (uint32_t*)_flash_buf, 4);
memcpy(_flash_buf + pos_in_word, buff, len_in_word);
result |= esp_rom_spiflash_write (word_addr, (uint32_t*)_flash_buf, 4);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
buff = (uint8_t*)buff + len_in_word;
addr += len_in_word;
len -= len_in_word;
@ -259,9 +281,17 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t addr, const void *buff, size_t size)
len_full_words = ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM;
}
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
memcpy(_flash_buf, buff, len_full_words);
result |= esp_rom_spiflash_write (addr, (uint32_t*)_flash_buf, len_full_words);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
buff = (uint8_t*)buff + len_full_words;
addr += len_full_words;
len -= len_full_words;
@ -269,15 +299,21 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t addr, const void *buff, size_t size)
/* if there is some remaining, we need to prepare last word */
if (len && result == ESP_ROM_SPIFLASH_RESULT_OK) {
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
result |= esp_rom_spiflash_read (addr, (uint32_t*)_flash_buf, 4);
memcpy(_flash_buf, buff, len);
result |= esp_rom_spiflash_write (addr, (uint32_t*)_flash_buf, 4);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
}
/* reset write access */
esp_rom_spiflash_lock();
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
/* return with the ESP-IDF error code that is mapped from ROM error code */
RETURN_WITH_ESP_ERR_CODE(result);
@ -298,21 +334,26 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(size_t addr, size_t size)
CHECK_PARAM_RET (size % _flashchip->sector_size == 0, -ENOTSUP)
/* prepare for write access */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
uint32_t result = esp_rom_spiflash_unlock();
/* erase as many sectors as necessary */
uint32_t sec = addr / _flashchip->sector_size;
uint32_t cnt = size / _flashchip->sector_size;
while (cnt-- && result == ESP_ROM_SPIFLASH_RESULT_OK) {
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
result = esp_rom_spiflash_erase_sector (sec++);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
}
/* reset write access */
esp_rom_spiflash_lock();
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
/* return with the ESP-IDF error code that is mapped from ROM error code */
RETURN_WITH_ESP_ERR_CODE(result);