1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-22 07:45:14 +03:00

Horus bootloader (#5455)

Horus bootloader
This commit is contained in:
Raphael Coeffic 2017-12-19 12:13:59 +01:00 committed by Bertrand Songis
parent 908adb4d2b
commit 0d7832b208
54 changed files with 1772 additions and 1038 deletions

View file

@ -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()

View file

@ -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

View file

@ -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()

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

View file

@ -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

View file

@ -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];

View file

@ -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;

View file

@ -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 };

View file

@ -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()
{

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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++) {

View 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"
};

View file

@ -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}

View 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")

View 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);
}

View 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

View 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

View 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

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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)

View file

@ -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
}

View file

@ -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();

View file

@ -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(...)

View 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);
}
}

View file

@ -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()
{

View file

@ -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

View file

@ -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;

View 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) }
}

View file

@ -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) */

View file

@ -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

View file

@ -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;

View file

@ -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 */

View file

@ -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 */

View file

@ -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)

View file

@ -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

View file

@ -1,3 +0,0 @@
/bootloader_ramBoot.*
/.dep

View file

@ -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;
}

View 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");
}
}

View file

@ -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_

View file

@ -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 = .;

View file

@ -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 */

View file

@ -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 */