risc-v/esp32c3: Enable booting from MCUboot bootloader

Signed-off-by: Gustavo Henrique Nihei <gustavo.nihei@espressif.com>
This commit is contained in:
Gustavo Henrique Nihei
2021-09-10 13:29:22 -03:00
committed by Xiang Xiao
parent 17ec1d04c0
commit 3c63cb522c
10 changed files with 1009 additions and 64 deletions

View File

@@ -35,17 +35,83 @@
#include "esp32c3_lowputc.h"
#include "esp32c3_start.h"
#include "esp32c3_wdt.h"
#include "hardware/esp32c3_cache_memory.h"
#include "hardware/extmem_reg.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_DEBUG_FEATURES
# define showprogress(c) riscv_lowputc(c)
# define showprogress(c) riscv_lowputc(c)
#else
# define showprogress(c)
#endif
#ifdef CONFIG_ESP32C3_APP_FORMAT_MCUBOOT
#define PRIMARY_SLOT_OFFSET CONFIG_ESP32C3_OTA_PRIMARY_SLOT_OFFSET
#define HDR_ATTR __attribute__((section(".entry_addr"))) \
__attribute__((used))
/* Cache MMU block size */
#define MMU_BLOCK_SIZE 0x00010000 /* 64 KB */
/* Cache MMU address mask (MMU tables ignore bits which are zero) */
#define MMU_FLASH_MASK (~(MMU_BLOCK_SIZE - 1))
#endif
/****************************************************************************
* Private Types
****************************************************************************/
#ifdef CONFIG_ESP32C3_APP_FORMAT_MCUBOOT
extern uint32_t _image_irom_vma;
extern uint32_t _image_irom_lma;
extern uint32_t _image_irom_size;
extern uint32_t _image_drom_vma;
extern uint32_t _image_drom_lma;
extern uint32_t _image_drom_size;
#endif
/****************************************************************************
* ROM Function Prototypes
****************************************************************************/
#ifdef CONFIG_ESP32C3_APP_FORMAT_MCUBOOT
extern int ets_printf(const char *fmt, ...);
extern uint32_t cache_suspend_icache(void);
extern void cache_resume_icache(uint32_t val);
extern void cache_invalidate_icache_all(void);
extern int cache_dbus_mmu_set(uint32_t ext_ram, uint32_t vaddr,
uint32_t paddr, uint32_t psize, uint32_t num,
uint32_t fixed);
extern int cache_ibus_mmu_set(uint32_t ext_ram, uint32_t vaddr,
uint32_t paddr, uint32_t psize, uint32_t num,
uint32_t fixed);
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
#ifdef CONFIG_ESP32C3_APP_FORMAT_MCUBOOT
IRAM_ATTR noreturn_function void __start(void);
#endif
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef CONFIG_ESP32C3_APP_FORMAT_MCUBOOT
HDR_ATTR static void (*_entry_point)(void) = &__start;
#endif
/****************************************************************************
* Public Data
****************************************************************************/
@@ -56,6 +122,101 @@ uint8_t g_idlestack[CONFIG_IDLETHREAD_STACKSIZE]
aligned_data(16) locate_data(".noinit");
uint32_t g_idle_topstack = ESP32C3_IDLESTACK_TOP;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: calc_mmu_pages
*
* Description:
* Calculate the number of cache pages to map.
*
* Input Parameters:
* size - Size of data to map
* vaddr - Virtual address where data will be mapped
*
* Returned Value:
* Number of cache MMU pages required to do the mapping.
*
****************************************************************************/
#ifdef CONFIG_ESP32C3_APP_FORMAT_MCUBOOT
static inline uint32_t calc_mmu_pages(uint32_t size, uint32_t vaddr)
{
return (size + (vaddr - (vaddr & MMU_FLASH_MASK)) + MMU_BLOCK_SIZE - 1) /
MMU_BLOCK_SIZE;
}
#endif
/****************************************************************************
* Name: map_rom_segments
*
* Description:
* Configure the MMU and Cache peripherals for accessing ROM code and data.
*
* Input Parameters:
* None.
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_ESP32C3_APP_FORMAT_MCUBOOT
static int map_rom_segments(void)
{
uint32_t rc = 0;
uint32_t regval;
uint32_t drom_lma_aligned;
uint32_t drom_vma_aligned;
uint32_t drom_page_count;
uint32_t irom_lma_aligned;
uint32_t irom_vma_aligned;
uint32_t irom_page_count;
size_t partition_offset = PRIMARY_SLOT_OFFSET;
uint32_t app_irom_lma = partition_offset + (uint32_t)&_image_irom_lma;
uint32_t app_irom_size = (uint32_t)&_image_irom_size;
uint32_t app_irom_vma = (uint32_t)&_image_irom_vma;
uint32_t app_drom_lma = partition_offset + (uint32_t)&_image_drom_lma;
uint32_t app_drom_size = (uint32_t)&_image_drom_size;
uint32_t app_drom_vma = (uint32_t)&_image_drom_vma;
uint32_t autoload = cache_suspend_icache();
cache_invalidate_icache_all();
/* Clear the MMU entries that are already set up, so the new app only has
* the mappings it creates.
*/
for (size_t i = 0; i < FLASH_MMU_TABLE_SIZE; i++)
{
FLASH_MMU_TABLE[i] = MMU_TABLE_INVALID_VAL;
}
drom_lma_aligned = app_drom_lma & MMU_FLASH_MASK;
drom_vma_aligned = app_drom_vma & MMU_FLASH_MASK;
drom_page_count = calc_mmu_pages(app_drom_size, app_drom_vma);
rc = cache_dbus_mmu_set(MMU_ACCESS_FLASH, drom_vma_aligned,
drom_lma_aligned, 64, (int)drom_page_count, 0);
irom_lma_aligned = app_irom_lma & MMU_FLASH_MASK;
irom_vma_aligned = app_irom_vma & MMU_FLASH_MASK;
irom_page_count = calc_mmu_pages(app_irom_size, app_irom_vma);
rc |= cache_ibus_mmu_set(MMU_ACCESS_FLASH, irom_vma_aligned,
irom_lma_aligned, 64, (int)irom_page_count, 0);
regval = getreg32(EXTMEM_ICACHE_CTRL1_REG);
regval &= ~(EXTMEM_ICACHE_SHUT_IBUS_M | EXTMEM_ICACHE_SHUT_DBUS_M);
putreg32(regval, EXTMEM_ICACHE_CTRL1_REG);
cache_resume_icache(autoload);
return (int)rc;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -66,7 +227,14 @@ uint32_t g_idle_topstack = ESP32C3_IDLESTACK_TOP;
void __esp32c3_start(void)
{
uint32_t *dest;
#ifdef CONFIG_ESP32C3_APP_FORMAT_MCUBOOT
if (map_rom_segments() != 0)
{
ets_printf("Failed to setup XIP, aborting\n");
while (true);
}
#endif
/* Set CPU frequency */
@@ -88,7 +256,7 @@ void __esp32c3_start(void)
* certain that there are no issues with the state of global variables.
*/
for (dest = &_sbss; dest < &_ebss; dest++)
for (uint32_t *dest = &_sbss; dest < &_ebss; dest++)
{
*dest = 0;
}