mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge #19079
19079: cpu/esp32: add periph_flashpage support r=kaspar030 a=gschorcht ### Contribution description This PR provides the `periph_flashpage` support for ESP32x SoCs. For byte-aligned read access to constant data in the flash, the MMU of all ESP32x SoCs allows to map a certain number of 64 kByte pages of the flash into the data address space of the CPU. This address space is called DROM. Normally the whole DROM address space is assigned to the section `.rodata`. The default flash layout used by all ESP32x SoCs is: | Address in Flash | Content | |:-----------------------|:-----------| | `0x0000` or `0x1000` | bootloader | | `0x8000` | parition table | | `0x9000` | `nvs` parition with WiFi data | | `0xf000` | `phy_init` partition with RF data | | `0x10000` | `factory` partition with the app image | The factory partition consists of a number of 64 kByte pages for the sections `.text`, `.rodata`, `.bss` and others. The `.text` and `rodata` sections are page-aligned and are simply mapped into the instruction address space (IROM) and the data address space (DROM), respectively. All other sections are loaded into RAM. If the `periph_flashpage` module is used, the `periph_flashpage` driver - decreases the size of the `.rodata` section in DROM address space by `CONFIG_ESP_FLASHPAGE_CAPACITY`, - adds a section `.flashpage.writable` of size `CONFIG_ESP_FLASHPAGE_CAPACITY` at the end of DROM address space that is mapped into data address space of the CPU, - reserves a region of size `CONFIG_ESP_FLASHPAGE_CAPACITY` starting from `0x10000` in front of the image partition `factory` and - moves the image partition `factory` by `CONFIG_ESP_FLASHPAGE_CAPACITY` to address `0x10000 + CONFIG_ESP_FLASHPAGE_CAPACITY`. The new flash layout is then: | Address in Flash | Content | |:-----------------------|:-----------| | `0x0000` or `0x1000` | bootloader | | `0x8000` | parition table | | `0x9000` | `nvs` parition with WiFi data | | `0xf000` | `phy_init` partition with RF data | | `0x10000` | flashpage region | | `0x10000 + CONFIG_ESP_FLASHPAGE_CAPACITY` | `factory` partition with the app image | This guarantees that the flash pages are not overwritten if a new app image with changed size is flashed. `CONFIG_ESP_FLASHPAGE_CAPACITY` has to be a multiple of 64 kBytes. ~The PR includes PR #19077 and PR #19078 for the moment to be compilable.~ ### Testing procedure The following tests should pass. ``` USEMODULE='esp_log_startup ps shell_cmds_default' BOARD=esp32-wroom-32 make -j8 -C tests/periph_flashpage flash term ``` ``` USEMODULE='esp_log_startup ps shell_cmds_default' BOARD=esp32-wroom-32 make -j8 -C tests/mtd_flashpage flash term ``` ### Issues/PRs references Depends on PR #19077 Depends on PR #19078 Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
This commit is contained in:
commit
7855aad7e4
@ -17,6 +17,9 @@ config CPU_FAM_ESP32
|
||||
select HAS_ESP_BLE_ESP32
|
||||
select HAS_ESP_HW_COUNTER
|
||||
select HAS_ESP_WIFI_ENTERPRISE
|
||||
select HAS_PERIPH_FLASHPAGE
|
||||
select HAS_PERIPH_FLASHPAGE_IN_ADDRESS_SPACE
|
||||
select HAS_PERIPH_FLASHPAGE_PAGEWISE
|
||||
select HAS_PERIPH_GPIO_LL
|
||||
select HAS_PERIPH_GPIO_LL_IRQ
|
||||
select HAS_PERIPH_GPIO_LL_IRQ_LEVEL_TRIGGERED_HIGH
|
||||
|
@ -18,6 +18,9 @@ config CPU_FAM_ESP32C3
|
||||
select HAS_ESP_BLE
|
||||
select HAS_ESP_BLE_ESP32C3
|
||||
select HAS_ESP_WIFI_ENTERPRISE
|
||||
select HAS_PERIPH_FLASHPAGE
|
||||
select HAS_PERIPH_FLASHPAGE_IN_ADDRESS_SPACE
|
||||
select HAS_PERIPH_FLASHPAGE_PAGEWISE
|
||||
select HAS_PERIPH_GPIO_LL
|
||||
select HAS_PERIPH_GPIO_LL_IRQ
|
||||
select HAS_PERIPH_GPIO_LL_IRQ_LEVEL_TRIGGERED_HIGH
|
||||
|
@ -13,6 +13,9 @@ config CPU_FAM_ESP32S2
|
||||
select HAS_CPU_ESP32
|
||||
select HAS_ESP_HW_COUNTER
|
||||
select HAS_ESP_WIFI_ENTERPRISE
|
||||
select HAS_PERIPH_FLASHPAGE
|
||||
select HAS_PERIPH_FLASHPAGE_IN_ADDRESS_SPACE
|
||||
select HAS_PERIPH_FLASHPAGE_PAGEWISE
|
||||
select HAS_PERIPH_GPIO_LL
|
||||
select HAS_PERIPH_GPIO_LL_IRQ
|
||||
select HAS_PERIPH_GPIO_LL_IRQ_LEVEL_TRIGGERED_HIGH
|
||||
|
@ -19,6 +19,9 @@ config CPU_FAM_ESP32S3
|
||||
select HAS_ESP_BLE_ESP32C3
|
||||
select HAS_ESP_HW_COUNTER
|
||||
select HAS_ESP_WIFI_ENTERPRISE
|
||||
select HAS_PERIPH_FLASHPAGE
|
||||
select HAS_PERIPH_FLASHPAGE_IN_ADDRESS_SPACE
|
||||
select HAS_PERIPH_FLASHPAGE_PAGEWISE
|
||||
select HAS_PERIPH_GPIO_LL
|
||||
select HAS_PERIPH_GPIO_LL_IRQ
|
||||
select HAS_PERIPH_GPIO_LL_IRQ_LEVEL_TRIGGERED_HIGH
|
||||
|
@ -128,7 +128,7 @@ ifneq (,$(filter esp_idf_heap,$(USEMODULE)))
|
||||
USEPKG += tlsf
|
||||
endif
|
||||
|
||||
ifneq (,$(filter mtd,$(USEMODULE)))
|
||||
ifneq (,$(filter mtd periph_flashpage,$(USEMODULE)))
|
||||
USEMODULE += esp_idf_spi_flash
|
||||
endif
|
||||
|
||||
|
@ -17,6 +17,9 @@ include $(RIOTCPU)/esp_common/Makefile.features
|
||||
|
||||
FEATURES_PROVIDED += arch_esp32
|
||||
FEATURES_PROVIDED += esp_wifi_enterprise
|
||||
FEATURES_PROVIDED += periph_flashpage
|
||||
FEATURES_PROVIDED += periph_flashpage_in_address_space
|
||||
FEATURES_PROVIDED += periph_flashpage_pagewise
|
||||
FEATURES_PROVIDED += periph_gpio_ll
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_high
|
||||
|
@ -23,6 +23,38 @@ else ifneq (,$(filter esp32s2,$(CPU_FAM)))
|
||||
else
|
||||
$(error Unkwnown ESP32x SoC variant (family))
|
||||
endif
|
||||
|
||||
ifneq (,$(filter periph_flashpage,$(USEMODULE)))
|
||||
ifneq (,$(CONFIG_ESP_FLASHPAGE_CAPACITY_64K))
|
||||
FLASHFILE_POS = 0x20000
|
||||
FLASHPAGE_CAP = 0x10000
|
||||
else ifneq (,$(CONFIG_ESP_FLASHPAGE_CAPACITY_128K))
|
||||
FLASHFILE_POS = 0x30000
|
||||
FLASHPAGE_CAP = 0x20000
|
||||
else ifneq (,$(CONFIG_ESP_FLASHPAGE_CAPACITY_256K))
|
||||
FLASHFILE_POS = 0x50000
|
||||
FLASHPAGE_CAP = 0x40000
|
||||
else ifneq (,$(CONFIG_ESP_FLASHPAGE_CAPACITY_512K))
|
||||
FLASHFILE_POS = 0x90000
|
||||
FLASHPAGE_CAP = 0x80000
|
||||
else ifneq (,$(CONFIG_ESP_FLASHPAGE_CAPACITY_1M))
|
||||
FLASHFILE_POS = 0x110000
|
||||
FLASHPAGE_CAP = 0x100000
|
||||
else ifneq (,$(CONFIG_ESP_FLASHPAGE_CAPACITY_2M))
|
||||
FLASHFILE_POS = 0x210000
|
||||
FLASHPAGE_CAP = 0x200000
|
||||
else
|
||||
# use 512 kByte for periph_flashpage by default
|
||||
FLASHFILE_POS = 0x90000
|
||||
FLASHPAGE_CAP = 0x80000
|
||||
CFLAGS += -DCONFIG_ESP_FLASHPAGE_CAPACITY_512K
|
||||
endif
|
||||
FLASHPAGE_ADDR_START = 0x10000
|
||||
FLASHPAGE_ADDR_END = $(FLASHFILE_POS)
|
||||
CFLAGS += -DFLASHPAGE_ADDR_START=$(FLASHPAGE_ADDR_START)
|
||||
CFLAGS += -DFLASHPAGE_ADDR_END=$(FLASHPAGE_ADDR_END)
|
||||
endif
|
||||
|
||||
FLASHFILE_POS ?= 0x10000
|
||||
|
||||
ESPTOOL ?= $(RIOTTOOLS)/esptools/esptool_v3.2.py
|
||||
@ -76,6 +108,7 @@ INCLUDES += -I$(ESP32_SDK_DIR)/components/log/include
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/newlib/platform_include
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/soc/include
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/soc/$(CPU_FAM)/include
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/spi_flash/include
|
||||
|
||||
ifneq (,$(filter riscv32%,$(TARGET_ARCH)))
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/riscv/include
|
||||
|
@ -13,7 +13,7 @@ config MODULE_ESP_IDF
|
||||
default y
|
||||
select MODULE_ESP_IDF_COMMON
|
||||
select MODULE_ESP_IDF_EFUSE
|
||||
select MODULE_ESP_IDF_SPI_FLASH if MODULE_MTD
|
||||
select MODULE_ESP_IDF_SPI_FLASH if MODULE_MTD || MODULE_PERIPH_FLASHPAGE
|
||||
select MODULE_ESP_IDF_USB if MODULE_TINYUSB_PORTABLE_ESPRESSIF
|
||||
help
|
||||
Espressif IoT Development Framework.
|
||||
|
@ -22,6 +22,10 @@
|
||||
#ifndef CPU_CONF_H
|
||||
#define CPU_CONF_H
|
||||
|
||||
#if !defined(__ASSEMBLER__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Stack size configuration
|
||||
* @{
|
||||
@ -60,6 +64,41 @@
|
||||
*/
|
||||
#define PUF_SRAM_ATTRIBUTES __attribute__((used, section(".noinit")))
|
||||
|
||||
/**
|
||||
* @brief Support of unaligned access
|
||||
*
|
||||
* All ESP32x SoCs allow unaligned read/write access to the RAM as well as
|
||||
* unaligned read access to the constant data in the flash, which is accessible
|
||||
* via the data bus and mapped by the MMU into the data address space of
|
||||
* the CPU.
|
||||
*/
|
||||
#define CPU_HAS_UNALIGNED_ACCESS 1
|
||||
|
||||
/**
|
||||
* @name Flash page configuration
|
||||
* @{
|
||||
*/
|
||||
#if !DOXYGEN && !defined(__ASSEMBLER__)
|
||||
/* start address of flash pages in CPU address space as determined by the linker */
|
||||
extern uint8_t _fp_mem_start;
|
||||
#endif
|
||||
|
||||
#define FLASHPAGE_SIZE (4096U) /**< Size of pages (flash sectors) in bytes */
|
||||
#define FLASHPAGE_WRITE_BLOCK_SIZE (4U) /**< Minimum write block size */
|
||||
#define FLASHPAGE_WRITE_BLOCK_ALIGNMENT (4U) /**< Write block alignment */
|
||||
|
||||
/**
|
||||
* @brief Number of pages
|
||||
*/
|
||||
#define FLASHPAGE_NUMOF (CONFIG_ESP_FLASHPAGE_CAPACITY / FLASHPAGE_SIZE)
|
||||
|
||||
/**
|
||||
* @brief CPU base address for flash page access as determined by the linker
|
||||
*/
|
||||
#define CPU_FLASH_BASE ((uint32_t)&_fp_mem_start)
|
||||
|
||||
/** @} */
|
||||
|
||||
/* include ESP32x SoC specific compile time configurations */
|
||||
#if defined(CPU_FAM_ESP32)
|
||||
#include "cpu_conf_esp32.h"
|
||||
|
@ -206,6 +206,33 @@
|
||||
#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE
|
||||
#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER CONFIG_ESP_PHY_MAX_WIFI_TX_POWER
|
||||
|
||||
/**
|
||||
* Flashpage configuration
|
||||
*/
|
||||
#ifndef CONFIG_ESP_FLASHPAGE_CAPACITY
|
||||
|
||||
#ifdef MODULE_PERIPH_FLASHPAGE
|
||||
#if CONFIG_ESP_FLASHPAGE_CAPACITY_64K
|
||||
#define CONFIG_ESP_FLASHPAGE_CAPACITY 0x10000
|
||||
#elif CONFIG_ESP_FLASHPAGE_CAPACITY_128K
|
||||
#define CONFIG_ESP_FLASHPAGE_CAPACITY 0x20000
|
||||
#elif CONFIG_ESP_FLASHPAGE_CAPACITY_256K
|
||||
#define CONFIG_ESP_FLASHPAGE_CAPACITY 0x40000
|
||||
#elif CONFIG_ESP_FLASHPAGE_CAPACITY_512K
|
||||
#define CONFIG_ESP_FLASHPAGE_CAPACITY 0x80000
|
||||
#elif CONFIG_ESP_FLASHPAGE_CAPACITY_1M
|
||||
#define CONFIG_ESP_FLASHPAGE_CAPACITY 0x100000
|
||||
#elif CONFIG_ESP_FLASHPAGE_CAPACITY_2M
|
||||
#define CONFIG_ESP_FLASHPAGE_CAPACITY 0x200000
|
||||
#else
|
||||
#define CONFIG_ESP_FLASHPAGE_CAPACITY 0x80000
|
||||
#endif
|
||||
#else /* MODULE_PERIPH_FLASHPAGE_IN_ADDRESS_SPACE */
|
||||
#define CONFIG_ESP_FLASHPAGE_CAPACITY 0x0
|
||||
#endif /* MODULE_PERIPH_FLASHPAGE_IN_ADDRESS_SPACE */
|
||||
|
||||
#endif /* !CONFIG_ESP_FLASHPAGE_CAPACITY */
|
||||
|
||||
#endif /* DOXYGEN */
|
||||
|
||||
/**
|
||||
|
@ -84,9 +84,16 @@ MEMORY
|
||||
|
||||
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped constant data */
|
||||
#ifdef MODULE_PERIPH_FLASHPAGE
|
||||
drom0_0_seg (R) : org = 0x3F400020,
|
||||
len = 0x400000 - 0x20 - CONFIG_ESP_FLASHPAGE_CAPACITY
|
||||
drom0_1_seg (R) : org = ORIGIN(drom0_0_seg) + LENGTH(drom0_0_seg),
|
||||
len = CONFIG_ESP_FLASHPAGE_CAPACITY
|
||||
#else
|
||||
drom0_0_seg (R) : org = 0x3F400020, len = 0x400000-0x20
|
||||
|
||||
/* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
|
||||
#endif /* MODULE_PERIPH_FLASHPAGE */
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
/* RTC fast memory (executable). Persists over deep sleep.
|
||||
|
@ -466,7 +466,6 @@ SECTIONS
|
||||
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||
} >default_rodata_seg
|
||||
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
{
|
||||
_flash_rodata_start = ABSOLUTE(.);
|
||||
@ -617,6 +616,17 @@ SECTIONS
|
||||
_heap_start = ABSOLUTE(.);
|
||||
_sheap = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
|
||||
#ifdef MODULE_PERIPH_FLASHPAGE
|
||||
.flash_writable (NOLOAD) : ALIGN(65536)
|
||||
{
|
||||
_fp_mem_start = . ;
|
||||
KEEP(*(SORT(.flash_writable.*)))
|
||||
_fp_mem_end = . ;
|
||||
. = ALIGN(4096);
|
||||
_end_fw = . ;
|
||||
} > drom0_1_seg
|
||||
#endif
|
||||
}
|
||||
|
||||
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
||||
|
@ -72,9 +72,16 @@ MEMORY
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped constant data */
|
||||
#ifdef MODULE_PERIPH_FLASHPAGE
|
||||
drom0_0_seg (R) : org = 0x3C000020,
|
||||
len = 0x800000 - 0x20 - CONFIG_ESP_FLASHPAGE_CAPACITY
|
||||
drom0_1_seg (R) : org = ORIGIN(drom0_0_seg) + LENGTH(drom0_0_seg),
|
||||
len = CONFIG_ESP_FLASHPAGE_CAPACITY
|
||||
#else
|
||||
drom0_0_seg (R) : org = 0x3C000020, len = 0x800000-0x20
|
||||
|
||||
/* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
|
||||
#endif /* MODULE_PERIPH_FLASHPAGE */
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
/**
|
||||
|
@ -599,6 +599,16 @@ SECTIONS
|
||||
} > dram0_0_seg
|
||||
_eheap = phy_param_rom;
|
||||
|
||||
#ifdef MODULE_PERIPH_FLASHPAGE
|
||||
.flash_writable (NOLOAD) : ALIGN(65536)
|
||||
{
|
||||
_fp_mem_start = . ;
|
||||
KEEP(*(SORT(.flash_writable.*)))
|
||||
_fp_mem_end = . ;
|
||||
. = ALIGN(4096);
|
||||
_end_fw = . ;
|
||||
} > drom0_1_seg
|
||||
#endif
|
||||
}
|
||||
|
||||
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
||||
|
@ -90,9 +90,16 @@ MEMORY
|
||||
|
||||
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped constant data */
|
||||
#ifdef MODULE_PERIPH_FLASHPAGE
|
||||
drom0_0_seg (R) : org = 0x3F000020,
|
||||
len = 0x3f0000-0x20 - CONFIG_ESP_FLASHPAGE_CAPACITY
|
||||
drom0_1_seg (R) : org = ORIGIN(drom0_0_seg) + LENGTH(drom0_0_seg),
|
||||
len = CONFIG_ESP_FLASHPAGE_CAPACITY
|
||||
#else
|
||||
drom0_0_seg (R) : org = 0x3F000020, len = 0x3f0000-0x20
|
||||
|
||||
/* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
|
||||
#endif /* MODULE_PERIPH_FLASHPAGE */
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
/* RTC fast memory (executable). Persists over deep sleep.
|
||||
|
@ -592,6 +592,17 @@ SECTIONS
|
||||
|
||||
. = _heap_end;
|
||||
_eheap = ABSOLUTE(.);
|
||||
|
||||
#ifdef MODULE_PERIPH_FLASHPAGE
|
||||
.flash_writable (NOLOAD) : ALIGN(65536)
|
||||
{
|
||||
_fp_mem_start = . ;
|
||||
KEEP(*(SORT(.flash_writable.*)))
|
||||
_fp_mem_end = . ;
|
||||
. = ALIGN(4096);
|
||||
_end_fw = . ;
|
||||
} > drom0_1_seg
|
||||
#endif
|
||||
}
|
||||
|
||||
ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
||||
|
@ -90,9 +90,16 @@ MEMORY
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
/* Flash mapped constant data */
|
||||
#ifdef MODULE_PERIPH_FLASHPAGE
|
||||
drom0_0_seg (R) : org = 0x3C000020,
|
||||
len = 0x800000-0x20 - CONFIG_ESP_FLASHPAGE_CAPACITY
|
||||
drom0_1_seg (R) : org = ORIGIN(drom0_0_seg) + LENGTH(drom0_0_seg),
|
||||
len = CONFIG_ESP_FLASHPAGE_CAPACITY
|
||||
#else
|
||||
drom0_0_seg (R) : org = 0x3C000020, len = 0x800000-0x20
|
||||
|
||||
/* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
|
||||
#endif /* MODULE_PERIPH_FLASHPAGE */
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
/**
|
||||
|
@ -619,6 +619,17 @@ SECTIONS
|
||||
|
||||
. = _heap_end;
|
||||
_eheap = ABSOLUTE(.);
|
||||
|
||||
#ifdef MODULE_PERIPH_FLASHPAGE
|
||||
.flash_writable (NOLOAD) : ALIGN(65536)
|
||||
{
|
||||
_fp_mem_start = . ;
|
||||
KEEP(*(SORT(.flash_writable.*)))
|
||||
_fp_mem_end = . ;
|
||||
. = ALIGN(4096);
|
||||
_end_fw = . ;
|
||||
} > drom0_1_seg
|
||||
#endif
|
||||
}
|
||||
|
||||
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
||||
|
@ -31,4 +31,22 @@ config MODULE_ESP_HW_COUNTER
|
||||
registers that can be used as low-level timer peripherals. Use this
|
||||
option to enable these CCOUNT and CCOMPARE register as low-level timer.
|
||||
|
||||
choice ESP_FLASHPAGE_CAPACITY
|
||||
bool "Flashpage capacity"
|
||||
default ESP_FLASHPAGE_CAPACITY_512K
|
||||
depends on MODULE_PERIPH_FLASHPAGE
|
||||
config ESP_FLASHPAGE_CAPACITY_64K
|
||||
bool "64 kByte"
|
||||
config ESP_FLASHPAGE_CAPACITY_128K
|
||||
bool "128 kByte"
|
||||
config ESP_FLASHPAGE_CAPACITY_256K
|
||||
bool "256 kByte"
|
||||
config ESP_FLASHPAGE_CAPACITY_512K
|
||||
bool "512 kByte"
|
||||
config ESP_FLASHPAGE_CAPACITY_1M
|
||||
bool "1 MByte"
|
||||
config ESP_FLASHPAGE_CAPACITY_2M
|
||||
bool "2 MByte"
|
||||
endchoice
|
||||
|
||||
endif # TEST_KCONFIG
|
||||
|
161
cpu/esp32/periph/flashpage.c
Normal file
161
cpu/esp32/periph/flashpage.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Gunar Schorcht
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_esp32
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the peripheral flashpage interface
|
||||
*
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "architecture.h"
|
||||
#include "cpu.h"
|
||||
#include "irq.h"
|
||||
#include "periph/flashpage.h"
|
||||
|
||||
#include "irq.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "rom/cache.h"
|
||||
#include "rom/spi_flash.h"
|
||||
#include "soc/mmu.h"
|
||||
#include "soc/soc.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
|
||||
#define ESP_PART_ENTRY_MAGIC ESP_PARTITION_MAGIC
|
||||
|
||||
extern uint8_t _fp_mem_start; /* start address in CPU address space */
|
||||
extern uint8_t _fp_mem_end;
|
||||
extern uint8_t _end_fw;
|
||||
|
||||
static uint32_t _fp_flash_start; /* start address in flash */
|
||||
|
||||
void IRAM_ATTR esp_flashpage_init(void)
|
||||
{
|
||||
/* CONFIG_ESP_FLASHPAGE_CAPACITY has to be a multiple of SPI_FLASH_MMU_PAGE_SIZE */
|
||||
assert((CONFIG_ESP_FLASHPAGE_CAPACITY % SPI_FLASH_MMU_PAGE_SIZE) == 0);
|
||||
|
||||
DEBUG("%s pages in CPU address space @0x%08"PRIx32"...0x%08"PRIx32"\n", __func__,
|
||||
CPU_FLASH_BASE, CPU_FLASH_BASE + CONFIG_ESP_FLASHPAGE_CAPACITY - 1);
|
||||
|
||||
_fp_flash_start = FLASHPAGE_ADDR_START;
|
||||
|
||||
DEBUG("%s pages in flash @0x%08"PRIx32"...0x%08"PRIx32"\n", __func__,
|
||||
_fp_flash_start, _fp_flash_start + CONFIG_ESP_FLASHPAGE_CAPACITY - 1);
|
||||
|
||||
uint32_t state = irq_disable();
|
||||
|
||||
uint32_t p_numof = CONFIG_ESP_FLASHPAGE_CAPACITY / SPI_FLASH_MMU_PAGE_SIZE;
|
||||
uint32_t p_addr = FLASHPAGE_ADDR_START;
|
||||
|
||||
#if CPU_FAM_ESP32S2
|
||||
/* ESP32-S2 requires special handling to enable the MMU pages in Cache
|
||||
* explicitly */
|
||||
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
int res = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, (uint32_t)&_fp_mem_start,
|
||||
p_addr, 64, p_numof, 0);
|
||||
Cache_Resume_ICache(autoload);
|
||||
|
||||
DEBUG("%s DCache MMU set paddr=%08x vaddr=%08x size=%d n=%u\n", __func__,
|
||||
p_addr, (uint32_t)&_fp_mem_start, CONFIG_ESP_FLASHPAGE_CAPACITY,
|
||||
p_numof);
|
||||
|
||||
if (res != ESP_OK) {
|
||||
LOG_TAG_ERROR("flashpage",
|
||||
"Could not map MMU pages in DCache, error: %d\n", res);
|
||||
}
|
||||
#else
|
||||
uint32_t p_mmu = ((uint32_t)&_fp_mem_start - SOC_DROM_LOW) / SPI_FLASH_MMU_PAGE_SIZE;
|
||||
|
||||
while (p_numof--) {
|
||||
uint32_t p_flash = p_addr / SPI_FLASH_MMU_PAGE_SIZE;
|
||||
DEBUG("%s map MMU page %"PRIu32" @0x%08"PRIx32" to "
|
||||
"flash page %"PRIu32" @0x%08"PRIx32"\n", __func__,
|
||||
p_mmu, (p_mmu * SPI_FLASH_MMU_PAGE_SIZE) + SOC_DROM_LOW,
|
||||
p_flash, p_flash * SPI_FLASH_MMU_PAGE_SIZE);
|
||||
SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[p_mmu] = SOC_MMU_PAGE_IN_FLASH(p_flash);
|
||||
p_addr += SPI_FLASH_MMU_PAGE_SIZE;
|
||||
p_mmu++;
|
||||
}
|
||||
#endif
|
||||
irq_restore(state);
|
||||
|
||||
if (IS_ACTIVE(ENABLE_DEBUG)) {
|
||||
spi_flash_mmap_dump();
|
||||
}
|
||||
}
|
||||
|
||||
void flashpage_erase(unsigned page)
|
||||
{
|
||||
assert(page < FLASHPAGE_NUMOF);
|
||||
|
||||
uint32_t flash_addr = _fp_flash_start + (page * FLASHPAGE_SIZE);
|
||||
|
||||
DEBUG("%s erase page in flash @0x%08"PRIx32"\n", __func__, flash_addr);
|
||||
|
||||
int res = spi_flash_erase_range(flash_addr, FLASHPAGE_SIZE);
|
||||
if (res != ESP_OK) {
|
||||
LOG_TAG_ERROR("flashpage", "Could not erase page %u, error %d\n",
|
||||
page, res);
|
||||
}
|
||||
}
|
||||
|
||||
void flashpage_write(void *target_addr, const void *data, size_t len)
|
||||
{
|
||||
DEBUG("%s write %u byte from @%p to @%p\n",
|
||||
__func__, len, data, target_addr);
|
||||
|
||||
/* assert multiples of FLASHPAGE_WRITE_BLOCK_SIZE are written */
|
||||
assert(!(len % FLASHPAGE_WRITE_BLOCK_SIZE));
|
||||
|
||||
/* ensure writes to flash are aligned */
|
||||
assert(!((unsigned)target_addr % FLASHPAGE_WRITE_BLOCK_ALIGNMENT));
|
||||
|
||||
/* ensure the length doesn't exceed the actual flash size */
|
||||
assert(((unsigned)target_addr + len) <=
|
||||
(CPU_FLASH_BASE + (FLASHPAGE_SIZE * FLASHPAGE_NUMOF)));
|
||||
|
||||
uint32_t flash_addr = ((uint32_t)target_addr - (uint32_t)&_fp_mem_start) + _fp_flash_start;
|
||||
|
||||
DEBUG("%s write to CPU address @%p (flash @0x%08"PRIx32")\n",
|
||||
__func__, target_addr, flash_addr);
|
||||
|
||||
int res = spi_flash_write(flash_addr, data, len);
|
||||
if (res != ESP_OK) {
|
||||
LOG_TAG_ERROR("flashpage", "Could not write to CPU address @%p "
|
||||
"(flash @0x%08"PRIx32"), error %d\n",
|
||||
target_addr, flash_addr, res);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned flashpage_first_free(void)
|
||||
{
|
||||
/* _end_fw is page aligned */
|
||||
return flashpage_page(&_end_fw);
|
||||
}
|
||||
|
||||
unsigned flashpage_last_free(void)
|
||||
{
|
||||
// return flashpage_page((const void *)SOC_DROM_HIGH) - 1;
|
||||
return flashpage_page((void *)(CPU_FLASH_BASE + CONFIG_ESP_FLASHPAGE_CAPACITY)) - 1;
|
||||
}
|
@ -289,6 +289,11 @@ static NORETURN void IRAM system_init (void)
|
||||
print_board_config();
|
||||
#endif
|
||||
|
||||
#if IS_USED(MODULE_PERIPH_FLASHPAGE)
|
||||
extern void esp_flashpage_init(void);
|
||||
esp_flashpage_init();
|
||||
#endif
|
||||
|
||||
#if IS_USED(MODULE_MTD)
|
||||
/* init flash drive */
|
||||
extern void spi_flash_drive_init (void);
|
||||
|
@ -150,12 +150,22 @@ TEST_EXTRA_FILES += $(FLASHFILE) $(BINDIR)/partitions.bin $(BOOTLOADER_BIN)
|
||||
# table setting PARTITION_TABLE_CSV.
|
||||
PARTITION_TABLE_CSV ?= $(BINDIR)/partitions.csv
|
||||
|
||||
ifneq (,$(filter periph_flashpage_in_address_space,$(USEMODULE)))
|
||||
$(BINDIR)/partitions.csv: $(FLASHFILE)
|
||||
$(Q)printf "\n" > $(BINDIR)/partitions.csv
|
||||
$(Q)printf "nvs, data, nvs, 0x9000, 0x6000\n" >> $@
|
||||
$(Q)printf "phy_init, data, phy, 0xf000, 0x1000\n" >> $@
|
||||
$(Q)printf "flashpage, data, phy, $(FLASHPAGE_ADDR_START), $(FLASHPAGE_CAP)\n" >> $@
|
||||
$(Q)printf "factory, app, factory, $(FLASHFILE_POS), " >> $@
|
||||
$(Q)ls -l $< | awk '{ print $$5 }' >> $@
|
||||
else
|
||||
$(BINDIR)/partitions.csv: $(FLASHFILE)
|
||||
$(Q)printf "\n" > $(BINDIR)/partitions.csv
|
||||
$(Q)printf "nvs, data, nvs, 0x9000, 0x6000\n" >> $@
|
||||
$(Q)printf "phy_init, data, phy, 0xf000, 0x1000\n" >> $@
|
||||
$(Q)printf "factory, app, factory, $(FLASHFILE_POS), " >> $@
|
||||
$(Q)ls -l $< | awk '{ print $$5 }' >> $@
|
||||
endif
|
||||
|
||||
$(BINDIR)/partitions.bin: $(PARTITION_TABLE_CSV)
|
||||
$(Q)python3 $(RIOTTOOLS)/esptools/gen_esp32part.py --verify $< $@
|
||||
|
@ -7,6 +7,7 @@ FEATURES_OPTIONAL += periph_flashpage_pagewise
|
||||
FEATURES_OPTIONAL += periph_flashpage_rwee
|
||||
|
||||
USEMODULE += od
|
||||
USEMODULE += od_string
|
||||
USEMODULE += shell
|
||||
|
||||
# avoid running Kconfig by default
|
||||
|
@ -1,5 +1,6 @@
|
||||
# this file enables modules defined in Kconfig. Do not use this file for
|
||||
# application configuration. This is only needed during migration.
|
||||
CONFIG_MODULE_OD=y
|
||||
CONFIG_MODULE_OD_STRING=y
|
||||
CONFIG_MODULE_PERIPH_FLASHPAGE=y
|
||||
CONFIG_MODULE_SHELL=y
|
||||
|
@ -81,31 +81,9 @@ static int getpage(const char *str)
|
||||
}
|
||||
|
||||
#ifdef MODULE_PERIPH_FLASHPAGE_PAGEWISE
|
||||
static void dumpchar(uint8_t mem)
|
||||
{
|
||||
if (mem >= ' ' && mem <= '~') {
|
||||
printf(" %c ", mem);
|
||||
}
|
||||
else {
|
||||
printf(" ?? ");
|
||||
}
|
||||
}
|
||||
|
||||
static void memdump(void *addr, size_t len)
|
||||
{
|
||||
unsigned pos = 0;
|
||||
uint8_t *mem = (uint8_t *)addr;
|
||||
|
||||
while (pos < (unsigned)len) {
|
||||
for (unsigned i = 0; i < LINE_LEN; i++) {
|
||||
printf("0x%02x ", mem[pos + i]);
|
||||
}
|
||||
puts("");
|
||||
for (unsigned i = 0; i < LINE_LEN; i++) {
|
||||
dumpchar(mem[pos++]);
|
||||
}
|
||||
puts("");
|
||||
}
|
||||
od_hex_dump (addr, len, LINE_LEN);
|
||||
}
|
||||
|
||||
static void dump_local(void)
|
||||
|
Loading…
Reference in New Issue
Block a user