|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
BIN
radio/src/bitmaps/480x272/bootloader/bmp_plug_usb.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
radio/src/bitmaps/480x272/bootloader/bmp_usb_plugged.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
radio/src/bitmaps/480x272/bootloader/icon_error.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
radio/src/bitmaps/480x272/bootloader/icon_exit.png
Normal file
After Width: | Height: | Size: 641 B |
BIN
radio/src/bitmaps/480x272/bootloader/icon_file.png
Normal file
After Width: | Height: | Size: 276 B |
BIN
radio/src/bitmaps/480x272/bootloader/icon_flash.png
Normal file
After Width: | Height: | Size: 696 B |
BIN
radio/src/bitmaps/480x272/bootloader/icon_ok.png
Normal file
After Width: | Height: | Size: 823 B |
BIN
radio/src/bitmaps/480x272/bootloader/icon_sd.png
Normal file
After Width: | Height: | Size: 514 B |
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#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<len; ++i) {
|
||||
char c;
|
||||
if (flags & ZCHAR)
|
||||
c = idx2char(*s);
|
||||
else
|
||||
c = *s;
|
||||
|
||||
#if !defined(BOOT)
|
||||
char c = (flags & ZCHAR) ? idx2char(*s) : *s;
|
||||
#else
|
||||
char c = *s;
|
||||
#endif
|
||||
if (c == '\0')
|
||||
break;
|
||||
result += getCharWidth(c, specs);
|
||||
|
@ -175,7 +177,6 @@ void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags flags, uint8_t le
|
|||
lcdDrawText(x, y, s, flags);
|
||||
}
|
||||
|
||||
#if !defined(BOOT)
|
||||
void lcdDrawLine(coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
int dx = x2-x1; /* the horizontal distance of the line */
|
||||
|
@ -218,8 +219,8 @@ void lcdDrawLine(coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t pat, Lc
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOT)
|
||||
void drawRtcTime(coord_t x, coord_t y, LcdFlags flags)
|
||||
{
|
||||
drawTimer(x, y, getValue(MIXSRC_TX_TIME), flags);
|
||||
|
@ -388,6 +389,7 @@ void drawGPSSensorValue(coord_t x, coord_t y, TelemetryItem & telemetryItem, Lcd
|
|||
{
|
||||
drawGPSPosition(x, y, telemetryItem.gps.longitude, telemetryItem.gps.latitude, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
void lcdSetContrast()
|
||||
{
|
||||
|
|
|
@ -87,8 +87,14 @@ enum FontSizeIndex {
|
|||
#define XXLSIZE (XXLSIZE_INDEX << 8)
|
||||
#define BOLD (STDSIZE_BOLD_INDEX << 8)
|
||||
#define FONTSIZE_MASK 0x0f00
|
||||
|
||||
#if !defined(BOOT)
|
||||
#define FONTSIZE(flags) ((flags) & FONTSIZE_MASK)
|
||||
#define FONTINDEX(flags) (FONTSIZE(flags) >> 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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++) {
|
||||
|
|
25
radio/src/targets/common/arm/loadboot.cpp
Normal file
|
@ -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"
|
||||
};
|
|
@ -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}
|
||||
|
|
130
radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt
Normal file
|
@ -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")
|
145
radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp
Normal file
|
@ -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);
|
||||
}
|
88
radio/src/targets/common/arm/stm32/bootloader/bin_files.h
Normal file
|
@ -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
|
523
radio/src/targets/common/arm/stm32/bootloader/boot.cpp
Normal file
|
@ -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<limit; i++) {
|
||||
bootloaderDrawFilename(binFiles[i].name, i, (vpos == i));
|
||||
}
|
||||
|
||||
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
// Select file to flash
|
||||
state = ST_FLASH_CHECK;
|
||||
Valid = FC_UNCHECKED;
|
||||
continue;
|
||||
}
|
||||
else if (event == EVT_KEY_BREAK(KEY_EXIT)) {
|
||||
state = ST_START;
|
||||
vpos = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (state == ST_FLASH_CHECK) {
|
||||
|
||||
bootloaderDrawScreen(state, Valid, binFiles[vpos].name);
|
||||
|
||||
int result = menuFlashFile(vpos, event);
|
||||
if (result == 0) {
|
||||
// canceled
|
||||
state = ST_FILE_LIST;
|
||||
}
|
||||
else if (result == 1) {
|
||||
// confirmed
|
||||
|
||||
if (memoryType == MEM_FLASH) {
|
||||
FirmwareSize = binFiles[vpos].size - BOOTLOADER_SIZE;
|
||||
firmwareAddress = FIRMWARE_ADDRESS + BOOTLOADER_SIZE;
|
||||
firmwareWritten = 0;
|
||||
}
|
||||
#if defined(EEPROM)
|
||||
else {
|
||||
eepromAddress = 0;
|
||||
eepromWritten = 0;
|
||||
}
|
||||
#endif
|
||||
state = ST_FLASHING;
|
||||
}
|
||||
}
|
||||
|
||||
else if (state == ST_FLASHING) {
|
||||
// commit to flashing
|
||||
if (!unlocked && (memoryType == MEM_FLASH)) {
|
||||
unlocked = 1;
|
||||
unlockFlash();
|
||||
}
|
||||
|
||||
int progress = 0;
|
||||
if (memoryType == MEM_FLASH) {
|
||||
flashWriteBlock();
|
||||
firmwareWritten += sizeof(Block_buffer);
|
||||
progress = (100*firmwareWritten) / FirmwareSize;
|
||||
}
|
||||
#if defined(EEPROM)
|
||||
else {
|
||||
writeEepromBlock();
|
||||
eepromWritten += sizeof(Block_buffer);
|
||||
progress = (100*eepromWritten) / EEPROM_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
bootloaderDrawScreen(state, progress);
|
||||
|
||||
fr = readBinFile();
|
||||
if (BlockCount == 0) {
|
||||
state = ST_FLASH_DONE; // EOF
|
||||
}
|
||||
else if ((memoryType == MEM_FLASH) &&
|
||||
(firmwareWritten >= 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
|
80
radio/src/targets/common/arm/stm32/bootloader/boot.h
Normal file
|
@ -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
|
|
@ -70,30 +70,61 @@ 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);
|
||||
#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);
|
||||
}
|
||||
else if ((uint32_t) address == 0x08004000) {
|
||||
eraseSector(1);
|
||||
// test 128KB sectors
|
||||
else if (SECTOR_ADDRESS == 0x20000) {
|
||||
eraseSector(5 + FLASH_BANK);
|
||||
}
|
||||
else if ((uint32_t) address == 0x08008000) {
|
||||
eraseSector(2);
|
||||
else if (SECTOR_ADDRESS == 0x40000) {
|
||||
eraseSector(6 + FLASH_BANK);
|
||||
}
|
||||
else if ((uint32_t) address == 0x0800C000) {
|
||||
eraseSector(3);
|
||||
else if (SECTOR_ADDRESS == 0x60000) {
|
||||
eraseSector(7 + FLASH_BANK);
|
||||
}
|
||||
else if ((uint32_t) address == 0x08010000) {
|
||||
eraseSector(4);
|
||||
else if (SECTOR_ADDRESS == 0x80000) {
|
||||
eraseSector(8 + FLASH_BANK);
|
||||
}
|
||||
else if ((uint32_t) address == 0x08020000) {
|
||||
eraseSector(5);
|
||||
else if (SECTOR_ADDRESS == 0xA0000) {
|
||||
eraseSector(9 + FLASH_BANK);
|
||||
}
|
||||
else if ((uint32_t) address == 0x08040000) {
|
||||
eraseSector(6);
|
||||
else if (SECTOR_ADDRESS == 0xC0000) {
|
||||
eraseSector(10 + FLASH_BANK);
|
||||
}
|
||||
else if ((uint32_t) address == 0x08060000) {
|
||||
eraseSector(7);
|
||||
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; i<FLASH_PAGESIZE/4; i++) {
|
||||
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
|
||||
|
@ -127,23 +158,29 @@ uint32_t isFirmwareStart(const uint8_t * buffer)
|
|||
{
|
||||
const uint32_t * block = (const uint32_t *)buffer;
|
||||
|
||||
#if defined(PCBX9E)
|
||||
#if defined(STM32F4)
|
||||
// Stack pointer in CCM or RAM
|
||||
if ((block[0] & 0xFFFC0000) != 0x10000000 && (block[0] & 0xFFFC0000) != 0x20000000) {
|
||||
return 0;
|
||||
}
|
||||
// First ISR pointer in FLASH
|
||||
if ((block[1] & 0xFFF00000) != 0x08000000) {
|
||||
return 0;
|
||||
}
|
||||
// Second ISR pointer in FLASH
|
||||
if ((block[2] & 0xFFF00000) != 0x08000000) {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
// Stack pointer in RAM
|
||||
if ((block[0] & 0xFFFC0000) != 0x20000000) {
|
||||
return 0;
|
||||
}
|
||||
// First ISR pointer in FLASH
|
||||
if ((block[1] & 0xFFF00000) != 0x08000000) {
|
||||
return 0;
|
||||
}
|
||||
// Second ISR pointer in FLASH
|
||||
if ((block[2] & 0xFFF00000) != 0x08000000) {
|
||||
return 0;
|
||||
}
|
|
@ -408,7 +408,7 @@ const FATDirEntry_t g_DIRroot[] =
|
|||
0xA302,
|
||||
0x3D55,
|
||||
0x0002,
|
||||
sizeof(firmware_txt) + strlen(getOtherVersion())
|
||||
sizeof(firmware_txt) + strlen(getOtherVersion(nullptr))
|
||||
},
|
||||
{
|
||||
{ 'F', 'I', 'R', 'M', 'W', 'A', 'R', 'E'},
|
||||
|
@ -515,7 +515,7 @@ int32_t fat12Read(uint8_t * buffer, uint16_t sector, uint16_t count)
|
|||
else if (sector == 4)
|
||||
{
|
||||
memcpy(buffer, firmware_txt, sizeof(firmware_txt));
|
||||
memcpy(buffer + sizeof(firmware_txt), getOtherVersion(), strlen(getOtherVersion()));
|
||||
memcpy(buffer + sizeof(firmware_txt), getOtherVersion(nullptr), strlen(getOtherVersion(nullptr)));
|
||||
}
|
||||
else if (sector < RESERVED_SECTORS)
|
||||
{
|
||||
|
|
|
@ -31,7 +31,10 @@ if (PCB STREQUAL X10)
|
|||
../common/arm/stm32/adc_driver.cpp
|
||||
pwm_driver.cpp
|
||||
)
|
||||
set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} x10_bitmaps)
|
||||
|
||||
set(BITMAPS_TARGET x10_bitmaps)
|
||||
set(FONTS_TARGET x10_fonts)
|
||||
set(LCD_DRIVER lcd_driver.cpp)
|
||||
set(LUA_EXPORT lua_export_x10)
|
||||
elseif (PCB STREQUAL X12S)
|
||||
set(FLAVOUR x12s)
|
||||
|
@ -52,11 +55,16 @@ elseif (PCB STREQUAL X12S)
|
|||
adc_driver.cpp
|
||||
gps_driver.cpp
|
||||
)
|
||||
set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} x12s_bitmaps)
|
||||
|
||||
set(BITMAPS_TARGET x12s_bitmaps)
|
||||
set(FONTS_TARGET x12s_fonts)
|
||||
set(LCD_DRIVER lcd_driver.cpp)
|
||||
set(LUA_EXPORT lua_export_x12s)
|
||||
add_definitions(-DPCBREV=${PCBREV})
|
||||
endif()
|
||||
|
||||
set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} ${BITMAPS_TARGET})
|
||||
|
||||
add_definitions(-DPCBHORUS -DSTM32F429_439xx -DSDRAM -DCOLORLCD -DPPM_PIN_UART -DPPM_PIN_TIMER)
|
||||
add_definitions(-DEEPROM_VARIANT=0 -DAUDIO -DVOICE -DRTCLOCK)
|
||||
add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE})
|
||||
|
@ -119,11 +127,12 @@ set(TARGET_SRC
|
|||
set(FIRMWARE_TARGET_SRC
|
||||
${FIRMWARE_TARGET_SRC}
|
||||
sdio_sd.c
|
||||
lcd_driver.cpp
|
||||
${LCD_DRIVER}
|
||||
backlight_driver.cpp
|
||||
pwr_driver.cpp
|
||||
sdram_driver.c
|
||||
startup_stm32f42_43xxx.s
|
||||
../common/arm/loadboot.cpp
|
||||
)
|
||||
|
||||
add_definitions(-DBLUETOOTH)
|
||||
|
|
|
@ -24,44 +24,44 @@ void backlightInit()
|
|||
{
|
||||
// PIN init
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = BL_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Pin = BACKLIGHT_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(BL_GPIO, &GPIO_InitStructure);
|
||||
GPIO_PinAFConfig(BL_GPIO, BL_GPIO_PinSource, BL_GPIO_AF);
|
||||
GPIO_Init(BACKLIGHT_GPIO, &GPIO_InitStructure);
|
||||
GPIO_PinAFConfig(BACKLIGHT_GPIO, BACKLIGHT_GPIO_PinSource, BACKLIGHT_GPIO_AF);
|
||||
|
||||
// TIMER init
|
||||
#if defined(PCBX12S)
|
||||
if (IS_HORUS_PROD()) {
|
||||
BL_TIMER->ARR = 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
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(...)
|
||||
|
||||
|
|
172
radio/src/targets/horus/bootloader/boot_menu.cpp
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
186
radio/src/targets/horus/stm32_ramboot.ld
Normal file
|
@ -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) }
|
||||
}
|
|
@ -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) */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; i<sizeof(dummy); i++) {
|
||||
if (dummy[i] == 0) {
|
||||
__asm("nop");
|
||||
}
|
||||
}
|
||||
|
||||
Pio *pioptr ;
|
||||
|
||||
ResetReason = RSTC->RSTC_SR;
|
||||
|
|
|
@ -75,8 +75,7 @@ SECTIONS
|
|||
|
||||
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 */
|
||||
|
|
|
@ -75,8 +75,7 @@ SECTIONS
|
|||
|
||||
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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
/bootloader_ramBoot.*
|
||||
/.dep
|
||||
|
|
@ -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<limit; i++) {
|
||||
uint32_t x;
|
||||
x = strlen(Filenames[i]);
|
||||
if (x > 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;
|
||||
}
|
91
radio/src/targets/taranis/bootloader/boot_menu.cpp
Normal file
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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_
|
||||
|
|
|
@ -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 = .;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -51,12 +51,9 @@ 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);
|
||||
KEEP(*(.isr_vector)) /* Startup code */
|
||||
|
|