diff --git a/CMakeLists.txt b/CMakeLists.txt index cc403535d5e..a62444aaa8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,9 @@ else() set(LUA NO) endif() +option(DISABLE_COMPANION "Disable building companion and simulators" OFF) + +if(NOT DISABLE_COMPANION) find_package(Qt5Core) find_package(Qt5Widgets) find_package(Qt5Xml) @@ -150,6 +153,7 @@ if(Qt5Core_FOUND OR FOX_FOUND) message(STATUS "SDL not found! Simulator audio, and joystick inputs, will not work.") endif() endif() +endif() # Check for a file that is typically left from a OpenTX 2.1 build and abort if found if (EXISTS ${RADIO_SRC_DIRECTORY}/stamp.h OR EXISTS ${RADIO_SRC_DIRECTORY}/translations/en.h) @@ -180,6 +184,6 @@ endif() add_subdirectory(${RADIO_SRC_DIRECTORY}) -if(Qt5Core_FOUND) +if(Qt5Core_FOUND AND NOT DISABLE_COMPANION) add_subdirectory(${COMPANION_SRC_DIRECTORY}) endif() diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 414facee5c9..987dd83aed0 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -486,9 +486,9 @@ if(NOT MSVC) endif() - if(PCB STREQUAL X9D OR PCB STREQUAL X9D+ OR PCB STREQUAL X9E OR PCB STREQUAL X7) - add_subdirectory(targets/${TARGET_DIR}/bootloader) - include_directories(${CMAKE_CURRENT_BINARY_DIR}/targets/${TARGET_DIR}/bootloader) + if(PCB STREQUAL X9D OR PCB STREQUAL X9D+ OR PCB STREQUAL X9E OR PCB STREQUAL X7 OR PCB STREQUAL X10 OR PCB STREQUAL X12S) + add_subdirectory(targets/common/arm/stm32/bootloader) + include_directories(${CMAKE_CURRENT_BINARY_DIR}/targets/common/arm/stm32/bootloader) set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} bootloader) elseif(OPENRC_BOOTLOADER) # We fetch Mike's bootloader as it is not included inside OpenTX diff --git a/radio/src/bitmaps/480x272/CMakeLists.txt b/radio/src/bitmaps/480x272/CMakeLists.txt index 0b5ac853abe..26cfd2d4453 100644 --- a/radio/src/bitmaps/480x272/CMakeLists.txt +++ b/radio/src/bitmaps/480x272/CMakeLists.txt @@ -10,7 +10,9 @@ if(PCB STREQUAL X12S) add_bitmaps_target(x12s_themes_bitmaps "${RADIO_SRC_DIRECTORY}/gui/480x272/themes/*.png" 480 5/6/5) add_bitmaps_target(x12s_fonts ${RADIO_SRC_DIRECTORY}/fonts/480x272/*.png 480 8bits) add_bitmaps_target(x12s_volume_masks ${RADIO_SRC_DIRECTORY}/bitmaps/480x272/volume/*.png 480 8bits) - add_dependencies(x12s_bitmaps x12s_calibration_bitmaps x12s_button_bitmaps x12s_alpha_bitmaps x12s_alpha_calibration_bitmaps x12s_masks x12s_slider_masks x12s_layouts_masks x12s_themes_bitmaps x12s_fonts x12s_volume_masks) + add_bitmaps_target(x12s_bootloader_bitmaps ${RADIO_SRC_DIRECTORY}/bitmaps/480x272/bootloader/bmp_*.png 480 5/6/5) + add_bitmaps_target(x12s_bootloader_icons ${RADIO_SRC_DIRECTORY}/bitmaps/480x272/bootloader/icon_*.png 480 8bits) + add_dependencies(x12s_bitmaps x12s_calibration_bitmaps x12s_button_bitmaps x12s_alpha_bitmaps x12s_alpha_calibration_bitmaps x12s_masks x12s_slider_masks x12s_layouts_masks x12s_themes_bitmaps x12s_fonts x12s_volume_masks x12s_bootloader_bitmaps x12s_bootloader_icons) else() add_bitmaps_target(x10_bitmaps "${RADIO_SRC_DIRECTORY}/bitmaps/480x272/bmp_*.png" 480 5/6/5-R) add_bitmaps_target(x10_calibration_bitmaps "${RADIO_SRC_DIRECTORY}/bitmaps/480x272/calibration/bmp_*.png" 480 5/6/5-R) @@ -23,5 +25,7 @@ else() add_bitmaps_target(x10_themes_bitmaps "${RADIO_SRC_DIRECTORY}/gui/480x272/themes/*.png" 480 5/6/5-R) add_bitmaps_target(x10_fonts ${RADIO_SRC_DIRECTORY}/fonts/480x272/*.png 480 8bits) add_bitmaps_target(x10_volume_masks ${RADIO_SRC_DIRECTORY}/bitmaps/480x272/volume/*.png 480 8bits) - add_dependencies(x10_bitmaps x10_calibration_bitmaps x10_button_bitmaps x10_alpha_bitmaps x10_alpha_calibration_bitmaps x10_masks x10_slider_masks x10_layouts_masks x10_themes_bitmaps x10_fonts x10_volume_masks) + add_bitmaps_target(x10_bootloader_bitmaps ${RADIO_SRC_DIRECTORY}/bitmaps/480x272/bootloader/bmp_*.png 480 5/6/5-R) + add_bitmaps_target(x10_bootloader_icons ${RADIO_SRC_DIRECTORY}/bitmaps/480x272/bootloader/icon_*.png 480 8bits) + add_dependencies(x10_bitmaps x10_calibration_bitmaps x10_button_bitmaps x10_alpha_bitmaps x10_alpha_calibration_bitmaps x10_masks x10_slider_masks x10_layouts_masks x10_themes_bitmaps x10_fonts x10_volume_masks x10_bootloader_bitmaps x10_bootloader_icons) endif() diff --git a/radio/src/bitmaps/480x272/bootloader/bmp_plug_usb.png b/radio/src/bitmaps/480x272/bootloader/bmp_plug_usb.png new file mode 100644 index 00000000000..0f6015747a2 Binary files /dev/null and b/radio/src/bitmaps/480x272/bootloader/bmp_plug_usb.png differ diff --git a/radio/src/bitmaps/480x272/bootloader/bmp_usb_plugged.png b/radio/src/bitmaps/480x272/bootloader/bmp_usb_plugged.png new file mode 100644 index 00000000000..f374f5b77e4 Binary files /dev/null and b/radio/src/bitmaps/480x272/bootloader/bmp_usb_plugged.png differ diff --git a/radio/src/bitmaps/480x272/bootloader/icon_error.png b/radio/src/bitmaps/480x272/bootloader/icon_error.png new file mode 100644 index 00000000000..52148e6bee4 Binary files /dev/null and b/radio/src/bitmaps/480x272/bootloader/icon_error.png differ diff --git a/radio/src/bitmaps/480x272/bootloader/icon_exit.png b/radio/src/bitmaps/480x272/bootloader/icon_exit.png new file mode 100644 index 00000000000..e3c440d844c Binary files /dev/null and b/radio/src/bitmaps/480x272/bootloader/icon_exit.png differ diff --git a/radio/src/bitmaps/480x272/bootloader/icon_file.png b/radio/src/bitmaps/480x272/bootloader/icon_file.png new file mode 100644 index 00000000000..515ed0e39d4 Binary files /dev/null and b/radio/src/bitmaps/480x272/bootloader/icon_file.png differ diff --git a/radio/src/bitmaps/480x272/bootloader/icon_flash.png b/radio/src/bitmaps/480x272/bootloader/icon_flash.png new file mode 100644 index 00000000000..a91436250e8 Binary files /dev/null and b/radio/src/bitmaps/480x272/bootloader/icon_flash.png differ diff --git a/radio/src/bitmaps/480x272/bootloader/icon_ok.png b/radio/src/bitmaps/480x272/bootloader/icon_ok.png new file mode 100644 index 00000000000..35dfe76035f Binary files /dev/null and b/radio/src/bitmaps/480x272/bootloader/icon_ok.png differ diff --git a/radio/src/bitmaps/480x272/bootloader/icon_sd.png b/radio/src/bitmaps/480x272/bootloader/icon_sd.png new file mode 100644 index 00000000000..360ce328f26 Binary files /dev/null and b/radio/src/bitmaps/480x272/bootloader/icon_sd.png differ diff --git a/radio/src/definitions.h b/radio/src/definitions.h index 740e6a0de81..02ff26e61e9 100644 --- a/radio/src/definitions.h +++ b/radio/src/definitions.h @@ -29,7 +29,7 @@ #if defined(SIMU) #define __DMA -#elif defined(STM32F4) && !defined(BOOT) +#elif (defined(STM32F4) && !defined(BOOT)) || defined(PCBHORUS) #define __DMA __attribute__((section(".ram"), aligned(32))) #else #define __DMA __ALIGNED diff --git a/radio/src/fonts.h b/radio/src/fonts.h index f9430b8cb68..4a134e58f02 100644 --- a/radio/src/fonts.h +++ b/radio/src/fonts.h @@ -23,8 +23,13 @@ #if defined(COLORLCD) +#if !defined(BOOT) extern const uint16_t * const fontspecsTable[16]; extern const uint8_t * const fontsTable[16]; +#else +extern const uint16_t * const fontspecsTable[1]; +extern const uint8_t * const fontsTable[1]; +#endif #if defined(PCBHORUS) extern BitmapBuffer * fontCache[2]; diff --git a/radio/src/gui/480x272/bitmapbuffer.cpp b/radio/src/gui/480x272/bitmapbuffer.cpp index 6060a728fd9..204249e9904 100644 --- a/radio/src/gui/480x272/bitmapbuffer.cpp +++ b/radio/src/gui/480x272/bitmapbuffer.cpp @@ -320,10 +320,12 @@ void BitmapBuffer::drawSizedText(coord_t x, coord_t y, const char * s, uint8_t l const uint16_t * fontspecs = fontspecsTable[fontindex]; BitmapBuffer * fontcache = NULL; - if (flags & RIGHT) + if (flags & RIGHT) { INCREMENT_POS(-width); - else if (flags & CENTERED) + } + else if (flags & CENTERED) { INCREMENT_POS(-width/2); + } coord_t & pos = (flags & VERTICAL) ? y : x; @@ -380,11 +382,11 @@ void BitmapBuffer::drawSizedText(coord_t x, coord_t y, const char * s, uint8_t l bool setpos = false; const coord_t orig_pos = pos; while (len--) { - unsigned char c; - if (flags & ZCHAR) - c = idx2char(*s); - else - c = pgm_read_byte(s); +#if defined(BOOT) + unsigned char c = *s; +#else + unsigned char c = (flags & ZCHAR) ? idx2char(*s) : *s; +#endif if (setpos) { pos = c; setpos = false; diff --git a/radio/src/gui/480x272/fonts.cpp b/radio/src/gui/480x272/fonts.cpp index ea953f059b9..75cc2b98352 100644 --- a/radio/src/gui/480x272/fonts.cpp +++ b/radio/src/gui/480x272/fonts.cpp @@ -20,6 +20,7 @@ #include "opentx.h" +#if !defined(BOOT) const uint16_t font_tinsize_specs[] = { #include "font_tinsize.specs" }; @@ -35,6 +36,7 @@ const uint16_t font_smlsize_specs[] = { const pm_uchar font_smlsize[] = { #include "font_smlsize.lbm" }; +#endif const uint16_t font_stdsize_specs[] = { #include "font_stdsize.specs" @@ -44,6 +46,7 @@ const pm_uchar font_stdsize[] = { #include "font_stdsize.lbm" }; +#if !defined(BOOT) const uint16_t font_midsize_specs[] = { #include "font_midsize.specs" }; @@ -75,7 +78,9 @@ const uint16_t font_stdsizebold_specs[] = { const pm_uchar font_stdsizebold[] = { #include "font_stdsizebold.lbm" }; +#endif +#if !defined(BOOT) const uint16_t * const fontspecsTable[16] = { font_stdsize_specs, font_tinsize_specs, font_smlsize_specs, font_midsize_specs, font_dblsize_specs, font_xxlsize_specs, font_stdsize_specs, font_stdsize_specs, font_stdsizebold_specs, font_tinsize_specs, font_smlsize_specs, font_midsize_specs, font_dblsize_specs, font_xxlsize_specs, font_stdsize_specs, font_stdsize_specs @@ -85,6 +90,10 @@ const uint8_t * const fontsTable[16] = { font_stdsize, font_tinsize, font_smlsize, font_midsize, font_dblsize, font_xxlsize, font_stdsize, font_stdsize, font_stdsizebold, font_tinsize, font_smlsize, font_midsize, font_dblsize, font_xxlsize, font_stdsize, font_stdsize }; +#else +const uint16_t * const fontspecsTable[1] = { font_stdsize_specs }; +const uint8_t * const fontsTable[1] = { font_stdsize }; +#endif BitmapBuffer * fontCache[2] = { NULL, NULL }; diff --git a/radio/src/gui/480x272/lcd.cpp b/radio/src/gui/480x272/lcd.cpp index a6d69df10cf..88384eb6a35 100644 --- a/radio/src/gui/480x272/lcd.cpp +++ b/radio/src/gui/480x272/lcd.cpp @@ -21,6 +21,7 @@ #include #include #include "opentx.h" +#include "strhelpers.h" #if defined(SIMU) display_t displayBuf[DISPLAY_BUFFER_SIZE]; @@ -103,11 +104,12 @@ int getTextWidth(const char * s, int len, LcdFlags flags) int result = 0; for (int i=0; len==0 || i> 8) +#else +#define FONTSIZE(flags) STDSIZE +#define FONTINDEX(flags) STDSIZE_INDEX +#endif #define TIMEBLINK 0x1000 #define TIMEHOUR 0x2000 @@ -134,6 +140,13 @@ inline void lcdDrawSizedText(coord_t x, coord_t y, const pm_char * s, uint8_t le void lcdDrawHexNumber(coord_t x, coord_t y, uint32_t val, LcdFlags mode=0); void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags flags=0, uint8_t len=0, const char * prefix=NULL, const char * suffix=NULL); +#if !defined(BOOT) + +#define putstime_t int32_t + +void drawRtcTime(coord_t x, coord_t y, LcdFlags att=0); +void drawTimer(coord_t x, coord_t y, putstime_t tme, LcdFlags att=0); + void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att); void putsStickName(coord_t x, coord_t y, uint8_t idx, LcdFlags att=0); void drawSwitch(coord_t x, coord_t y, swsrc_t swtch, LcdFlags flags=0); @@ -145,10 +158,7 @@ void drawTrimMode(coord_t x, coord_t y, uint8_t phase, uint8_t idx, LcdFlags att #define putsChn(x, y, idx, att) drawSource(x, y, MIXSRC_CH1+idx-1, att) void putsChnLetter(coord_t x, coord_t y, uint8_t idx, LcdFlags attr); -#define putstime_t int32_t - -void drawRtcTime(coord_t x, coord_t y, LcdFlags att=0); -void drawTimer(coord_t x, coord_t y, putstime_t tme, LcdFlags att=0); +#endif // !BOOT #define SOLID 0xff #define DOTTED 0x55 diff --git a/radio/src/loadboot.cpp b/radio/src/loadboot.cpp deleted file mode 100644 index ae687e98051..00000000000 --- a/radio/src/loadboot.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * 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 "opentx.h" - -#if defined(PCBSKY9X) - #include "AT91SAM3S4.h" -#else - #include "targets/taranis/board.h" -#endif - -#if defined(PCBTARANIS) -void bwdt_reset() -{ - IWDG->KR = 0xAAAA; // reload -} -#endif - -#if defined(PCBTARANIS) -// TODO needed? -__attribute__ ((section(".bootrodata"), used)) -void _bootStart(void); -#endif - -#if defined(PCBTARANIS) -__attribute__ ((section(".isr_boot_vector"), used)) -const uint32_t BootVectors[] = { - (uint32_t) &_estack, - (uint32_t) (void (*)(void)) ((unsigned long) &_bootStart) }; -#endif - -#if defined(PCBTARANIS) -__attribute__ ((section(".bootrodata.*"), used)) -#elif defined(PCBSKY9X) -__attribute__ ((section(".bootrodata"), used)) -#endif - -const uint8_t BootCode[] = { -#include "bootloader.lbm" -}; - -#if defined(PCBTARANIS) -__attribute__ ((section(".bootrodata"), used)) -void _bootStart() -{ -#if defined(PCBX9E) - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIODEN; -#else - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIODEN; -#endif - - // these two NOPs are needed (see STM32F errata sheet) before the peripheral - // register can be written after the peripheral clock was enabled - __ASM volatile ("nop"); - __ASM volatile ("nop"); - - // Turn soft power ON now, but only if we got started because of the watchdog - // or software reset. If the radio was started by user pressing the power button - // then that button is providing power and we don't need to enable it here. - // - // If we were to turn it on here indiscriminately, then the radio can go into the - // power on/off loop after being powered off by the user. (issue #2790) - if (WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) { - GPIOD->BSRRL = 1; // set PWR_ON_GPIO_PIN pin to 1 - GPIOD->MODER = (GPIOD->MODER & 0xFFFFFFFC) | 1; // General purpose output mode - } - - // TRIMS_GPIO_PIN_LHR is on PG0 on X9E and on PE3 on Taranis - // TRIMS_GPIO_PIN_RHL is on PC1 on all versions - // turn on pull-ups on trim keys - GPIOC->PUPDR = 0x00000004; -#if defined(PCBX9E) - GPIOG->PUPDR = 0x00000001; -#else - GPIOE->PUPDR = 0x00000040; -#endif - - // wait for inputs to stabilize - for (uint32_t i = 0; i < 50000; i += 1) { - bwdt_reset(); - } - - // now the second part of power on sequence - // If we got here and the radio was not started by the watchdog/software reset, - // then we must have a power button pressed. If not then we are in power on/off loop - // and to terminate it, just wait here without turning on PWR pin. The power supply will - // eventually exhaust and the radio will turn off. - if (!WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) { - // wait here until the power key is pressed - while (GPIOD->IDR & PWR_SWITCH_GPIO_PIN) { - bwdt_reset(); - } - } - - if (!(TRIMS_GPIO_REG_LHR & TRIMS_GPIO_PIN_LHR) && !(TRIMS_GPIO_REG_RHL & TRIMS_GPIO_PIN_RHL)) { - // Bootloader needed - const uint8_t *src; - uint8_t *dest; - uint32_t size; - - bwdt_reset(); - size = sizeof(BootCode); - src = BootCode; - dest = (uint8_t *) 0x20000000; - - for (; size; size -= 1) { - *dest++ = *src++; - } - // Could check for a valid copy to RAM here - // Go execute bootloader - bwdt_reset(); - - uint32_t address = *(uint32_t *) 0x20000004; - - ((void (*)(void)) (address))(); // Go execute the loaded application - } - -// run_application() ; - asm(" mov.w r1, #134217728"); - // 0x8000000 - asm(" add.w r1, #32768"); - // 0x8000 - - asm(" movw r0, #60680"); - // 0xED08 - asm(" movt r0, #57344"); - // 0xE000 - asm(" str r1, [r0, #0]"); - // Set the VTOR - - asm("ldr r0, [r1, #0]"); - // Stack pointer value - asm("msr msp, r0"); - // Set it - asm("ldr r0, [r1, #4]"); - // Reset address - asm("mov.w r1, #1"); - asm("orr r0, r1"); - // Set lsbit - asm("bx r0"); - // Execute application -} -#endif - diff --git a/radio/src/opentx.h b/radio/src/opentx.h index f093549d1c1..a803ec6e4a4 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -980,7 +980,12 @@ extern const char eeprom_stamp[]; #else extern const char vers_stamp[]; #endif -const char* getOtherVersion(); +/** + * Tries to find 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 + * @return The opentx version string starting with "opentx-" or "no version found" if the version string is not found + */ +const char* getOtherVersion(char* buffer); extern uint8_t g_vbat100mV; #if LCD_W > 128 diff --git a/radio/src/serial.cpp b/radio/src/serial.cpp index e7548f2347f..1fa7897658f 100644 --- a/radio/src/serial.cpp +++ b/radio/src/serial.cpp @@ -26,8 +26,10 @@ #define PRINTF_BUFFER_SIZE 128 void serialPutc(char c) { +#if !defined(BOOT) if (getSelectedUsbMode() == USB_SERIAL_MODE) usbSerialPutc(c); +#endif #if defined(SERIAL2) if (serial2TracesEnabled()) serial2Putc(c); diff --git a/radio/src/stamp.cpp b/radio/src/stamp.cpp index a3f32434b78..e26e83e393b 100644 --- a/radio/src/stamp.cpp +++ b/radio/src/stamp.cpp @@ -49,23 +49,24 @@ * Retrieves the version of the bootloader or firmware * @return */ -#if defined(HORUS) -const char* getOtherVersion() -{ - return "no bootloader support"; -} -#elif defined(STM32) +#if defined(STM32) __attribute__ ((section(".fwversiondata"), used)) const char firmware_version[32] = "opentx-" FLAVOUR "-" VERSION " (" GIT_STR ")"; __attribute__ ((section(".bootversiondata"), used)) const char boot_version[32] = "opentx-" FLAVOUR "-" VERSION " (" GIT_STR ")"; -const char* getOtherVersion() +/** + * Tries to find 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* getOtherVersion(char* buffer) { #if defined(BOOT) const char* startother = (char*)(FIRMWARE_ADDRESS+BOOTLOADER_SIZE); #else const char* startother = (char*)(FIRMWARE_ADDRESS); #endif + if (buffer != nullptr) + startother=buffer; const char* other_str = nullptr; for (int i=0; i< 1024;i++) { diff --git a/radio/src/targets/common/arm/loadboot.cpp b/radio/src/targets/common/arm/loadboot.cpp new file mode 100644 index 00000000000..3eb0d390b8a --- /dev/null +++ b/radio/src/targets/common/arm/loadboot.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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. + */ + +__attribute__ ((section(".bootloader"), used)) + +const unsigned char BootCode[] = { +#include "bootloader.lbm" +}; diff --git a/radio/src/targets/common/arm/stm32/CMakeLists.txt b/radio/src/targets/common/arm/stm32/CMakeLists.txt index a2c232e5a59..c99efa07575 100644 --- a/radio/src/targets/common/arm/stm32/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/CMakeLists.txt @@ -36,6 +36,7 @@ set(FIRMWARE_TARGET_SRC ../common/arm/stm32/usbd_desc.c ../common/arm/stm32/usbd_usr.cpp ../common/arm/stm32/usb_driver.cpp + ../common/arm/stm32/flash_driver.cpp ) set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} diff --git a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt new file mode 100644 index 00000000000..d9cd29bcd09 --- /dev/null +++ b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt @@ -0,0 +1,130 @@ +# TODO if the files order is different (these 2 SRC sections exchanged), the bootloader hangs for 20s in USB init. Why? + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + +if(PCB STREQUAL X12S OR PCB STREQUAL X10) + set(BOOTLOADER_SRC + ${BOOTLOADER_SRC} + ../f4/system_stm32f4xx.c + ../../../../../targets/${TARGET_DIR}/startup_stm32f42_43xxx.s + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rcc.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_gpio.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_spi.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_fmc.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_ltdc.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dma.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dma2d.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_sdio.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/misc.c + ) +elseif(PCB STREQUAL X9E) + set(BOOTLOADER_SRC + ${BOOTLOADER_SRC} + ../f4/system_stm32f4xx.c + ../../../../../${STM32LIB_DIR}/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc_ride7/startup_stm32f40_41xxx.s + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rcc.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_gpio.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_spi.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_i2c.c + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/misc.c + ) +else() + set(BOOTLOADER_SRC + ${BOOTLOADER_SRC} + ../f2/system_stm32f2xx.c + ../../../../../${STM32LIB_DIR}/CMSIS/Device/ST/STM32F2xx/Source/Templates/gcc_ride7/startup_stm32f2xx.s + ../../../../../${STM32LIB_DIR}/STM32F2xx_StdPeriph_Driver/src/stm32f2xx_rcc.c + ../../../../../${STM32LIB_DIR}/STM32F2xx_StdPeriph_Driver/src/stm32f2xx_gpio.c + ../../../../../${STM32LIB_DIR}/STM32F2xx_StdPeriph_Driver/src/stm32f2xx_spi.c + ../../../../../${STM32LIB_DIR}/STM32F2xx_StdPeriph_Driver/src/stm32f2xx_i2c.c + ../../../../../${STM32LIB_DIR}/STM32F2xx_StdPeriph_Driver/src/misc.c + ) +endif() + +set(BOOTLOADER_SRC + ${BOOTLOADER_SRC} + ../../../../../gui/${GUI_DIR}/lcd.cpp + ../../../../../gui/${GUI_DIR}/fonts.cpp + ../../../../../keys.cpp + ../../../../../strhelpers.cpp + ../../../../../stamp.cpp + ../../../../../${STM32USB_DIR}/STM32_USB_OTG_Driver/src/usb_core.c + ../../../../../${STM32USB_DIR}/STM32_USB_OTG_Driver/src/usb_dcd.c + ../../../../../${STM32USB_DIR}/STM32_USB_OTG_Driver/src/usb_dcd_int.c + ../../../../../${STM32USB_DIR}/STM32_USB_Device_Library/Core/src/usbd_core.c + ../../../../../${STM32USB_DIR}/STM32_USB_Device_Library/Core/src/usbd_ioreq.c + ../../../../../${STM32USB_DIR}/STM32_USB_Device_Library/Core/src/usbd_req.c + ../../../../../${STM32USB_DIR}/STM32_USB_Device_Library/Class/msc/src/usbd_msc_data.c + ../../../../../${STM32USB_DIR}/STM32_USB_Device_Library/Class/msc/src/usbd_msc_scsi.c + ../../../../../${STM32USB_DIR}/STM32_USB_Device_Library/Class/msc/src/usbd_msc_bot.c + ../../../../../${STM32USB_DIR}/STM32_USB_Device_Library/Class/msc/src/usbd_msc_core.c + ../../../../../${FATFS_DIR}/ff.c + ../../../../../${FATFS_DIR}/option/ccsbcs.c + ../../../../../targets/${TARGET_DIR}/${LCD_DRIVER} + ../../../../../targets/${TARGET_DIR}/backlight_driver.cpp + ../../../../../targets/${TARGET_DIR}/keys_driver.cpp + ../../../../../targets/${TARGET_DIR}/diskio.cpp + ../../../../../targets/${TARGET_DIR}/pwr_driver.cpp + ../../../../../targets/${TARGET_DIR}/bootloader/boot_menu.cpp + ../usbd_usr.cpp + ../usbd_storage_msd.cpp + ../delays.cpp + ../usbd_desc.c + ../usb_bsp.c + ../usb_driver.cpp + ../flash_driver.cpp + init.c + boot.cpp + bin_files.cpp + ) + +if(NOT (PCB STREQUAL X10 OR PCB STREQUAL X12S)) + set(BOOTLOADER_SRC + ${BOOTLOADER_SRC} + ../../../../../targets/${TARGET_DIR}/i2c_driver.cpp + ) + + remove_definitions(-DDEBUG) + +else() + set(BOOTLOADER_SRC + ${BOOTLOADER_SRC} + ../../../../../targets/${TARGET_DIR}/sdram_driver.c + ../../../../../targets/${TARGET_DIR}/sdio_sd.c + ../../../../../targets/${TARGET_DIR}/haptic_driver.cpp + ../../../../../gui/${GUI_DIR}/bitmapbuffer.cpp + ../../../../../syscalls.c + ) + + if(DEBUG) + set(BOOTLOADER_SRC + ${BOOTLOADER_SRC} + ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_usart.c + ../../../../../serial.cpp + ../serial2_driver.cpp + ) + endif() +endif() + +remove_definitions(-DDISK_CACHE) +remove_definitions(-DLUA) +remove_definitions(-DCLI) +add_definitions(-DBOOT) + +set(CMAKE_EXE_LINKER_FLAGS "-mcpu=${MCU} -mthumb -nostartfiles -lm -T${RADIO_SRC_DIRECTORY}/targets/${TARGET_DIR}/stm32_ramboot.ld -Wl,-Map=bootloader.map,--cref,--no-warn-mismatch,--gc-sections") + +add_executable(bootloader ${BOOTLOADER_SRC}) +add_dependencies(bootloader ${BITMAPS_TARGET} firmware_translations) + +add_custom_command( + TARGET bootloader POST_BUILD + COMMAND arm-none-eabi-objcopy -O binary bootloader.elf bootloader.bin +) +if(PYTHONINTERP_FOUND) + add_custom_command( + TARGET bootloader POST_BUILD + COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/bin2lbm.py bootloader.bin bootloader.lbm + ) +endif() + +PrintTargetReport("bootloader") diff --git a/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp b/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp new file mode 100644 index 00000000000..3684f45d7ca --- /dev/null +++ b/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp @@ -0,0 +1,145 @@ +#include "opentx.h" +#include "boot.h" +#include "bin_files.h" + +// 'private' +static DIR dir; +static FIL FlashFile; + +// 'public' variables +BinFileInfo binFiles[MAX_BIN_FILES]; +uint8_t Block_buffer[BLOCK_LEN]; +UINT BlockCount; + + +FRESULT openBinDir(MemoryType mt) +{ + FRESULT fr = f_chdir(getBinaryPath(mt)); + if (fr != FR_OK) return fr; + + return f_opendir(&dir, "."); +} + +static FRESULT findNextBinFile(FILINFO* fno) +{ + FRESULT fr; + + do { + fr = f_readdir(&dir, fno); + + if (fr != FR_OK || fno->fname[0] == 0) + break; + + int32_t len = strlen(fno->fname) - 4; + if (len < 0) + continue; + + if (fno->fname[len] != '.') + continue; + + if ((fno->fname[len + 1] != 'b') && (fno->fname[len + 1] != 'B')) + continue; + + if ((fno->fname[len + 2] != 'i') && (fno->fname[len + 2] != 'I')) + continue; + + if ((fno->fname[len + 3] != 'n') && (fno->fname[len + 3] != 'N')) + continue; + + // match! + break; + + } while (1); + + return fr; +} + +unsigned int fetchBinFiles(unsigned int index) +{ + FILINFO file_info; + + // rewind + if (f_readdir(&dir, NULL) != FR_OK) + return 0; + + // skip 'index' .bin files + for (unsigned int i = 0; i <= index; i++) { + + if (findNextBinFile(&file_info) != FR_OK /*|| file_info.fname[0] == 0*/) + return 0; + } + + strAppend(binFiles[0].name, file_info.fname); + binFiles[0].size = file_info.fsize; + + unsigned int i = 1; + for (; i < MAX_NAMES_ON_SCREEN+1; i++) { + + 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; + } + + return i; +} + +FRESULT openBinFile(MemoryType mt, unsigned int index) +{ + TCHAR full_path[_MAX_LFN+1]; + FRESULT fr; + + // build full_path: [bin path]/[filename] + char* s = strAppend(full_path, getBinaryPath(mt)); + s = strAppend(s, "/"); + strAppend(s, binFiles[index].name); + + BlockCount = 0; + + // open the file + if ((fr = f_open(&FlashFile, full_path, FA_READ)) != FR_OK) + return fr; + + // skip bootloader in firmware + if (mt == MEM_FLASH && + ((fr = f_lseek(&FlashFile, BOOTLOADER_SIZE)) != FR_OK)) + return fr; + + // ... and fetch BLOCK_LEN bytes + fr = f_read(&FlashFile, Block_buffer, BLOCK_LEN, &BlockCount); + + if (BlockCount == BLOCK_LEN) + return fr; + + return FR_INVALID_OBJECT; +} + +void extractFirmwareVersion(VersionTag* tag) +{ + const char* vers = getOtherVersion((char*)Block_buffer); + if (!vers || (vers[0] == 'n' && vers[1] == 'o')) { // "no version found" + memcpy(tag->flavour, "unknown", sizeof("unknown")); + tag->version = "unknown"; + } + + // skip "opentx-" + vers += sizeof("opentx-") - 1; + + char* fl = tag->flavour; + while(*vers != '-') + *(fl++) = *(vers++); + + tag->version = ++vers; +} + +FRESULT readBinFile() +{ + BlockCount = 0; + return f_read(&FlashFile, Block_buffer, sizeof(Block_buffer), &BlockCount); +} + +FRESULT closeBinFile() +{ + return f_close(&FlashFile); +} diff --git a/radio/src/targets/common/arm/stm32/bootloader/bin_files.h b/radio/src/targets/common/arm/stm32/bootloader/bin_files.h new file mode 100644 index 00000000000..33be0af2731 --- /dev/null +++ b/radio/src/targets/common/arm/stm32/bootloader/bin_files.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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. + */ + +#ifndef _bin_files_h_ +#define _bin_files_h_ + +#include "opentx.h" + +enum MemoryType { + MEM_FLASH, + MEM_EEPROM +}; + +#if defined(EEPROM) +#define getBinaryPath(mt) ((mt == MEM_FLASH) ? FIRMWARES_PATH : EEPROMS_PATH) +#else +#define getBinaryPath(mt) (FIRMWARES_PATH) +#endif + +#define MAX_NAMES_ON_SCREEN 6 +#define MAX_BIN_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[_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); + +// 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); + +// 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); + +struct VersionTag +{ + char flavour[8]; + const char* version; +}; + +// Can be called right after openBinFile() to extract the version information +// from a firmware file +void extractFirmwareVersion(VersionTag* tag); + +// Read the next BLOCK_LEN bytes into 'Block_buffer' +// Check 'BlockCount' for # of bytes read +FRESULT readBinFile(); + +// Close the previously opened file +FRESULT closeBinFile(); + +#endif diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp new file mode 100644 index 00000000000..f0cf3de2dae --- /dev/null +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp @@ -0,0 +1,523 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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 "opentx.h" +#include "stamp.h" + +#include "boot.h" +#include "bin_files.h" + +#define APP_START_ADDRESS (uint32_t)(FIRMWARE_ADDRESS + BOOTLOADER_SIZE) + +#if defined(EEPROM) +#define MAIN_MENU_LEN 3 +#else +#define MAIN_MENU_LEN 2 +#endif + +typedef void (*voidFunction)(void); + +#define jumpTo(addr) { \ + SCB->VTOR = addr; \ + __set_MSP(*(__IO uint32_t*)addr); \ + uint32_t jumpAddress = *(uint32_t*)(addr + 4); \ + voidFunction jumpFn = (voidFunction)jumpAddress; \ + jumpFn(); \ + } + +// Bootloader marker: +// -> used to detect valid bootloader files +const uint8_t bootloaderVersion[] __attribute__ ((section(".version"), used)) = +{ 'B', 'O', 'O', 'T', '1', '0' }; + +#if defined(ROTARY_ENCODER_NAVIGATION) +volatile rotenc_t rotencValue[1] = {0}; +#endif + +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ + +uint32_t FirmwareSize; +uint32_t firmwareAddress = FIRMWARE_ADDRESS; +uint32_t firmwareWritten = 0; + +#if defined(EEPROM) +uint32_t eepromAddress = 0; +uint32_t eepromWritten = 0; +#endif + +//TCHAR backupFilename[_MAX_LFN+1]; + +//uint32_t Master_frequency; +volatile uint8_t Tenms = 1; + +FlashCheckRes Valid; + +MemoryType memoryType; +uint32_t unlocked = 0; + +void interrupt10ms(void) +{ + Tenms |= 1; // 10 mS has passed + + uint8_t index = 0; + uint8_t in = readKeys(); + for (uint8_t i = 1; i != uint8_t(1 << TRM_BASE); i <<= 1) { + uint8_t value = (in & i); + keys[index].input(value); + ++index; + } + +#if defined(ROTARY_ENCODER_NAVIGATION) + checkRotaryEncoder(); + static rotenc_t rePreviousValue; + rotenc_t reNewValue = (rotencValue[0] / 2); + int8_t scrollRE = reNewValue - rePreviousValue; + if (scrollRE) { + rePreviousValue = reNewValue; + if (scrollRE < 0) { + putEvent(EVT_KEY_FIRST(KEY_UP)); //EVT_ROTARY_LEFT + } + else { + putEvent(EVT_KEY_FIRST(KEY_DOWN)); //EVT_ROTARY_RIGHT + } + } +#endif +} + +void init10msTimer() +{ + INTERRUPT_xMS_TIMER->ARR = 9999; // 10mS in uS + INTERRUPT_xMS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1uS + INTERRUPT_xMS_TIMER->CCER = 0; + INTERRUPT_xMS_TIMER->CCMR1 = 0; + INTERRUPT_xMS_TIMER->EGR = 0; + INTERRUPT_xMS_TIMER->CR1 = 5; + INTERRUPT_xMS_TIMER->DIER |= 1; + NVIC_EnableIRQ(INTERRUPT_xMS_IRQn); +} + +extern "C" void INTERRUPT_xMS_IRQHandler() +{ + INTERRUPT_xMS_TIMER->SR &= ~TIM_SR_UIF; + interrupt10ms(); +} + +uint32_t isValidBufferStart(const uint8_t * buffer) +{ +#if defined(EEPROM) + if (memoryType == MEM_FLASH) + return isFirmwareStart(buffer); + else + return isEepromStart(buffer); +#else + return isFirmwareStart(buffer); +#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; +} + +extern Key keys[]; + +static uint32_t PowerUpDelay; + +void flashWriteBlock() +{ + uint32_t blockOffset = 0; + 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; + } + } +} + +#if defined(EEPROM) +void writeEepromBlock() +{ + eepromWriteBlock(Block_buffer, eepromAddress, BlockCount); + eepromAddress += BlockCount; +} +#endif + +int main() +{ + BootloaderState state = ST_START; + uint32_t vpos = 0; + uint8_t index = 0; + FRESULT fr; + uint32_t nameCount = 0; + + wdt_reset(); + RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | KEYS_RCC_AHB1Periph | + LCD_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | + SERIAL_RCC_AHB1Periph | I2C_RCC_AHB1Periph | + SD_RCC_AHB1Periph, ENABLE); + + RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | + INTERRUPT_xMS_RCC_APB1Periph | I2C_RCC_APB1Periph | + SERIAL_RCC_APB1Periph | + SD_RCC_APB1Periph, ENABLE); + + RCC_APB2PeriphClockCmd(LCD_RCC_APB2Periph | BACKLIGHT_RCC_APB2Periph, ENABLE); + + keysInit(); + + // wait for inputs to stabilize + for (uint32_t i = 0; i < 50000; i += 1) { + wdt_reset(); + } + + // LHR & RHL trims not pressed simultanously + if (readTrims() != 0x42) { + // Start main application + jumpTo(APP_START_ADDRESS); + } + + pwrInit(); + delaysInit(); // needed for lcdInit() + +#if defined(DEBUG) + serial2Init(UART_MODE_DEBUG, 0); // default serial mode (None if DEBUG not defined) +#endif + + __enable_irq(); + TRACE("\nBootloader started :)"); + + lcdInit(); + backlightInit(); + +#if defined(PCBTARANIS) + i2cInit(); +#endif + init10msTimer(); + + // SD card detect pin + sdInit(); + usbInit(); + + // init screen + bootloaderInitScreen(); + +#if defined(PWR_PRESS_BUTTON) or defined(PCBHORUS) + // wait until power button is released + while(pwrPressed()) { + wdt_reset(); + } +#endif + + for (;;) { + wdt_reset(); + + if (Tenms) { + Tenms = 0; + + if (state != ST_USB) { + if (usbPlugged()) { + state = ST_USB; + if (!unlocked) { + unlocked = 1; + unlockFlash(); + } + usbStart(); + usbPluggedIn(); + } + } + + if (state == ST_USB) { + if (usbPlugged() == 0) { + vpos = 0; + usbStop(); + if (unlocked) { + lockFlash(); + unlocked = 0; + } + state = ST_START; + } + bootloaderDrawScreen(state, 0); + } + + lcdRefreshWait(); + event_t event = getEvent(); + + if (state == ST_START) { + + bootloaderDrawScreen(state, vpos); + + if (event == EVT_KEY_FIRST(KEY_DOWN)) { + vpos = (vpos + 1) % MAIN_MENU_LEN; + continue; + } + else if (event == EVT_KEY_FIRST(KEY_UP)) { + vpos = (vpos + MAIN_MENU_LEN - 1) % MAIN_MENU_LEN; + continue; + } + else if (event == EVT_KEY_BREAK(KEY_ENTER)) { + switch (vpos) { + case 0: + memoryType = MEM_FLASH; + state = ST_DIR_CHECK; + break; +#if defined(EEPROM) + case 1: + memoryType = MEM_EEPROM; + state = ST_DIR_CHECK; + break; +#endif + default: + 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 (event == EVT_KEY_REPT(KEY_DOWN) || event == EVT_KEY_FIRST(KEY_DOWN)) { + if (vpos < limit - 1) { + vpos += 1; + } + else { + if (nameCount > limit) { + index += 1; + nameCount = fetchBinFiles(index); + } + } + } + else if (event == EVT_KEY_REPT(KEY_UP) || event == EVT_KEY_FIRST(KEY_UP)) { + if (vpos > 0) { + vpos -= 1; + } + else { + if (index) { + index -= 1; + nameCount = fetchBinFiles(index); + } + } + } + + bootloaderDrawScreen(state, 0); + + for (uint32_t i=0; i= FLASHSIZE - BOOTLOADER_SIZE)) { + state = ST_FLASH_DONE; // Backstop + } +#if defined(EEPROM) + else if ((memoryType == MEM_EEPROM) && + (eepromWritten >= EEPROM_SIZE)) { + state = ST_FLASH_DONE; // Backstop + } +#endif + } + + 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 (PowerUpDelay < 20) { // 200 mS + PowerUpDelay += 1; + } + else { + sdPoll10ms(); + } + } + + if (state != ST_FLASHING && state != ST_USB) { + if (pwrOffPressed()) { + lcdClear(); + lcdOff(); // this drains LCD caps + pwrOff(); + for (;;) { + // Wait for power to go off + } + } + } + + if (state == ST_REBOOT) { + // Jump to proper application address + lcdClear(); + jumpTo(APP_START_ADDRESS); + } + } + + return 0; +} + +#if defined(PCBHORUS) +void *__dso_handle = 0; +#endif diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.h b/radio/src/targets/common/arm/stm32/bootloader/boot.h new file mode 100644 index 00000000000..140c772e647 --- /dev/null +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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. + */ + +#ifndef _boot_h_ +#define _boot_h_ + +#include "stamp.h" + +#define BOOTLOADER_TITLE " OTX Bootloader - " VERSION +#define DISPLAY_CHAR_WIDTH (LCD_COLS+4) + +#if LCD_W >= 480 + #define STR_INVALID_FIRMWARE "Not a valid firmware file" +#elif LCD_W >= 212 + #define STR_OR_PLUGIN_USB_CABLE INDENT "Or plug in a USB cable for mass storage" + #define STR_HOLD_ENTER_TO_START "\012Hold [ENT] to start writing" + #define STR_INVALID_FIRMWARE "\011Not a valid firmware file! " + #define STR_INVALID_EEPROM "\011Not a valid EEPROM file! " +#else + #define STR_OR_PLUGIN_USB_CABLE INDENT "Or plug in a USB cable" + #define STR_HOLD_ENTER_TO_START "\006Hold [ENT] to start" + #define STR_INVALID_FIRMWARE "\004Not a valid firmware! " + #define STR_INVALID_EEPROM "\004Not a valid EEPROM! " +#endif + +#define STR_USB_CONNECTED CENTER "\011USB Connected" + + +// Bootloader states +enum BootloaderState { + ST_START, + ST_FLASH_MENU, + ST_DIR_CHECK, + ST_OPEN_DIR, + ST_FILE_LIST, + ST_FLASH_CHECK, + ST_FLASHING, + ST_FLASH_DONE, + ST_RESTORE_MENU, + ST_USB, + ST_REBOOT, +}; + +enum FlashCheckRes { + FC_UNCHECKED=0, + FC_OK, + FC_ERROR +}; + +// Declarations of functions that need to be implemented +// for each target with a bootloader + +// On bootloader start after lcdInit() +void bootloaderInitScreen(); + +// Depending on the state, up to two optional parameters are passed. +// See boot.cpp/main for more details +void bootloaderDrawScreen(BootloaderState st, int opt, const char* str = NULL); + +// Once for each file in a filename list on screen +void bootloaderDrawFilename(const char* str, uint8_t line, bool selected); + +#endif diff --git a/radio/src/targets/taranis/bootloader/init.c b/radio/src/targets/common/arm/stm32/bootloader/init.c similarity index 100% rename from radio/src/targets/taranis/bootloader/init.c rename to radio/src/targets/common/arm/stm32/bootloader/init.c diff --git a/radio/src/targets/taranis/flash_driver.cpp b/radio/src/targets/common/arm/stm32/flash_driver.cpp similarity index 65% rename from radio/src/targets/taranis/flash_driver.cpp rename to radio/src/targets/common/arm/stm32/flash_driver.cpp index dc06d6b9d91..ab653c2d6f0 100644 --- a/radio/src/targets/taranis/flash_driver.cpp +++ b/radio/src/targets/common/arm/stm32/flash_driver.cpp @@ -70,31 +70,62 @@ void eraseSector(uint32_t sector) void flashWrite(uint32_t * address, uint32_t * buffer) // page size is 256 bytes { - if ((uint32_t) address == 0x08000000) { - eraseSector(0); - } - else if ((uint32_t) address == 0x08004000) { - eraseSector(1); - } - else if ((uint32_t) address == 0x08008000) { - eraseSector(2); - } - else if ((uint32_t) address == 0x0800C000) { - eraseSector(3); - } - else if ((uint32_t) address == 0x08010000) { - eraseSector(4); - } - else if ((uint32_t) address == 0x08020000) { - eraseSector(5); - } - else if ((uint32_t) address == 0x08040000) { - eraseSector(6); - } - else if ((uint32_t) address == 0x08060000) { - eraseSector(7); - } +#define SECTOR_ADDRESS (((uint32_t)address) & 0xFFFFF) + +// Please note that there is an offset of 4 between +// sector 11 and 12 +#define FLASH_BANK ((((uint32_t)address) & 0x100000) ? 16 : 0) + + // test for possible flash sector boundary + if ((((uint32_t)address) & 0x1FFFF) == 0) { + // test first 16KB sectors + if (SECTOR_ADDRESS == 0x00000) { + eraseSector(0 + FLASH_BANK); + } + // test 128KB sectors + else if (SECTOR_ADDRESS == 0x20000) { + eraseSector(5 + FLASH_BANK); + } + else if (SECTOR_ADDRESS == 0x40000) { + eraseSector(6 + FLASH_BANK); + } + else if (SECTOR_ADDRESS == 0x60000) { + eraseSector(7 + FLASH_BANK); + } + else if (SECTOR_ADDRESS == 0x80000) { + eraseSector(8 + FLASH_BANK); + } + else if (SECTOR_ADDRESS == 0xA0000) { + eraseSector(9 + FLASH_BANK); + } + else if (SECTOR_ADDRESS == 0xC0000) { + eraseSector(10 + FLASH_BANK); + } + else if (SECTOR_ADDRESS == 0xE0000) { + eraseSector(11 + FLASH_BANK); + } + } + // test 64KB sector + else if (SECTOR_ADDRESS == 0x10000) { + eraseSector(4 + FLASH_BANK); + } + else if ((((uint32_t)address) & 0x3FFF) == 0) { + + // test other 16KB sectors + if (SECTOR_ADDRESS == 0x04000) { + eraseSector(1 + FLASH_BANK); + } + else if (SECTOR_ADDRESS == 0x08000) { + eraseSector(2 + FLASH_BANK); + } + else if (SECTOR_ADDRESS == 0x0C000) { + eraseSector(3 + FLASH_BANK); + } + } +#undef SECTOR_ADDRESS +#undef FLASH_BANK + for (uint32_t i=0; iARR = 100; - BL_TIMER->PSC = BL_TIMER_FREQ / 10000 - 1; // 1kHz - BL_TIMER->CCMR2 = TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2; // PWM - BL_TIMER->CCER = TIM_CCER_CC4E; - BL_TIMER->CCR4 = 0; - BL_TIMER->EGR = 0; - BL_TIMER->CR1 = TIM_CR1_CEN; // Counter enable + BACKLIGHT_TIMER->ARR = 100; + BACKLIGHT_TIMER->PSC = BACKLIGHT_TIMER_FREQ / 10000 - 1; // 1kHz + BACKLIGHT_TIMER->CCMR2 = TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2; // PWM + BACKLIGHT_TIMER->CCER = TIM_CCER_CC4E; + BACKLIGHT_TIMER->CCR4 = 0; + BACKLIGHT_TIMER->EGR = 0; + BACKLIGHT_TIMER->CR1 = TIM_CR1_CEN; // Counter enable } else { - BL_TIMER->ARR = 100; - BL_TIMER->PSC = BL_TIMER_FREQ / 10000 - 1; // 1kHz - BL_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; // PWM - BL_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1NE; - BL_TIMER->CCR1 = 100; - BL_TIMER->EGR = 1; - BL_TIMER->CR1 |= TIM_CR1_CEN; // Counter enable - BL_TIMER->BDTR |= TIM_BDTR_MOE; + BACKLIGHT_TIMER->ARR = 100; + BACKLIGHT_TIMER->PSC = BACKLIGHT_TIMER_FREQ / 10000 - 1; // 1kHz + BACKLIGHT_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; // PWM + BACKLIGHT_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1NE; + BACKLIGHT_TIMER->CCR1 = 100; + BACKLIGHT_TIMER->EGR = 1; + BACKLIGHT_TIMER->CR1 |= TIM_CR1_CEN; // Counter enable + BACKLIGHT_TIMER->BDTR |= TIM_BDTR_MOE; } #elif defined(PCBX10) - BL_TIMER->ARR = 100; - BL_TIMER->PSC = BL_TIMER_FREQ / 1000000 - 1; // 10kHz (same as FrOS) - BL_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3PE; // PWM mode 1 - BL_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3NE; - BL_TIMER->CCR3 = 100; - BL_TIMER->EGR = TIM_EGR_UG; - BL_TIMER->CR1 |= TIM_CR1_CEN; // Counter enable - BL_TIMER->BDTR |= TIM_BDTR_MOE; + BACKLIGHT_TIMER->ARR = 100; + BACKLIGHT_TIMER->PSC = BACKLIGHT_TIMER_FREQ / 1000000 - 1; // 10kHz (same as FrOS) + BACKLIGHT_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3PE; // PWM mode 1 + BACKLIGHT_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3NE; + BACKLIGHT_TIMER->CCR3 = 100; + BACKLIGHT_TIMER->EGR = TIM_EGR_UG; + BACKLIGHT_TIMER->CR1 |= TIM_CR1_CEN; // Counter enable + BACKLIGHT_TIMER->BDTR |= TIM_BDTR_MOE; #endif } @@ -69,12 +69,12 @@ void backlightEnable(uint8_t dutyCycle) { #if defined(PCBX12S) if (IS_HORUS_PROD()) { - BL_TIMER->CCR4 = dutyCycle; + BACKLIGHT_TIMER->CCR4 = dutyCycle; } else { - BL_TIMER->CCR1 = BACKLIGHT_LEVEL_MAX - dutyCycle; + BACKLIGHT_TIMER->CCR1 = BACKLIGHT_LEVEL_MAX - dutyCycle; } #elif defined(PCBX10) - BL_TIMER->CCR3 = BACKLIGHT_LEVEL_MAX - dutyCycle; + BACKLIGHT_TIMER->CCR3 = BACKLIGHT_LEVEL_MAX - dutyCycle; #endif } diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index 8d6d89bafe4..6fc5405548f 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -42,7 +42,7 @@ void watchdogInit(unsigned int duration) // Start TIMER7 at 2000000Hz void init2MhzTimer() { - TIMER_2MHz_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1; // 0.5 uS, 2 MHz + TIMER_2MHz_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1; // 0.5 uS, 2 MHz TIMER_2MHz_TIMER->ARR = 65535; TIMER_2MHz_TIMER->CR2 = 0; TIMER_2MHz_TIMER->CR1 = TIM_CR1_CEN; @@ -51,15 +51,15 @@ void init2MhzTimer() // Starts TIMER at 1000Hz void init1msTimer() { - INTERRUPT_1MS_TIMER->ARR = 999; // 1mS - INTERRUPT_1MS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1uS from 30MHz - INTERRUPT_1MS_TIMER->CCER = 0; - INTERRUPT_1MS_TIMER->CCMR1 = 0; - INTERRUPT_1MS_TIMER->EGR = 0; - INTERRUPT_1MS_TIMER->CR1 = 5; - INTERRUPT_1MS_TIMER->DIER |= 1; - NVIC_EnableIRQ(INTERRUPT_1MS_IRQn); - NVIC_SetPriority(INTERRUPT_1MS_IRQn, 7); + INTERRUPT_xMS_TIMER->ARR = 999; // 1mS in uS + INTERRUPT_xMS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1uS + INTERRUPT_xMS_TIMER->CCER = 0; + INTERRUPT_xMS_TIMER->CCMR1 = 0; + INTERRUPT_xMS_TIMER->EGR = 0; + INTERRUPT_xMS_TIMER->CR1 = 5; + INTERRUPT_xMS_TIMER->DIER |= 1; + NVIC_EnableIRQ(INTERRUPT_xMS_IRQn); + NVIC_SetPriority(INTERRUPT_xMS_IRQn, 7); } // TODO use the same than board_sky9x.cpp @@ -90,9 +90,9 @@ void interrupt1ms() DEBUG_TIMER_STOP(debugTimerRotEnc); } -extern "C" void INTERRUPT_1MS_IRQHandler() +extern "C" void INTERRUPT_xMS_IRQHandler() { - INTERRUPT_1MS_TIMER->SR &= ~TIM_SR_UIF; + INTERRUPT_xMS_TIMER->SR &= ~TIM_SR_UIF; interrupt1ms(); DEBUG_INTERRUPT(INT_1MS); } @@ -135,10 +135,10 @@ void boardInit() PCBREV_RCC_AHB1Periph | LED_RCC_AHB1Periph | LCD_RCC_AHB1Periph | - BL_RCC_AHB1Periph | + BACKLIGHT_RCC_AHB1Periph | SD_RCC_AHB1Periph | AUDIO_RCC_AHB1Periph | - KEYS_RCC_AHB1Periph_GPIO | + KEYS_RCC_AHB1Periph | ADC_RCC_AHB1Periph | SERIAL_RCC_AHB1Periph | TELEMETRY_RCC_AHB1Periph | @@ -149,11 +149,10 @@ void boardInit() INTMODULE_RCC_AHB1Periph | EXTMODULE_RCC_AHB1Periph | GPS_RCC_AHB1Periph | - SPORT_UPDATE_RCC_AHB1Periph | - BL_RCC_AHB1Periph, + SPORT_UPDATE_RCC_AHB1Periph, ENABLE); - RCC_APB1PeriphClockCmd(INTERRUPT_1MS_RCC_APB1Periph | + RCC_APB1PeriphClockCmd(INTERRUPT_xMS_RCC_APB1Periph | ADC_RCC_APB1Periph | TIMER_2MHz_RCC_APB1Periph | AUDIO_RCC_APB1Periph | @@ -164,7 +163,7 @@ void boardInit() INTMODULE_RCC_APB1Periph | EXTMODULE_RCC_APB1Periph | GPS_RCC_APB1Periph | - BL_RCC_APB1Periph, + BACKLIGHT_RCC_APB1Periph, ENABLE); RCC_APB2PeriphClockCmd(LCD_RCC_APB2Periph | @@ -173,7 +172,7 @@ void boardInit() INTMODULE_RCC_APB2Periph | EXTMODULE_RCC_APB2Periph | BT_RCC_APB2Periph | - BL_RCC_APB2Periph, + BACKLIGHT_RCC_APB2Periph, ENABLE); pwrInit(); diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index e86487ec295..a4c9cfdb0fa 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -82,7 +82,7 @@ extern "C" { #endif #define FLASHSIZE 0x200000 -#define BOOTLOADER_SIZE 0x8000 +#define BOOTLOADER_SIZE 0x20000 #define FIRMWARE_ADDRESS 0x08000000 #define MB *1024*1024 @@ -160,6 +160,7 @@ uint32_t sdMounted(void); #define sdDone() #define SD_CARD_PRESENT() true #endif + #if defined(DISK_CACHE) #include "diskio.h" DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count); @@ -446,7 +447,7 @@ void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t void lcdStoreBackupBuffer(void); int lcdRestoreBackupBuffer(void); void lcdSetContrast(); -#define lcdOff(...) +#define lcdOff() backlightEnable(0) /* just disable the backlight */ #define lcdSetRefVolt(...) #define lcdRefreshWait(...) diff --git a/radio/src/targets/horus/bootloader/boot_menu.cpp b/radio/src/targets/horus/bootloader/boot_menu.cpp new file mode 100644 index 00000000000..b50b9c7299a --- /dev/null +++ b/radio/src/targets/horus/bootloader/boot_menu.cpp @@ -0,0 +1,172 @@ +#include "opentx.h" +#include "../../common/arm/stm32/bootloader/boot.h" +#include "../../common/arm/stm32/bootloader/bin_files.h" + +#define SELECTED_COLOR (INVERS | TEXT_COLOR) + +#include "bmp_plug_usb.lbm" +#include "bmp_usb_plugged.lbm" + +const uint8_t LBM_FLASH[] = { +#include "icon_flash.lbm" +}; + +const uint8_t LBM_EXIT[] = { +#include "icon_exit.lbm" +}; + +const uint8_t LBM_SD[] = { +#include "icon_sd.lbm" +}; + +const uint8_t LBM_FILE[] = { +#include "icon_file.lbm" +}; + +const uint8_t LBM_ERROR[] = { +#include "icon_error.lbm" +}; + +const uint8_t LBM_OK[] = { +#include "icon_ok.lbm" +}; + +void bootloaderInitScreen() +{ + lcdColorTable[TEXT_COLOR_INDEX] = BLACK; + lcdColorTable[TEXT_BGCOLOR_INDEX] = WHITE; + lcdColorTable[LINE_COLOR_INDEX] = RED; + lcdColorTable[BARGRAPH1_COLOR_INDEX] = RED; + lcdColorTable[BARGRAPH2_COLOR_INDEX] = RGB(73, 219, 62); // green + + backlightEnable(BACKLIGHT_LEVEL_MAX); +} + +static void bootloaderDrawTitle(unsigned int x, const char* text) +{ + lcdDrawText(x, 28, text); + lcdDrawSolidFilledRect(28, 56, 422, 2, TEXT_COLOR); +} + +static void bootloaderDrawFooter() +{ + lcdDrawSolidFilledRect(28, 234, 422, 2, TEXT_COLOR); +} + +void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) +{ + // clear screen + lcdDrawSolidFilledRect(0, 0, LCD_W-1, LCD_H-1, TEXT_BGCOLOR); + + if (st == ST_START) { + + bootloaderDrawTitle(88, "HORUS BOOTLOADER"); + + lcdDrawBitmapPattern(90, 72, LBM_FLASH, TEXT_COLOR); + lcdDrawText(124, 75, "Write Firmware"); + + lcdDrawBitmapPattern(90, 107, LBM_EXIT, TEXT_COLOR); + lcdDrawText(124, 110, "Exit"); + + lcdDrawSolidRect(119, (opt == 0) ? 72 : 107, 270, 26, 2, LINE_COLOR); + + lcd->drawBitmap(60, 166, &BMP_PLUG_USB); + lcdDrawText(195, 175, "Or plug in a USB cable"); + lcdDrawText(195, 200, "for mass storage"); + + bootloaderDrawFooter(); + lcdDrawText( 36, 242, "Current Firmware:"); + lcdDrawText(200, 242, getOtherVersion(nullptr)); + } + else if (st == ST_USB) { + + lcd->drawBitmap(136, 98, &BMP_USB_PLUGGED); + lcdDrawText(195, 128, "USB Connected"); + } + else if (st == ST_FILE_LIST || st == ST_DIR_CHECK || st == ST_FLASH_CHECK || + st == ST_FLASHING || st == ST_FLASH_DONE) { + + bootloaderDrawTitle(126, "SD>FIRMWARE"); + lcdDrawBitmapPattern(87, 16, LBM_SD, TEXT_COLOR); + + if (st == ST_FLASHING || st == ST_FLASH_DONE) { + + LcdFlags color = BARGRAPH1_COLOR; // red + + if (st == ST_FLASH_DONE) { + color = BARGRAPH2_COLOR/* green */; + opt = 100; // Completed > 100% + } + + lcdDrawRect(70, 120, 340, 31, 2); + lcdDrawSolidFilledRect(74, 124, (332 * opt) / 100, 23, color); + } + else if (st == ST_DIR_CHECK) { + + if (opt == FR_NO_PATH) { + lcdDrawText(90, 168, "Directory is missing"); + } + else { + lcdDrawText(90, 168, "Directory is empty"); + } + + lcdDrawBitmapPattern(356, 158, LBM_ERROR, BARGRAPH1_COLOR); + } + else if (st == ST_FLASH_CHECK) { + + bootloaderDrawFilename(str, 0, true); + + if (opt == FC_ERROR) { + lcdDrawText(94, 168, STR_INVALID_FIRMWARE); + lcdDrawBitmapPattern(356, 158, LBM_ERROR, BARGRAPH1_COLOR); + } + else if (opt == FC_OK) { + VersionTag tag; + extractFirmwareVersion(&tag); + + lcdDrawText(168, 158, "Version:", RIGHT); + lcdDrawText(174, 158, tag.version); + + lcdDrawText(168, 178, "Radio:", RIGHT); + lcdDrawText(174, 178, tag.flavour); + + lcdDrawBitmapPattern(356, 158, LBM_OK, BARGRAPH2_COLOR); + } + } + + bootloaderDrawFooter(); + + if ( st != ST_DIR_CHECK && (st != ST_FLASH_CHECK || opt == FC_OK)) { + + lcdDrawBitmapPattern(28, 242, LBM_FLASH, TEXT_COLOR); + + if (st == ST_FILE_LIST) { + lcdDrawText(56, 244, "[ENT] to select file"); + } + else if (st == ST_FLASH_CHECK && opt == FC_OK) { + lcdDrawText(56, 244, "Hold [ENT] long to flash"); + } + else if (st == ST_FLASHING) { + lcdDrawText(56, 244, "Writing Firmware ..."); + } + else if (st == ST_FLASH_DONE) { + lcdDrawText(56, 244, "Writing Completed"); + } + } + + if (st != ST_FLASHING) { + lcdDrawBitmapPattern(305, 242, LBM_EXIT, TEXT_COLOR); + lcdDrawText(335, 244, "[RTN] to exit"); + } + } +} + +void bootloaderDrawFilename(const char* str, uint8_t line, bool selected) +{ + lcdDrawBitmapPattern(94, 76 + (line * 25), LBM_FILE, TEXT_COLOR); + lcdDrawText(124, 75 + (line * 25), str); + + if (selected) { + lcdDrawSolidRect(119, 72 + (line * 25), 278, 26, 2, LINE_COLOR); + } +} diff --git a/radio/src/targets/horus/diskio.cpp b/radio/src/targets/horus/diskio.cpp index 489865b5c60..b0d9e8174c3 100644 --- a/radio/src/targets/horus/diskio.cpp +++ b/radio/src/targets/horus/diskio.cpp @@ -313,6 +313,14 @@ FATFS g_FATFS_Obj __DMA; // initialized in boardInit() FIL g_telemetryFile = {}; #endif +#if defined(BOOT) +void sdInit(void) +{ + if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) { + f_chdir("/"); + } +} +#else void sdInit() { TRACE("sdInit"); @@ -359,6 +367,7 @@ void sdDone() f_mount(NULL, "", 0); // unmount SD } } +#endif uint32_t sdMounted() { diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 2608448cd09..f08800762c8 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -22,7 +22,7 @@ #define _HAL_H_ // Keys -#define KEYS_RCC_AHB1Periph_GPIO (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOJ) +#define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOJ) #if defined(PCBX12S) #define KEYS_GPIO_REG_PGUP GPIOC->IDR #define KEYS_GPIO_PIN_PGUP GPIO_Pin_13 // PC.13 @@ -246,8 +246,11 @@ // Power #define PWR_RCC_AHB1Periph RCC_AHB1Periph_GPIOJ #define PWR_GPIO GPIOJ -#define PWR_ON_GPIO_PIN GPIO_Pin_1 // PJ.01 +#define PWR_SWITCH_GPIO_REG PWR_GPIO->IDR #define PWR_SWITCH_GPIO_PIN GPIO_Pin_0 // PJ.00 +#define PWR_ON_GPIO_PIN GPIO_Pin_1 // PJ.01 +#define PWR_ON_GPIO_MODER GPIO_MODER_MODER1 +#define PWR_ON_GPIO_MODER_OUT GPIO_MODER_MODER1_0 #if defined(PCBX10) #define SPORT_UPDATE_RCC_AHB1Periph RCC_AHB1Periph_GPIOH @@ -327,6 +330,7 @@ // LCD #define LCD_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOJ | RCC_AHB1Periph_GPIOK | RCC_AHB1Periph_DMA2D) +#define LCD_RCC_APB1Periph 0 #define LCD_RCC_APB2Periph RCC_APB2Periph_LTDC #if defined(PCBX12S) #define LCD_GPIO_NRST GPIOF @@ -340,39 +344,40 @@ // Backlight #if defined(PCBX12S) - #define BL_RCC_AHB1Periph RCC_AHB1Periph_GPIOA - #define BL_GPIO GPIOA + #define BACKLIGHT_RCC_AHB1Periph RCC_AHB1Periph_GPIOA + #define BACKLIGHT_GPIO GPIOA #if PCBREV >= 13 - #define BL_TIMER TIM5 - #define BL_GPIO_PIN GPIO_Pin_3 // PA.03 - #define BL_GPIO_PinSource GPIO_PinSource3 - #define BL_RCC_APB1Periph RCC_APB1Periph_TIM5 - #define BL_RCC_APB2Periph 0 - #define BL_GPIO_AF GPIO_AF_TIM5 - #define BL_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) + #define BACKLIGHT_TIMER TIM5 + #define BACKLIGHT_GPIO_PIN GPIO_Pin_3 // PA.03 + #define BACKLIGHT_GPIO_PinSource GPIO_PinSource3 + #define BACKLIGHT_RCC_APB1Periph RCC_APB1Periph_TIM5 + #define BACKLIGHT_RCC_APB2Periph 0 + #define BACKLIGHT_GPIO_AF GPIO_AF_TIM5 + #define BACKLIGHT_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) #else - #define BL_TIMER TIM8 - #define BL_GPIO_PIN GPIO_Pin_5 // PA.05 - #define BL_GPIO_PinSource GPIO_PinSource5 - #define BL_RCC_APB1Periph 0 - #define BL_RCC_APB2Periph RCC_APB2Periph_TIM8 - #define BL_GPIO_AF GPIO_AF_TIM8 - #define BL_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) + #define BACKLIGHT_TIMER TIM8 + #define BACKLIGHT_GPIO_PIN GPIO_Pin_5 // PA.05 + #define BACKLIGHT_GPIO_PinSource GPIO_PinSource5 + #define BACKLIGHT_RCC_APB1Periph 0 + #define BACKLIGHT_RCC_APB2Periph RCC_APB2Periph_TIM8 + #define BACKLIGHT_GPIO_AF GPIO_AF_TIM8 + #define BACKLIGHT_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) #endif #elif defined(PCBX10) - #define BL_RCC_AHB1Periph RCC_AHB1Periph_GPIOB - #define BL_GPIO GPIOB - #define BL_TIMER TIM8 - #define BL_GPIO_PIN GPIO_Pin_1 // PB.01 - #define BL_GPIO_PinSource GPIO_PinSource1 - #define BL_RCC_APB1Periph 0 - #define BL_RCC_APB2Periph RCC_APB2Periph_TIM8 - #define BL_GPIO_AF GPIO_AF_TIM8 - #define BL_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) + #define BACKLIGHT_RCC_AHB1Periph RCC_AHB1Periph_GPIOB + #define BACKLIGHT_GPIO GPIOB + #define BACKLIGHT_TIMER TIM8 + #define BACKLIGHT_GPIO_PIN GPIO_Pin_1 // PB.01 + #define BACKLIGHT_GPIO_PinSource GPIO_PinSource1 + #define BACKLIGHT_RCC_APB1Periph 0 + #define BACKLIGHT_RCC_APB2Periph RCC_APB2Periph_TIM8 + #define BACKLIGHT_GPIO_AF GPIO_AF_TIM8 + #define BACKLIGHT_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) #endif // SD #define SD_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2) +#define SD_RCC_APB1Periph 0 #define SD_PRESENT_GPIO GPIOC #define SD_PRESENT_GPIO_PIN GPIO_Pin_5 // PC.05 #define SD_SDIO_DMA_STREAM DMA2_Stream3 @@ -607,11 +612,11 @@ #define TRAINER_DMA_FLAG_TC DMA_IT_TCIF2 #define TRAINER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) -// 1ms Interrupt -#define INTERRUPT_1MS_RCC_APB1Periph RCC_APB1Periph_TIM14 -#define INTERRUPT_1MS_TIMER TIM14 -#define INTERRUPT_1MS_IRQn TIM8_TRG_COM_TIM14_IRQn -#define INTERRUPT_1MS_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler +// Xms Interrupt +#define INTERRUPT_xMS_RCC_APB1Periph RCC_APB1Periph_TIM14 +#define INTERRUPT_xMS_TIMER TIM14 +#define INTERRUPT_xMS_IRQn TIM8_TRG_COM_TIM14_IRQn +#define INTERRUPT_xMS_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler // 2MHz Timer #define TIMER_2MHz_RCC_APB1Periph RCC_APB1Periph_TIM7 diff --git a/radio/src/targets/horus/keys_driver.cpp b/radio/src/targets/horus/keys_driver.cpp index 1a4b96830db..a20d373973e 100644 --- a/radio/src/targets/horus/keys_driver.cpp +++ b/radio/src/targets/horus/keys_driver.cpp @@ -211,12 +211,12 @@ void readKeysAndTrims() } \ break -#if !defined(BOOT) uint8_t keyState(uint8_t index) { return keys[index].state(); } +#if !defined(BOOT) uint32_t switchState(uint8_t index) { uint32_t xxx = 0; diff --git a/radio/src/targets/horus/stm32_ramboot.ld b/radio/src/targets/horus/stm32_ramboot.ld new file mode 100644 index 00000000000..d7fa9d338c2 --- /dev/null +++ b/radio/src/targets/horus/stm32_ramboot.ld @@ -0,0 +1,186 @@ +/* +***************************************************************************** +** +** File : stm32f4_flash.ld +** +** Abstract : Linker script for STM32F439 Device with +** 2MByte FLASH, 192KByte SRAM, 64KByte CCM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20030000; /* end of 192K RAM */ +_heap_end = 0xD0800000; /* end of 8192K SDRAM */ + +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0; /* required amount of heap */ +_Main_Stack_Size = 1024; /* required amount of stack for interrupt stack (Main stack) */ + +/* Main stack end */ +_main_stack_start = _estack - _Main_Stack_Size; + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K + CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K + MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K + SDRAM(xrw) : ORIGIN = 0xD0000000, LENGTH = 8192K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + KEEP(*(.version)) + KEEP(*(.bootversiondata)) + . = ALIGN(4); /* Align the start of the text part */ + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + .ARM.extab : + { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array*)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = .; + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >CCM + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + /* __bss_start__ = _sbss; */ + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + } >CCM + + /* Non-zeroed data section */ + . = ALIGN(4); + .noinit (NOLOAD) : + { + *(.noinit) + } >CCM + + /* collect all uninitialized .ccm sections */ + .ram (NOLOAD) : + { + . = ALIGN(4); + _sram = .; + *(.ram) + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + . = . + _Min_Heap_Size; + . = . + _Main_Stack_Size; + . = ALIGN(4); + } >RAM + + /* MEMORY_bank1 section, code must be located here explicitly */ + /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ + .memory_b1_text : + { + *(.mb1text) /* .mb1text sections (code) */ + *(.mb1text*) /* .mb1text* sections (code) */ + *(.mb1rodata) /* read-only data (constants) */ + *(.mb1rodata*) + } >MEMORY_B1 + + .sdram (NOLOAD) : + { + *(.sdram) + *(.sdram*) + *(.sdram_rodata) + *(.sdram_rodata*) + . = ALIGN(4); + _eram = .; + } >SDRAM + + PROVIDE ( end = _eram ); + PROVIDE ( _end = _eram ); + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/radio/src/targets/horus/stm32f4_flash.ld b/radio/src/targets/horus/stm32f4_flash.ld index 47bffc1f278..7ab6ee4f0ba 100644 --- a/radio/src/targets/horus/stm32f4_flash.ld +++ b/radio/src/targets/horus/stm32f4_flash.ld @@ -52,6 +52,11 @@ SECTIONS CREATE_OBJECT_SYMBOLS + KEEP(*(.bootloader)) /* Bootloader code */ + + . = 0x20000; /* Set the start of the main program */ + _stext = .; /* Provide the name for the start of this section */ + . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ KEEP(*(.fwversiondata)) *(.text) /* .text sections (code) */ @@ -60,7 +65,7 @@ SECTIONS *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) + *(.eh_frame) KEEP (*(.init)) KEEP (*(.fini)) diff --git a/radio/src/targets/sky9x/CMakeLists.txt b/radio/src/targets/sky9x/CMakeLists.txt index 75f46956ecb..068e19bb881 100644 --- a/radio/src/targets/sky9x/CMakeLists.txt +++ b/radio/src/targets/sky9x/CMakeLists.txt @@ -67,6 +67,7 @@ set(GUI_SRC set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} + ../common/arm/loadboot.cpp core_cm3.c board_lowlevel.c crt.c @@ -109,11 +110,6 @@ set(TARGET_SRC audio_driver.cpp ) -set(FIRMWARE_SRC - ${FIRMWARE_SRC} - loadboot.cpp - ) - set(SRC ${SRC} debug.cpp diff --git a/radio/src/targets/sky9x/board.cpp b/radio/src/targets/sky9x/board.cpp index 359559c6165..fca8b297cee 100644 --- a/radio/src/targets/sky9x/board.cpp +++ b/radio/src/targets/sky9x/board.cpp @@ -401,15 +401,6 @@ void i2cInit() void boardInit() { - // TODO this is not clean, completely unuseful, but prevents the bootloader from being optimized away... - uint8_t dummy[3]; - memcpy(&dummy, BootCode, sizeof(dummy)); - for (unsigned int i=0; iRSTC_SR; diff --git a/radio/src/targets/sky9x/sam3s4c_flash.ld b/radio/src/targets/sky9x/sam3s4c_flash.ld index 1a7c1104170..4e3f55b3e6a 100644 --- a/radio/src/targets/sky9x/sam3s4c_flash.ld +++ b/radio/src/targets/sky9x/sam3s4c_flash.ld @@ -71,15 +71,14 @@ SECTIONS */ .text : { - FILL(0xFFFF) - - CREATE_OBJECT_SYMBOLS + FILL(0xFFFF) + + CREATE_OBJECT_SYMBOLS - *(.bootrodata) - *(.bootrodata.*) + KEEP(*(.bootloader)) /* Bootloader code */ - . = ALIGN(32768); /* Align the start of the exidx part */ - _stext = .; /* Provide the name for the start of this section */ + . = ALIGN(32768); /* Align the start of the exidx part */ + _stext = .; /* Provide the name for the start of this section */ KEEP(*(.vectors)) diff --git a/radio/src/targets/sky9x/sam3s8c_flash.ld b/radio/src/targets/sky9x/sam3s8c_flash.ld index 833e56e6944..010f7040808 100644 --- a/radio/src/targets/sky9x/sam3s8c_flash.ld +++ b/radio/src/targets/sky9x/sam3s8c_flash.ld @@ -71,15 +71,14 @@ SECTIONS */ .text : { - FILL(0xFFFF) + FILL(0xFFFF) CREATE_OBJECT_SYMBOLS - *(.bootrodata) - *(.bootrodata.*) - + KEEP(*(.bootloader)) + . = ALIGN(32768); /* Align the start of the exidx part */ - _stext = .; /* Provide the name for the start of this section */ + _stext = .; /* Provide the name for the start of this section */ KEEP(*(.vectors)) *(.text) diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index f678b1fb566..98dc5de2f55 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -25,6 +25,7 @@ if(PCB STREQUAL X9E) endif() set(GUI_DIR 212x64) set(BITMAPS_TARGET taranis_bitmaps) + set(FONTS_TARGET taranis_fonts) set(LCD_DRIVER lcd_driver_spi.cpp) set(GVAR_SCREEN model_gvars.cpp) elseif(PCB STREQUAL X9D+) @@ -38,6 +39,7 @@ elseif(PCB STREQUAL X9D+) add_definitions(-DEEPROM_VARIANT=0) set(GUI_DIR 212x64) set(BITMAPS_TARGET taranis_bitmaps) + set(FONTS_TARGET taranis_fonts) set(LCD_DRIVER lcd_driver_spi.cpp) set(SERIAL2_DRIVER ../common/arm/stm32/serial2_driver.cpp) set(GVAR_SCREEN model_gvars.cpp) @@ -52,6 +54,7 @@ elseif(PCB STREQUAL X9D) add_definitions(-DEEPROM_VARIANT=0) set(GUI_DIR 212x64) set(BITMAPS_TARGET taranis_bitmaps) + set(FONTS_TARGET taranis_fonts) set(LCD_DRIVER lcd_driver_aspi.cpp) set(SERIAL2_DRIVER ../common/arm/stm32/serial2_driver.cpp) set(GVAR_SCREEN model_gvars.cpp) @@ -68,6 +71,7 @@ elseif(PCB STREQUAL X7) add_definitions(-DPWR_BUTTON_${PWR_BUTTON}) set(GUI_DIR 128x64) set(BITMAPS_TARGET 9x_bitmaps) + set(FONTS_TARGET 9x_fonts_1bit) set(LCD_DRIVER lcd_driver_spi.cpp) endif() @@ -124,17 +128,12 @@ set(TARGET_SRC ../common/arm/stm32/adc_driver.cpp ) -set(FIRMWARE_SRC - ${FIRMWARE_SRC} - loadboot.cpp - ) - set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} ${LCD_DRIVER} i2c_driver.cpp pwr_driver.cpp - flash_driver.cpp + ../common/arm/loadboot.cpp ) if(LCD_DUAL_BUFFER) diff --git a/radio/src/targets/taranis/board.cpp b/radio/src/targets/taranis/board.cpp index 7de3b5042f7..1ef74ee8da7 100644 --- a/radio/src/targets/taranis/board.cpp +++ b/radio/src/targets/taranis/board.cpp @@ -51,21 +51,21 @@ void init2MhzTimer() // Starts TIMER at 200Hz (5ms) void init5msTimer() { - INTERRUPT_5MS_TIMER->ARR = 4999 ; // 5mS - INTERRUPT_5MS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1 ; // 1uS from 30MHz - INTERRUPT_5MS_TIMER->CCER = 0 ; - INTERRUPT_5MS_TIMER->CCMR1 = 0 ; - INTERRUPT_5MS_TIMER->EGR = 0 ; - INTERRUPT_5MS_TIMER->CR1 = 5 ; - INTERRUPT_5MS_TIMER->DIER |= 1 ; - NVIC_EnableIRQ(INTERRUPT_5MS_IRQn) ; - NVIC_SetPriority(INTERRUPT_5MS_IRQn, 7); + INTERRUPT_xMS_TIMER->ARR = 4999 ; // 5mS in uS + INTERRUPT_xMS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1 ; // 1uS + INTERRUPT_xMS_TIMER->CCER = 0 ; + INTERRUPT_xMS_TIMER->CCMR1 = 0 ; + INTERRUPT_xMS_TIMER->EGR = 0 ; + INTERRUPT_xMS_TIMER->CR1 = 5 ; + INTERRUPT_xMS_TIMER->DIER |= 1 ; + NVIC_EnableIRQ(INTERRUPT_xMS_IRQn) ; + NVIC_SetPriority(INTERRUPT_xMS_IRQn, 7); } void stop5msTimer( void ) { - INTERRUPT_5MS_TIMER->CR1 = 0 ; // stop timer - NVIC_DisableIRQ(INTERRUPT_5MS_IRQn) ; + INTERRUPT_xMS_TIMER->CR1 = 0 ; // stop timer + NVIC_DisableIRQ(INTERRUPT_xMS_IRQn) ; } // TODO use the same than board_sky9x.cpp @@ -93,9 +93,9 @@ void interrupt5ms() } #if !defined(SIMU) -extern "C" void INTERRUPT_5MS_IRQHandler() +extern "C" void INTERRUPT_xMS_IRQHandler() { - INTERRUPT_5MS_TIMER->SR &= ~TIM_SR_UIF ; + INTERRUPT_xMS_TIMER->SR &= ~TIM_SR_UIF ; interrupt5ms() ; DEBUG_INTERRUPT(INT_5MS); } @@ -147,9 +147,27 @@ void sportUpdatePowerOff() void boardInit() { #if !defined(SIMU) - RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | PCBREV_RCC_AHB1Periph | KEYS_RCC_AHB1Periph | LCD_RCC_AHB1Periph | AUDIO_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | ADC_RCC_AHB1Periph | I2C_RCC_AHB1Periph | SD_RCC_AHB1Periph | HAPTIC_RCC_AHB1Periph | INTMODULE_RCC_AHB1Periph | EXTMODULE_RCC_AHB1Periph | TELEMETRY_RCC_AHB1Periph | SPORT_UPDATE_RCC_AHB1Periph | SERIAL_RCC_AHB1Periph | TRAINER_RCC_AHB1Periph | HEARTBEAT_RCC_AHB1Periph | BT_RCC_AHB1Periph, ENABLE); - RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | AUDIO_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | INTERRUPT_5MS_APB1Periph | TIMER_2MHz_APB1Periph | I2C_RCC_APB1Periph | SD_RCC_APB1Periph | TRAINER_RCC_APB1Periph | TELEMETRY_RCC_APB1Periph | SERIAL_RCC_APB1Periph | BT_RCC_APB1Periph, ENABLE); - RCC_APB2PeriphClockCmd(BACKLIGHT_RCC_APB2Periph | ADC_RCC_APB2Periph | HAPTIC_RCC_APB2Periph | INTMODULE_RCC_APB2Periph | EXTMODULE_RCC_APB2Periph | HEARTBEAT_RCC_APB2Periph | BT_RCC_APB2Periph, ENABLE); + RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | PCBREV_RCC_AHB1Periph | + KEYS_RCC_AHB1Periph | LCD_RCC_AHB1Periph | + AUDIO_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | + ADC_RCC_AHB1Periph | I2C_RCC_AHB1Periph | + SD_RCC_AHB1Periph | HAPTIC_RCC_AHB1Periph | + INTMODULE_RCC_AHB1Periph | EXTMODULE_RCC_AHB1Periph | + TELEMETRY_RCC_AHB1Periph | SPORT_UPDATE_RCC_AHB1Periph | + SERIAL_RCC_AHB1Periph | TRAINER_RCC_AHB1Periph | + HEARTBEAT_RCC_AHB1Periph | BT_RCC_AHB1Periph, ENABLE); + + RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | AUDIO_RCC_APB1Periph | + BACKLIGHT_RCC_APB1Periph | INTERRUPT_xMS_RCC_APB1Periph | + TIMER_2MHz_RCC_APB1Periph | I2C_RCC_APB1Periph | + SD_RCC_APB1Periph | TRAINER_RCC_APB1Periph | + TELEMETRY_RCC_APB1Periph | SERIAL_RCC_APB1Periph | + BT_RCC_APB1Periph, ENABLE); + + RCC_APB2PeriphClockCmd(BACKLIGHT_RCC_APB2Periph | ADC_RCC_APB2Periph | + HAPTIC_RCC_APB2Periph | INTMODULE_RCC_APB2Periph | + EXTMODULE_RCC_APB2Periph | HEARTBEAT_RCC_APB2Periph | + BT_RCC_APB2Periph, ENABLE); #if !defined(PCBX9E) // some X9E boards need that the pwrInit() is moved a little bit later diff --git a/radio/src/targets/taranis/bootloader/.gitignore b/radio/src/targets/taranis/bootloader/.gitignore deleted file mode 100644 index eaeb7d8c513..00000000000 --- a/radio/src/targets/taranis/bootloader/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/bootloader_ramBoot.* -/.dep - diff --git a/radio/src/targets/taranis/bootloader/boot.cpp b/radio/src/targets/taranis/bootloader/boot.cpp deleted file mode 100644 index 5b5dd0fe1f3..00000000000 --- a/radio/src/targets/taranis/bootloader/boot.cpp +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * 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 "opentx.h" -#include "stamp.h" - -#if defined(PCBX7) - #define BOOTLOADER_TITLE " X7 Bootloader - " VERSION -#elif defined(PCBTARANIS) - #define BOOTLOADER_TITLE " Taranis Bootloader - " VERSION -#else - #error "Not implemented" -#endif - -#if defined(PCBX9E) || defined(PCBX7) - #define BOOT_KEY_UP KEY_MINUS - #define BOOT_KEY_DOWN KEY_PLUS -#else - #define BOOT_KEY_UP KEY_PLUS - #define BOOT_KEY_DOWN KEY_MINUS -#endif -#define BOOT_KEY_LEFT KEY_MENU -#define BOOT_KEY_RIGHT KEY_PAGE -#define BOOT_KEY_MENU KEY_ENTER -#define BOOT_KEY_EXIT KEY_EXIT -#define DISPLAY_CHAR_WIDTH 35 - -#if LCD_W >= 212 - #define STR_OR_PLUGIN_USB_CABLE INDENT "Or plug in a USB cable for mass storage" - #define STR_HOLD_ENTER_TO_START "\012Hold [ENT] to start writing" - #define STR_INVALID_FIRMWARE "\011Not a valid firmware file! " - #define STR_INVALID_EEPROM "\011Not a valid EEPROM file! " -#else - #define STR_OR_PLUGIN_USB_CABLE INDENT "Or plug in a USB cable" - #define STR_HOLD_ENTER_TO_START "\006Hold [ENT] to start" - #define STR_INVALID_FIRMWARE "\004Not a valid firmware! " - #define STR_INVALID_EEPROM "\004Not a valid EEPROM! " -#endif - -#define STR_USB_CONNECTED CENTER "\011USB Connected" - -const uint8_t bootloaderVersion[] __attribute__ ((section(".version"), used)) = -{ - 'B', 'O', 'O', 'T', '1', '0' -}; - -#if defined(ROTARY_ENCODER_NAVIGATION) -volatile rotenc_t rotencValue[1] = {0}; -#endif - -// states -enum BootLoaderStates { - ST_START, - ST_FLASH_MENU, - ST_DIR_CHECK, - ST_OPEN_DIR, - ST_FILE_LIST, - ST_FLASH_CHECK, - ST_FLASHING, - ST_FLASH_DONE, - ST_RESTORE_MENU, - ST_USB, - ST_REBOOT, -}; - -enum MemoryTypes { - MEM_FLASH, - MEM_EEPROM -}; - -/*---------------------------------------------------------------------------- - * Local variables - *----------------------------------------------------------------------------*/ - -uint32_t FirmwareSize; -uint32_t firmwareAddress = FIRMWARE_ADDRESS; -uint32_t firmwareWritten = 0; -uint32_t eepromAddress = 0; -uint32_t eepromWritten = 0; - -TCHAR backupFilename[_MAX_LFN+1]; - -uint32_t Master_frequency; -volatile uint8_t Tenms; - -FIL FlashFile; -DIR Dj; -FILINFO Finfo; - -TCHAR Filenames[20][_MAX_LFN + 1]; -uint32_t FileSize[20]; -uint32_t Valid; - -#define BLOCK_LEN 4096 -uint8_t Block_buffer[BLOCK_LEN]; -UINT BlockCount; - -uint32_t memoryType; - -uint32_t unlocked = 0; - -void interrupt10ms(void) -{ - Tenms |= 1; // 10 mS has passed - - uint8_t index = KEY_MENU; - uint8_t in = readKeys(); - for (uint8_t i = 1; i != uint8_t(1 << TRM_BASE); i <<= 1) { - uint8_t value = (in & i); - keys[index].input(value); - ++index; - } - -#if defined(PCBX9E) || defined(PCBX7) - checkRotaryEncoder(); - static rotenc_t rePreviousValue; - rotenc_t reNewValue = (rotencValue[0] / 2); - int8_t scrollRE = reNewValue - rePreviousValue; - if (scrollRE) { - rePreviousValue = reNewValue; - if (scrollRE < 0) { - putEvent(EVT_KEY_FIRST(KEY_MINUS)); - } - else { - putEvent(EVT_KEY_FIRST(KEY_PLUS)); - } - } -#endif -} - -void init10msTimer() -{ - INTERRUPT_5MS_TIMER->ARR = 9999; // 10mS - INTERRUPT_5MS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1uS from 12MHz - INTERRUPT_5MS_TIMER->CCER = 0; - INTERRUPT_5MS_TIMER->CCMR1 = 0; - INTERRUPT_5MS_TIMER->EGR = 0; - INTERRUPT_5MS_TIMER->CR1 = 5; - INTERRUPT_5MS_TIMER->DIER |= 1; - NVIC_EnableIRQ(INTERRUPT_5MS_IRQn); -} - -extern "C" void INTERRUPT_5MS_IRQHandler() -{ - INTERRUPT_5MS_TIMER->SR &= ~TIM_SR_UIF; - interrupt10ms(); -} - -FRESULT readBinDir(DIR *dj, FILINFO *fno) -{ - FRESULT fr; - uint32_t loop; - do { - loop = 0; - fr = f_readdir(dj, fno); // First entry - - if (fr != FR_OK || fno->fname[0] == 0) { - break; - } - int32_t len = strlen(fno->fname) - 4; - if (len < 0) { - loop = 1; - } - if (fno->fname[len] != '.') { - loop = 1; - } - if ((fno->fname[len + 1] != 'b') && (fno->fname[len + 1] != 'B')) { - loop = 1; - } - if ((fno->fname[len + 2] != 'i') && (fno->fname[len + 2] != 'I')) { - loop = 1; - } - if ((fno->fname[len + 3] != 'n') && (fno->fname[len + 3] != 'N')) { - loop = 1; - } - - } while (loop); - return fr; -} - -uint32_t fillNames(uint32_t index) -{ - uint32_t i; - FRESULT fr; - fr = f_readdir(&Dj, 0); // rewind - for (i = 0; i <= index; ++i) { - fr = readBinDir(&Dj, &Finfo); // First entry - if (fr == FR_NO_FILE) { - return 0; - } - } - strAppend(Filenames[0], Finfo.fname); - FileSize[0] = Finfo.fsize; - for (i = 1; i < 7; i += 1) { - fr = readBinDir(&Dj, &Finfo); - if (fr != FR_OK || Finfo.fname[0] == 0) { - break; - } - strAppend(Filenames[i], Finfo.fname); - FileSize[i] = Finfo.fsize; - } - return i; -} - -const char *getBinaryPath() -{ - if (memoryType == MEM_FLASH) - return FIRMWARES_PATH; - else - return EEPROMS_PATH; -} - -FRESULT openBinaryFile(uint32_t index) -{ - TCHAR filename[_MAX_LFN+1]; - FRESULT fr; - memset(Block_buffer, 0, sizeof(Block_buffer)); - strAppend(strAppend(strAppend(filename, getBinaryPath()), "/"), Filenames[index]); - if ((fr = f_open(&FlashFile, filename, FA_READ)) != FR_OK) { - return fr; - } - if (memoryType == MEM_FLASH) { - if ((fr = f_lseek(&FlashFile, BOOTLOADER_SIZE)) != FR_OK) { - return fr; - } - } - fr = f_read(&FlashFile, Block_buffer, BLOCK_LEN, &BlockCount); - - if (BlockCount == BLOCK_LEN) - return fr; - else - return FR_INVALID_OBJECT; -} - -uint32_t isValidBufferStart(const uint8_t * buffer) -{ - if (memoryType == MEM_FLASH) - return isFirmwareStart(buffer); - else - return isEepromStart(buffer); -} - -int menuFlashFile(uint32_t index, event_t event) -{ - FRESULT fr; - - lcdDrawTextAlignedLeft(4*FH, STR_HOLD_ENTER_TO_START); - - if (Valid == 0) { - // Validate file here - if ((fr = openBinaryFile(index))) { - Valid = 2; - } - else { - if ((fr = f_close(&FlashFile))) { - Valid = 2; - } - else { - Valid = 1; - } - if (!isValidBufferStart(Block_buffer)) { - Valid = 2; - } - } - } - - if (Valid == 2) { - if (memoryType == MEM_FLASH) - lcdDrawTextAlignedLeft(4*FH, STR_INVALID_FIRMWARE); - else - lcdDrawTextAlignedLeft(4*FH, STR_INVALID_EEPROM); - if (event == EVT_KEY_BREAK(BOOT_KEY_EXIT) || event == EVT_KEY_BREAK(BOOT_KEY_MENU)) { - return 0; - } - return -1; - } - - if (event == EVT_KEY_LONG(BOOT_KEY_MENU)) { - fr = openBinaryFile(index); - return (fr == FR_OK && isValidBufferStart(Block_buffer)); - } - else if (event == EVT_KEY_FIRST(BOOT_KEY_EXIT)) { - return 0; - } - - return -1; -} - -extern Key keys[]; - -static uint32_t PowerUpDelay; - -void flashWriteBlock() -{ - uint32_t blockOffset = 0; - 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; - } - } -} - -void writeEepromBlock() -{ - eepromWriteBlock(Block_buffer, eepromAddress, BlockCount); - eepromAddress += BlockCount; -} - -int main() -{ - uint8_t index = 0; - uint8_t maxhsize = DISPLAY_CHAR_WIDTH; - FRESULT fr; - uint32_t state = ST_START; - uint32_t nameCount = 0; - uint32_t vpos = 0; - uint32_t hpos = 0; - -#if defined(PCBTARANIS) - wdt_reset(); - RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | KEYS_RCC_AHB1Periph | LCD_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | I2C_RCC_AHB1Periph | SD_RCC_AHB1Periph, ENABLE); - RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | BACKLIGHT_RCC_APB1Periph | INTERRUPT_5MS_APB1Periph | I2C_RCC_APB1Periph | SD_RCC_APB1Periph, ENABLE); - RCC_APB2PeriphClockCmd(BACKLIGHT_RCC_APB2Periph, ENABLE); -#endif - - pwrInit(); - delaysInit(); // needed for lcdInit() - lcdInit(); - backlightInit(); - - lcdClear(); - lcdDrawSizedText(0, 0, (const char *)bootloaderVersion, 0); // trick to avoid bootloaderVersion to be optimized out ... - lcdDrawTextAlignedLeft(0, BOOTLOADER_TITLE); - lcdInvertLine(0); - lcdRefresh(); - - keysInit(); - i2cInit(); - - __enable_irq(); - init10msTimer(); - -#if defined(PCBTARANIS) - // SD card detect pin - sdInit(); - usbInit(); -#endif - - for (;;) { - wdt_reset(); - - if (Tenms) { - Tenms = 0; - - lcdRefreshWait(); - lcdClear(); - lcdDrawTextAlignedLeft(0, BOOTLOADER_TITLE); - lcdInvertLine(0); - - event_t event = getEvent(); - - if (state != ST_USB) { - if (usbPlugged()) { - state = ST_USB; - if (!unlocked) { - unlocked = 1; - unlockFlash(); - } - usbStart(); - usbPluggedIn(); - } - } - - if (state == ST_START) { - lcdDrawTextAlignedLeft(2*FH, "\010Write Firmware"); - lcdDrawTextAlignedLeft(3*FH, "\010Restore EEPROM"); - lcdDrawTextAlignedLeft(4*FH, "\010Exit"); -#if LCD_W >= 212 - lcdDrawTextAlignedLeft(6*FH, "\001Curr FW:"); - lcdDrawText(50, 6*FH, getOtherVersion()); -#else - lcdDrawTextAlignedLeft(6*FH, "\001FW:"); - - // Remove opentx- from string - const char* other_ver = getOtherVersion(); - if (strstr(other_ver, "opentx-")) - other_ver = other_ver+7; - lcdDrawText(20, 6*FH, other_ver); -#endif - lcdInvertLine(2+vpos); - lcdDrawTextAlignedLeft(7*FH, STR_OR_PLUGIN_USB_CABLE); - if (event == EVT_KEY_FIRST(BOOT_KEY_DOWN)) { - vpos == 2 ? vpos = 0 : vpos = vpos+1; - } - else if (event == EVT_KEY_FIRST(BOOT_KEY_UP)) { - vpos == 0 ? vpos = 2 : vpos = vpos-1; - } - else if (event == EVT_KEY_BREAK(BOOT_KEY_MENU)) { - switch (vpos) { - case 0: - state = ST_FLASH_MENU; - break; - case 1: - state = ST_RESTORE_MENU; - break; - default: - state = ST_REBOOT; - } - } - } - - if (state == ST_USB) { - lcdDrawTextAlignedLeft(4*FH, STR_USB_CONNECTED); - if (usbPlugged() == 0) { - vpos = 0; - usbStop(); - if (unlocked) { - lockFlash(); - unlocked = 0; - } - state = ST_START; - } - } - - if (state == ST_FLASH_MENU || state == ST_RESTORE_MENU) { - sdInit(); - memoryType = (state == ST_RESTORE_MENU ? MEM_EEPROM : MEM_FLASH); - state = ST_DIR_CHECK; - } - - else if (state == ST_DIR_CHECK) { - fr = f_chdir(getBinaryPath()); - if (fr == FR_OK) { - state = ST_OPEN_DIR; - } - else { - lcdDrawTextAlignedLeft(2*FH, INDENT "Directory is missing!"); - if (event == EVT_KEY_BREAK(BOOT_KEY_EXIT) || event == EVT_KEY_BREAK(BOOT_KEY_MENU)) { - vpos = 0; - state = ST_START; - } - } - } - - if (state == ST_OPEN_DIR) { - index = 0; - fr = f_opendir(&Dj, "."); - if (fr == FR_OK) { - state = ST_FILE_LIST; - nameCount = fillNames(0); - hpos = 0; - vpos = 0; - } - } - - if (state == ST_FILE_LIST) { - uint32_t limit = 6; - if (nameCount < limit) { - limit = nameCount; - } - maxhsize = 0; - for (uint32_t i=0; i maxhsize) { - maxhsize = x; - } - if (x > DISPLAY_CHAR_WIDTH) { - if (hpos + DISPLAY_CHAR_WIDTH > x) { - x = x - DISPLAY_CHAR_WIDTH; - } - else { - x = hpos; - } - } - else { - x = 0; - } - lcdDrawSizedText(INDENT_WIDTH, 16 + FH * i, &Filenames[i][x], DISPLAY_CHAR_WIDTH, 0); - } - - if (event == EVT_KEY_REPT(BOOT_KEY_DOWN) || event == EVT_KEY_FIRST(BOOT_KEY_DOWN)) { - if (vpos < limit - 1) { - vpos += 1; - } - else { - if (nameCount > limit) { - index += 1; - nameCount = fillNames(index); - } - } - } - else if (event == EVT_KEY_REPT(BOOT_KEY_UP) || event == EVT_KEY_FIRST(BOOT_KEY_UP)) { - if (vpos > 0) { - vpos -= 1; - } - else { - if (index) { - index -= 1; - nameCount = fillNames(index); - } - } - } -#if !defined(PCBTARANIS) - else if (event == EVT_KEY_REPT(BOOT_KEY_RIGHT) || event == EVT_KEY_FIRST(BOOT_KEY_RIGHT)) { - if (hpos + DISPLAY_CHAR_WIDTH < maxhsize) { - hpos += 1; - } - } - else if (event == EVT_KEY_REPT(BOOT_KEY_LEFT) || event == EVT_KEY_FIRST(BOOT_KEY_LEFT)) { - if (hpos) { - hpos -= 1; - } - } -#endif - else if (event == EVT_KEY_BREAK(BOOT_KEY_MENU)) { - // Select file to flash - state = ST_FLASH_CHECK; - Valid = 0; - } - else if (event == EVT_KEY_FIRST(BOOT_KEY_EXIT)) { - state = ST_START; - vpos = 0; - } - - lcdInvertLine(2 + vpos); - } - - else if (state == ST_FLASH_CHECK) { - int result = menuFlashFile(vpos, event); - FirmwareSize = FileSize[vpos] - BOOTLOADER_SIZE; - if (result == 0) { - // canceled - state = ST_FILE_LIST; - } - else if (result == 1) { - // confirmed - firmwareAddress = FIRMWARE_ADDRESS + BOOTLOADER_SIZE; - firmwareWritten = 0; - eepromAddress = 0; - eepromWritten = 0; - state = ST_FLASHING; - } - } - - else if (state == ST_FLASHING) { - // commit to flashing - lcdDrawTextAlignedLeft(4*FH, CENTER "\015Writing..."); - - if (!unlocked && (memoryType == MEM_FLASH)) { - unlocked = 1; - unlockFlash(); - } - - int progress; - if (memoryType == MEM_FLASH) { - flashWriteBlock(); - firmwareWritten += sizeof(Block_buffer); - progress = ((LCD_W-12)*firmwareWritten) / FirmwareSize; - } - else { - writeEepromBlock(); - eepromWritten += sizeof(Block_buffer); - progress = ((LCD_W-12)*eepromWritten) / EEPROM_SIZE; - } - - lcdDrawRect(3, 6*FH+4, (LCD_W-8), 7); - lcdDrawSolidHorizontalLine(5, 6*FH+6, progress, FORCE); - lcdDrawSolidHorizontalLine(5, 6*FH+7, progress, FORCE); - lcdDrawSolidHorizontalLine(5, 6*FH+8, progress, FORCE); - - fr = f_read(&FlashFile, Block_buffer, sizeof(Block_buffer), &BlockCount); - if (BlockCount == 0) { - state = ST_FLASH_DONE; // EOF - } - if (firmwareWritten >= FLASHSIZE - BOOTLOADER_SIZE) { - state = ST_FLASH_DONE; // Backstop - } - if (eepromWritten >= EEPROM_SIZE) { - state = ST_FLASH_DONE; // Backstop - } - } - - if (state == ST_FLASH_DONE) { - if (unlocked) { - lockFlash(); - unlocked = 0; - } - lcdDrawTextAlignedLeft(4*FH, CENTER "\007Writing complete"); - if (event == EVT_KEY_FIRST(BOOT_KEY_EXIT) || event == EVT_KEY_BREAK(BOOT_KEY_MENU)) { - state = ST_START; - vpos = 0; - } - } - - if (event == EVT_KEY_LONG(BOOT_KEY_EXIT)) { - state = ST_REBOOT; - } - - lcdRefresh(); - - if (PowerUpDelay < 20) { // 200 mS - PowerUpDelay += 1; - } - else { - sdPoll10ms(); - } - } - - if (state != ST_FLASHING && state != ST_USB) { - if (pwrOffPressed()) { - lcdOff(); // this drains LCD caps - pwrOff(); - for (;;) { - // Wait for power to go off - } - } - } - - if (state == ST_REBOOT) { - if (readKeys() == 0) { - lcdClear(); - lcdRefresh(); - lcdRefreshWait(); - RCC->CSR |= RCC_CSR_RMVF; // clear the reset flags in RCC clock control & status register - NVIC_SystemReset(); - } - } - } - - return 0; -} diff --git a/radio/src/targets/taranis/bootloader/boot_menu.cpp b/radio/src/targets/taranis/bootloader/boot_menu.cpp new file mode 100644 index 00000000000..1d7835569cf --- /dev/null +++ b/radio/src/targets/taranis/bootloader/boot_menu.cpp @@ -0,0 +1,91 @@ +#include "opentx.h" +#include "../../common/arm/stm32/bootloader/boot.h" +#include "../../common/arm/stm32/bootloader/bin_files.h" + +extern MemoryType memoryType; + +void bootloaderInitScreen() +{ +} + +static void bootloaderDrawMsg(unsigned int x, const char* str, uint8_t line, bool inverted) +{ + lcdDrawSizedText(x, (line + 2) * FH, str, DISPLAY_CHAR_WIDTH, inverted ? INVERS : 0); +} + +void bootloaderDrawFilename(const char* str, uint8_t line, bool selected) +{ + bootloaderDrawMsg(INDENT_WIDTH, str, line, selected); +} + +void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) +{ + lcdClear(); + lcdDrawText(0, 0, BOOTLOADER_TITLE, INVERS); + + if (st == ST_START) { + lcdDrawTextAlignedLeft(2*FH, "\010Write Firmware"); + lcdDrawTextAlignedLeft(3*FH, "\010Restore EEPROM"); + lcdDrawTextAlignedLeft(4*FH, "\010Exit"); + +#if LCD_W >= 212 + lcdDrawTextAlignedLeft(6*FH, "\001Curr FW:"); + lcdDrawText(50, 6*FH, getOtherVersion(nullptr)); +#else + lcdDrawTextAlignedLeft(6*FH, "\001FW:"); + + // Remove opentx- from string + const char* other_ver = getOtherVersion(nullptr); + if (strstr(other_ver, "opentx-")) + other_ver = other_ver+7; + lcdDrawText(20, 6*FH, other_ver); +#endif + + lcdInvertLine(2+opt); + lcdDrawTextAlignedLeft(7*FH, STR_OR_PLUGIN_USB_CABLE); + } + else if (st == ST_USB) { + lcdDrawTextAlignedLeft(4*FH, STR_USB_CONNECTED); + } + else if (st == ST_DIR_CHECK) { + if (opt == FR_NO_PATH) { + bootloaderDrawMsg(INDENT_WIDTH, "Directory is missing!", 1, false); + bootloaderDrawMsg(INDENT_WIDTH, getBinaryPath(memoryType), 2, false); + } + else { + bootloaderDrawMsg(INDENT_WIDTH, "Directory is empty!", 1, false); + } + } + else if (st == ST_FLASH_CHECK) { + if (opt == FC_ERROR) { + + if (memoryType == MEM_FLASH) + bootloaderDrawMsg(0, STR_INVALID_FIRMWARE, 2, false); + else + bootloaderDrawMsg(0, STR_INVALID_EEPROM, 2, false); + } + else if (opt == FC_OK) { + + const char* vers = getOtherVersion((char*)Block_buffer); +#if LCD_W < 212 + // Remove opentx- from string + if (strstr(vers, "opentx-")) + vers = vers+7; +#endif + bootloaderDrawMsg(INDENT_WIDTH, vers, 0, false); + bootloaderDrawMsg(0, STR_HOLD_ENTER_TO_START, 2, false); + } + } + else if (st == ST_FLASHING) { + lcdDrawTextAlignedLeft(4*FH, CENTER "\015Writing..."); + + lcdDrawRect(3, 6*FH+4, (LCD_W-8), 7); + lcdDrawSolidHorizontalLine(5, 6*FH+6, (LCD_W-12) * opt / 100, FORCE); + lcdDrawSolidHorizontalLine(5, 6*FH+7, (LCD_W-12) * opt / 100, FORCE); + lcdDrawSolidHorizontalLine(5, 6*FH+8, (LCD_W-12) * opt / 100, FORCE); + } + else if (st == ST_FLASH_DONE) { + + lcdDrawTextAlignedLeft(4*FH, CENTER "\007Writing complete"); + } +} diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index afb8bdb4ef6..7c3857ab8f0 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -433,9 +433,14 @@ #if defined(PCBX9E) || defined(PCBX7) #define PWR_PRESS_BUTTON #endif + #define PWR_GPIO GPIOD +#define PWR_SWITCH_GPIO_REG PWR_GPIO->IDR #define PWR_SWITCH_GPIO_PIN GPIO_Pin_1 // PD.01 #define PWR_ON_GPIO_PIN GPIO_Pin_0 // PD.00 +#define PWR_ON_GPIO_MODER GPIO_MODER_MODER0 +#define PWR_ON_GPIO_MODER_OUT GPIO_MODER_MODER0_0 + #if defined(PCBX7) #define LED_GREEN_GPIO GPIOC #define LED_GREEN_GPIO_PIN GPIO_Pin_4 // PC.04 @@ -697,6 +702,8 @@ #define LCD_RST_GPIO GPIOD #define LCD_RST_GPIO_PIN GPIO_Pin_12 // PD.12 #endif +#define LCD_RCC_APB2Periph 0 + // I2C Bus: EEPROM and CAT5137 digital pot for volume control #define I2C_RCC_AHB1Periph RCC_AHB1Periph_GPIOB @@ -828,14 +835,14 @@ #define BT_RCC_APB2Periph 0 #endif -// 5ms Interrupt -#define INTERRUPT_5MS_APB1Periph RCC_APB1Periph_TIM14 -#define INTERRUPT_5MS_TIMER TIM14 -#define INTERRUPT_5MS_IRQn TIM8_TRG_COM_TIM14_IRQn -#define INTERRUPT_5MS_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler +// Xms Interrupt +#define INTERRUPT_xMS_RCC_APB1Periph RCC_APB1Periph_TIM14 +#define INTERRUPT_xMS_TIMER TIM14 +#define INTERRUPT_xMS_IRQn TIM8_TRG_COM_TIM14_IRQn +#define INTERRUPT_xMS_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler // 2MHz Timer -#define TIMER_2MHz_APB1Periph RCC_APB1Periph_TIM7 +#define TIMER_2MHz_RCC_APB1Periph RCC_APB1Periph_TIM7 #define TIMER_2MHz_TIMER TIM7 #endif // _HAL_H_ diff --git a/radio/src/targets/taranis/stm32_ramboot.ld b/radio/src/targets/taranis/stm32_ramboot.ld index f2e6e555a2d..05df857a6b5 100644 --- a/radio/src/targets/taranis/stm32_ramboot.ld +++ b/radio/src/targets/taranis/stm32_ramboot.ld @@ -47,7 +47,7 @@ SECTIONS { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ - *(.version) + KEEP(*(.bootversiondata)) . = ALIGN(4); /* Align the start of the text part */ *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ @@ -62,36 +62,36 @@ SECTIONS . = ALIGN(4); _etext = .; /* define a global symbols at end of code */ - } >RAM + } >FLASH - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >RAM + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; - } >RAM + } >FLASH .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)) PROVIDE_HIDDEN (__preinit_array_end = .); - } >RAM + } >FLASH .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array*)) PROVIDE_HIDDEN (__init_array_end = .); - } >RAM + } >FLASH .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(.fini_array*)) KEEP (*(SORT(.fini_array.*))) PROVIDE_HIDDEN (__fini_array_end = .); - } >RAM + } >FLASH /* used by the startup to initialize data */ _sidata = .; diff --git a/radio/src/targets/taranis/stm32f2_flash.ld b/radio/src/targets/taranis/stm32f2_flash.ld index 3d72e6a95e4..e696af60499 100644 --- a/radio/src/targets/taranis/stm32f2_flash.ld +++ b/radio/src/targets/taranis/stm32f2_flash.ld @@ -50,10 +50,7 @@ SECTIONS CREATE_OBJECT_SYMBOLS - KEEP(*(.isr_boot_vector)) /* Startup code */ - KEEP(*(.bootversiondata)) - *(.bootrodata) - *(.bootrodata.*) + KEEP(*(.bootloader)) /* Bootloader code */ . = 32768; /* Set the start of the main program */ _stext = .; /* Provide the name for the start of this section */ diff --git a/radio/src/targets/taranis/stm32f4_flash.ld b/radio/src/targets/taranis/stm32f4_flash.ld index c3732e799ce..7d5706c5528 100644 --- a/radio/src/targets/taranis/stm32f4_flash.ld +++ b/radio/src/targets/taranis/stm32f4_flash.ld @@ -51,14 +51,11 @@ SECTIONS CREATE_OBJECT_SYMBOLS - KEEP(*(.isr_boot_vector)) /* Startup code */ - KEEP(*(.bootversiondata)) - *(.bootrodata) - *(.bootrodata.*) + KEEP(*(.bootloader)) /* Bootloader code */ - . = 32768; /* Set the start of the main program */ + . = 0x8000; /* Set the start of the main program */ _stext = .; /* Provide the name for the start of this section */ - . = ALIGN(4); + . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ KEEP(*(.fwversiondata)) *(.text) /* .text sections (code) */ @@ -67,7 +64,7 @@ SECTIONS *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) + *(.eh_frame) KEEP (*(.init)) KEEP (*(.fini))