217 lines
7.2 KiB
C
217 lines
7.2 KiB
C
/*
|
|
* This file is part of the MicroPython project, http://micropython.org/
|
|
*
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2019-2020 Damien P. George
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
#ifndef MICROPY_INCLUDED_STM32_MBOOT_MBOOT_H
|
|
#define MICROPY_INCLUDED_STM32_MBOOT_MBOOT_H
|
|
|
|
#include "py/mpconfig.h"
|
|
#include "py/mphal.h"
|
|
|
|
// Use this to tag global static data in RAM that doesn't need to be zeroed on startup
|
|
#define SECTION_NOZERO_BSS __attribute__((section(".nozero_bss")))
|
|
|
|
#define ELEM_DATA_SIZE (1024)
|
|
#define ELEM_DATA_START (&_estack[0])
|
|
#define ELEM_DATA_MAX (&_estack[ELEM_DATA_SIZE])
|
|
|
|
#define NORETURN __attribute__((noreturn))
|
|
#define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
|
|
|
// The default UI code in ui.c only works if there is at least one LED configured.
|
|
#if defined(MBOOT_LED1) || defined(MICROPY_HW_LED1)
|
|
#define MBOOT_ENABLE_DEFAULT_UI (1)
|
|
#else
|
|
#define MBOOT_ENABLE_DEFAULT_UI (0)
|
|
#endif
|
|
|
|
#ifndef MBOOT_BOARD_EARLY_INIT
|
|
#define MBOOT_BOARD_EARLY_INIT(initial_r0)
|
|
#endif
|
|
|
|
#ifndef MBOOT_BOARD_ENTRY_INIT
|
|
#define MBOOT_BOARD_ENTRY_INIT(initial_r0) mboot_entry_init_default()
|
|
#endif
|
|
|
|
#ifndef MBOOT_BOARD_GET_RESET_MODE
|
|
#if MBOOT_ENABLE_DEFAULT_UI
|
|
#define MBOOT_BOARD_GET_RESET_MODE(initial_r0) mboot_get_reset_mode_default()
|
|
#else
|
|
#define MBOOT_BOARD_GET_RESET_MODE(initial_r0) BOARDCTRL_RESET_MODE_NORMAL
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef MBOOT_BOARD_STATE_CHANGE
|
|
#if MBOOT_ENABLE_DEFAULT_UI
|
|
#define MBOOT_BOARD_STATE_CHANGE(state, arg) mboot_state_change_default((state), (arg))
|
|
#else
|
|
#define MBOOT_BOARD_STATE_CHANGE(state, arg)
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef MBOOT_BOARD_SYSTICK
|
|
#if MBOOT_ENABLE_DEFAULT_UI
|
|
#define MBOOT_BOARD_SYSTICK() mboot_ui_systick()
|
|
#else
|
|
#define MBOOT_BOARD_SYSTICK()
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef MBOOT_ADDRESS_SPACE_64BIT
|
|
#define MBOOT_ADDRESS_SPACE_64BIT (0)
|
|
#endif
|
|
|
|
// These values are used in initial_r0 to enter mboot programatically.
|
|
#define MBOOT_INITIAL_R0_KEY (0x70ad0000)
|
|
#define MBOOT_INITIAL_R0_KEY_FSLOAD (MBOOT_INITIAL_R0_KEY | 0x80)
|
|
|
|
// These are for led_state_all() and can be or'd together.
|
|
#define MBOOT_LED_STATE_LED0 (0x01)
|
|
#define MBOOT_LED_STATE_LED1 (0x02)
|
|
#define MBOOT_LED_STATE_LED2 (0x04)
|
|
#define MBOOT_LED_STATE_LED3 (0x08)
|
|
|
|
// These enum values are passed as the first argument to mboot_state_change() to
|
|
// notify of a change in state of the bootloader activity. This function has a
|
|
// default implementation in ui.c but can be overridden by a board. Some states
|
|
// have an argument passed along as the second argument to mboot_state_change().
|
|
// If this argument is unused then 0 is passed in. A result of an operation is
|
|
// 0 for success and <0 for failure, with a failure being either an MP_Exxx code
|
|
// or MBOOT_ERRNO_xxx code.
|
|
typedef enum {
|
|
MBOOT_STATE_DFU_START, // arg: unused
|
|
MBOOT_STATE_DFU_END, // arg: unused
|
|
MBOOT_STATE_FSLOAD_START, // arg: unused
|
|
MBOOT_STATE_FSLOAD_END, // arg: result of fsload operation
|
|
MBOOT_STATE_FSLOAD_PASS_START, // arg: pass number, 0 or 1 (verify and write respectively)
|
|
MBOOT_STATE_FSLOAD_PROGRESS, // arg: total bytes processed so far, high bit set when doing write pass
|
|
MBOOT_STATE_ERASE_START, // arg: address of erase
|
|
MBOOT_STATE_ERASE_END, // arg: result of erase
|
|
MBOOT_STATE_READ_START, // arg: address of read
|
|
MBOOT_STATE_READ_END, // arg: result of read
|
|
MBOOT_STATE_WRITE_START, // arg: address of write
|
|
MBOOT_STATE_WRITE_END, // arg: result of write
|
|
} mboot_state_t;
|
|
|
|
enum {
|
|
MBOOT_ERRNO_FLASH_ERASE_DISALLOWED = 200,
|
|
MBOOT_ERRNO_FLASH_ERASE_FAILED,
|
|
MBOOT_ERRNO_FLASH_READ_DISALLOWED,
|
|
MBOOT_ERRNO_FLASH_WRITE_DISALLOWED,
|
|
|
|
MBOOT_ERRNO_DFU_INVALID_HEADER = 210,
|
|
MBOOT_ERRNO_DFU_INVALID_TARGET,
|
|
MBOOT_ERRNO_DFU_INVALID_SIZE,
|
|
MBOOT_ERRNO_DFU_TOO_MANY_TARGETS,
|
|
MBOOT_ERRNO_DFU_READ_ERROR,
|
|
MBOOT_ERRNO_DFU_INVALID_CRC,
|
|
|
|
MBOOT_ERRNO_FSLOAD_NO_FSLOAD = 220,
|
|
MBOOT_ERRNO_FSLOAD_NO_MOUNT,
|
|
MBOOT_ERRNO_FSLOAD_INVALID_MOUNT,
|
|
|
|
MBOOT_ERRNO_PACK_INVALID_ADDR = 230,
|
|
MBOOT_ERRNO_PACK_INVALID_CHUNK,
|
|
MBOOT_ERRNO_PACK_INVALID_VERSION,
|
|
MBOOT_ERRNO_PACK_DECRYPT_FAILED,
|
|
MBOOT_ERRNO_PACK_SIGN_FAILED,
|
|
|
|
MBOOT_ERRNO_VFS_FAT_MOUNT_FAILED = 240,
|
|
MBOOT_ERRNO_VFS_FAT_OPEN_FAILED,
|
|
MBOOT_ERRNO_VFS_LFS1_MOUNT_FAILED,
|
|
MBOOT_ERRNO_VFS_LFS1_OPEN_FAILED,
|
|
MBOOT_ERRNO_VFS_LFS2_MOUNT_FAILED,
|
|
MBOOT_ERRNO_VFS_LFS2_OPEN_FAILED,
|
|
|
|
MBOOT_ERRNO_GUNZIP_FAILED = 250,
|
|
};
|
|
|
|
enum {
|
|
ELEM_TYPE_END = 1,
|
|
ELEM_TYPE_MOUNT,
|
|
ELEM_TYPE_FSLOAD,
|
|
ELEM_TYPE_STATUS,
|
|
};
|
|
|
|
enum {
|
|
ELEM_MOUNT_FAT = 1,
|
|
ELEM_MOUNT_LFS1,
|
|
ELEM_MOUNT_LFS2,
|
|
};
|
|
|
|
// Configure the type used to hold an address in the mboot address space.
|
|
#if MBOOT_ADDRESS_SPACE_64BIT
|
|
typedef uint64_t mboot_addr_t;
|
|
#else
|
|
typedef uint32_t mboot_addr_t;
|
|
#endif
|
|
|
|
extern volatile uint32_t systick_ms;
|
|
extern uint8_t _estack[ELEM_DATA_SIZE];
|
|
extern int32_t first_writable_flash_sector;
|
|
|
|
void systick_init(void);
|
|
void led_init(void);
|
|
void mboot_ui_systick(void);
|
|
void SystemClock_Config(void);
|
|
|
|
uint32_t get_le32(const uint8_t *b);
|
|
uint64_t get_le64(const uint8_t *b);
|
|
void led_state_all(unsigned int mask);
|
|
|
|
int hw_page_erase(uint32_t addr, uint32_t *next_addr);
|
|
void hw_read(mboot_addr_t addr, size_t len, uint8_t *buf);
|
|
int hw_write(uint32_t addr, const uint8_t *src8, size_t len);
|
|
|
|
int do_page_erase(uint32_t addr, uint32_t *next_addr);
|
|
void do_read(mboot_addr_t addr, size_t len, uint8_t *buf);
|
|
int do_write(uint32_t addr, const uint8_t *src8, size_t len, bool dry_run);
|
|
|
|
const uint8_t *elem_search(const uint8_t *elem, uint8_t elem_id);
|
|
int fsload_process(void);
|
|
|
|
static inline void mboot_entry_init_default(void) {
|
|
#if MBOOT_ENABLE_DEFAULT_UI
|
|
// Init subsystems (mboot_get_reset_mode() may call these, calling them again is ok)
|
|
led_init();
|
|
#endif
|
|
|
|
// set the system clock to be HSE
|
|
SystemClock_Config();
|
|
|
|
#if defined(STM32H7)
|
|
// Ensure IRQs are enabled (needed coming out of ST bootloader on H7)
|
|
__set_PRIMASK(0);
|
|
#endif
|
|
}
|
|
|
|
int mboot_get_reset_mode_default(void);
|
|
void mboot_state_change_default(mboot_state_t state, uint32_t arg);
|
|
|
|
static inline void mboot_state_change(mboot_state_t state, uint32_t arg) {
|
|
return MBOOT_BOARD_STATE_CHANGE(state, arg);
|
|
}
|
|
|
|
#endif // MICROPY_INCLUDED_STM32_MBOOT_MBOOT_H
|