chore(radio): unify the bootloader UI code (#6189)
Co-authored-by: Richard Li <richard.li@ces.hk>
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
__attribute__ ((section(".bootloader"), used))
|
||||
|
||||
const unsigned char BootCode[] = {
|
||||
#include "bootloader.lbm"
|
||||
};
|
||||
@@ -1,112 +0,0 @@
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
AddHardwareDefTarget(${HW_DESC_JSON})
|
||||
AddHWGenTarget(${HW_DESC_JSON} hal_keys hal_keys.inc)
|
||||
|
||||
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/hal_keys.inc
|
||||
${RADIO_SRC_DIR}/os/time_nortos.cpp
|
||||
${RADIO_SRC_DIR}/os/sleep_nortos.cpp
|
||||
${RADIO_SRC_DIR}/keys.cpp
|
||||
${RADIO_SRC_DIR}/strhelpers.cpp
|
||||
${RADIO_SRC_DIR}/stamp.cpp
|
||||
${RADIO_SRC_DIR}/syscalls.c
|
||||
${RADIO_SRC_DIR}/crc.cpp
|
||||
boot.cpp
|
||||
)
|
||||
|
||||
if(FIRMWARE_FORMAT_UF2)
|
||||
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
|
||||
boot_uf2.cpp
|
||||
boot_dfu.cpp
|
||||
${RADIO_SRC_DIR}/io/uf2.cpp
|
||||
${RADIO_SRC_DIR}/drivers/uf2_ghostfat.cpp
|
||||
)
|
||||
else()
|
||||
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
|
||||
boot_menu.cpp
|
||||
bin_fw_files.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(DEBUG_SEGGER_RTT)
|
||||
set(BOOTLOADER_SRC ${BOOTLOADER_SRC}
|
||||
${RADIO_SRC_DIR}/thirdparty/Segger_RTT/RTT/SEGGER_RTT.c
|
||||
)
|
||||
endif()
|
||||
|
||||
# TODO: this shouldn't be needed at all
|
||||
remove_definitions(-DDISK_CACHE)
|
||||
remove_definitions(-DLUA)
|
||||
remove_definitions(-DCLI)
|
||||
remove_definitions(-DSEMIHOSTING)
|
||||
remove_definitions(-DUSB_SERIAL)
|
||||
|
||||
if(NOT NO_LTO)
|
||||
message("-- Use LTO to compile bootloader")
|
||||
target_compile_options(stm32cube_ll PRIVATE -flto)
|
||||
target_compile_options(stm32usb PRIVATE -flto)
|
||||
target_compile_options(stm32usb_device_bl PRIVATE -flto)
|
||||
target_compile_options(stm32usb_device_fw PRIVATE -flto)
|
||||
target_compile_options(stm32_drivers PRIVATE -flto)
|
||||
target_compile_options(stm32_drivers_w_dbg_fw PRIVATE -flto)
|
||||
target_compile_options(stm32_drivers_w_dbg_bl PRIVATE -flto)
|
||||
endif()
|
||||
|
||||
add_executable(bootloader EXCLUDE_FROM_ALL ${BOOTLOADER_SRC})
|
||||
add_dependencies(bootloader ${BITMAPS_TARGET})
|
||||
|
||||
target_compile_definitions(bootloader PUBLIC BOOT)
|
||||
target_compile_definitions(board_bl PUBLIC BOOT)
|
||||
|
||||
if(ARCH STREQUAL ARM)
|
||||
target_link_libraries(bootloader PUBLIC cmsis)
|
||||
endif()
|
||||
|
||||
target_link_options(bootloader BEFORE PRIVATE
|
||||
-L${LINKER_DIR}/${TARGET_LINKER_DIR}/bootloader
|
||||
-T${LINKER_DIR}/bootloader.ld
|
||||
-Wl,-Map=bootloader.map,--cref,--no-warn-mismatch,--gc-sections
|
||||
-lm --specs=nano.specs
|
||||
)
|
||||
|
||||
if (DEFINED TARGET_EXTRAM_START)
|
||||
target_link_options(bootloader PRIVATE
|
||||
-Wl,--defsym=__EXTRAM_START__=${TARGET_EXTRAM_START}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (DEFINED TARGET_EXTRAM_SIZE)
|
||||
target_link_options(bootloader PRIVATE
|
||||
-Wl,--defsym=__EXTRAM_SIZE__=${TARGET_EXTRAM_SIZE}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (ENABLE_BOOTLOADER_DEBUG)
|
||||
target_compile_definitions(board_bl PRIVATE -DDEBUG)
|
||||
target_compile_definitions(bootloader PRIVATE -DDEBUG)
|
||||
target_sources(bootloader PRIVATE
|
||||
${RADIO_SRC_DIR}/serial.cpp
|
||||
)
|
||||
# uncomment to enable TRACE in drivers
|
||||
# target_compile_definitions(stm32_drivers_w_dbg_bl PRIVATE -DDEBUG)
|
||||
endif()
|
||||
|
||||
target_include_directories(bootloader
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
TARGET bootloader POST_BUILD
|
||||
COMMAND ${CMAKE_OBJCOPY} -O binary bootloader.elf ${CMAKE_BINARY_DIR}/bootloader.bin
|
||||
)
|
||||
|
||||
if(PYTHONINTERP_FOUND)
|
||||
add_custom_command(
|
||||
TARGET bootloader POST_BUILD
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/bin2lbm.py ${CMAKE_BINARY_DIR}/bootloader.bin bootloader.lbm
|
||||
)
|
||||
endif()
|
||||
|
||||
PrintTargetReport("bootloader")
|
||||
@@ -1,288 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <strings.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "boot.h"
|
||||
#include "board.h"
|
||||
#include "sdcard.h"
|
||||
#include "firmware_files.h"
|
||||
#include "fw_version.h"
|
||||
#include "strhelpers.h"
|
||||
#include "hal/storage.h"
|
||||
#include "flash_driver.h"
|
||||
|
||||
// Size of the block read when checking / writing BIN files
|
||||
#define BLOCK_LEN 4096
|
||||
|
||||
// 'private'
|
||||
static DIR dir;
|
||||
static FIL FlashFile;
|
||||
|
||||
static uint32_t firmwareSize;
|
||||
static uint32_t firmwareAddress = FIRMWARE_ADDRESS;
|
||||
static uint32_t firmwareWritten = 0;
|
||||
uint32_t unlocked = 0;
|
||||
|
||||
struct FWFileInfo {
|
||||
TCHAR name[FF_MAX_LFN + 1];
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
// 'public' variables
|
||||
static FWFileInfo fwFiles[MAX_FW_FILES];
|
||||
static uint8_t Block_buffer[BLOCK_LEN];
|
||||
static UINT BlockCount;
|
||||
|
||||
static void flashWriteBlock()
|
||||
{
|
||||
// TODO: use some board provided driver instead
|
||||
uint32_t blockOffset = 0;
|
||||
#if !defined(SIMU)
|
||||
while (BlockCount) {
|
||||
flashWrite((uint32_t *)firmwareAddress, (uint32_t *)&Block_buffer[blockOffset]);
|
||||
blockOffset += FLASH_PAGESIZE;
|
||||
firmwareAddress += FLASH_PAGESIZE;
|
||||
if (BlockCount > FLASH_PAGESIZE) {
|
||||
BlockCount -= FLASH_PAGESIZE;
|
||||
}
|
||||
else {
|
||||
BlockCount = 0;
|
||||
}
|
||||
}
|
||||
#endif // SIMU
|
||||
}
|
||||
|
||||
void sdInit(void)
|
||||
{
|
||||
storageInit();
|
||||
|
||||
static FATFS fatFS __DMA;
|
||||
if (f_mount(&fatFS, "", 1) == FR_OK) {
|
||||
f_chdir("/");
|
||||
}
|
||||
}
|
||||
|
||||
void sdDone()
|
||||
{
|
||||
// unmount
|
||||
f_mount(nullptr, "", 0);
|
||||
storageDeInit();
|
||||
}
|
||||
|
||||
FRESULT openFirmwareDir()
|
||||
{
|
||||
FRESULT fr = f_chdir(getFirmwarePath());
|
||||
if (fr != FR_OK) return fr;
|
||||
|
||||
return f_opendir(&dir, ".");
|
||||
}
|
||||
|
||||
static uint32_t isValidBufferStart(const uint8_t * buffer)
|
||||
{
|
||||
#if !defined(SIMU)
|
||||
return isFirmwareStart(buffer);
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
FlashCheckRes checkFirmwareFile(unsigned int index, FlashCheckRes res)
|
||||
{
|
||||
if (res != FC_UNCHECKED)
|
||||
return res;
|
||||
|
||||
if (openFirmwareFile(index) != FR_OK)
|
||||
return FC_ERROR;
|
||||
|
||||
if (closeFirmwareFile() != FR_OK)
|
||||
return FC_ERROR;
|
||||
|
||||
if (!isValidBufferStart(Block_buffer))
|
||||
return FC_ERROR;
|
||||
|
||||
return FC_OK;
|
||||
}
|
||||
|
||||
|
||||
static FRESULT findNextBinFile(FILINFO* fno)
|
||||
{
|
||||
FRESULT fr;
|
||||
|
||||
do {
|
||||
fr = f_readdir(&dir, fno);
|
||||
|
||||
if (fr != FR_OK || fno->fname[0] == 0)
|
||||
break;
|
||||
if (fno->fattrib & (AM_HID | AM_SYS | AM_DIR))
|
||||
continue; // Skip folders and hidden files
|
||||
if (fno->fname[0] == '.' && fno->fname[1] != '.')
|
||||
continue; // Ignore hidden files under UNIX, but not ..
|
||||
|
||||
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 fetchFirmwareFiles(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(fwFiles[0].name, file_info.fname);
|
||||
fwFiles[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(fwFiles[i].name, file_info.fname);
|
||||
fwFiles[i].size = file_info.fsize;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
const char* getFirmwareFileNameByIndex(unsigned int index)
|
||||
{
|
||||
if(index >= MAX_FW_FILES)
|
||||
return "";
|
||||
|
||||
return fwFiles[index].name;
|
||||
}
|
||||
|
||||
FRESULT openFirmwareFile(unsigned int index)
|
||||
{
|
||||
TCHAR full_path[FF_MAX_LFN+1];
|
||||
FRESULT res;
|
||||
|
||||
// build full_path: [bin path]/[filename]
|
||||
char* s = strAppend(full_path, getFirmwarePath());
|
||||
s = strAppend(s, "/");
|
||||
strAppend(s, fwFiles[index].name);
|
||||
|
||||
BlockCount = 0;
|
||||
|
||||
// open the file
|
||||
res = f_open(&FlashFile, full_path, FA_READ);
|
||||
if (res != FR_OK) return res;
|
||||
|
||||
// skip bootloader in firmware
|
||||
res = f_lseek(&FlashFile, BOOTLOADER_SIZE);
|
||||
if (res != FR_OK) return res;
|
||||
|
||||
// ... and fetch BLOCK_LEN bytes
|
||||
res = f_read(&FlashFile, Block_buffer, BLOCK_LEN, &BlockCount);
|
||||
if (BlockCount == BLOCK_LEN && isValidBufferStart(Block_buffer)) return res;
|
||||
|
||||
f_close(&FlashFile);
|
||||
return FR_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
void getFileFirmwareVersion(VersionTag* tag)
|
||||
{
|
||||
memset(tag->flavour, 0, sizeof(tag->flavour));
|
||||
const char * vers = getFirmwareVersion((const uint8_t *)Block_buffer);
|
||||
if (!vers || (vers[0] == 'n' && vers[1] == 'o')) { // "no version found"
|
||||
memcpy(tag->flavour, "unknown", sizeof("unknown"));
|
||||
tag->version = "unknown";
|
||||
tag->flavour[sizeof(tag->flavour)-1] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
tag->fork = vers;
|
||||
|
||||
// skip 'edgetx-' / 'opentx-'
|
||||
vers += sizeof("edgetx-") - 1;
|
||||
|
||||
char* fl = tag->flavour;
|
||||
while(*vers != '-')
|
||||
*(fl++) = *(vers++);
|
||||
tag->flavour[sizeof(tag->flavour)-1] = 0;
|
||||
|
||||
// skip '-'
|
||||
tag->version = ++vers;
|
||||
}
|
||||
|
||||
FRESULT readFirmwareFile()
|
||||
{
|
||||
BlockCount = 0;
|
||||
return f_read(&FlashFile, Block_buffer, sizeof(Block_buffer), &BlockCount);
|
||||
}
|
||||
|
||||
FRESULT closeFirmwareFile()
|
||||
{
|
||||
return f_close(&FlashFile);
|
||||
}
|
||||
|
||||
void firmwareInitWrite(uint32_t index)
|
||||
{
|
||||
firmwareSize = fwFiles[index].size - BOOTLOADER_SIZE;
|
||||
firmwareAddress = FIRMWARE_ADDRESS + BOOTLOADER_SIZE;
|
||||
firmwareWritten = 0;
|
||||
}
|
||||
|
||||
bool firmwareWriteBlock(uint32_t* progress)
|
||||
{
|
||||
flashWriteBlock();
|
||||
firmwareWritten += sizeof(Block_buffer);
|
||||
*progress = (100 * firmwareWritten) / firmwareSize;
|
||||
|
||||
readFirmwareFile();
|
||||
if (BlockCount == 0 || firmwareWritten >= FLASHSIZE - BOOTLOADER_SIZE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "boot.h"
|
||||
|
||||
#include "hal/usb_driver.h"
|
||||
#include "hal/abnormal_reboot.h"
|
||||
#include "hal/rotary_encoder.h"
|
||||
|
||||
#include "board.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "timers_driver.h"
|
||||
|
||||
#if defined(BLUETOOTH)
|
||||
#include "bluetooth_driver.h"
|
||||
#include "stm32_serial_driver.h"
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_SEGGER_RTT)
|
||||
#include "thirdparty/Segger_RTT/RTT/SEGGER_RTT.h"
|
||||
#endif
|
||||
|
||||
#define REBOOT_CMD_DFU 0x55464442
|
||||
|
||||
#if !defined(SIMU)
|
||||
// Bootloader marker:
|
||||
// -> used to detect valid bootloader files
|
||||
const uint8_t bootloaderVersion[] __attribute__ ((section(".version"), used)) =
|
||||
{'B', 'O', 'O', 'T', '1', '0'};
|
||||
#endif
|
||||
|
||||
#if defined(SIMU)
|
||||
#define __weak
|
||||
#elif !defined(__weak)
|
||||
#define __weak __attribute__((weak))
|
||||
#endif
|
||||
|
||||
#if !defined(SIMU)
|
||||
|
||||
typedef void (*fctptr_t)(void);
|
||||
|
||||
static __attribute__((noreturn)) void jumpTo(uint32_t addr)
|
||||
{
|
||||
__disable_irq();
|
||||
__set_MSP(*(uint32_t*)addr);
|
||||
fctptr_t reset_handler = (fctptr_t)*(uint32_t*)(addr + 4);
|
||||
reset_handler();
|
||||
while(1){}
|
||||
}
|
||||
|
||||
// Optional board hook
|
||||
__weak void boardBLEarlyInit() {}
|
||||
__weak bool boardBLStartCondition() { return false; }
|
||||
__weak void boardBLPreJump() {}
|
||||
__weak void boardBLInit() {}
|
||||
|
||||
void bootloaderInitApp()
|
||||
{
|
||||
boardBLEarlyInit();
|
||||
|
||||
#if defined(DEBUG_SEGGER_RTT)
|
||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
|
||||
#endif
|
||||
|
||||
pwrInit();
|
||||
keysInit();
|
||||
delaysInit();
|
||||
|
||||
bool boot_dfu = abnormalRebootGetCmd() == REBOOT_CMD_DFU;
|
||||
if (!boot_dfu) {
|
||||
bool start_firmware = true;
|
||||
|
||||
// wait a bit for the inputs to stabilize...
|
||||
if (!WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) {
|
||||
delay_ms(10);
|
||||
}
|
||||
|
||||
start_firmware = !boardBLStartCondition();
|
||||
if (start_firmware) {
|
||||
// Start main application
|
||||
boardBLPreJump();
|
||||
jumpTo(APP_START_ADDRESS);
|
||||
}
|
||||
} else {
|
||||
#if defined(FIRMWARE_QSPI)
|
||||
abnormalRebootResetCmd();
|
||||
setSelectedUsbMode(USB_DFU_MODE);
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO: move all this into board specifics
|
||||
pwrOn();
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS)
|
||||
rotaryEncoderInit();
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG)
|
||||
initSerialPorts();
|
||||
#endif
|
||||
|
||||
__enable_irq();
|
||||
|
||||
TRACE("\nBootloader started :)");
|
||||
|
||||
// TODO: move BT into board specifics
|
||||
#if defined(BLUETOOTH)
|
||||
// we shutdown the bluetooth module now to be sure it will be detected on
|
||||
// firmware start
|
||||
bluetoothInit(BLUETOOTH_DEFAULT_BAUDRATE, false);
|
||||
#endif
|
||||
|
||||
timersInit();
|
||||
|
||||
usbInit();
|
||||
boardBLInit();
|
||||
}
|
||||
|
||||
#if defined(FIRMWARE_FORMAT_UF2)
|
||||
// make linker happy
|
||||
void per5ms() {}
|
||||
#endif
|
||||
|
||||
int main()
|
||||
#else // SIMU
|
||||
void bootloaderInitApp() {}
|
||||
int bootloaderMain()
|
||||
#endif
|
||||
{
|
||||
// init hardware (may jump to app)
|
||||
bootloaderInitApp();
|
||||
|
||||
// init screen
|
||||
bootloaderInitScreen();
|
||||
|
||||
#if defined(FIRMWARE_FORMAT_UF2)
|
||||
if (getSelectedUsbMode() == USB_DFU_MODE) {
|
||||
bootloaderDFU();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PWR_BUTTON_PRESS)
|
||||
// wait until power button is released
|
||||
while (pwrPressed()) {}
|
||||
#endif
|
||||
|
||||
#if !defined(FIRMWARE_FORMAT_UF2)
|
||||
bootloaderMenu();
|
||||
#else
|
||||
bootloaderUF2();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "stamp.h"
|
||||
#include "keys.h"
|
||||
|
||||
#include "hal/flash_driver.h"
|
||||
|
||||
#if LCD_W < 212
|
||||
#if defined(VERSION_TAG)
|
||||
#define BOOTLOADER_TITLE " Bootloader - " VERSION_TAG
|
||||
#else
|
||||
#define BOOTLOADER_TITLE " Bootloader " VERSION "-" VERSION_SUFFIX
|
||||
#endif
|
||||
#else
|
||||
#if defined(VERSION_TAG)
|
||||
#define BOOTLOADER_TITLE " EdgeTX Bootloader - " VERSION_TAG
|
||||
#else
|
||||
#define BOOTLOADER_TITLE " EdgeTX Bootloader - " VERSION "-" VERSION_SUFFIX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DISPLAY_CHAR_WIDTH (LCD_COLS+4)
|
||||
|
||||
// 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,
|
||||
#if defined(SPI_FLASH)
|
||||
ST_CLEAR_FLASH_CHECK,
|
||||
ST_CLEAR_FLASH,
|
||||
#endif
|
||||
ST_RADIO_MENU,
|
||||
ST_REBOOT,
|
||||
};
|
||||
|
||||
// interactive bootloader
|
||||
void bootloaderMenu();
|
||||
|
||||
// non-interactive UF2 bootloader
|
||||
void bootloaderUF2();
|
||||
|
||||
// non-interactive DFU bootloader
|
||||
void bootloaderDFU();
|
||||
|
||||
// Declarations of functions that need to be implemented
|
||||
// for each target with a bootloader
|
||||
|
||||
// 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 = nullptr);
|
||||
|
||||
// Once for each file in a filename list on screen
|
||||
void bootloaderDrawFilename(const char* str, uint8_t line, bool selected);
|
||||
|
||||
// get menu item count for main menu, by adding 1 to the baseCount, when a radio specific menu is used
|
||||
uint32_t bootloaderGetMenuItemCount(int baseCount);
|
||||
|
||||
// when a radio specifc menu is used, all events are forwarded to that menu code
|
||||
// returns true on submenu exit
|
||||
bool bootloaderRadioMenu(uint32_t menuItem, event_t event);
|
||||
|
||||
void bootloaderDrawDFUScreen();
|
||||
|
||||
void sdInit();
|
||||
void blExit();
|
||||
@@ -1,31 +0,0 @@
|
||||
#include "stm32_hal.h"
|
||||
|
||||
#include "boot.h"
|
||||
#include "hal/usb_driver.h"
|
||||
#include "os/time.h"
|
||||
|
||||
#include "lcd.h"
|
||||
|
||||
#define FRAME_INTERVAL_MS 20
|
||||
|
||||
void bootloaderDFU()
|
||||
{
|
||||
usbPlugged();
|
||||
usbStart();
|
||||
|
||||
bootloaderDrawDFUScreen();
|
||||
|
||||
uint32_t next_frame = time_get_ms();
|
||||
for (;;) {
|
||||
if (time_get_ms() - next_frame >= FRAME_INTERVAL_MS) {
|
||||
next_frame += FRAME_INTERVAL_MS;
|
||||
|
||||
if (!usbPlugged()) break;
|
||||
bootloaderDrawDFUScreen();
|
||||
lcdRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
blExit();
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
@@ -1,301 +0,0 @@
|
||||
#include "boot.h"
|
||||
#include "firmware_files.h"
|
||||
|
||||
#include "hal/usb_driver.h"
|
||||
#include "hal/rotary_encoder.h"
|
||||
#include "os/time.h"
|
||||
|
||||
#include "lcd.h"
|
||||
|
||||
#define FRAME_INTERVAL_MS 20
|
||||
|
||||
#if defined(SPI_FLASH)
|
||||
#define MAIN_MENU_LEN 3
|
||||
#else
|
||||
#define MAIN_MENU_LEN 2
|
||||
#endif
|
||||
|
||||
#if defined(SPI_FLASH)
|
||||
#include "diskio_spi_flash.h"
|
||||
#define SEL_CLEAR_FLASH_STORAGE_MENU_LEN 2
|
||||
#endif
|
||||
|
||||
void pollInputs()
|
||||
{
|
||||
keysPollingCycle();
|
||||
|
||||
// TODO: use rotaryEncoderPollingCycle() instead
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS)
|
||||
static rotenc_t rePreviousValue;
|
||||
|
||||
rotenc_t reNewValue = rotaryEncoderGetValue();
|
||||
int8_t scrollRE = reNewValue - rePreviousValue;
|
||||
if (scrollRE) {
|
||||
rePreviousValue = reNewValue;
|
||||
pushEvent(scrollRE < 0 ? EVT_ROTARY_LEFT : EVT_ROTARY_RIGHT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// poll inputs every 10ms
|
||||
void per5ms()
|
||||
{
|
||||
static uint32_t cnt = 0;
|
||||
if (++cnt & 1) { pollInputs(); }
|
||||
}
|
||||
|
||||
FlashCheckRes valid;
|
||||
|
||||
int menuFlashFile(uint32_t index, event_t event)
|
||||
{
|
||||
valid = checkFirmwareFile(index, valid);
|
||||
|
||||
if (valid == FC_ERROR) {
|
||||
if (event == EVT_KEY_BREAK(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_ENTER))
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (event == EVT_KEY_LONG(KEY_ENTER)) {
|
||||
return openFirmwareFile(index) == FR_OK ? 1 : -1;
|
||||
} else if (event == EVT_KEY_BREAK(KEY_EXIT))
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void bootloaderMenu()
|
||||
{
|
||||
BootloaderState state = ST_START;
|
||||
uint32_t vpos = 0;
|
||||
uint32_t radioMenuItem = 0;
|
||||
uint8_t index = 0;
|
||||
FRESULT fr;
|
||||
uint32_t nameCount = 0;
|
||||
|
||||
sdInit();
|
||||
|
||||
uint32_t next_frame = time_get_ms();
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (time_get_ms() - next_frame >= FRAME_INTERVAL_MS) {
|
||||
next_frame += FRAME_INTERVAL_MS;
|
||||
|
||||
if (state != ST_USB && state != ST_FLASHING
|
||||
&& state != ST_FLASH_DONE && state != ST_RADIO_MENU) {
|
||||
if (usbPlugged()) {
|
||||
state = ST_USB;
|
||||
#if !defined(SIMU)
|
||||
usbStart();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (state == ST_USB) {
|
||||
if (usbPlugged() == 0) {
|
||||
vpos = 0;
|
||||
#if !defined(SIMU)
|
||||
usbStop();
|
||||
#endif
|
||||
state = ST_START;
|
||||
}
|
||||
bootloaderDrawScreen(state, 0);
|
||||
}
|
||||
|
||||
lcdRefreshWait();
|
||||
event_t event = getEvent();
|
||||
|
||||
if (state == ST_START) {
|
||||
|
||||
bootloaderDrawScreen(state, vpos);
|
||||
|
||||
if (IS_NEXT_EVENT(event)) {
|
||||
if (vpos < bootloaderGetMenuItemCount(MAIN_MENU_LEN) - 1) { vpos++; }
|
||||
continue;
|
||||
}
|
||||
else if (IS_PREVIOUS_EVENT(event)) {
|
||||
if (vpos > 0) { vpos--; }
|
||||
continue;
|
||||
}
|
||||
else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
switch (vpos) {
|
||||
case 0:
|
||||
state = ST_DIR_CHECK;
|
||||
break;
|
||||
#if defined(SPI_FLASH)
|
||||
case 1:
|
||||
state = ST_CLEAR_FLASH_CHECK;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
if(vpos < bootloaderGetMenuItemCount(MAIN_MENU_LEN-1))
|
||||
{
|
||||
state = ST_RADIO_MENU;
|
||||
radioMenuItem = vpos - MAIN_MENU_LEN - 1;
|
||||
} else {
|
||||
state = ST_REBOOT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// next loop
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (state == ST_DIR_CHECK) {
|
||||
fr = openFirmwareDir();
|
||||
|
||||
if (fr == FR_OK) {
|
||||
index = vpos = 0;
|
||||
state = ST_FILE_LIST;
|
||||
nameCount = fetchFirmwareFiles(index);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
bootloaderDrawScreen(state, fr);
|
||||
|
||||
if (event == EVT_KEY_BREAK(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
vpos = 0;
|
||||
state = ST_START;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state == ST_FILE_LIST) {
|
||||
uint32_t limit = MAX_NAMES_ON_SCREEN;
|
||||
if (nameCount < limit) {
|
||||
limit = nameCount;
|
||||
}
|
||||
|
||||
if (IS_NEXT_EVENT(event)) {
|
||||
if (vpos < limit - 1) {
|
||||
vpos += 1;
|
||||
} else {
|
||||
if (nameCount > limit) {
|
||||
index += 1;
|
||||
nameCount = fetchFirmwareFiles(index);
|
||||
}
|
||||
}
|
||||
} else if (IS_PREVIOUS_EVENT(event)) {
|
||||
if (vpos > 0) {
|
||||
vpos -= 1;
|
||||
}
|
||||
else {
|
||||
if (index) {
|
||||
index -= 1;
|
||||
nameCount = fetchFirmwareFiles(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bootloaderDrawScreen(state, 0);
|
||||
|
||||
for (uint32_t i = 0; i < limit; i++) {
|
||||
bootloaderDrawFilename(getFirmwareFileNameByIndex(i), i, (vpos == i));
|
||||
}
|
||||
|
||||
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
// Select file to flash
|
||||
state = ST_FLASH_CHECK;
|
||||
valid = FC_UNCHECKED;
|
||||
continue;
|
||||
} else if (event == EVT_KEY_BREAK(KEY_EXIT)) {
|
||||
state = ST_START;
|
||||
vpos = 0;
|
||||
continue;
|
||||
}
|
||||
} else if (state == ST_FLASH_CHECK) {
|
||||
bootloaderDrawScreen(state, valid, getFirmwareFileNameByIndex(vpos));
|
||||
|
||||
int result = menuFlashFile(vpos, event);
|
||||
if (result == 0) {
|
||||
// canceled
|
||||
state = ST_FILE_LIST;
|
||||
} else if (result == 1) {
|
||||
// confirmed
|
||||
firmwareInitWrite(vpos);
|
||||
state = ST_FLASHING;
|
||||
}
|
||||
} else if (state == ST_FLASHING) {
|
||||
uint32_t progress = 0;
|
||||
bool done = firmwareWriteBlock(&progress);
|
||||
bootloaderDrawScreen(state, progress);
|
||||
if(done) {
|
||||
state = ST_FLASH_DONE;
|
||||
}
|
||||
#if defined(SPI_FLASH)
|
||||
} else if (state == ST_CLEAR_FLASH_CHECK) {
|
||||
bootloaderDrawScreen(state, vpos);
|
||||
if (IS_NEXT_EVENT(event)) {
|
||||
if (vpos < SEL_CLEAR_FLASH_STORAGE_MENU_LEN - 1) { vpos++; }
|
||||
continue;
|
||||
}
|
||||
if (IS_PREVIOUS_EVENT(event)) {
|
||||
if (vpos > 0) { vpos--; }
|
||||
continue;
|
||||
}
|
||||
if (event == EVT_KEY_LONG(KEY_ENTER) && vpos == 0)
|
||||
{
|
||||
state = ST_CLEAR_FLASH;
|
||||
} else if (event == EVT_KEY_BREAK(KEY_EXIT) ||
|
||||
(event == EVT_KEY_BREAK(KEY_ENTER) && vpos == 1) ) {
|
||||
vpos = 0;
|
||||
state = ST_START;
|
||||
continue;
|
||||
}
|
||||
} else if (state == ST_CLEAR_FLASH) {
|
||||
bootloaderDrawScreen(state, 0);
|
||||
lcdRefresh();
|
||||
sdDone();
|
||||
spiFlashDiskEraseAll();
|
||||
sdInit();
|
||||
vpos = 0;
|
||||
state = ST_START;
|
||||
#endif
|
||||
} else if (state == ST_RADIO_MENU) {
|
||||
if(bootloaderRadioMenu(radioMenuItem, event))
|
||||
{
|
||||
state = ST_START;
|
||||
vpos = 0;
|
||||
bootloaderDrawScreen(state, vpos);
|
||||
}
|
||||
}
|
||||
|
||||
if (state == ST_FLASH_DONE) {
|
||||
if (event == EVT_KEY_BREAK(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
state = ST_START;
|
||||
vpos = 0;
|
||||
}
|
||||
|
||||
bootloaderDrawScreen(state, 100);
|
||||
}
|
||||
|
||||
if (event == EVT_KEY_LONG(KEY_EXIT)) {
|
||||
// Start the main application
|
||||
state = ST_REBOOT;
|
||||
}
|
||||
|
||||
lcdRefresh();
|
||||
}
|
||||
|
||||
if (state != ST_FLASHING && state != ST_USB) {
|
||||
if (pwrOffPressed()) {
|
||||
sdDone();
|
||||
boardOff();
|
||||
}
|
||||
}
|
||||
|
||||
if (state == ST_REBOOT) {
|
||||
sdDone();
|
||||
#if !defined(SIMU)
|
||||
blExit();
|
||||
NVIC_SystemReset();
|
||||
#else
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
#include "boot.h"
|
||||
|
||||
#include "hal/usb_driver.h"
|
||||
#include "hal/storage.h"
|
||||
#include "hal/fatfs_diskio.h"
|
||||
#include "os/time.h"
|
||||
|
||||
#include "thirdparty/FatFs/diskio.h"
|
||||
#include "drivers/uf2_ghostfat.h"
|
||||
|
||||
#include "board.h"
|
||||
#include "lcd.h"
|
||||
|
||||
#define FRAME_INTERVAL_MS 20
|
||||
|
||||
extern uf2_fat_write_state_t _uf2_write_state;
|
||||
|
||||
void bootloaderUF2()
|
||||
{
|
||||
BootloaderState state = ST_START;
|
||||
|
||||
// register SD storage
|
||||
storageInit();
|
||||
disk_initialize(0);
|
||||
|
||||
uint32_t next_frame = time_get_ms();
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (time_get_ms() - next_frame >= FRAME_INTERVAL_MS) {
|
||||
next_frame += FRAME_INTERVAL_MS;
|
||||
|
||||
if (state != ST_USB && state != ST_FLASHING && state != ST_FLASH_DONE) {
|
||||
if (usbPlugged()) {
|
||||
state = ST_USB;
|
||||
#if !defined(SIMU)
|
||||
usbStart();
|
||||
#endif
|
||||
} else if (pwrOffPressed()) {
|
||||
storageDeInit();
|
||||
boardOff();
|
||||
}
|
||||
}
|
||||
|
||||
if (state == ST_USB || state == ST_FLASH_DONE) {
|
||||
if (usbPlugged() == 0) {
|
||||
#if !defined(SIMU)
|
||||
usbStop();
|
||||
#endif
|
||||
state = (state == ST_FLASH_DONE) ? ST_REBOOT : ST_START;
|
||||
} else {
|
||||
auto wr_st = uf2_fat_get_state();
|
||||
if (wr_st->num_blocks != 0 && wr_st->num_blocks <= UF2_MAX_BLOCKS) {
|
||||
state = ST_FLASHING;
|
||||
}
|
||||
}
|
||||
bootloaderDrawScreen(state, 0);
|
||||
}
|
||||
|
||||
if (state == ST_START) {
|
||||
bootloaderDrawScreen(state, 0);
|
||||
} else if (state == ST_FLASHING) {
|
||||
auto wr_st = uf2_fat_get_state();
|
||||
if (wr_st->num_blocks == 0 || wr_st->num_blocks > UF2_MAX_BLOCKS) {
|
||||
state = ST_USB;
|
||||
} else {
|
||||
uint32_t progress = (wr_st->num_written * 100) / wr_st->num_blocks;
|
||||
if (wr_st->num_written == wr_st->num_blocks) {
|
||||
state = ST_FLASH_DONE;
|
||||
uf2_fat_reset_state();
|
||||
}
|
||||
bootloaderDrawScreen(state, progress);
|
||||
}
|
||||
} else if (state == ST_FLASH_DONE) {
|
||||
bootloaderDrawScreen(state, 100);
|
||||
}
|
||||
|
||||
lcdRefresh();
|
||||
}
|
||||
|
||||
if (state == ST_REBOOT) {
|
||||
storageDeInit();
|
||||
#if !defined(SIMU)
|
||||
blExit();
|
||||
NVIC_SystemReset();
|
||||
#else
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <FatFs/ff.h>
|
||||
#include "sdcard.h"
|
||||
#if defined(COLORLCD)
|
||||
#include "bitmaps.h"
|
||||
#endif
|
||||
#include "boards/FirmwareVersionTag.h"
|
||||
|
||||
#define getFirmwarePath() (FIRMWARES_PATH)
|
||||
|
||||
#if LCD_H == 480
|
||||
#define MAX_NAMES_ON_SCREEN 13
|
||||
#else
|
||||
#define MAX_NAMES_ON_SCREEN 6
|
||||
#endif
|
||||
|
||||
#define MAX_FW_FILES (MAX_NAMES_ON_SCREEN+1)
|
||||
|
||||
|
||||
// Open directory for firmware files
|
||||
FRESULT openFirmwareDir();
|
||||
|
||||
// Fetch file names and sizes into binFiles,
|
||||
// starting at the provided index.
|
||||
// Only files ending with ".bin" (case-insensitive)
|
||||
// will be considered.
|
||||
unsigned int fetchFirmwareFiles(unsigned int index);
|
||||
const char* getFirmwareFileNameByIndex(unsigned int index);
|
||||
|
||||
// Open file indexed in binFiles and read the first BLOCK_LEN bytes
|
||||
// Bootloader is skipped in firmware files
|
||||
FRESULT openFirmwareFile(unsigned int index);
|
||||
|
||||
|
||||
|
||||
// Can be called right after openBinFile() to extract the version information
|
||||
// from a firmware file
|
||||
void getFileFirmwareVersion(VersionTag* tag);
|
||||
|
||||
// Read the next BLOCK_LEN bytes into 'Block_buffer'
|
||||
// Check 'BlockCount' for # of bytes read
|
||||
FRESULT readFirmwareFile();
|
||||
|
||||
// Close the previously opened file
|
||||
FRESULT closeFirmwareFile();
|
||||
|
||||
enum FlashCheckRes {
|
||||
FC_UNCHECKED=0,
|
||||
FC_OK,
|
||||
FC_ERROR
|
||||
};
|
||||
FlashCheckRes checkFirmwareFile(unsigned int index, FlashCheckRes res);
|
||||
|
||||
void firmwareInitWrite(uint32_t index);
|
||||
bool firmwareEraseBlock(uint32_t* progress);
|
||||
bool firmwareWriteBlock(uint32_t* progress);
|
||||
|
||||
@@ -290,7 +290,7 @@ endif()
|
||||
# Bootloader board library
|
||||
add_library(board_bl OBJECT EXCLUDE_FROM_ALL
|
||||
${BOARD_COMMON_SRC}
|
||||
${TARGET_SRC_DIR}/bootloader/boot_menu.cpp
|
||||
${RADIO_SRC_DIR}/gui/colorlcd/boot_menu.cpp
|
||||
)
|
||||
add_dependencies(board_bl ${BITMAPS_TARGET})
|
||||
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:board_bl>)
|
||||
@@ -348,7 +348,7 @@ endif()
|
||||
|
||||
set(FIRMWARE_SRC
|
||||
${FIRMWARE_SRC}
|
||||
targets/common/arm/loadboot.cpp
|
||||
bootloader/loadboot.cpp
|
||||
)
|
||||
|
||||
if (MULTIMODULE)
|
||||
|
||||
@@ -1,307 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
#include "fw_version.h"
|
||||
#include "lcd.h"
|
||||
#include "etx_lv_theme.h"
|
||||
|
||||
#include "translations.h"
|
||||
|
||||
#include "targets/common/arm/stm32/bootloader/boot.h"
|
||||
#include "bootloader/firmware_files.h"
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
const uint8_t __bmp_plug_usb[] {
|
||||
#include "bmp_plug_usb.lbm"
|
||||
};
|
||||
LZ4BitmapBuffer BMP_PLUG_USB(BMP_ARGB4444);
|
||||
|
||||
const uint8_t __bmp_usb_plugged[] {
|
||||
#include "bmp_usb_plugged.lbm"
|
||||
};
|
||||
LZ4BitmapBuffer BMP_USB_PLUGGED(BMP_ARGB4444);
|
||||
|
||||
#define BL_GREEN COLOR2FLAGS(RGB(73, 219, 62))
|
||||
#define BL_RED COLOR2FLAGS(RGB(229, 32, 30))
|
||||
#define BL_BACKGROUND COLOR_BLACK
|
||||
#define BL_FOREGROUND COLOR_WHITE
|
||||
#define BL_SELECTED COLOR2FLAGS(RGB(11, 65, 244)) // deep blue
|
||||
|
||||
LAYOUT_VAL_SCALED(LINE_X1, 28)
|
||||
LAYOUT_VAL_SCALED(LINE_W, 422)
|
||||
static constexpr coord_t LINE_H = 2;
|
||||
|
||||
LAYOUT_VAL_SCALED(TITLE_X1, 88)
|
||||
LAYOUT_VAL_SCALED(TITLE_Y1, 28)
|
||||
LAYOUT_VAL_SCALED(TITLE_Y2, 56)
|
||||
|
||||
LAYOUT_VAL_SCALED(FOOTER_Y1, 30)
|
||||
LAYOUT_VAL_SCALED(FOOTER_Y2, 38)
|
||||
|
||||
LAYOUT_VAL_SCALED(SYM_X, 102)
|
||||
LAYOUT_VAL_SCALED(SYM_X2, 100)
|
||||
LAYOUT_VAL_SCALED(LBL_X, 124)
|
||||
LAYOUT_VAL_SCALED(SYM_Y, 75)
|
||||
LAYOUT_VAL_SCALED(SYM_H, 35)
|
||||
|
||||
LAYOUT_VAL_SCALED(BOX_GAP, 8)
|
||||
LAYOUT_VAL_SCALED(BOX_Y, 72)
|
||||
LAYOUT_VAL_SCALED(BOX_H, 26)
|
||||
|
||||
LAYOUT_VAL_SCALED(OPTBOX_X, 92)
|
||||
|
||||
LAYOUT_VAL_SCALED(USB_ICN_X, 60)
|
||||
LAYOUT_VAL_SCALED(USB_PLG_X, 136)
|
||||
LAYOUT_VAL_SCALED(USB_ICN_Y, 106)
|
||||
LAYOUT_VAL_SCALED(USB_TXT_X, 195)
|
||||
LAYOUT_VAL_SCALED(USB_TXT_Y1, 97)
|
||||
LAYOUT_VAL_SCALED(USB_TXT_Y2, 72)
|
||||
|
||||
LAYOUT_VAL_SCALED(FILENAM_X1, 94)
|
||||
LAYOUT_VAL_SCALED(FILENAM_X2, 124)
|
||||
LAYOUT_VAL_SCALED(FILENAM_Y1, 75)
|
||||
LAYOUT_VAL_SCALED(FILENAM_H, 25)
|
||||
LAYOUT_VAL_SCALED(FILESEL_X, 119)
|
||||
LAYOUT_VAL_SCALED(FILESEL_W, 278)
|
||||
|
||||
LAYOUT_VAL_SCALED(NLSYM_X, 305)
|
||||
LAYOUT_VAL_SCALED(RTNTXT_X, 335)
|
||||
|
||||
LAYOUT_VAL_SCALED(DIRMSG_X, 90)
|
||||
LAYOUT_VAL_SCALED(DIRMSG_Y, 168)
|
||||
|
||||
LAYOUT_VAL_SCALED(PROGRESS_X, 70)
|
||||
LAYOUT_VAL_SCALED(PROGRESS_W, 340)
|
||||
LAYOUT_VAL_SCALED(PROGRESS_H, 31)
|
||||
|
||||
LAYOUT_VAL_SCALED(VERCHK_X, 168)
|
||||
LAYOUT_VAL_SCALED(VERCHK_Y, 138)
|
||||
LAYOUT_VAL_SCALED(VERCHK_ICN_X, 78)
|
||||
|
||||
extern BitmapBuffer * lcd;
|
||||
|
||||
void bootloaderInitScreen()
|
||||
{
|
||||
BMP_PLUG_USB.load((LZ4Bitmap*)__bmp_plug_usb);
|
||||
BMP_USB_PLUGGED.load((LZ4Bitmap*)__bmp_usb_plugged);
|
||||
|
||||
lcdInitDisplayDriver();
|
||||
}
|
||||
|
||||
static void bootloaderDrawTitle(unsigned int x, const char* text)
|
||||
{
|
||||
lcd->drawText(x, TITLE_Y1, text, BL_FOREGROUND);
|
||||
lcd->drawSolidFilledRect(LINE_X1, TITLE_Y2, LINE_W, LINE_H, BL_FOREGROUND);
|
||||
}
|
||||
|
||||
static void bootloaderDrawFooter()
|
||||
{
|
||||
lcd->drawSolidFilledRect(LINE_X1, LCD_H - FOOTER_Y2, LINE_W, LINE_H, BL_FOREGROUND);
|
||||
}
|
||||
|
||||
static void bootloaderDrawBackground()
|
||||
{
|
||||
lcd->clear(BL_BACKGROUND);
|
||||
}
|
||||
|
||||
void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
|
||||
{
|
||||
static bool _first_screen = true;
|
||||
|
||||
lcdInitDirectDrawing();
|
||||
bootloaderDrawBackground();
|
||||
|
||||
if (!_first_screen) {
|
||||
// ... and turn backlight ON
|
||||
backlightEnable(BACKLIGHT_LEVEL_MAX);
|
||||
}
|
||||
|
||||
if (st == ST_START) {
|
||||
bootloaderDrawTitle(TITLE_X1, BOOTLOADER_TITLE);
|
||||
|
||||
lcd->drawText(SYM_X, SYM_Y, LV_SYMBOL_CHARGE, BL_FOREGROUND);
|
||||
coord_t pos = lcd->drawText(LBL_X, SYM_Y, TR_BL_WRITE_FW, BL_FOREGROUND);
|
||||
pos += BOX_GAP;
|
||||
|
||||
#if defined(SPI_FLASH)
|
||||
lcd->drawText(SYM_X, SYM_Y + SYM_H, LV_SYMBOL_SD_CARD, BL_FOREGROUND);
|
||||
pos = lcd->drawText(LBL_X, SYM_Y + SYM_H, TR_BL_ERASE_FLASH, BL_FOREGROUND);
|
||||
pos += BOX_GAP;
|
||||
|
||||
lcd->drawText(SYM_X2, SYMY + SYM_H * 2, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
|
||||
lcd->drawText(LBL_X, SYMY + SYM_H * 2, TR_BL_EXIT, BL_FOREGROUND);
|
||||
#else
|
||||
lcd->drawText(SYM_X2, SYM_Y + SYM_H, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
|
||||
lcd->drawText(LBL_X, SYM_Y + SYM_H, TR_BL_EXIT, BL_FOREGROUND);
|
||||
#endif
|
||||
|
||||
pos -= OPTBOX_X;
|
||||
lcd->drawSolidRect(OPTBOX_X, BOX_Y + (opt * SYM_H), pos, BOX_H, PAD_TINY, BL_SELECTED);
|
||||
|
||||
lcd->drawBitmap(USB_ICN_X, LCD_H - USB_ICN_Y, (const BitmapBuffer*)&BMP_PLUG_USB);
|
||||
lcd->drawText(USB_TXT_X, LCD_H - USB_TXT_Y1, TR_BL_USB_PLUGIN, BL_FOREGROUND);
|
||||
lcd->drawText(USB_TXT_X, LCD_H - USB_TXT_Y2, TR_BL_USB_MASS_STORE, BL_FOREGROUND);
|
||||
|
||||
bootloaderDrawFooter();
|
||||
lcd->drawText(LCD_W / 2, LCD_H - FOOTER_Y1, getFirmwareVersion(), CENTERED | BL_FOREGROUND);
|
||||
}
|
||||
#if defined(SPI_FLASH)
|
||||
else if (st == ST_CLEAR_FLASH_CHECK) {
|
||||
|
||||
bootloaderDrawTitle(TITLE_X1, TR_BL_ERASE_INT_FLASH);
|
||||
|
||||
lcd->drawText(SYM_X, SYM_Y, LV_SYMBOL_SD_CARD, BL_FOREGROUND);
|
||||
coord_t pos = lcd->drawText(LBL_X, SYM_Y, TR_BL_ERASE_FLASH, BL_FOREGROUND);
|
||||
pos += BOX_GAP;
|
||||
|
||||
lcd->drawText(SYM_X2, SYM_Y + SYM_H, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
|
||||
lcd->drawText(LBL_X, SYM_Y + SYM_H, TR_BL_EXIT, BL_FOREGROUND);
|
||||
|
||||
pos -= OPTBOX_X;
|
||||
lcd->drawSolidRect(OPTBOX_X, BOX_Y + (opt * SYM_H), pos, BOX_H, PAD_TINY, BL_SELECTED);
|
||||
|
||||
bootloaderDrawFooter();
|
||||
lcd->drawText(LINE_X1 * 2, 244,
|
||||
LV_SYMBOL_SD_CARD TR_BL_ERASE_KEY, BL_FOREGROUND);
|
||||
lcd->drawText(NLSYM_X, 244,
|
||||
LV_SYMBOL_NEW_LINE TR_BL_EXIT_KEY, BL_FOREGROUND);
|
||||
}
|
||||
else if (st == ST_CLEAR_FLASH) {
|
||||
bootloaderDrawTitle(TITLE_X1, TR_BL_ERASE_INT_FLASH);
|
||||
|
||||
lcd->drawText(LCD_W / 2, SYM_Y, TR_BL_ERASE_FLASH_MSG, CENTERED | BL_FOREGROUND);
|
||||
bootloaderDrawFooter();
|
||||
}
|
||||
#endif
|
||||
else if (st == ST_USB) {
|
||||
coord_t y = (LCD_H - BMP_USB_PLUGGED.height()) / 2;
|
||||
lcd->drawBitmap(USB_PLG_X, y, (const BitmapBuffer*)&BMP_USB_PLUGGED);
|
||||
lcd->drawText(USB_TXT_X, y + FOOTER_Y1, TR_BL_USB_CONNECTED, BL_FOREGROUND);
|
||||
}
|
||||
else if (st == ST_FILE_LIST || st == ST_DIR_CHECK || st == ST_FLASH_CHECK ||
|
||||
st == ST_FLASHING || st == ST_FLASH_DONE) {
|
||||
|
||||
bootloaderDrawTitle(TITLE_X1, LV_SYMBOL_SD_CARD " /FIRMWARE");
|
||||
|
||||
if (st == ST_FLASHING || st == ST_FLASH_DONE) {
|
||||
LcdFlags color = BL_RED;
|
||||
|
||||
if (st == ST_FLASH_DONE) {
|
||||
color = BL_GREEN;
|
||||
opt = 100; // Completed > 100%
|
||||
}
|
||||
|
||||
lcd->drawRect(PROGRESS_X, (LCD_H - PROGRESS_H) / 2, PROGRESS_W, PROGRESS_H, LINE_H, SOLID, BL_SELECTED);
|
||||
lcd->drawSolidFilledRect(PROGRESS_X + PAD_SMALL, (LCD_H - PROGRESS_H) / 2 + PAD_SMALL, ((PROGRESS_W - PAD_SMALL * 2) * opt) / 100, PROGRESS_H - PAD_SMALL * 2, color);
|
||||
} else if (st == ST_DIR_CHECK) {
|
||||
if (opt == FR_NO_PATH) {
|
||||
lcd->drawText(DIRMSG_X, DIRMSG_Y, LV_SYMBOL_CLOSE TR_BL_DIR_MISSING,
|
||||
BL_FOREGROUND);
|
||||
} else {
|
||||
lcd->drawText(DIRMSG_X, DIRMSG_Y, LV_SYMBOL_CLOSE TR_BL_DIR_EMPTY,
|
||||
BL_FOREGROUND);
|
||||
}
|
||||
} else if (st == ST_FLASH_CHECK) {
|
||||
bootloaderDrawFilename(str, 0, true);
|
||||
|
||||
if (opt == FC_ERROR) {
|
||||
lcd->drawText(DIRMSG_X, DIRMSG_Y, LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE,
|
||||
BL_FOREGROUND);
|
||||
} else if (opt == FC_OK) {
|
||||
VersionTag tag;
|
||||
memset(&tag, 0, sizeof(tag));
|
||||
getFileFirmwareVersion(&tag);
|
||||
|
||||
if (strcmp(tag.flavour, FLAVOUR)) {
|
||||
lcd->drawText(DIRMSG_X, DIRMSG_Y, LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE,
|
||||
BL_FOREGROUND);
|
||||
} else {
|
||||
lcd->drawText(VERCHK_X, VERCHK_Y, TR_BL_FORK, RIGHT | BL_FOREGROUND);
|
||||
lcd->drawSizedText(VERCHK_X + PAD_MEDIUM, VERCHK_Y, tag.fork, 6, BL_FOREGROUND);
|
||||
|
||||
lcd->drawText(VERCHK_X, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT, TR_BL_VERSION, RIGHT | BL_FOREGROUND);
|
||||
lcd->drawText(VERCHK_X + PAD_MEDIUM, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT, tag.version, BL_FOREGROUND);
|
||||
|
||||
lcd->drawText(VERCHK_X, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT * 2, TR_BL_RADIO, RIGHT | BL_FOREGROUND);
|
||||
lcd->drawText(VERCHK_X + PAD_MEDIUM, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT * 2, tag.flavour, BL_FOREGROUND);
|
||||
|
||||
lcd->drawText(VERCHK_ICN_X, VERCHK_Y + EdgeTxStyles::STD_FONT_HEIGHT, LV_SYMBOL_OK, BL_GREEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bootloaderDrawFooter();
|
||||
|
||||
if ( st != ST_DIR_CHECK && (st != ST_FLASH_CHECK || opt == FC_OK)) {
|
||||
|
||||
lcd->drawText(LINE_X1, LCD_H - FOOTER_Y1, LV_SYMBOL_CHARGE, BL_FOREGROUND);
|
||||
|
||||
if (st == ST_FILE_LIST) {
|
||||
lcd->drawText(LINE_X1 * 2, LCD_H - TITLE_Y1, TR_BL_SELECT_KEY, BL_FOREGROUND);
|
||||
}
|
||||
else if (st == ST_FLASH_CHECK && opt == FC_OK) {
|
||||
lcd->drawText(LINE_X1 * 2, LCD_H - TITLE_Y1, TR_BL_FLASH_KEY, BL_FOREGROUND);
|
||||
}
|
||||
else if (st == ST_FLASHING) {
|
||||
lcd->drawText(LINE_X1 * 2, LCD_H - TITLE_Y1, TR_BL_WRITING_FW, BL_FOREGROUND);
|
||||
}
|
||||
else if (st == ST_FLASH_DONE) {
|
||||
lcd->drawText(LINE_X1 * 2, LCD_H - TITLE_Y1, TR_BL_WRITING_COMPL, BL_FOREGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
if (st != ST_FLASHING) {
|
||||
lcd->drawText(NLSYM_X, LCD_H - TITLE_Y1, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
|
||||
lcd->drawText(RTNTXT_X, LCD_H - TITLE_Y1, TR_BL_EXIT_KEY, BL_FOREGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
_first_screen = false;
|
||||
}
|
||||
|
||||
void bootloaderDrawFilename(const char* str, uint8_t line, bool selected)
|
||||
{
|
||||
lcd->drawText(FILENAM_X1, FILENAM_Y1 + (line * FILENAM_H), LV_SYMBOL_FILE, BL_FOREGROUND);
|
||||
lcd->drawText(FILENAM_X2, FILENAM_Y1 + (line * FILENAM_H), str, BL_FOREGROUND);
|
||||
|
||||
if (selected) {
|
||||
lcd->drawSolidRect(FILESEL_X, BOX_Y + (line * FILENAM_H), FILESEL_W, BOX_H, PAD_TINY, BL_SELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t bootloaderGetMenuItemCount(int baseCount)
|
||||
{
|
||||
return baseCount;
|
||||
}
|
||||
|
||||
bool bootloaderRadioMenu(uint32_t menuItem, event_t event)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void blExit(void)
|
||||
{
|
||||
lcdClear();
|
||||
lcdRefresh();
|
||||
lcdRefreshWait();
|
||||
}
|
||||
@@ -117,7 +117,7 @@ set(BOARD_COMMON_SRC
|
||||
# Bootloader board library
|
||||
add_library(board_bl OBJECT EXCLUDE_FROM_ALL
|
||||
${BOARD_COMMON_SRC}
|
||||
${TARGET_SRC_DIR}/bootloader/boot_menu.cpp
|
||||
${RADIO_SRC_DIR}/gui/colorlcd/boot_menu.cpp
|
||||
)
|
||||
add_dependencies(board_bl ${BITMAPS_TARGET})
|
||||
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:board_bl>)
|
||||
@@ -142,7 +142,7 @@ set(FIRMWARE_SRC ${FIRMWARE_SRC} $<TARGET_OBJECTS:board>)
|
||||
|
||||
set(FIRMWARE_SRC
|
||||
${FIRMWARE_SRC}
|
||||
targets/common/arm/loadboot.cpp
|
||||
bootloader/loadboot.cpp
|
||||
)
|
||||
|
||||
set(SRC ${SRC}
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "hal/gpio.h"
|
||||
#include "stm32_gpio.h"
|
||||
|
||||
#include "board.h"
|
||||
#include "fw_version.h"
|
||||
#include "lcd.h"
|
||||
|
||||
#include "translations.h"
|
||||
|
||||
#include "targets/common/arm/stm32/bootloader/boot.h"
|
||||
#include "bootloader/firmware_files.h"
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#define RADIO_MENU_LEN 2
|
||||
|
||||
#define USB_SW_TO_INTERNAL_MODULE() gpio_set(USB_SW_GPIO);
|
||||
#define USB_SW_TO_MCU() gpio_clear(USB_SW_GPIO);
|
||||
|
||||
#define DEFAULT_PADDING 28
|
||||
#define DOUBLE_PADDING 56
|
||||
#define MESSAGE_TOP (LCD_H - (2*DOUBLE_PADDING))
|
||||
|
||||
const uint8_t __bmp_plug_usb[] {
|
||||
#include "bmp_plug_usb.lbm"
|
||||
};
|
||||
LZ4BitmapBuffer BMP_PLUG_USB(BMP_ARGB4444);
|
||||
|
||||
const uint8_t __bmp_usb_plugged[] {
|
||||
#include "bmp_usb_plugged.lbm"
|
||||
};
|
||||
LZ4BitmapBuffer BMP_USB_PLUGGED(BMP_ARGB4444);
|
||||
|
||||
#define BL_GREEN COLOR2FLAGS(RGB(73, 219, 62))
|
||||
#define BL_RED COLOR2FLAGS(RGB(229, 32, 30))
|
||||
#define BL_BACKGROUND COLOR_BLACK
|
||||
#define BL_FOREGROUND COLOR_WHITE
|
||||
#define BL_SELECTED COLOR2FLAGS(RGB(11, 65, 244)) // deep blue
|
||||
|
||||
extern BitmapBuffer * lcd;
|
||||
|
||||
static bool rfUsbAccess = false;
|
||||
|
||||
void bootloaderInitScreen()
|
||||
{
|
||||
BMP_PLUG_USB.load((LZ4Bitmap*)__bmp_plug_usb);
|
||||
BMP_USB_PLUGGED.load((LZ4Bitmap*)__bmp_usb_plugged);
|
||||
|
||||
lcdInitDisplayDriver();
|
||||
setHatsAsKeys(true);
|
||||
}
|
||||
|
||||
static void bootloaderDrawTitle(const char* text)
|
||||
{
|
||||
lcd->drawText(LCD_W/2, DEFAULT_PADDING, text, CENTERED | BL_FOREGROUND);
|
||||
lcd->drawSolidFilledRect(DEFAULT_PADDING, DOUBLE_PADDING, LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND);
|
||||
}
|
||||
|
||||
static void bootloaderDrawFooter()
|
||||
{
|
||||
lcd->drawSolidFilledRect(DEFAULT_PADDING, LCD_H - (DOUBLE_PADDING + 4), LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND);
|
||||
}
|
||||
|
||||
static void bootloaderDrawBackground()
|
||||
{
|
||||
lcd->clear(BL_BACKGROUND);
|
||||
}
|
||||
|
||||
void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
|
||||
{
|
||||
static bool _first_screen = true;
|
||||
|
||||
lcdInitDirectDrawing();
|
||||
bootloaderDrawBackground();
|
||||
|
||||
if (!_first_screen) {
|
||||
// ... and turn backlight ON
|
||||
backlightEnable(BACKLIGHT_LEVEL_MAX);
|
||||
}
|
||||
|
||||
int center = LCD_W/2;
|
||||
if (st == ST_START) {
|
||||
int yOffset = 0;
|
||||
|
||||
bootloaderDrawTitle(BOOTLOADER_TITLE);
|
||||
|
||||
lcd->drawText(62, 75, LV_SYMBOL_CHARGE, BL_FOREGROUND);
|
||||
coord_t pos = lcd->drawText(84, 75, TR_BL_WRITE_FW, BL_FOREGROUND);
|
||||
pos += 8;
|
||||
if(hardwareOptions.pcbrev == PCBREV_EL18)
|
||||
{
|
||||
lcd->drawText(57, 110, LV_SYMBOL_WIFI, BL_FOREGROUND);
|
||||
lcd->drawText(84, 110, TR_BL_RF_USB_ACCESS, BL_FOREGROUND);
|
||||
pos += 8;
|
||||
yOffset = 35;
|
||||
}
|
||||
|
||||
lcd->drawText(60, 110 + yOffset, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
|
||||
lcd->drawText(84, 110 + yOffset, TR_BL_EXIT, BL_FOREGROUND);
|
||||
|
||||
pos -= 79;
|
||||
lcd->drawSolidRect(79, 72 + (opt * 35), pos, 26, 2, BL_SELECTED);
|
||||
|
||||
lcd->drawBitmap(center - 55, 165, (const BitmapBuffer*)&BMP_PLUG_USB);
|
||||
lcd->drawText(center, 250, TR_BL_USB_PLUGIN, CENTERED | BL_FOREGROUND);
|
||||
lcd->drawText(center, 275, TR_BL_USB_MASS_STORE, CENTERED | BL_FOREGROUND);
|
||||
|
||||
bootloaderDrawFooter();
|
||||
lcd->drawText(center, LCD_H - DOUBLE_PADDING,
|
||||
TR_BL_CURRENT_FW, CENTERED | BL_FOREGROUND);
|
||||
lcd->drawText(center, LCD_H - DEFAULT_PADDING,
|
||||
getFirmwareVersion(), CENTERED | BL_FOREGROUND);
|
||||
} else if (st == ST_USB) {
|
||||
lcd->drawBitmap(center - 26, 98, (const BitmapBuffer*)&BMP_USB_PLUGGED);
|
||||
lcd->drawText(center, 168, TR_BL_USB_CONNECTED, CENTERED | BL_FOREGROUND);
|
||||
} else if (st == ST_FILE_LIST || st == ST_DIR_CHECK ||
|
||||
st == ST_FLASH_CHECK || st == ST_FLASHING ||
|
||||
st == ST_FLASH_DONE) {
|
||||
|
||||
bootloaderDrawTitle(LV_SYMBOL_SD_CARD " /FIRMWARE");
|
||||
|
||||
if (st == ST_FLASHING || st == ST_FLASH_DONE) {
|
||||
LcdFlags color = BL_RED; // red
|
||||
|
||||
if (st == ST_FLASH_DONE) {
|
||||
color = BL_GREEN /* green */;
|
||||
opt = 100; // Completed > 100%
|
||||
}
|
||||
|
||||
lcd->drawRect(DEFAULT_PADDING, 120, LCD_W - DOUBLE_PADDING, 31, 2,
|
||||
SOLID, BL_SELECTED);
|
||||
lcd->drawSolidFilledRect(DEFAULT_PADDING + 4, 124,
|
||||
((LCD_W - DOUBLE_PADDING - 8) * opt) / 100, 23,
|
||||
color);
|
||||
} else if (st == ST_DIR_CHECK) {
|
||||
if (opt == FR_NO_PATH) {
|
||||
lcd->drawText(20, MESSAGE_TOP,
|
||||
LV_SYMBOL_CLOSE TR_BL_DIR_MISSING, BL_FOREGROUND);
|
||||
} else {
|
||||
lcd->drawText(20, MESSAGE_TOP, LV_SYMBOL_CLOSE TR_BL_DIR_EMPTY,
|
||||
BL_FOREGROUND);
|
||||
}
|
||||
} else if (st == ST_FLASH_CHECK) {
|
||||
bootloaderDrawFilename(str, 0, true);
|
||||
|
||||
if (opt == FC_ERROR) {
|
||||
lcd->drawText(20, MESSAGE_TOP,
|
||||
LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE,
|
||||
BL_FOREGROUND);
|
||||
} else if (opt == FC_OK) {
|
||||
VersionTag tag;
|
||||
memset(&tag, 0, sizeof(tag));
|
||||
getFileFirmwareVersion(&tag);
|
||||
|
||||
if (strcmp(tag.flavour, FLAVOUR)) {
|
||||
lcd->drawText(20, MESSAGE_TOP, LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE,
|
||||
BL_FOREGROUND);
|
||||
} else {
|
||||
lcd->drawText(LCD_W / 4 + DEFAULT_PADDING,
|
||||
MESSAGE_TOP - DEFAULT_PADDING,
|
||||
TR_BL_FORK, RIGHT | BL_FOREGROUND);
|
||||
lcd->drawSizedText(LCD_W / 4 + 6 + DEFAULT_PADDING,
|
||||
MESSAGE_TOP - DEFAULT_PADDING, tag.fork, 6,
|
||||
BL_FOREGROUND);
|
||||
|
||||
lcd->drawText(LCD_W / 4 + DEFAULT_PADDING, MESSAGE_TOP,
|
||||
TR_BL_VERSION, RIGHT | BL_FOREGROUND);
|
||||
lcd->drawText(LCD_W / 4 + 6 + DEFAULT_PADDING, MESSAGE_TOP,
|
||||
tag.version, BL_FOREGROUND);
|
||||
|
||||
lcd->drawText(LCD_W / 4 + DEFAULT_PADDING,
|
||||
MESSAGE_TOP + DEFAULT_PADDING,
|
||||
TR_BL_RADIO, RIGHT | BL_FOREGROUND);
|
||||
lcd->drawText(LCD_W / 4 + 6 + DEFAULT_PADDING,
|
||||
MESSAGE_TOP + DEFAULT_PADDING, tag.flavour,
|
||||
BL_FOREGROUND);
|
||||
|
||||
lcd->drawText(LCD_W / 4 + DEFAULT_PADDING - 90, MESSAGE_TOP,
|
||||
LV_SYMBOL_OK, BL_GREEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bootloaderDrawFooter();
|
||||
|
||||
if (st != ST_DIR_CHECK && (st != ST_FLASH_CHECK || opt == FC_OK)) {
|
||||
|
||||
lcd->drawText(DEFAULT_PADDING, LCD_H - DOUBLE_PADDING - 2,
|
||||
LV_SYMBOL_CHARGE, BL_FOREGROUND);
|
||||
|
||||
if (st == ST_FILE_LIST) {
|
||||
lcd->drawText(DOUBLE_PADDING, LCD_H - DOUBLE_PADDING,
|
||||
TR_BL_SELECT_KEY, BL_FOREGROUND);
|
||||
} else if (st == ST_FLASH_CHECK && opt == FC_OK) {
|
||||
lcd->drawText(DOUBLE_PADDING, LCD_H - DOUBLE_PADDING,
|
||||
TR_BL_FLASH_KEY, BL_FOREGROUND);
|
||||
} else if (st == ST_FLASHING) {
|
||||
lcd->drawText(DOUBLE_PADDING, LCD_H - DOUBLE_PADDING,
|
||||
TR_BL_WRITING_FW, BL_FOREGROUND);
|
||||
} else if (st == ST_FLASH_DONE) {
|
||||
lcd->drawText(DOUBLE_PADDING, LCD_H - DOUBLE_PADDING,
|
||||
TR_BL_WRITING_COMPL, BL_FOREGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
if (st != ST_FLASHING) {
|
||||
lcd->drawText(DOUBLE_PADDING, LCD_H - DEFAULT_PADDING,
|
||||
LV_SYMBOL_NEW_LINE TR_BL_EXIT_KEY, BL_FOREGROUND);
|
||||
}
|
||||
} else if (st == ST_RADIO_MENU) {
|
||||
bootloaderDrawTitle(TR_BL_RF_USB_ACCESS);
|
||||
|
||||
lcd->drawText(62, 75, LV_SYMBOL_USB, BL_FOREGROUND);
|
||||
coord_t pos = lcd->drawText(84, 75, rfUsbAccess ? TR_BL_DISABLE : TR_BL_ENABLE, BL_FOREGROUND);
|
||||
pos += 8;
|
||||
|
||||
lcd->drawText(60, 110, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
|
||||
lcd->drawText(84, 110, TR_BL_EXIT, BL_FOREGROUND);
|
||||
|
||||
pos -= 79;
|
||||
lcd->drawSolidRect(79, 72 + (opt * 35), pos, 26, 2, BL_SELECTED);
|
||||
}
|
||||
|
||||
_first_screen = false;
|
||||
}
|
||||
|
||||
void bootloaderDrawFilename(const char* str, uint8_t line, bool selected)
|
||||
{
|
||||
lcd->drawText(DEFAULT_PADDING, 75 + (line * 25), LV_SYMBOL_FILE, BL_FOREGROUND);
|
||||
lcd->drawText(DEFAULT_PADDING + 30, 75 + (line * 25), str, BL_FOREGROUND);
|
||||
|
||||
if (selected) {
|
||||
lcd->drawSolidRect(DEFAULT_PADDING + 25, 72 + (line * 25),
|
||||
LCD_W - (DEFAULT_PADDING + 25) - 28, 26, 2,
|
||||
BL_SELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t bootloaderGetMenuItemCount(int baseCount)
|
||||
{
|
||||
if(hardwareOptions.pcbrev == PCBREV_EL18)
|
||||
return baseCount+1;
|
||||
|
||||
return baseCount;
|
||||
}
|
||||
|
||||
bool bootloaderRadioMenu(uint32_t menuItem, event_t event)
|
||||
{
|
||||
static int pos = 0;
|
||||
|
||||
if (event == EVT_KEY_FIRST(KEY_DOWN)) {
|
||||
if (pos < RADIO_MENU_LEN-1)
|
||||
pos++;
|
||||
} else if (event == EVT_KEY_FIRST(KEY_UP)) {
|
||||
if (pos > 0)
|
||||
pos--;
|
||||
} else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
switch (pos) {
|
||||
case 0:
|
||||
if (rfUsbAccess)
|
||||
{
|
||||
rfUsbAccess = false;
|
||||
INTERNAL_MODULE_OFF();
|
||||
USB_SW_TO_MCU();
|
||||
} else {
|
||||
rfUsbAccess = true;
|
||||
INTERNAL_MODULE_ON();
|
||||
USB_SW_TO_INTERNAL_MODULE();
|
||||
}
|
||||
break;
|
||||
case 1: // fall through
|
||||
default:
|
||||
USB_SW_TO_MCU();
|
||||
pos = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bootloaderDrawScreen(ST_RADIO_MENU, pos, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
void blExit(void)
|
||||
{
|
||||
USB_SW_TO_MCU();
|
||||
lcdClear();
|
||||
lcdRefresh();
|
||||
lcdRefreshWait();
|
||||
}
|
||||
@@ -180,7 +180,7 @@ endif()
|
||||
# Bootloader board library
|
||||
add_library(board_bl OBJECT EXCLUDE_FROM_ALL
|
||||
${BOARD_COMMON_SRC}
|
||||
${TARGET_SRC_DIR}/bootloader/boot_menu.cpp
|
||||
${RADIO_SRC_DIR}/gui/colorlcd/boot_menu.cpp
|
||||
)
|
||||
add_dependencies(board_bl ${BITMAPS_TARGET})
|
||||
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:board_bl>)
|
||||
@@ -223,7 +223,7 @@ endif()
|
||||
|
||||
set(FIRMWARE_SRC
|
||||
${FIRMWARE_SRC}
|
||||
targets/common/arm/loadboot.cpp
|
||||
bootloader/loadboot.cpp
|
||||
)
|
||||
|
||||
set(SRC ${SRC}
|
||||
|
||||
@@ -1,387 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "hal/gpio.h"
|
||||
#include "stm32_gpio.h"
|
||||
|
||||
#include "board.h"
|
||||
#include "fw_version.h"
|
||||
#include "lcd.h"
|
||||
|
||||
#include "translations.h"
|
||||
|
||||
#include "targets/common/arm/stm32/bootloader/boot.h"
|
||||
#include "bootloader/firmware_files.h"
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include "etx_lv_theme.h"
|
||||
|
||||
#define RADIO_MENU_LEN 2
|
||||
|
||||
#define SELECTED_COLOR (INVERS | COLOR_THEME_SECONDARY1)
|
||||
#define DEFAULT_PADDING 28
|
||||
#define DOUBLE_PADDING 56
|
||||
#define MESSAGE_TOP (LCD_H - (2*DOUBLE_PADDING))
|
||||
|
||||
const uint8_t __bmp_plug_usb[] {
|
||||
#include "bmp_plug_usb.lbm"
|
||||
};
|
||||
LZ4BitmapBuffer BMP_PLUG_USB(BMP_ARGB4444);
|
||||
|
||||
const uint8_t __bmp_usb_plugged[] {
|
||||
#include "bmp_usb_plugged.lbm"
|
||||
};
|
||||
LZ4BitmapBuffer BMP_USB_PLUGGED(BMP_ARGB4444);
|
||||
|
||||
#define BL_GREEN COLOR2FLAGS(RGB(73, 219, 62))
|
||||
#define BL_RED COLOR2FLAGS(RGB(229, 32, 30))
|
||||
#define BL_BACKGROUND COLOR_BLACK
|
||||
#define BL_FOREGROUND COLOR_WHITE
|
||||
#define BL_SELECTED COLOR2FLAGS(RGB(11, 65, 244)) // deep blue
|
||||
|
||||
extern BitmapBuffer * lcd;
|
||||
|
||||
#if defined(USB_SW_GPIO)
|
||||
#define USB_SW_TO_INTERNAL_MODULE() gpio_set(USB_SW_GPIO);
|
||||
#define USB_SW_TO_MCU() gpio_clear(USB_SW_GPIO);
|
||||
static bool rfUsbAccess = false;
|
||||
#endif
|
||||
|
||||
void bootloaderInitScreen()
|
||||
{
|
||||
BMP_PLUG_USB.load((LZ4Bitmap*)__bmp_plug_usb);
|
||||
BMP_USB_PLUGGED.load((LZ4Bitmap*)__bmp_usb_plugged);
|
||||
|
||||
lcdInitDisplayDriver();
|
||||
#if defined(USE_HATS_AS_KEYS)
|
||||
setHatsAsKeys(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void bootloaderDrawTitle(const char* text)
|
||||
{
|
||||
lcd->drawText(LCD_W/2, DEFAULT_PADDING, text, CENTERED | BL_FOREGROUND);
|
||||
lcd->drawSolidFilledRect(DEFAULT_PADDING, DOUBLE_PADDING, LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND);
|
||||
}
|
||||
|
||||
static void bootloaderDrawFooter()
|
||||
{
|
||||
if (LANDSCAPE)
|
||||
lcd->drawSolidFilledRect(DEFAULT_PADDING, LCD_H - (DEFAULT_PADDING + 10), LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND);
|
||||
else
|
||||
lcd->drawSolidFilledRect(DEFAULT_PADDING, LCD_H - (DOUBLE_PADDING + 4), LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND);
|
||||
}
|
||||
|
||||
static void bootloaderDrawBackground()
|
||||
{
|
||||
lcd->clear(BL_BACKGROUND);
|
||||
}
|
||||
|
||||
void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
|
||||
{
|
||||
static bool _first_screen = true;
|
||||
lcdInitDirectDrawing();
|
||||
bootloaderDrawBackground();
|
||||
|
||||
if (!_first_screen) {
|
||||
// ... and turn backlight ON
|
||||
backlightEnable(BACKLIGHT_LEVEL_MAX);
|
||||
}
|
||||
|
||||
int center = LCD_W/2;
|
||||
int menuItemX = center - 120;
|
||||
if (st == ST_START) {
|
||||
int y = 75;
|
||||
|
||||
bootloaderDrawTitle(BOOTLOADER_TITLE);
|
||||
|
||||
lcd->drawText(menuItemX + 2, y, LV_SYMBOL_CHARGE, BL_FOREGROUND);
|
||||
coord_t pos = lcd->drawText(menuItemX + 24, y, TR_BL_WRITE_FW, BL_FOREGROUND);
|
||||
pos += 8;
|
||||
coord_t npos;
|
||||
y += 35;
|
||||
|
||||
#if defined(SPI_FLASH)
|
||||
lcd->drawText(menuItemX + 2, y, LV_SYMBOL_SD_CARD, BL_FOREGROUND);
|
||||
npos = lcd->drawText(menuItemX + 24, y, TR_BL_ERASE_FLASH, BL_FOREGROUND);
|
||||
npos += 8;
|
||||
if (npos > pos)
|
||||
pos = npos;
|
||||
y += 35;
|
||||
#endif
|
||||
#if defined(USB_SW_GPIO)
|
||||
#if defined(RADIO_NV14_FAMILY)
|
||||
if(hardwareOptions.pcbrev == PCBREV_EL18)
|
||||
#endif
|
||||
{
|
||||
lcd->drawText(menuItemX, y, LV_SYMBOL_WIFI, BL_FOREGROUND);
|
||||
npos = lcd->drawText(menuItemX + 24, y, TR_BL_RF_USB_ACCESS, BL_FOREGROUND);
|
||||
npos += 8;
|
||||
if (npos > pos)
|
||||
pos = npos;
|
||||
y += 35;
|
||||
}
|
||||
#endif
|
||||
lcd->drawText(menuItemX, y, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
|
||||
lcd->drawText(menuItemX + 24, y, TR_BL_EXIT, BL_FOREGROUND);
|
||||
|
||||
pos -= menuItemX - 8;
|
||||
lcd->drawSolidRect(menuItemX - 8, 72 + (opt * 35), pos, 26, 2, BL_SELECTED);
|
||||
|
||||
if (LANDSCAPE) {
|
||||
lcd->drawBitmap(menuItemX - 40, LCD_H - 106, (const BitmapBuffer*)&BMP_PLUG_USB);
|
||||
lcd->drawText(menuItemX + 95, LCD_H - 97, TR_BL_USB_PLUGIN, BL_FOREGROUND);
|
||||
lcd->drawText(menuItemX + 95, LCD_H - 72, TR_BL_USB_MASS_STORE, BL_FOREGROUND);
|
||||
} else {
|
||||
lcd->drawBitmap(center - 55, LCD_H - DEFAULT_PADDING - 157, (const BitmapBuffer*)&BMP_PLUG_USB);
|
||||
lcd->drawText(center, LCD_H - DEFAULT_PADDING - 97, TR_BL_USB_PLUGIN, CENTERED | BL_FOREGROUND);
|
||||
lcd->drawText(center, LCD_H - DEFAULT_PADDING - 72, TR_BL_USB_MASS_STORE, CENTERED | BL_FOREGROUND);
|
||||
}
|
||||
|
||||
bootloaderDrawFooter();
|
||||
if (LCD_W < LCD_H)
|
||||
lcd->drawText(center, LCD_H - DOUBLE_PADDING, TR_BL_CURRENT_FW, CENTERED | BL_FOREGROUND);
|
||||
lcd->drawText(center, LCD_H - DEFAULT_PADDING, getFirmwareVersion(), CENTERED | BL_FOREGROUND);
|
||||
}
|
||||
#if defined(SPI_FLASH)
|
||||
else if (st == ST_CLEAR_FLASH_CHECK) {
|
||||
|
||||
bootloaderDrawTitle(TR_BL_ERASE_INT_FLASH);
|
||||
|
||||
lcd->drawText(menuItemX + 2, 75, LV_SYMBOL_SD_CARD, BL_FOREGROUND);
|
||||
coord_t pos = lcd->drawText(menuItemX + 24, 75, TR_BL_ERASE_FLASH, BL_FOREGROUND);
|
||||
pos += 8;
|
||||
|
||||
lcd->drawText(menuItemX, 110, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
|
||||
lcd->drawText(menuItemX + 24, 110, TR_BL_EXIT, BL_FOREGROUND);
|
||||
|
||||
pos -= menuItemX - 8;
|
||||
lcd->drawSolidRect(menuItemX - 8, 72 + (opt * 35), pos, 26, 2, BL_SELECTED);
|
||||
|
||||
bootloaderDrawFooter();
|
||||
if (LANDSCAPE) {
|
||||
lcd->drawText(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING,
|
||||
LV_SYMBOL_SD_CARD " " TR_BL_ERASE_KEY, BL_FOREGROUND);
|
||||
lcd->drawText(LCD_W - 175, LCD_H - DEFAULT_PADDING,
|
||||
LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, BL_FOREGROUND);
|
||||
} else {
|
||||
lcd->drawText(DOUBLE_PADDING, LCD_H - DOUBLE_PADDING,
|
||||
LV_SYMBOL_SD_CARD " " TR_BL_ERASE_KEY, BL_FOREGROUND);
|
||||
lcd->drawText(DOUBLE_PADDING, LCD_H - DEFAULT_PADDING,
|
||||
LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, BL_FOREGROUND);
|
||||
}
|
||||
}
|
||||
else if (st == ST_CLEAR_FLASH) {
|
||||
bootloaderDrawTitle(TR_BL_ERASE_INT_FLASH);
|
||||
|
||||
lcd->drawText(center, 75, TR_BL_ERASE_FLASH_MSG, CENTERED | BL_FOREGROUND);
|
||||
bootloaderDrawFooter();
|
||||
}
|
||||
#endif
|
||||
#if defined(USB_SW_GPIO)
|
||||
else if (st == ST_RADIO_MENU) {
|
||||
bootloaderDrawTitle(TR_BL_RF_USB_ACCESS);
|
||||
|
||||
lcd->drawText(menuItemX + 2, 75, LV_SYMBOL_USB, BL_FOREGROUND);
|
||||
coord_t pos = lcd->drawText(menuItemX + 24, 75, rfUsbAccess ? TR_BL_DISABLE : TR_BL_ENABLE, BL_FOREGROUND);
|
||||
pos += 8;
|
||||
|
||||
lcd->drawText(menuItemX + 2, 110, LV_SYMBOL_NEW_LINE, BL_FOREGROUND);
|
||||
lcd->drawText(menuItemX + 24, 110, TR_BL_EXIT, BL_FOREGROUND);
|
||||
|
||||
pos -= menuItemX - 8;
|
||||
lcd->drawSolidRect(menuItemX - 8, 72 + (opt * 35), pos, 26, 2, BL_SELECTED);
|
||||
}
|
||||
#endif
|
||||
else if (st == ST_USB) {
|
||||
lcd->drawBitmap(center - 26, 98, (const BitmapBuffer*)&BMP_USB_PLUGGED);
|
||||
lcd->drawText(center, 168, TR_BL_USB_CONNECTED, CENTERED | BL_FOREGROUND);
|
||||
} else if (st == ST_FILE_LIST || st == ST_DIR_CHECK ||
|
||||
st == ST_FLASH_CHECK || st == ST_FLASHING ||
|
||||
st == ST_FLASH_DONE) {
|
||||
|
||||
bootloaderDrawTitle(LV_SYMBOL_SD_CARD " /FIRMWARE");
|
||||
|
||||
if (st == ST_FLASHING || st == ST_FLASH_DONE) {
|
||||
LcdFlags color = BL_RED; // red
|
||||
|
||||
if (st == ST_FLASH_DONE) {
|
||||
color = BL_GREEN /* green */;
|
||||
opt = 100; // Completed > 100%
|
||||
}
|
||||
|
||||
lcd->drawRect(DEFAULT_PADDING, 120, LCD_W - DOUBLE_PADDING, 31, 2,
|
||||
SOLID, BL_SELECTED);
|
||||
lcd->drawSolidFilledRect(DEFAULT_PADDING + 4, 124,
|
||||
((LCD_W - DOUBLE_PADDING - 8) * opt) / 100, 23,
|
||||
color);
|
||||
} else if (st == ST_DIR_CHECK) {
|
||||
if (opt == FR_NO_PATH) {
|
||||
lcd->drawText(20, MESSAGE_TOP,
|
||||
LV_SYMBOL_CLOSE TR_BL_DIR_MISSING, BL_FOREGROUND);
|
||||
} else {
|
||||
lcd->drawText(20, MESSAGE_TOP, LV_SYMBOL_CLOSE TR_BL_DIR_EMPTY,
|
||||
BL_FOREGROUND);
|
||||
}
|
||||
} else if (st == ST_FLASH_CHECK) {
|
||||
bootloaderDrawFilename(str, 0, true);
|
||||
|
||||
if (opt == FC_ERROR) {
|
||||
lcd->drawText(20, MESSAGE_TOP,
|
||||
LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE,
|
||||
BL_FOREGROUND);
|
||||
} else if (opt == FC_OK) {
|
||||
VersionTag tag;
|
||||
memset(&tag, 0, sizeof(tag));
|
||||
getFileFirmwareVersion(&tag);
|
||||
if (strcmp(tag.flavour, FLAVOUR)) {
|
||||
lcd->drawText(20, MESSAGE_TOP, LV_SYMBOL_CLOSE " " TR_BL_INVALID_FIRMWARE,
|
||||
BL_FOREGROUND);
|
||||
} else {
|
||||
lcd->drawText(LCD_W / 4 + DEFAULT_PADDING,
|
||||
MESSAGE_TOP - DEFAULT_PADDING,
|
||||
TR_BL_FORK, RIGHT | BL_FOREGROUND);
|
||||
lcd->drawSizedText(LCD_W / 4 + 6 + DEFAULT_PADDING,
|
||||
MESSAGE_TOP - DEFAULT_PADDING, tag.fork, 6,
|
||||
BL_FOREGROUND);
|
||||
|
||||
lcd->drawText(LCD_W / 4 + DEFAULT_PADDING, MESSAGE_TOP,
|
||||
TR_BL_VERSION, RIGHT | BL_FOREGROUND);
|
||||
lcd->drawText(LCD_W / 4 + 6 + DEFAULT_PADDING, MESSAGE_TOP,
|
||||
tag.version, BL_FOREGROUND);
|
||||
|
||||
lcd->drawText(LCD_W / 4 + DEFAULT_PADDING,
|
||||
MESSAGE_TOP + DEFAULT_PADDING,
|
||||
TR_BL_RADIO, RIGHT | BL_FOREGROUND);
|
||||
lcd->drawText(LCD_W / 4 + 6 + DEFAULT_PADDING,
|
||||
MESSAGE_TOP + DEFAULT_PADDING, tag.flavour,
|
||||
BL_FOREGROUND);
|
||||
|
||||
lcd->drawText(LANDSCAPE ? DOUBLE_PADDING : DEFAULT_PADDING, MESSAGE_TOP, LV_SYMBOL_OK, BL_GREEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bootloaderDrawFooter();
|
||||
|
||||
if (st != ST_DIR_CHECK && (st != ST_FLASH_CHECK || opt == FC_OK)) {
|
||||
|
||||
int padding = DOUBLE_PADDING;
|
||||
if (LANDSCAPE)
|
||||
padding = DEFAULT_PADDING;
|
||||
if (st == ST_FILE_LIST) {
|
||||
lcd->drawText(padding, LCD_H - padding,
|
||||
LV_SYMBOL_CHARGE " " TR_BL_SELECT_KEY, BL_FOREGROUND);
|
||||
} else if (st == ST_FLASH_CHECK && opt == FC_OK) {
|
||||
lcd->drawText(padding, LCD_H - padding,
|
||||
LV_SYMBOL_CHARGE " " TR_BL_FLASH_KEY, BL_FOREGROUND);
|
||||
} else if (st == ST_FLASHING) {
|
||||
lcd->drawText(padding, LCD_H - padding,
|
||||
LV_SYMBOL_CHARGE " " TR_BL_WRITING_FW, BL_FOREGROUND);
|
||||
} else if (st == ST_FLASH_DONE) {
|
||||
lcd->drawText(padding, LCD_H - padding,
|
||||
LV_SYMBOL_CHARGE " " TR_BL_WRITING_COMPL, BL_FOREGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
if (st != ST_FLASHING) {
|
||||
if (LANDSCAPE) {
|
||||
lcd->drawText(LCD_W - 175, LCD_H - DEFAULT_PADDING,
|
||||
LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, BL_FOREGROUND);
|
||||
} else {
|
||||
lcd->drawText(DOUBLE_PADDING, LCD_H - DEFAULT_PADDING,
|
||||
LV_SYMBOL_NEW_LINE " " TR_BL_EXIT_KEY, BL_FOREGROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
_first_screen = false;
|
||||
}
|
||||
|
||||
void bootloaderDrawFilename(const char* str, uint8_t line, bool selected)
|
||||
{
|
||||
lcd->drawText(DEFAULT_PADDING, 75 + (line * 25), LV_SYMBOL_FILE, BL_FOREGROUND);
|
||||
lcd->drawText(DEFAULT_PADDING + 30, 75 + (line * 25), str, BL_FOREGROUND);
|
||||
|
||||
if (selected) {
|
||||
lcd->drawSolidRect(DEFAULT_PADDING + 25, 72 + (line * 25),
|
||||
LCD_W - (DEFAULT_PADDING + 25) - 28, 26, 2, BL_SELECTED);
|
||||
}
|
||||
}
|
||||
uint32_t bootloaderGetMenuItemCount(int baseCount)
|
||||
{
|
||||
uint8_t n = 0;
|
||||
#if defined(USB_SW_GPIO)
|
||||
#if defined(RADIO_NV14_FAMILY)
|
||||
if(hardwareOptions.pcbrev == PCBREV_EL18)
|
||||
#endif
|
||||
n = 1;
|
||||
#endif
|
||||
return baseCount + n;
|
||||
}
|
||||
|
||||
bool bootloaderRadioMenu(uint32_t menuItem, event_t event)
|
||||
{
|
||||
#if defined(USB_SW_GPIO)
|
||||
static int pos = 0;
|
||||
|
||||
if (event == EVT_KEY_FIRST(KEY_DOWN)) {
|
||||
if (pos < RADIO_MENU_LEN-1)
|
||||
pos++;
|
||||
} else if (event == EVT_KEY_FIRST(KEY_UP)) {
|
||||
if (pos > 0)
|
||||
pos--;
|
||||
} else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
switch (pos) {
|
||||
case 0:
|
||||
if (rfUsbAccess)
|
||||
{
|
||||
rfUsbAccess = false;
|
||||
INTERNAL_MODULE_OFF();
|
||||
USB_SW_TO_MCU();
|
||||
} else {
|
||||
rfUsbAccess = true;
|
||||
INTERNAL_MODULE_ON();
|
||||
USB_SW_TO_INTERNAL_MODULE();
|
||||
}
|
||||
break;
|
||||
case 1: // fall through
|
||||
default:
|
||||
USB_SW_TO_MCU();
|
||||
pos = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bootloaderDrawScreen(ST_RADIO_MENU, pos, nullptr);
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void blExit(void)
|
||||
{
|
||||
#if defined(USB_SW_GPIO)
|
||||
USB_SW_TO_MCU();
|
||||
#endif
|
||||
lcdClear();
|
||||
lcdRefresh();
|
||||
lcdRefreshWait();
|
||||
}
|
||||
@@ -50,9 +50,10 @@ endif()
|
||||
if(SIMU_BOOTLOADER)
|
||||
add_definitions(-DSIMU_BOOTLOADER)
|
||||
set(SIMU_DRIVERS ${SIMU_DRIVERS}
|
||||
../../targets/common/arm/stm32/bootloader/bin_files.cpp
|
||||
../../targets/common/arm/stm32/bootloader/boot.cpp
|
||||
../../targets/${TARGET_DIR}/bootloader/boot_menu.cpp
|
||||
../../bootloader/bin_files.cpp
|
||||
../../bootloader/boot.cpp
|
||||
# TODO - how to handle this for B&W (not currently used)?
|
||||
../../gui/colorlcd/boot_menu.cpp
|
||||
../../thirdparty/lz4/lz4.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -137,7 +137,7 @@ add_library(board_bl OBJECT EXCLUDE_FROM_ALL
|
||||
${BOARD_COMMON_SRC}
|
||||
${TARGET_SRC_DIR}/system_clock.c
|
||||
${TARGET_SRC_DIR}/sdram_driver.cpp
|
||||
${TARGET_SRC_DIR}/bootloader/boot_menu.cpp
|
||||
${RADIO_SRC_DIR}/gui/colorlcd/boot_menu.cpp
|
||||
targets/common/arm/stm32/stm32_qspi.cpp
|
||||
targets/common/arm/stm32/stm32_pulse_driver.cpp
|
||||
)
|
||||
@@ -170,7 +170,7 @@ include_directories(${RADIO_SRC_DIR}/fonts/colorlcd gui/${GUI_DIR} gui/${GUI_DIR
|
||||
if(BOOTLOADER)
|
||||
set(FIRMWARE_TARGET_SRC
|
||||
${FIRMWARE_TARGET_SRC}
|
||||
../common/arm/loadboot.cpp
|
||||
../../bootloader/loadboot.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
#include "bsp_io.h"
|
||||
#include "fw_version.h"
|
||||
#include "lcd.h"
|
||||
#include "bitmapbuffer.h"
|
||||
|
||||
#include "translations.h"
|
||||
|
||||
#include "targets/common/arm/stm32/bootloader/boot.h"
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#define SELECTED_COLOR (INVERS | COLOR_THEME_SECONDARY1)
|
||||
#define DEFAULT_PADDING 28
|
||||
#define DOUBLE_PADDING 56
|
||||
#define MESSAGE_TOP (LCD_H - (2*DOUBLE_PADDING))
|
||||
|
||||
#define BL_GREEN COLOR2FLAGS(RGB(73, 219, 62))
|
||||
#define BL_RED COLOR2FLAGS(RGB(229, 32, 30))
|
||||
#define BL_BACKGROUND COLOR_BLACK
|
||||
#define BL_FOREGROUND COLOR_WHITE
|
||||
#define BL_SELECTED COLOR2FLAGS(RGB(11, 65, 244)) // deep blue
|
||||
|
||||
extern BitmapBuffer* lcd;
|
||||
|
||||
void bootloaderInitScreen()
|
||||
{
|
||||
lcdInitDisplayDriver();
|
||||
backlightInit();
|
||||
backlightEnable(100);
|
||||
}
|
||||
|
||||
static void bootloaderDrawTitle(const char* text)
|
||||
{
|
||||
lcd->drawText(LCD_W / 2, DEFAULT_PADDING, text, CENTERED | BL_FOREGROUND);
|
||||
lcd->drawSolidFilledRect(DEFAULT_PADDING, DOUBLE_PADDING,
|
||||
LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND);
|
||||
}
|
||||
|
||||
static void bootloaderDrawFooter()
|
||||
{
|
||||
lcd->drawSolidFilledRect(DEFAULT_PADDING, LCD_H - (DEFAULT_PADDING + 10),
|
||||
LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND);
|
||||
}
|
||||
|
||||
static void bootloaderDrawBackground() { lcd->clear(BL_BACKGROUND); }
|
||||
|
||||
void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
|
||||
{
|
||||
lcdInitDirectDrawing();
|
||||
bootloaderDrawBackground();
|
||||
bootloaderDrawTitle(BOOTLOADER_TITLE);
|
||||
|
||||
if (st == ST_START || st == ST_USB) {
|
||||
|
||||
const char* msg = nullptr;
|
||||
if (st == ST_START) {
|
||||
msg = "Plug USB cable";
|
||||
} else if (st == ST_USB) {
|
||||
msg = "Copy firmware.uf2 to flash";
|
||||
}
|
||||
|
||||
coord_t x = LCD_W/2;
|
||||
coord_t y = LCD_H/2;
|
||||
lcd->drawText(x, y, msg, CENTERED | BL_FOREGROUND);
|
||||
|
||||
bootloaderDrawFooter();
|
||||
|
||||
const char* fw_ver = getFirmwareVersion();
|
||||
if (!fw_ver) fw_ver = "no version";
|
||||
lcd->drawText(x, LCD_H - DEFAULT_PADDING, fw_ver,
|
||||
CENTERED | BL_FOREGROUND);
|
||||
|
||||
} else if (st == ST_FLASHING || st == ST_FLASH_DONE) {
|
||||
|
||||
const coord_t pb_h = 31;
|
||||
const coord_t pb_x = 70;
|
||||
const coord_t pb_y = (LCD_H - pb_h) / 2;
|
||||
|
||||
const char* msg = (st == ST_FLASH_DONE) ? TR_BL_WRITING_COMPL : TR_BL_WRITING_FW;
|
||||
lcd->drawText(pb_x, pb_y - 28, msg, BL_FOREGROUND);
|
||||
lcd->drawRect(pb_x, pb_y, 340, pb_h, 2, SOLID, BL_SELECTED);
|
||||
|
||||
LcdFlags color = (st == ST_FLASH_DONE) ? BL_GREEN : BL_RED;
|
||||
lcd->drawSolidFilledRect(pb_x + 4, pb_y + 4, (332 * opt) / 100, 23, color);
|
||||
}
|
||||
}
|
||||
|
||||
void bootloaderDrawDFUScreen()
|
||||
{
|
||||
lcdInitDirectDrawing();
|
||||
bootloaderDrawBackground();
|
||||
lcd->drawText(LCD_W / 2, LCD_H / 2, "DFU mode", CENTERED | BL_FOREGROUND);
|
||||
}
|
||||
|
||||
void blExit(void)
|
||||
{
|
||||
lcdClear();
|
||||
lcdRefresh();
|
||||
lcdRefreshWait();
|
||||
}
|
||||
@@ -88,7 +88,7 @@ add_library(board_bl OBJECT EXCLUDE_FROM_ALL
|
||||
${BOARD_COMMON_SRC}
|
||||
${TARGET_SRC_DIR}/system_clock.c
|
||||
${TARGET_SRC_DIR}/extram_driver.cpp
|
||||
${TARGET_SRC_DIR}/bootloader/boot_menu.cpp
|
||||
${RADIO_SRC_DIR}/gui/colorlcd/boot_menu.cpp
|
||||
)
|
||||
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:board_bl>)
|
||||
|
||||
@@ -110,6 +110,6 @@ include_directories(${RADIO_SRC_DIR}/fonts/colorlcd gui/${GUI_DIR} gui/${GUI_DIR
|
||||
if(BOOTLOADER)
|
||||
set(FIRMWARE_TARGET_SRC
|
||||
${FIRMWARE_TARGET_SRC}
|
||||
../common/arm/loadboot.cpp
|
||||
../../bootloader/loadboot.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
#include "fw_version.h"
|
||||
#include "lcd.h"
|
||||
|
||||
#include "translations.h"
|
||||
|
||||
#include "targets/common/arm/stm32/bootloader/boot.h"
|
||||
#include "bootloader/firmware_files.h"
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#define SELECTED_COLOR (INVERS | COLOR_THEME_SECONDARY1)
|
||||
#define DEFAULT_PADDING 28
|
||||
#define DOUBLE_PADDING 56
|
||||
#define MESSAGE_TOP (LCD_H - (2*DOUBLE_PADDING))
|
||||
|
||||
#define BL_GREEN COLOR2FLAGS(RGB(73, 219, 62))
|
||||
#define BL_RED COLOR2FLAGS(RGB(229, 32, 30))
|
||||
#define BL_BACKGROUND COLOR_BLACK
|
||||
#define BL_FOREGROUND COLOR_WHITE
|
||||
#define BL_SELECTED COLOR2FLAGS(RGB(11, 65, 244)) // deep blue
|
||||
|
||||
extern BitmapBuffer * lcd;
|
||||
|
||||
void bootloaderInitScreen()
|
||||
{
|
||||
lcdInitDisplayDriver();
|
||||
}
|
||||
|
||||
static void bootloaderDrawTitle(const char* text)
|
||||
{
|
||||
lcd->drawText(LCD_W / 2, DEFAULT_PADDING, text, CENTERED | BL_FOREGROUND);
|
||||
lcd->drawSolidFilledRect(DEFAULT_PADDING, DOUBLE_PADDING,
|
||||
LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND);
|
||||
}
|
||||
|
||||
static void bootloaderDrawFooter()
|
||||
{
|
||||
lcd->drawSolidFilledRect(DEFAULT_PADDING, LCD_H - (DEFAULT_PADDING + 10),
|
||||
LCD_W - DOUBLE_PADDING, 2, BL_FOREGROUND);
|
||||
}
|
||||
|
||||
static void bootloaderDrawBackground() { lcd->clear(BL_BACKGROUND); }
|
||||
|
||||
void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
|
||||
{
|
||||
lcdInitDirectDrawing();
|
||||
bootloaderDrawBackground();
|
||||
bootloaderDrawTitle(BOOTLOADER_TITLE);
|
||||
|
||||
if (st == ST_START || st == ST_USB) {
|
||||
|
||||
const char* msg = nullptr;
|
||||
if (st == ST_START) {
|
||||
msg = "Plug USB cable";
|
||||
} else if (st == ST_USB) {
|
||||
msg = "Copy firmware.uf2 to flash";
|
||||
}
|
||||
|
||||
coord_t x = LCD_W/2;
|
||||
coord_t y = LCD_H/2;
|
||||
lcd->drawText(x, y, msg, CENTERED | BL_FOREGROUND);
|
||||
|
||||
bootloaderDrawFooter();
|
||||
|
||||
const char* fw_ver = getFirmwareVersion();
|
||||
if (!fw_ver) fw_ver = "no version";
|
||||
lcd->drawText(x, LCD_H - DEFAULT_PADDING, fw_ver,
|
||||
CENTERED | BL_FOREGROUND);
|
||||
|
||||
} else if (st == ST_FLASHING || st == ST_FLASH_DONE) {
|
||||
|
||||
const coord_t pb_h = 31;
|
||||
const coord_t pb_x = 70;
|
||||
const coord_t pb_y = (LCD_H - pb_h) / 2;
|
||||
|
||||
const char* msg = (st == ST_FLASH_DONE) ? TR_BL_WRITING_COMPL : TR_BL_WRITING_FW;
|
||||
lcd->drawText(pb_x, pb_y - 28, msg, BL_FOREGROUND);
|
||||
lcd->drawRect(pb_x, pb_y, 340, pb_h, 2, SOLID, BL_SELECTED);
|
||||
|
||||
LcdFlags color = (st == ST_FLASH_DONE) ? BL_GREEN : BL_RED;
|
||||
lcd->drawSolidFilledRect(pb_x + 4, pb_y + 4, (332 * opt) / 100, 23, color);
|
||||
}
|
||||
}
|
||||
|
||||
void bootloaderDrawDFUScreen()
|
||||
{
|
||||
lcdInitDirectDrawing();
|
||||
bootloaderDrawBackground();
|
||||
lcd->drawText(LCD_W / 2, LCD_H / 2, "DFU mode", CENTERED | BL_FOREGROUND);
|
||||
}
|
||||
|
||||
void blExit(void)
|
||||
{
|
||||
lcdClear();
|
||||
lcdRefresh();
|
||||
lcdRefreshWait();
|
||||
}
|
||||
@@ -628,7 +628,7 @@ endif()
|
||||
# Bootloader board library
|
||||
add_library(board_bl OBJECT EXCLUDE_FROM_ALL
|
||||
${BOARD_COMMON_SRC}
|
||||
${TARGET_SRC_DIR}/bootloader/boot_menu.cpp
|
||||
${RADIO_SRC_DIR}/gui/common/stdlcd/boot_menu.cpp
|
||||
)
|
||||
# add_dependencies(board_bl ${BITMAPS_TARGET})
|
||||
set(BOOTLOADER_SRC ${BOOTLOADER_SRC} $<TARGET_OBJECTS:board_bl>)
|
||||
@@ -723,7 +723,7 @@ endif()
|
||||
|
||||
set(FIRMWARE_SRC
|
||||
${FIRMWARE_SRC}
|
||||
targets/common/arm/loadboot.cpp
|
||||
bootloader/loadboot.cpp
|
||||
)
|
||||
|
||||
set(RADIO_DEPENDENCIES ${RADIO_DEPENDENCIES} ${BITMAPS_TARGET})
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "lcd.h"
|
||||
|
||||
#include "translations.h"
|
||||
|
||||
#include "fw_version.h"
|
||||
#include "translations.h"
|
||||
#include "../../common/arm/stm32/bootloader/boot.h"
|
||||
#include "bootloader/firmware_files.h"
|
||||
|
||||
void bootloaderInitScreen()
|
||||
{
|
||||
lcdInit();
|
||||
lcdSetContrast(true);
|
||||
|
||||
backlightInit();
|
||||
#if defined(LCD_BRIGHTNESS_DEFAULT)
|
||||
backlightEnable(LCD_BRIGHTNESS_DEFAULT);
|
||||
#else
|
||||
backlightFullOn();
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool checkFirmwareFlavor(const char * flavour)
|
||||
{
|
||||
if (strncmp(flavour,FLAVOUR, sizeof(FLAVOUR) - 1) != 0)
|
||||
return false;
|
||||
|
||||
char * tmp = (char *) flavour;
|
||||
while (*tmp != 0) tmp++;
|
||||
if ((tmp - flavour) != (sizeof(FLAVOUR) - 1))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void bootloaderDrawScreen(BootloaderState st, int opt, const char *str)
|
||||
{
|
||||
lcdClear();
|
||||
lcdDrawText(LCD_W / 2, 0, BOOTLOADER_TITLE, CENTERED);
|
||||
lcdInvertLine(0);
|
||||
|
||||
if (st == ST_START) {
|
||||
lcdDrawText(3*FW, 2*FH, TR_BL_WRITE_FW, opt == 0 ? INVERS : 0);
|
||||
lcdDrawText(3*FW, 3*FH, TR_BL_EXIT, opt == 1 ? INVERS : 0);
|
||||
|
||||
lcdDrawText(LCD_W / 2, 5 * FH + FH / 2, TR_BL_OR_PLUGIN_USB_CABLE, CENTERED);
|
||||
|
||||
const char * vers = getFirmwareVersion();
|
||||
#if LCD_W < 212
|
||||
// Remove "edgetx-" from string
|
||||
if (strncmp(vers, "edgetx-", 7) == 0)
|
||||
vers += 7;
|
||||
#endif
|
||||
lcdDrawCenteredText(7 * FH, vers);
|
||||
lcdInvertLine(7);
|
||||
}
|
||||
else if (st == ST_USB) {
|
||||
lcdDrawCenteredText(4 * FH, TR_BL_USB_CONNECTED);
|
||||
}
|
||||
else if (st == ST_DIR_CHECK) {
|
||||
if (opt == FR_NO_PATH) {
|
||||
bootloaderDrawMsg(INDENT_WIDTH, TR_BL_DIR_MISSING, 1, false);
|
||||
bootloaderDrawMsg(INDENT_WIDTH, getFirmwarePath(), 2, false);
|
||||
}
|
||||
else {
|
||||
bootloaderDrawMsg(INDENT_WIDTH, TR_BL_DIR_EMPTY, 1, false);
|
||||
}
|
||||
}
|
||||
else if (st == ST_FLASH_CHECK) {
|
||||
if (opt == FC_ERROR) {
|
||||
bootloaderDrawMsg(0, TR_BL_INVALID_FIRMWARE, 2, false);
|
||||
}
|
||||
else if (opt == FC_OK) {
|
||||
bool flavorCheck = false;
|
||||
VersionTag tag;
|
||||
getFileFirmwareVersion(&tag);
|
||||
#if LCD_W < 212
|
||||
// Remove "edgetx-" from string
|
||||
flavorCheck = checkFirmwareFlavor(tag.flavour);
|
||||
#else
|
||||
flavorCheck = checkFirmwareFlavor(tag.flavour);
|
||||
#endif
|
||||
bootloaderDrawMsg(INDENT_WIDTH, tag.version, 0, false);
|
||||
if (flavorCheck)
|
||||
bootloaderDrawMsg(0, TR_BL_HOLD_ENTER_TO_START, 2, false);
|
||||
else
|
||||
bootloaderDrawMsg(0, TR_BL_INVALID_FIRMWARE, 2, false);
|
||||
}
|
||||
}
|
||||
else if (st == ST_FLASHING) {
|
||||
lcdDrawCenteredText(4 * FH, TR_BL_WRITING_FW);
|
||||
|
||||
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) {
|
||||
lcdDrawCenteredText(4 * FH, TR_BL_WRITING_COMPL);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t bootloaderGetMenuItemCount(int baseCount)
|
||||
{
|
||||
return baseCount;
|
||||
}
|
||||
|
||||
bool bootloaderRadioMenu(uint32_t menuItem, event_t event)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void blExit(void)
|
||||
{
|
||||
#if defined(RADIO_COMMANDO8)
|
||||
lcdClear();
|
||||
lcdDrawText(2, 22, TR_BL_POWER_KEY);
|
||||
lcdDrawText(2, 33, TR_BL_FLASH_EXIT);
|
||||
lcdRefresh();
|
||||
lcdRefreshWait();
|
||||
while(1);
|
||||
#else
|
||||
lcdClear();
|
||||
lcdRefresh();
|
||||
lcdRefreshWait();
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user