feat: H7 support (#5738)

Co-authored-by: Richard Li <richard.li@ces.hk>
Co-authored-by: philmoz <phil.a.mitchell@gmail.com>
Co-authored-by: raphaelcoeffic <1050031+raphaelcoeffic@users.noreply.github.com>
This commit is contained in:
Malte Langermann
2025-01-18 10:08:13 +01:00
committed by GitHub
co-authored by Richard Li philmoz raphaelcoeffic
parent 5a15ffb017
commit 3d25c2a0f8
458 changed files with 441554 additions and 2410 deletions
+4
View File
@@ -15,3 +15,7 @@
path = radio/src/thirdparty/lvgl
url = https://github.com/EdgeTX/lvgl.git
branch = release/v8.2
[submodule "radio/src/thirdparty/uf2"]
path = radio/src/thirdparty/uf2
url = https://github.com/microsoft/uf2.git
shallow = true
+28 -3
View File
@@ -57,7 +57,11 @@ option(BOOTLOADER "Include Bootloader" ON)
option(FWDRIVE "Attach also firmware drive with USB" OFF)
option(DISABLE_MCUCHECK "Disable MCU check at start" OFF)
option(LUA_MIXER "Enable LUA mixer/model scripts support" ON)
option(USBJ_EX "Enable USB Joystick Extension" ON)
if(PCB STREQUAL X9D+ AND PCBREV STREQUAL 2019)
option(USBJ_EX "Enable USB Joystick Extension" OFF)
else()
option(USBJ_EX "Enable USB Joystick Extension" ON)
endif()
# since we reset all default CMAKE compiler flags for firmware builds, provide an alternate way for user to specify additional flags.
set(FIRMWARE_C_FLAGS "" CACHE STRING "Additional flags for firmware target c compiler (note: all CMAKE_C_FLAGS[_*] are ignored for firmware/bootloader).")
@@ -79,6 +83,8 @@ elseif(PCB STREQUAL NV14)
include(targets/nv14/CMakeLists.txt)
elseif(PCB STREQUAL PL18)
include(targets/pl18/CMakeLists.txt)
elseif(PCB STREQUAL STM32H7S78_DK)
include(targets/stm32h7s78-dk/CMakeLists.txt)
elseif(PCB STREQUAL X9E OR PCB STREQUAL X9D+ OR PCB STREQUAL X9D OR PCB STREQUAL X7 OR PCB STREQUAL X9LITE OR PCB STREQUAL X9LITES OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES)
include(targets/taranis/CMakeLists.txt)
else()
@@ -96,7 +102,7 @@ include(hal/CMakeLists.txt)
add_subdirectory(bitmaps)
add_subdirectory(fonts)
if(CPU_TYPE STREQUAL STM32H7)
if(CPU_TYPE STREQUAL STM32H7 OR CPU_TYPE STREQUAL STM32H7RS)
include(targets/common/arm/stm32/h7/CMakeLists.txt)
endif()
@@ -119,6 +125,10 @@ endif()
include_directories(targets/${TARGET_DIR} ${THIRDPARTY_DIR})
if(NATIVE_BUILD)
include_directories(targets/simu)
endif()
foreach(LANGUAGE ${RADIO_LANGUAGES})
if(TRANSLATIONS STREQUAL ${LANGUAGE})
add_definitions(-DTRANSLATIONS_${LANGUAGE} -DTRANSLATIONS="${LANGUAGE}")
@@ -544,8 +554,10 @@ if(DEBUG)
target_compile_definitions(stm32_drivers_w_dbg_fw PRIVATE -DDEBUG)
endif()
set(LINKER_SCRIPT firmware.ld)
target_link_options(firmware PRIVATE
-lm -T${LINKER_DIR}/firmware.ld
-lm -T${LINKER_DIR}/${LINKER_SCRIPT}
-Wl,-Map=firmware.map,--cref,--no-warn-mismatch,--gc-sections
--specs=nano.specs
)
@@ -592,11 +604,24 @@ else()
message("-- Bootloader contained in firmware binary")
endif()
if(FIRMWARE_FORMAT_UF2)
add_custom_command(
TARGET firmware POST_BUILD
COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/elf2uf2.py
--reboot auto --device "${FLAVOUR}"
--version "edgetx-${VERSION}-${VERSION_SUFFIX} (${GIT_STR})"
-i firmware.elf firmware.uf2
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
VERBATIM
)
endif()
add_custom_command(
TARGET firmware POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary ${OBJCOPY_ARGS} firmware.elf firmware.bin
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
find_program(GAWK gawk
HINTS "c:/cygwin/bin/" "c:/msys/bin/"
+7 -4
View File
@@ -62,9 +62,9 @@
#define STR_MULTI_DEFAULT QT_TRANSLATE_NOOP("Multiprotocols", "DEFAULT")
STRLIST(NO_SUBTYPE, {STR_MULTI_DEFAULT})
#else
#elif defined(MULTIMODULE)
#define STRLIST(x, ...) const char* const x[] = __VA_ARGS__;
#define PROTODEF const mm_protocol_definition multi_protocols[]
#define PROTODEF(...) const mm_protocol_definition multi_protocols[] = __VA_ARGS__
const char* const mm_options_strings::options[] = {
nullptr,
@@ -81,6 +81,9 @@
};
#define NO_SUBTYPE nullptr
#else
#define STRLIST(x, ...)
#define PROTODEF(...)
#endif
//
@@ -161,7 +164,7 @@ STRLIST(STR_SUBTYPE_NN, { SPARE_SUBTYPE_NAMES })
// failsafe support yes/no, channel map disabled yes/no, reference to the suptype options strings above
// and further protocol options, e.g. RF tune, video frequency.
//
PROTODEF {
PROTODEF ({
{MODULE_SUBTYPE_MULTI_FLYSKY, 4, false, true, STR_SUBTYPE_FLYSKY, nullptr},
{MODULE_SUBTYPE_MULTI_HUBSAN, 2, false, false, STR_SUBTYPE_HUBSAN, STR_MULTI_VIDFREQ},
{MODULE_SUBTYPE_MULTI_FRSKY, 1, false, false, STR_SUBTYPE_FRSKYD, STR_MULTI_RFTUNE},
@@ -273,6 +276,6 @@ PROTODEF {
// Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff)
{MODULE_SUBTYPE_MULTI_SENTINEL, 0, false, false, NO_SUBTYPE, nullptr},
};
});
#endif // MULTIMODULE
+12 -12
View File
@@ -92,19 +92,19 @@ class BinAllocator
};
#if defined(SIMU)
typedef BinAllocator<40,300> BinAllocator_slots1;
typedef BinAllocator<80,100> BinAllocator_slots2;
#elif defined(CCMRAM)
#if defined(DEBUG)
typedef BinAllocator<28,400> BinAllocator_slots1;
typedef BinAllocator<92,90> BinAllocator_slots2;
typedef BinAllocator<40,300> BinAllocator_slots1;
typedef BinAllocator<80,100> BinAllocator_slots2;
#elif defined(STM32F4)
#if defined(DEBUG)
typedef BinAllocator<28,395> BinAllocator_slots1;
typedef BinAllocator<92,85> BinAllocator_slots2;
#else
typedef BinAllocator<28,415> BinAllocator_slots1;
typedef BinAllocator<92,98> BinAllocator_slots2;
#endif
#else
typedef BinAllocator<28,415> BinAllocator_slots1;
typedef BinAllocator<92,98> BinAllocator_slots2;
#endif
#else
typedef BinAllocator<28,200> BinAllocator_slots1;
typedef BinAllocator<92,50> BinAllocator_slots2;
typedef BinAllocator<28,200> BinAllocator_slots1;
typedef BinAllocator<92,50> BinAllocator_slots2;
#endif
BinAllocator_slots1 slots1;
+2
View File
@@ -8,6 +8,8 @@ elseif(PCB STREQUAL PL18)
set(BITMAP_TARGET_PREFIX pl18)
elseif(PCB STREQUAL X12S)
set(BITMAP_TARGET_PREFIX x12s)
elseif(PCB STREQUAL STM32H7S78_DK)
set(BITMAP_TARGET_PREFIX h7rs)
else()
set(BITMAP_TARGET_PREFIX x10)
endif()
+34
View File
@@ -0,0 +1,34 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
struct VersionTag
{
char flavour[12];
char full_version[44];
const char* version;
const char* fork;
};
// Ensure flavour can hold FLAVOUR defined in target cmakefile
static_assert(sizeof(((VersionTag){}).flavour) >= sizeof(FLAVOUR),
"VersionTag flavour size too small");
@@ -7,13 +7,25 @@ INCLUDE definitions.ld
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
/* ISR vector to be loaded */
.isr_vector :
{
_sisr_vector = .;
KEEP(*(.isr_vector))
. = ALIGN(4);
_eisr_vector = .;
} > REGION_ISR_VECT AT> REGION_TEXT_STORAGE
_isr_load = LOADADDR(.isr_vector);
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
FILL(0xFFFF)
CREATE_OBJECT_SYMBOLS
_stext = .;
KEEP(*(.version))
KEEP(*(.bootversiondata))
@@ -21,7 +33,9 @@ SECTIONS
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
} > REGION_TEXT AT> REGION_TEXT_STORAGE
_text_load = LOADADDR(.text);
INCLUDE common_sections.ld
}
@@ -12,11 +12,11 @@
PROVIDE(__exidx_end = .);
} > REGION_TEXT AT> REGION_TEXT_STORAGE
.reboot_buffer(NOLOAD) :
/* Bootstrap code to load ISR vector and code sections */
.bootstrap :
{
. = ALIGN(4);
*(.reboot*)
} > REGION_DATA
*(.bootstrap)
} > REGION_TEXT_STORAGE
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
@@ -32,7 +32,7 @@
_sidata = LOADADDR(.data);
/* Uninitialized data section */
.bss(NOLOAD) :
.bss(NOLOAD) : AT (ADDR(.bss))
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
@@ -43,8 +43,8 @@ _sidata = LOADADDR(.data);
_ebss = .; /* define a global symbol at bss end */
} > REGION_BSS
/* collect all uninitialized .ram sections (force DMA accessible) */
.ram (NOLOAD) :
/* collect all uninitialized .ram sections */
.ram (NOLOAD) : AT (ADDR(.ram))
{
. = ALIGN(4);
_sram = .;
@@ -55,6 +55,12 @@ _sidata = LOADADDR(.data);
INCLUDE extra_sections.ld
/* Seems to be the safest place for all targets (see AN2606) */
.reboot_buffer (ORIGIN(REGION_DATA) + LENGTH(REGION_DATA) - 4) (NOLOAD) : AT (ADDR(.reboot_buffer))
{
KEEP(*(.reboot*))
} > REGION_DATA
/* Remove information from the standard libraries */
/DISCARD/ :
{
@@ -9,13 +9,21 @@ SECTIONS
{
.bootloader :
{
FILL(0xFFFF)
KEEP(*(.bootloader))
. = BOOTLOADER_SIZE;
} > REGION_BOOTLOADER
/* Used only with H7 */
.firmware_header :
{
KEEP(*(.fwdescription))
} > REGION_TEXT AT> REGION_TEXT_STORAGE
/* ISR vector to be loaded */
.isr_vector :
{
. = ALIGN(4);
_sisr_vector = .;
KEEP(*(.isr_vector))
@@ -42,11 +50,9 @@ SECTIONS
_text_load = LOADADDR(.text);
/* Firmware bootstrap code to load ISR vector and code sections */
.bootstrap :
{
*(.bootstrap)
} > REGION_TEXT_STORAGE
INCLUDE common_sections.ld
.text_end_section : {} > REGION_TEXT AT > REGION_TEXT_STORAGE
_firmware_length = LOADADDR(.text_end_section) - LOADADDR(.firmware_header);
_firmware_version = _text_load;
}
@@ -0,0 +1,36 @@
/* SDRAM definitions */
SDRAM_START = DEFINED(__SDRAM_START__) ? __SDRAM_START__ : 0xC0000000;
SDRAM_SIZE = DEFINED(__SDRAM_SIZE__) ? __SDRAM_SIZE__ : 8192K;
/* Highest heap address */
HEAP_ADDRESS = SDRAM_START + SDRAM_SIZE;
/* Highest address of the user mode stack */
STACK_ADDRESS = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM) - 16; /* end of RAM */
/* Maximum bootloader code size */
BOOTLOADER_SIZE = 0x20000;
/* Required amount of stack for interrupt stack (Main stack) */
MAIN_STACK_SIZE = 8192;
/* Generate a link error if heap and stack don't fit into RAM */
MIN_HEAP_SIZE = 4096k; /* required amount of heap */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K
SDRAM (rwx) : ORIGIN = SDRAM_START, LENGTH = SDRAM_SIZE
}
REGION_ALIAS("REGION_TEXT_STORAGE", FLASH);
REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_DATA", DTCMRAM);
REGION_ALIAS("REGION_BSS", RAM_D1);
REGION_ALIAS("REGION_RAM", RAM_D1);
@@ -0,0 +1,58 @@
/* Task stacks */
.ccm (NOLOAD) :
{
. = ALIGN(4);
_sccm = .;
*(.ccm)
. = ALIGN(4);
_eccm = .;
} > DTCMRAM
/* Reserve stack space */
.stack (NOLOAD) :
{
. = ALIGN(4);
. = . + MAIN_STACK_SIZE;
. = ALIGN(4);
} > DTCMRAM
/* Fast code */
.iram (NOLOAD) :
{
. = ALIGN(4);
_siram = .;
*(.iram)
. = ALIGN(4);
_eiram = .;
} > ITCMRAM AT> REGION_TEXT_STORAGE
_stext_iram = LOADADDR(.iram);
/* Extra DMA section */
.dram (NOLOAD) :
{
. = ALIGN(4);
_s_dram = .;
*(.dram)
. = ALIGN(4);
_e_dram = .;
} > RAM_D2
.sdram (NOLOAD) :
{
. = ALIGN(4);
*(.sdram)
*(.sdram*)
*(.sdram_rodata)
*(.sdram_rodata*)
. = ALIGN(4);
_esdram = .;
/* Reserve heap space in RAM */
. = . + MIN_HEAP_SIZE;
. = ALIGN(4);
} > SDRAM
PROVIDE(_heap_start = _esdram);
@@ -0,0 +1,40 @@
/* SDRAM definitions */
SDRAM_START = DEFINED(__SDRAM_START__) ? __SDRAM_START__ : 0xC0000000;
SDRAM_SIZE = DEFINED(__SDRAM_SIZE__) ? __SDRAM_SIZE__ : 8192K;
/* Highest heap address */
HEAP_ADDRESS = SDRAM_START + SDRAM_SIZE;
/* Highest address of the user mode stack */
STACK_ADDRESS = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM); /* end of RAM */
/* Maximum bootloader code size */
BOOTLOADER_SIZE = 0x20000;
/* Required amount of stack for interrupt stack (Main stack) */
MAIN_STACK_SIZE = 8192;
/* Generate a link error if heap and stack don't fit into RAM */
MIN_HEAP_SIZE = 4096k; /* required amount of heap */
/*_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K
SDRAM (rwx) : ORIGIN = SDRAM_START, LENGTH = SDRAM_SIZE
QSPIFLASH (rx) : ORIGIN = 0x90000000, LENGTH = 8M
}
REGION_ALIAS("REGION_BOOTLOADER", FLASH);
REGION_ALIAS("REGION_ISR_VECT", DTCMRAM);
REGION_ALIAS("REGION_TEXT_STORAGE", QSPIFLASH);
REGION_ALIAS("REGION_TEXT", SDRAM);
REGION_ALIAS("REGION_DATA", DTCMRAM);
REGION_ALIAS("REGION_BSS", RAM_D1);
REGION_ALIAS("REGION_RAM", RAM_D1);
@@ -0,0 +1,39 @@
/* PSRAM definitions */
PSRAM_START = DEFINED(__PSRAM_START__) ? __PSRAM_START__ : 0x90000000;
PSRAM_SIZE = DEFINED(__PSRAM_SIZE__) ? __PSRAM_SIZE__ : 32678K;
NORFLASH_START = 0x70000000;
NORFLASH_SIZE = 128M;
/* Highest heap address */
HEAP_ADDRESS = PSRAM_START + PSRAM_SIZE;
/* Highest address of the user mode stack */
STACK_ADDRESS = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM) - 16; /* end of RAM */
/* Maximum bootloader code size */
BOOTLOADER_SIZE = 0x10000;
/* Required amount of stack for interrupt stack (Main stack) */
MAIN_STACK_SIZE = 8192;
/* Generate a link error if heap and stack don't fit into RAM */
MIN_HEAP_SIZE = 4096k; /* required amount of heap */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 384K
DMA (xrw) : ORIGIN = 0x24060000, LENGTH = 72K
PSRAM (rwx) : ORIGIN = PSRAM_START, LENGTH = PSRAM_SIZE
}
REGION_ALIAS("REGION_TEXT_STORAGE", FLASH);
REGION_ALIAS("REGION_TEXT", ITCMRAM);
REGION_ALIAS("REGION_ISR_VECT", DTCMRAM);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
REGION_ALIAS("REGION_RAM", RAM);
@@ -0,0 +1,59 @@
/* Task stacks */
.ccm (NOLOAD) :
{
. = ALIGN(4);
_sccm = .;
*(.ccm)
. = ALIGN(4);
_eccm = .;
} > DTCMRAM
/* Reserve stack space */
.stack(NOLOAD) :
{
. = ALIGN(4);
. = . + MAIN_STACK_SIZE;
. = ALIGN(4);
} > DTCMRAM
/* Fast code */
.iram (NOLOAD) :
{
. = ALIGN(4);
_siram = .;
*(.iram)
. = ALIGN(4);
_eiram = .;
} > ITCMRAM AT> REGION_TEXT_STORAGE
_stext_iram = LOADADDR(.iram);
/* Extra DMA section */
.dram (NOLOAD) :
{
. = ALIGN(4);
_s_dram = .;
*(.dram)
_e_dram = .;
} > DMA
_dram_addr = ADDR(.dram);
.sdram (NOLOAD) :
{
. = ALIGN(4);
*(.sdram)
*(.sdram*)
*(.sdram_rodata)
*(.sdram_rodata*)
. = ALIGN(4);
_esdram = .;
/* Reserve heap space in RAM */
. = . + MIN_HEAP_SIZE;
. = ALIGN(4);
} > PSRAM
PROVIDE(_heap_start = _esdram);
@@ -0,0 +1,41 @@
/* PSRAM definitions */
PSRAM_START = DEFINED(__PSRAM_START__) ? __PSRAM_START__ : 0x90000000;
PSRAM_SIZE = DEFINED(__PSRAM_SIZE__) ? __PSRAM_SIZE__ : 32678K;
NORFLASH_START = 0x70000000;
NORFLASH_SIZE = 128M;
/* Highest heap address */
HEAP_ADDRESS = PSRAM_START + PSRAM_SIZE;
/* Highest address of the user mode stack */
STACK_ADDRESS = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM);
/* Maximum bootloader code size */
BOOTLOADER_SIZE = 0x10000;
/* Required amount of stack for interrupt stack (Main stack) */
MAIN_STACK_SIZE = 8192;
/* Generate a link error if heap and stack don't fit into RAM */
MIN_HEAP_SIZE = 4096k; /* required amount of heap */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K /* SRAM1 = 128K */
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K /* SRAM3 = 128K */
RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 384K /* SRAM1 + SRAM2 + SRAM3 */
DMA (xrw) : ORIGIN = 0x24060000, LENGTH = 72K /* SRAM4 */
PSRAM (rwx) : ORIGIN = PSRAM_START, LENGTH = PSRAM_SIZE
NORFLASH (rwx) : ORIGIN = 0x70000000, LENGTH = 128M
}
REGION_ALIAS("REGION_BOOTLOADER", FLASH);
REGION_ALIAS("REGION_TEXT_STORAGE", NORFLASH);
REGION_ALIAS("REGION_TEXT", PSRAM);
REGION_ALIAS("REGION_ISR_VECT", DTCMRAM);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
REGION_ALIAS("REGION_RAM", RAM);
+70 -42
View File
@@ -124,30 +124,6 @@ DEFINE_STM32_SOFTSERIAL_PORT(InternalModule, intmoduleTimer);
#define EXTMODULE_USART_IRQ_PRIORITY 6
#if defined(EXTMODULE_TX_INVERT_GPIO) && defined(EXTMODULE_RX_INVERT_GPIO)
#define HAS_EXTMODULE_INVERTERS
static void _extmod_set_inverted(uint8_t enable)
{
// In EdgeTX the external module is normally always
// inverted, so invert the logic here
gpio_write(EXTMODULE_TX_INVERT_GPIO, !enable);
gpio_write(EXTMODULE_RX_INVERT_GPIO, !enable);
}
static void _extmod_init_inverter()
{
gpio_init(EXTMODULE_TX_INVERT_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
gpio_init(EXTMODULE_RX_INVERT_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
// this sets the output to idle-low as is
// the default in EdgeTX on external module
// (historically, most radios work this way)
_extmod_set_inverted(false);
}
#endif
static const stm32_usart_t extmoduleUSART = {
.USARTx = EXTMODULE_USART,
.txGPIO = EXTMODULE_TX_GPIO,
@@ -167,6 +143,44 @@ static const stm32_usart_t extmoduleUSART = {
DEFINE_STM32_SERIAL_PORT(ExternalModule, extmoduleUSART, INTMODULE_FIFO_SIZE, 0);
#if (defined(EXTMODULE_TX_INVERT_GPIO) && defined(EXTMODULE_RX_INVERT_GPIO)) \
|| defined(STM32H7) || defined(STM32H7RS)
#define HAS_EXTMODULE_INVERTERS
static void _extmod_set_inverted(uint8_t enable)
{
#if defined(STM32H7) || defined(STM32H7RS)
#ifdef EXTMODULE_USART
stm32_usart_rx_inversion(&extmoduleUSART, !enable);
stm32_usart_tx_inversion(&extmoduleUSART, !enable);
#else
#error no UART to invert
#endif
#else
// In EdgeTX the external module is normally always
// inverted, so invert the logic here
gpio_write(EXTMODULE_TX_INVERT_GPIO, !enable);
gpio_write(EXTMODULE_RX_INVERT_GPIO, !enable);
#endif
}
static void _extmod_init_inverter()
{
#if defined(EXTMODULE_TX_INVERT_GPIO) && defined(EXTMODULE_RX_INVERT_GPIO)
gpio_init(EXTMODULE_TX_INVERT_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
gpio_init(EXTMODULE_RX_INVERT_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
#endif
// this sets the output to idle-low as is
// the default in EdgeTX on external module
// (historically, most radios work this way)
_extmod_set_inverted(false);
}
#endif
#elif defined(TRAINER_MODULE_SBUS_USART)
static const stm32_usart_t sbus_trainer_USART = {
@@ -269,24 +283,6 @@ static void _set_sport_input(uint8_t enable)
#endif
}
#if defined(TELEMETRY_TX_REV_GPIO) && defined(TELEMETRY_RX_REV_GPIO)
#define HAS_SPORT_INVERTER
static void _sport_set_inverted(uint8_t enable)
{
gpio_write(TELEMETRY_TX_REV_GPIO, !enable);
gpio_write(TELEMETRY_RX_REV_GPIO, !enable);
}
static void _sport_init_inverter()
{
gpio_init(TELEMETRY_TX_REV_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
gpio_init(TELEMETRY_RX_REV_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
_sport_set_inverted(false);
}
#endif
#if defined(TELEMETRY_USART)
static const stm32_usart_t sportUSART = {
.USARTx = TELEMETRY_USART,
@@ -300,7 +296,11 @@ static const stm32_usart_t sportUSART = {
.rxDMA = nullptr,
.rxDMA_Stream = 0,
.rxDMA_Channel = 0,
#if defined(STM32H7) || (STM32H7RS)
.set_input = nullptr,
#else
.set_input = _set_sport_input,
#endif
.txDMA_IRQn = TELEMETRY_DMA_TX_Stream_IRQ,
.txDMA_IRQ_Prio = TELEMETRY_DMA_IRQ_PRIORITY,
};
@@ -320,6 +320,34 @@ static void _sport_direction_init()
#endif
#endif
#if (defined(TELEMETRY_TX_REV_GPIO) && defined(TELEMETRY_RX_REV_GPIO)) || defined(STM32H7) || defined(STM32H7RS)
#define HAS_SPORT_INVERTER
static void _sport_set_inverted(uint8_t enable)
{
#if defined(STM32H7) || defined(STM32H7RS)
#if defined(TELEMETRY_USART)
stm32_usart_rx_inversion(&sportUSART, !enable);
stm32_usart_tx_inversion(&sportUSART, !enable);
#endif
#else
gpio_write(TELEMETRY_TX_REV_GPIO, !enable);
gpio_write(TELEMETRY_RX_REV_GPIO, !enable);
#endif
}
static void _sport_init_inverter()
{
#if defined(TELEMETRY_TX_REV_GPIO) && defined(TELEMETRY_RX_REV_GPIO)
gpio_init(TELEMETRY_TX_REV_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
gpio_init(TELEMETRY_RX_REV_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
#endif
_sport_set_inverted(false);
}
#endif
#if defined(TELEMETRY_TIMER)
static const stm32_softserial_rx_port sportSoftRX = {
.GPIO = TELEMETRY_RX_GPIO,
+3 -2
View File
@@ -55,6 +55,7 @@ uint32_t rgbGetLedColor(uint8_t led)
return ws2812_get_color(led);
}
bool rgbGetState(uint8_t led)
{
return ws2812_get_state(led);
@@ -79,7 +80,7 @@ void rgbLedStart()
xTimerCreateStatic("rgbLed", LED_STRIP_REFRESH_PERIOD / RTOS_MS_PER_TICK, pdTRUE, (void*)0,
rgbLedTimerCb, &rgbLedTimerBuffer);
}
if (rgbLedTimer) {
if( xTimerStart( rgbLedTimer, 0 ) != pdPASS ) {
/* The timer could not be set into the Active state. */
@@ -127,4 +128,4 @@ extern "C" void LED_STRIP_TIMER_DMA_IRQHandler()
ws2812_dma_isr(&_led_timer);
}
#endif
#endif
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) EdgeTx
* Copyright (C) EdgeTx
*
* Based on code named
* opentx - https://github.com/opentx/opentx
@@ -26,4 +26,4 @@ void rgbLedStop();
void rgbSetLedColor(unsigned char, unsigned char, unsigned char, unsigned char);
uint32_t rgbGetLedColor(uint8_t led);
bool rgbGetState(unsigned char);
void rgbLedColorApply();
void rgbLedColorApply();
@@ -0,0 +1,753 @@
/**
******************************************************************************
* @file startup_stm32h750xx.s
* @author MCD Application Team
* @brief STM32H750xx Devices vector table for GCC based toolchain.
* This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Branches to main in the C library (which eventually
* calls main()).
* After Reset the Cortex-M processor is in Thread mode,
* priority is Privileged, and the Stack is set to Main.
******************************************************************************
* @attention
*
* Copyright (c) 2018 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
.syntax unified
.cpu cortex-m7
.fpu softvfp
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr sp, =_estack /* set stack pointer */
/* Call the clock system initialization function.*/
bl SystemInit
/* Copy the data segment initializers from flash to SRAM */
ldr r0, =_sdata
ldr r1, =_edata
ldr r2, =_sidata
movs r3, #0
b LoopCopyDataInit
CopyDataInit:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopyDataInit:
adds r4, r0, r3
cmp r4, r1
bcc CopyDataInit
/* Zero fill the bss segment. */
ldr r2, =_sbss
ldr r4, =_ebss
movs r3, #0
b LoopFillZerobss
FillZerobss:
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
cmp r2, r4
bcc FillZerobss
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
bx lr
.size Reset_Handler, .-Reset_Handler
/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
* @param None
* @retval None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex M. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
*******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
.size g_pfnVectors, .-g_pfnVectors
/* External Interrupts */
.word WWDG_IRQHandler /* Window WatchDog */
.word PVD_AVD_IRQHandler /* PVD/AVD through EXTI Line detection */
.word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
.word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
.word RCC_IRQHandler /* RCC */
.word EXTI0_IRQHandler /* EXTI Line0 */
.word EXTI1_IRQHandler /* EXTI Line1 */
.word EXTI2_IRQHandler /* EXTI Line2 */
.word EXTI3_IRQHandler /* EXTI Line3 */
.word EXTI4_IRQHandler /* EXTI Line4 */
.word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
.word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
.word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
.word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */
.word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */
.word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
.word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
.word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
.word FDCAN1_IT0_IRQHandler /* FDCAN1 interrupt line 0 */
.word FDCAN2_IT0_IRQHandler /* FDCAN2 interrupt line 0 */
.word FDCAN1_IT1_IRQHandler /* FDCAN1 interrupt line 1 */
.word FDCAN2_IT1_IRQHandler /* FDCAN2 interrupt line 1 */
.word EXTI9_5_IRQHandler /* External Line[9:5]s */
.word TIM1_BRK_IRQHandler /* TIM1 Break interrupt */
.word TIM1_UP_IRQHandler /* TIM1 Update interrupt */
.word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation interrupt */
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.word TIM2_IRQHandler /* TIM2 */
.word TIM3_IRQHandler /* TIM3 */
.word TIM4_IRQHandler /* TIM4 */
.word I2C1_EV_IRQHandler /* I2C1 Event */
.word I2C1_ER_IRQHandler /* I2C1 Error */
.word I2C2_EV_IRQHandler /* I2C2 Event */
.word I2C2_ER_IRQHandler /* I2C2 Error */
.word SPI1_IRQHandler /* SPI1 */
.word SPI2_IRQHandler /* SPI2 */
.word USART1_IRQHandler /* USART1 */
.word USART2_IRQHandler /* USART2 */
.word USART3_IRQHandler /* USART3 */
.word EXTI15_10_IRQHandler /* External Line[15:10]s */
.word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
.word 0 /* Reserved */
.word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */
.word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */
.word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */
.word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
.word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
.word FMC_IRQHandler /* FMC */
.word SDMMC1_IRQHandler /* SDMMC1 */
.word TIM5_IRQHandler /* TIM5 */
.word SPI3_IRQHandler /* SPI3 */
.word UART4_IRQHandler /* UART4 */
.word UART5_IRQHandler /* UART5 */
.word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */
.word TIM7_IRQHandler /* TIM7 */
.word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
.word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
.word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
.word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */
.word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
.word ETH_IRQHandler /* Ethernet */
.word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */
.word FDCAN_CAL_IRQHandler /* FDCAN calibration unit interrupt*/
.word 0 /* Reserved */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
.word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
.word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
.word USART6_IRQHandler /* USART6 */
.word I2C3_EV_IRQHandler /* I2C3 event */
.word I2C3_ER_IRQHandler /* I2C3 error */
.word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */
.word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */
.word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */
.word OTG_HS_IRQHandler /* USB OTG HS */
.word DCMI_IRQHandler /* DCMI */
.word CRYP_IRQHandler /* Crypto */
.word HASH_RNG_IRQHandler /* Hash and Rng */
.word FPU_IRQHandler /* FPU */
.word UART7_IRQHandler /* UART7 */
.word UART8_IRQHandler /* UART8 */
.word SPI4_IRQHandler /* SPI4 */
.word SPI5_IRQHandler /* SPI5 */
.word SPI6_IRQHandler /* SPI6 */
.word SAI1_IRQHandler /* SAI1 */
.word LTDC_IRQHandler /* LTDC */
.word LTDC_ER_IRQHandler /* LTDC error */
.word DMA2D_IRQHandler /* DMA2D */
.word SAI2_IRQHandler /* SAI2 */
.word QUADSPI_IRQHandler /* QUADSPI */
.word LPTIM1_IRQHandler /* LPTIM1 */
.word CEC_IRQHandler /* HDMI_CEC */
.word I2C4_EV_IRQHandler /* I2C4 Event */
.word I2C4_ER_IRQHandler /* I2C4 Error */
.word SPDIF_RX_IRQHandler /* SPDIF_RX */
.word OTG_FS_EP1_OUT_IRQHandler /* USB OTG FS End Point 1 Out */
.word OTG_FS_EP1_IN_IRQHandler /* USB OTG FS End Point 1 In */
.word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI */
.word OTG_FS_IRQHandler /* USB OTG FS */
.word DMAMUX1_OVR_IRQHandler /* DMAMUX1 Overrun interrupt */
.word HRTIM1_Master_IRQHandler /* HRTIM Master Timer global Interrupt */
.word HRTIM1_TIMA_IRQHandler /* HRTIM Timer A global Interrupt */
.word HRTIM1_TIMB_IRQHandler /* HRTIM Timer B global Interrupt */
.word HRTIM1_TIMC_IRQHandler /* HRTIM Timer C global Interrupt */
.word HRTIM1_TIMD_IRQHandler /* HRTIM Timer D global Interrupt */
.word HRTIM1_TIME_IRQHandler /* HRTIM Timer E global Interrupt */
.word HRTIM1_FLT_IRQHandler /* HRTIM Fault global Interrupt */
.word DFSDM1_FLT0_IRQHandler /* DFSDM Filter0 Interrupt */
.word DFSDM1_FLT1_IRQHandler /* DFSDM Filter1 Interrupt */
.word DFSDM1_FLT2_IRQHandler /* DFSDM Filter2 Interrupt */
.word DFSDM1_FLT3_IRQHandler /* DFSDM Filter3 Interrupt */
.word SAI3_IRQHandler /* SAI3 global Interrupt */
.word SWPMI1_IRQHandler /* Serial Wire Interface 1 global interrupt */
.word TIM15_IRQHandler /* TIM15 global Interrupt */
.word TIM16_IRQHandler /* TIM16 global Interrupt */
.word TIM17_IRQHandler /* TIM17 global Interrupt */
.word MDIOS_WKUP_IRQHandler /* MDIOS Wakeup Interrupt */
.word MDIOS_IRQHandler /* MDIOS global Interrupt */
.word JPEG_IRQHandler /* JPEG global Interrupt */
.word MDMA_IRQHandler /* MDMA global Interrupt */
.word 0 /* Reserved */
.word SDMMC2_IRQHandler /* SDMMC2 global Interrupt */
.word HSEM1_IRQHandler /* HSEM1 global Interrupt */
.word 0 /* Reserved */
.word ADC3_IRQHandler /* ADC3 global Interrupt */
.word DMAMUX2_OVR_IRQHandler /* DMAMUX Overrun interrupt */
.word BDMA_Channel0_IRQHandler /* BDMA Channel 0 global Interrupt */
.word BDMA_Channel1_IRQHandler /* BDMA Channel 1 global Interrupt */
.word BDMA_Channel2_IRQHandler /* BDMA Channel 2 global Interrupt */
.word BDMA_Channel3_IRQHandler /* BDMA Channel 3 global Interrupt */
.word BDMA_Channel4_IRQHandler /* BDMA Channel 4 global Interrupt */
.word BDMA_Channel5_IRQHandler /* BDMA Channel 5 global Interrupt */
.word BDMA_Channel6_IRQHandler /* BDMA Channel 6 global Interrupt */
.word BDMA_Channel7_IRQHandler /* BDMA Channel 7 global Interrupt */
.word COMP1_IRQHandler /* COMP1 global Interrupt */
.word LPTIM2_IRQHandler /* LP TIM2 global interrupt */
.word LPTIM3_IRQHandler /* LP TIM3 global interrupt */
.word LPTIM4_IRQHandler /* LP TIM4 global interrupt */
.word LPTIM5_IRQHandler /* LP TIM5 global interrupt */
.word LPUART1_IRQHandler /* LP UART1 interrupt */
.word 0 /* Reserved */
.word CRS_IRQHandler /* Clock Recovery Global Interrupt */
.word ECC_IRQHandler /* ECC diagnostic Global Interrupt */
.word SAI4_IRQHandler /* SAI4 global interrupt */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word WAKEUP_PIN_IRQHandler /* Interrupt for all 6 wake-up pins */
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
.weak PVD_AVD_IRQHandler
.thumb_set PVD_AVD_IRQHandler,Default_Handler
.weak TAMP_STAMP_IRQHandler
.thumb_set TAMP_STAMP_IRQHandler,Default_Handler
.weak RTC_WKUP_IRQHandler
.thumb_set RTC_WKUP_IRQHandler,Default_Handler
.weak FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler
.weak RCC_IRQHandler
.thumb_set RCC_IRQHandler,Default_Handler
.weak EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler
.weak EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler
.weak EXTI2_IRQHandler
.thumb_set EXTI2_IRQHandler,Default_Handler
.weak EXTI3_IRQHandler
.thumb_set EXTI3_IRQHandler,Default_Handler
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
.weak DMA1_Stream0_IRQHandler
.thumb_set DMA1_Stream0_IRQHandler,Default_Handler
.weak DMA1_Stream1_IRQHandler
.thumb_set DMA1_Stream1_IRQHandler,Default_Handler
.weak DMA1_Stream2_IRQHandler
.thumb_set DMA1_Stream2_IRQHandler,Default_Handler
.weak DMA1_Stream3_IRQHandler
.thumb_set DMA1_Stream3_IRQHandler,Default_Handler
.weak DMA1_Stream4_IRQHandler
.thumb_set DMA1_Stream4_IRQHandler,Default_Handler
.weak DMA1_Stream5_IRQHandler
.thumb_set DMA1_Stream5_IRQHandler,Default_Handler
.weak DMA1_Stream6_IRQHandler
.thumb_set DMA1_Stream6_IRQHandler,Default_Handler
.weak ADC_IRQHandler
.thumb_set ADC_IRQHandler,Default_Handler
.weak FDCAN1_IT0_IRQHandler
.thumb_set FDCAN1_IT0_IRQHandler,Default_Handler
.weak FDCAN2_IT0_IRQHandler
.thumb_set FDCAN2_IT0_IRQHandler,Default_Handler
.weak FDCAN1_IT1_IRQHandler
.thumb_set FDCAN1_IT1_IRQHandler,Default_Handler
.weak FDCAN2_IT1_IRQHandler
.thumb_set FDCAN2_IT1_IRQHandler,Default_Handler
.weak EXTI9_5_IRQHandler
.thumb_set EXTI9_5_IRQHandler,Default_Handler
.weak TIM1_BRK_IRQHandler
.thumb_set TIM1_BRK_IRQHandler,Default_Handler
.weak TIM1_UP_IRQHandler
.thumb_set TIM1_UP_IRQHandler,Default_Handler
.weak TIM1_TRG_COM_IRQHandler
.thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
.weak TIM2_IRQHandler
.thumb_set TIM2_IRQHandler,Default_Handler
.weak TIM3_IRQHandler
.thumb_set TIM3_IRQHandler,Default_Handler
.weak TIM4_IRQHandler
.thumb_set TIM4_IRQHandler,Default_Handler
.weak I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak I2C2_EV_IRQHandler
.thumb_set I2C2_EV_IRQHandler,Default_Handler
.weak I2C2_ER_IRQHandler
.thumb_set I2C2_ER_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak USART3_IRQHandler
.thumb_set USART3_IRQHandler,Default_Handler
.weak EXTI15_10_IRQHandler
.thumb_set EXTI15_10_IRQHandler,Default_Handler
.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
.weak TIM8_BRK_TIM12_IRQHandler
.thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
.weak TIM8_UP_TIM13_IRQHandler
.thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
.weak TIM8_TRG_COM_TIM14_IRQHandler
.thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
.weak TIM8_CC_IRQHandler
.thumb_set TIM8_CC_IRQHandler,Default_Handler
.weak DMA1_Stream7_IRQHandler
.thumb_set DMA1_Stream7_IRQHandler,Default_Handler
.weak FMC_IRQHandler
.thumb_set FMC_IRQHandler,Default_Handler
.weak SDMMC1_IRQHandler
.thumb_set SDMMC1_IRQHandler,Default_Handler
.weak TIM5_IRQHandler
.thumb_set TIM5_IRQHandler,Default_Handler
.weak SPI3_IRQHandler
.thumb_set SPI3_IRQHandler,Default_Handler
.weak UART4_IRQHandler
.thumb_set UART4_IRQHandler,Default_Handler
.weak UART5_IRQHandler
.thumb_set UART5_IRQHandler,Default_Handler
.weak TIM6_DAC_IRQHandler
.thumb_set TIM6_DAC_IRQHandler,Default_Handler
.weak TIM7_IRQHandler
.thumb_set TIM7_IRQHandler,Default_Handler
.weak DMA2_Stream0_IRQHandler
.thumb_set DMA2_Stream0_IRQHandler,Default_Handler
.weak DMA2_Stream1_IRQHandler
.thumb_set DMA2_Stream1_IRQHandler,Default_Handler
.weak DMA2_Stream2_IRQHandler
.thumb_set DMA2_Stream2_IRQHandler,Default_Handler
.weak DMA2_Stream3_IRQHandler
.thumb_set DMA2_Stream3_IRQHandler,Default_Handler
.weak DMA2_Stream4_IRQHandler
.thumb_set DMA2_Stream4_IRQHandler,Default_Handler
.weak ETH_IRQHandler
.thumb_set ETH_IRQHandler,Default_Handler
.weak ETH_WKUP_IRQHandler
.thumb_set ETH_WKUP_IRQHandler,Default_Handler
.weak FDCAN_CAL_IRQHandler
.thumb_set FDCAN_CAL_IRQHandler,Default_Handler
.weak DMA2_Stream5_IRQHandler
.thumb_set DMA2_Stream5_IRQHandler,Default_Handler
.weak DMA2_Stream6_IRQHandler
.thumb_set DMA2_Stream6_IRQHandler,Default_Handler
.weak DMA2_Stream7_IRQHandler
.thumb_set DMA2_Stream7_IRQHandler,Default_Handler
.weak USART6_IRQHandler
.thumb_set USART6_IRQHandler,Default_Handler
.weak I2C3_EV_IRQHandler
.thumb_set I2C3_EV_IRQHandler,Default_Handler
.weak I2C3_ER_IRQHandler
.thumb_set I2C3_ER_IRQHandler,Default_Handler
.weak OTG_HS_EP1_OUT_IRQHandler
.thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
.weak OTG_HS_EP1_IN_IRQHandler
.thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler
.weak OTG_HS_WKUP_IRQHandler
.thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler
.weak OTG_HS_IRQHandler
.thumb_set OTG_HS_IRQHandler,Default_Handler
.weak DCMI_IRQHandler
.thumb_set DCMI_IRQHandler,Default_Handler
.weak CRYP_IRQHandler
.thumb_set CRYP_IRQHandler,Default_Handler
.weak HASH_RNG_IRQHandler
.thumb_set HASH_RNG_IRQHandler,Default_Handler
.weak FPU_IRQHandler
.thumb_set FPU_IRQHandler,Default_Handler
.weak UART7_IRQHandler
.thumb_set UART7_IRQHandler,Default_Handler
.weak UART8_IRQHandler
.thumb_set UART8_IRQHandler,Default_Handler
.weak SPI4_IRQHandler
.thumb_set SPI4_IRQHandler,Default_Handler
.weak SPI5_IRQHandler
.thumb_set SPI5_IRQHandler,Default_Handler
.weak SPI6_IRQHandler
.thumb_set SPI6_IRQHandler,Default_Handler
.weak SAI1_IRQHandler
.thumb_set SAI1_IRQHandler,Default_Handler
.weak LTDC_IRQHandler
.thumb_set LTDC_IRQHandler,Default_Handler
.weak LTDC_ER_IRQHandler
.thumb_set LTDC_ER_IRQHandler,Default_Handler
.weak DMA2D_IRQHandler
.thumb_set DMA2D_IRQHandler,Default_Handler
.weak SAI2_IRQHandler
.thumb_set SAI2_IRQHandler,Default_Handler
.weak QUADSPI_IRQHandler
.thumb_set QUADSPI_IRQHandler,Default_Handler
.weak LPTIM1_IRQHandler
.thumb_set LPTIM1_IRQHandler,Default_Handler
.weak CEC_IRQHandler
.thumb_set CEC_IRQHandler,Default_Handler
.weak I2C4_EV_IRQHandler
.thumb_set I2C4_EV_IRQHandler,Default_Handler
.weak I2C4_ER_IRQHandler
.thumb_set I2C4_ER_IRQHandler,Default_Handler
.weak SPDIF_RX_IRQHandler
.thumb_set SPDIF_RX_IRQHandler,Default_Handler
.weak OTG_FS_EP1_OUT_IRQHandler
.thumb_set OTG_FS_EP1_OUT_IRQHandler,Default_Handler
.weak OTG_FS_EP1_IN_IRQHandler
.thumb_set OTG_FS_EP1_IN_IRQHandler,Default_Handler
.weak OTG_FS_WKUP_IRQHandler
.thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
.weak OTG_FS_IRQHandler
.thumb_set OTG_FS_IRQHandler,Default_Handler
.weak DMAMUX1_OVR_IRQHandler
.thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler
.weak HRTIM1_Master_IRQHandler
.thumb_set HRTIM1_Master_IRQHandler,Default_Handler
.weak HRTIM1_TIMA_IRQHandler
.thumb_set HRTIM1_TIMA_IRQHandler,Default_Handler
.weak HRTIM1_TIMB_IRQHandler
.thumb_set HRTIM1_TIMB_IRQHandler,Default_Handler
.weak HRTIM1_TIMC_IRQHandler
.thumb_set HRTIM1_TIMC_IRQHandler,Default_Handler
.weak HRTIM1_TIMD_IRQHandler
.thumb_set HRTIM1_TIMD_IRQHandler,Default_Handler
.weak HRTIM1_TIME_IRQHandler
.thumb_set HRTIM1_TIME_IRQHandler,Default_Handler
.weak HRTIM1_FLT_IRQHandler
.thumb_set HRTIM1_FLT_IRQHandler,Default_Handler
.weak DFSDM1_FLT0_IRQHandler
.thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler
.weak DFSDM1_FLT1_IRQHandler
.thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler
.weak DFSDM1_FLT2_IRQHandler
.thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler
.weak DFSDM1_FLT3_IRQHandler
.thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler
.weak SAI3_IRQHandler
.thumb_set SAI3_IRQHandler,Default_Handler
.weak SWPMI1_IRQHandler
.thumb_set SWPMI1_IRQHandler,Default_Handler
.weak TIM15_IRQHandler
.thumb_set TIM15_IRQHandler,Default_Handler
.weak TIM16_IRQHandler
.thumb_set TIM16_IRQHandler,Default_Handler
.weak TIM17_IRQHandler
.thumb_set TIM17_IRQHandler,Default_Handler
.weak MDIOS_WKUP_IRQHandler
.thumb_set MDIOS_WKUP_IRQHandler,Default_Handler
.weak MDIOS_IRQHandler
.thumb_set MDIOS_IRQHandler,Default_Handler
.weak JPEG_IRQHandler
.thumb_set JPEG_IRQHandler,Default_Handler
.weak MDMA_IRQHandler
.thumb_set MDMA_IRQHandler,Default_Handler
.weak SDMMC2_IRQHandler
.thumb_set SDMMC2_IRQHandler,Default_Handler
.weak HSEM1_IRQHandler
.thumb_set HSEM1_IRQHandler,Default_Handler
.weak ADC3_IRQHandler
.thumb_set ADC3_IRQHandler,Default_Handler
.weak DMAMUX2_OVR_IRQHandler
.thumb_set DMAMUX2_OVR_IRQHandler,Default_Handler
.weak BDMA_Channel0_IRQHandler
.thumb_set BDMA_Channel0_IRQHandler,Default_Handler
.weak BDMA_Channel1_IRQHandler
.thumb_set BDMA_Channel1_IRQHandler,Default_Handler
.weak BDMA_Channel2_IRQHandler
.thumb_set BDMA_Channel2_IRQHandler,Default_Handler
.weak BDMA_Channel3_IRQHandler
.thumb_set BDMA_Channel3_IRQHandler,Default_Handler
.weak BDMA_Channel4_IRQHandler
.thumb_set BDMA_Channel4_IRQHandler,Default_Handler
.weak BDMA_Channel5_IRQHandler
.thumb_set BDMA_Channel5_IRQHandler,Default_Handler
.weak BDMA_Channel6_IRQHandler
.thumb_set BDMA_Channel6_IRQHandler,Default_Handler
.weak BDMA_Channel7_IRQHandler
.thumb_set BDMA_Channel7_IRQHandler,Default_Handler
.weak COMP1_IRQHandler
.thumb_set COMP1_IRQHandler,Default_Handler
.weak LPTIM2_IRQHandler
.thumb_set LPTIM2_IRQHandler,Default_Handler
.weak LPTIM3_IRQHandler
.thumb_set LPTIM3_IRQHandler,Default_Handler
.weak LPTIM4_IRQHandler
.thumb_set LPTIM4_IRQHandler,Default_Handler
.weak LPTIM5_IRQHandler
.thumb_set LPTIM5_IRQHandler,Default_Handler
.weak LPUART1_IRQHandler
.thumb_set LPUART1_IRQHandler,Default_Handler
.weak CRS_IRQHandler
.thumb_set CRS_IRQHandler,Default_Handler
.weak ECC_IRQHandler
.thumb_set ECC_IRQHandler,Default_Handler
.weak SAI4_IRQHandler
.thumb_set SAI4_IRQHandler,Default_Handler
.weak WAKEUP_PIN_IRQHandler
.thumb_set WAKEUP_PIN_IRQHandler,Default_Handler
@@ -0,0 +1,780 @@
/**
******************************************************************************
* @file startup_stm32h7s7xx.s
* @author MCD Application Team
* @brief STM32H7S7xx Devices vector table for GCC toolchain.
* This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Branches to main in the C library (which eventually
* calls main()).
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
.syntax unified
.cpu cortex-m7
.fpu softvfp
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr r0, =_estack
mov sp, r0 /* set stack pointer */
/* Call the clock system initialization function.*/
bl SystemInit
/* Copy the data segment initializers from flash to SRAM */
ldr r0, =_sdata
ldr r1, =_edata
ldr r2, =_sidata
movs r3, #0
b LoopCopyDataInit
CopyDataInit:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopyDataInit:
adds r4, r0, r3
cmp r4, r1
bcc CopyDataInit
/* Zero fill the bss segment. */
ldr r2, =_sbss
ldr r4, =_ebss
movs r3, #0
b LoopFillZerobss
FillZerobss:
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
cmp r2, r4
bcc FillZerobss
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
LoopForever:
b LoopForever
.size Reset_Handler, .-Reset_Handler
/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
*
* @param None
* @retval : None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The STM32H7S7xx vector table. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
/* External Interrupts */
.word PVD_PVM_IRQHandler /* PVD/PVM through EXTI Line detection */
.word 0 /* Reserved */
.word DTS_IRQHandler /* Digital Temperature Sensor */
.word IWDG_IRQHandler /* Internal Watchdog */
.word WWDG_IRQHandler /* Window Watchdog */
.word RCC_IRQHandler /* RCC global interrupts through EXTI Line detection */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word FLASH_IRQHandler /* FLASH interrupts */
.word RAMECC_IRQHandler /* RAMECC interrupts */
.word FPU_IRQHandler /* FPU */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word TAMP_IRQHandler /* Tamper and TimeStamp interrupts */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word EXTI0_IRQHandler /* EXTI Line0 */
.word EXTI1_IRQHandler /* EXTI Line1 */
.word EXTI2_IRQHandler /* EXTI Line2 */
.word EXTI3_IRQHandler /* EXTI Line3 */
.word EXTI4_IRQHandler /* EXTI Line4 */
.word EXTI5_IRQHandler /* EXTI Line5 */
.word EXTI6_IRQHandler /* EXTI Line6 */
.word EXTI7_IRQHandler /* EXTI Line7 */
.word EXTI8_IRQHandler /* EXTI Line8 */
.word EXTI9_IRQHandler /* EXTI Line9 */
.word EXTI10_IRQHandler /* EXTI Line10 */
.word EXTI11_IRQHandler /* EXTI Line11 */
.word EXTI12_IRQHandler /* EXTI Line12 */
.word EXTI13_IRQHandler /* EXTI Line13 */
.word EXTI14_IRQHandler /* EXTI Line14 */
.word EXTI15_IRQHandler /* EXTI Line15 */
.word RTC_IRQHandler /* RTC wakeup and alarm interrupts */
.word SAES_IRQHandler /* SAES */
.word CRYP_IRQHandler /* CRYP */
.word PKA_IRQHandler /* PKA */
.word HASH_IRQHandler /* HASH */
.word RNG_IRQHandler /* RNG */
.word ADC1_2_IRQHandler /* ADC1 & ADC2 */
.word GPDMA1_Channel0_IRQHandler /* GPDMA1 Channel 0 */
.word GPDMA1_Channel1_IRQHandler /* GPDMA1 Channel 1 */
.word GPDMA1_Channel2_IRQHandler /* GPDMA1 Channel 2 */
.word GPDMA1_Channel3_IRQHandler /* GPDMA1 Channel 3 */
.word GPDMA1_Channel4_IRQHandler /* GPDMA1 Channel 4 */
.word GPDMA1_Channel5_IRQHandler /* GPDMA1 Channel 5 */
.word GPDMA1_Channel6_IRQHandler /* GPDMA1 Channel 6 */
.word GPDMA1_Channel7_IRQHandler /* GPDMA1 Channel 7 */
.word TIM1_BRK_IRQHandler /* TIM1 Break */
.word TIM1_UP_IRQHandler /* TIM1 Update */
.word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation */
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.word TIM2_IRQHandler /* TIM2 */
.word TIM3_IRQHandler /* TIM3 */
.word TIM4_IRQHandler /* TIM4 */
.word TIM5_IRQHandler /* TIM5 */
.word TIM6_IRQHandler /* TIM6 */
.word TIM7_IRQHandler /* TIM7 */
.word TIM9_IRQHandler /* TIM9 */
.word SPI1_IRQHandler /* SPI1 */
.word SPI2_IRQHandler /* SPI2 */
.word SPI3_IRQHandler /* SPI3 */
.word SPI4_IRQHandler /* SPI4 */
.word SPI5_IRQHandler /* SPI5 */
.word SPI6_IRQHandler /* SPI6 */
.word HPDMA1_Channel0_IRQHandler /* HPDMA1 Channel 0 */
.word HPDMA1_Channel1_IRQHandler /* HPDMA1 Channel 1 */
.word HPDMA1_Channel2_IRQHandler /* HPDMA1 Channel 2 */
.word HPDMA1_Channel3_IRQHandler /* HPDMA1 Channel 3 */
.word HPDMA1_Channel4_IRQHandler /* HPDMA1 Channel 4 */
.word HPDMA1_Channel5_IRQHandler /* HPDMA1 Channel 5 */
.word HPDMA1_Channel6_IRQHandler /* HPDMA1 Channel 6 */
.word HPDMA1_Channel7_IRQHandler /* HPDMA1 Channel 7 */
.word SAI1_A_IRQHandler /* Serial Audio Interface 1 block A */
.word SAI1_B_IRQHandler /* Serial Audio Interface 1 block B */
.word SAI2_A_IRQHandler /* Serial Audio Interface 2 block A */
.word SAI2_B_IRQHandler /* Serial Audio Interface 2 block B */
.word I2C1_EV_IRQHandler /* I2C1 Event */
.word I2C1_ER_IRQHandler /* I2C1 Error */
.word I2C2_EV_IRQHandler /* I2C2 Event */
.word I2C2_ER_IRQHandler /* I2C2 Error */
.word I2C3_EV_IRQHandler /* I2C3 Event */
.word I2C3_ER_IRQHandler /* I2C3 Error */
.word USART1_IRQHandler /* USART1 */
.word USART2_IRQHandler /* USART2 */
.word USART3_IRQHandler /* USART3 */
.word UART4_IRQHandler /* UART4 */
.word UART5_IRQHandler /* UART5 */
.word UART7_IRQHandler /* UART7 */
.word UART8_IRQHandler /* UART8 */
.word I3C1_EV_IRQHandler /* I3C1 Event */
.word I3C1_ER_IRQHandler /* I3C1 Error */
.word OTG_HS_IRQHandler /* USB OTG HS */
.word ETH_IRQHandler /* Ethernet */
.word CORDIC_IRQHandler /* CORDIC */
.word GFXTIM_IRQHandler /* GFXTIM */
.word DCMIPP_IRQHandler /* DCMIPP */
.word LTDC_IRQHandler /* LTDC */
.word LTDC_ER_IRQHandler /* LTDC error */
.word DMA2D_IRQHandler /* DMA2D */
.word JPEG_IRQHandler /* JPEG */
.word GFXMMU_IRQHandler /* GFXMMU */
.word I3C1_WKUP_IRQHandler /* I3C1 wakeup */
.word MCE1_IRQHandler /* MCE1 */
.word MCE2_IRQHandler /* MCE2 */
.word MCE3_IRQHandler /* MCE3 */
.word XSPI1_IRQHandler /* XSPI1 */
.word XSPI2_IRQHandler /* XSPI2 */
.word FMC_IRQHandler /* FMC */
.word SDMMC1_IRQHandler /* SDMMC1 */
.word SDMMC2_IRQHandler /* SDMMC2 */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word OTG_FS_IRQHandler /* USB OTG FS */
.word TIM12_IRQHandler /* TIM12 */
.word TIM13_IRQHandler /* TIM13 */
.word TIM14_IRQHandler /* TIM14 */
.word TIM15_IRQHandler /* TIM15 */
.word TIM16_IRQHandler /* TIM16 */
.word TIM17_IRQHandler /* TIM17 */
.word LPTIM1_IRQHandler /* LP TIM1 */
.word LPTIM2_IRQHandler /* LP TIM2 */
.word LPTIM3_IRQHandler /* LP TIM3 */
.word LPTIM4_IRQHandler /* LP TIM4 */
.word LPTIM5_IRQHandler /* LP TIM5 */
.word SPDIF_RX_IRQHandler /* SPDIF_RX */
.word MDIOS_IRQHandler /* MDIOS */
.word ADF1_FLT0_IRQHandler /* ADF1 Filter 0 */
.word CRS_IRQHandler /* CRS */
.word UCPD1_IRQHandler /* UCPD1 */
.word CEC_IRQHandler /* HDMI_CEC */
.word PSSI_IRQHandler /* PSSI */
.word LPUART1_IRQHandler /* LP UART1 */
.word WAKEUP_PIN_IRQHandler /* Wake-up pins interrupt */
.word GPDMA1_Channel8_IRQHandler /* GPDMA1 Channel 8 */
.word GPDMA1_Channel9_IRQHandler /* GPDMA1 Channel 9 */
.word GPDMA1_Channel10_IRQHandler /* GPDMA1 Channel 10 */
.word GPDMA1_Channel11_IRQHandler /* GPDMA1 Channel 11 */
.word GPDMA1_Channel12_IRQHandler /* GPDMA1 Channel 12 */
.word GPDMA1_Channel13_IRQHandler /* GPDMA1 Channel 13 */
.word GPDMA1_Channel14_IRQHandler /* GPDMA1 Channel 14 */
.word GPDMA1_Channel15_IRQHandler /* GPDMA1 Channel 15 */
.word HPDMA1_Channel8_IRQHandler /* HPDMA1 Channel 8 */
.word HPDMA1_Channel9_IRQHandler /* HPDMA1 Channel 9 */
.word HPDMA1_Channel10_IRQHandler /* HPDMA1 Channel 10 */
.word HPDMA1_Channel11_IRQHandler /* HPDMA1 Channel 11 */
.word HPDMA1_Channel12_IRQHandler /* HPDMA1 Channel 12 */
.word HPDMA1_Channel13_IRQHandler /* HPDMA1 Channel 13 */
.word HPDMA1_Channel14_IRQHandler /* HPDMA1 Channel 14 */
.word HPDMA1_Channel15_IRQHandler /* HPDMA1 Channel 15 */
.word GPU2D_IRQHandler /* GPU2D */
.word GPU2D_ER_IRQHandler /* GPU2D error */
.word ICACHE_IRQHandler /* ICACHE */
.word FDCAN1_IT0_IRQHandler /* FDCAN1 Interrupt 0 */
.word FDCAN1_IT1_IRQHandler /* FDCAN1 Interrupt 1 */
.word FDCAN2_IT0_IRQHandler /* FDCAN2 Interrupt 0 */
.word FDCAN2_IT1_IRQHandler /* FDCAN2 Interrupt 1 */
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak PVD_PVM_IRQHandler
.thumb_set PVD_PVM_IRQHandler,Default_Handler
.weak DTS_IRQHandler
.thumb_set DTS_IRQHandler,Default_Handler
.weak IWDG_IRQHandler
.thumb_set IWDG_IRQHandler,Default_Handler
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
.weak RCC_IRQHandler
.thumb_set RCC_IRQHandler,Default_Handler
.weak FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler
.weak RAMECC_IRQHandler
.thumb_set RAMECC_IRQHandler,Default_Handler
.weak FPU_IRQHandler
.thumb_set FPU_IRQHandler,Default_Handler
.weak TAMP_IRQHandler
.thumb_set TAMP_IRQHandler,Default_Handler
.weak EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler
.weak EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler
.weak EXTI2_IRQHandler
.thumb_set EXTI2_IRQHandler,Default_Handler
.weak EXTI3_IRQHandler
.thumb_set EXTI3_IRQHandler,Default_Handler
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
.weak EXTI5_IRQHandler
.thumb_set EXTI5_IRQHandler,Default_Handler
.weak EXTI6_IRQHandler
.thumb_set EXTI6_IRQHandler,Default_Handler
.weak EXTI7_IRQHandler
.thumb_set EXTI7_IRQHandler,Default_Handler
.weak EXTI8_IRQHandler
.thumb_set EXTI8_IRQHandler,Default_Handler
.weak EXTI9_IRQHandler
.thumb_set EXTI9_IRQHandler,Default_Handler
.weak EXTI10_IRQHandler
.thumb_set EXTI10_IRQHandler,Default_Handler
.weak EXTI11_IRQHandler
.thumb_set EXTI11_IRQHandler,Default_Handler
.weak EXTI12_IRQHandler
.thumb_set EXTI12_IRQHandler,Default_Handler
.weak EXTI13_IRQHandler
.thumb_set EXTI13_IRQHandler,Default_Handler
.weak EXTI14_IRQHandler
.thumb_set EXTI14_IRQHandler,Default_Handler
.weak EXTI15_IRQHandler
.thumb_set EXTI15_IRQHandler,Default_Handler
.weak RTC_IRQHandler
.thumb_set RTC_IRQHandler,Default_Handler
.weak SAES_IRQHandler
.thumb_set SAES_IRQHandler,Default_Handler
.weak CRYP_IRQHandler
.thumb_set CRYP_IRQHandler,Default_Handler
.weak PKA_IRQHandler
.thumb_set PKA_IRQHandler,Default_Handler
.weak HASH_IRQHandler
.thumb_set HASH_IRQHandler,Default_Handler
.weak RNG_IRQHandler
.thumb_set RNG_IRQHandler,Default_Handler
.weak ADC1_2_IRQHandler
.thumb_set ADC1_2_IRQHandler,Default_Handler
.weak GPDMA1_Channel0_IRQHandler
.thumb_set GPDMA1_Channel0_IRQHandler,Default_Handler
.weak GPDMA1_Channel1_IRQHandler
.thumb_set GPDMA1_Channel1_IRQHandler,Default_Handler
.weak GPDMA1_Channel2_IRQHandler
.thumb_set GPDMA1_Channel2_IRQHandler,Default_Handler
.weak GPDMA1_Channel3_IRQHandler
.thumb_set GPDMA1_Channel3_IRQHandler,Default_Handler
.weak GPDMA1_Channel4_IRQHandler
.thumb_set GPDMA1_Channel4_IRQHandler,Default_Handler
.weak GPDMA1_Channel5_IRQHandler
.thumb_set GPDMA1_Channel5_IRQHandler,Default_Handler
.weak GPDMA1_Channel6_IRQHandler
.thumb_set GPDMA1_Channel6_IRQHandler,Default_Handler
.weak GPDMA1_Channel7_IRQHandler
.thumb_set GPDMA1_Channel7_IRQHandler,Default_Handler
.weak TIM1_BRK_IRQHandler
.thumb_set TIM1_BRK_IRQHandler,Default_Handler
.weak TIM1_UP_IRQHandler
.thumb_set TIM1_UP_IRQHandler,Default_Handler
.weak TIM1_TRG_COM_IRQHandler
.thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
.weak TIM2_IRQHandler
.thumb_set TIM2_IRQHandler,Default_Handler
.weak TIM3_IRQHandler
.thumb_set TIM3_IRQHandler,Default_Handler
.weak TIM4_IRQHandler
.thumb_set TIM4_IRQHandler,Default_Handler
.weak TIM5_IRQHandler
.thumb_set TIM5_IRQHandler,Default_Handler
.weak TIM6_IRQHandler
.thumb_set TIM6_IRQHandler,Default_Handler
.weak TIM7_IRQHandler
.thumb_set TIM7_IRQHandler,Default_Handler
.weak TIM9_IRQHandler
.thumb_set TIM9_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler
.weak SPI3_IRQHandler
.thumb_set SPI3_IRQHandler,Default_Handler
.weak SPI4_IRQHandler
.thumb_set SPI4_IRQHandler,Default_Handler
.weak SPI5_IRQHandler
.thumb_set SPI5_IRQHandler,Default_Handler
.weak SPI6_IRQHandler
.thumb_set SPI6_IRQHandler,Default_Handler
.weak HPDMA1_Channel0_IRQHandler
.thumb_set HPDMA1_Channel0_IRQHandler,Default_Handler
.weak HPDMA1_Channel1_IRQHandler
.thumb_set HPDMA1_Channel1_IRQHandler,Default_Handler
.weak HPDMA1_Channel2_IRQHandler
.thumb_set HPDMA1_Channel2_IRQHandler,Default_Handler
.weak HPDMA1_Channel3_IRQHandler
.thumb_set HPDMA1_Channel3_IRQHandler,Default_Handler
.weak HPDMA1_Channel4_IRQHandler
.thumb_set HPDMA1_Channel4_IRQHandler,Default_Handler
.weak HPDMA1_Channel5_IRQHandler
.thumb_set HPDMA1_Channel5_IRQHandler,Default_Handler
.weak HPDMA1_Channel6_IRQHandler
.thumb_set HPDMA1_Channel6_IRQHandler,Default_Handler
.weak HPDMA1_Channel7_IRQHandler
.thumb_set HPDMA1_Channel7_IRQHandler,Default_Handler
.weak SAI1_A_IRQHandler
.thumb_set SAI1_A_IRQHandler,Default_Handler
.weak SAI1_B_IRQHandler
.thumb_set SAI1_B_IRQHandler,Default_Handler
.weak SAI2_A_IRQHandler
.thumb_set SAI2_A_IRQHandler,Default_Handler
.weak SAI2_B_IRQHandler
.thumb_set SAI2_B_IRQHandler,Default_Handler
.weak I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak I2C2_EV_IRQHandler
.thumb_set I2C2_EV_IRQHandler,Default_Handler
.weak I2C2_ER_IRQHandler
.thumb_set I2C2_ER_IRQHandler,Default_Handler
.weak I2C3_EV_IRQHandler
.thumb_set I2C3_EV_IRQHandler,Default_Handler
.weak I2C3_ER_IRQHandler
.thumb_set I2C3_ER_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak USART3_IRQHandler
.thumb_set USART3_IRQHandler,Default_Handler
.weak UART4_IRQHandler
.thumb_set UART4_IRQHandler,Default_Handler
.weak UART5_IRQHandler
.thumb_set UART5_IRQHandler,Default_Handler
.weak UART7_IRQHandler
.thumb_set UART7_IRQHandler,Default_Handler
.weak UART8_IRQHandler
.thumb_set UART8_IRQHandler,Default_Handler
.weak I3C1_EV_IRQHandler
.thumb_set I3C1_EV_IRQHandler,Default_Handler
.weak I3C1_ER_IRQHandler
.thumb_set I3C1_ER_IRQHandler,Default_Handler
.weak OTG_HS_IRQHandler
.thumb_set OTG_HS_IRQHandler,Default_Handler
.weak ETH_IRQHandler
.thumb_set ETH_IRQHandler,Default_Handler
.weak CORDIC_IRQHandler
.thumb_set CORDIC_IRQHandler,Default_Handler
.weak GFXTIM_IRQHandler
.thumb_set GFXTIM_IRQHandler,Default_Handler
.weak DCMIPP_IRQHandler
.thumb_set DCMIPP_IRQHandler,Default_Handler
.weak LTDC_IRQHandler
.thumb_set LTDC_IRQHandler,Default_Handler
.weak LTDC_ER_IRQHandler
.thumb_set LTDC_ER_IRQHandler,Default_Handler
.weak DMA2D_IRQHandler
.thumb_set DMA2D_IRQHandler,Default_Handler
.weak JPEG_IRQHandler
.thumb_set JPEG_IRQHandler,Default_Handler
.weak GFXMMU_IRQHandler
.thumb_set GFXMMU_IRQHandler,Default_Handler
.weak I3C1_WKUP_IRQHandler
.thumb_set I3C1_WKUP_IRQHandler,Default_Handler
.weak MCE1_IRQHandler
.thumb_set MCE1_IRQHandler,Default_Handler
.weak MCE2_IRQHandler
.thumb_set MCE2_IRQHandler,Default_Handler
.weak MCE3_IRQHandler
.thumb_set MCE3_IRQHandler,Default_Handler
.weak XSPI1_IRQHandler
.thumb_set XSPI1_IRQHandler,Default_Handler
.weak XSPI2_IRQHandler
.thumb_set XSPI2_IRQHandler,Default_Handler
.weak FMC_IRQHandler
.thumb_set FMC_IRQHandler,Default_Handler
.weak SDMMC1_IRQHandler
.thumb_set SDMMC1_IRQHandler,Default_Handler
.weak SDMMC2_IRQHandler
.thumb_set SDMMC2_IRQHandler,Default_Handler
.weak OTG_FS_IRQHandler
.thumb_set OTG_FS_IRQHandler,Default_Handler
.weak TIM12_IRQHandler
.thumb_set TIM12_IRQHandler,Default_Handler
.weak TIM13_IRQHandler
.thumb_set TIM13_IRQHandler,Default_Handler
.weak TIM14_IRQHandler
.thumb_set TIM14_IRQHandler,Default_Handler
.weak TIM15_IRQHandler
.thumb_set TIM15_IRQHandler,Default_Handler
.weak TIM16_IRQHandler
.thumb_set TIM16_IRQHandler,Default_Handler
.weak TIM17_IRQHandler
.thumb_set TIM17_IRQHandler,Default_Handler
.weak LPTIM1_IRQHandler
.thumb_set LPTIM1_IRQHandler,Default_Handler
.weak LPTIM2_IRQHandler
.thumb_set LPTIM2_IRQHandler,Default_Handler
.weak LPTIM3_IRQHandler
.thumb_set LPTIM3_IRQHandler,Default_Handler
.weak LPTIM4_IRQHandler
.thumb_set LPTIM4_IRQHandler,Default_Handler
.weak LPTIM5_IRQHandler
.thumb_set LPTIM5_IRQHandler,Default_Handler
.weak SPDIF_RX_IRQHandler
.thumb_set SPDIF_RX_IRQHandler,Default_Handler
.weak MDIOS_IRQHandler
.thumb_set MDIOS_IRQHandler,Default_Handler
.weak ADF1_FLT0_IRQHandler
.thumb_set ADF1_FLT0_IRQHandler,Default_Handler
.weak CRS_IRQHandler
.thumb_set CRS_IRQHandler,Default_Handler
.weak UCPD1_IRQHandler
.thumb_set UCPD1_IRQHandler,Default_Handler
.weak CEC_IRQHandler
.thumb_set CEC_IRQHandler,Default_Handler
.weak PSSI_IRQHandler
.thumb_set PSSI_IRQHandler,Default_Handler
.weak LPUART1_IRQHandler
.thumb_set LPUART1_IRQHandler,Default_Handler
.weak WAKEUP_PIN_IRQHandler
.thumb_set WAKEUP_PIN_IRQHandler,Default_Handler
.weak GPDMA1_Channel8_IRQHandler
.thumb_set GPDMA1_Channel8_IRQHandler,Default_Handler
.weak GPDMA1_Channel9_IRQHandler
.thumb_set GPDMA1_Channel9_IRQHandler,Default_Handler
.weak GPDMA1_Channel10_IRQHandler
.thumb_set GPDMA1_Channel10_IRQHandler,Default_Handler
.weak GPDMA1_Channel11_IRQHandler
.thumb_set GPDMA1_Channel11_IRQHandler,Default_Handler
.weak GPDMA1_Channel12_IRQHandler
.thumb_set GPDMA1_Channel12_IRQHandler,Default_Handler
.weak GPDMA1_Channel13_IRQHandler
.thumb_set GPDMA1_Channel13_IRQHandler,Default_Handler
.weak GPDMA1_Channel14_IRQHandler
.thumb_set GPDMA1_Channel14_IRQHandler,Default_Handler
.weak GPDMA1_Channel15_IRQHandler
.thumb_set GPDMA1_Channel15_IRQHandler,Default_Handler
.weak HPDMA1_Channel8_IRQHandler
.thumb_set HPDMA1_Channel8_IRQHandler,Default_Handler
.weak HPDMA1_Channel9_IRQHandler
.thumb_set HPDMA1_Channel9_IRQHandler,Default_Handler
.weak HPDMA1_Channel10_IRQHandler
.thumb_set HPDMA1_Channel10_IRQHandler,Default_Handler
.weak HPDMA1_Channel11_IRQHandler
.thumb_set HPDMA1_Channel11_IRQHandler,Default_Handler
.weak HPDMA1_Channel12_IRQHandler
.thumb_set HPDMA1_Channel12_IRQHandler,Default_Handler
.weak HPDMA1_Channel13_IRQHandler
.thumb_set HPDMA1_Channel13_IRQHandler,Default_Handler
.weak HPDMA1_Channel14_IRQHandler
.thumb_set HPDMA1_Channel14_IRQHandler,Default_Handler
.weak HPDMA1_Channel15_IRQHandler
.thumb_set HPDMA1_Channel15_IRQHandler,Default_Handler
.weak GPU2D_IRQHandler
.thumb_set GPU2D_IRQHandler,Default_Handler
.weak GPU2D_ER_IRQHandler
.thumb_set GPU2D_ER_IRQHandler,Default_Handler
.weak ICACHE_IRQHandler
.thumb_set ICACHE_IRQHandler,Default_Handler
.weak FDCAN1_IT0_IRQHandler
.thumb_set FDCAN1_IT0_IRQHandler,Default_Handler
.weak FDCAN1_IT1_IRQHandler
.thumb_set FDCAN1_IT1_IRQHandler,Default_Handler
.weak FDCAN2_IT0_IRQHandler
.thumb_set FDCAN2_IT0_IRQHandler,Default_Handler
.weak FDCAN2_IT1_IRQHandler
.thumb_set FDCAN2_IT1_IRQHandler,Default_Handler
.weak SystemInit
+9 -4
View File
@@ -20,6 +20,7 @@
*/
#include "hal/switch_driver.h"
#include "bsp_io.h"
#include "stm32_switch_driver.h"
#include "stm32_gpio_driver.h"
@@ -36,17 +37,21 @@ __weak void boardInitSwitches()
_init_switches();
}
__weak SwitchHwPos boardSwitchGetPosition(uint8_t cat, uint8_t idx)
__weak SwitchHwPos boardSwitchGetPosition(SwitchCategory cat, uint8_t idx)
{
return stm32_switch_get_position(&_switch_offsets[cat][idx]);
const stm32_switch_t* sw = &_switch_offsets[cat][idx];
if(sw->type != SWITCH_HW_ADC && sw->GPIOx_high == nullptr)
return bsp_get_switch_position(sw, cat, idx);
return stm32_switch_get_position(sw);
}
const char* boardSwitchGetName(uint8_t cat, uint8_t idx)
const char* boardSwitchGetName(SwitchCategory cat, uint8_t idx)
{
return _switch_offsets[cat][idx].name;
}
SwitchHwType boardSwitchGetType(uint8_t cat, uint8_t idx)
SwitchHwType boardSwitchGetType(SwitchCategory cat, uint8_t idx)
{
return _switch_offsets[cat][idx].type;
}
+4
View File
@@ -1388,9 +1388,11 @@ int cliDisplay(const char ** argv)
case 2:
tim = TIM2;
break;
#if defined(TIM8)
case 8:
tim = TIM8;
break;
#endif
case 13:
tim = TIM13;
break;
@@ -1417,10 +1419,12 @@ int cliDisplay(const char ** argv)
cliSerialPrint(" CCR4 0x%x", tim->CCR4);
}
}
#if defined(DMA1_Stream7)
else if (!strcmp(argv[1], "dma")) {
cliSerialPrint("DMA1_Stream7");
cliSerialPrint(" CR 0x%x", DMA1_Stream7->CR);
}
#endif
#if defined(DEBUG_INTERRUPTS)
else if (!strcmp(argv[1], "int")) {
printInterrupts();
+1 -1
View File
@@ -40,7 +40,7 @@
#define LABELS_LENGTH 100 // Maximum length of the label string
#define LABEL_LENGTH 16
#if defined(COLORLCD) || defined(STM32H747xx)
#if defined(COLORLCD)
#define MAX_MODELS 60
#define MAX_OUTPUT_CHANNELS 32 // number of real output channels CH1-CH32
#define MAX_FLIGHT_MODES 9
+12 -16
View File
@@ -628,19 +628,19 @@ PACK(struct CustomScreenData {
#endif
struct RGBLedColor {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t r;
uint8_t g;
uint8_t b;
uint32_t getColor() {
return ((r << 16) + (g << 8) + b);
}
uint32_t getColor() {
return ((r << 16) + (g << 8) + b);
}
void setColor(uint32_t color) {
r = color >> 16;
g = color >> 8;
b = color;
}
void setColor(uint32_t color) {
r = color >> 16;
g = color >> 8;
b = color;
}
};
#if defined(FUNCTION_SWITCHES_RGB_LEDS)
@@ -655,7 +655,7 @@ struct RGBLedColor {
uint16_t functionSwitchConfig; \
uint16_t functionSwitchGroup; \
uint16_t functionSwitchStartConfig; \
uint8_t functionSwitchLogicalState; \
uint8_t functionSwitchLogicalState; \
char switchNames[NUM_FUNCTIONS_SWITCHES][LEN_SWITCH_NAME]; \
FUNCTION_SWITCHS_RGB_LEDS_FIELDS
#else
@@ -973,12 +973,8 @@ PACK(struct RadioData {
char ownerRegistrationID[PXX2_LEN_REGISTRATION_ID];
#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS)
CUST_ATTR(rotEncDirection, r_rotEncDirection, nullptr);
NOBACKUP(uint8_t rotEncMode:3);
#else
NOBACKUP(uint8_t rotEncModeSpare:3 SKIP);
#endif
NOBACKUP(int8_t uartSampleMode:2); // See UartSampleModes
+2 -24
View File
@@ -25,6 +25,8 @@
#include <stdbool.h>
#include <stddef.h>
#include "memory_sections.h"
#if !defined(M_PI)
#define M_PI 3.14159265358979323846 // pi
#define M_PI_2 1.57079632679489661923 // pi/2
@@ -55,30 +57,6 @@
#endif
#endif
#if defined(SIMU)
#define __DMA
#else
#define __DMA __attribute__((section(".ram"), aligned(4)))
#endif
#if defined(CCMRAM) && !defined(SIMU)
#define __CCMRAM __attribute__((section(".ccm"), aligned(4)))
#else
#define __CCMRAM
#endif
#if defined(SDRAM) && !defined(SIMU)
#define __SDRAM __attribute__((section(".sdram"), aligned(4)))
#if defined(COLORLCD)
#define __SDRAMFONTS __attribute__((section(".sdram_fonts"), aligned(4)))
#endif
#else
#define __SDRAM __DMA
#if defined(COLORLCD)
#define __SDRAMFONTS __DMA
#endif
#endif
#if __GNUC__
#define PACK(__Declaration__) __Declaration__ __attribute__((__packed__))
#else
+489
View File
@@ -0,0 +1,489 @@
/*
* Copyright (c) 2016 Adafruit Industries
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "uf2_ghostfat.h"
#include "board.h"
#include "uf2/uf2.h"
#include "io/uf2.h"
#include "hal/flash_driver.h"
#include "fw_desc.h"
#include "debug.h"
#include <string.h>
typedef struct {
uint8_t JumpInstruction[3];
uint8_t OEMInfo[8];
uint16_t SectorSize;
uint8_t SectorsPerCluster;
uint16_t ReservedSectors;
uint8_t FATCopies;
uint16_t RootDirectoryEntries;
uint16_t TotalSectors16;
uint8_t MediaDescriptor;
uint16_t SectorsPerFAT;
uint16_t SectorsPerTrack;
uint16_t Heads;
uint32_t HiddenSectors;
uint32_t TotalSectors32;
uint8_t PhysicalDriveNum;
uint8_t Reserved;
uint8_t ExtendedBootSig;
uint32_t VolumeSerialNumber;
uint8_t VolumeLabel[11];
uint8_t FilesystemIdentifier[8];
} __attribute__((packed)) FAT_BootBlock;
typedef struct {
char name[8];
char ext[3];
uint8_t attrs;
uint8_t reserved;
uint8_t createTimeFine;
uint16_t createTime;
uint16_t createDate;
uint16_t lastAccessDate;
uint16_t highStartCluster;
uint16_t updateTime;
uint16_t updateDate;
uint16_t startCluster;
uint32_t size;
} __attribute__((packed)) DirEntry;
static_assert(sizeof(DirEntry) == 32);
struct TextFile {
char const name[11];
char const *content;
};
#define NUM_FAT_BLOCKS UF2_NUM_BLOCKS
#define UF2_VOLUME_LABEL {'E', 'D', 'G', 'E', 'T', 'X', '_', 'U', 'F', '2', ' ' }
#define UF2_INDEX_URL "https://edgetx.org"
#define STR0(x) #x
#define STR(x) STR0(x)
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif
#define __YEAR_INT__ ((( \
(__DATE__ [ 7u] - '0') * 10u + \
(__DATE__ [ 8u] - '0')) * 10u + \
(__DATE__ [ 9u] - '0')) * 10u + \
(__DATE__ [10u] - '0'))
#define __MONTH_INT__ ( \
(__DATE__ [2u] == 'n' && __DATE__ [1u] == 'a') ? 1u /*Jan*/ \
: (__DATE__ [2u] == 'b' ) ? 2u /*Feb*/ \
: (__DATE__ [2u] == 'r' && __DATE__ [1u] == 'a') ? 3u /*Mar*/ \
: (__DATE__ [2u] == 'r' ) ? 4u /*Apr*/ \
: (__DATE__ [2u] == 'y' ) ? 5u /*May*/ \
: (__DATE__ [2u] == 'n' ) ? 6u /*Jun*/ \
: (__DATE__ [2u] == 'l' ) ? 7u /*Jul*/ \
: (__DATE__ [2u] == 'g' ) ? 8u /*Aug*/ \
: (__DATE__ [2u] == 'p' ) ? 9u /*Sep*/ \
: (__DATE__ [2u] == 't' ) ? 10u /*Oct*/ \
: (__DATE__ [2u] == 'v' ) ? 11u /*Nov*/ \
: 12u /*Dec*/ )
#define __DAY_INT__ ( \
(__DATE__ [4u] == ' ' ? 0u : __DATE__ [4u] - '0') * 10u \
+ (__DATE__ [5u] - '0') )
// __TIME__ expands to an eight-character string constant
// "23:59:01", or (if cannot determine time) "??:??:??"
#define __HOUR_INT__ ( \
(__TIME__ [0u] == '?' ? 0u : __TIME__ [0u] - '0') * 10u \
+ (__TIME__ [1u] == '?' ? 0u : __TIME__ [1u] - '0') )
#define __MINUTE_INT__ ( \
(__TIME__ [3u] == '?' ? 0u : __TIME__ [3u] - '0') * 10u \
+ (__TIME__ [4u] == '?' ? 0u : __TIME__ [4u] - '0') )
#define __SECONDS_INT__ ( \
(__TIME__ [6u] == '?' ? 0u : __TIME__ [6u] - '0') * 10u \
+ (__TIME__ [7u] == '?' ? 0u : __TIME__ [7u] - '0') )
#define __DOSDATE__ ( \
((__YEAR_INT__ - 1980u) << 9u) | \
( __MONTH_INT__ << 5u) | \
( __DAY_INT__ << 0u) )
#define __DOSTIME__ ( \
( __HOUR_INT__ << 11u) | \
( __MINUTE_INT__ << 5u) | \
( __SECONDS_INT__ << 0u) )
#include "stamp.h"
const char infoUf2File[] =
"UF2 Bootloader " VERSION "\r\n"
"Board-ID: " FLAVOUR "\r\n"
"Date: " DATE "\r\n";
const char indexFile[] = //
"<!doctype html>\n"
"<html>"
"<body>"
"<script>\n"
"location.replace(\"" UF2_INDEX_URL "\");\n"
"</script>"
"</body>"
"</html>\n";
// WARNING -- code presumes only one NULL .content for .UF2 file
// and requires it be the last element of the array
static struct TextFile const info[] = {
{.name = {'I','N','F','O','_','U','F','2','T','X','T'}, .content = infoUf2File},
{.name = {'I','N','D','E','X',' ',' ',' ','H','T','M'}, .content = indexFile},
{.name = {'C','U','R','R','E','N','T',' ','U','F','2'}, .content = nullptr},
};
// WARNING -- code presumes each non-UF2 file content fits in single sector
// Cannot programmatically statically assert .content length
// for each element above.
static_assert(ARRAY_SIZE(indexFile) < 512);
#define NUM_FILES (ARRAY_SIZE(info))
#define NUM_DIRENTRIES (NUM_FILES + 1) // Code adds volume label as first root directory entry
#define UF2_SIZE (current_flash_size() * 2 + 512)
#define UF2_SECTORS (UF2_SIZE / 512)
#define UF2_FIRST_SECTOR (NUM_FILES + 1) // WARNING -- code presumes each non-UF2 file content fits in single sector
#define UF2_LAST_SECTOR (UF2_FIRST_SECTOR + UF2_SECTORS - 1)
#define RESERVED_SECTORS 1
#define ROOT_DIR_SECTORS 4
#define SECTORS_PER_FAT ((NUM_FAT_BLOCKS * 2 + 511) / 512)
#define START_FAT0 RESERVED_SECTORS
#define START_FAT1 (START_FAT0 + SECTORS_PER_FAT)
#define START_ROOTDIR (START_FAT1 + SECTORS_PER_FAT)
#define START_CLUSTERS (START_ROOTDIR + ROOT_DIR_SECTORS)
// all directory entries must fit in a single sector
// because otherwise current code overflows buffer
#define DIRENTRIES_PER_SECTOR (512/sizeof(DirEntry))
static_assert(NUM_DIRENTRIES < DIRENTRIES_PER_SECTOR * ROOT_DIR_SECTORS);
static FAT_BootBlock const BootBlock = {
.JumpInstruction = {0xeb, 0x3c, 0x90},
.OEMInfo = {'M','S','W','I','N','4','.','1'},
.SectorSize = 512,
.SectorsPerCluster = 1,
.ReservedSectors = RESERVED_SECTORS,
.FATCopies = 2,
.RootDirectoryEntries = (ROOT_DIR_SECTORS * DIRENTRIES_PER_SECTOR),
.TotalSectors16 = NUM_FAT_BLOCKS - 2,
.MediaDescriptor = 0xF8,
.SectorsPerFAT = SECTORS_PER_FAT,
.SectorsPerTrack = 1,
.Heads = 1,
.PhysicalDriveNum = 0x80, // to match MediaDescriptor of 0xF8
.ExtendedBootSig = 0x29,
.VolumeSerialNumber = 0x00000000,
.VolumeLabel = UF2_VOLUME_LABEL,
.FilesystemIdentifier = {'F','A','T','1','6',' ',' ',' '},
};
static uf2_fat_write_state_t _uf2_write_state;
void uf2_fat_reset_state()
{
memset(&_uf2_write_state, 0, sizeof(_uf2_write_state));
}
const uf2_fat_write_state_t* uf2_fat_get_state()
{
return &_uf2_write_state;
}
static inline bool is_firmware_length_valid(uint32_t len)
{
return len && len <= UF2_MAX_FW_SIZE;
}
static inline bool is_address_in_firmware(uintptr_t addr)
{
return (addr & FIRMWARE_ADDRESS) == FIRMWARE_ADDRESS;
}
static inline bool is_firmware_valid(firmware_description_t const* fw_desc)
{
return fw_desc && is_firmware_length_valid(fw_desc->length) &&
is_address_in_firmware(fw_desc->version_ptr) &&
is_address_in_firmware((uintptr_t)fw_desc->reset_handler);
}
// get current.uf2 flash size in bytes, round up to 256 bytes
static uint32_t current_flash_size(void)
{
static uint32_t flash_sz = 0;
uint32_t result = flash_sz; // presumes atomic 32-bit read/write and static result
// only need to compute once
if ( result == 0 ) {
firmware_description_t const *fw_desc =
(firmware_description_t const *)FIRMWARE_ADDRESS;
if (is_firmware_valid(fw_desc)) {
// round up to 256 bytes
result = (fw_desc->length + BOOTLOADER_SIZE + 255U) & (~255U);
} else {
result = UF2_MAX_FW_SIZE;
}
flash_sz = result; // presumes atomic 32-bit read/write and static result
}
return flash_sz;
}
static void padded_memcpy (char *dst, char const *src, int len)
{
for (int i = 0; i < len; ++i) {
if (*src)
*dst = *src++;
else
*dst = ' ';
dst++;
}
}
/*------------------------------------------------------------------*/
/* Read
*------------------------------------------------------------------*/
void uf2_fat_read_block(uint32_t block_no, uint8_t *data)
{
memset(data, 0, 512);
uint32_t sectionIdx = block_no;
if (block_no == 0) { // Requested boot block
memcpy(data, &BootBlock, sizeof(BootBlock));
data[510] = 0x55;
data[511] = 0xaa;
// logval("data[0]", data[0]);
} else if (block_no < START_ROOTDIR) { // Requested FAT table sector
sectionIdx -= START_FAT0;
// logval("sidx", sectionIdx);
if (sectionIdx >= SECTORS_PER_FAT)
sectionIdx -= SECTORS_PER_FAT; // second FAT is same as the first...
if (sectionIdx == 0) {
data[0] = 0xf8; // first FAT entry must match BPB MediaDescriptor
// WARNING -- code presumes only one NULL .content for .UF2 file
// and all non-NULL .content fit in one sector
// and requires it be the last element of the array
for (unsigned i = 1; i < NUM_FILES * 2 + 4; ++i) {
data[i] = 0xff;
}
}
for (unsigned i = 0; i < 256; ++i) { // Generate the FAT chain for the firmware "file"
uint32_t v = sectionIdx * 256 + i;
if (UF2_FIRST_SECTOR <= v && v <= UF2_LAST_SECTOR)
((uint16_t *)(void *)data)[i] = v == UF2_LAST_SECTOR ? 0xffff : v + 1;
}
} else if (block_no < START_CLUSTERS) { // Requested root directory sector
sectionIdx -= START_ROOTDIR;
DirEntry *d = (DirEntry *)data;
int remainingEntries = DIRENTRIES_PER_SECTOR;
if (sectionIdx == 0) { // volume label first
// volume label is first directory entry
padded_memcpy(d->name, (char const *) BootBlock.VolumeLabel, 11);
d->attrs = 0x28;
d++;
remainingEntries--;
}
for (unsigned i = DIRENTRIES_PER_SECTOR * sectionIdx;
remainingEntries > 0 && i < NUM_FILES;
i++, d++) {
// WARNING -- code presumes all but last file take exactly one sector
uint16_t startCluster = i + 2;
struct TextFile const * inf = &info[i];
padded_memcpy(d->name, inf->name, 11);
d->createTimeFine = __SECONDS_INT__ % 2 * 100;
d->createTime = __DOSTIME__;
d->createDate = __DOSDATE__;
d->lastAccessDate = __DOSDATE__;
d->highStartCluster = startCluster >> 8;
// DIR_WrtTime and DIR_WrtDate must be supported
d->updateTime = __DOSTIME__;
d->updateDate = __DOSDATE__;
d->startCluster = startCluster & 0xFF;
// WARNING -- code presumes only one NULL .content for .UF2 file
// and requires it be the last element of the array
d->size = inf->content ? strlen(inf->content) : UF2_SIZE;
}
} else {
sectionIdx -= START_CLUSTERS;
if (sectionIdx < NUM_FILES - 1) {
memcpy(data, info[sectionIdx].content, strlen(info[sectionIdx].content));
} else { // generate the UF2 file data on-the-fly
sectionIdx -= NUM_FILES - 1;
uint32_t addr = 0;
if (sectionIdx >= UF2_MAX_FW_SIZE / 256) return;
UF2_Block *bl = (UF2_Block *)data;
bl->magicStart0 = UF2_MAGIC_START0;
bl->magicStart1 = UF2_MAGIC_START1;
bl->magicEnd = UF2_MAGIC_END;
bl->blockNo = sectionIdx;
bl->numBlocks = current_flash_size() / 256 + 1;
bl->flags = 0;
bl->reserved = 0;
if (sectionIdx == BOOTLOADER_SIZE / 256) {
writeUF2RebootBlock(bl);
writeUF2FirmwareVersion(bl);
} else {
if (sectionIdx < BOOTLOADER_SIZE / 256) {
addr = 0x08000000 + sectionIdx * 256;
} else {
sectionIdx -= BOOTLOADER_SIZE / 256 + 1;
addr = FIRMWARE_ADDRESS + sectionIdx * 256;
}
bl->targetAddr = addr;
bl->payloadSize = 256;
memcpy(bl->data, (void *)addr, bl->payloadSize);
writeUF2FirmwareVersion(bl);
}
}
}
}
/*------------------------------------------------------------------*/
/* Write UF2
*------------------------------------------------------------------*/
/** Write an block
*
* @return number of bytes processed, only the following values
* -1 : if not an uf2 block
* 512 : write is successful
*/
int uf2_fat_write_block(uint32_t block_no, uint8_t *data)
{
uf2_fat_write_state_t *wr_st = &_uf2_write_state;
UF2_Block *bl = (UF2_Block *)data;
// TRACE("Write magic: %x", bl->magicStart0);
if (!isUF2Block((const uint8_t*)bl, 512)) {
return -1;
}
// only accept block with same family id
if (UF2_FAMILY_ID && !((bl->flags & UF2_FLAG_FAMILY_ID) &&
(bl->reserved == UF2_FAMILY_ID))) {
return -1;
}
if ((bl->flags & UF2_FLAG_NOFLASH) || bl->payloadSize > 256 ||
(bl->targetAddr & 0xff) || bl->targetAddr < BOOTLOADER_ADDRESS ||
bl->targetAddr + bl->payloadSize >
(FIRMWARE_ADDRESS + UF2_MAX_FW_SIZE)) {
// block doesn't seem valid; we still want to count these blocks
// to reset properly
} else {
uint32_t wr_block = bl->blockNo;
if (wr_block >= BOOTLOADER_SIZE / 256) wr_block--;
uint32_t erase_sector = wr_block / (UF2_ERASE_BLOCK_SIZE / 256);
uint32_t mask = 1 << (erase_sector & 0x1F);
uint32_t pos = erase_sector >> 5;
uint32_t addr = bl->targetAddr;
if (wr_st && !(wr_st->erased_mask[pos] & mask)) {
TRACE_DEBUG("[UF2] erase 0x%08x\n", bl->targetAddr);
auto drv = flashFindDriver(addr);
if (drv) {
if (drv->erase_sector(addr) < 0) return -1;
// mark additional erased sectors
uint32_t sector = drv->get_sector(addr);
uint32_t sect_len = drv->get_sector_size(sector);
uint32_t media_len = flashGetSize(addr);
if (media_len < sect_len) sect_len = media_len;
uint32_t erased_sectors = sect_len / UF2_ERASE_BLOCK_SIZE;
while (erased_sectors-- != 0) {
pos = erase_sector >> 5;
mask = 1 << (erase_sector & 0x1F);
wr_st->erased_mask[pos] |= mask;
erase_sector++;
}
}
}
TRACE_DEBUG("[UF2] write 0x%08x\n", bl->targetAddr);
auto drv = flashFindDriver(addr);
if (drv) {
uint32_t len = bl->payloadSize;
uint8_t* data = (uint8_t*)bl->data;
if (drv->program(addr, data, len) < 0) return -1;
}
}
if (wr_st && bl->numBlocks) {
if (wr_st->num_blocks != bl->numBlocks) {
if (bl->numBlocks >= UF2_MAX_BLOCKS || wr_st->num_blocks) {
wr_st->num_blocks = UF2_INVALID_NUM_BLOCKS;
} else {
wr_st->num_blocks = bl->numBlocks;
}
}
if (bl->blockNo < UF2_MAX_BLOCKS) {
uint32_t mask = 1 << (bl->blockNo & 0x1F);
uint32_t pos = bl->blockNo >> 5;
if (!(wr_st->written_mask[pos] & mask)) {
wr_st->written_mask[pos] |= mask;
wr_st->num_written++;
TRACE_DEBUG("[UF2] wr #%d (%d / %d)\n", bl->blockNo,
state->num_written, bl->numBlocks);
}
if (wr_st->num_written >= wr_st->num_blocks) {
TRACE_DEBUG("[UF2] done: reboot\n");
}
}
}
return 512;
}
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <stdint.h>
#define UF2_NUM_BLOCKS 32768 // at least 16MB
#define UF2_INVALID_NUM_BLOCKS 0xFFFFFFFF
#if !defined(UF2_MAX_FW_SIZE)
#define UF2_MAX_FW_SIZE (2 * 1024 * 1024)
#endif
#define UF2_MAX_BLOCKS (UF2_MAX_FW_SIZE / 256)
#define UF2_ERASE_BLOCK_SIZE (4 * 1024)
#define UF2_ERASE_BLOCKS (UF2_MAX_FW_SIZE / UF2_ERASE_BLOCK_SIZE)
typedef struct {
uint32_t num_blocks;
uint32_t num_written;
uint32_t written_mask[UF2_MAX_BLOCKS / 32];
uint32_t erased_mask[UF2_ERASE_BLOCKS / 32];
} uf2_fat_write_state_t;
void uf2_fat_reset_state();
const uf2_fat_write_state_t* uf2_fat_get_state();
void uf2_fat_read_block(uint32_t block_no, uint8_t *data);
int uf2_fat_write_block(uint32_t block_no, uint8_t *data);
+5 -4
View File
@@ -94,7 +94,6 @@ uint8_t heartbeat;
safetych_t safetyCh[MAX_OUTPUT_CHANNELS];
#endif
// __DMA for the MSC_BOT_Data member
union ReusableBuffer reusableBuffer __DMA;
#if defined(DEBUG_LATENCY)
@@ -143,6 +142,8 @@ void checkValidMCU(void)
#define TARGET_IDCODE 0x463
#elif defined(STM32H750xx) || defined(STM32H747xx)
#define TARGET_IDCODE 0x450
#elif defined(STM32H7RS)
#define TARGET_IDCODE 0x485
#else
// Ensure new radio get registered :)
#warning "Target MCU code undefined"
@@ -208,7 +209,7 @@ void timer_10ms()
evalFunctionSwitches();
#endif
#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(LIBOPENUI)
#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(COLORLCD)
if (rotaryEncoderPollingCycle()) {
inactivityTimerReset(ActivitySource::Keys);
}
@@ -1123,7 +1124,7 @@ void edgeTxResume()
{
TRACE("edgeTxResume");
sdMount();
if (!sdMounted()) sdInit();
#if defined(COLORLCD) && defined(LUA)
// reload widgets
luaInitThemesAndWidgets();
@@ -1596,7 +1597,7 @@ int main()
checkValidMCU();
#endif
#if defined(PCBHORUS)
#if defined(IS_FIRMWARE_COMPATIBLE_WITH_BOARD)
if (!IS_FIRMWARE_COMPATIBLE_WITH_BOARD()) {
runFatalErrorScreen(STR_WRONG_PCBREV);
}
-4
View File
@@ -451,12 +451,8 @@ enum FunctionsActive {
FUNCTION_BACKGND_MUSIC_PAUSE,
FUNCTION_BACKLIGHT,
FUNCTION_RACING_MODE,
#if defined(HARDWARE_TOUCH)
FUNCTION_DISABLE_TOUCH,
#endif
#if defined(AUDIO_MUTE_GPIO)
FUNCTION_DISABLE_AUDIO_AMP,
#endif
};
#define VARIO_FREQUENCY_ZERO 700/*Hz*/
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "fw_desc.h"
// Symbols from linker script
extern uint32_t _estack;
extern uint32_t _firmware_length;
extern uint32_t _firmware_version;
extern void Reset_Handler();
__attribute__((section(".fwdescription"), used))
firmware_description_t _fw_desc = {
.stack_address = &_estack,
.reset_handler = (void*)Reset_Handler,
.length = (uint32_t)&_firmware_length,
.version_ptr = (uintptr_t)&_firmware_version,
};
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <stdint.h>
typedef struct {
// Allows the bootloader to load
// the firmware as if this would
// be the vector table.
void* stack_address;
void* reset_handler;
// TODO: insert some magic tag here
uint32_t length;
uint32_t version_ptr;
// .. and here ?
} firmware_description_t;
+1 -1
View File
@@ -37,5 +37,5 @@ extern const char vers_stamp[];
* (the one not running) or the buffer
* @param buffer If non-null find the firmware version in the buffer instead
*/
const char * getFirmwareVersion(const char * buffer = nullptr);
const char * getFirmwareVersion(const uint8_t* buffer = nullptr);
#endif
+49 -3
View File
@@ -64,12 +64,12 @@ uint16_t lcdColorTable[] = {
uint32_t HSVtoRGB(float H, float S, float V)
{
if (H > 360 || H < 0 || S > 100 || S < 0 || V > 100 || V < 0) {
if (H > 360 || H < 0 || S > MAX_SATURATION || S < 0 || V > MAX_BRIGHTNESS || V < 0) {
return 0;
}
float s = S / 100;
float v = V / 100;
float s = S / MAX_SATURATION;
float v = V / MAX_BRIGHTNESS;
float C = s * v;
float X = C * (1 - abs(fmod(H / 60.0, 2) - 1));
float m = v - C;
@@ -95,6 +95,39 @@ uint32_t HSVtoRGB(float H, float S, float V)
return RGB(R, G, B);
}
uint32_t HSVtoRGB32(float H, float S, float V)
{
if (H > 360 || H < 0 || S > MAX_SATURATION || S < 0 || V > MAX_BRIGHTNESS || V < 0) {
return 0;
}
float s = S / MAX_SATURATION;
float v = V / MAX_BRIGHTNESS;
float C = s * v;
float X = C * (1 - abs(fmod(H / 60.0, 2) - 1));
float m = v - C;
float r, g, b;
if (H >= 0 && H < 60) {
r = C, g = X, b = 0;
} else if (H >= 60 && H < 120) {
r = X, g = C, b = 0;
} else if (H >= 120 && H < 180) {
r = 0, g = C, b = X;
} else if (H >= 180 && H < 240) {
r = 0, g = X, b = C;
} else if (H >= 240 && H < 300) {
r = X, g = 0, b = C;
} else {
r = C, g = 0, b = X;
}
int R = (r + m) * 255;
int G = (g + m) * 255;
int B = (b + m) * 255;
return RGB32(R, G, B);
}
void RGBtoHSV(uint8_t R, uint8_t G, uint8_t B, float &fH, float &fS, float &fV)
{
float fR = (float)R / 255;
@@ -152,6 +185,19 @@ LcdFlags colorToRGB(LcdFlags colorFlags)
return (colorFlags & 0xFFFF) | COLOR(COLOR_VAL(colorFlags)) | RGB_FLAG;
}
uint32_t color32ToRGB(uint32_t color)
{
// RGB or indexed color?
if (color & RGB888_FLAG)
return color;
color = COLOR_VAL(COLOR(color));
auto r = GET_RED(color);
auto g = GET_GREEN(color);
auto b = GET_BLUE(color);
return RGB32(r, g, b) | RGB888_FLAG;
}
/**
* Helper function to translate a colorFlags value to a lv_color_t suitable
* for passing to an lv_obj function
+16
View File
@@ -132,9 +132,25 @@ constexpr int MAX_HUE = 360;
constexpr int MAX_BRIGHTNESS = 100;
extern uint32_t HSVtoRGB(float H, float S, float V);
extern uint32_t HSVtoRGB32(float H, float S, float V);
extern void RGBtoHSV(uint8_t R, uint8_t G, uint8_t B, float& fH, float& fS,
float& fV);
LcdFlags colorToRGB(LcdFlags colorFlags);
uint32_t color32ToRGB(uint32_t color);
lv_color_t makeLvColor(uint32_t colorFlags);
constexpr uint32_t RGB888_FLAG = 0x1000000;
enum COLOR_EDITOR_FMT {
RGB565 = 0,
RGB888
};
#define RGB32(r, g, b) \
(uint32_t)((((r) & 0xFF) << 16) + (((g) & 0xFF) << 8) + ((b) & 0xFF))
#define GET_RED32(color) (((color) & 0xFF0000) >> 16)
#define GET_GREEN32(color) (((color) & 0x00FF00) >> 8)
#define GET_BLUE32(color) ((color) & 0x0000FF)
@@ -18,6 +18,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "color_editor.h"
#include "button.h"
@@ -162,7 +163,7 @@ class ColorBar : public FormField
p2.x = area->x2 - 1;
}
auto c = bar->getRGB(bar->screenToValue(i));
line_dsc.color = lv_color_make(GET_RED(c), GET_GREEN(c), GET_BLUE(c));
line_dsc.color = lv_color_make(GET_RED32(c), GET_GREEN32(c), GET_BLUE32(c));
lv_draw_line(dsc->draw_ctx, &line_dsc, &p1, &p2);
}
@@ -289,42 +290,42 @@ class HSVColorType : public BarColorType
public:
HSVColorType(Window* parent, uint32_t color) : BarColorType(parent)
{
auto rgb = COLOR_VAL(colorToRGB(color));
auto rgb = color32ToRGB(color);
auto r = GET_RED(rgb), g = GET_GREEN(rgb), b = GET_BLUE(rgb);
auto r = GET_RED32(rgb), g = GET_GREEN32(rgb), b = GET_BLUE32(rgb);
float values[MAX_BARS];
RGBtoHSV(r, g, b, values[0], values[1], values[2]);
values[1] *= MAX_SATURATION; // convert the proper base
values[2] *= MAX_BRIGHTNESS;
for (auto i = 0; i < MAX_BARS; i++) {
bars[i]->maxValue = i == 0 ? MAX_HUE : MAX_BRIGHTNESS;
bars[i]->maxValue = (i == 0) ? MAX_HUE : (i == 1) ? MAX_SATURATION : MAX_BRIGHTNESS;
bars[i]->invert = i != 0;
bars[i]->value = values[i];
}
// hue
bars[0]->getRGB = [=](int pos) {
auto rgb = HSVtoRGB(pos, bars[1]->value, bars[2]->value);
auto rgb = HSVtoRGB32(pos, bars[1]->value, bars[2]->value);
return rgb;
};
// saturation
bars[1]->getRGB = [=](int pos) {
auto rgb = HSVtoRGB(bars[0]->value, pos, bars[2]->value);
auto rgb = HSVtoRGB32(bars[0]->value, pos, bars[2]->value);
return rgb;
};
// brightness
bars[2]->getRGB = [=](int pos) {
auto rgb = HSVtoRGB(bars[0]->value, bars[1]->value, pos);
auto rgb = HSVtoRGB32(bars[0]->value, bars[1]->value, pos);
return rgb;
};
}
uint32_t getRGB() override
{
return COLOR2FLAGS(HSVtoRGB(bars[0]->value, bars[1]->value, bars[2]->value)) | RGB_FLAG;
return HSVtoRGB32(bars[0]->value, bars[1]->value, bars[2]->value) | RGB888_FLAG;
}
protected:
@@ -337,9 +338,9 @@ class RGBColorType : public BarColorType
public:
RGBColorType(Window* parent, uint32_t color) : BarColorType(parent)
{
auto rgb = COLOR_VAL(colorToRGB(color));
auto rgb = color32ToRGB(color);
auto r = GET_RED(rgb), g = GET_GREEN(rgb), b = GET_BLUE(rgb);
auto r = GET_RED32(rgb), g = GET_GREEN32(rgb), b = GET_BLUE32(rgb);
float values[MAX_BARS];
values[0] = r;
values[1] = g;
@@ -351,14 +352,14 @@ class RGBColorType : public BarColorType
bars[i]->invert = true;
}
bars[0]->getRGB = [=](int pos) { return RGB(pos, 0, 0); };
bars[1]->getRGB = [=](int pos) { return RGB(0, pos, 0); };
bars[2]->getRGB = [=](int pos) { return RGB(0, 0, pos); };
bars[0]->getRGB = [=](int pos) { return RGB32(pos, 0, 0); };
bars[1]->getRGB = [=](int pos) { return RGB32(0, pos, 0); };
bars[2]->getRGB = [=](int pos) { return RGB32(0, 0, pos); };
}
uint32_t getRGB() override
{
return RGB2FLAGS(bars[0]->value, bars[1]->value, bars[2]->value);
return RGB32(bars[0]->value, bars[1]->value, bars[2]->value) | RGB888_FLAG;
}
protected:
@@ -396,7 +397,7 @@ class ThemeColorType : public ColorType
auto btn = new TextButton(parent, rect_t{}, " ");
etx_bg_color(btn->getLvObj(), (LcdColorIndex)color);
btn->setPressHandler([=]() {
m_color = COLOR2FLAGS(color);
m_color = color;
lv_event_send(parent->getParent()->getParent()->getLvObj(),
LV_EVENT_VALUE_CHANGED, nullptr);
return 0;
@@ -421,14 +422,31 @@ class ThemeColorType : public ColorType
////// ColorEditor Base class
/////////////////////////////////////////////////////////////////////////
ColorEditor::ColorEditor(Window* parent, const rect_t& rect, uint32_t color,
std::function<void(uint32_t rgb)> setValue) :
Window(parent, rect), _setValue(std::move(setValue)), _color(color)
std::function<void(uint32_t rgb)> setValue,
std::function<void(uint32_t rgb)> preview,
COLOR_EDITOR_FMT fmt) :
Window(parent, rect), _setValue(std::move(setValue)), _preview(std::move(preview)),
format(fmt)
{
_colorType = new HSVColorType(this, color);
if (format == RGB565) {
if (color & RGB_FLAG) {
color = COLOR_VAL(color);
auto r = GET_RED(color);
auto g = GET_GREEN(color);
auto b = GET_BLUE(color);
color = RGB32(r, g, b) | RGB888_FLAG;
} else {
color = COLOR_VAL(color);
}
}
_color = color;
_colorType = new HSVColorType(this, _color);
_colorType->setText();
lv_obj_add_event_cb(lvobj, ColorEditor::value_changed, LV_EVENT_VALUE_CHANGED,
nullptr);
if (_preview) _preview(_color);
}
void ColorEditor::setColorEditorType(COLOR_EDITOR_TYPE colorType)
@@ -439,10 +457,10 @@ void ColorEditor::setColorEditorType(COLOR_EDITOR_TYPE colorType)
}
if (colorType == RGB_COLOR_EDITOR) {
_colorType = new RGBColorType(this, _color);
setRGB();
setText();
} else if (colorType == HSV_COLOR_EDITOR) {
_colorType = new HSVColorType(this, _color);
setHSV();
setText();
} else {
_colorType = new ThemeColorType(this, _color);
setText();
@@ -454,7 +472,20 @@ void ColorEditor::setColorEditorType(COLOR_EDITOR_TYPE colorType)
void ColorEditor::setText()
{
_colorType->setText();
if (_setValue != nullptr) _setValue(_color);
if (_setValue != nullptr) {
uint32_t c = _color;
if (format == RGB565) {
if (c & RGB888_FLAG) {
auto r = GET_RED32(c);
auto g = GET_GREEN32(c);
auto b = GET_BLUE32(c);
c = RGB2FLAGS(r, g, b);
} else {
c = COLOR2FLAGS(c);
}
}
_setValue(c);
}
}
void ColorEditor::setRGB()
@@ -462,12 +493,7 @@ void ColorEditor::setRGB()
_color = _colorType->getRGB();
// update bars & labels
setText();
}
void ColorEditor::setHSV()
{
// update bars & labels
setText();
if (_preview) _preview(_color);
}
void ColorEditor::value_changed(lv_event_t* e)
@@ -37,7 +37,9 @@ class ColorEditor : public Window
{
public:
ColorEditor(Window* parent, const rect_t& rect, uint32_t color,
std::function<void(uint32_t rgb)> setValue = nullptr);
std::function<void(uint32_t rgb)> setValue = nullptr,
std::function<void(uint32_t rgb)> preview = nullptr,
COLOR_EDITOR_FMT fmt = RGB565);
#if defined(DEBUG_WINDOWS)
std::string getName() const override { return "ColorEditor"; }
@@ -57,10 +59,11 @@ class ColorEditor : public Window
protected:
ColorType* _colorType = nullptr;
std::function<void(uint32_t)> _setValue;
std::function<void(uint32_t)> _preview;
uint32_t _color;
COLOR_EDITOR_FMT format;
void setText();
void setHSV();
void setRGB();
static void value_changed(lv_event_t* e);
};
@@ -21,7 +21,6 @@
#include "color_picker.h"
#include "color_editor.h"
#include "color_list.h"
#include "etx_lv_theme.h"
@@ -44,14 +43,23 @@ class ColorEditorPopup : public BaseDialog
ColorSwatch* colorPad = nullptr;
StaticText* hexStr = nullptr;
uint32_t m_color;
uint32_t origColor;
std::function<void(uint32_t)> setValue;
COLOR_EDITOR_FMT format;
void updateColor(uint32_t c)
{
m_color = c;
auto rgb = COLOR_VAL(colorToRGB(m_color));
uint8_t r, g, b;
uint8_t r = GET_RED(rgb), g = GET_GREEN(rgb), b = GET_BLUE(rgb);
if (format == RGB565) {
auto rgb = COLOR_VAL(colorToRGB(m_color));
r = GET_RED(rgb); g = GET_GREEN(rgb); b = GET_BLUE(rgb);
} else {
auto rgb = color32ToRGB(m_color);
r = GET_RED32(rgb); g = GET_GREEN32(rgb); b = GET_BLUE32(rgb);
}
colorPad->setColor(r, g, b);
@@ -60,18 +68,27 @@ class ColorEditorPopup : public BaseDialog
hexStr->setText(s);
}
void onCancel() override
{
if (setValue) setValue(origColor);
this->deleteLater();
}
public:
ColorEditorPopup(uint32_t color,
std::function<void(uint32_t)> _setValue) :
std::function<void(uint32_t)> _setValue,
std::function<void(uint32_t)> _preview,
COLOR_EDITOR_FMT fmt) :
BaseDialog(STR_COLOR_PICKER, false, COLOR_EDIT_WIDTH,
LV_SIZE_CONTENT)
LV_SIZE_CONTENT),
origColor(color), setValue(std::move(_setValue)), format(fmt)
{
FlexGridLayout grid(col_dsc, row_dsc);
auto line = form->newLine(grid);
rect_t r{0, 0, CE_SZ, CE_SZ};
auto cedit =
new ColorEditor(line, r, color, [=](uint32_t c) { updateColor(c); });
new ColorEditor(line, r, color, [=](uint32_t c) { updateColor(c); }, _preview, format);
lv_obj_set_style_grid_cell_x_align(cedit->getLvObj(), LV_GRID_ALIGN_CENTER,
0);
@@ -138,12 +155,12 @@ class ColorEditorPopup : public BaseDialog
lv_obj_set_flex_grow(hbox->getLvObj(), 1);
new TextButton(hbox, rect_t{0, 0, BTN_W, 0}, STR_CANCEL, [=]() -> int8_t {
this->deleteLater();
onCancel();
return 0;
});
new TextButton(hbox, rect_t{0, 0, BTN_W, 0}, STR_SAVE, [=]() -> int8_t {
if (_setValue) _setValue(m_color);
if (setValue) setValue(m_color);
this->deleteLater();
return 0;
});
@@ -161,16 +178,18 @@ class ColorEditorPopup : public BaseDialog
ColorPicker::ColorPicker(Window* parent, const rect_t& rect,
std::function<uint32_t()> getValue,
std::function<void(uint32_t)> setValue) :
Button(parent, {rect.x, rect.y, ColorEditorPopup::COLOR_PAD_WIDTH, ColorEditorPopup::COLOR_PAD_HEIGHT}),
setValue(std::move(setValue))
std::function<void(uint32_t)> setValue,
std::function<void(uint32_t)> preview,
COLOR_EDITOR_FMT fmt) :
Button(parent, {rect.x, rect.y, rect.w == 0 ? ColorEditorPopup::COLOR_PAD_WIDTH : rect.w, ColorEditorPopup::COLOR_PAD_HEIGHT}),
setValue(std::move(setValue)), preview(std::move(preview)), format(fmt)
{
updateColor(getValue());
}
void ColorPicker::onClicked()
{
new ColorEditorPopup(getColor(), [=](uint32_t c) { setColor(c); });
new ColorEditorPopup(getColor(), [=](uint32_t c) { setColor(c); }, preview, format);
}
void ColorPicker::setColor(uint32_t c)
@@ -183,8 +202,16 @@ void ColorPicker::updateColor(uint32_t c)
{
color = c;
auto rgb = COLOR_VAL(colorToRGB(color));
auto lvcolor =
lv_color_make(GET_RED(rgb), GET_GREEN(rgb), GET_BLUE(rgb));
uint8_t r, g, b;
if (format == RGB565) {
auto rgb = COLOR_VAL(colorToRGB(color));
r = GET_RED(rgb); g = GET_GREEN(rgb); b = GET_BLUE(rgb);
} else {
auto rgb = color32ToRGB(color);
r = GET_RED32(rgb); g = GET_GREEN32(rgb); b = GET_BLUE32(rgb);
}
auto lvcolor = lv_color_make(r, g, b);
lv_obj_set_style_bg_color(lvobj, lvcolor, LV_PART_MAIN);
}
@@ -22,18 +22,23 @@
#pragma once
#include "button.h"
#include "color_editor.h"
class ColorPicker : public Button
{
uint32_t color;
std::function<void(uint32_t)> setValue;
std::function<void(uint32_t)> preview;
COLOR_EDITOR_FMT format;
void updateColor(uint32_t c);
public:
ColorPicker(Window* parent, const rect_t& rect,
std::function<uint32_t()> getValue,
std::function<void(uint32_t)> setValue = nullptr);
std::function<void(uint32_t)> setValue = nullptr,
std::function<void(uint32_t)> preview = nullptr,
COLOR_EDITOR_FMT fmt = RGB565);
void setColor(uint32_t c);
uint32_t getColor() const { return color; }
+4 -1
View File
@@ -56,7 +56,10 @@ class NumberArea : public FormField
#if defined(DEBUG_WINDOWS)
std::string getName() const override
{
return "NumberArea(" + std::to_string(getValue()) + ")";
if(numEdit)
return "NumberArea(" + numEdit->getName() + ")";
else
return "NumberArea(unknown)";
}
#endif
+1 -1
View File
@@ -30,7 +30,7 @@ class TextEdit : public TextButton
std::function<void(void)> updateHandler = nullptr);
#if defined(DEBUG_WINDOWS)
std::string getName() const override { return "TextEdit \"" + text + "\""; }
std::string getName() const override { return std::string("TextEdit \"") + text + "\""; }
#endif
void preview(bool edited, char* text, uint8_t length);
+6 -3
View File
@@ -24,6 +24,7 @@
/* clang-format off */
#include <stdint.h>
#include "definitions.h"
/*====================
COLOR SETTINGS
@@ -185,8 +186,10 @@
#if LV_USE_GPU_STM32_DMA2D
/*Must be defined to include path of CMSIS header of target processor
e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
#ifdef STM32H7
#if defined(STM32H7)
#define LV_GPU_DMA2D_CMSIS_INCLUDE "stm32h7xx.h"
#elif defined(STM32H7RS)
#define LV_GPU_DMA2D_CMSIS_INCLUDE "stm32h7rsxx.h"
#else
#define LV_GPU_DMA2D_CMSIS_INCLUDE "stm32f4xx.h"
#endif
@@ -353,10 +356,10 @@
#define LV_ATTRIBUTE_LARGE_RAM_ARRAY
/*Place performance critical functions into a faster memory (e.g RAM)*/
#define LV_ATTRIBUTE_FAST_MEM
#define LV_ATTRIBUTE_FAST_MEM __IRAM
/*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/
#define LV_ATTRIBUTE_DMA
#define LV_ATTRIBUTE_DMA __DMA
/*Export integer constant to binding. This macro is used with constants in the form of LV_<CONST> that
*should also appear on LVGL binding API such as Micropython.*/
@@ -28,20 +28,21 @@
#include "switches.h"
#include "color_picker.h"
#if defined(FUNCTION_SWITCHES_RGB_LEDS)
static constexpr coord_t LH = 72;
#else
static constexpr coord_t LH = 36;
#endif
#define SET_DIRTY() storageDirty(EE_MODEL)
static const lv_coord_t line_col_dsc1[] = {LV_GRID_CONTENT,
LV_GRID_TEMPLATE_LAST};
#if defined(FUNCTION_SWITCHES_RGB_LEDS)
static const lv_coord_t line_col_dsc2[] = {
LV_GRID_FR(13), LV_GRID_FR(11), LV_GRID_FR(11),
LV_GRID_FR(12), LV_GRID_FR(10), LV_GRID_FR(7), LV_GRID_FR(7),
LV_GRID_TEMPLATE_LAST};
#else
static const lv_coord_t line_col_dsc2[] = {
LV_GRID_FR(10), LV_GRID_FR(10), LV_GRID_FR(10),
LV_GRID_FR(12), LV_GRID_FR(8), LV_GRID_TEMPLATE_LAST};
#endif
static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT,
LV_GRID_TEMPLATE_LAST};
@@ -124,60 +125,110 @@ class FunctionSwitch : public Window
});
#if defined(FUNCTION_SWITCHES_RGB_LEDS)
new StaticText(this, {8 , 6 + 36, SW_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, STR_FS_OFF_COLOR, COLOR_THEME_PRIMARY1);
offValue = g_model.functionSwitchLedOFFColor[switchIndex];
onValue = g_model.functionSwitchLedONColor[switchIndex];
auto offcolor = new ColorPicker(
this, rect_t{},
offColor = new ColorPicker(
this, {C1_X, 0, C1_W, 0},
[=]() -> int { // getValue
return g_model.functionSwitchLedOFFColor[switchIndex];
return g_model.functionSwitchLedOFFColor[switchIndex].getColor();
},
[=](int newValue) { // setValue
g_model.functionSwitchLedOFFColor[switchIndex] =
(uint32_t)newValue;
TRACE("Color: %x", g_model.functionSwitchLedOFFColor[switchIndex]);
g_model.functionSwitchLedOFFColor[switchIndex] = offValue;
g_model.functionSwitchLedONColor[switchIndex] = onValue;
// Convert color index to RGB
newValue = color32ToRGB(newValue);
g_model.functionSwitchLedOFFColor[switchIndex].setColor(newValue);
offValue = g_model.functionSwitchLedOFFColor[switchIndex];
SET_DIRTY();
});
offcolor->setPos(NM_X, 36);
},
[=](int newValue) { previewColor(newValue); }, RGB888);
new StaticText(this, {TP_X, 6 + 36, SW_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, STR_FS_ON_COLOR, COLOR_THEME_PRIMARY1);
auto oncolor = new ColorPicker(
this, rect_t{},
onColor = new ColorPicker(
this, {C2_X, 0, C2_W, 0},
[=]() -> int { // getValue
return g_model.functionSwitchLedONColor[switchIndex];
return g_model.functionSwitchLedONColor[switchIndex].getColor();
},
[=](int newValue) { // setValue
g_model.functionSwitchLedONColor[switchIndex] =
(uint32_t)newValue;
g_model.functionSwitchLedOFFColor[switchIndex] = offValue;
g_model.functionSwitchLedONColor[switchIndex] = onValue;
// Convert color index to RGB
newValue = color32ToRGB(newValue);
g_model.functionSwitchLedONColor[switchIndex].setColor(newValue);
onValue = g_model.functionSwitchLedONColor[switchIndex];
SET_DIRTY();
});
oncolor->setPos(GR_X, 36);
},
[=](int newValue) { previewColor(newValue); }, RGB888);
#endif //FUNCTION_SWITCHES_RGB_LEDS
setState();
}
static constexpr coord_t SW_W = (LCD_W - 4 * 2 - 2 * 4) / 5;
static constexpr coord_t NM_X = SW_W + 2;
#if defined(FUNCTION_SWITCHES_RGB_LEDS)
static constexpr coord_t SW_X = PAD_SMALL;
static constexpr coord_t SW_W = 70;
static constexpr coord_t NM_X = SW_X + SW_W;
static constexpr coord_t NM_W = 60;
static constexpr coord_t TP_X = NM_X + NM_W + PAD_SMALL;
static constexpr coord_t TP_W = 78;
static constexpr coord_t GR_X = TP_X + TP_W + PAD_SMALL;
static constexpr coord_t GR_W = 84;
static constexpr coord_t ST_X = GR_X + GR_W + PAD_SMALL;
static constexpr coord_t ST_W = 60;
static constexpr coord_t C1_X = ST_X + ST_W + PAD_SMALL;
static constexpr coord_t C1_W = 40;
static constexpr coord_t C2_X = C1_X + C1_W + PAD_SMALL;
static constexpr coord_t C2_W = 40;
#else
static constexpr coord_t SW_W = (LCD_W - PAD_SMALL * 2 - PAD_TINY_GAP * 4) / 5;
static constexpr coord_t NM_X = SW_W + PAD_TINY_GAP;
static constexpr coord_t NM_W = 80;
static constexpr coord_t TP_X = NM_X + SW_W + 2;
static constexpr coord_t TP_X = NM_X + SW_W + PAD_TINY_GAP;
static constexpr coord_t TP_W = 86;
static constexpr coord_t GR_X = TP_X + SW_W + 2;
static constexpr coord_t GR_X = TP_X + SW_W + PAD_TINY_GAP;
static constexpr coord_t GR_W = 94;
static constexpr coord_t ST_X = GR_X + SW_W + 20;
static constexpr coord_t ST_W = 70;
#endif
protected:
uint8_t switchIndex;
Choice* typeChoice = nullptr;
Choice* groupChoice = nullptr;
Choice* startChoice = nullptr;
#if defined(FUNCTION_SWITCHES_RGB_LEDS)
ColorPicker* offColor = nullptr;
ColorPicker* onColor = nullptr;
RGBLedColor offValue;
RGBLedColor onValue;
#endif
int lastType = -1;
#if defined(FUNCTION_SWITCHES_RGB_LEDS)
void previewColor(int newValue)
{
// Convert color index to RGB
newValue = color32ToRGB(newValue);
if (getFSLogicalState(switchIndex)) {
g_model.functionSwitchLedONColor[switchIndex].setColor(newValue);
} else {
g_model.functionSwitchLedOFFColor[switchIndex].setColor(newValue);
}
}
#endif
void setState()
{
startChoice->show(FSWITCH_CONFIG(switchIndex) == SWITCH_2POS && FSWITCH_GROUP(switchIndex) == 0);
groupChoice->show(FSWITCH_CONFIG(switchIndex) != SWITCH_NONE);
#if defined(FUNCTION_SWITCHES_RGB_LEDS)
offColor->show(FSWITCH_CONFIG(switchIndex) != SWITCH_NONE);
onColor->show(FSWITCH_CONFIG(switchIndex) != SWITCH_NONE);
#endif
}
void checkEvents() override
@@ -276,6 +327,10 @@ ModelFunctionSwitches::ModelFunctionSwitches() : Page(ICON_MODEL_SETUP)
new StaticText(line, rect_t{}, STR_GROUP, COLOR_THEME_PRIMARY1_INDEX, FONT(XS));
startupHeader = new StaticText(line, rect_t{}, STR_SWITCH_STARTUP,
COLOR_THEME_PRIMARY1_INDEX, FONT(XS));
#if defined(FUNCTION_SWITCHES_RGB_LEDS)
new StaticText(line, rect_t{}, STR_OFF, COLOR_THEME_PRIMARY1_INDEX, FONT(XS));
new StaticText(line, rect_t{}, STR_ON_ONE_SWITCHES[0], COLOR_THEME_PRIMARY1_INDEX, FONT(XS));
#endif
for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i += 1) {
new FunctionSwitch(body, i);
@@ -603,6 +603,7 @@ class ModuleSubTypeChoice : public Choice
g_model.moduleData[moduleIdx].subType = newValue;
SET_DIRTY();
} else {
#if defined(MULTIMODULE)
g_model.moduleData[moduleIdx].multi.rfProtocol = newValue;
g_model.moduleData[moduleIdx].subType = 0;
resetMultiProtocolsOptions(moduleIdx);
@@ -614,6 +615,7 @@ class ModuleSubTypeChoice : public Choice
while (!status.isValid() && (RTOS_GET_MS() - startUpdate < 250))
;
SET_DIRTY();
#endif
}
if (moduleWindow)
@@ -88,4 +88,4 @@ RadioCustSwitchesDiagsPage::RadioCustSwitchesDiagsPage() :
buildBody(body);
}
#endif
#endif
@@ -26,6 +26,7 @@
#include "io/frsky_firmware_update.h"
#include "io/multi_firmware_update.h"
#include "io/bootloader_flash.h"
#include "io/uf2_flash.h"
#include "standalone_lua.h"
#include "sdcard.h"
#include "view_text.h"
@@ -354,6 +355,7 @@ void RadioSdManagerPage::fileAction(const char* path, const char* name,
menu->addLine(STR_FLASH_EXTERNAL_ELRS, [=]() {
MultiFirmwareUpdate(fullpath, EXTERNAL_MODULE, MULTI_TYPE_ELRS);
});
#endif
} else if (!strcasecmp(BITMAPS_PATH, path) &&
isExtensionMatching(ext, BITMAPS_EXT) &&
strlen(name) <= LEN_BITMAP_NAME) {
@@ -382,10 +384,18 @@ void RadioSdManagerPage::fileAction(const char* path, const char* name,
});
}
if (!strcasecmp(ext, FIRMWARE_EXT)) {
#if defined(FIRMWARE_FORMAT_UF2)
if (isUF2FirmwareFile(fullpath)) {
menu->addLine(STR_FLASH_BOOTLOADER,
[=]() { FirmwareUpdate(fullpath); });
}
#else
if (isBootloader(fullpath)) {
menu->addLine(STR_FLASH_BOOTLOADER,
[=]() { BootloaderUpdate(fullpath); });
}
#endif
#if defined(HARDWARE_INTERNAL_MODULE) || defined(HARDWARE_EXTERNAL_MODULE)
} else if (!strcasecmp(ext, SPORT_FIRMWARE_EXT)) {
auto mod_desc = modulePortGetModuleDescription(SPORT_MODULE);
@@ -535,6 +545,15 @@ void RadioSdManagerPage::fileAction(const char* path, const char* name,
});
}
#if defined(FIRMWARE_FORMAT_UF2)
void RadioSdManagerPage::FirmwareUpdate(const char* fn)
{
UF2FirmwareUpdate firmwareUpdate;
auto dialog =
new FlashDialog<UF2FirmwareUpdate>(firmwareUpdate);
dialog->flash(fn);
}
#else
void RadioSdManagerPage::BootloaderUpdate(const char* fn)
{
BootloaderFirmwareUpdate bootloaderFirmwareUpdate;
@@ -542,6 +561,7 @@ void RadioSdManagerPage::BootloaderUpdate(const char* fn)
new FlashDialog<BootloaderFirmwareUpdate>(bootloaderFirmwareUpdate);
dialog->flash(fn);
}
#endif
#if defined(BLUETOOTH)
void RadioSdManagerPage::BluetoothFirmwareUpdate(const char* fn)
@@ -551,6 +571,7 @@ void RadioSdManagerPage::BluetoothFirmwareUpdate(const char* fn)
}
#endif
#if defined(HARDWARE_INTERNAL_MODULE) || defined(HARDWARE_EXTERNAL_MODULE)
void RadioSdManagerPage::FrSkyFirmwareUpdate(const char* fn,
ModuleIndex module)
{
@@ -569,3 +590,4 @@ void RadioSdManagerPage::MultiFirmwareUpdate(const char* fn,
new FlashDialog<MultiDeviceFirmwareUpdate>(deviceFirmwareUpdate);
dialog->flash(fn);
}
#endif
@@ -48,14 +48,20 @@ class RadioSdManagerPage : public PageTab
void fileAction(const char* path, const char* name, const char* fullpath);
void dirAction(const char* path, const char* name, const char* fullpath);
#if defined(FIRMWARE_FORMAT_UF2)
void FirmwareUpdate(const char* fn);
#else
void BootloaderUpdate(const char* fn);
#endif
#if defined(BLUETOOTH)
void BluetoothFirmwareUpdate(const char* fn);
#endif
#if defined(HARDWARE_INTERNAL_MODULE) || defined(HARDWARE_EXTERNAL_MODULE)
void FrSkyFirmwareUpdate(const char* fn, ModuleIndex module);
void MultiFirmwareUpdate(const char* fn, ModuleIndex module,
MultiModuleType type);
#endif
void checkEvents() override;
};
+9
View File
@@ -30,16 +30,25 @@ set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
${CMAKE_CURRENT_SOURCE_DIR}/hal/key_driver.cpp
)
if(FUNCTION_SWITCHES_WITH_RGB)
set(SRC ${SRC}
hal/rgbleds.cpp
)
endif()
if (NOT NATIVE_BUILD)
set(SRC ${SRC}
hal/storage.cpp
hal/fatfs_diskio.cpp
hal/flash_driver.cpp
${FATFS_DIR}/ff.c
${FATFS_DIR}/ffunicode.c
)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
${CMAKE_CURRENT_SOURCE_DIR}/hal/storage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/hal/fatfs_diskio.cpp
${CMAKE_CURRENT_SOURCE_DIR}/hal/flash_driver.cpp
${CMAKE_CURRENT_SOURCE_DIR}/${FATFS_DIR}/ff.c
${CMAKE_CURRENT_SOURCE_DIR}/${FATFS_DIR}/ffunicode.c
)
+6
View File
@@ -41,6 +41,12 @@ void abnormalRebootDisableDetection();
// (see AbnormalRebootCause)
uint32_t abnormalRebootGetCause();
// Retrieve last reboot command
uint32_t abnormalRebootGetCmd();
// Reset reboot command
void abnormalRebootResetCmd();
#define UNEXPECTED_SHUTDOWN() \
(abnormalRebootGetCause() == ARC_Watchdog)
+1 -1
View File
@@ -27,7 +27,7 @@
const etx_hal_adc_driver_t* _hal_adc_driver = nullptr;
const etx_hal_adc_inputs_t* _hal_adc_inputs = nullptr;
static uint16_t adcValues[MAX_ANALOG_INPUTS] __DMA;
static uint16_t adcValues[MAX_ANALOG_INPUTS] __DMA_NO_CACHE;
#if defined(CSD203_SENSOR)
extern uint16_t getCSD203BatteryVoltage(void);
+48
View File
@@ -0,0 +1,48 @@
#include "hal/flash_driver.h"
typedef struct {
const etx_flash_driver_t* drv;
uint32_t start_addr;
uint32_t end_addr;
} flash_media_t;
static flash_media_t _flash_media[2] = {{nullptr, 0, 0}};
void flashRegisterDriver(uint32_t start_addr, uint32_t length,
const etx_flash_driver_t* drv)
{
for (int i = 0; i < 2; i++) {
flash_media_t& fm = _flash_media[i];
if (fm.drv) continue;
fm = {
.drv = drv,
.start_addr = start_addr,
.end_addr = start_addr + length - 1,
};
return;
}
}
const etx_flash_driver_t* flashFindDriver(uint32_t addr)
{
for (int i = 0; i < 2; i++) {
const flash_media_t& fm = _flash_media[i];
if (!fm.drv) continue;
if (fm.start_addr <= addr && fm.end_addr >= addr)
return fm.drv;
}
return nullptr;
}
uint32_t flashGetSize(uint32_t addr)
{
for (int i = 0; i < 2; i++) {
const flash_media_t& fm = _flash_media[i];
if (!fm.drv) continue;
if (fm.start_addr <= addr && fm.end_addr >= addr)
return fm.end_addr - fm.start_addr + 1;
}
return 0;
}
+40
View File
@@ -0,0 +1,40 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <stdint.h>
typedef struct {
uint32_t (*get_size_kb)();
uint32_t (*get_sector)(uint32_t address);
uint32_t (*get_sector_size)(uint32_t sector);
int (*erase_sector)(uint32_t address);
int (*program)(uint32_t address, void* data, uint32_t len);
int (*read)(uint32_t address, void* data, uint32_t len);
} etx_flash_driver_t;
void flashRegisterDriver(uint32_t start_addr, uint32_t length,
const etx_flash_driver_t* drv);
const etx_flash_driver_t* flashFindDriver(uint32_t addr);
uint32_t flashGetSize(uint32_t addr);
+1 -2
View File
@@ -1,5 +1,4 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
@@ -49,4 +48,4 @@ void setFSLedON(uint8_t index) {
bool getFSLedState(uint8_t index) {
return fsLedState(index);
}
#endif
#endif
+1 -2
View File
@@ -1,5 +1,4 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
@@ -30,4 +29,4 @@ constexpr uint32_t colorTabl2[] = {0x000000, 0xF8F8F8, 0xF80000, 0x00F800, 0xF8F
void setFSLedOFF(uint8_t index);
void setFSLedON(uint8_t index);
bool getFSLedState(uint8_t index);
bool getFSLedState(uint8_t index);
+3 -3
View File
@@ -31,10 +31,10 @@
// Board API
void boardInitSwitches();
SwitchHwPos boardSwitchGetPosition(uint8_t cat, uint8_t idx);
SwitchHwPos boardSwitchGetPosition(SwitchCategory cat, uint8_t idx);
const char* boardSwitchGetName(uint8_t cat, uint8_t idx);
SwitchHwType boardSwitchGetType(uint8_t cat, uint8_t idx);
const char* boardSwitchGetName(SwitchCategory cat, uint8_t idx);
SwitchHwType boardSwitchGetType(SwitchCategory cat, uint8_t idx);
uint8_t boardGetMaxSwitches();
uint8_t boardGetMaxFctSwitches();
+8 -3
View File
@@ -33,10 +33,11 @@ enum usbMode {
USB_JOYSTICK_MODE,
USB_MASS_STORAGE_MODE,
USB_SERIAL_MODE,
USB_DFU_MODE,
#if defined(USB_SERIAL)
USB_MAX_MODE=USB_SERIAL_MODE
USB_MAX_MODE=USB_SERIAL_MODE,
#else
USB_MAX_MODE=USB_MASS_STORAGE_MODE
USB_MAX_MODE=USB_MASS_STORAGE_MODE,
#endif
};
@@ -53,11 +54,15 @@ bool usbStarted();
EXTERN_C(int getSelectedUsbMode());
void setSelectedUsbMode(int mode);
// USB CDC
uint32_t usbSerialFreeSpace();
extern const etx_serial_port_t UsbSerialPort;
// USB HID
#if defined(USBJ_EX)
void usbJoystickRestart();
#endif
void usbJoystickUpdate();
extern const etx_serial_port_t UsbSerialPort;
// USB DFU
int usbRegisterDFUMedia(const void* dfu_media);
+5 -13
View File
@@ -34,6 +34,10 @@
#include "lib_file.h"
#endif
#ifndef BOOTLOADER_ADDRESS
#define BOOTLOADER_ADDRESS FIRMWARE_ADDRESS
#endif
bool isBootloader(const char * filename)
{
FIL file;
@@ -66,12 +70,6 @@ void BootloaderFirmwareUpdate::flashFirmware(const char * filename, ProgressHand
f_open(&file, filename, FA_READ);
static uint8_t unlocked = 0;
if (!unlocked) {
unlocked = 1;
unlockFlash();
}
UINT flash_size = file.obj.objsize;
if (flash_size > BOOTLOADER_SIZE) {
flash_size = BOOTLOADER_SIZE;
@@ -97,7 +95,7 @@ void BootloaderFirmwareUpdate::flashFirmware(const char * filename, ProgressHand
}
for (UINT j = 0; j < count; j += FLASH_PAGESIZE) {
WDG_ENABLE(3000);
flashWrite(CONVERT_UINT_PTR(FIRMWARE_ADDRESS + i + j), CONVERT_UINT_PTR(buffer + j));
flashWrite(CONVERT_UINT_PTR(BOOTLOADER_ADDRESS + i + j), CONVERT_UINT_PTR(buffer + j));
WDG_ENABLE(WDG_DURATION);
}
progressHandler("Bootloader", STR_WRITING, i, flash_size);
@@ -117,12 +115,6 @@ void BootloaderFirmwareUpdate::flashFirmware(const char * filename, ProgressHand
watchdogSuspend(0);
WDG_RESET();
if (unlocked) {
lockFlash();
unlocked = 0;
}
f_close(&file);
pulsesStart();
}
+211
View File
@@ -0,0 +1,211 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "uf2.h"
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include "board.h"
#include "fw_version.h"
#include "thirdparty/FatFs/ff.h"
#include "thirdparty/uf2/uf2.h"
#define UF2_BLOCK_SIZE 512
bool isUF2Block(const void* block, uint32_t len)
{
const UF2_Block* uf2 = (UF2_Block*)block;
return len >= UF2_BLOCK_SIZE
&& uf2->magicStart0 == UF2_MAGIC_START0
&& uf2->magicStart1 == UF2_MAGIC_START1
&& uf2->magicEnd == UF2_MAGIC_END;
}
static size_t getUF2Extension(const UF2_Block* block, uint32_t extension,
const char** data)
{
if ((block->flags & UF2_FLAG_EXTENSION_TAGS) == 0) return 0;
uint32_t* ptr = (uint32_t*)(block->data + block->payloadSize);
if (*ptr == 0) return 0;
while ((size_t)((uint8_t*)ptr - (uint8_t*)block) < sizeof(UF2_Block)) {
uint32_t tag = ((*ptr) & 0xFFFFFF00) >> 8;
uint32_t len = (*ptr) & 0x000000FF;
if (*ptr == 0) break;
if (tag != extension) {
ptr += (len + 3) / 4;
continue;
}
*data = (char*)++ptr;
return len > 4 ? len - 4 : 0;
}
return 0;
}
bool extractUF2FirmwareVersion(const void* block, VersionTag* tag)
{
memset(tag, 0, sizeof(VersionTag));
const char* extension;
size_t len = getUF2Extension((UF2_Block*)block, UF2_DEVICE_TAG, &extension);
if (len == 0) return false;
memcpy(tag->flavour, extension, std::min(len, sizeof(tag->flavour) - 1));
len = getUF2Extension((UF2_Block*)block, UF2_VERSION_TAG, &extension);
if (len == 0) return false;
memcpy(tag->full_version, extension, std::min(len, sizeof(tag->full_version) - 1));
tag->fork = tag->full_version;
tag->full_version[sizeof("edgetx") - 1] = '\0';
tag->version = tag->fork + sizeof("edgetx");
return true;
}
bool isUF2FirmwareImage(const void* buffer, uint32_t length)
{
const uint8_t* bptr = (const uint8_t*)buffer;
const uint8_t* end_ptr = bptr + length;
while(bptr < end_ptr) {
if (!isUF2Block(bptr, end_ptr - bptr)) return false;
bptr += UF2_BLOCK_SIZE;
}
// check compat: should this really be part of checking
// the file type?
// VersionTag tag;
// if(!extractFirmwareVersion(buffer, &tag))
// return false;
// if(strnlen(tag.flavour, sizeof(tag.flavour)) != strlen(FLAVOUR))
// return false;
// if(strncmp(tag.flavour, FLAVOUR, sizeof(FLAVOUR)) != 0)
// return false;
return true;
}
bool isUF2FirmwareFile(const char * filename)
{
FIL file;
uint8_t buffer[2048];
UINT count;
if(f_open(&file, filename, FA_READ) != FR_OK)
return false;
if (f_read(&file, buffer, sizeof(buffer), &count) != FR_OK || count != sizeof(buffer)) {
f_close(&file);
return false;
}
f_close(&file);
bool ret = isUF2FirmwareImage(buffer, sizeof(buffer));
return ret;
}
static uint8_t* skipUF2Extensions(uint8_t* data) {
uint32_t* ptr = (uint32_t*)data;
while(true) {
uint32_t tag = ((*ptr) & 0xFFFFFF00) >> 8;
uint32_t len = (*ptr) & 0x000000FF;
if (*ptr == 0) break;
if (tag) {
ptr += (len + 3) / 4;
continue;
}
}
return (uint8_t*)ptr;
}
void writeUF2FirmwareVersion(void* block)
{
UF2_Block* uf2 = (UF2_Block*)block;
uint8_t* end_data = skipUF2Extensions(uf2->data + uf2->payloadSize);
const char* version = getFirmwareVersion((const uint8_t*)FIRMWARE_ADDRESS);
if (version) {
uf2->flags |= UF2_FLAG_EXTENSION_TAGS;
size_t version_len = strlen(version);
const char* flavour_start = version + sizeof("edgetx-") - 1;
const char* flavour_end = strchr(flavour_start, '-');
uint32_t ext_tag = UF2_DEVICE_TAG << 8;
if (flavour_end < version + version_len) {
size_t flavour_len = flavour_end - flavour_start;
ext_tag |= (flavour_len + 4) & 0xFF;
memcpy(end_data, &ext_tag, sizeof(ext_tag));
end_data += 4;
memcpy(end_data, flavour_start, flavour_len);
end_data += ((flavour_len) + 3) & (~3);
version_len -= flavour_len + 1;
} else {
flavour_end = nullptr;
}
ext_tag = UF2_VERSION_TAG << 8;
ext_tag |= (version_len + 4) & 0xFF;
memcpy(end_data, &ext_tag, sizeof(ext_tag));
end_data +=4;
if (flavour_end) {
memcpy(end_data, version, sizeof("edgetx-") - 1);
end_data += sizeof("edgetx-") - 1;
version_len -= sizeof("edgetx-") - 1;
memcpy(end_data, flavour_end + 1, version_len);
} else {
memcpy(end_data, version, version_len);
}
}
}
void writeUF2RebootBlock(void* block)
{
extern uint32_t _reboot_cmd;
UF2_Block* uf2 = (UF2_Block*)block;
uf2->targetAddr = (uintptr_t)&_reboot_cmd;
uf2->flags |= UF2_FLAG_EXTENSION_TAGS | UF2_FLAG_NOFLASH;
uf2->payloadSize = 4;
memcpy(uf2->data, "BDFU", 4);
uint8_t* end_data = skipUF2Extensions(uf2->data + uf2->payloadSize);
uint32_t ext_tag = (UF2_REBOOT_TAG << 8) | 8;
memcpy(end_data, &ext_tag, sizeof(ext_tag));
end_data += 4;
uint32_t reboot_addr = BOOTLOADER_ADDRESS;
memcpy(end_data, &reboot_addr, sizeof(reboot_addr));
}
+44
View File
@@ -0,0 +1,44 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include <stdint.h>
#include "boards/FirmwareVersionTag.h"
#define UF2_VERSION_TAG 0x9FC7BC
#define UF2_DEVICE_TAG 0x650D9D
#define UF2_REBOOT_TAG 0xE60835
// ignore family ID if not defined
#if !defined(UF2_FAMILY_ID)
#define UF2_FAMILY_ID 0
#endif
bool isUF2Block(const void* block, uint32_t len);
bool isUF2FirmwareImage(const void* buffer, uint32_t length);
bool isUF2FirmwareFile(const char * filename);
bool extractUF2FirmwareVersion(const void* block, VersionTag* tag);
void writeUF2FirmwareVersion(void* block);
void writeUF2RebootBlock(void* block);
+120
View File
@@ -0,0 +1,120 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "uf2_flash.h"
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include "thirdparty/FatFs/ff.h"
#include "thirdparty/uf2/uf2.h"
#include "hal/watchdog_driver.h"
#include "hal/flash_driver.h"
#include "pulses/pulses.h"
#define UF2_BLOCK_SIZE 512
void UF2FirmwareUpdate::flashFirmware(const char* filename,
ProgressHandler progressHandler)
{
#if !defined(SIMU)
FIL file;
UF2_Block block;
bool success = false;
pulsesStop();
if (f_open(&file, filename, FA_READ) != FR_OK) {
progressHandler("Firmware", STR_FIRMWARE_UPDATE_ERROR, 1, 1);
pulsesStart();
return;
}
size_t total_len = f_size(&file);
size_t erased_len = 0;
uint32_t last_erased = 0;
UINT bytes_read;
while (f_read(&file, &block, sizeof(block), &bytes_read) == FR_OK &&
bytes_read > 0) {
uint32_t addr = block.targetAddr;
if ((block.flags & UF2_FLAG_NOFLASH) == 0 && addr > last_erased) {
auto drv = flashFindDriver(addr);
if (drv) {
uint32_t sector = drv->get_sector(addr);
uint32_t sect_len = drv->get_sector_size(sector);
if (drv->erase_sector(addr) < 0) break;
last_erased = block.targetAddr + sect_len - 1;
}
}
erased_len += bytes_read;
progressHandler("Firmware", "Erasing...", erased_len, total_len);
if (erased_len >= total_len) {
success = true;
break;
}
}
if (success) {
success = false;
size_t written_len = 0;
f_rewind(&file);
while (f_read(&file, &block, sizeof(block), &bytes_read) == FR_OK &&
bytes_read > 0) {
if ((block.flags & UF2_FLAG_NOFLASH) == 0) {
uint32_t addr = block.targetAddr;
auto drv = flashFindDriver(addr);
if (drv) {
uint32_t len = block.payloadSize;
uint8_t* data = (uint8_t*)block.data;
drv->program(addr, data, len);
}
}
written_len += bytes_read;
progressHandler("Firmware", "Writing...", written_len, total_len);
if (written_len >= total_len) {
success = true;
break;
}
}
}
if(success)
POPUP_INFORMATION(STR_FIRMWARE_UPDATE_SUCCESS);
else
POPUP_INFORMATION(STR_FIRMWARE_UPDATE_ERROR);
watchdogSuspend(0);
WDG_RESET();
f_close(&file);
pulsesStart();
#endif
}
+31
View File
@@ -0,0 +1,31 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#include "io/uf2.h"
#include "edgetx.h"
class UF2FirmwareUpdate
{
public:
void flashFirmware(const char* filename, ProgressHandler progressHandler);
};
-5
View File
@@ -548,9 +548,4 @@ bool rotaryEncoderPollingCycle()
return false;
}
#elif !defined(COLORLCD)
int8_t rotaryEncoderGetAccel() { return ROTENC_LOWSPEED; }
void rotaryEncoderResetAccel() {}
#endif
+7
View File
@@ -122,6 +122,13 @@ void applyDefaultTemplate()
#endif
#endif
#if defined(FUNCTION_SWITCHES_RGB_LEDS)
for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i++) {
g_model.functionSwitchLedOFFColor[i].setColor(0);
g_model.functionSwitchLedONColor[i].setColor(0xFFFFFF);
}
#endif
#if defined(COLORLCD)
LayoutFactory::loadDefaultLayout();
+14 -4
View File
@@ -346,10 +346,10 @@ static void _crsf_extmodule_frame_received()
// FreeRTOS methods from ISR with prio 0
static void _soft_irq_trigger(void*)
{
#ifndef STM32H7
EXTI->SWIER = TELEMETRY_RX_FRAME_EXTI_LINE;
#if defined(TELEMETRY_USE_CUSTOM_EXTI)
stm32_exti_custom_trigger_swi(TELEMETRY_RX_FRAME_EXTI_LINE);
#else
EXTI->SWIER1 = TELEMETRY_RX_FRAME_EXTI_LINE;
stm32_exti_trigger_swi(TELEMETRY_RX_FRAME_EXTI_LINE);
#endif
}
#endif
@@ -397,8 +397,14 @@ static void* crossfireInit(uint8_t module)
#if !defined(SIMU)
if (drv && ctx && drv->setIdleCb) {
drv->setIdleCb(ctx, _soft_irq_trigger, nullptr);
#if defined(TELEMETRY_USE_CUSTOM_EXTI)
stm32_exti_custom_enable(TELEMETRY_RX_FRAME_EXTI_LINE, 3,
_crsf_extmodule_frame_received);
#else
stm32_exti_enable(TELEMETRY_RX_FRAME_EXTI_LINE, 0,
_crsf_extmodule_frame_received);
#endif
}
#endif
}
@@ -426,7 +432,11 @@ static void crossfireDeInit(void* ctx)
auto drv = modulePortGetSerialDrv(mod_st->rx);
auto ctx = modulePortGetCtx(mod_st->rx);
if (drv && ctx && drv->setIdleCb) {
stm32_exti_disable(TELEMETRY_RX_FRAME_EXTI_LINE);
#if defined(TELEMETRY_USE_CUSTOM_EXTI)
stm32_exti_custom_disable(TELEMETRY_RX_FRAME_EXTI_LINE);
#else
stm32_exti_disable(TELEMETRY_RX_FRAME_EXTI_LINE);
#endif
}
}
#endif
+2 -2
View File
@@ -65,7 +65,7 @@
#endif
static module_pulse_driver _module_drivers[MAX_MODULES];
static module_pulse_buffer _module_buffers[MAX_MODULES] __DMA;
static module_pulse_buffer _module_buffers[MAX_MODULES] __DMA_NO_CACHE;
void pulsesInit()
{
@@ -83,7 +83,7 @@ uint8_t* pulsesGetModuleBuffer(uint8_t module)
}
ModuleState moduleState[NUM_MODULES];
TrainerPulsesData trainerPulsesData __DMA;
TrainerPulsesData trainerPulsesData __DMA_NO_CACHE;
void pulsesStart()
{
+4
View File
@@ -85,7 +85,11 @@ const char YAMLFILE_CHECKSUM_TAG_NAME[] = "checksum";
#define SCRIPT_EXT ".lua"
#define SCRIPT_BIN_EXT ".luac"
#define TEXT_EXT ".txt"
#if defined(FIRMWARE_FORMAT_UF2)
#define FIRMWARE_EXT ".uf2"
#else
#define FIRMWARE_EXT ".bin"
#endif
#define SPORT_FIRMWARE_EXT ".frk"
#define FRSKY_FIRMWARE_EXT ".frsk"
#define MULTI_FIRMWARE_EXT ".bin"
+7 -13
View File
@@ -96,28 +96,22 @@ __SECTION_USED(".bootversiondata") const char boot_version[] = "edgetx-" FLA
* Tries to find EdgeTX or OpenTX version in the first 1024 byte of either firmware/bootloader (the one not running) or the buffer
* @param buffer If non-null find the firmware version in the buffer instead
*/
const char * getFirmwareVersion(const char * buffer)
const char * getFirmwareVersion(const uint8_t* buffer)
{
if (buffer == nullptr) {
#if defined(BOOT)
buffer = (const char *)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE);
if(buffer == nullptr) {
#if defined(BOOT) && !defined(FIRMWARE_QSPI)
buffer = (const uint8_t *)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE);
#else
buffer = (const char *)FIRMWARE_ADDRESS;
buffer = (const uint8_t *)FIRMWARE_ADDRESS;
#endif
}
for (int i = 0; i < 1024; i++) {
for (int i = 0; i < 2024; i++) {
if ((memcmp(buffer + i, "edgetx-", 7) == 0)
|| memcmp(buffer + i, "opentx-", 7) == 0) {
return buffer + i;
return (const char*)buffer + i;
}
}
return "no version found";
}
#else
const char * getFirmwareVersion(const char * buffer)
{
return "edgetx-" FLAVOUR "-" VERSION DISPLAY_VERSION " (" GIT_STR ")";
}
#endif
+1 -1
View File
@@ -14,7 +14,7 @@ endif()
# Warning: this file must be kept in sync with 'yaml_datastructs.cpp'
# in the same directory.
if((PCB STREQUAL X10) OR (PCB STREQUAL X12S))
if((PCB STREQUAL X10) OR (PCB STREQUAL X12S) OR (PCB STREQUAL STM32H7S78_DK))
if(PCBREV STREQUAL T15)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_t15.cpp)
elseif(PCBREV STREQUAL F16)
@@ -2258,14 +2258,12 @@ static void r_carryTrim(void* user, uint8_t* data, uint32_t bitoffs,
yaml_put_bits(data, i, bitoffs, 6);
}
#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS)
static void r_rotEncDirection(void* user, uint8_t* data, uint32_t bitoffs,
const char* val, uint8_t val_len)
{
uint32_t i = yaml_str2uint(val, val_len);
yaml_put_bits(data, i, bitoffs, 2);
}
#endif
static void r_telemetryBaudrate(void* user, uint8_t* data, uint32_t bitoffs,
const char* val, uint8_t val_len)
@@ -363,7 +363,8 @@ static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "blOffBright", 7 ),
YAML_STRING("bluetoothName", 10),
YAML_STRING("ownerRegistrationID", 8),
YAML_PADDING( 3 ),
YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr),
YAML_UNSIGNED( "rotEncMode", 3 ),
YAML_SIGNED( "uartSampleMode", 2 ),
YAML_UNSIGNED( "stickDeadZone", 3 ),
YAML_STRING("selectedTheme", 26),
@@ -363,7 +363,8 @@ static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "blOffBright", 7 ),
YAML_STRING("bluetoothName", 10),
YAML_STRING("ownerRegistrationID", 8),
YAML_PADDING( 3 ),
YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr),
YAML_UNSIGNED( "rotEncMode", 3 ),
YAML_SIGNED( "uartSampleMode", 2 ),
YAML_UNSIGNED( "stickDeadZone", 3 ),
YAML_STRING("selectedTheme", 26),
@@ -344,7 +344,8 @@ static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "backlightColor", 8 ),
YAML_STRING("bluetoothName", 10),
YAML_STRING("ownerRegistrationID", 8),
YAML_PADDING( 3 ),
YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr),
YAML_UNSIGNED( "rotEncMode", 3 ),
YAML_SIGNED( "uartSampleMode", 2 ),
YAML_PADDING( 3 ),
YAML_UNSIGNED( "radioGFDisabled", 1 ),
@@ -344,7 +344,8 @@ static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "backlightColor", 8 ),
YAML_STRING("bluetoothName", 10),
YAML_STRING("ownerRegistrationID", 8),
YAML_PADDING( 3 ),
YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr),
YAML_UNSIGNED( "rotEncMode", 3 ),
YAML_SIGNED( "uartSampleMode", 2 ),
YAML_PADDING( 3 ),
YAML_UNSIGNED( "radioGFDisabled", 1 ),
@@ -346,7 +346,8 @@ static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "backlightColor", 8 ),
YAML_STRING("bluetoothName", 10),
YAML_STRING("ownerRegistrationID", 8),
YAML_PADDING( 3 ),
YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr),
YAML_UNSIGNED( "rotEncMode", 3 ),
YAML_SIGNED( "uartSampleMode", 2 ),
YAML_PADDING( 3 ),
YAML_SIGNED( "imuMax", 8 ),
+1
View File
@@ -170,6 +170,7 @@ void evalFunctionSwitches()
for (uint8_t i = 0; i < fct_switches; i++) {
if (FSWITCH_CONFIG(i) == SWITCH_NONE) {
setFSLedOFF(i);
//fsLedRGB(i, 0);
continue;
}
@@ -25,6 +25,7 @@ if(NOT NATIVE_BUILD)
${STM32USB_DIR}/Core/Src/usbd_ctlreq.c
${STM32USB_DIR}/Core/Src/usbd_ioreq.c
${STM32USB_DIR}/Class/CDC/Src/usbd_cdc.c
${STM32USB_DIR}/Class/DFU/Src/usbd_dfu.c
${STM32USB_DIR}/Class/MSC/Src/usbd_msc_data.c
${STM32USB_DIR}/Class/MSC/Src/usbd_msc_scsi.c
${STM32USB_DIR}/Class/MSC/Src/usbd_msc_bot.c
@@ -34,9 +35,14 @@ if(NOT NATIVE_BUILD)
target_include_directories(stm32usb PRIVATE
${STM32USB_DIR}/Core/Inc
${STM32USB_DIR}/Class/CDC/Inc
${STM32USB_DIR}/Class/DFU/Inc
${STM32USB_DIR}/Class/HID/Inc
${STM32USB_DIR}/Class/MSC/Inc)
target_include_directories(board_bl PRIVATE
${STM32USB_DIR}/Core/Inc
${STM32USB_DIR}/Class/DFU/Inc)
set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:stm32usb>)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:stm32usb>)
@@ -44,14 +50,15 @@ if(NOT NATIVE_BUILD)
add_library(stm32usb_device_bl OBJECT EXCLUDE_FROM_ALL
${STM32_DRIVER_DIR}/usbd_conf.c
${STM32_DRIVER_DIR}/usbd_desc.c
${STM32_DRIVER_DIR}/usb_driver.cpp
${STM32_DRIVER_DIR}/usbd_storage_msd.cpp
${STM32_DRIVER_DIR}/usb_driver.cpp
)
target_compile_options(stm32usb_device_bl PRIVATE -DBOOT)
target_include_directories(stm32usb_device_bl PRIVATE
${STM32USB_DIR}/Core/Inc
${STM32USB_DIR}/Class/CDC/Inc
${STM32USB_DIR}/Class/DFU/Inc
${STM32USB_DIR}/Class/HID/Inc
${STM32USB_DIR}/Class/MSC/Inc)
@@ -74,6 +81,7 @@ if(NOT NATIVE_BUILD)
target_include_directories(stm32usb_device_fw PRIVATE
${STM32USB_DIR}/Core/Inc
${STM32USB_DIR}/Class/CDC/Inc
${STM32USB_DIR}/Class/DFU/Inc
${STM32USB_DIR}/Class/HID/Inc
${STM32USB_DIR}/Class/MSC/Inc)
@@ -146,3 +154,11 @@ set(FIRMWARE_SRC ${FIRMWARE_SRC} syscalls.c)
set(TARGET_SRC ${TARGET_SRC} ../common/arm/stm32/cpu_id.cpp)
set(SRC ${SRC} io/bootloader_flash.cpp)
if(FIRMWARE_FORMAT_UF2)
add_definitions(-DFIRMWARE_FORMAT_UF2)
set(SRC ${SRC}
io/uf2.cpp
io/uf2_flash.cpp
)
endif()
@@ -83,3 +83,13 @@ uint32_t abnormalRebootGetCause()
_init_reboot_cause();
return _reboot_cause;
}
uint32_t abnormalRebootGetCmd()
{
return _reboot_cmd;
}
void abnormalRebootResetCmd()
{
_reboot_cmd = 0;
}
@@ -24,9 +24,11 @@
#include <inttypes.h>
#include "cpu_id.h"
#if !defined(SIMU) && !defined(BACKUP)
#if !defined(SIMU) && !defined(BACKUP) && !defined(YAML_GENERATOR)
#if defined(STM32H7)
#include "stm32h7xx.h"
#elif defined(STM32H7RS)
#include "stm32h7rsxx.h"
#elif defined(STM32F4)
#include "stm32f4xx.h"
#elif defined(STM32F2)
@@ -12,9 +12,22 @@ set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
${RADIO_SRC_DIR}/syscalls.c
${RADIO_SRC_DIR}/crc.cpp
boot.cpp
bin_files.cpp
)
if(FIRMWARE_FORMAT_UF2)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
boot_uf2.cpp
boot_dfu.cpp
${RADIO_SRC_DIR}/io/uf2.cpp
${RADIO_SRC_DIR}/drivers/uf2_ghostfat.cpp
)
else()
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
boot_menu.cpp
bin_fw_files.cpp
)
endif()
if(DEBUG_SEGGER_RTT)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
${RADIO_SRC_DIR}/thirdparty/Segger_RTT/RTT/SEGGER_RTT.c
@@ -25,19 +25,52 @@
#include "boot.h"
#include "board.h"
#include "sdcard.h"
#include "bin_files.h"
#include "firmware_files.h"
#include "fw_version.h"
#include "strhelpers.h"
#include "hal/storage.h"
#include "flash_driver.h"
// Size of the block read when checking / writing BIN files
#define BLOCK_LEN 4096
// 'private'
static DIR dir;
static FIL FlashFile;
static uint32_t firmwareSize;
static uint32_t firmwareAddress = FIRMWARE_ADDRESS;
static uint32_t firmwareWritten = 0;
uint32_t unlocked = 0;
struct FWFileInfo {
TCHAR name[FF_MAX_LFN + 1];
unsigned int size;
};
// 'public' variables
BinFileInfo binFiles[MAX_BIN_FILES];
uint8_t Block_buffer[BLOCK_LEN];
UINT BlockCount;
static FWFileInfo fwFiles[MAX_FW_FILES];
static uint8_t Block_buffer[BLOCK_LEN];
static UINT BlockCount;
static void flashWriteBlock()
{
// TODO: use some board provided driver instead
uint32_t blockOffset = 0;
#if !defined(SIMU)
while (BlockCount) {
flashWrite((uint32_t *)firmwareAddress, (uint32_t *)&Block_buffer[blockOffset]);
blockOffset += FLASH_PAGESIZE;
firmwareAddress += FLASH_PAGESIZE;
if (BlockCount > FLASH_PAGESIZE) {
BlockCount -= FLASH_PAGESIZE;
}
else {
BlockCount = 0;
}
}
#endif // SIMU
}
void sdInit(void)
{
@@ -56,14 +89,41 @@ void sdDone()
storageDeInit();
}
FRESULT openBinDir(MemoryType mt)
FRESULT openFirmwareDir()
{
FRESULT fr = f_chdir(getBinaryPath(mt));
FRESULT fr = f_chdir(getFirmwarePath());
if (fr != FR_OK) return fr;
return f_opendir(&dir, ".");
}
static uint32_t isValidBufferStart(const uint8_t * buffer)
{
#if !defined(SIMU)
return isFirmwareStart(buffer);
#else
return 1;
#endif
}
FlashCheckRes checkFirmwareFile(unsigned int index, FlashCheckRes res)
{
if (res != FC_UNCHECKED)
return res;
if (openFirmwareFile(index) != FR_OK)
return FC_ERROR;
if (closeFirmwareFile() != FR_OK)
return FC_ERROR;
if (!isValidBufferStart(Block_buffer))
return FC_ERROR;
return FC_OK;
}
static FRESULT findNextBinFile(FILINFO* fno)
{
FRESULT fr;
@@ -102,7 +162,7 @@ static FRESULT findNextBinFile(FILINFO* fno)
return fr;
}
unsigned int fetchBinFiles(unsigned int index)
unsigned int fetchFirmwareFiles(unsigned int index)
{
FILINFO file_info;
@@ -117,8 +177,8 @@ unsigned int fetchBinFiles(unsigned int index)
return 0;
}
strAppend(binFiles[0].name, file_info.fname);
binFiles[0].size = file_info.fsize;
strAppend(fwFiles[0].name, file_info.fname);
fwFiles[0].size = file_info.fsize;
unsigned int i = 1;
for (; i < MAX_NAMES_ON_SCREEN+1; i++) {
@@ -126,49 +186,57 @@ unsigned int fetchBinFiles(unsigned int index)
if (findNextBinFile(&file_info) != FR_OK || file_info.fname[0] == 0)
return i;
strAppend(binFiles[i].name, file_info.fname);
binFiles[i].size = file_info.fsize;
strAppend(fwFiles[i].name, file_info.fname);
fwFiles[i].size = file_info.fsize;
}
return i;
}
FRESULT openBinFile(MemoryType mt, unsigned int index)
const char* getFirmwareFileNameByIndex(unsigned int index)
{
if(index >= MAX_FW_FILES)
return "";
return fwFiles[index].name;
}
FRESULT openFirmwareFile(unsigned int index)
{
TCHAR full_path[FF_MAX_LFN+1];
FRESULT fr;
FRESULT res;
// build full_path: [bin path]/[filename]
char* s = strAppend(full_path, getBinaryPath(mt));
char* s = strAppend(full_path, getFirmwarePath());
s = strAppend(s, "/");
strAppend(s, binFiles[index].name);
strAppend(s, fwFiles[index].name);
BlockCount = 0;
// open the file
if ((fr = f_open(&FlashFile, full_path, FA_READ)) != FR_OK)
return fr;
res = f_open(&FlashFile, full_path, FA_READ);
if (res != FR_OK) return res;
// skip bootloader in firmware
if (mt == MEM_FLASH &&
((fr = f_lseek(&FlashFile, BOOTLOADER_SIZE)) != FR_OK))
return fr;
res = f_lseek(&FlashFile, BOOTLOADER_SIZE);
if (res != FR_OK) return res;
// ... and fetch BLOCK_LEN bytes
fr = f_read(&FlashFile, Block_buffer, BLOCK_LEN, &BlockCount);
if (BlockCount == BLOCK_LEN)
return fr;
res = f_read(&FlashFile, Block_buffer, BLOCK_LEN, &BlockCount);
if (BlockCount == BLOCK_LEN && isValidBufferStart(Block_buffer)) return res;
f_close(&FlashFile);
return FR_INVALID_OBJECT;
}
void extractFirmwareVersion(VersionTag* tag)
void getFileFirmwareVersion(VersionTag* tag)
{
const char * vers = getFirmwareVersion((const char *)Block_buffer);
memset(tag->flavour, 0, sizeof(tag->flavour));
const char * vers = getFirmwareVersion((const uint8_t *)Block_buffer);
if (!vers || (vers[0] == 'n' && vers[1] == 'o')) { // "no version found"
memcpy(tag->flavour, "unknown", sizeof("unknown"));
tag->version = "unknown";
tag->flavour[sizeof(tag->flavour)-1] = 0;
return;
}
@@ -180,18 +248,41 @@ void extractFirmwareVersion(VersionTag* tag)
char* fl = tag->flavour;
while(*vers != '-')
*(fl++) = *(vers++);
tag->flavour[sizeof(tag->flavour)-1] = 0;
// skip '-'
tag->version = ++vers;
}
FRESULT readBinFile()
FRESULT readFirmwareFile()
{
BlockCount = 0;
return f_read(&FlashFile, Block_buffer, sizeof(Block_buffer), &BlockCount);
}
FRESULT closeBinFile()
FRESULT closeFirmwareFile()
{
return f_close(&FlashFile);
}
void firmwareInitWrite(uint32_t index)
{
firmwareSize = fwFiles[index].size - BOOTLOADER_SIZE;
firmwareAddress = FIRMWARE_ADDRESS + BOOTLOADER_SIZE;
firmwareWritten = 0;
}
bool firmwareWriteBlock(uint32_t* progress)
{
flashWriteBlock();
firmwareWritten += sizeof(Block_buffer);
*progress = (100 * firmwareWritten) / firmwareSize;
readFirmwareFile();
if (BlockCount == 0 || firmwareWritten >= FLASHSIZE - BOOTLOADER_SIZE) {
return true;
}
return false;
}
@@ -19,45 +19,27 @@
* GNU General Public License for more details.
*/
// #if !defined(SIMU)
// #include "stm32_hal_ll.h"
// #include "stm32_hal.h"
// #include "stm32_timer.h"
// #endif
#include "boot.h"
#include "hal/usb_driver.h"
#include "hal/abnormal_reboot.h"
#include "hal/rotary_encoder.h"
#include "board.h"
#include "debug.h"
#include "timers_driver.h"
#if defined(BLUETOOTH)
#include "bluetooth_driver.h"
#include "stm32_serial_driver.h"
#endif
#include "board.h"
#include "boot.h"
#include "bin_files.h"
#include "lcd.h"
#include "debug.h"
#include "timers_driver.h"
#include "flash_driver.h"
#include "hal/abnormal_reboot.h"
#include "hal/rotary_encoder.h"
#if defined(DEBUG_SEGGER_RTT)
#include "thirdparty/Segger_RTT/RTT/SEGGER_RTT.h"
#endif
#if defined(SPI_FLASH)
#define MAIN_MENU_LEN 3
#else
#define MAIN_MENU_LEN 2
#endif
#if defined(SPI_FLASH)
#include "diskio_spi_flash.h"
#define SEL_CLEAR_FLASH_STORAGE_MENU_LEN 2
#endif
#define REBOOT_CMD_DFU 0x55464442
#if !defined(SIMU)
// Bootloader marker:
@@ -72,104 +54,6 @@ const uint8_t bootloaderVersion[] __attribute__ ((section(".version"), used)) =
#define __weak __attribute__((weak))
#endif
volatile tmr10ms_t g_tmr10ms;
volatile uint8_t tenms = 1;
uint32_t firmwareSize;
uint32_t firmwareAddress = FIRMWARE_ADDRESS;
uint32_t firmwareWritten = 0;
FlashCheckRes valid;
MemoryType memoryType;
uint32_t unlocked = 0;
void per5ms() {} // make linker happy
void per10ms()
{
tenms |= 1u; // 10 mS has passed
g_tmr10ms++;
keysPollingCycle();
#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS)
static rotenc_t rePreviousValue;
rotenc_t reNewValue = rotaryEncoderGetValue();
int8_t scrollRE = reNewValue - rePreviousValue;
if (scrollRE) {
rePreviousValue = reNewValue;
pushEvent(scrollRE < 0 ? EVT_ROTARY_LEFT : EVT_ROTARY_RIGHT);
}
#endif
}
uint32_t isValidBufferStart(const uint8_t * buffer)
{
#if !defined(SIMU)
return isFirmwareStart(buffer);
#else
return 1;
#endif
}
FlashCheckRes checkFlashFile(unsigned int index, FlashCheckRes res)
{
if (res != FC_UNCHECKED)
return res;
if (openBinFile(memoryType, index) != FR_OK)
return FC_ERROR;
if (closeBinFile() != FR_OK)
return FC_ERROR;
if (!isValidBufferStart(Block_buffer))
return FC_ERROR;
return FC_OK;
}
int menuFlashFile(uint32_t index, event_t event)
{
valid = checkFlashFile(index, valid);
if (valid == FC_ERROR) {
if (event == EVT_KEY_BREAK(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_ENTER))
return 0;
return -1;
}
if (event == EVT_KEY_LONG(KEY_ENTER)) {
return (openBinFile(memoryType, index) == FR_OK) && isValidBufferStart(Block_buffer);
}
else if (event == EVT_KEY_BREAK(KEY_EXIT))
return 0;
return -1;
}
void flashWriteBlock()
{
// TODO: use some board provided driver instead
uint32_t blockOffset = 0;
#if !defined(SIMU)
while (BlockCount) {
flashWrite((uint32_t *)firmwareAddress, (uint32_t *)&Block_buffer[blockOffset]);
blockOffset += FLASH_PAGESIZE;
firmwareAddress += FLASH_PAGESIZE;
if (BlockCount > FLASH_PAGESIZE) {
BlockCount -= FLASH_PAGESIZE;
}
else {
BlockCount = 0;
}
}
#endif // SIMU
}
#if !defined(SIMU)
typedef void (*fctptr_t)(void);
@@ -184,13 +68,14 @@ static __attribute__((noreturn)) void jumpTo(uint32_t addr)
}
// Optional board hook
__weak void boardBLInit() {}
__weak void boardBLEarlyInit() {}
__weak bool boardBLStartCondition() { return false; }
__weak void boardBLPreJump() {}
__weak void boardBLInit() {}
void bootloaderInitApp()
{
boardBLInit();
boardBLEarlyInit();
#if defined(DEBUG_SEGGER_RTT)
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
@@ -198,18 +83,28 @@ void bootloaderInitApp()
pwrInit();
keysInit();
delaysInit();
// wait a bit for the inputs to stabilize...
if (!WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) {
for (uint32_t i = 0; i < 150000; i++) {
__ASM volatile("nop");
bool boot_dfu = abnormalRebootGetCmd() == REBOOT_CMD_DFU;
if (!boot_dfu) {
bool start_firmware = true;
// wait a bit for the inputs to stabilize...
if (!WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) {
delay_us(200);
}
}
if (!boardBLStartCondition()) {
// Start main application
boardBLPreJump();
jumpTo(APP_START_ADDRESS);
start_firmware = !boardBLStartCondition();
if (start_firmware) {
// Start main application
boardBLPreJump();
jumpTo(APP_START_ADDRESS);
}
} else {
#if defined(FIRMWARE_QSPI)
abnormalRebootResetCmd();
setSelectedUsbMode(USB_DFU_MODE);
#endif
}
// TODO: move all this into board specifics
@@ -219,8 +114,6 @@ void bootloaderInitApp()
rotaryEncoderInit();
#endif
delaysInit(); // needed for lcdInit()
#if defined(DEBUG)
initSerialPorts();
#endif
@@ -238,9 +131,8 @@ void bootloaderInitApp()
timersInit();
// SD card detect pin
sdInit();
usbInit();
boardBLInit();
}
int main()
@@ -249,286 +141,28 @@ void bootloaderInitApp() {}
int bootloaderMain()
#endif
{
BootloaderState state = ST_START;
uint32_t vpos = 0;
uint32_t radioMenuItem = 0;
uint8_t index = 0;
FRESULT fr;
uint32_t nameCount = 0;
// init hardware (may jump to app)
bootloaderInitApp();
// init screen
bootloaderInitScreen();
#if defined(FIRMWARE_FORMAT_UF2)
if (getSelectedUsbMode() == USB_DFU_MODE) {
bootloaderDFU();
}
#endif
#if defined(PWR_BUTTON_PRESS)
// wait until power button is released
while (pwrPressed()) {}
#endif
for (;;) {
if (tenms) {
tenms = 0;
if (state != ST_USB && state != ST_FLASHING
&& state != ST_FLASH_DONE && state != ST_RADIO_MENU) {
if (usbPlugged()) {
state = ST_USB;
if (!unlocked) {
unlocked = 1;
unlockFlash();
}
#if !defined(SIMU)
usbStart();
#endif
}
}
if (state == ST_USB) {
if (usbPlugged() == 0) {
vpos = 0;
#if !defined(SIMU)
usbStop();
#endif
if (unlocked) {
lockFlash();
unlocked = 0;
}
state = ST_START;
}
bootloaderDrawScreen(state, 0);
}
lcdRefreshWait();
event_t event = getEvent();
if (state == ST_START) {
bootloaderDrawScreen(state, vpos);
if (IS_NEXT_EVENT(event)) {
if (vpos < bootloaderGetMenuItemCount(MAIN_MENU_LEN) - 1) { vpos++; }
continue;
}
else if (IS_PREVIOUS_EVENT(event)) {
if (vpos > 0) { vpos--; }
continue;
}
else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
switch (vpos) {
case 0:
memoryType = MEM_FLASH;
state = ST_DIR_CHECK;
break;
#if defined(SPI_FLASH)
case 1:
state = ST_CLEAR_FLASH_CHECK;
break;
#endif
default:
if(vpos < bootloaderGetMenuItemCount(MAIN_MENU_LEN-1))
{
state = ST_RADIO_MENU;
radioMenuItem = vpos - MAIN_MENU_LEN - 1;
} else {
state = ST_REBOOT;
}
break;
}
// next loop
continue;
}
}
else if (state == ST_DIR_CHECK) {
fr = openBinDir(memoryType);
if (fr == FR_OK) {
index = vpos = 0;
state = ST_FILE_LIST;
nameCount = fetchBinFiles(index);
continue;
}
else {
bootloaderDrawScreen(state, fr);
if (event == EVT_KEY_BREAK(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_ENTER)) {
vpos = 0;
state = ST_START;
continue;
}
}
}
if (state == ST_FILE_LIST) {
uint32_t limit = MAX_NAMES_ON_SCREEN;
if (nameCount < limit) {
limit = nameCount;
}
if (IS_NEXT_EVENT(event)) {
if (vpos < limit - 1) {
vpos += 1;
}
else {
if (nameCount > limit) {
index += 1;
nameCount = fetchBinFiles(index);
}
}
}
else if (IS_PREVIOUS_EVENT(event)) {
if (vpos > 0) {
vpos -= 1;
}
else {
if (index) {
index -= 1;
nameCount = fetchBinFiles(index);
}
}
}
bootloaderDrawScreen(state, 0);
for (uint32_t i = 0; i < limit; i++) {
bootloaderDrawFilename(binFiles[i].name, i, (vpos == i));
}
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
// Select file to flash
state = ST_FLASH_CHECK;
valid = FC_UNCHECKED;
continue;
}
else if (event == EVT_KEY_BREAK(KEY_EXIT)) {
state = ST_START;
vpos = 0;
continue;
}
}
else if (state == ST_FLASH_CHECK) {
bootloaderDrawScreen(state, valid, binFiles[vpos].name);
int result = menuFlashFile(vpos, event);
if (result == 0) {
// canceled
state = ST_FILE_LIST;
}
else if (result == 1) {
// confirmed
if (memoryType == MEM_FLASH) {
firmwareSize = FIRMWARE_LEN(binFiles[vpos].size);
firmwareAddress = APP_START_ADDRESS;
firmwareWritten = 0;
}
state = ST_FLASHING;
}
}
else if (state == ST_FLASHING) {
// commit to flashing
if (!unlocked && (memoryType == MEM_FLASH)) {
unlocked = 1;
unlockFlash();
}
int progress = 0;
if (memoryType == MEM_FLASH) {
flashWriteBlock();
firmwareWritten += sizeof(Block_buffer);
progress = (100 * firmwareWritten) / firmwareSize;
}
bootloaderDrawScreen(state, progress);
fr = readBinFile();
if (BlockCount == 0) {
state = ST_FLASH_DONE; // EOF
}
else if (memoryType == MEM_FLASH && firmwareWritten >= FIRMWARE_MAX_LEN) {
state = ST_FLASH_DONE; // Backstop
}
#if defined(SPI_FLASH)
} else if (state == ST_CLEAR_FLASH_CHECK) {
bootloaderDrawScreen(state, vpos);
if (IS_NEXT_EVENT(event)) {
if (vpos < SEL_CLEAR_FLASH_STORAGE_MENU_LEN - 1) { vpos++; }
continue;
}
if (IS_PREVIOUS_EVENT(event)) {
if (vpos > 0) { vpos--; }
continue;
}
if (event == EVT_KEY_LONG(KEY_ENTER) && vpos == 0)
{
state = ST_CLEAR_FLASH;
} else if (event == EVT_KEY_BREAK(KEY_EXIT) ||
(event == EVT_KEY_BREAK(KEY_ENTER) && vpos == 1) ) {
vpos = 0;
state = ST_START;
continue;
}
} else if (state == ST_CLEAR_FLASH) {
bootloaderDrawScreen(state, 0);
lcdRefresh();
sdDone();
spiFlashDiskEraseAll();
sdInit();
vpos = 0;
state = ST_START;
#endif
} else if (state == ST_RADIO_MENU) {
if(bootloaderRadioMenu(radioMenuItem, event))
{
state = ST_START;
vpos = 0;
bootloaderDrawScreen(state, vpos);
}
}
if (state == ST_FLASH_DONE) {
if (unlocked) {
lockFlash();
unlocked = 0;
}
if (event == EVT_KEY_BREAK(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_ENTER)) {
state = ST_START;
vpos = 0;
}
bootloaderDrawScreen(state, 100);
}
if (event == EVT_KEY_LONG(KEY_EXIT)) {
// Start the main application
state = ST_REBOOT;
}
lcdRefresh();
}
if (state != ST_FLASHING && state != ST_USB) {
if (pwrOffPressed()) {
sdDone();
boardOff();
}
}
if (state == ST_REBOOT) {
sdDone();
#if !defined(SIMU)
blExit();
NVIC_SystemReset();
#if !defined(FIRMWARE_FORMAT_UF2)
bootloaderMenu();
#else
exit(1);
bootloaderUF2();
#endif
}
}
return 0;
}
@@ -25,6 +25,8 @@
#include "stamp.h"
#include "keys.h"
#include "hal/flash_driver.h"
#if LCD_W < 212
#if defined(VERSION_TAG)
#define BOOTLOADER_TITLE " Bootloader - " VERSION_TAG
@@ -61,11 +63,14 @@ enum BootloaderState {
ST_REBOOT,
};
enum FlashCheckRes {
FC_UNCHECKED=0,
FC_OK,
FC_ERROR
};
// interactive bootloader
void bootloaderMenu();
// non-interactive UF2 bootloader
void bootloaderUF2();
// non-interactive DFU bootloader
void bootloaderDFU();
// Declarations of functions that need to be implemented
// for each target with a bootloader
@@ -87,4 +92,7 @@ uint32_t bootloaderGetMenuItemCount(int baseCount);
// returns true on submenu exit
bool bootloaderRadioMenu(uint32_t menuItem, event_t event);
void bootloaderDrawDFUScreen();
void sdInit();
void blExit();
@@ -0,0 +1,26 @@
#include "stm32_hal.h"
#include "boot.h"
#include "hal/usb_driver.h"
#include "lcd.h"
extern volatile uint8_t tenms;
void bootloaderDFU()
{
usbPlugged();
usbStart();
bootloaderDrawDFUScreen();
for (;;) {
if (tenms) {
if (!usbPlugged()) break;
bootloaderDrawDFUScreen();
lcdRefresh();
}
}
blExit();
NVIC_SystemReset();
}
@@ -0,0 +1,297 @@
#include "boot.h"
#include "firmware_files.h"
#include "hal/usb_driver.h"
#include "hal/rotary_encoder.h"
#include "lcd.h"
#if defined(SPI_FLASH)
#define MAIN_MENU_LEN 3
#else
#define MAIN_MENU_LEN 2
#endif
#if defined(SPI_FLASH)
#include "diskio_spi_flash.h"
#define SEL_CLEAR_FLASH_STORAGE_MENU_LEN 2
#endif
volatile tmr10ms_t g_tmr10ms;
volatile uint8_t tenms = 1;
void per5ms() {} // make linker happy
void per10ms()
{
tenms |= 1u; // 10 mS has passed
g_tmr10ms++;
keysPollingCycle();
// TODO: use rotaryEncoderPollingCycle() instead
#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS)
static rotenc_t rePreviousValue;
rotenc_t reNewValue = rotaryEncoderGetValue();
int8_t scrollRE = reNewValue - rePreviousValue;
if (scrollRE) {
rePreviousValue = reNewValue;
pushEvent(scrollRE < 0 ? EVT_ROTARY_LEFT : EVT_ROTARY_RIGHT);
}
#endif
}
FlashCheckRes valid;
int menuFlashFile(uint32_t index, event_t event)
{
valid = checkFirmwareFile(index, valid);
if (valid == FC_ERROR) {
if (event == EVT_KEY_BREAK(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_ENTER))
return 0;
return -1;
}
if (event == EVT_KEY_LONG(KEY_ENTER)) {
return openFirmwareFile(index) == FR_OK ? 1 : -1;
} else if (event == EVT_KEY_BREAK(KEY_EXIT))
return 0;
return -1;
}
void bootloaderMenu()
{
BootloaderState state = ST_START;
uint32_t vpos = 0;
uint32_t radioMenuItem = 0;
uint8_t index = 0;
FRESULT fr;
uint32_t nameCount = 0;
sdInit();
for (;;) {
if (tenms) {
tenms = 0;
if (state != ST_USB && state != ST_FLASHING
&& state != ST_FLASH_DONE && state != ST_RADIO_MENU) {
if (usbPlugged()) {
state = ST_USB;
#if !defined(SIMU)
usbStart();
#endif
}
}
if (state == ST_USB) {
if (usbPlugged() == 0) {
vpos = 0;
#if !defined(SIMU)
usbStop();
#endif
state = ST_START;
}
bootloaderDrawScreen(state, 0);
}
lcdRefreshWait();
event_t event = getEvent();
if (state == ST_START) {
bootloaderDrawScreen(state, vpos);
if (IS_NEXT_EVENT(event)) {
if (vpos < bootloaderGetMenuItemCount(MAIN_MENU_LEN) - 1) { vpos++; }
continue;
}
else if (IS_PREVIOUS_EVENT(event)) {
if (vpos > 0) { vpos--; }
continue;
}
else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
switch (vpos) {
case 0:
state = ST_DIR_CHECK;
break;
#if defined(SPI_FLASH)
case 1:
state = ST_CLEAR_FLASH_CHECK;
break;
#endif
default:
if(vpos < bootloaderGetMenuItemCount(MAIN_MENU_LEN-1))
{
state = ST_RADIO_MENU;
radioMenuItem = vpos - MAIN_MENU_LEN - 1;
} else {
state = ST_REBOOT;
}
break;
}
// next loop
continue;
}
}
else if (state == ST_DIR_CHECK) {
fr = openFirmwareDir();
if (fr == FR_OK) {
index = vpos = 0;
state = ST_FILE_LIST;
nameCount = fetchFirmwareFiles(index);
continue;
}
else {
bootloaderDrawScreen(state, fr);
if (event == EVT_KEY_BREAK(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_ENTER)) {
vpos = 0;
state = ST_START;
continue;
}
}
}
if (state == ST_FILE_LIST) {
uint32_t limit = MAX_NAMES_ON_SCREEN;
if (nameCount < limit) {
limit = nameCount;
}
if (IS_NEXT_EVENT(event)) {
if (vpos < limit - 1) {
vpos += 1;
} else {
if (nameCount > limit) {
index += 1;
nameCount = fetchFirmwareFiles(index);
}
}
} else if (IS_PREVIOUS_EVENT(event)) {
if (vpos > 0) {
vpos -= 1;
}
else {
if (index) {
index -= 1;
nameCount = fetchFirmwareFiles(index);
}
}
}
bootloaderDrawScreen(state, 0);
for (uint32_t i = 0; i < limit; i++) {
bootloaderDrawFilename(getFirmwareFileNameByIndex(i), i, (vpos == i));
}
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
// Select file to flash
state = ST_FLASH_CHECK;
valid = FC_UNCHECKED;
continue;
} else if (event == EVT_KEY_BREAK(KEY_EXIT)) {
state = ST_START;
vpos = 0;
continue;
}
} else if (state == ST_FLASH_CHECK) {
bootloaderDrawScreen(state, valid, getFirmwareFileNameByIndex(vpos));
int result = menuFlashFile(vpos, event);
if (result == 0) {
// canceled
state = ST_FILE_LIST;
} else if (result == 1) {
// confirmed
firmwareInitWrite(vpos);
state = ST_FLASHING;
}
} else if (state == ST_FLASHING) {
uint32_t progress = 0;
bool done = firmwareWriteBlock(&progress);
bootloaderDrawScreen(state, progress);
if(done) {
state = ST_FLASH_DONE;
}
#if defined(SPI_FLASH)
} else if (state == ST_CLEAR_FLASH_CHECK) {
bootloaderDrawScreen(state, vpos);
if (IS_NEXT_EVENT(event)) {
if (vpos < SEL_CLEAR_FLASH_STORAGE_MENU_LEN - 1) { vpos++; }
continue;
}
if (IS_PREVIOUS_EVENT(event)) {
if (vpos > 0) { vpos--; }
continue;
}
if (event == EVT_KEY_LONG(KEY_ENTER) && vpos == 0)
{
state = ST_CLEAR_FLASH;
} else if (event == EVT_KEY_BREAK(KEY_EXIT) ||
(event == EVT_KEY_BREAK(KEY_ENTER) && vpos == 1) ) {
vpos = 0;
state = ST_START;
continue;
}
} else if (state == ST_CLEAR_FLASH) {
bootloaderDrawScreen(state, 0);
lcdRefresh();
sdDone();
spiFlashDiskEraseAll();
sdInit();
vpos = 0;
state = ST_START;
#endif
} else if (state == ST_RADIO_MENU) {
if(bootloaderRadioMenu(radioMenuItem, event))
{
state = ST_START;
vpos = 0;
bootloaderDrawScreen(state, vpos);
}
}
if (state == ST_FLASH_DONE) {
if (event == EVT_KEY_BREAK(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_ENTER)) {
state = ST_START;
vpos = 0;
}
bootloaderDrawScreen(state, 100);
}
if (event == EVT_KEY_LONG(KEY_EXIT)) {
// Start the main application
state = ST_REBOOT;
}
lcdRefresh();
}
if (state != ST_FLASHING && state != ST_USB) {
if (pwrOffPressed()) {
sdDone();
boardOff();
}
}
if (state == ST_REBOOT) {
sdDone();
#if !defined(SIMU)
blExit();
NVIC_SystemReset();
#else
exit(1);
#endif
}
}
}
@@ -0,0 +1,97 @@
#include "boot.h"
#include "hal/usb_driver.h"
#include "hal/storage.h"
#include "hal/fatfs_diskio.h"
#include "thirdparty/FatFs/diskio.h"
#include "drivers/uf2_ghostfat.h"
#include "board.h"
#include "lcd.h"
extern uf2_fat_write_state_t _uf2_write_state;
volatile tmr10ms_t g_tmr10ms;
volatile uint8_t tenms = 1;
void per5ms() {} // make linker happy
void per10ms()
{
tenms |= 1u; // 10 mS has passed
g_tmr10ms++;
}
void bootloaderUF2()
{
BootloaderState state = ST_START;
// register SD storage
storageInit();
disk_initialize(0);
for (;;) {
if (tenms) {
tenms = 0;
if (state != ST_USB && state != ST_FLASHING && state != ST_FLASH_DONE) {
if (usbPlugged()) {
state = ST_USB;
#if !defined(SIMU)
usbStart();
#endif
} else if (pwrOffPressed()) {
storageDeInit();
boardOff();
}
}
if (state == ST_USB || state == ST_FLASH_DONE) {
if (usbPlugged() == 0) {
#if !defined(SIMU)
usbStop();
#endif
state = (state == ST_FLASH_DONE) ? ST_REBOOT : ST_START;
} else {
auto wr_st = uf2_fat_get_state();
if (wr_st->num_blocks != 0 && wr_st->num_blocks <= UF2_MAX_BLOCKS) {
state = ST_FLASHING;
}
}
bootloaderDrawScreen(state, 0);
}
if (state == ST_START) {
bootloaderDrawScreen(state, 0);
} else if (state == ST_FLASHING) {
auto wr_st = uf2_fat_get_state();
if (wr_st->num_blocks == 0 || wr_st->num_blocks > UF2_MAX_BLOCKS) {
state = ST_USB;
} else {
uint32_t progress = (wr_st->num_written * 100) / wr_st->num_blocks;
if (wr_st->num_written == wr_st->num_blocks) {
state = ST_FLASH_DONE;
uf2_fat_reset_state();
}
bootloaderDrawScreen(state, progress);
}
} else if (state == ST_FLASH_DONE) {
bootloaderDrawScreen(state, 100);
}
lcdRefresh();
}
if (state == ST_REBOOT) {
storageDeInit();
#if !defined(SIMU)
blExit();
NVIC_SystemReset();
#else
exit(1);
#endif
}
}
}
@@ -26,13 +26,9 @@
#if defined(COLORLCD)
#include "bitmaps.h"
#endif
#include "boards/FirmwareVersionTag.h"
enum MemoryType {
MEM_FLASH,
MEM_EEPROM
};
#define getBinaryPath(mt) (FIRMWARES_PATH)
#define getFirmwarePath() (FIRMWARES_PATH)
#if LCD_H == 480
#define MAX_NAMES_ON_SCREEN 13
@@ -40,56 +36,44 @@ enum MemoryType {
#define MAX_NAMES_ON_SCREEN 6
#endif
#define MAX_BIN_FILES (MAX_NAMES_ON_SCREEN+1)
#define MAX_FW_FILES (MAX_NAMES_ON_SCREEN+1)
// Size of the block read when checking / writing BIN files
#define BLOCK_LEN 4096
// File info struct while browsing files on SD card
struct BinFileInfo {
TCHAR name[FF_MAX_LFN + 1];
unsigned int size;
};
// File info storage while browsing files on SD card
extern BinFileInfo binFiles[MAX_BIN_FILES];
// Block buffer used when checking / writing BIN files
extern uint8_t Block_buffer[BLOCK_LEN];
// Bytes read into the Block_buffer
extern UINT BlockCount;
// Open directory for EEPROM / firmware files
FRESULT openBinDir(MemoryType mt);
// Open directory for firmware files
FRESULT openFirmwareDir();
// Fetch file names and sizes into binFiles,
// starting at the provided index.
// Only files ending with ".bin" (case-insensitive)
// will be considered.
unsigned int fetchBinFiles(unsigned int index);
unsigned int fetchFirmwareFiles(unsigned int index);
const char* getFirmwareFileNameByIndex(unsigned int index);
// Open file indexed in binFiles and read the first BLOCK_LEN bytes
// Bootloader is skipped in firmware files
FRESULT openBinFile(MemoryType mt, unsigned int index);
FRESULT openFirmwareFile(unsigned int index);
struct VersionTag
{
char flavour[11];
const char* version;
const char* fork;
};
// Ensure flavour can hold FLAVOUR defined in target cmakefile
static_assert(sizeof(((VersionTag){}).flavour) >= sizeof(FLAVOUR), "VersionTag flavour size too small");
// Can be called right after openBinFile() to extract the version information
// from a firmware file
void extractFirmwareVersion(VersionTag* tag);
void getFileFirmwareVersion(VersionTag* tag);
// Read the next BLOCK_LEN bytes into 'Block_buffer'
// Check 'BlockCount' for # of bytes read
FRESULT readBinFile();
FRESULT readFirmwareFile();
// Close the previously opened file
FRESULT closeBinFile();
FRESULT closeFirmwareFile();
enum FlashCheckRes {
FC_UNCHECKED=0,
FC_OK,
FC_ERROR
};
FlashCheckRes checkFirmwareFile(unsigned int index, FlashCheckRes res);
void firmwareInitWrite(uint32_t index);
bool firmwareEraseBlock(uint32_t* progress);
bool firmwareWriteBlock(uint32_t* progress);
@@ -125,17 +125,28 @@
#define BLOCK_SIZE FF_MAX_SS
#define SD_TIMEOUT 300 /* 300ms */
#if defined(STM32H7) || defined(STM32H7RS) || defined(STM32F4)
#if defined(STM32F4)
extern uint32_t _sram;
extern uint32_t _heap_start;
#if defined(SDRAM)
#define _IS_DMA_BUFFER(addr) \
#define _IS_DMA_BUFFER(addr) \
(((((intptr_t)(addr)) & 0xFF000000) == (((intptr_t)&_sram) & 0xFF000000)) || \
((((intptr_t)(addr)) & 0xFC000000) == (((intptr_t)&_heap_start) & 0xFC000000)))
((((intptr_t)(addr)) & 0xFC000000) == \
(((intptr_t)&_heap_start) & 0xFC000000)))
#else
#define _IS_DMA_BUFFER(addr) \
((((intptr_t)(addr)) & 0xFF000000) == (((intptr_t)&_sram) & 0xFF000000))
#endif
#elif defined(STM32H7) || defined(STM32H7RS)
extern uint32_t _sram;
extern uint32_t _s_dram;
extern uint32_t _heap_start;
#define _IS_DMA_BUFFER(addr) \
(((((intptr_t)(addr)) & 0xFF000000) == (((intptr_t)&_sram) & 0xFF000000)) || \
((((intptr_t)(addr)) & 0xFFF60000) == \
(((intptr_t)&_s_dram) & 0xFFF60000)) || \
((((intptr_t)(addr)) & 0xFC000000) == \
(((intptr_t)&_heap_start) & 0xFC000000)))
#else
#define _IS_DMA_BUFFER(addr) (true)
#endif
@@ -343,14 +354,14 @@ static DRESULT _read_dma(BYTE* buff, DWORD sector, UINT count)
return RES_ERROR;
}
#if __CORTEX_M >= 0x07
SCB_CleanInvalidateDCache();
#endif
// Wait for the reading process to complete or a timeout to occur
uint32_t timeout = HAL_GetTick();
while((ReadStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT));
#if __CORTEX_M >= 0x07
SCB_CleanInvalidateDCache();
#endif
if (ReadStatus == 0) {
TRACE("SD read timeout (s:%u c:%u)", sector, (uint32_t)count);
return RES_ERROR;
@@ -30,6 +30,7 @@
#include "hal/gpio.h"
#include "sdcard_spi.h"
#include "hal.h"
#if defined(SD_SPI)
@@ -39,10 +40,10 @@
static const stm32_spi_t _sd_spi_hw = {
.SPIx = SD_SPI,
.SPI_GPIOx = SD_GPIO,
.SPI_Pins = SD_GPIO_PIN_SCK | SD_GPIO_PIN_MISO | SD_GPIO_PIN_MOSI,
.CS_GPIOx = SD_GPIO,
.CS_Pin = SD_GPIO_PIN_CS,
.SCK = SD_GPIO_PIN_SCK,
.MISO = SD_GPIO_PIN_MISO,
.MOSI = SD_GPIO_PIN_MOSI,
.CS = SD_GPIO_PIN_CS,
.DMA = SD_SPI_DMA,
.DMA_Channel = SD_SPI_DMA_CHANNEL,
.txDMA_Stream = SD_SPI_DMA_TX_STREAM,
@@ -62,6 +62,8 @@ set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:stm32_stdperiph>)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:stm32_stdperiph>)
if(NOT NATIVE_BUILD)
include_directories(targets/common/arm/stm32/f2)
#
# FreeRTOS port specific include
#
@@ -0,0 +1,30 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#define __CCMRAM
#define __DMA
#define __DMA_NO_CACHE
#define __IRAM
#define __SDRAM
#define __SDRAMFONTS
@@ -97,6 +97,8 @@ set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:stm32_stdperiph>)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:stm32_stdperiph>)
if(NOT NATIVE_BUILD)
include_directories(targets/common/arm/stm32/f4)
#
# FreeRTOS port specific include
#
@@ -0,0 +1,36 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#define __CCMRAM __attribute__((section(".ccm"), aligned(4)))
#define __DMA __attribute__((section(".ram"), aligned(4)))
#define __DMA_NO_CACHE __DMA
#define __IRAM
#if defined(SDRAM)
#define __SDRAM __attribute__((section(".sdram"), aligned(4)))
#define __SDRAMFONTS __attribute__((section(".sdram_fonts"), aligned(4)))
#else
#define __SDRAM
#define __SDRAMFONTS
#endif
@@ -19,10 +19,14 @@
* GNU General Public License for more details.
*/
#include "flash_driver.h"
#include "stm32_cmsis.h"
#include "stm32_hal.h"
uint32_t stm32_flash_get_size_kb()
#include <string.h>
static uint32_t stm32_flash_get_size_kb()
{
uint32_t flash_size_kb = *(const uint32_t*)FLASHSIZE_BASE;
return flash_size_kb;
@@ -30,7 +34,7 @@ uint32_t stm32_flash_get_size_kb()
#if defined(STM32F2) || defined(STM32F4)
uint32_t stm32_flash_get_sector(uint32_t address)
static uint32_t stm32_flash_get_sector(uint32_t address)
{
uint32_t sector;
uint32_t sector_addr = address & 0xFFFFF;
@@ -68,12 +72,12 @@ static uint32_t _flash_sector_address(uint32_t sector, uint32_t bank)
return addr;
}
uint32_t stm32_flash_get_sector_size(uint32_t sector)
static uint32_t stm32_flash_get_sector_size(uint32_t sector)
{
// bank 2
if (sector >= 12) sector -= 12;
// first 4: 16KB
// first 4: 16KB
if (sector < 4) return 16 * 1024;
// sector 4: 64KB
if (sector == 4) return 64 * 1024;
@@ -83,7 +87,7 @@ uint32_t stm32_flash_get_sector_size(uint32_t sector)
#elif defined(STM32H7) || defined(STM32H7RS)
uint32_t stm32_flash_get_sector(uint32_t address)
static uint32_t stm32_flash_get_sector(uint32_t address)
{
uint32_t sector_addr = address & 0xFFFFF;
return sector_addr / FLASH_SECTOR_SIZE;
@@ -99,7 +103,7 @@ static uint32_t _flash_sector_address(uint32_t sector, uint32_t bank)
return addr;
}
uint32_t stm32_flash_get_sector_size(uint32_t sector)
static uint32_t stm32_flash_get_sector_size(uint32_t sector)
{
(void)sector;
return FLASH_SECTOR_SIZE;
@@ -107,7 +111,7 @@ uint32_t stm32_flash_get_sector_size(uint32_t sector)
#endif
uint32_t stm32_flash_get_bank(uint32_t address)
static uint32_t stm32_flash_get_bank(uint32_t address)
{
#if defined(DUAL_BANK)
return ((address & 0x100000) != 0x100000) ? FLASH_BANK_1 : FLASH_BANK_2;
@@ -120,10 +124,10 @@ uint32_t stm32_flash_get_bank(uint32_t address)
#endif
}
void stm32_flash_unlock() { HAL_FLASH_Unlock(); }
void stm32_flash_lock() { HAL_FLASH_Lock(); }
static inline void stm32_flash_unlock() { HAL_FLASH_Unlock(); }
static inline void stm32_flash_lock() { HAL_FLASH_Lock(); }
int stm32_flash_erase_sector(uint32_t address)
static int stm32_flash_erase_sector(uint32_t address)
{
FLASH_EraseInitTypeDef eraseInit;
eraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
@@ -138,12 +142,16 @@ int stm32_flash_erase_sector(uint32_t address)
eraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3;
#endif
int ret = 0;
uint32_t sector_errors = 0;
stm32_flash_unlock();
if (HAL_FLASHEx_Erase(&eraseInit, &sector_errors) != HAL_OK) {
return -1;
ret = -1;
}
return 0;
stm32_flash_lock();
return ret;
}
#if defined(STM32H7)
@@ -160,23 +168,42 @@ int stm32_flash_erase_sector(uint32_t address)
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, *p_data)
#endif
int stm32_flash_program(uint32_t address, uint8_t* data, uint32_t len)
static int stm32_flash_program(uint32_t address, void* data, uint32_t len)
{
uint32_t* p_data = (uint32_t*)data;
uint32_t end_addr = address + len;
int ret = 0;
stm32_flash_unlock();
while (address < end_addr) {
if (_FLASH_PROGRAM(address, p_data) != HAL_OK) {
return -1;
ret = -1;
break;
}
address += sizeof(uint32_t) * FLASH_PROG_WORDS;
p_data += FLASH_PROG_WORDS;
}
stm32_flash_lock();
return ret;
}
static int stm32_flash_read(uint32_t address, void* data, uint32_t len)
{
memcpy(data, (void*)address, len);
return 0;
}
const etx_flash_driver_t stm32_flash_driver = {
.get_size_kb = stm32_flash_get_size_kb,
.get_sector = stm32_flash_get_sector,
.get_sector_size = stm32_flash_get_sector_size,
.erase_sector = stm32_flash_erase_sector,
.program = stm32_flash_program,
.read = stm32_flash_read,
};
// Legacy API
#define FLASH_PAGESIZE 256
@@ -215,6 +242,21 @@ uint32_t isFirmwareStart(const uint8_t * buffer)
if ((block[2] & 0xFFC00000) != 0x08000000) {
return 0;
}
#elif defined(STM32H7)
// // Stack pointer in D1 RAM
// if ((block[0] & 0xFFFC0000) != 0x24080000) {
// Stack pointer in DTCM RAM
if ((block[0] & 0xFFFF0000) != 0x20020000) {
return 0;
}
// First ISR pointer in FLASH
if ((block[1] & 0xF0000000) != 0x90000000) {
return 0;
}
// Second ISR pointer in FLASH
if ((block[2] & 0xF0000000) != 0xC0000000) {
return 0;
}
#else
// Stack pointer in RAM
if ((block[0] & 0xFFFC0000) != 0x20000000) {
@@ -23,24 +23,26 @@
#include <stdint.h>
uint32_t stm32_flash_get_size_kb();
uint32_t stm32_flash_get_sector(uint32_t address);
uint32_t stm32_flash_get_sector_size(uint32_t sector);
uint32_t stm32_flash_get_bank(uint32_t address);
#include "hal/flash_driver.h"
void stm32_flash_unlock();
void stm32_flash_lock();
// uint32_t stm32_flash_get_size_kb();
// uint32_t stm32_flash_get_sector(uint32_t address);
// uint32_t stm32_flash_get_sector_size(uint32_t sector);
// uint32_t stm32_flash_get_bank(uint32_t address);
int stm32_flash_erase_sector(uint32_t address);
int stm32_flash_program(uint32_t address, uint8_t* data, uint32_t len);
// void stm32_flash_unlock();
// void stm32_flash_lock();
// int stm32_flash_erase_sector(uint32_t address);
// int stm32_flash_program(uint32_t address, uint8_t* data, uint32_t len);
extern const etx_flash_driver_t stm32_flash_driver;
extern const void* stm32_flash_dfu_media;
// Legacy API
uint32_t isFirmwareStart(const uint8_t * buffer);
uint32_t isBootloaderStart(const uint8_t * buffer);
void unlockFlash();
void lockFlash();
void flashWrite(uint32_t* address, const uint32_t* buffer);
@@ -85,7 +85,9 @@ static void _fs_parse(STRUCT_HALL *hallBuffer, unsigned char ch)
hallBuffer->length = ch;
hallBuffer->dataIndex = 0;
hallBuffer->status = GET_DATA;
if (0 == hallBuffer->length) {
if(hallBuffer->length > HALLSTICK_BUFF_SIZE - 5) { // buffer size - header size (1 byte header + 1 byte ID + 1 byte length + 2 bytes CRC = 5 bytes)
hallBuffer->status = GET_START;
} else if (0 == hallBuffer->length) {
hallBuffer->status = GET_CHECKSUM;
hallBuffer->checkSum = 0;
}
@@ -142,6 +144,7 @@ static void flysky_gimbal_loop(void*)
switch (HallProtocol.hallID.hall_Id.receiverID) {
case TRANSFER_DIR_TXMCU:
case TRANSFER_DIR_RFMODULE:
if (HallProtocol.hallID.hall_Id.packetID ==
FLYSKY_HALL_RESP_TYPE_VALUES) {
int16_t* p_values = (int16_t*)HallProtocol.data;
@@ -22,8 +22,10 @@
#pragma once
#include "hal/serial_port.h"
#define HALLSTICK_BUFF_SIZE ( 512 )
// Max packet size = 1 byte header + 1 byte ID + 1 byte length + 25 bytes payload + 2 bytes CRC = 30 bytes
// using 32 bytes is more than enough
#define HALLSTICK_BUFF_SIZE ( 32 )
#define FLYSKY_HALL_BAUDRATE ( 921600 )
#define FLYSKY_HALL_CHANNEL_COUNT ( 4 )
@@ -2,89 +2,149 @@ set(CPU_FAMILY STM32)
set(MCU cortex-m7)
set(FPU_FLAGS "-mfloat-abi=hard -mfpu=fpv4-sp-d16")
if(NOT NATIVE_BUILD)
# STM32 HAL/LL library
set(STM32CUBE_DIR ${THIRDPARTY_DIR}/STM32H7xx_HAL_Driver)
include_directories(${STM32CUBE_DIR}/Inc)
add_library(stm32cube_ll OBJECT EXCLUDE_FROM_ALL
# LL drivers
${STM32CUBE_DIR}/Src/stm32h7xx_ll_gpio.c
${STM32CUBE_DIR}/Src/stm32h7xx_ll_fmc.c
${STM32CUBE_DIR}/Src/stm32h7xx_ll_tim.c
${STM32CUBE_DIR}/Src/stm32h7xx_ll_dma.c
${STM32CUBE_DIR}/Src/stm32h7xx_ll_usart.c
${STM32CUBE_DIR}/Src/stm32h7xx_ll_rcc.c
${STM32CUBE_DIR}/Src/stm32h7xx_ll_exti.c
${STM32CUBE_DIR}/Src/stm32h7xx_ll_sdmmc.c
${STM32CUBE_DIR}/Src/stm32h7xx_ll_adc.c
${STM32CUBE_DIR}/Src/stm32h7xx_ll_spi.c
${STM32CUBE_DIR}/Src/stm32h7xx_ll_usb.c
${STM32CUBE_DIR}/Src/stm32h7xx_ll_dma2d.c
# HAL drivers
${STM32CUBE_DIR}/Src/stm32h7xx_hal.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_pwr.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_pwr_ex.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_rcc.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_rcc_ex.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_rtc.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_i2c.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_i2c_ex.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_sd.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_dma.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_mdma.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_pcd.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_pcd_ex.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_qspi.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_flash.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_flash_ex.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_cortex.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_sdram.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_gpio.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_dsi.c
${STM32CUBE_DIR}/Src/stm32h7xx_hal_ltdc.c
)
# CMSIS library
set(CMSIS_DIR ${THIRDPARTY_DIR}/CMSIS)
include_directories(${CMSIS_DIR}/Include)
if(CPU_TYPE STREQUAL STM32H7RS)
include_directories(${CMSIS_DIR}/Device/ST/STM32H7RS/Include)
set(CMSIS_SRC
targets/common/arm/stm32/h7/system_stm32h7rsxx.c
)
else()
include_directories(${CMSIS_DIR}/Device/ST/STM32H7xx/Include)
set(CMSIS_SRC
targets/common/arm/stm32/h7/system_stm32h7xx.c
)
endif()
if(NOT NATIVE_BUILD)
if(CPU_TYPE STREQUAL STM32H7RS)
set(STM32CUBE_PREFIX stm32h7rsxx)
set(STM32CUBE_DIR ${THIRDPARTY_DIR}/STM32H7RS_HAL_Driver)
set(STM32CUBE_SRC_PREFIX ${STM32CUBE_DIR}/Src/${STM32CUBE_PREFIX})
set(STM32CUBE_SRC
# LL drivers
${STM32CUBE_SRC_PREFIX}_ll_gpio.c
${STM32CUBE_SRC_PREFIX}_ll_fmc.c
${STM32CUBE_SRC_PREFIX}_ll_tim.c
${STM32CUBE_SRC_PREFIX}_ll_dma.c
${STM32CUBE_SRC_PREFIX}_ll_usart.c
${STM32CUBE_SRC_PREFIX}_ll_rcc.c
${STM32CUBE_SRC_PREFIX}_ll_exti.c
${STM32CUBE_SRC_PREFIX}_ll_sdmmc.c
${STM32CUBE_SRC_PREFIX}_ll_adc.c
${STM32CUBE_SRC_PREFIX}_ll_spi.c
${STM32CUBE_SRC_PREFIX}_ll_usb.c
${STM32CUBE_SRC_PREFIX}_ll_dma2d.c
# HAL drivers
${STM32CUBE_SRC_PREFIX}_hal.c
${STM32CUBE_SRC_PREFIX}_hal_pwr.c
${STM32CUBE_SRC_PREFIX}_hal_pwr_ex.c
${STM32CUBE_SRC_PREFIX}_hal_rcc.c
${STM32CUBE_SRC_PREFIX}_hal_rcc_ex.c
${STM32CUBE_SRC_PREFIX}_hal_rtc.c
${STM32CUBE_SRC_PREFIX}_hal_i2c.c
${STM32CUBE_SRC_PREFIX}_hal_i2c_ex.c
${STM32CUBE_SRC_PREFIX}_hal_sd.c
${STM32CUBE_SRC_PREFIX}_hal_dma.c
${STM32CUBE_SRC_PREFIX}_hal_pcd.c
${STM32CUBE_SRC_PREFIX}_hal_pcd_ex.c
${STM32CUBE_SRC_PREFIX}_hal_xspi.c
${STM32CUBE_SRC_PREFIX}_hal_flash.c
${STM32CUBE_SRC_PREFIX}_hal_flash_ex.c
${STM32CUBE_SRC_PREFIX}_hal_cortex.c
${STM32CUBE_SRC_PREFIX}_hal_sdram.c
${STM32CUBE_SRC_PREFIX}_hal_gpio.c
${STM32CUBE_SRC_PREFIX}_hal_ltdc.c
${STM32CUBE_SRC_PREFIX}_hal_lptim.c
)
else()
set(STM32CUBE_PREFIX stm32h7xx)
set(STM32CUBE_DIR ${THIRDPARTY_DIR}/STM32H7xx_HAL_Driver)
set(STM32CUBE_SRC_PREFIX ${STM32CUBE_DIR}/Src/${STM32CUBE_PREFIX})
set(STM32CUBE_SRC
# LL drivers
${STM32CUBE_SRC_PREFIX}_ll_gpio.c
${STM32CUBE_SRC_PREFIX}_ll_fmc.c
${STM32CUBE_SRC_PREFIX}_ll_tim.c
${STM32CUBE_SRC_PREFIX}_ll_dma.c
${STM32CUBE_SRC_PREFIX}_ll_usart.c
${STM32CUBE_SRC_PREFIX}_ll_rcc.c
${STM32CUBE_SRC_PREFIX}_ll_exti.c
${STM32CUBE_SRC_PREFIX}_ll_sdmmc.c
${STM32CUBE_SRC_PREFIX}_ll_adc.c
${STM32CUBE_SRC_PREFIX}_ll_spi.c
${STM32CUBE_SRC_PREFIX}_ll_usb.c
${STM32CUBE_SRC_PREFIX}_ll_dma2d.c
# HAL drivers
${STM32CUBE_SRC_PREFIX}_hal.c
${STM32CUBE_SRC_PREFIX}_hal_pwr.c
${STM32CUBE_SRC_PREFIX}_hal_pwr_ex.c
${STM32CUBE_SRC_PREFIX}_hal_rcc.c
${STM32CUBE_SRC_PREFIX}_hal_rcc_ex.c
${STM32CUBE_SRC_PREFIX}_hal_rtc.c
${STM32CUBE_SRC_PREFIX}_hal_i2c.c
${STM32CUBE_SRC_PREFIX}_hal_i2c_ex.c
${STM32CUBE_SRC_PREFIX}_hal_sd.c
${STM32CUBE_SRC_PREFIX}_hal_dma.c
${STM32CUBE_SRC_PREFIX}_hal_mdma.c
${STM32CUBE_SRC_PREFIX}_hal_pcd.c
${STM32CUBE_SRC_PREFIX}_hal_pcd_ex.c
${STM32CUBE_SRC_PREFIX}_hal_qspi.c
${STM32CUBE_SRC_PREFIX}_hal_flash.c
${STM32CUBE_SRC_PREFIX}_hal_flash_ex.c
${STM32CUBE_SRC_PREFIX}_hal_cortex.c
${STM32CUBE_SRC_PREFIX}_hal_sdram.c
${STM32CUBE_SRC_PREFIX}_hal_gpio.c
${STM32CUBE_SRC_PREFIX}_hal_dsi.c
${STM32CUBE_SRC_PREFIX}_hal_ltdc.c
)
endif()
# STM32 HAL/LL library
include_directories(${STM32CUBE_DIR}/Inc)
add_library(stm32cube_ll OBJECT EXCLUDE_FROM_ALL ${STM32CUBE_SRC})
target_compile_definitions(stm32cube_ll PRIVATE USE_FULL_LL_DRIVER)
target_include_directories(stm32cube_ll PRIVATE
${THIRDPARTY_DIR}/CMSIS/Device/ST/STM32H7xx/Include
${THIRDPARTY_DIR}/CMSIS/Include)
set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:stm32cube_ll>)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:stm32cube_ll>)
endif()
# StdPeriph library
set(STM32LIB_DIR ${THIRDPARTY_DIR})
include_directories(${STM32LIB_DIR}/CMSIS/Device/ST/STM32H7xx/Include)
include_directories(${STM32LIB_DIR}/CMSIS/Include)
add_definitions(-DSTM32H7)
set(STM32_STDPERIPH_SRC
targets/common/arm/stm32/h7/system_stm32h7xx.c
)
if(CPU_TYPE STREQUAL STM32H7RS)
add_definitions(-DSTM32H7RS)
else()
add_definitions(-DSTM32H7)
endif()
if(CPU_TYPE_FULL STREQUAL STM32H750Ix)
set(STM32_STDPERIPH_SRC ${STM32_STDPERIPH_SRC}
set(CMSIS_SRC ${CMSIS_SRC}
boards/generic_stm32/startup/startup_stm32h750xx.s
)
)
elseif(CPU_TYPE_FULL STREQUAL STM32H747Ix)
set(STM32_STDPERIPH_SRC ${STM32_STDPERIPH_SRC}
set(CMSIS_SRC ${CMSIS_SRC}
boards/generic_stm32/startup/startup_stm32h747xx.s
)
elseif(CPU_TYPE_FULL STREQUAL STM32H7S7xx)
set(CMSIS_SRC ${CMSIS_SRC}
boards/generic_stm32/startup/startup_stm32h7s7xx.s
)
else()
message("### ERROR ####: ${CPU_TYPE_FULL}")
endif()
add_library(stm32_stdperiph OBJECT EXCLUDE_FROM_ALL
${STM32_STDPERIPH_SRC}
add_library(cmsis OBJECT EXCLUDE_FROM_ALL
${CMSIS_SRC}
)
set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:stm32_stdperiph>)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:stm32_stdperiph>)
set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:cmsis>)
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:cmsis>)
if(NOT NATIVE_BUILD)
include_directories(targets/common/arm/stm32/h7)
#
# FreeRTOS port specific include
#
@@ -112,4 +172,9 @@ if(NOT NATIVE_BUILD)
# System and FreeRTOS port files
#
set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:freertos>)
#
# Firmware description
#
set(FIRMWARE_SRC ${FIRMWARE_SRC} fw_desc.c)
endif()
@@ -0,0 +1,31 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#pragma once
#define __CCMRAM __attribute__((section(".ccm"), aligned(4)))
#define __DMA __attribute__((section(".ram"), aligned(4)))
#define __DMA_NO_CACHE __attribute__((section(".dram"), aligned(4)))
#define __IRAM __attribute__((section(".iram")))
#define __SDRAM __attribute__((section(".sdram"), aligned(4)))
#define __SDRAMFONTS __attribute__((section(".sdram_fonts"), aligned(4)))
@@ -0,0 +1,285 @@
/**
******************************************************************************
* @file system_stm32h7rsxx.c
* @author MCD Application Team
* @brief CMSIS Cortex-M7 Device Peripheral Access Layer System Source File
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*
* 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_stm32h7rsxx.s" file.
*
* - SystemCoreClock variable: Contains the core clock (sys_cpu_ck), 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.
*
* After each device reset the HSI (64 MHz) is used as system clock source.
* Then SystemInit() function is called, in "startup_stm32h7rsxx.s" file, to
* optionally configure the system clock before to branch to main program.
*
*=============================================================================
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup STM32H7RSxx_System
* @{
*/
/** @addtogroup STM32H7RSxx_System_Private_Includes
* @{
*/
#include "stm32h7rsxx.h"
#include <math.h>
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_Defines
* @{
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE 24000000UL /*!< Value of the High-Speed External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE 64000000UL /*!< Value of the High-Speed Internal oscillator in Hz */
#endif /* HSI_VALUE */
#if !defined (CSI_VALUE)
#define CSI_VALUE 4000000UL /*!< Value of the Low-power Internal oscillator in Hz */
#endif /* CSI_VALUE */
/*!< The VTOR location information is based on information from the linker with a dependency
on the IDE, the cortex register is updated using the INTVECT_START.
*/
#if defined(__ICCARM__)
extern uint32_t __vector_table;
#define INTVECT_START ((uint32_t)& __vector_table)
#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
extern void * __Vectors;
#define INTVECT_START ((uint32_t) & __Vectors)
#elif defined(__GNUC__)
extern void * g_pfnVectors;
#define INTVECT_START ((uint32_t)& g_pfnVectors)
#endif /* __ICCARM__*/
/******************************************************************************/
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_Variables
* @{
*/
/* The SystemCoreClock variable is updated in two ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) 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 first function listed above, since SystemCoreClock
variable is updated automatically.
*/
uint32_t SystemCoreClock = HSI_VALUE;
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @addtogroup STM32H7RSxx_System_Private_Functions
* @{
*/
/**
* @brief Setup the microcontroller system.
* @retval None
*/
void SystemInit(void)
{
/* Configure the Vector Table location -------------------------------------*/
SCB->VTOR = INTVECT_START;
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 20U)|(3UL << 22U)); /* set CP10 and CP11 Full Access */
#endif
}
/**
* @brief Update SystemCoreClock variable according to RCC registers values.
* The SystemCoreClock variable contains the core clock (sys_cpu_ck), it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock 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 CSI, SystemCoreClock will contain the CSI_VALUE(**)
*
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***)
*
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSI_VALUE(*)
* or CSI_VALUE(**) or HSE_VALUE(***) multiplied/divided by the PLL factors.
*
* (*) HSI_VALUE is a constant defined in stm32h7rsxx_hal.h file (default value
* 64 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (**) CSI_VALUE is a constant defined in stm32h7rsxx_hal.h file (default value
* 4 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (***) HSE_VALUE is a constant defined in stm32h7rsxx_hal.h file (default value
* 24 MHz), 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.
*
* @retval None
*/
void SystemCoreClockUpdate(void)
{
uint32_t sysclk, hsivalue, pllsource, pllm, pllp, core_presc;
float_t pllfracn, pllvco;
/* Get SYSCLK source -------------------------------------------------------*/
switch (RCC->CFGR & RCC_CFGR_SWS)
{
case 0x00: /* HSI used as system clock source (default after reset) */
sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> RCC_CR_HSIDIV_Pos));
break;
case 0x08: /* CSI used as system clock source */
sysclk = CSI_VALUE;
break;
case 0x10: /* HSE used as system clock source */
sysclk = HSE_VALUE;
break;
case 0x18: /* PLL1 used as system clock source */
/* PLL1_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN
SYSCLK = PLL1_VCO / PLL1R
*/
pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC);
pllm = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1) >> RCC_PLLCKSELR_DIVM1_Pos) ;
if ((RCC->PLLCFGR & RCC_PLLCFGR_PLL1FRACEN) != 0U)
{
pllfracn = (float_t)(uint32_t)(((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN)>> RCC_PLL1FRACR_FRACN_Pos));
}
else
{
pllfracn = (float_t)0U;
}
if (pllm != 0U)
{
switch (pllsource)
{
case 0x02: /* HSE used as PLL1 clock source */
pllvco = ((float_t)HSE_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + (pllfracn/(float_t)0x2000) +(float_t)1 );
break;
case 0x01: /* CSI used as PLL1 clock source */
pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + (pllfracn/(float_t)0x2000) +(float_t)1 );
break;
case 0x00: /* HSI used as PLL1 clock source */
default:
hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> RCC_CR_HSIDIV_Pos));
pllvco = ( (float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + (pllfracn/(float_t)0x2000) +(float_t)1 );
break;
}
pllp = (((RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVP) >> RCC_PLL1DIVR1_DIVP_Pos) + 1U ) ;
sysclk = (uint32_t)(float_t)(pllvco/(float_t)pllp);
}
else
{
sysclk = 0U;
}
break;
default: /* Unexpected, default to HSI used as system clock source (default after reset) */
sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> RCC_CR_HSIDIV_Pos));
break;
}
/* system clock frequency : CM7 CPU frequency */
core_presc = (RCC->CDCFGR & RCC_CDCFGR_CPRE);
if (core_presc >= 8U)
{
SystemCoreClock = (sysclk >> (core_presc - RCC_CDCFGR_CPRE_3 + 1U));
}
else
{
SystemCoreClock = sysclk;
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
@@ -178,7 +178,10 @@
* @param None
* @retval None
*/
void SystemInit (void)
#define BOOTSTRAP __attribute__((section(".bootstrap")))
BOOTSTRAP void SystemInit (void)
{
#if defined (DATA_IN_D2_SRAM)
__IO uint32_t tmpreg;
@@ -481,21 +484,21 @@ void I2C2_EV_IRQHandler(void){asm("BKPT");}
void I2C2_ER_IRQHandler(void){asm("BKPT");}
void SPI1_IRQHandler(void){asm("BKPT");}
void SPI2_IRQHandler(void){asm("BKPT");}
void EXTI15_10_IRQHandler(void){asm("BKPT");}
//void EXTI15_10_IRQHandler(void){asm("BKPT");}
void RTC_Alarm_IRQHandler(void){asm("BKPT");}
void TIM8_CC_IRQHandler(void){asm("BKPT");}
void DMA1_Stream7_IRQHandler(void){asm("BKPT");}
//void DMA1_Stream7_IRQHandler(void){asm("BKPT");}
void FMC_IRQHandler(void){asm("BKPT");}
void TIM5_IRQHandler(void){asm("BKPT");}
void SPI3_IRQHandler(void){asm("BKPT");}
void UART5_IRQHandler(void){asm("BKPT");}
//void UART5_IRQHandler(void){asm("BKPT");}
void TIM7_IRQHandler(void){asm("BKPT");}
//void DMA2_Stream0_IRQHandler(void){asm("BKPT");}
void DMA2_Stream2_IRQHandler(void){asm("BKPT");}
void DMA2_Stream3_IRQHandler(void){asm("BKPT");}
//void DMA2_Stream4_IRQHandler(void){asm("BKPT");}
void ETH_IRQHandler(void){asm("BKPT");}
void ETH_WKUP_IRQHandler(void){asm("BKPT");}
//void ETH_WKUP_IRQHandler(void){asm("BKPT");}
void FDCAN_CAL_IRQHandler(void){asm("BKPT");}
void DMA2_Stream5_IRQHandler(void){asm("BKPT");}
void DMA2_Stream6_IRQHandler(void){asm("BKPT");}
@@ -510,7 +513,7 @@ void DCMI_IRQHandler(void){asm("BKPT");}
void CRYP_IRQHandler(void){asm("BKPT");}
void HASH_RNG_IRQHandler(void){asm("BKPT");}
void FPU_IRQHandler(void){asm("BKPT");}
void UART8_IRQHandler(void){asm("BKPT");}
//void UART8_IRQHandler(void){asm("BKPT");}
void SPI4_IRQHandler(void){asm("BKPT");}
void SPI5_IRQHandler(void){asm("BKPT");}
void SPI6_IRQHandler(void){asm("BKPT");}
@@ -541,7 +544,6 @@ void DFSDM1_FLT2_IRQHandler(void){asm("BKPT");}
void DFSDM1_FLT3_IRQHandler(void){asm("BKPT");}
void SAI3_IRQHandler(void){asm("BKPT");}
void SWPMI1_IRQHandler(void){asm("BKPT");}
void TIM15_IRQHandler(void){asm("BKPT");}
void TIM16_IRQHandler(void){asm("BKPT");}
void MDIOS_WKUP_IRQHandler(void){asm("BKPT");}
void MDIOS_IRQHandler(void){asm("BKPT");}
@@ -27,6 +27,7 @@
void pwrInit()
{
#if defined(SD_PRESENT_GPIO)
gpio_init(SD_PRESENT_GPIO, GPIO_IN_PU, GPIO_PIN_SPEED_LOW);
#endif
@@ -37,13 +38,13 @@ void pwrInit()
#endif
// Internal module power
#if defined(HARDWARE_INTERNAL_MODULE)
#if defined(HARDWARE_INTERNAL_MODULE) && defined(INTMODULE_PWR_GPIO)
gpio_init(INTMODULE_PWR_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
INTERNAL_MODULE_OFF();
#endif
// External module power
#if defined(HARDWARE_EXTERNAL_MODULE)
#if defined(HARDWARE_EXTERNAL_MODULE) && defined(EXTMODULE_PWR_GPIO)
gpio_init(EXTMODULE_PWR_GPIO, GPIO_OUT, GPIO_PIN_SPEED_LOW);
EXTERNAL_MODULE_PWR_OFF();
#endif

Some files were not shown because too many files have changed in this diff Show More