Temporarily backport app updates from apps repo

This commit is contained in:
Willy-JL
2023-11-12 11:06:02 +00:00
parent 79e7f491fe
commit e309fa8a88
1498 changed files with 1325977 additions and 20227 deletions

View File

@@ -0,0 +1,366 @@
# This is the CMakeCache file.
# For build in directory: /home/cococode/flipperzero-firmware/lib/esp-serial-flasher
# It was generated by CMake: /usr/bin/cmake
# You can edit this file to change values found and used by cmake.
# If you do not want to change any of the values, simply exit the editor.
# If you do want to change a value, simply edit, save, and exit the editor.
# The syntax for the file is as follows:
# KEY:TYPE=VALUE
# KEY is the name of a variable in the cache.
# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
# VALUE is the current value for the KEY.
########################
# EXTERNAL cache entries
########################
//Path to a program.
CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line
//Path to a program.
CMAKE_AR:FILEPATH=/usr/bin/ar
//Choose the type of build, options are: None Debug Release RelWithDebInfo
// MinSizeRel ...
CMAKE_BUILD_TYPE:STRING=
//Enable/Disable color output during build.
CMAKE_COLOR_MAKEFILE:BOOL=ON
//CXX compiler
CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++
//A wrapper around 'ar' adding the appropriate '--plugin' option
// for the GCC compiler
CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9
//A wrapper around 'ranlib' adding the appropriate '--plugin' option
// for the GCC compiler
CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9
//Flags used by the CXX compiler during all build types.
CMAKE_CXX_FLAGS:STRING=
//Flags used by the CXX compiler during DEBUG builds.
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
//Flags used by the CXX compiler during MINSIZEREL builds.
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
//Flags used by the CXX compiler during RELEASE builds.
CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
//Flags used by the CXX compiler during RELWITHDEBINFO builds.
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
//C compiler
CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc
//A wrapper around 'ar' adding the appropriate '--plugin' option
// for the GCC compiler
CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-9
//A wrapper around 'ranlib' adding the appropriate '--plugin' option
// for the GCC compiler
CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-9
//Flags used by the C compiler during all build types.
CMAKE_C_FLAGS:STRING=
//Flags used by the C compiler during DEBUG builds.
CMAKE_C_FLAGS_DEBUG:STRING=-g
//Flags used by the C compiler during MINSIZEREL builds.
CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
//Flags used by the C compiler during RELEASE builds.
CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
//Flags used by the C compiler during RELWITHDEBINFO builds.
CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
//Path to a program.
CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND
//Flags used by the linker during all build types.
CMAKE_EXE_LINKER_FLAGS:STRING=
//Flags used by the linker during DEBUG builds.
CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
//Flags used by the linker during MINSIZEREL builds.
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
//Flags used by the linker during RELEASE builds.
CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
//Flags used by the linker during RELWITHDEBINFO builds.
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
//Enable/Disable output of compile commands during generation.
CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF
//Install path prefix, prepended onto install directories.
CMAKE_INSTALL_PREFIX:PATH=/usr/local
//Path to a program.
CMAKE_LINKER:FILEPATH=/usr/bin/ld
//Path to a program.
CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make
//Flags used by the linker during the creation of modules during
// all build types.
CMAKE_MODULE_LINKER_FLAGS:STRING=
//Flags used by the linker during the creation of modules during
// DEBUG builds.
CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
//Flags used by the linker during the creation of modules during
// MINSIZEREL builds.
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
//Flags used by the linker during the creation of modules during
// RELEASE builds.
CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
//Flags used by the linker during the creation of modules during
// RELWITHDEBINFO builds.
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
//Path to a program.
CMAKE_NM:FILEPATH=/usr/bin/nm
//Path to a program.
CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy
//Path to a program.
CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump
//Value Computed by CMake
CMAKE_PROJECT_DESCRIPTION:STATIC=
//Value Computed by CMake
CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
//Value Computed by CMake
CMAKE_PROJECT_NAME:STATIC=Project
//Path to a program.
CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib
//Path to a program.
CMAKE_READELF:FILEPATH=/usr/bin/readelf
//Flags used by the linker during the creation of shared libraries
// during all build types.
CMAKE_SHARED_LINKER_FLAGS:STRING=
//Flags used by the linker during the creation of shared libraries
// during DEBUG builds.
CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
//Flags used by the linker during the creation of shared libraries
// during MINSIZEREL builds.
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
//Flags used by the linker during the creation of shared libraries
// during RELEASE builds.
CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
//Flags used by the linker during the creation of shared libraries
// during RELWITHDEBINFO builds.
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
//If set, runtime paths are not added when installing shared libraries,
// but are added when building.
CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
//If set, runtime paths are not added when using shared libraries.
CMAKE_SKIP_RPATH:BOOL=NO
//Flags used by the linker during the creation of static libraries
// during all build types.
CMAKE_STATIC_LINKER_FLAGS:STRING=
//Flags used by the linker during the creation of static libraries
// during DEBUG builds.
CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
//Flags used by the linker during the creation of static libraries
// during MINSIZEREL builds.
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
//Flags used by the linker during the creation of static libraries
// during RELEASE builds.
CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
//Flags used by the linker during the creation of static libraries
// during RELWITHDEBINFO builds.
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
//Path to a program.
CMAKE_STRIP:FILEPATH=/usr/bin/strip
//If this value is on, makefiles will be generated without the
// .SILENT directive, and all commands will be echoed to the console
// during the make. This is useful for debugging only. With Visual
// Studio IDE projects all commands are done without /nologo.
CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
//Value Computed by CMake
Project_BINARY_DIR:STATIC=/home/cococode/flipperzero-firmware/lib/esp-serial-flasher
//Value Computed by CMake
Project_SOURCE_DIR:STATIC=/home/cococode/flipperzero-firmware/lib/esp-serial-flasher
########################
# INTERNAL cache entries
########################
//ADVANCED property for variable: CMAKE_ADDR2LINE
CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_AR
CMAKE_AR-ADVANCED:INTERNAL=1
//This is the directory where this CMakeCache.txt was created
CMAKE_CACHEFILE_DIR:INTERNAL=/home/cococode/flipperzero-firmware/lib/esp-serial-flasher
//Major version of cmake used to create the current loaded cache
CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
//Minor version of cmake used to create the current loaded cache
CMAKE_CACHE_MINOR_VERSION:INTERNAL=16
//Patch version of cmake used to create the current loaded cache
CMAKE_CACHE_PATCH_VERSION:INTERNAL=3
//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE
CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1
//Path to CMake executable.
CMAKE_COMMAND:INTERNAL=/usr/bin/cmake
//Path to cpack program executable.
CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack
//Path to ctest program executable.
CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest
//ADVANCED property for variable: CMAKE_CXX_COMPILER
CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR
CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB
CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_COMPILER
CMAKE_C_COMPILER-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_COMPILER_AR
CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB
CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS
CMAKE_C_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_DLLTOOL
CMAKE_DLLTOOL-ADVANCED:INTERNAL=1
//Executable file format
CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG
CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE
CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS
CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1
//Name of external makefile project generator.
CMAKE_EXTRA_GENERATOR:INTERNAL=
//Name of generator.
CMAKE_GENERATOR:INTERNAL=Unix Makefiles
//Generator instance identifier.
CMAKE_GENERATOR_INSTANCE:INTERNAL=
//Name of generator platform.
CMAKE_GENERATOR_PLATFORM:INTERNAL=
//Name of generator toolset.
CMAKE_GENERATOR_TOOLSET:INTERNAL=
//Source directory with the top level CMakeLists.txt file for this
// project
CMAKE_HOME_DIRECTORY:INTERNAL=/home/cococode/flipperzero-firmware/lib/esp-serial-flasher
//Install .so files without execute permission.
CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1
//ADVANCED property for variable: CMAKE_LINKER
CMAKE_LINKER-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MAKE_PROGRAM
CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG
CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE
CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_NM
CMAKE_NM-ADVANCED:INTERNAL=1
//number of local generators
CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1
//ADVANCED property for variable: CMAKE_OBJCOPY
CMAKE_OBJCOPY-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_OBJDUMP
CMAKE_OBJDUMP-ADVANCED:INTERNAL=1
//Platform information initialized
CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1
//ADVANCED property for variable: CMAKE_RANLIB
CMAKE_RANLIB-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_READELF
CMAKE_READELF-ADVANCED:INTERNAL=1
//Path to CMake installation.
CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.16
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE
CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH
CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SKIP_RPATH
CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS
CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG
CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE
CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STRIP
CMAKE_STRIP-ADVANCED:INTERNAL=1
//uname command
CMAKE_UNAME:INTERNAL=/usr/bin/uname
//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1

View File

@@ -0,0 +1,119 @@
cmake_minimum_required(VERSION 3.5)
set(srcs
src/esp_targets.c
src/md5_hash.c
src/esp_loader.c
src/protocol_common.c
)
if (DEFINED ESP_PLATFORM)
if (${CONFIG_SERIAL_FLASHER_INTERFACE_UART})
list(APPEND srcs
src/protocol_uart.c
src/slip.c
port/esp32_port.c
)
elseif (${CONFIG_SERIAL_FLASHER_INTERFACE_SPI})
list(APPEND srcs
src/protocol_spi.c
port/esp32_spi_port.c
)
endif()
# Register component to esp-idf build system
if ("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.0")
# esp_timer component was introduced in v4.2
set(priv_requires driver)
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.1")
list(APPEND priv_requires esp_timer)
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS include port
PRIV_INCLUDE_DIRS private_include
PRIV_REQUIRES ${priv_requires})
set(target ${COMPONENT_LIB})
component_compile_options(-Wstrict-prototypes)
else()
# Remove when dropping support for IDF 3.3
set(COMPONENT_SRCS ${srcs})
set(COMPONENT_ADD_INCLUDEDIRS include port)
set(COMPONENT_PRIV_INCLUDEDIRS private_include)
register_component()
set(target ${COMPONENT_TARGET})
endif()
else()
if (NOT DEFINED SERIAL_FLASHER_INTERFACE_UART AND NOT DEFINED SERIAL_FLASHER_INTERFACE_SPI)
set(SERIAL_FLASHER_INTERFACE_UART true)
endif()
if (DEFINED SERIAL_FLASHER_INTERFACE_UART)
list(APPEND srcs
src/protocol_uart.c
src/slip.c
)
elseif (DEFINED SERIAL_FLASHER_INTERFACE_SPI)
list(APPEND srcs src/protocol_spi.c)
endif()
# Create traditional CMake target
add_library(flasher ${srcs})
target_include_directories(flasher PUBLIC include port PRIVATE private_include)
if(PORT STREQUAL "STM32")
target_link_libraries(flasher PUBLIC stm_cube)
target_sources(flasher PRIVATE port/stm32_port.c)
elseif(PORT STREQUAL "RASPBERRY_PI")
find_library(pigpio_LIB pigpio)
target_link_libraries(flasher PUBLIC ${pigpio_LIB})
target_sources(flasher PRIVATE port/raspberry_port.c)
else()
message(FATAL_ERROR "Selected port is not supported")
endif()
set(target flasher)
endif()
if (DEFINED SERIAL_FLASHER_INTERFACE_UART OR CONFIG_SERIAL_FLASHER_INTERFACE_UART STREQUAL "y")
target_compile_definitions(${target}
PUBLIC
SERIAL_FLASHER_INTERFACE_UART
)
if (DEFINED MD5_ENABLED OR CONFIG_SERIAL_FLASHER_MD5_ENABLED)
target_compile_definitions(${target} PUBLIC MD5_ENABLED=1)
endif()
elseif (DEFINED SERIAL_FLASHER_INTERFACE_SPI OR CONFIG_SERIAL_FLASHER_INTERFACE_SPI STREQUAL "y")
target_compile_definitions(${target}
PUBLIC
SERIAL_FLASHER_INTERFACE_SPI
)
endif()
if(DEFINED SERIAL_FLASHER_DEBUG_TRACE OR CONFIG_SERIAL_FLASHER_DEBUG_TRACE)
target_compile_definitions(${target} PUBLIC SERIAL_FLASHER_DEBUG_TRACE)
endif()
if(DEFINED CONFIG_SERIAL_FLASHER_RESET_HOLD_TIME_MS AND DEFINED CONFIG_SERIAL_FLASHER_BOOT_HOLD_TIME_MS)
target_compile_definitions(${target}
PUBLIC
SERIAL_FLASHER_RESET_HOLD_TIME_MS=${CONFIG_SERIAL_FLASHER_RESET_HOLD_TIME_MS}
SERIAL_FLASHER_BOOT_HOLD_TIME_MS=${CONFIG_SERIAL_FLASHER_BOOT_HOLD_TIME_MS}
)
else()
if(NOT DEFINED SERIAL_FLASHER_RESET_HOLD_TIME_MS)
target_compile_definitions(${target}
PUBLIC
SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
)
endif()
if(NOT DEFINED SERIAL_FLASHER_BOOT_HOLD_TIME_MS)
target_compile_definitions(${target}
PUBLIC
SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
)
endif()
endif()

View File

@@ -0,0 +1,154 @@
# esp-serial-flasher
`esp-serial-flasher` is a portable C library for flashing or loading apps to RAM of Espressif SoCs from other host microcontrollers.
## Using the library
Espressif SoCs are normally programmed via serial interface (UART). The port layer for the given host microcontroller has to be implemented if not available. Details can be found in section below.
Supported **host** microcontrollers:
- STM32
- Raspberry Pi SBC
- ESP32
- Any MCU running Zephyr OS
Supported **target** microcontrollers:
- ESP32
- ESP8266
- ESP32-S2
- ESP32-S3
- ESP32-C3
- ESP32-C2
- ESP32-H2
Supported hardware interfaces:
- UART
- SPI (only for RAM download, experimental)
For example usage check the `examples` directory.
## Supporting a new host target
In order to support a new target, following functions have to be implemented by user:
- `loader_port_read()`
- `loader_port_write()`
- `loader_port_enter_bootloader()`
- `loader_port_delay_ms()`
- `loader_port_start_timer()`
- `loader_port_remaining_time()`
For the SPI interface ports
- `loader_port_spi_set_cs()`
needs to be implemented as well.
The following functions are part of the [io.h](include/io.h) header for convenience, however, the user does not have to strictly follow function signatures, as there are not called directly from library.
- `loader_port_change_transmission_rate()`
- `loader_port_reset_target()`
- `loader_port_debug_print()`
Prototypes of all functions mentioned above can be found in [io.h](include/io.h).
## Configuration
These are the configuration toggles available to the user:
* `SERIAL_FLASHER_INTERFACE_UART/SERIAL_FLASHER_INTERFACE_SPI`
This defines the hardware interface to use. SPI interface only supports RAM download mode and is in experimental stage and can undergo changes.
Default: SERIAL_FLASHER_INTERFACE_UART
* `MD5_ENABLED`
If enabled, `esp-serial-flasher` is capable of verifying flash integrity after writing to flash.
Default: Enabled
> Warning: As ROM bootloader of the ESP8266 does not support MD5_CHECK, this option has to be disabled!
* `SERIAL_FLASHER_RESET_HOLD_TIME_MS`
This is the time for which the reset pin is asserted when doing a hard reset in milliseconds.
Default: 100
* `SERIAL_FLASHER_BOOT_HOLD_TIME_MS`
This is the time for which the boot pin is asserted when doing a hard reset in milliseconds.
Default: 50
Configuration can be passed to `cmake` via command line:
```
cmake -DMD5_ENABLED=1 .. && cmake --build .
```
### STM32 support
The STM32 port makes use of STM32 HAL libraries, and these do not come with CMake support. In order to compile the project, `stm32-cmake` (a `CMake` support package) has to be pulled as submodule.
```
git clone --recursive https://github.com/espressif/esp-serial-flasher.git
```
If you have cloned this repository without the `--recursive` flag, you can initialize the submodule using the following command:
```
git submodule update --init
```
In addition to configuration parameters mentioned above, following definitions has to be set:
- TOOLCHAIN_PREFIX: path to arm toolchain (i.e /home/user/gcc-arm-none-eabi-9-2019-q4-major)
- STM32Cube_DIR: path to STM32 Cube libraries (i.e /home/user/STM32Cube/Repository/STM32Cube_FW_F4_V1.25.0)
- STM32_CHIP: name of STM32 for which project should be compiled (i.e STM32F407VG)
- PORT: STM32
This can be achieved by passing definitions to the command line, such as:
```
cmake -DTOOLCHAIN_PREFIX="/path_to_toolchain" -DSTM32Cube_DIR="path_to_stm32Cube" -DSTM32_CHIP="STM32F407VG" -DPORT="STM32" .. && cmake --build .
```
Alternatively, those variables can be set in the top level `cmake` directory:
```
set(TOOLCHAIN_PREFIX path_to_toolchain)
set(STM32Cube_DIR path_to_stm32_HAL)
set(STM32_CHIP STM32F407VG)
set(PORT STM32)
```
### Zephyr support
The Zephyr port is ready to be integrated into Zephyr apps as a Zephyr module. In the manifest file (west.yml), add:
```
- name: esp-flasher
url: https://github.com/espressif/esp-serial-flasher
revision: master
path: modules/lib/esp_flasher
```
And add
```
CONFIG_ESP_SERIAL_FLASHER=y
CONFIG_CONSOLE_GETCHAR=y
CONFIG_SERIAL_FLASHER_MD5_ENABLED=y
```
to the project configuration `prj.conf`.
For the C/C++ source code, the example code provided in `examples/zephyr_example` can be used as a starting point.
## Licence
Code is distributed under Apache 2.0 license.
## Known limitations
Size of new binary image has to be known before flashing.

View File

@@ -0,0 +1,15 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
# Here we remove all unecessary components from the build to make the binary smaller
set(COMPONENTS main)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hello_world)
# This generates a binary file from the elf, as the RAM build doesn't do that automatically
add_custom_command(TARGET ${PROJECT_NAME}.elf
POST_BUILD
COMMAND esptool.py elf2image --output app.bin ${PROJECT_NAME}.elf
)

View File

@@ -0,0 +1,2 @@
idf_component_register(SRCS "main.c"
INCLUDE_DIRS "")

View File

@@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
void app_main(void)
{
while (true) {
esp_rom_printf("Hello world!\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}

View File

@@ -0,0 +1,10 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
#
CONFIG_APP_BUILD_TYPE_ELF_RAM=y
CONFIG_APP_NO_BLOBS=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
# CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set
CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT=y
CONFIG_LOG_DEFAULT_LEVEL_NONE=y

View File

@@ -0,0 +1,20 @@
# Creates C resources file from files in given directory recursively
function(create_resources dir output)
# Create empty output file
file(WRITE ${output} "#include <stdint.h>\n\n")
# Collect input files
file(GLOB bin_paths ${dir}/ESP*/*)
# Iterate through input files
foreach(bin ${bin_paths})
# Get short filenames, by discarding relative path
file(GLOB name RELATIVE ${dir} ${bin})
# Replace filename spaces & extension separator for C compatibility
string(REGEX REPLACE "[\\./-]" "_" filename ${name})
# Read hex data from file
file(READ ${bin} filedata HEX)
# Convert hex data for C compatibility
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," filedata ${filedata})
# Append data to output file
file(APPEND ${output} "const uint8_t ${filename}[] = {${filedata}};\nconst uint32_t ${filename}_size = sizeof(${filename});\n")
endforeach()
endfunction()

View File

@@ -0,0 +1,322 @@
/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <sys/param.h>
#include "esp_loader_io.h"
#include "esp_loader.h"
#include "example_common.h"
#ifndef SINGLE_TARGET_SUPPORT
// For esp8266, esp32, esp32s2
#define BOOTLOADER_ADDRESS_V0 0x1000
// For esp32s3 and later chips
#define BOOTLOADER_ADDRESS_V1 0x0
#define PARTITION_ADDRESS 0x8000
#define APPLICATION_ADDRESS 0x10000
extern const uint8_t ESP32_bootloader_bin[];
extern const uint32_t ESP32_bootloader_bin_size;
extern const uint8_t ESP32_hello_world_bin[];
extern const uint32_t ESP32_hello_world_bin_size;
extern const uint8_t ESP32_partition_table_bin[];
extern const uint32_t ESP32_partition_table_bin_size;
extern const uint8_t ESP32_S2_bootloader_bin[];
extern const uint32_t ESP32_S2_bootloader_bin_size;
extern const uint8_t ESP32_S2_hello_world_bin[];
extern const uint32_t ESP32_S2_hello_world_bin_size;
extern const uint8_t ESP32_S2_partition_table_bin[];
extern const uint32_t ESP32_S2_partition_table_bin_size;
extern const uint8_t ESP8266_bootloader_bin[];
extern const uint32_t ESP8266_bootloader_bin_size;
extern const uint8_t ESP8266_hello_world_bin[];
extern const uint32_t ESP8266_hello_world_bin_size;
extern const uint8_t ESP8266_partition_table_bin[];
extern const uint32_t ESP8266_partition_table_bin_size;
extern const uint8_t ESP32_H4_bootloader_bin[];
extern const uint32_t ESP32_H4_bootloader_bin_size;
extern const uint8_t ESP32_H4_hello_world_bin[];
extern const uint32_t ESP32_H4_hello_world_bin_size;
extern const uint8_t ESP32_H4_partition_table_bin[];
extern const uint32_t ESP32_H4_partition_table_bin_size;
extern const uint8_t ESP32_H2_bootloader_bin[];
extern const uint32_t ESP32_H2_bootloader_bin_size;
extern const uint8_t ESP32_H2_hello_world_bin[];
extern const uint32_t ESP32_H2_hello_world_bin_size;
extern const uint8_t ESP32_H2_partition_table_bin[];
extern const uint32_t ESP32_H2_partition_table_bin_size;
void get_example_binaries(target_chip_t target, example_binaries_t *bins)
{
if (target == ESP8266_CHIP) {
bins->boot.data = ESP8266_bootloader_bin;
bins->boot.size = ESP8266_bootloader_bin_size;
bins->boot.addr = BOOTLOADER_ADDRESS_V0;
bins->part.data = ESP8266_partition_table_bin;
bins->part.size = ESP8266_partition_table_bin_size;
bins->part.addr = PARTITION_ADDRESS;
bins->app.data = ESP8266_hello_world_bin;
bins->app.size = ESP8266_hello_world_bin_size;
bins->app.addr = APPLICATION_ADDRESS;
} else if (target == ESP32_CHIP) {
bins->boot.data = ESP32_bootloader_bin;
bins->boot.size = ESP32_bootloader_bin_size;
bins->boot.addr = BOOTLOADER_ADDRESS_V0;
bins->part.data = ESP32_partition_table_bin;
bins->part.size = ESP32_partition_table_bin_size;
bins->part.addr = PARTITION_ADDRESS;
bins->app.data = ESP32_hello_world_bin;
bins->app.size = ESP32_hello_world_bin_size;
bins->app.addr = APPLICATION_ADDRESS;
} else if (target == ESP32S2_CHIP) {
bins->boot.data = ESP32_S2_bootloader_bin;
bins->boot.size = ESP32_S2_bootloader_bin_size;
bins->boot.addr = BOOTLOADER_ADDRESS_V0;
bins->part.data = ESP32_S2_partition_table_bin;
bins->part.size = ESP32_S2_partition_table_bin_size;
bins->part.addr = PARTITION_ADDRESS;
bins->app.data = ESP32_S2_hello_world_bin;
bins->app.size = ESP32_S2_hello_world_bin_size;
bins->app.addr = APPLICATION_ADDRESS;
} else if (target == ESP32H4_CHIP){
bins->boot.data = ESP32_H4_bootloader_bin;
bins->boot.size = ESP32_H4_bootloader_bin_size;
bins->boot.addr = BOOTLOADER_ADDRESS_V1;
bins->part.data = ESP32_H4_partition_table_bin;
bins->part.size = ESP32_H4_partition_table_bin_size;
bins->part.addr = PARTITION_ADDRESS;
bins->app.data = ESP32_H4_hello_world_bin;
bins->app.size = ESP32_H4_hello_world_bin_size;
bins->app.addr = APPLICATION_ADDRESS;
} else if (target == ESP32H2_CHIP){
bins->boot.data = ESP32_H2_bootloader_bin;
bins->boot.size = ESP32_H2_bootloader_bin_size;
bins->boot.addr = BOOTLOADER_ADDRESS_V1;
bins->part.data = ESP32_H2_partition_table_bin;
bins->part.size = ESP32_H2_partition_table_bin_size;
bins->part.addr = PARTITION_ADDRESS;
bins->app.data = ESP32_H2_hello_world_bin;
bins->app.size = ESP32_H2_hello_world_bin_size;
bins->app.addr = APPLICATION_ADDRESS;
}else {
abort();
}
}
extern const uint8_t ESP32_app_bin[];
extern const uint32_t ESP32_app_bin_size;
extern const uint8_t ESP32_C2_app_bin[];
extern const uint32_t ESP32_C2_app_bin_size;
extern const uint8_t ESP32_C3_app_bin[];
extern const uint32_t ESP32_C3_app_bin_size;
extern const uint8_t ESP32_H2_app_bin[];
extern const uint32_t ESP32_H2_app_bin_size;
extern const uint8_t ESP32_H4_app_bin[];
extern const uint32_t ESP32_H4_app_bin_size;
extern const uint8_t ESP32_S3_app_bin[];
extern const uint32_t ESP32_S3_app_bin_size;
void get_example_ram_app_binary(target_chip_t target, example_ram_app_binary_t *bin)
{
switch (target) {
case ESP32_CHIP: {
bin->ram_app.data = ESP32_app_bin;
bin->ram_app.size = ESP32_app_bin_size;
break;
}
case ESP32C2_CHIP: {
bin->ram_app.data = ESP32_C2_app_bin;
bin->ram_app.size = ESP32_C2_app_bin_size;
break;
}
case ESP32C3_CHIP: {
bin->ram_app.data = ESP32_C3_app_bin;
bin->ram_app.size = ESP32_C3_app_bin_size;
break;
}
case ESP32H2_CHIP: {
bin->ram_app.data = ESP32_H2_app_bin;
bin->ram_app.size = ESP32_H2_app_bin_size;
break;
}
case ESP32H4_CHIP: {
bin->ram_app.data = ESP32_H4_app_bin;
bin->ram_app.size = ESP32_H4_app_bin_size;
break;
}
case ESP32S3_CHIP: {
bin->ram_app.data = ESP32_S3_app_bin;
bin->ram_app.size = ESP32_S3_app_bin_size;
break;
}
default: {
abort();
}
}
}
#endif
esp_loader_error_t connect_to_target(uint32_t higher_transmission_rate)
{
esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT();
esp_loader_error_t err = esp_loader_connect(&connect_config);
if (err != ESP_LOADER_SUCCESS) {
printf("Cannot connect to target. Error: %u\n", err);
return err;
}
printf("Connected to target\n");
#ifdef SERIAL_FLASHER_INTERFACE_UART
if (higher_transmission_rate && esp_loader_get_target() != ESP8266_CHIP) {
err = esp_loader_change_transmission_rate(higher_transmission_rate);
if (err == ESP_LOADER_ERROR_UNSUPPORTED_FUNC) {
printf("ESP8266 does not support change transmission rate command.");
return err;
} else if (err != ESP_LOADER_SUCCESS) {
printf("Unable to change transmission rate on target.");
return err;
} else {
err = loader_port_change_transmission_rate(higher_transmission_rate);
if (err != ESP_LOADER_SUCCESS) {
printf("Unable to change transmission rate.");
return err;
}
printf("Transmission rate changed changed\n");
}
}
#endif /* SERIAL_FLASHER_INTERFACE_UART */
return ESP_LOADER_SUCCESS;
}
#ifdef SERIAL_FLASHER_INTERFACE_UART
esp_loader_error_t flash_binary(const uint8_t *bin, size_t size, size_t address)
{
esp_loader_error_t err;
static uint8_t payload[1024];
const uint8_t *bin_addr = bin;
printf("Erasing flash (this may take a while)...\n");
err = esp_loader_flash_start(address, size, sizeof(payload));
if (err != ESP_LOADER_SUCCESS) {
printf("Erasing flash failed with error %d.\n", err);
return err;
}
printf("Start programming\n");
size_t binary_size = size;
size_t written = 0;
while (size > 0) {
size_t to_read = MIN(size, sizeof(payload));
memcpy(payload, bin_addr, to_read);
err = esp_loader_flash_write(payload, to_read);
if (err != ESP_LOADER_SUCCESS) {
printf("\nPacket could not be written! Error %d.\n", err);
return err;
}
size -= to_read;
bin_addr += to_read;
written += to_read;
int progress = (int)(((float)written / binary_size) * 100);
printf("\rProgress: %d %%", progress);
fflush(stdout);
};
printf("\nFinished programming\n");
#if MD5_ENABLED
err = esp_loader_flash_verify();
if (err == ESP_LOADER_ERROR_UNSUPPORTED_FUNC) {
printf("ESP8266 does not support flash verify command.");
return err;
} else if (err != ESP_LOADER_SUCCESS) {
printf("MD5 does not match. err: %d\n", err);
return err;
}
printf("Flash verified\n");
#endif
return ESP_LOADER_SUCCESS;
}
#endif /* SERIAL_FLASHER_INTERFACE_UART */
esp_loader_error_t load_ram_binary(const uint8_t *bin)
{
printf("Start loading\n");
esp_loader_error_t err;
const esp_loader_bin_header_t *header = (const esp_loader_bin_header_t *)bin;
esp_loader_bin_segment_t segments[header->segments];
// Parse segments
uint32_t seg;
uint32_t *cur_seg_pos;
for (seg=0, cur_seg_pos = (uint32_t *)(&bin[BIN_FIRST_SEGMENT_OFFSET]);
seg < header->segments;
seg++) {
segments[seg].addr = *cur_seg_pos++;
segments[seg].size = *cur_seg_pos++;
segments[seg].data = (uint8_t *)cur_seg_pos;
cur_seg_pos += (segments[seg].size) / 4;
}
// Download segments
for (seg=0; seg < header->segments; seg++) {
printf("Downloading %"PRIu32" bytes at 0x%08"PRIx32"...\n", segments[seg].size, segments[seg].addr);
err = esp_loader_mem_start(segments[seg].addr, segments[seg].size, ESP_RAM_BLOCK);
if (err != ESP_LOADER_SUCCESS) {
printf("Loading ram start with error %d.\n", err);
return err;
}
size_t remain_size = segments[seg].size;
uint8_t *data_pos = segments[seg].data;
while(remain_size > 0) {
size_t data_size = MIN(ESP_RAM_BLOCK, remain_size);
err = esp_loader_mem_write(data_pos, data_size);
if (err != ESP_LOADER_SUCCESS) {
printf("\nPacket could not be written! Error %d.\n", err);
return err;
}
data_pos += data_size;
remain_size -= data_size;
}
}
err = esp_loader_mem_finish(header->entrypoint);
if (err != ESP_LOADER_SUCCESS) {
printf("\nLoad ram finish with Error %d.\n", err);
return err;
}
printf("\nFinished loading\n");
return ESP_LOADER_SUCCESS;
}

View File

@@ -0,0 +1,63 @@
/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#define BIN_FIRST_SEGMENT_OFFSET 0x18
// Maximum block sized for RAM and Flash writes, respectively.
#define ESP_RAM_BLOCK 0x1800
typedef struct {
const uint8_t *data;
uint32_t size;
uint32_t addr;
} partition_attr_t;
typedef struct {
partition_attr_t boot;
partition_attr_t part;
partition_attr_t app;
} example_binaries_t;
typedef struct {
partition_attr_t ram_app;
} example_ram_app_binary_t;
/**
* @brief esptool portable bin header format
*/
typedef struct example_bin_header {
uint8_t magic;
uint8_t segments;
uint8_t flash_mode;
uint8_t flash_size_freq;
uint32_t entrypoint;
} example_bin_header_t;
/**
* @brief esptool portable bin segment format
*/
typedef struct example_bin_segment {
uint32_t addr;
uint32_t size;
uint8_t *data;
} example_bin_segment_t;
void get_example_binaries(target_chip_t target, example_binaries_t *binaries);
void get_example_ram_app_binary(target_chip_t target, example_ram_app_binary_t *bin);
esp_loader_error_t connect_to_target(uint32_t higher_transmission_rate);
esp_loader_error_t flash_binary(const uint8_t *bin, size_t size, size_t address);
esp_loader_error_t load_ram_binary(const uint8_t *bin);

View File

@@ -0,0 +1,7 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS ../../)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp-serial-flasher)

View File

@@ -0,0 +1,78 @@
# Flash multiple partitions example
## Overview
Example demonstrates how to flash ESP32/ESP32-S2/ESP8266 from another (host) MCU using esp_serial_flash component API. In this case, ESP32 is also used as host MCU. Binaries to be flashed from host MCU to another Espressif SoC can be found in `binaries` folder and are converted into C-array during build process.
Following steps are performed in order to re-program target's memory:
1. Filesystem is initialized and mounted.
2. UART1 through which new binary will be transfered is initialized.
3. Host puts slave device into boot mode tries to connect by calling `esp_loader_connect()`.
4. Binary file is opened and its size is acquired, as it has to be known before flashing.
5. Then `esp_loader_flash_start()` is called to enter flashing mode and erase amount of memory to be flashed.
6. `esp_loader_flash_write()` function is called repeatedly until the whole binary image is transfered.
Note: In addition, to steps mentioned above, `esp_loader_change_transmission_rate` is called after connection is established in order to increase flashing speed. This does not apply for ESP8266, as its bootloader does not support this command. However, ESP8266 is capable of detecting baud rate during connection phase, and can be changed before calling `esp_loader_connect`, if necessary.
## SPI pin initialization
In majority of cases `ESP_LOADER_CONNECT_DEFAULT` helper macro is used in order to initialize `loader_connect_args_t` data structure passed to `esp_loader_connect`. Helper macro sets `spi_pin_config` field of the data structure to zero, thus, default SPI pins are used to connect to FLASH memory. In special cases, such as custom design in which FLASH is connected to different pins, `spi_pin_config` field has to be set accordingly. For more detailed information refer to [serial protocol](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/advanced-topics/serial-protocol.html).
## Hardware Required
* Two development boards with ESP32 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.).
* One or two USB cables for power supply and programming.
## Hardware connection
Table below shows connection between two ESP32 devices.
| ESP32 (host) | ESP32 (slave) |
|:------------:|:-------------:|
| IO26 | IO0 |
| IO25 | RESET |
| IO4 | RX0 |
| IO5 | TX0 |
Note: interconnection is the same for all three targets (slaves).
## Build and flash
To run the example, type the following command:
```CMake
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Configuration
For details about available configuration option, please refer to top level [README.md](../../README.md).
Compile definitions can be specified on command line when running `idf.py`, for example:
```
idf.py build -DMD5_ENABLED=1
```
Binaries to be flashed are placed in separate folder (binaries.c) for each possible target and converted to C-array. Without explicitly enabling MD5 check, flash integrity verification is disabled by default.
## Example output
Here is the example's console output:
```
...
I (342) example: Initializing SPIFFS
I (482) example: Image size: 144672
I (902) example: Connected to target
I (1732) example: Start programming
I (1832) example: packet: 0 written: 1024 B
I (1932) example: packet: 1 written: 1024 B
...
I (16052) example: packet: 140 written: 1024 B
I (16152) example: packet: 141 written: 288 B
I (16152) example: Finished programming
```

View File

@@ -0,0 +1,22 @@
set(srcs main.c ../../common/example_common.c)
set(include_dirs . ../../common)
if ("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.0")
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include_dirs})
set(target ${COMPONENT_LIB})
else()
# remove when dropping IDF 3.3 support
set(COMPONENT_SRCS ${srcs})
set(COMPONENT_ADD_INCLUDEDIRS ${include_dirs})
register_component()
set(target ${COMPONENT_TARGET})
endif()
# Embed binaries into the app.
# In ESP-IDF this can also be done using EMBED_FILES option of idf_component_register.
# Here an external tool is used to make file embedding similar with other ports.
include(${CMAKE_CURRENT_LIST_DIR}/../../common/bin2array.cmake)
create_resources(${CMAKE_CURRENT_LIST_DIR}/../../binaries/Hello-world ${CMAKE_BINARY_DIR}/binaries.c)
set_property(SOURCE ${CMAKE_BINARY_DIR}/binaries.c PROPERTY GENERATED 1)
target_sources(${target} PRIVATE ${CMAKE_BINARY_DIR}/binaries.c)

View File

@@ -0,0 +1,54 @@
/* Flash multiple partitions example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <sys/param.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp32_port.h"
#include "esp_loader.h"
#include "example_common.h"
static const char *TAG = "serial_flasher";
#define HIGHER_BAUDRATE 230400
void app_main(void)
{
example_binaries_t bin;
const loader_esp32_config_t config = {
.baud_rate = 115200,
.uart_port = UART_NUM_1,
.uart_rx_pin = GPIO_NUM_5,
.uart_tx_pin = GPIO_NUM_4,
.reset_trigger_pin = GPIO_NUM_25,
.gpio0_trigger_pin = GPIO_NUM_26,
};
if (loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) {
ESP_LOGE(TAG, "serial initialization failed.");
return;
}
if (connect_to_target(HIGHER_BAUDRATE) == ESP_LOADER_SUCCESS) {
get_example_binaries(esp_loader_get_target(), &bin);
ESP_LOGI(TAG, "Loading bootloader...");
flash_binary(bin.boot.data, bin.boot.size, bin.boot.addr);
ESP_LOGI(TAG, "Loading partition table...");
flash_binary(bin.part.data, bin.part.size, bin.part.addr);
ESP_LOGI(TAG, "Loading app...");
flash_binary(bin.app.data, bin.app.size, bin.app.addr);
ESP_LOGI(TAG, "Done!");
}
}

View File

@@ -0,0 +1,4 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, , 0x6000,
phy_init, data, phy, , 0x1000,
factory, app, factory, , 1500K,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x6000
3 phy_init data phy 0x1000
4 factory app factory 1500K

View File

@@ -0,0 +1 @@
CONFIG_PARTITION_TABLE_CUSTOM=y

View File

@@ -0,0 +1,7 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS ../../)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp32-serial-ram-loader)

View File

@@ -0,0 +1,14 @@
set(srcs main.c ../../common/example_common.c)
set(include_dirs . ../../common)
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include_dirs})
set(target ${COMPONENT_LIB})
# Embed binaries into the app.
# In ESP-IDF this can also be done using EMBED_FILES option of idf_component_register.
# Here an external tool is used to make file embedding similar with other ports.
include(${CMAKE_CURRENT_LIST_DIR}/../../common/bin2array.cmake)
create_resources(${CMAKE_CURRENT_LIST_DIR}/../../binaries/RAM_APP ${CMAKE_BINARY_DIR}/binaries.c)
set_property(SOURCE ${CMAKE_BINARY_DIR}/binaries.c PROPERTY GENERATED 1)
target_sources(${target} PRIVATE ${CMAKE_BINARY_DIR}/binaries.c)

View File

@@ -0,0 +1,80 @@
/* Example of loading the program into RAM
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <sys/param.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_task_wdt.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp32_port.h"
#include "esp_loader.h"
#include "example_common.h"
#include "freertos/FreeRTOS.h"
static const char *TAG = "serial_ram_loader";
// This can be set to a higher baud rate, but because it takes some time to
// switch the uart baud rate in slave_monitor task, the log at slave starup
// time will be lost or garbled.
#define HIGHER_BAUDRATE 115200
// Max line size
#define BUF_LEN 128
static uint8_t buf[BUF_LEN] = {0};
void slave_monitor(void *arg)
{
#if (HIGHER_BAUDRATE != 115200)
uart_flush_input(UART_NUM_1);
uart_flush(UART_NUM_1);
uart_set_baudrate(UART_NUM_1, 115200);
#endif
while (1) {
int rxBytes = uart_read_bytes(UART_NUM_1, buf, BUF_LEN, 100 / portTICK_PERIOD_MS);
buf[rxBytes] = '\0';
printf("%s", buf);
}
}
void app_main(void)
{
example_ram_app_binary_t bin;
const loader_esp32_config_t config = {
.baud_rate = 115200,
.uart_port = UART_NUM_1,
.uart_rx_pin = GPIO_NUM_5,
.uart_tx_pin = GPIO_NUM_4,
.reset_trigger_pin = GPIO_NUM_25,
.gpio0_trigger_pin = GPIO_NUM_26,
};
if (loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) {
ESP_LOGE(TAG, "serial initialization failed.");
abort();
}
if (connect_to_target(HIGHER_BAUDRATE) == ESP_LOADER_SUCCESS) {
get_example_ram_app_binary(esp_loader_get_target(), &bin);
ESP_LOGI(TAG, "Loading app to RAM ...");
esp_loader_error_t err = load_ram_binary(bin.ram_app.data);
if (err == ESP_LOADER_SUCCESS) {
// Forward slave's serial output
ESP_LOGI(TAG, "********************************************");
ESP_LOGI(TAG, "*** Logs below are print from slave .... ***");
ESP_LOGI(TAG, "********************************************");
xTaskCreate(slave_monitor, "slave_monitor", 2048, NULL, configMAX_PRIORITIES, NULL);
} else {
ESP_LOGE(TAG, "Loading to ram failed ...");
}
}
vTaskDelete(NULL);
}

View File

@@ -0,0 +1,7 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS ../../)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp32-spi-ram-loader)

View File

@@ -0,0 +1,80 @@
# Example of loading the program into RAM through SPI
## Overview
This example demonstrates how to upload an app to RAM of an Espressif MCU with SPI download support from another (host) MCU using the `esp_serial_flash` component API. In this case, another Espressif MCU is used as the host. Binaries to be uploaded to RAM from host MCU to the target MCU can be found in `binaries/RAM_APP` folder and are converted into C-array during build process.
Following steps are performed in order to re-program the target's memory:
1. SPI2 through which the binary will be transfered is initialized.
2. Host puts slave device into SPI download mode tries to connect by calling `esp_loader_connect()`.
3. Then `esp_loader_mem_start()` is called for each segment in RAM.
4. `esp_loader_flash_write()` function is called repeatedly for every segment until the whole binary image is transfered.
5. `esp_loader_mem_finish()` is called with the binary entrypoint, telling the chip to start the uploaded program.
6. UART2 is initialized for the connection to the target
7. Target output is continually read and printed
## Hardware Required
* Two development boards, one with any Espressif MCU (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) and one with an Espressif MCU with SPI download support. Here is a short list of supported MCUs:
1. ESP32-C3
2. ESP32-C2
3. ESP32-S3
4. ESP32-S2
5. ESP32-H2
* One or two USB cables for power supply and programming.
## Hardware connection
Table below shows connection between two Espressif MCUs.
| Host | Slave |
| IO_5 | RESET |
| IO_12 | CLK |
| IO_10 | CS |
| IO_13 | MISO |
| IO_11 | MOSI |
| IO_14 | QUADWP |
| IO_9 | QUADHD |
| IO_13 | STRAP_B0 |
| IO_2 | STRAP_B1 |
| IO_3 | STRAP_B2 |
| IO_4 | STRAP_B3 |
| IO_6 | UART0_RX |
| IO_7 | UART0_TX |
> Note 1: Strapping bit pins are documented in the TRM for each respective chip
> Note 2: For achieving highest speeds, check which pins go through the IO MUX bypassing the GPIO matrix and use those. Pins chosen here are IO MUX pins for ESP32S3 and ESP32S2 chips.
## Build and flash
To run the example, type the following command:
```CMake
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is the example's console output:
```
Connected to target
I (682) spi_ram_loader: Loading app to RAM ...
Start loading
Downloading 7840 bytes at 0x3fc96e00...
Downloading 312 bytes at 0x3fca0020...
Downloading 93164 bytes at 0x40380000...
Finished loading
I (802) spi_ram_loader: ********************************************
I (802) spi_ram_loader: *** Logs below are print from slave .... ***
I (812) spi_ram_loader: ********************************************
Hello world!
Hello world!
...
```

View File

@@ -0,0 +1,14 @@
set(srcs main.c ../../common/example_common.c)
set(include_dirs . ../../common)
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include_dirs})
set(target ${COMPONENT_LIB})
# Embed binaries into the app.
# In ESP-IDF this can also be done using EMBED_FILES option of idf_component_register.
# Here an external tool is used to make file embedding similar with other ports.
include(${CMAKE_CURRENT_LIST_DIR}/../../common/bin2array.cmake)
create_resources(${CMAKE_CURRENT_LIST_DIR}/../../binaries/RAM_APP ${CMAKE_BINARY_DIR}/binaries.c)
set_property(SOURCE ${CMAKE_BINARY_DIR}/binaries.c PROPERTY GENERATED 1)
target_sources(${target} PRIVATE ${CMAKE_BINARY_DIR}/binaries.c)

View File

@@ -0,0 +1,97 @@
/* Example of loading the program into RAM through SPI
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <sys/param.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_task_wdt.h"
#include "driver/spi_master.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp32_spi_port.h"
#include "esp_loader.h"
#include "example_common.h"
#include "freertos/FreeRTOS.h"
static const char *TAG = "spi_ram_loader";
// Max line size
#define BUF_LEN 128
static uint8_t buf[BUF_LEN] = {0};
void slave_monitor(void *arg)
{
// Initialize UART
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
.source_clk = UART_SCLK_DEFAULT,
#endif
};
ESP_ERROR_CHECK(uart_param_config(UART_NUM_2, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, GPIO_NUM_6, GPIO_NUM_7,
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, BUF_LEN * 4, BUF_LEN * 4, 0, NULL, 0));
while (1) {
int rxBytes = uart_read_bytes(UART_NUM_2, buf, BUF_LEN, 100 / portTICK_PERIOD_MS);
buf[rxBytes] = '\0';
printf("%s", buf);
}
}
void app_main(void)
{
example_ram_app_binary_t bin;
const loader_esp32_spi_config_t config = {
.spi_bus = SPI2_HOST,
.frequency = 20 * 1000000,
.reset_trigger_pin = GPIO_NUM_5,
.spi_clk_pin = GPIO_NUM_12,
.spi_cs_pin = GPIO_NUM_10,
.spi_miso_pin = GPIO_NUM_13,
.spi_mosi_pin = GPIO_NUM_11,
.spi_quadwp_pin = GPIO_NUM_14,
.spi_quadhd_pin = GPIO_NUM_9,
.strap_bit0_pin = GPIO_NUM_13,
.strap_bit1_pin = GPIO_NUM_2,
.strap_bit2_pin = GPIO_NUM_3,
.strap_bit3_pin = GPIO_NUM_4,
};
if (loader_port_esp32_spi_init(&config) != ESP_LOADER_SUCCESS) {
ESP_LOGE(TAG, "SPI initialization failed.");
abort();
}
if (connect_to_target(0) == ESP_LOADER_SUCCESS) {
get_example_ram_app_binary(esp_loader_get_target(), &bin);
ESP_LOGI(TAG, "Loading app to RAM ...");
esp_loader_error_t err = load_ram_binary(bin.ram_app.data);
if (err == ESP_LOADER_SUCCESS) {
// Forward slave's serial output
ESP_LOGI(TAG, "********************************************");
ESP_LOGI(TAG, "*** Logs below are print from slave .... ***");
ESP_LOGI(TAG, "********************************************");
xTaskCreate(slave_monitor, "slave_monitor", 2048, NULL, configMAX_PRIORITIES, NULL);
} else {
ESP_LOGE(TAG, "Loading to RAM failed ...");
}
}
vTaskDelete(NULL);
}

View File

@@ -0,0 +1,4 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
#
CONFIG_SERIAL_FLASHER_INTERFACE_SPI=y

View File

@@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.5)
set(FLASHER_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
set(PORT RASPBERRY_PI)
project(raspberry_flasher)
add_executable(${CMAKE_PROJECT_NAME} Src/main.c ../common/example_common.c)
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ../common/)
add_subdirectory(${FLASHER_DIR} ${CMAKE_BINARY_DIR}/flasher)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE flasher)
# This example only supports one target (ESP32) and uses specific binary to be flashed.
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE -DSINGLE_TARGET_SUPPORT=1)

View File

@@ -0,0 +1,76 @@
# Raspberry Pi example
## Overview
Example demonstrates how to flash ESP32 from Raspberry Pi 4 (Model B) using esp_serial_flash component API. AT command firmware to be flashed from Raspberry Pi to ESP32 can be found in `binaries`. USART0 is dedicated for communication with ESP32.
Following steps are performed in order to re-program target's memory:
1. Peripherals are initialized.
2. Host puts slave device into boot mode tries to connect by calling `esp_loader_connect()`.
3. Then `esp_loader_flash_start()` is called to enter flashing mode and erase amount of memory to be flashed.
4. `esp_loader_flash_write()` function is called repeatedly until the whole binary image is transfered.
5. At the end, `loader_port_reset_target()` is called to restart ESP32 and execute updated firmware.
Note: In addition, to steps mentioned above, `esp_loader_change_transmission_rate` is called after connection is established in order to increase flashing speed. Bootloader is also capable of detecting baud rate during connection phase, and can be changed before calling `esp_loader_connect`. However, it is recommended to start at lower speed and then use dedicated command to increase baud rate. This does not apply for ESP8266, as its bootloader does not support this command, therefore, baud rate can only be changed before connection phase in this case.
## Hardware Required
* Raspberry Pi 4 Model B.
* A development board with ESP32 SoC (e.g. ESP-WROVER-KIT, ESP32-DevKitC, etc.).
* USB cable in case ESP32 board is powered from USB. ESP32 can be powered by Raspberry Pi as well.
## Hardware connection
Table below shows connection between Raspberry Pi and ESP32.
| Raspberry Pi (host) | ESP32 (slave) |
|:-------------------:|:-------------------:|
| GPIO3 | IO0 |
| GPIO2 | RST |
| GPIO14 | RX0 |
| GPIO15 | TX0 |
| GND | GND |
Optionally, UART-to-USB bridge can be connected to PD5(RX) and PD6(TX) for debug purposes.
## Installation
### GPIO library
Raspberry Pi makes use of [pigpio](http://abyz.me.uk/rpi/pigpio/) library in order to simplify controlling GPIO pins. Some distributions of 'Raspberry Pi OS' may come with `pigpio` already installed. Presence of the library in the system can checked by running command:
```
pigpiod -v
```
If not present, run following commands to install the library.
```
sudo apt-get update
sudo apt-get install pigpio
```
### Enable UART
On Raspberry Pi 4, primary UART (UART0) is connected to the On-board Bluetooth module by default.
In order to enable serial communication on this UART, run following command in terminal:
```
sudo raspi-config
```
* Navigate to **Interfacing Options -> Serial**.
* Then it will ask for login shell to be accessible over Serial, select **No**.
* After that, it will ask for enabling Hardware Serial port, select **Yes**.
* Reboot the Raspberry Pi.
## Build and run
To compile the example:
Create and navigate to `build` directory:
```
mkdir build && cd build
```
Run cmake, build example and run example:
```
cmake .. && cmake --build . && ./raspberry_flasher
```
For more details regarding to esp_serial_flasher configuration, please refer to top level [README.md](../../README.md).

View File

@@ -0,0 +1,81 @@
/* Flash multiple partitions example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include "esp_loader.h"
#include "example_common.h"
#include "raspberry_port.h"
#define TARGET_RST_Pin 2
#define TARGET_IO0_Pin 3
#define DEFAULT_BAUD_RATE 115200
#define HIGHER_BAUD_RATE 460800
#define SERIAL_DEVICE "/dev/ttyS0"
#define BINARY_PATH "../../binaries/ESP32_AT_Firmware/Firmware.bin"
static void upload_file(const char *path, size_t address)
{
char *buffer = NULL;
FILE *image = fopen(path, "r");
if (image == NULL) {
printf("Error:Failed to open file %s\n", path);
return;
}
fseek(image, 0L, SEEK_END);
size_t size = ftell(image);
rewind(image);
printf("File %s opened. Size: %u bytes\n", path, size);
buffer = (char *)malloc(size);
if (buffer == NULL) {
printf("Error: Failed allocate memory\n");
goto cleanup;
}
// copy file content to buffer
size_t bytes_read = fread(buffer, 1, size, image);
if (bytes_read != size) {
printf("Error occurred while reading file");
goto cleanup;
}
flash_binary(buffer, size, address);
cleanup:
fclose(image);
free(buffer);
}
int main(void)
{
const loader_raspberry_config_t config = {
.device = SERIAL_DEVICE,
.baudrate = DEFAULT_BAUD_RATE,
.reset_trigger_pin = TARGET_RST_Pin,
.gpio0_trigger_pin = TARGET_IO0_Pin,
};
loader_port_raspberry_init(&config);
if (connect_to_target(HIGHER_BAUD_RATE) == ESP_LOADER_SUCCESS) {
upload_file(BINARY_PATH, 0);
}
loader_port_reset_target();
}

View File

@@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.5)
include(${CMAKE_CURRENT_LIST_DIR}/../common/bin2array.cmake)
set(TOOLCHAIN_PREFIX / CACHE PATH "Path to arm toolchain")
set(STM32Cube_DIR / CACHE PATH "Path to STM32 hal library")
set(FLASHER_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
set(CMAKE_TOOLCHAIN_FILE ${FLASHER_DIR}/submodules/stm32-cmake/cmake/gcc_stm32.cmake)
set(STM32_CHIP STM32F407VG)
set(PORT STM32)
project(stm32_flasher)
enable_language(ASM)
create_resources(${CMAKE_CURRENT_LIST_DIR}/../binaries/Hello-world Src/binaries.c)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} Inc)
add_executable(${CMAKE_PROJECT_NAME}
../common/example_common.c
Src/main.c
Src/stm32f4xx_hal_msp.c
Src/stm32f4xx_it.c
Src/libc_compat.c
Src/binaries.c)
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ../common)
add_subdirectory(${FLASHER_DIR}/submodules ${CMAKE_BINARY_DIR}/submodules)
add_subdirectory(${FLASHER_DIR} ${CMAKE_BINARY_DIR}/flasher)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE stm_cube flasher)
STM32_ADD_HEX_BIN_TARGETS(${CMAKE_PROJECT_NAME})
add_custom_target(BuildBinary ALL)
add_dependencies(BuildBinary ${CMAKE_PROJECT_NAME}.bin)

View File

@@ -0,0 +1,50 @@
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx_hal.h"
void Error_Handler(void);
#define GREEN_LED_Pin GPIO_PIN_12
#define GREEN_LED_GPIO_Port GPIOD
#define ORANGE_LED_Pin GPIO_PIN_13
#define ORANGE_LED_GPIO_Port GPIOD
#define RED_LED_Pin GPIO_PIN_14
#define RED_LED_GPIO_Port GPIOD
#define BLUE_LED_Pin GPIO_PIN_15
#define BLUE_LED_GPIO_Port GPIOD
#define TARGET_RST_Pin GPIO_PIN_4
#define TARGET_RST_GPIO_Port GPIOB
#define TARGET_IO0_Pin GPIO_PIN_5
#define TARGET_IO0_GPIO_Port GPIOB
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,443 @@
/**
******************************************************************************
* @file stm32f4xx_hal_conf_template.h
* @author MCD Application Team
* @brief HAL configuration template file.
* This file should be copied to the application folder and renamed
* to stm32f4xx_hal_conf.h.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_HAL_CONF_H
#define __STM32F4xx_HAL_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* ########################## Module Selection ############################## */
/**
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_MODULE_ENABLED
/* #define HAL_ADC_MODULE_ENABLED */
/* #define HAL_CRYP_MODULE_ENABLED */
/* #define HAL_CAN_MODULE_ENABLED */
/* #define HAL_CRC_MODULE_ENABLED */
/* #define HAL_CRYP_MODULE_ENABLED */
/* #define HAL_DAC_MODULE_ENABLED */
/* #define HAL_DCMI_MODULE_ENABLED */
/* #define HAL_DMA2D_MODULE_ENABLED */
/* #define HAL_ETH_MODULE_ENABLED */
/* #define HAL_NAND_MODULE_ENABLED */
/* #define HAL_NOR_MODULE_ENABLED */
/* #define HAL_PCCARD_MODULE_ENABLED */
/* #define HAL_SRAM_MODULE_ENABLED */
/* #define HAL_SDRAM_MODULE_ENABLED */
/* #define HAL_HASH_MODULE_ENABLED */
/* #define HAL_I2C_MODULE_ENABLED */
/* #define HAL_I2S_MODULE_ENABLED */
/* #define HAL_IWDG_MODULE_ENABLED */
/* #define HAL_LTDC_MODULE_ENABLED */
/* #define HAL_RNG_MODULE_ENABLED */
/* #define HAL_RTC_MODULE_ENABLED */
/* #define HAL_SAI_MODULE_ENABLED */
/* #define HAL_SD_MODULE_ENABLED */
/* #define HAL_MMC_MODULE_ENABLED */
/* #define HAL_SPI_MODULE_ENABLED */
/* #define HAL_TIM_MODULE_ENABLED */
#define HAL_UART_MODULE_ENABLED
/* #define HAL_USART_MODULE_ENABLED */
/* #define HAL_IRDA_MODULE_ENABLED */
/* #define HAL_SMARTCARD_MODULE_ENABLED */
/* #define HAL_SMBUS_MODULE_ENABLED */
/* #define HAL_WWDG_MODULE_ENABLED */
/* #define HAL_PCD_MODULE_ENABLED */
/* #define HAL_HCD_MODULE_ENABLED */
/* #define HAL_DSI_MODULE_ENABLED */
/* #define HAL_QSPI_MODULE_ENABLED */
/* #define HAL_QSPI_MODULE_ENABLED */
/* #define HAL_CEC_MODULE_ENABLED */
/* #define HAL_FMPI2C_MODULE_ENABLED */
/* #define HAL_SPDIFRX_MODULE_ENABLED */
/* #define HAL_DFSDM_MODULE_ENABLED */
/* #define HAL_LPTIM_MODULE_ENABLED */
#define HAL_GPIO_MODULE_ENABLED
#define HAL_EXTI_MODULE_ENABLED
#define HAL_DMA_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
#define HAL_FLASH_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
/* ########################## HSE/HSI Values adaptation ##################### */
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)25000000U) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL).
*/
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @brief Internal Low Speed oscillator (LSI) value.
*/
#if !defined (LSI_VALUE)
#define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
in voltage and temperature.*/
/**
* @brief External Low Speed oscillator (LSE) value.
*/
#if !defined (LSE_VALUE)
#define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */
#endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */
/**
* @brief External clock source for I2S peripheral
* This value is used by the I2S HAL module to compute the I2S clock source
* frequency, this source is inserted directly through I2S_CKIN pad.
*/
#if !defined (EXTERNAL_CLOCK_VALUE)
#define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/
#endif /* EXTERNAL_CLOCK_VALUE */
/* Tip: To avoid modifying this file each time you need to use different HSE,
=== you can define the HSE value in your toolchain compiler preprocessor. */
/* ########################### System Configuration ######################### */
/**
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */
#define USE_RTOS 0U
#define PREFETCH_ENABLE 1U
#define INSTRUCTION_CACHE_ENABLE 1U
#define DATA_CACHE_ENABLE 1U
/* ########################## Assert Selection ############################## */
/**
* @brief Uncomment the line below to expanse the "assert_param" macro in the
* HAL drivers code
*/
/* #define USE_FULL_ASSERT 1U */
/* ################## Ethernet peripheral configuration ##################### */
/* Section 1 : Ethernet peripheral configuration */
/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
#define MAC_ADDR0 2U
#define MAC_ADDR1 0U
#define MAC_ADDR2 0U
#define MAC_ADDR3 0U
#define MAC_ADDR4 0U
#define MAC_ADDR5 0U
/* Definition of the Ethernet driver buffers size and count */
#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
/* Section 2: PHY configuration section */
/* DP83848_PHY_ADDRESS Address*/
#define DP83848_PHY_ADDRESS 0x01U
/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
#define PHY_RESET_DELAY ((uint32_t)0x000000FFU)
/* PHY Configuration delay */
#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU)
#define PHY_READ_TO ((uint32_t)0x0000FFFFU)
#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU)
/* Section 3: Common PHY Registers */
#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */
#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */
#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */
#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */
#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */
#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */
#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */
#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */
#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */
#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */
#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */
#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */
#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */
#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */
#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */
/* Section 4: Extended PHY Registers */
#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */
#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */
#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */
/* ################## SPI peripheral configuration ########################## */
/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
* Activated: CRC code is present inside driver
* Deactivated: CRC code cleaned from driver
*/
#define USE_SPI_CRC 0U
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include module's header file
*/
#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32f4xx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */
#ifdef HAL_EXTI_MODULE_ENABLED
#include "stm32f4xx_hal_exti.h"
#endif /* HAL_EXTI_MODULE_ENABLED */
#ifdef HAL_GPIO_MODULE_ENABLED
#include "stm32f4xx_hal_gpio.h"
#endif /* HAL_GPIO_MODULE_ENABLED */
#ifdef HAL_DMA_MODULE_ENABLED
#include "stm32f4xx_hal_dma.h"
#endif /* HAL_DMA_MODULE_ENABLED */
#ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32f4xx_hal_cortex.h"
#endif /* HAL_CORTEX_MODULE_ENABLED */
#ifdef HAL_ADC_MODULE_ENABLED
#include "stm32f4xx_hal_adc.h"
#endif /* HAL_ADC_MODULE_ENABLED */
#ifdef HAL_CAN_MODULE_ENABLED
#include "stm32f4xx_hal_can.h"
#endif /* HAL_CAN_MODULE_ENABLED */
#ifdef HAL_CRC_MODULE_ENABLED
#include "stm32f4xx_hal_crc.h"
#endif /* HAL_CRC_MODULE_ENABLED */
#ifdef HAL_CRYP_MODULE_ENABLED
#include "stm32f4xx_hal_cryp.h"
#endif /* HAL_CRYP_MODULE_ENABLED */
#ifdef HAL_SMBUS_MODULE_ENABLED
#include "stm32f4xx_hal_smbus.h"
#endif /* HAL_SMBUS_MODULE_ENABLED */
#ifdef HAL_DMA2D_MODULE_ENABLED
#include "stm32f4xx_hal_dma2d.h"
#endif /* HAL_DMA2D_MODULE_ENABLED */
#ifdef HAL_DAC_MODULE_ENABLED
#include "stm32f4xx_hal_dac.h"
#endif /* HAL_DAC_MODULE_ENABLED */
#ifdef HAL_DCMI_MODULE_ENABLED
#include "stm32f4xx_hal_dcmi.h"
#endif /* HAL_DCMI_MODULE_ENABLED */
#ifdef HAL_ETH_MODULE_ENABLED
#include "stm32f4xx_hal_eth.h"
#endif /* HAL_ETH_MODULE_ENABLED */
#ifdef HAL_FLASH_MODULE_ENABLED
#include "stm32f4xx_hal_flash.h"
#endif /* HAL_FLASH_MODULE_ENABLED */
#ifdef HAL_SRAM_MODULE_ENABLED
#include "stm32f4xx_hal_sram.h"
#endif /* HAL_SRAM_MODULE_ENABLED */
#ifdef HAL_NOR_MODULE_ENABLED
#include "stm32f4xx_hal_nor.h"
#endif /* HAL_NOR_MODULE_ENABLED */
#ifdef HAL_NAND_MODULE_ENABLED
#include "stm32f4xx_hal_nand.h"
#endif /* HAL_NAND_MODULE_ENABLED */
#ifdef HAL_PCCARD_MODULE_ENABLED
#include "stm32f4xx_hal_pccard.h"
#endif /* HAL_PCCARD_MODULE_ENABLED */
#ifdef HAL_SDRAM_MODULE_ENABLED
#include "stm32f4xx_hal_sdram.h"
#endif /* HAL_SDRAM_MODULE_ENABLED */
#ifdef HAL_HASH_MODULE_ENABLED
#include "stm32f4xx_hal_hash.h"
#endif /* HAL_HASH_MODULE_ENABLED */
#ifdef HAL_I2C_MODULE_ENABLED
#include "stm32f4xx_hal_i2c.h"
#endif /* HAL_I2C_MODULE_ENABLED */
#ifdef HAL_I2S_MODULE_ENABLED
#include "stm32f4xx_hal_i2s.h"
#endif /* HAL_I2S_MODULE_ENABLED */
#ifdef HAL_IWDG_MODULE_ENABLED
#include "stm32f4xx_hal_iwdg.h"
#endif /* HAL_IWDG_MODULE_ENABLED */
#ifdef HAL_LTDC_MODULE_ENABLED
#include "stm32f4xx_hal_ltdc.h"
#endif /* HAL_LTDC_MODULE_ENABLED */
#ifdef HAL_PWR_MODULE_ENABLED
#include "stm32f4xx_hal_pwr.h"
#endif /* HAL_PWR_MODULE_ENABLED */
#ifdef HAL_RNG_MODULE_ENABLED
#include "stm32f4xx_hal_rng.h"
#endif /* HAL_RNG_MODULE_ENABLED */
#ifdef HAL_RTC_MODULE_ENABLED
#include "stm32f4xx_hal_rtc.h"
#endif /* HAL_RTC_MODULE_ENABLED */
#ifdef HAL_SAI_MODULE_ENABLED
#include "stm32f4xx_hal_sai.h"
#endif /* HAL_SAI_MODULE_ENABLED */
#ifdef HAL_SD_MODULE_ENABLED
#include "stm32f4xx_hal_sd.h"
#endif /* HAL_SD_MODULE_ENABLED */
#ifdef HAL_MMC_MODULE_ENABLED
#include "stm32f4xx_hal_mmc.h"
#endif /* HAL_MMC_MODULE_ENABLED */
#ifdef HAL_SPI_MODULE_ENABLED
#include "stm32f4xx_hal_spi.h"
#endif /* HAL_SPI_MODULE_ENABLED */
#ifdef HAL_TIM_MODULE_ENABLED
#include "stm32f4xx_hal_tim.h"
#endif /* HAL_TIM_MODULE_ENABLED */
#ifdef HAL_UART_MODULE_ENABLED
#include "stm32f4xx_hal_uart.h"
#endif /* HAL_UART_MODULE_ENABLED */
#ifdef HAL_USART_MODULE_ENABLED
#include "stm32f4xx_hal_usart.h"
#endif /* HAL_USART_MODULE_ENABLED */
#ifdef HAL_IRDA_MODULE_ENABLED
#include "stm32f4xx_hal_irda.h"
#endif /* HAL_IRDA_MODULE_ENABLED */
#ifdef HAL_SMARTCARD_MODULE_ENABLED
#include "stm32f4xx_hal_smartcard.h"
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
#ifdef HAL_WWDG_MODULE_ENABLED
#include "stm32f4xx_hal_wwdg.h"
#endif /* HAL_WWDG_MODULE_ENABLED */
#ifdef HAL_PCD_MODULE_ENABLED
#include "stm32f4xx_hal_pcd.h"
#endif /* HAL_PCD_MODULE_ENABLED */
#ifdef HAL_HCD_MODULE_ENABLED
#include "stm32f4xx_hal_hcd.h"
#endif /* HAL_HCD_MODULE_ENABLED */
#ifdef HAL_DSI_MODULE_ENABLED
#include "stm32f4xx_hal_dsi.h"
#endif /* HAL_DSI_MODULE_ENABLED */
#ifdef HAL_QSPI_MODULE_ENABLED
#include "stm32f4xx_hal_qspi.h"
#endif /* HAL_QSPI_MODULE_ENABLED */
#ifdef HAL_CEC_MODULE_ENABLED
#include "stm32f4xx_hal_cec.h"
#endif /* HAL_CEC_MODULE_ENABLED */
#ifdef HAL_FMPI2C_MODULE_ENABLED
#include "stm32f4xx_hal_fmpi2c.h"
#endif /* HAL_FMPI2C_MODULE_ENABLED */
#ifdef HAL_SPDIFRX_MODULE_ENABLED
#include "stm32f4xx_hal_spdifrx.h"
#endif /* HAL_SPDIFRX_MODULE_ENABLED */
#ifdef HAL_DFSDM_MODULE_ENABLED
#include "stm32f4xx_hal_dfsdm.h"
#endif /* HAL_DFSDM_MODULE_ENABLED */
#ifdef HAL_LPTIM_MODULE_ENABLED
#include "stm32f4xx_hal_lptim.h"
#endif /* HAL_LPTIM_MODULE_ENABLED */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_HAL_CONF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,42 @@
/**
******************************************************************************
* @file stm32f4xx_it.h
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#ifndef __STM32F4xx_IT_H
#define __STM32F4xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_IT_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,59 @@
# STM32 example
## Overview
Example demonstrates how to flash ESP32 from another STM32 (host MCU) using esp_serial_flash component API. STM32F4-Discovery board is used in this example, as STM32F407VG has FLASH memory large enough to fit the whole hello-world example of ESP32. Binaries to be flashed from host MCU to ESP32 can be found in `binaries` directory and converted into C-arrays during build process. USART1 is dedicated for communication with ESP32, whereas, USART2 can be used for debug purposes by attaching UART-to-USB bridge.
Following steps are performed in order to re-program target's memory:
1. Peripherals are initialized.
2. Host puts slave device into boot mode tries to connect by calling `esp_loader_connect()`.
3. Then `esp_loader_flash_start()` is called to enter flashing mode and erase amount of memory to be flashed.
4. `esp_loader_flash_write()` function is called repeatedly until the whole binary image is transfered.
Note: In addition, to steps mentioned above, `esp_loader_change_transmission_rate` is called after connection is established in order to increase flashing speed. Bootloader is also capable of detecting baud rate during connection phase, and can be changed before calling `esp_loader_connect`. However, it is recommended to start at lower speed and then use dedicated command to increase baud rate. This does not apply for ESP8266, as its bootloader does not support this command, therefore, baud rate can only be changed before connection phase in this case.
## Hardware Required
* STM32F4-Discovery board.
* A development board with ESP32 SoC (e.g. ESP-WROVER-KIT, ESP32-DevKitC, etc.).
* One or two USB cables for power supply and programming.
## Hardware connection
Table below shows connection between STM32 and ESP32.
| STM32 (host) | ESP32 (slave) |
|:------------:|:-------------:|
| PB5 | IO0 |
| PB4 | RST |
| PB6 | RX0 |
| PB7 | TX0 |
Optionally, UART-to-USB bridge can be connected to PD5(RX) and PD6(TX) for debug purposes.
## Build and flash
To compile the example:
Create and navigate to `build` directory:
```
mkdir build && cd build
```
Run cmake (with appropriate parameters) and build:
```
cmake -DTOOLCHAIN_PREFIX="/path_to_toolchain" -DSTM32Cube_DIR="path_to_stm32Cube" -DSTM32_CHIP="STM32F407VG" -DPORT="STM32" .. && cmake --build .
```
Binaries to be flashed are placed in separate folder (binaries.c) for each possible target and converted to C-array. Without explicitly enabling MD5 check, flash integrity verification is disabled by default.
For more details regarding to esp_serial_flasher configuration and STM32 support, please refer to top level [README.md](../../README.md).
Note: CMake 3.13 or later is required.
## STM32CubeMx configuration
Following configuration was used to generate STM32 `cmake` based project:
* Project tab: Toolchain/IDE - Other toolchain (GPDSC)
* Code Generator tab: Add necessary files as reference in the toolchain project configuration file

View File

@@ -0,0 +1,183 @@
/* libc_compat
This code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <errno.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/unistd.h>
#include <sys/time.h>
#if defined STM32F1
# include <stm32f1xx_hal.h>
#elif defined STM32F2
# include <stm32f2xx_hal.h>
#elif defined STM32F4
# include <stm32f4xx_hal.h>
#elif defined STM32G0
# include <stm32g0xx_hal.h>
#endif
extern uint32_t __get_MSP(void);
extern UART_HandleTypeDef huart2;
extern uint64_t virtualTimer;
#undef errno
extern int errno;
char *__env[1] = { 0 };
char **environ = __env;
int _write(int file, char *ptr, int len);
void _exit(int status)
{
while (1);
}
int _close(int file)
{
return -1;
}
int _execve(char *name, char **argv, char **env)
{
errno = ENOMEM;
return -1;
}
int _fork()
{
errno = EAGAIN;
return -1;
}
int _fstat(int file, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
int _getpid()
{
return 1;
}
int _gettimeofday(struct timeval *tv, struct timezone *tz)
{
tv->tv_sec = HAL_GetTick() / 1000;
tv->tv_usec = (HAL_GetTick() % 1000) * 1000;
return 0;
}
int _isatty(int file)
{
switch (file)
{
case STDOUT_FILENO:
case STDERR_FILENO:
case STDIN_FILENO:
return 1;
default:
//errno = ENOTTY;
errno = EBADF;
return 0;
}
}
int _kill(int pid, int sig)
{
errno = EINVAL;
return (-1);
}
int _link(char *old, char *new)
{
errno = EMLINK;
return -1;
}
int _lseek(int file, int ptr, int dir)
{
return 0;
}
caddr_t _sbrk(int incr)
{
extern char _ebss;
static char *heap_end= &_ebss;
char *prev_heap_end;
prev_heap_end = heap_end;
char * stack = (char*) __get_MSP();
if (heap_end + incr > stack)
{
_write(STDERR_FILENO, "Heap and stack collision\n", 25);
errno = ENOMEM;
return (caddr_t) - 1;
//abort ();
}
heap_end += incr;
return (caddr_t) prev_heap_end;
}
int _read(int file, char *ptr, int len)
{
switch (file)
{
case STDIN_FILENO:
HAL_UART_Receive(&huart2, (uint8_t *)ptr, 1, HAL_MAX_DELAY);
return 1;
default:
errno = EBADF;
return -1;
}
}
int _stat(const char *filepath, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
clock_t _times(struct tms *buf)
{
return -1;
}
int _unlink(char *name)
{
errno = ENOENT;
return -1;
}
int _wait(int *status)
{
errno = ECHILD;
return -1;
}
int _write(int file, char *ptr, int len)
{
switch (file)
{
case STDOUT_FILENO: /*stdout*/
HAL_UART_Transmit(&huart2, (uint8_t*)ptr, len, HAL_MAX_DELAY);
break;
case STDERR_FILENO: /* stderr */
HAL_UART_Transmit(&huart2, (uint8_t*)ptr, len, HAL_MAX_DELAY);
break;
default:
errno = EBADF;
return -1;
}
return len;
}

View File

@@ -0,0 +1,189 @@
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "main.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/param.h>
#include "stm32_port.h"
#include "esp_loader.h"
#include "example_common.h"
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART2_UART_Init(void);
#define HIGHER_BAUDRATE 230400
int main(void)
{
example_binaries_t bin;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
loader_stm32_config_t config = {
.huart = &huart1,
.port_io0 = GPIOB,
.pin_num_io0 = TARGET_IO0_Pin,
.port_rst = GPIOB,
.pin_num_rst = TARGET_RST_Pin,
};
loader_port_stm32_init(&config);
if (connect_to_target(HIGHER_BAUDRATE) == ESP_LOADER_SUCCESS) {
get_example_binaries(esp_loader_get_target(), &bin);
flash_binary(bin.boot.data, bin.boot.size, bin.boot.addr);
flash_binary(bin.part.data, bin.part.size, bin.part.addr);
flash_binary(bin.app.data, bin.app.size, bin.app.addr);
}
while (1) { }
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
Error_Handler();
}
}
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK) {
Error_Handler();
}
}
static void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK) {
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, GREEN_LED_Pin | ORANGE_LED_Pin | RED_LED_Pin | BLUE_LED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, TARGET_RST_Pin | TARGET_IO0_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : GREEN_LED_Pin ORANGE_LED_Pin RED_LED_Pin BLUE_LED_Pin */
GPIO_InitStruct.Pin = GREEN_LED_Pin | ORANGE_LED_Pin | RED_LED_Pin | BLUE_LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pins : PB4 PB5 */
GPIO_InitStruct.Pin = TARGET_RST_Pin | TARGET_IO0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* User can add his own implementation to report the HAL error return state */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,109 @@
/**
******************************************************************************
* File Name : stm32f4xx_hal_msp.c
* Description : This file provides code for the MSP Initialization
* and de-Initialization codes.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "main.h"
void HAL_MspInit(void)
{
__HAL_RCC_SYSCFG_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
}
/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(huart->Instance==USART1)
{
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART1 GPIO Configuration
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
else if(huart->Instance==USART2)
{
/* Peripheral clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**USART2 GPIO Configuration
PD5 ------> USART2_TX
PD6 ------> USART2_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
}
/**
* @brief UART MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
if(huart->Instance==USART1)
{
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7);
}
else if(huart->Instance==USART2)
{
/* Peripheral clock disable */
__HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
PD5 ------> USART2_TX
PD6 ------> USART2_RX
*/
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_5|GPIO_PIN_6);
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,204 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f4xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M4 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Pre-fetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVCall_IRQn 0 */
/* USER CODE END SVCall_IRQn 0 */
/* USER CODE BEGIN SVCall_IRQn 1 */
/* USER CODE END SVCall_IRQn 1 */
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
/******************************************************************************/
/* STM32F4xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f4xx.s). */
/******************************************************************************/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,727 @@
/**
******************************************************************************
* @file system_stm32f4xx.c
* @author MCD Application Team
* @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
*
* This file provides two functions and one global variable to be called from
* user application:
* - SystemInit(): This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32f4xx.s" file.
*
* - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
* by the user application to setup the SysTick
* timer or configure other parameters.
*
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
* be called whenever the core clock is changed
* during program execution.
*
*
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32f4xx_system
* @{
*/
/** @addtogroup STM32F4xx_System_Private_Includes
* @{
*/
#include "stm32f4xx.h"
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Defines
* @{
*/
/************************* Miscellaneous Configuration ************************/
/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
|| defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
/* #define DATA_IN_ExtSRAM */
#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\
STM32F412Zx || STM32F412Vx */
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
/* #define DATA_IN_ExtSDRAM */
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\
STM32F479xx */
/*!< Uncomment the following line if you need to relocate your vector Table in
Internal SRAM. */
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
/******************************************************************************/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Variables
* @{
*/
/* This variable is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
Note: If you use this function to configure the system clock; then there
is no need to call the 2 first functions listed above, since SystemCoreClock
variable is updated automatically.
*/
uint32_t SystemCoreClock = 16000000;
const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
* @{
*/
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
static void SystemInit_ExtMemCtl(void);
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Functions
* @{
*/
/**
* @brief Setup the microcontroller system
* Initialize the FPU setting, vector table location and External memory
* configuration.
* @param None
* @retval None
*/
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}
/**
* @brief Update SystemCoreClock variable according to Clock Register Values.
* The SystemCoreClock variable contains the core clock (HCLK), it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock (HCLK) changes, this function must be called
* to update SystemCoreClock variable value. Otherwise, any configuration
* based on this variable will be incorrect.
*
* @note - The system frequency computed by this function is not the real
* frequency in the chip. It is calculated based on the predefined
* constant and the selected clock source:
*
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
*
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
*
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
* or HSI_VALUE(*) multiplied/divided by the PLL factors.
*
* (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
* 16 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value
* depends on the application requirements), user has to ensure that HSE_VALUE
* is same as the real frequency of the crystal used. Otherwise, this function
* may have wrong result.
*
* - The result of this function could be not correct when using fractional
* value for HSE crystal.
*
* @param None
* @retval None
*/
void SystemCoreClockUpdate(void)
{
uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & RCC_CFGR_SWS;
switch (tmp)
{
case 0x00: /* HSI used as system clock source */
SystemCoreClock = HSI_VALUE;
break;
case 0x04: /* HSE used as system clock source */
SystemCoreClock = HSE_VALUE;
break;
case 0x08: /* PLL used as system clock source */
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
SYSCLK = PLL_VCO / PLL_P
*/
pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
if (pllsource != 0)
{
/* HSE used as PLL clock source */
pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
}
else
{
/* HSI used as PLL clock source */
pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
}
pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
SystemCoreClock = pllvco/pllp;
break;
default:
SystemCoreClock = HSI_VALUE;
break;
}
/* Compute HCLK frequency --------------------------------------------------*/
/* Get HCLK prescaler */
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
/* HCLK frequency */
SystemCoreClock >>= tmp;
}
#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM)
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx)
/**
* @brief Setup the external memory controller.
* Called in startup_stm32f4xx.s before jump to main.
* This function configures the external memories (SRAM/SDRAM)
* This SRAM/SDRAM will be used as program data memory (including heap and stack).
* @param None
* @retval None
*/
void SystemInit_ExtMemCtl(void)
{
__IO uint32_t tmp = 0x00;
register uint32_t tmpreg = 0, timeout = 0xFFFF;
register __IO uint32_t index;
/* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */
RCC->AHB1ENR |= 0x000001F8;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x00CCC0CC;
GPIOD->AFR[1] = 0xCCCCCCCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xAAAA0A8A;
/* Configure PDx pins speed to 100 MHz */
GPIOD->OSPEEDR = 0xFFFF0FCF;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000;
/* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[0] = 0xC00CC0CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA828A;
/* Configure PEx pins speed to 100 MHz */
GPIOE->OSPEEDR = 0xFFFFC3CF;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000;
/* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[0] = 0xCCCCCCCC;
GPIOF->AFR[1] = 0xCCCCCCCC;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA800AAA;
/* Configure PFx pins speed to 50 MHz */
GPIOF->OSPEEDR = 0xAA800AAA;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000;
/* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[0] = 0xCCCCCCCC;
GPIOG->AFR[1] = 0xCCCCCCCC;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0xAAAAAAAA;
/* Configure PGx pins speed to 50 MHz */
GPIOG->OSPEEDR = 0xAAAAAAAA;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000;
/* Connect PHx pins to FMC Alternate function */
GPIOH->AFR[0] = 0x00C0CC00;
GPIOH->AFR[1] = 0xCCCCCCCC;
/* Configure PHx pins in Alternate function mode */
GPIOH->MODER = 0xAAAA08A0;
/* Configure PHx pins speed to 50 MHz */
GPIOH->OSPEEDR = 0xAAAA08A0;
/* Configure PHx pins Output type to push-pull */
GPIOH->OTYPER = 0x00000000;
/* No pull-up, pull-down for PHx pins */
GPIOH->PUPDR = 0x00000000;
/* Connect PIx pins to FMC Alternate function */
GPIOI->AFR[0] = 0xCCCCCCCC;
GPIOI->AFR[1] = 0x00000CC0;
/* Configure PIx pins in Alternate function mode */
GPIOI->MODER = 0x0028AAAA;
/* Configure PIx pins speed to 50 MHz */
GPIOI->OSPEEDR = 0x0028AAAA;
/* Configure PIx pins Output type to push-pull */
GPIOI->OTYPER = 0x00000000;
/* No pull-up, pull-down for PIx pins */
GPIOI->PUPDR = 0x00000000;
/*-- FMC Configuration -------------------------------------------------------*/
/* Enable the FMC interface clock */
RCC->AHB3ENR |= 0x00000001;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
FMC_Bank5_6->SDCR[0] = 0x000019E4;
FMC_Bank5_6->SDTR[0] = 0x01115351;
/* SDRAM initialization sequence */
/* Clock enable command */
FMC_Bank5_6->SDCMR = 0x00000011;
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Delay */
for (index = 0; index<1000; index++);
/* PALL command */
FMC_Bank5_6->SDCMR = 0x00000012;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Auto refresh command */
FMC_Bank5_6->SDCMR = 0x00000073;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* MRD register program */
FMC_Bank5_6->SDCMR = 0x00046014;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Set refresh count */
tmpreg = FMC_Bank5_6->SDRTR;
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
/* Disable write protection */
tmpreg = FMC_Bank5_6->SDCR[0];
FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001011;
FMC_Bank1->BTCR[3] = 0x00000201;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
#if defined(STM32F469xx) || defined(STM32F479xx)
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001091;
FMC_Bank1->BTCR[3] = 0x00110212;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F469xx || STM32F479xx */
(void)(tmp);
}
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
/**
* @brief Setup the external memory controller.
* Called in startup_stm32f4xx.s before jump to main.
* This function configures the external memories (SRAM/SDRAM)
* This SRAM/SDRAM will be used as program data memory (including heap and stack).
* @param None
* @retval None
*/
void SystemInit_ExtMemCtl(void)
{
__IO uint32_t tmp = 0x00;
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
#if defined (DATA_IN_ExtSDRAM)
register uint32_t tmpreg = 0, timeout = 0xFFFF;
register __IO uint32_t index;
#if defined(STM32F446xx)
/* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface
clock */
RCC->AHB1ENR |= 0x0000007D;
#else
/* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface
clock */
RCC->AHB1ENR |= 0x000001F8;
#endif /* STM32F446xx */
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
#if defined(STM32F446xx)
/* Connect PAx pins to FMC Alternate function */
GPIOA->AFR[0] |= 0xC0000000;
GPIOA->AFR[1] |= 0x00000000;
/* Configure PDx pins in Alternate function mode */
GPIOA->MODER |= 0x00008000;
/* Configure PDx pins speed to 50 MHz */
GPIOA->OSPEEDR |= 0x00008000;
/* Configure PDx pins Output type to push-pull */
GPIOA->OTYPER |= 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOA->PUPDR |= 0x00000000;
/* Connect PCx pins to FMC Alternate function */
GPIOC->AFR[0] |= 0x00CC0000;
GPIOC->AFR[1] |= 0x00000000;
/* Configure PDx pins in Alternate function mode */
GPIOC->MODER |= 0x00000A00;
/* Configure PDx pins speed to 50 MHz */
GPIOC->OSPEEDR |= 0x00000A00;
/* Configure PDx pins Output type to push-pull */
GPIOC->OTYPER |= 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOC->PUPDR |= 0x00000000;
#endif /* STM32F446xx */
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x000000CC;
GPIOD->AFR[1] = 0xCC000CCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xA02A000A;
/* Configure PDx pins speed to 50 MHz */
GPIOD->OSPEEDR = 0xA02A000A;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000;
/* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[0] = 0xC00000CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA800A;
/* Configure PEx pins speed to 50 MHz */
GPIOE->OSPEEDR = 0xAAAA800A;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000;
/* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[0] = 0xCCCCCCCC;
GPIOF->AFR[1] = 0xCCCCCCCC;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA800AAA;
/* Configure PFx pins speed to 50 MHz */
GPIOF->OSPEEDR = 0xAA800AAA;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000;
/* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[0] = 0xCCCCCCCC;
GPIOG->AFR[1] = 0xCCCCCCCC;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0xAAAAAAAA;
/* Configure PGx pins speed to 50 MHz */
GPIOG->OSPEEDR = 0xAAAAAAAA;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000;
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx)
/* Connect PHx pins to FMC Alternate function */
GPIOH->AFR[0] = 0x00C0CC00;
GPIOH->AFR[1] = 0xCCCCCCCC;
/* Configure PHx pins in Alternate function mode */
GPIOH->MODER = 0xAAAA08A0;
/* Configure PHx pins speed to 50 MHz */
GPIOH->OSPEEDR = 0xAAAA08A0;
/* Configure PHx pins Output type to push-pull */
GPIOH->OTYPER = 0x00000000;
/* No pull-up, pull-down for PHx pins */
GPIOH->PUPDR = 0x00000000;
/* Connect PIx pins to FMC Alternate function */
GPIOI->AFR[0] = 0xCCCCCCCC;
GPIOI->AFR[1] = 0x00000CC0;
/* Configure PIx pins in Alternate function mode */
GPIOI->MODER = 0x0028AAAA;
/* Configure PIx pins speed to 50 MHz */
GPIOI->OSPEEDR = 0x0028AAAA;
/* Configure PIx pins Output type to push-pull */
GPIOI->OTYPER = 0x00000000;
/* No pull-up, pull-down for PIx pins */
GPIOI->PUPDR = 0x00000000;
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
/*-- FMC Configuration -------------------------------------------------------*/
/* Enable the FMC interface clock */
RCC->AHB3ENR |= 0x00000001;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
/* Configure and enable SDRAM bank1 */
#if defined(STM32F446xx)
FMC_Bank5_6->SDCR[0] = 0x00001954;
#else
FMC_Bank5_6->SDCR[0] = 0x000019E4;
#endif /* STM32F446xx */
FMC_Bank5_6->SDTR[0] = 0x01115351;
/* SDRAM initialization sequence */
/* Clock enable command */
FMC_Bank5_6->SDCMR = 0x00000011;
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Delay */
for (index = 0; index<1000; index++);
/* PALL command */
FMC_Bank5_6->SDCMR = 0x00000012;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Auto refresh command */
#if defined(STM32F446xx)
FMC_Bank5_6->SDCMR = 0x000000F3;
#else
FMC_Bank5_6->SDCMR = 0x00000073;
#endif /* STM32F446xx */
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* MRD register program */
#if defined(STM32F446xx)
FMC_Bank5_6->SDCMR = 0x00044014;
#else
FMC_Bank5_6->SDCMR = 0x00046014;
#endif /* STM32F446xx */
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Set refresh count */
tmpreg = FMC_Bank5_6->SDRTR;
#if defined(STM32F446xx)
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1));
#else
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
#endif /* STM32F446xx */
/* Disable write protection */
tmpreg = FMC_Bank5_6->SDCR[0];
FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
#endif /* DATA_IN_ExtSDRAM */
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
|| defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
#if defined(DATA_IN_ExtSRAM)
/*-- GPIOs Configuration -----------------------------------------------------*/
/* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
RCC->AHB1ENR |= 0x00000078;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN);
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x00CCC0CC;
GPIOD->AFR[1] = 0xCCCCCCCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xAAAA0A8A;
/* Configure PDx pins speed to 100 MHz */
GPIOD->OSPEEDR = 0xFFFF0FCF;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000;
/* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[0] = 0xC00CC0CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA828A;
/* Configure PEx pins speed to 100 MHz */
GPIOE->OSPEEDR = 0xFFFFC3CF;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000;
/* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[0] = 0x00CCCCCC;
GPIOF->AFR[1] = 0xCCCC0000;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA000AAA;
/* Configure PFx pins speed to 100 MHz */
GPIOF->OSPEEDR = 0xFF000FFF;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000;
/* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[0] = 0x00CCCCCC;
GPIOG->AFR[1] = 0x000000C0;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0x00085AAA;
/* Configure PGx pins speed to 100 MHz */
GPIOG->OSPEEDR = 0x000CAFFF;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000;
/*-- FMC/FSMC Configuration --------------------------------------------------*/
/* Enable the FMC/FSMC interface clock */
RCC->AHB3ENR |= 0x00000001;
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001011;
FMC_Bank1->BTCR[3] = 0x00000201;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
#if defined(STM32F469xx) || defined(STM32F479xx)
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001091;
FMC_Bank1->BTCR[3] = 0x00110212;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F469xx || STM32F479xx */
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\
|| defined(STM32F412Zx) || defined(STM32F412Vx)
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);
/* Configure and enable Bank1_SRAM2 */
FSMC_Bank1->BTCR[2] = 0x00001011;
FSMC_Bank1->BTCR[3] = 0x00000201;
FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF;
#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */
#endif /* DATA_IN_ExtSRAM */
#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\
STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */
(void)(tmp);
}
#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,27 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(zephyr_flasher)
zephyr_compile_definitions_ifdef(CONFIG_SERIAL_FLASHER_MD5_ENABLED MD5_ENABLED)
zephyr_library_sources(
../common/example_common.c
)
zephyr_library_include_directories(
../common
../binaries
)
# Needed for example_common
add_compile_definitions(SERIAL_FLASHER_INTERFACE_UART)
# Embed binaries into the app.
include(${CMAKE_CURRENT_LIST_DIR}/../common/bin2array.cmake)
create_resources(${CMAKE_CURRENT_LIST_DIR}/../binaries/Hello-world ${CMAKE_BINARY_DIR}/binaries.c)
set_property(SOURCE ${CMAKE_BINARY_DIR}/binaries.c PROPERTY GENERATED 1)
target_sources(app PRIVATE src/main.c ${CMAKE_BINARY_DIR}/binaries.c)

View File

@@ -0,0 +1,84 @@
# ESP32 Zephyr example
## Overview
This sample code demonstrates how to flash ESP32/ESP32-S2/ESP8266 from another (host) MCU using
esp_serial_flash component API. In this case, ESP32 is also used as host MCU.
Binaries to be flashed from host MCU to another Espressif SoC can be found in `binaries` folder
and are converted into C-array during build process.
Following steps are performed in order to re-program target's memory:
1. Peripherals are initialized (GPIO for BOOT and EN pins and UART).
2. UART1 (can be changed) through which new binary will be transfered is initialized.
3. Host puts slave device into boot mode tries to connect by calling `esp_loader_connect()`.
4. Binary file is opened and its size is acquired, as it has to be known before flashing.
5. Then `esp_loader_flash_start()` is called to enter flashing mode and erase amount of memory to be flashed.
6. `esp_loader_flash_write()` function is called repeatedly until the whole binary image is transfered.
Note: In addition, to steps mentioned above, `esp_loader_change_transmission_rate` is called after connection
is established in order to increase flashing speed. This does not apply for ESP8266, as its bootloader
does not support this command. However, ESP8266 is capable of detecting baud rate during connection
phase, and can be changed before calling `esp_loader_connect`, if necessary.
## Hardware Required
* Two development boards with ESP32 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.).
* One or two USB cables for power supply and programming.
## Hardware connection
Table below shows connection between two ESP32 devices.
| ESP32 (host) | ESP32 (slave) |
|:------------:|:-------------:|
| IO4 | IO0 |
| IO2 | RESET |
| IO9 | TX0 |
| IO10 | RX0 |
Note: interconnection is the same for all three targets (slaves).
## Build and flash
To run the example, type the following command:
```c
west build -p -b esp32
west flash
west espressif monitor
```
(To exit the serial monitor, type ``ctrl-c``.)
For more information, check [Zephyr's Getting Started](https://docs.zephyrproject.org/latest/develop/getting_started/index.html)
## Configuration
For details about available configuration option, please refer to top level [README.md](../../README.md).
Compile definitions can be specified in `prj.conf` file.
Binaries to be flashed are placed in separate folder (binaries.c) for each possible target and converted to C-array. Without explicitly enabling MD5 check, flash integrity verification is disabled by default.
## Example output
Here is the example's console output:
```
*** Booting Zephyr OS build zephyr-v3.2.0-3548-ga1bb9c9d1736 ***
Running ESP Flasher from Zephyr
Connected to target
Baudrate changed
Erasing flash (this may take a while)...
Start programming
Progress: 100 %
Finished programming
Erasing flash (this may take a while)...
Start programming
Progress: 100 %
Finished programming
Erasing flash (this may take a while)...
Start programming
Progress: 100 %
Finished programming
```

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h>
#include <dt-bindings/pinctrl/esp32-pinctrl.h>
#include <zephyr/dt-bindings/pinctrl/esp32-gpio-sigmap.h>
/ {
aliases {
en = &en_button;
boot = &boot_button;
uart1 = &uart1;
};
gpio_keys {
compatible = "gpio-keys";
en_button: en_button {
gpios = <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_HIGH)>;
};
boot_button: boot_button {
gpios = <&gpio0 4 (GPIO_PULL_UP | GPIO_ACTIVE_HIGH)>;
};
};
};
&uart1 {
status = "okay";
current-speed = <115200>;
pinctrl-0 = <&uart1_default>;
pinctrl-names = "default";
};

View File

@@ -0,0 +1,4 @@
# nothing here
CONFIG_CONSOLE=y
CONFIG_CONSOLE_GETCHAR=y
CONFIG_NEWLIB_LIBC=y

View File

@@ -0,0 +1,7 @@
sample:
description: ESP Serial Flasher sample code
name: zephyr_flasher
tests:
sample.esp_flasher.zephyr_example:
platform_allow: esp32
tags: esp32

View File

@@ -0,0 +1,81 @@
/*
* ESP Flasher Library Example for Zephyr
* Written in 2022 by KT-Elektronik, Klaucke und Partner GmbH
* This example code is in the Public Domain (or CC0 licensed, at your option.)
* Unless required by applicable law or agreed to in writing, this
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied.
*
* Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd.
*/
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/util.h>
#include <stdio.h>
#include <string.h>
#include <zephyr_port.h>
#include <esp_loader.h>
#include "example_common.h"
#define HIGHER_BAUDRATE 230400
#define DEFAULT_BAUDRATE 115200
/* Get UART DTS entry used as flash interface */
static const struct device *esp_uart_dev = DEVICE_DT_GET(DT_ALIAS(uart1));
/* Get GPIO pin connected to the ESP's enable pin. */
static const struct gpio_dt_spec esp_enable_spec = GPIO_DT_SPEC_GET(DT_ALIAS(en), gpios);
/* Get GPIO pin connected to the ESP's boot pin. */
static const struct gpio_dt_spec esp_boot_spec = GPIO_DT_SPEC_GET(DT_ALIAS(boot), gpios);
void main(void)
{
example_binaries_t bin;
const loader_zephyr_config_t config = {
.uart_dev = esp_uart_dev,
.enable_spec = esp_enable_spec,
.boot_spec = esp_boot_spec
};
printk("Running ESP Flasher from Zephyr\r\n");
if (!device_is_ready(esp_uart_dev)) {
printk("ESP UART not ready");
return;
}
if (!device_is_ready(esp_boot_spec.port)) {
printk("ESP boot GPIO not ready");
return;
}
if (!device_is_ready(esp_enable_spec.port)) {
printk("Bluetooth Enable GPIO not ready");
return;
}
gpio_pin_configure_dt(&esp_boot_spec, GPIO_OUTPUT_ACTIVE);
gpio_pin_configure_dt(&esp_enable_spec, GPIO_OUTPUT_INACTIVE);
if (loader_port_zephyr_init(&config) != ESP_LOADER_SUCCESS) {
printk("ESP loader init failed");
return;
}
if (connect_to_target(HIGHER_BAUDRATE) == ESP_LOADER_SUCCESS) {
get_example_binaries(esp_loader_get_target(), &bin);
flash_binary(bin.boot.data, bin.boot.size, bin.boot.addr);
flash_binary(bin.part.data, bin.part.size, bin.part.addr);
flash_binary(bin.app.data, bin.app.size, bin.app.addr);
}
loader_port_change_transmission_rate(DEFAULT_BAUDRATE);
loader_port_reset_target();
}

View File

@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.13)
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/stm32-cmake/cmake/gcc_stm32.cmake)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/stm32-cmake/cmake)
find_package(CMSIS REQUIRED)
find_package(STM32HAL COMPONENTS gpio tim uart REQUIRED)
add_library(stm_cube_impl ${CMSIS_SOURCES} ${STM32HAL_SOURCES})
target_include_directories(stm_cube_impl PUBLIC ${CMSIS_INCLUDE_DIRS} ${STM32HAL_INCLUDE_DIR})
stm32_set_target_properties(stm_cube_impl)
# stm_cube target is made to propagate properties of stm_cube_impl, as stm32_set_target_properties
# sets properties privately for given target. This eliminates need to call stm32_set_target_properties
# on every target that links against STM32HAL.
add_library(stm_cube INTERFACE)
target_link_libraries(stm_cube INTERFACE stm_cube_impl)
target_compile_definitions(stm_cube INTERFACE $<TARGET_PROPERTY:stm_cube_impl,COMPILE_DEFINITIONS>)
target_link_options(stm_cube INTERFACE -T${CMAKE_CURRENT_BINARY_DIR}/stm_cube_impl_flash.ld)

View File

@@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.5)
project(serial_flasher_test)
add_executable( ${PROJECT_NAME}
test_main.cpp
../src/esp_loader.c
../src/esp_targets.c
../src/md5_hash.c
../src/protocol_common.c
../src/protocol_uart.c
../src/slip.c)
target_include_directories(${PROJECT_NAME} PRIVATE ../include ../private_include ../test ../port)
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Werror -O3)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14)
if( QEMU_TEST )
target_sources(${PROJECT_NAME} PRIVATE serial_io_tcp.cpp qemu_test.cpp)
else()
target_sources(${PROJECT_NAME} PRIVATE serial_io_mock.cpp test.cpp)
endif()
target_compile_definitions(${PROJECT_NAME} PRIVATE
MD5_ENABLED=1
SERIAL_FLASHER_INTERFACE_UART
SERIAL_FLASHER_DEBUG_TRACE
)

View File

@@ -0,0 +1,30 @@
# Serial flasher Tests
##Overview
Two kinds of tests are written for serial flasher:
* Host tests
* Qemu tests
Qemu tests uses emulated esp32 to test correctness of the library.
## Installation (Only for qemu tests)
Please refer to [building qemu](https://github.com/espressif/qemu) for instructions how to compile.
## Build and run
### Qemu test
QEMU_PATH environment variable pointing to compiled `qemu/build/xtensa-softmmu/qemu-system-xtensa` has to be defined.
```
export QEMU_PATH=path_to_qemu-system-xtensa
./run_test.sh qemu
```
### Host test
```
./run_test.sh host
```

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,121 @@
/* Copyright 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "catch.hpp"
#include "serial_io_mock.h"
#include "esp_loader.h"
#include "esp_loader_io.h"
#include <algorithm>
#include <iostream>
#include <fstream>
using namespace std;
#define ESP_ERR_CHECK(exp) REQUIRE( (exp) == ESP_LOADER_SUCCESS )
const uint32_t APP_START_ADDRESS = 0x10000;
TEST_CASE( "Can connect " )
{
esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT();
ESP_ERR_CHECK( esp_loader_connect(&connect_config) );
REQUIRE( esp_loader_get_target() == ESP32_CHIP );
}
inline auto file_size_is(ifstream& file)
{
uint32_t file_size;
file.seekg(0, ios::end);
file_size = file.tellg();
file.seekg(0);
return file_size;
}
void flash_application(ifstream& image)
{
uint8_t payload[1024];
int32_t count = 0;
size_t image_size = file_size_is(image);
ESP_ERR_CHECK( esp_loader_flash_start(APP_START_ADDRESS, image_size, sizeof(payload)) );
while(image_size > 0) {
size_t to_read = min(image_size, sizeof(payload));
image.read((char *)payload, to_read);
ESP_ERR_CHECK( esp_loader_flash_write(payload, to_read) );
cout << endl << "--- FLASH DATA PACKET: " << count++
<< " DATA WRITTEN: " << to_read << " ---" << endl;
image_size -= to_read;
};
// Omit restart
// loader_flash_finish(false);
}
bool file_compare(ifstream& file_1, ifstream& file_2, size_t file_size)
{
vector<char> file_data_1(file_size);
vector<char> file_data_2(file_size);
file_1.read((char*) &file_data_1[0], file_size);
file_2.read((char*) &file_data_2[0], file_size);
return file_data_1 == file_data_2;
}
TEST_CASE( "Can write application to flash" )
{
ifstream new_image;
ifstream qemu_image;
new_image.open ("../hello-world.bin", ios::binary | ios::in);
qemu_image.open ("empty_file.bin", ios::binary | ios::in);
REQUIRE ( new_image.is_open() );
REQUIRE ( qemu_image.is_open() );
flash_application(new_image);
auto new_image_size = file_size_is(new_image);
qemu_image.seekg(APP_START_ADDRESS);
new_image.seekg(0);
REQUIRE ( file_compare(new_image, qemu_image, new_image_size) );
ESP_ERR_CHECK ( esp_loader_flash_verify() );
// NOTE: loader_flash_finish() is not called to prevent reset of target
}
TEST_CASE( "Can write and read register" )
{
uint32_t reg_value = 0;
uint32_t SPI_MOSI_DLEN_REG = 0x60002000 + 0x28;
ESP_ERR_CHECK( esp_loader_write_register(SPI_MOSI_DLEN_REG, 55) );
ESP_ERR_CHECK( esp_loader_read_register(SPI_MOSI_DLEN_REG, &reg_value) );
REQUIRE ( reg_value == 55 );
}

View File

@@ -0,0 +1,33 @@
#!/bin/bash
set -e
mkdir -p build && cd build
if [ "$1" = "host" ]; then
cmake -DQEMU_TEST=False .. && cmake --build . && ./serial_flasher_test
elif [ "$1" = "qemu" ]; then
# QEMU_PATH environment variable has to be defined, pointing to qemu-system-xtensa
# Example: export QEMU_PATH=/home/user/esp/qemu/xtensa-softmmu/qemu-system-xtensa
if [ -z "${QEMU_PATH}" ]; then
echo "QEMU_PATH environment variable needs to be set"
exit 1
fi
# Generate empty file into which application will be flashed and compared against
dd if=/dev/zero bs=1024 count=4096 of="empty_file.bin"
# Run qemu in background (daemonized)
${QEMU_PATH} \
-daemonize \
-machine esp32 \
-drive file=empty_file.bin,if=mtd,format=raw \
-global driver=esp32.gpio,property=strap_mode,value=0x0f \
-serial tcp::5555,server,nowait
cmake -DQEMU_TEST=True .. && cmake --build . && ./serial_flasher_test
# Kill qemu process running in background
kill -9 $(pidof qemu-system-xtensa)
else
echo "Please select which test to run: qemu or host"
fi

View File

@@ -0,0 +1,158 @@
/* Copyright 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <limits>
#include <vector>
#include <iterator>
#include <algorithm>
#include <iostream>
#include <stdio.h>
#include "esp_loader_io.h"
#include "serial_io_mock.h"
using namespace std;
static vector<int8_t> write_buffer;
static vector<int8_t> read_buffer;
static uint32_t receive_delay = 0;
static int32_t timer = 0;
esp_loader_error_t loader_port_mock_init(const loader_serial_config_t *config)
{
return ESP_LOADER_SUCCESS;
}
void loader_port_mock_deinit()
{
}
esp_loader_error_t loader_port_write(const uint8_t *data, uint16_t size, uint32_t timeout)
{
copy(&data[0], &data[size], back_inserter(write_buffer));
return ESP_LOADER_SUCCESS;
}
esp_loader_error_t loader_port_read(uint8_t *data, uint16_t size, uint32_t timeout)
{
if (read_buffer.size() < size) {
return ESP_LOADER_ERROR_TIMEOUT;
}
if (receive_delay != 0 && timeout != 0) {
if (receive_delay > timeout) {
receive_delay -= timeout;
return ESP_LOADER_ERROR_TIMEOUT;
}
receive_delay = 0;
}
copy_n(read_buffer.begin(), size, data);
read_buffer.erase(read_buffer.begin(), read_buffer.begin() + size);
return ESP_LOADER_SUCCESS;
}
void loader_port_enter_bootloader()
{
// GPIO0 and GPIO2 must be LOW
// Then Reset
}
void loader_port_reset_target()
{
}
void loader_port_delay_ms(uint32_t ms)
{
}
void loader_port_start_timer(uint32_t ms)
{
timer = (int32_t)ms;
}
uint32_t loader_port_remaining_time(void)
{
return (timer > 0) ? timer : 0;
}
// ---------- For testing purposes only ----------
static void SLIP_encode(const int8_t *in_buff, size_t size, vector<int8_t> &encoded_buff)
{
encoded_buff.push_back('\xc0');
for (uint32_t i = 0; i < size; i++) {
if (in_buff[i] == '\xc0') {
encoded_buff.push_back('\xdb');
encoded_buff.push_back('\xdc');
} else if (in_buff[i] == '\xdb') {
encoded_buff.push_back('\xdb');
encoded_buff.push_back('\xdd');
} else {
encoded_buff.push_back(in_buff[i]);
}
}
encoded_buff.push_back('\xc0');
}
void clear_buffers()
{
write_buffer.clear();
read_buffer.clear();
}
int8_t *write_buffer_data()
{
return write_buffer.data();
}
size_t write_buffer_size()
{
return write_buffer.size();
}
void set_read_buffer(const void *data, size_t size)
{
SLIP_encode((const int8_t *)data, size, read_buffer);
}
void print_array(int8_t *data, uint32_t size)
{
for (uint32_t i = 0; i < size; i++) {
printf("%02x, ", (uint8_t)data[i]);
}
printf("\n");
}
void write_buffer_print()
{
print_array(write_buffer.data(), write_buffer.size());
}
void serial_set_time_delay(uint32_t miliseconds)
{
receive_delay = miliseconds;
}

View File

@@ -0,0 +1,38 @@
/* Copyright 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
#include "esp_loader.h"
void clear_buffers();
void write_buffer_print();
size_t write_buffer_size();
int8_t* write_buffer_data();
void set_read_buffer(const void *data, size_t size);
void print_array(int8_t *data, uint32_t size);
void serial_set_time_delay(uint32_t miliseconds);
typedef struct {
uint32_t dummy;
} loader_serial_config_t;
esp_loader_error_t loader_port_mock_init(const loader_serial_config_t *config);
void loader_port_mock_deinit();

View File

@@ -0,0 +1,167 @@
/* Copyright 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "esp_loader_io.h"
#include "serial_io_mock.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <chrono>
#include <thread>
#include <iostream>
#include <fstream>
using namespace std;
const uint32_t PORT = 5555;
static int sock = 0;
ofstream file;
#ifdef SERIAL_FLASHER_DEBUG_TRACE
static void transfer_debug_print(const uint8_t *data, uint16_t size, bool write)
{
static bool write_prev = false;
if (write_prev != write) {
write_prev = write;
cout << endl << "--- " << (write ? "WRITE" : "READ") << " ---" << endl;
}
for (uint32_t i = 0; i < size; i++) {
cout << hex << static_cast<unsigned int>(data[i]) << dec << ' ';
}
}
#endif
esp_loader_error_t loader_port_mock_init(const loader_serial_config_t *config)
{
struct sockaddr_in serv_addr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
cout << "Socket creation error \n";
return ESP_LOADER_ERROR_FAIL;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
cout << "Invalid address/ Address not supported \n";
return ESP_LOADER_ERROR_FAIL;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
cout << "Connection Failed \n";
return ESP_LOADER_ERROR_FAIL;
}
file.open ("received_data.bin", ios::binary | ios::out);
if (!file.is_open()) {
cout << "Cannot open file\n";
return ESP_LOADER_ERROR_FAIL;
}
return ESP_LOADER_SUCCESS;
}
void loader_port_mock_deinit()
{
if (sock != 0) {
shutdown(sock, 0);
close(sock);
}
if (file.is_open()) {
file.close();
}
}
esp_loader_error_t loader_port_write(const uint8_t *data, uint16_t size, uint32_t timeout)
{
uint32_t written = 0;
do {
int bytes_written = send(sock, &data[written], size - written, 0);
if (bytes_written == -1) {
cout << "Socket send failed\n";
return ESP_LOADER_ERROR_FAIL;
}
#ifdef SERIAL_FLASHER_DEBUG_TRACE
transfer_debug_print(data, bytes_written, true);
#endif
written += bytes_written;
} while (written != size);
return ESP_LOADER_SUCCESS;
}
esp_loader_error_t loader_port_read(uint8_t *data, uint16_t size, uint32_t timeout)
{
uint32_t written = 0;
int bytes_read = 0;
do {
bytes_read = read(sock, &data[written], size - written);
if (bytes_read == 0) {
cout << "Socket connection lost\n";
return ESP_LOADER_ERROR_FAIL;
}
#ifdef SERIAL_FLASHER_DEBUG_TRACE
transfer_debug_print(data, bytes_read, false);
#endif
file.write((const char*)&data[written], bytes_read);
file.flush();
written += bytes_read;
} while (written != size);
return ESP_LOADER_SUCCESS;
}
void loader_port_enter_bootloader()
{
// GPIO0 and GPIO2 must be LOW
// Then Reset
}
void loader_port_reset_target()
{
// Toggle reset pin
}
void loader_port_delay_ms(uint32_t ms)
{
this_thread::sleep_for(chrono::milliseconds(ms));
}
void loader_port_start_timer(uint32_t ms)
{
(void)ms;
}
uint32_t loader_port_remaining_time(void)
{
return 1;
}

View File

@@ -0,0 +1,397 @@
/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "catch.hpp"
#include "protocol.h"
#include "serial_io_mock.h"
#include "esp_loader.h"
#include "esp_loader_io.h"
#include <string.h>
#include <stdio.h>
#include <array>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
#define TEST_SLIP_PACKET 0xdb, 'a', 'b', 'c', 0xc0, 0xdb, 'd', 'e', 0xc0, 'f', 0xdb
#define SLIP_ENCODED_PACKET 0xdb, 0xdd, 'a', 'b', 'c', 0xdb, 0xdc, 0xdb, \
0xdd, 'd', 'e', 0xdb, 0xdc, 'f', 0xdb, 0xdd
#define REQUIRE_SUCCESS(exp) REQUIRE( (exp) == ESP_LOADER_SUCCESS )
// Helper function for debugging.
__attribute__((unused))
static void arrays_match(void *array_1, void *array_2, size_t size)
{
int8_t *arr_1 = (int8_t *)array_1;
int8_t *arr_2 = (int8_t *)array_2;
for (size_t i = 0; i < size; i++) {
if (arr_1[i] != arr_2[i]) {
printf("\nArrays do NOT match on index: %lu, with values %02hhx, %02hhx \n",
i, arr_1[i], arr_2[i]);
printf("\nExpected: ");
for (uint32_t j = 0; j < size; j++) { printf("%02hhx ", arr_1[j]); }
printf("\nActual: ");
for (uint32_t j = 0; j < size; j++) { printf("%02hhx ", arr_2[j]); }
return;
}
}
printf("Arrays Match\n");
}
// Wrapper around command_t for convenience
struct __attribute__((packed)) expected_response {
expected_response(command_t cmd)
{
data.common.direction = READ_DIRECTION;
data.common.command = cmd;
data.common.size = 16;
data.common.value = 0;
data.status.failed = STATUS_SUCCESS;
data.status.error = 0;
}
response_t data;
};
static_assert(sizeof(expected_response) == sizeof(response_t), "Size NOT equal");
inline void queue_response(expected_response &response, size_t size = sizeof(expected_response))
{
set_read_buffer(&response, size);
}
expected_response set_params_response(SPI_SET_PARAMS);
expected_response flash_begin_response(FLASH_BEGIN);
expected_response flash_data_response(FLASH_DATA);
expected_response flash_end_response(FLASH_END);
expected_response write_reg_response(WRITE_REG);
expected_response read_reg_response(READ_REG);
expected_response attach_response(SPI_ATTACH);
expected_response sync_response(SYNC);
const uint32_t reg_address = 0x1000;
const uint32_t reg_value = 55;
struct __attribute__((packed)) write_reg_cmd_response {
uint8_t delimiter_1 = 0xc0;
write_reg_command_t write_reg_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = WRITE_REG,
.size = 16,
.checksum = 0
},
.address = reg_address,
.value = reg_value,
.mask = 0xFFFFFFFF,
.delay_us = 0
};
uint8_t delimiter_2 = 0xc0;
};
map<target_chip_t, uint32_t> chip_magic_value = {
{ESP8266_CHIP, 0xfff0c101},
{ESP32_CHIP, 0x00f01d83},
{ESP32S2_CHIP, 0x000007c6},
{ESP32C2_CHIP, 0x6f51306f},
{ESP32C3_CHIP, 0x6921506f},
{ESP32S3_CHIP, 0x00000009},
{ESP32H4_CHIP, 0xca26cc22},
{ESP32H2_CHIP, 0xd7b73e80},
};
void queue_connect_response(target_chip_t target = ESP32_CHIP, uint32_t magic_value = 0)
{
// Set magic value register used for detection of attached chip
auto magic_value_response = read_reg_response;
magic_value_response.data.common.value = magic_value ? magic_value : chip_magic_value[target];
clear_buffers();
queue_response(sync_response);
queue_response(magic_value_response);
if (target == ESP8266_CHIP) {
queue_response(flash_begin_response);
} else {
auto efuse_pin_config_reg_1 = read_reg_response;
auto efuse_pin_config_reg_2 = read_reg_response;
queue_response(efuse_pin_config_reg_1);
queue_response(efuse_pin_config_reg_2);
queue_response(attach_response);
}
}
TEST_CASE( "chip_magic_value contains all supported chips " )
{
REQUIRE( chip_magic_value.size() == ESP_MAX_CHIP );
}
TEST_CASE( "Can connect within specified time " )
{
queue_connect_response();
esp_loader_connect_args_t connect_config = {
.sync_timeout = 10,
.trials = 1
};
SECTION( "Can connect" ) {
serial_set_time_delay(5);
REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
}
SECTION( "Timeout error is returned when timeout expires" ) {
serial_set_time_delay(20);
REQUIRE ( esp_loader_connect(&connect_config) == ESP_LOADER_ERROR_TIMEOUT );
}
SECTION( "Can connect after several trials within specified time" ) {
connect_config.trials = 5;
serial_set_time_delay(40);
REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
serial_set_time_delay(60);
REQUIRE( esp_loader_connect(&connect_config) == ESP_LOADER_ERROR_TIMEOUT );
}
serial_set_time_delay(0);
}
TEST_CASE( "Can detect attached target" )
{
esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT();
SECTION( "Can detect ESP32" ) {
queue_connect_response(ESP32_CHIP);
REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
REQUIRE( esp_loader_get_target() == ESP32_CHIP );
}
SECTION( "Can detect ESP32S2" ) {
queue_connect_response(ESP32S2_CHIP);
REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
REQUIRE( esp_loader_get_target() == ESP32S2_CHIP );
}
SECTION( "Can detect ESP32C2" ) {
queue_connect_response(ESP32C2_CHIP);
REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
REQUIRE( esp_loader_get_target() == ESP32C2_CHIP );
}
SECTION( "Can detect ESP32H4" ) {
queue_connect_response(ESP32H4_CHIP);
REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
REQUIRE( esp_loader_get_target() == ESP32H4_CHIP );
}
SECTION( "Can detect ESP32H2" ) {
queue_connect_response(ESP32H2_CHIP);
REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
REQUIRE( esp_loader_get_target() == ESP32H2_CHIP );
}
SECTION( "Can detect ESP32C3" ) {
queue_connect_response(ESP32C3_CHIP);
REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
REQUIRE( esp_loader_get_target() == ESP32C3_CHIP );
}
SECTION( "Can detect ESP32C3 rev3" ) {
queue_connect_response(ESP32C3_CHIP, 0x1b31506f);
REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
REQUIRE( esp_loader_get_target() == ESP32C3_CHIP );
}
SECTION( "Can detect ESP32S3" ) {
queue_connect_response(ESP32S3_CHIP);
REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
REQUIRE( esp_loader_get_target() == ESP32S3_CHIP );
}
SECTION( "Can detect ESP8266" ) {
queue_connect_response(ESP8266_CHIP);
REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
REQUIRE( esp_loader_get_target() == ESP8266_CHIP );
}
SECTION( "Can detect unknown chip" ) {
queue_connect_response(ESP_UNKNOWN_CHIP, 0xaaaaaaaa);
REQUIRE( esp_loader_connect(&connect_config) == ESP_LOADER_ERROR_INVALID_TARGET);
}
}
TEST_CASE( "Register can be read correctly" )
{
clear_buffers();
uint32_t reg_value = 0;
read_reg_response.data.common.value = 55;
queue_response(read_reg_response);
REQUIRE_SUCCESS( esp_loader_read_register(0, &reg_value) );
REQUIRE( reg_value == 55 );
}
TEST_CASE( "Register can be written correctly" )
{
write_reg_cmd_response expected;
write_reg_response.data.common.value = 55;
clear_buffers();
queue_response(write_reg_response);
REQUIRE_SUCCESS( esp_loader_write_register(reg_address, reg_value) );
REQUIRE( memcmp(write_buffer_data(), &expected, sizeof(expected)) == 0 );
}
// -------------------- Serial comm test -----------------------
TEST_CASE ( "SLIP is encoded correctly" )
{
loader_flash_begin_cmd(0, 0, 0, 0, ESP32_CHIP); // To reset sequence number counter
uint8_t data[] = { TEST_SLIP_PACKET };
uint8_t expected[] = {
0xc0, // Begin
0x00, // Write direction
0x03, // FLASH_DATA command
16 + sizeof(data), 0, // Number of characters to send
0x33, 0, 0, 0,// Checksum
sizeof(data), 0, 0, 0, // Data size
0, 0, 0, 0, // Sequence number
0, 0, 0, 0, // zero
0, 0, 0, 0, // zero
SLIP_ENCODED_PACKET,
0xc0, // End
};
// write_buffer_print();
// print_array(expected, sizeof(expected));
clear_buffers();
queue_response(flash_data_response);
REQUIRE_SUCCESS( loader_flash_data_cmd(data, sizeof(data)) );
REQUIRE( memcmp(write_buffer_data(), expected, sizeof(expected)) == 0 );
}
TEST_CASE( "Sync command is constructed correctly" )
{
uint8_t expected[] = {
0xc0, // Begin
0x00, // Write direction
0x08, // SYNC command
36, 0, // Number of characters to send
0, 0, 0, 0, // Checksum is ignored for this command
0x07, 0x07, 0x12, 0x20,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0xc0, // End
};
clear_buffers();
queue_response(sync_response);
REQUIRE_SUCCESS( loader_sync_cmd() );
REQUIRE( memcmp(write_buffer_data(), expected, sizeof(expected)) == 0 );
}
TEST_CASE( "Register can be read and decoded correctly" )
{
clear_buffers();
read_reg_response.data.common.value = 55;
queue_response(read_reg_response);
uint32_t reg_value = 0;
esp_loader_read_register(0, &reg_value);
REQUIRE( reg_value == 55 );
}
TEST_CASE( "Received response (in SLIP format) is decoded correctly" )
{
clear_buffers();
read_reg_response.data.common.value = 0xC0BD; // C0, BD has to be replaced
queue_response(read_reg_response);
uint32_t reg_value = 0;
esp_loader_read_register(0, &reg_value);
REQUIRE( reg_value == 0xC0BD );
}
// -------------------- Serial mock test -----------------------
TEST_CASE( "Serial read works correctly" )
{
uint32_t reg_value = 5;
uint8_t readout[sizeof(reg_value) + 2];
uint8_t expected[] = { 0xc0, 5, 0, 0, 0, 0xc0 };
clear_buffers();
set_read_buffer(&reg_value, sizeof(reg_value));
SECTION( "Read buffer can be read" ) {
loader_port_read(readout, sizeof(readout), 0);
REQUIRE( memcmp(readout, expected, sizeof(readout)) == 0 );
}
SECTION ( "Read buffer can be read in smaller chunks" ) {
loader_port_read(&readout[0], 3, 0);
loader_port_read(&readout[3], 3, 0);
REQUIRE( memcmp(readout, expected, sizeof(readout)) == 0 );
}
SECTION ( "Timeout is returned when requested amount of data is not available" ) {
REQUIRE( loader_port_read(readout, sizeof(readout) + 1, 0) == ESP_LOADER_ERROR_TIMEOUT);
}
SECTION ( "Read buffer is correctly SLIP encoded " ) {
uint8_t data_to_encode[] = { TEST_SLIP_PACKET };
uint8_t expected[] = { 0xc0, SLIP_ENCODED_PACKET, 0xc0};
uint8_t encoded[sizeof(expected)];
clear_buffers();
fill(encoded, &encoded[sizeof(encoded)], 0);
set_read_buffer(data_to_encode, sizeof(data_to_encode));
loader_port_read(encoded, sizeof(encoded), 0);
REQUIRE( memcmp(expected, encoded, sizeof(expected)) == 0 );
}
}

View File

@@ -0,0 +1,40 @@
/* Copyright 2018-2023 Espressif Systems (Shanghai) CO LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// #define CATCH_CONFIG_MAIN
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include "esp_loader_io.h"
#include "serial_io_mock.h"
int main( int argc, char* argv[] ) {
const loader_serial_config_t dummy_config = { 0 };
// global setup...
if( loader_port_mock_init(&dummy_config) != ESP_LOADER_SUCCESS ) {
std::cout << "Serial initialization failed";
return 0;
}
int result = Catch::Session().run( argc, argv );
// global clean-up...
loader_port_mock_deinit();
return result;
}

View File

@@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 3.5)
if (CONFIG_ESP_SERIAL_FLASHER)
zephyr_include_directories(
"${ZEPHYR_CURRENT_MODULE_DIR}/include"
"${ZEPHYR_CURRENT_MODULE_DIR}/port"
"${ZEPHYR_CURRENT_MODULE_DIR}/private_include"
)
zephyr_interface_library_named(esp_flasher)
zephyr_library()
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/src/esp_loader.c
${ZEPHYR_CURRENT_MODULE_DIR}/src/esp_targets.c
${ZEPHYR_CURRENT_MODULE_DIR}/src/protocol_common.c
${ZEPHYR_CURRENT_MODULE_DIR}/src/protocol_uart.c
${ZEPHYR_CURRENT_MODULE_DIR}/src/slip.c
${ZEPHYR_CURRENT_MODULE_DIR}/src/md5_hash.c
${ZEPHYR_CURRENT_MODULE_DIR}/port/zephyr_port.c
)
target_compile_definitions(esp_flasher INTERFACE SERIAL_FLASHER_INTERFACE_UART)
zephyr_library_link_libraries(esp_flasher)
if(DEFINED MD5_ENABLED OR CONFIG_SERIAL_FLASHER_MD5_ENABLED)
target_compile_definitions(esp_flasher INTERFACE -DMD5_ENABLED=1)
endif()
endif()