diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index 00e050e61..a937bcab5 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -22,6 +22,7 @@ #include "diskio.h" #include #include +#include #define CLI_COMMAND_MAX_ARGS 8 #define CLI_COMMAND_MAX_LEN 256 @@ -302,6 +303,62 @@ int cliTestSD(const char ** argv) return 0; } +int cliTestNew() +{ + char * tmp = 0; + serialPrint("Allocating 1kB with new()"); + CoTickDelay(100); + tmp = new char[1024]; + if (tmp) { + serialPrint("\tsuccess"); + delete[] tmp; + tmp = 0; + } + else { + serialPrint("\tFAILURE"); + } + + serialPrint("Allocating 10MB with (std::nothrow) new()"); + CoTickDelay(100); + tmp = new (std::nothrow) char[1024*1024*10]; + if (tmp) { + serialPrint("\tFAILURE, tmp = %p", tmp); + delete[] tmp; + tmp = 0; + } + else { + serialPrint("\tsuccess, allocaton failed, tmp = 0"); + } + + serialPrint("Allocating 10MB with new()"); + CoTickDelay(100); + tmp = new char[1024*1024*10]; + if (tmp) { + serialPrint("\tFAILURE, tmp = %p", tmp); + delete[] tmp; + tmp = 0; + } + else { + serialPrint("\tsuccess, allocaton failed, tmp = 0"); + } + serialPrint("Test finished"); + return 0; +} + +int cliTest(const char ** argv) +{ + if (!strcmp(argv[1], "new")) { + return cliTestNew(); + } + else if (!strcmp(argv[1], "std::exception")) { + serialPrint("Not implemented"); + } + else { + serialPrint("%s: Invalid argument \"%s\"", argv[0], argv[1]); + } + return 0; +} + int cliTrace(const char ** argv) { if (!strcmp(argv[1], "on")) { @@ -509,7 +566,7 @@ void printTaskSwitchLog() uint32_t * tsl = new uint32_t[DEBUG_TASKS_LOG_SIZE]; if (!tsl) { serialPrint("Not enough memory"); - return 0; + return; } memcpy(tsl, taskSwitchLog, sizeof(taskSwitchLog)); uint32_t * p = tsl + taskSwitchLogPos; @@ -892,6 +949,7 @@ const CliCommand cliCommands[] = { { "set", cliSet, " " }, { "stackinfo", cliStackInfo, "" }, { "meminfo", cliMemoryInfo, "" }, + { "test", cliTest, "new | std::exception" }, { "trace", cliTrace, "on | off" }, #if defined(PCBFLAMENCO) { "read_bq24195", cliReadBQ24195, "" }, diff --git a/radio/src/definitions.h b/radio/src/definitions.h index 9aec93a27..740e6a0de 100644 --- a/radio/src/definitions.h +++ b/radio/src/definitions.h @@ -41,6 +41,12 @@ #define __SDRAM __DMA #endif +#if defined(PCBHORUS) && !defined(SIMU) + #define __NOINIT __attribute__((section(".noinit"))) +#else + #define __NOINIT +#endif + #if defined(SIMU) || defined(CPUARM) || GCC_VERSION < 472 typedef int32_t int24_t; #else diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index e25578033..f08ae7aeb 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -2438,29 +2438,47 @@ void opentxInit(OPENTX_INIT_ARGS) #if defined(RTCLOCK) && !defined(COPROCESSOR) rtcInit(); // RTC must be initialized before rambackupRestore() is called #endif - + #if defined(EEPROM) storageReadAll(); #endif + // Radios handle UNEXPECTED_SHUTDOWN() differently: + // * radios with WDT and EEPROM and CPU controlled power use Reset status register + // and eeGeneral.unexpectedShutdown + // * radios with SDCARD model storage use Reset status register and special + // variables in RAM. They can not use eeGeneral.unexpectedShutdown + // * radios without CPU controlled power can only use Reset status register (if available) if (UNEXPECTED_SHUTDOWN()) { + TRACE("Unexpected Shutdown detected"); unexpectedShutdown = 1; } - else { + #if defined(SDCARD) && !defined(PCBMEGA2560) + // SDCARD related stuff, only done if not unexpectedShutdown + if (!unexpectedShutdown) { sdInit(); logsInit(); + } #endif - } #if defined(PCBHORUS) - topbar = new Topbar(&g_model.topbarData); - LUA_INIT_THEMES_AND_WIDGETS(); + if (!unexpectedShutdown) { + // g_model.topbarData is still zero here (because it was not yet read from SDCARD), + // but we only remember the pointer to in in constructor. + // The storageReadAll() needs topbar object, so it must be created here + topbar = new Topbar(&g_model.topbarData); + // lua widget state must also be prepared before the call to storageReadAll() + LUA_INIT_THEMES_AND_WIDGETS(); + } #endif - + + // handling of storage for radios that have no EEPROM #if !defined(EEPROM) #if defined(RAMBACKUP) - if (UNEXPECTED_SHUTDOWN()) { + if (unexpectedShutdown) { + // SDCARD not available, try to restore last model from RAM + TRACE("rambackupRestore"); rambackupRestore(); } else { @@ -2469,7 +2487,7 @@ void opentxInit(OPENTX_INIT_ARGS) #else storageReadAll(); #endif -#endif +#endif // #if !defined(EEPROM) #if defined(SERIAL2) serial2Init(g_eeGeneral.serial2Mode, MODEL_TELEMETRY_PROTOCOL()); @@ -2515,11 +2533,12 @@ void opentxInit(OPENTX_INIT_ARGS) if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on - if (!UNEXPECTED_SHUTDOWN()) { + if (!unexpectedShutdown) { opentxStart(); } #if defined(CPUARM) || defined(CPUM2560) + // TODO Horus does not need this if (!g_eeGeneral.unexpectedShutdown) { g_eeGeneral.unexpectedShutdown = 1; storageDirty(EE_GENERAL); @@ -2667,7 +2686,7 @@ int main() drawSleepBitmap(); opentxClose(); boardOff(); // Only turn power off if necessary - wdt_disable(); + wdt_disable(); // this function is provided by AVR Libc while(1); // never return from main() - there is no code to return back, if any delays occurs in physical power it does dead loop. #endif diff --git a/radio/src/syscalls.c b/radio/src/syscalls.c index d9ac26fd1..4688f3bf6 100644 --- a/radio/src/syscalls.c +++ b/radio/src/syscalls.c @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -37,7 +37,7 @@ #include #include #include - +#include "debug.h" /*---------------------------------------------------------------------------- * Exported variables *----------------------------------------------------------------------------*/ @@ -50,11 +50,12 @@ extern int _heap_end; /*---------------------------------------------------------------------------- * Exported functions *----------------------------------------------------------------------------*/ -extern void _exit( int status ) ; -extern void _kill( int pid, int sig ) ; -extern int _getpid ( void ) ; +// extern void _exit( int status ) ; +// extern void _kill( int pid, int sig ) ; +// extern int _getpid ( void ) ; unsigned char * heap = (unsigned char *)&_end; + extern caddr_t _sbrk(int nbytes) { if (heap + nbytes < (unsigned char *)&_heap_end) { @@ -70,84 +71,68 @@ extern caddr_t _sbrk(int nbytes) extern int _gettimeofday(void *p1, void *p2) { - return 0 ; + return 0; } -extern int _link( char *old, char *nw ) +extern int _link(char *old, char *nw) { - return -1 ; + return -1; } -extern int _unlink (const char *path) +extern int _unlink(const char *path) { - return -1 ; + return -1; } extern int _open(const char *name, int flags, int mode) { - return -1 ; + return -1; } -extern int _close( int file ) +extern int _close(int file) { - return -1 ; + return -1; } -extern int _fstat( int file, struct stat *st ) +extern int _fstat(int file, struct stat * st) { - st->st_mode = S_IFCHR ; - - return 0 ; + st->st_mode = S_IFCHR ; + return 0; } -extern int _isatty( int file ) +extern int _isatty(int file) { - return 1 ; + return 1; } -extern int _lseek( int file, int ptr, int dir ) +extern int _lseek(int file, int ptr, int dir) { - return 0 ; + return 0; } extern int _read(int file, char *ptr, int len) { - return 0 ; + return 0; } -extern int _write( int file, char *ptr, int len ) +extern int _write(int file, char *ptr, int len) { - int iIndex ; - - -// for ( ; *ptr != 0 ; ptr++ ) - for ( iIndex=0 ; iIndex < len ; iIndex++, ptr++ ) - { -// TODO UART_PutChar( *ptr ) ; - } - - return iIndex ; + return 0; } -extern void _exit( int status ) +extern void _exit(int status) { -#if defined(SIMU) - printf( "Exiting with status %d.\n", status ) ; -#endif - for ( ; ; ) ; + TRACE("_exit(%d)", status); + for (;;); } -extern void _kill( int pid, int sig ) +extern void _kill(int pid, int sig) { - return ; + return ; } -extern int _getpid ( void ) +extern int _getpid() { return -1 ; } -//void _init (void) -//{ - -//} diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index 86a781f25..9aadfb386 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -156,6 +156,11 @@ void boardInit() __enable_irq(); TRACE("\nHorus board started :)"); + TRACE("RCC->CSR = %08x", RCC->CSR); + + // we need to initialize g_FATFS_Obj here, because it is in .ram section (because of DMA access) + // and this section is un-initialized + memset(&g_FATFS_Obj, 0, sizeof(g_FATFS_Obj)); keysInit(); adcInit(); diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 5093c7b3c..e3c153163 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -1,462 +1,481 @@ -/* - * 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 _BOARD_HORUS_H_ -#define _BOARD_HORUS_H_ - -#include "stddef.h" - -#if defined(__cplusplus) && !defined(SIMU) -extern "C" { -#endif - -#if __clang__ -// clang is very picky about the use of "register" -// Tell clang to ignore the warnings for the following files -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-register" -#endif - -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_rcc.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_gpio.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_spi.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_i2c.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_rtc.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_pwr.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_dma.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_usart.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_flash.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_sdio.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_dbgmcu.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_ltdc.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_fmc.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_tim.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_dma2d.h" -#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/misc.h" -#if __clang__ -// Restore warnings about registers -#pragma clang diagnostic pop -#endif - - -#if !defined(SIMU) -#include "usbd_cdc_core.h" -#include "usbd_msc_core.h" -#include "usbd_hid_core.h" -#include "usbd_usr.h" -#include "usbd_desc.h" -#include "usb_conf.h" -#include "usbd_conf.h" -#endif - -#include "hal.h" - -#if defined(__cplusplus) && !defined(SIMU) -} -#endif - -#define FLASHSIZE 0x80000 -#define BOOTLOADER_SIZE 0x8000 -#define FIRMWARE_ADDRESS 0x08000000 - -// HSI is at 168Mhz (over-drive is not enabled!) -#define PERI1_FREQUENCY 42000000 -#define PERI2_FREQUENCY 84000000 -#define TIMER_MULT_APB1 2 -#define TIMER_MULT_APB2 2 - -#define strcpy_P strcpy -#define strcat_P strcat - -extern uint16_t sessionTimer; - -#define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE) -#define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_RESET) - -// Board driver -void boardInit(void); -void boardOff(void); - -// Delays driver -#ifdef __cplusplus -extern "C" { -#endif -void delaysInit(void); -void delay_01us(uint16_t nb); -void delay_us(uint16_t nb); -void delay_ms(uint32_t ms); -#ifdef __cplusplus -} -#endif - -// PCBREV driver -#define IS_HORUS_PROD() GPIO_ReadInputDataBit(PCBREV_GPIO, PCBREV_GPIO_PIN) -#if defined(SIMU) - #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() true -#elif PCBREV >= 13 - #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() IS_HORUS_PROD() -#else - #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() (!IS_HORUS_PROD()) -#endif - -// CPU Unique ID -#define LEN_CPU_UID (3*8+2) -void getCPUUniqueID(char * s); - -// SD driver -#define BLOCK_SIZE 512 /* Block Size in Bytes */ -#if !defined(SIMU) || defined(SIMU_DISKIO) -uint32_t sdIsHC(void); -uint32_t sdGetSpeed(void); -#define SD_IS_HC() (sdIsHC()) -#define SD_GET_SPEED() (sdGetSpeed()) -#define SD_GET_FREE_BLOCKNR() (sdGetFreeSectors()) -#define SD_CARD_PRESENT() (~SD_PRESENT_GPIO->IDR & SD_PRESENT_GPIO_PIN) -void sdInit(void); -void sdMount(void); -void sdDone(void); -#define sdPoll10ms() -uint32_t sdMounted(void); -#else -#define SD_IS_HC() (0) -#define SD_GET_SPEED() (0) -#define sdInit() -#define sdMount() -#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); -DRESULT __disk_write(BYTE drv, const BYTE * buff, DWORD sector, UINT count); -#else -#define __disk_read disk_read -#define __disk_write disk_write -#endif - -// Flash Write driver -#define FLASH_PAGESIZE 256 -void unlockFlash(void); -void lockFlash(void); -void flashWrite(uint32_t * address, uint32_t * buffer); -uint32_t isFirmwareStart(const uint8_t * buffer); -uint32_t isBootloaderStart(const uint8_t * buffer); - -// SDRAM driver -void SDRAM_Init(void); - -// Pulses driver -#define INTERNAL_MODULE_ON() GPIO_SetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) -#define INTERNAL_MODULE_OFF() GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) -#define EXTERNAL_MODULE_ON() GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) -#define EXTERNAL_MODULE_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) -#define IS_INTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) == Bit_SET) -#define IS_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET) -#define IS_UART_MODULE(port) (port == INTERNAL_MODULE) - -void init_no_pulses(uint32_t port); -void disable_no_pulses(uint32_t port); -void init_ppm(uint32_t module_index); -void disable_ppm(uint32_t module_index); -void init_pxx(uint32_t module_index); -void disable_pxx(uint32_t module_index); -void init_dsm2(uint32_t module_index); -void disable_dsm2(uint32_t module_index); -void init_crossfire(uint32_t module_index); -void disable_crossfire(uint32_t module_index); - -// Trainer driver -void init_trainer_ppm(void); -void stop_trainer_ppm(void); -void init_trainer_capture(void); -void stop_trainer_capture(void); - -// Keys driver -enum EnumKeys -{ - KEY_PGUP, - KEY_PGDN, - KEY_ENTER, - KEY_MODEL, - KEY_UP = KEY_MODEL, - KEY_EXIT, - KEY_DOWN = KEY_EXIT, - KEY_TELEM, - KEY_RIGHT = KEY_TELEM, - KEY_RADIO, - KEY_LEFT = KEY_RADIO, - - TRM_BASE, - TRM_LH_DWN = TRM_BASE, - TRM_LH_UP, - TRM_LV_DWN, - TRM_LV_UP, - TRM_RV_DWN, - TRM_RV_UP, - TRM_RH_DWN, - TRM_RH_UP, - TRM_LS_DWN, - TRM_LS_UP, - TRM_RS_DWN, - TRM_RS_UP, - TRM_LAST = TRM_RS_UP, - - NUM_KEYS -}; - -enum EnumSwitches -{ - SW_SA, - SW_SB, - SW_SC, - SW_SD, - SW_SE, - SW_SF, - SW_SG, - SW_SH, - NUM_SWITCHES -}; -#define IS_3POS(x) ((x) != SW_SF && (x) != SW_SH) - -enum EnumSwitchesPositions -{ - SW_SA0, - SW_SA1, - SW_SA2, - SW_SB0, - SW_SB1, - SW_SB2, - SW_SC0, - SW_SC1, - SW_SC2, - SW_SD0, - SW_SD1, - SW_SD2, - SW_SE0, - SW_SE1, - SW_SE2, - SW_SF0, - SW_SF1, - SW_SF2, - SW_SG0, - SW_SG1, - SW_SG2, - SW_SH0, - SW_SH1, - SW_SH2, -}; -void keysInit(void); -uint8_t keyState(uint8_t index); -uint32_t switchState(uint8_t index); -uint32_t readKeys(void); -uint32_t readTrims(void); -#define TRIMS_PRESSED() (readTrims()) -#define KEYS_PRESSED() (readKeys()) -#define DBLKEYS_PRESSED_RGT_LFT(in) ((in & ((1<KR = 0xAAAA -#endif -#define WAS_RESET_BY_WATCHDOG() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF)) -#define WAS_RESET_BY_SOFTWARE() (RCC->CSR & RCC_CSR_SFTRSTF) -#define WAS_RESET_BY_WATCHDOG_OR_SOFTWARE() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF | RCC_CSR_SFTRSTF)) - -// ADC driver -#define NUM_POTS 3 -#define NUM_SLIDERS 4 -#define NUM_XPOTS 3 -enum Analogs { - STICK1, - STICK2, - STICK3, - STICK4, - POT_FIRST, - POT1 = POT_FIRST, - POT2, - POT3, - POT_LAST = POT3, - SLIDER1, - SLIDER2, - SLIDER3, - SLIDER4, - TX_VOLTAGE, - MOUSE1, - MOUSE2, - NUMBER_ANALOG -}; -#define IS_POT(x) ((x)>=POT_FIRST && (x)<=POT_LAST) -#define IS_SLIDER(x) ((x)>=SLIDER1 && (x)<=SLIDER4) -extern uint16_t adcValues[NUMBER_ANALOG]; -void adcInit(void); -void adcRead(void); -uint16_t getAnalogValue(uint8_t index); -uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps - -#if defined(__cplusplus) && !defined(SIMU) -extern "C" { -#endif - -// Power driver -void pwrInit(void); -uint32_t pwrCheck(void); -void pwrOn(void); -void pwrOff(void); -void pwrResetHandler(void); -uint32_t pwrPressed(void); -uint32_t pwrPressedDuration(void); -#define pwroffPressed() pwrPressed() -#define UNEXPECTED_SHUTDOWN() (WAS_RESET_BY_WATCHDOG() || g_eeGeneral.unexpectedShutdown) - -// Led driver -void ledOff(void); -void ledRed(void); -void ledBlue(void); - -// LCD driver -#define LCD_W 480 -#define LCD_H 272 -#define LCD_DEPTH 16 -void lcdInit(void); -void lcdRefresh(void); -void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color); -void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h); -void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h); -void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t h, uint32_t format); -void lcdStoreBackupBuffer(void); -int lcdRestoreBackupBuffer(void); -void lcdSetContrast(); -#define lcdOff(...) -#define lcdSetRefVolt(...) -#define lcdRefreshWait(...) - -// Backlight driver -void backlightInit(void); -#if defined(SIMU) -#define backlightEnable(...) -#else -void backlightEnable(uint8_t dutyCycle); -#endif -#define BACKLIGHT_ENABLE() backlightEnable(unexpectedShutdown ? 100 : 100-g_eeGeneral.backlightBright) -#define BACKLIGHT_DISABLE() backlightEnable(unexpectedShutdown ? 100 : g_eeGeneral.blOffBright) -#define isBacklightEnabled() true - -// USB driver -int usbPlugged(void); -void usbInit(void); -void usbStart(void); -void usbStop(void); -void usbSerialPutc(uint8_t c); -#define USB_NAME "FrSky Horus" -#define USB_MANUFACTURER 'F', 'r', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */ -#define USB_PRODUCT 'H', 'o', 'r', 'u', 's', ' ', ' ', ' ' /* 8 Bytes */ - -#if defined(__cplusplus) && !defined(SIMU) -} -#endif - -// Audio driver -void audioInit(void); -void audioConsumeCurrentBuffer(void); -#define audioDisableIrq() // interrupts must stay enabled on Horus -#define audioEnableIrq() // interrupts must stay enabled on Horus -#define setSampleRate(freq) -void setScaledVolume(uint8_t volume); -void setVolume(uint8_t volume); -int32_t getVolume(void); -#define VOLUME_LEVEL_MAX 23 -#define VOLUME_LEVEL_DEF 12 - -// Telemetry driver -#define TELEMETRY_FIFO_SIZE 512 -void telemetryPortInit(uint32_t baudrate, uint8_t mode); -void telemetryPortSetDirectionOutput(void); -void sportSendBuffer(uint8_t * buffer, uint32_t count); -uint8_t telemetryGetByte(uint8_t * byte); - -// Haptic driver -void hapticInit(void); -void hapticDone(void); -void hapticOff(void); -#define HAPTIC_OFF() hapticOff() -void hapticOn(uint32_t pwmPercent); - -// GPS driver -void gpsInit(uint32_t baudrate); -uint8_t gpsGetByte(uint8_t * byte); -#if defined(DEBUG) -extern uint8_t gpsTraceEnabled; -#endif -void gpsSendByte(uint8_t byte); - -// Second serial port driver -#define SERIAL2 -#define DEBUG_BAUDRATE 115200 -extern uint8_t serial2Mode; -void serial2Init(unsigned int mode, unsigned int protocol); -void serial2Putc(char c); -#define serial2TelemetryInit(protocol) serial2Init(UART_MODE_TELEMETRY, protocol) -void serial2SbusInit(void); -void serial2Stop(void); -#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE) -int sbusGetByte(uint8_t * byte); - -// BT driver -#define BLUETOOTH_DEFAULT_BAUDRATE 115200 -#define BLUETOOTH_FACTORY_BAUDRATE 9600 -uint8_t bluetoothReady(void); -void bluetoothInit(uint32_t baudrate); -void bluetoothWrite(const void * buffer, int len); -void bluetoothWriteString(const char * str); -int bluetoothRead(void * buffer, int len); -void bluetoothWakeup(void); -void bluetoothDone(void); - -#if defined(USB_JOYSTICK) && !defined(SIMU) -void usbJoystickUpdate(void); -#endif - -extern uint8_t currentTrainerMode; -void checkTrainerSettings(void); - -#if defined(__cplusplus) -#include "fifo.h" -#include "dmafifo.h" -extern DMAFifo<512> telemetryFifo; -extern DMAFifo<32> serial2RxFifo; -#endif - - -#endif // _BOARD_HORUS_H_ +/* + * 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 _BOARD_HORUS_H_ +#define _BOARD_HORUS_H_ + +#include "stddef.h" + +#if defined(__cplusplus) && !defined(SIMU) +extern "C" { +#endif + +#if __clang__ +// clang is very picky about the use of "register" +// Tell clang to ignore the warnings for the following files +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-register" +#endif + +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_rcc.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_gpio.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_spi.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_i2c.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_rtc.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_pwr.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_dma.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_usart.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_flash.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_sdio.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_dbgmcu.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_ltdc.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_fmc.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_tim.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/stm32f4xx_dma2d.h" +#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/misc.h" +#if __clang__ +// Restore warnings about registers +#pragma clang diagnostic pop +#endif + + +#if !defined(SIMU) +#include "usbd_cdc_core.h" +#include "usbd_msc_core.h" +#include "usbd_hid_core.h" +#include "usbd_usr.h" +#include "usbd_desc.h" +#include "usb_conf.h" +#include "usbd_conf.h" +#endif + +#include "hal.h" + +#if defined(__cplusplus) && !defined(SIMU) +} +#endif + +#define FLASHSIZE 0x80000 +#define BOOTLOADER_SIZE 0x8000 +#define FIRMWARE_ADDRESS 0x08000000 + +// HSI is at 168Mhz (over-drive is not enabled!) +#define PERI1_FREQUENCY 42000000 +#define PERI2_FREQUENCY 84000000 +#define TIMER_MULT_APB1 2 +#define TIMER_MULT_APB2 2 + +#define strcpy_P strcpy +#define strcat_P strcat + +extern uint16_t sessionTimer; + +#define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE) +#define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_RESET) + +// Board driver +void boardInit(void); +void boardOff(void); + +// Delays driver +#ifdef __cplusplus +extern "C" { +#endif +void delaysInit(void); +void delay_01us(uint16_t nb); +void delay_us(uint16_t nb); +void delay_ms(uint32_t ms); +#ifdef __cplusplus +} +#endif + +// PCBREV driver +#define IS_HORUS_PROD() GPIO_ReadInputDataBit(PCBREV_GPIO, PCBREV_GPIO_PIN) +#if defined(SIMU) + #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() true +#elif PCBREV >= 13 + #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() IS_HORUS_PROD() +#else + #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() (!IS_HORUS_PROD()) +#endif + +// CPU Unique ID +#define LEN_CPU_UID (3*8+2) +void getCPUUniqueID(char * s); + +// SD driver +#define BLOCK_SIZE 512 /* Block Size in Bytes */ +#if !defined(SIMU) || defined(SIMU_DISKIO) +uint32_t sdIsHC(void); +uint32_t sdGetSpeed(void); +#define SD_IS_HC() (sdIsHC()) +#define SD_GET_SPEED() (sdGetSpeed()) +#define SD_GET_FREE_BLOCKNR() (sdGetFreeSectors()) +#define SD_CARD_PRESENT() (~SD_PRESENT_GPIO->IDR & SD_PRESENT_GPIO_PIN) +void sdInit(void); +void sdMount(void); +void sdDone(void); +#define sdPoll10ms() +uint32_t sdMounted(void); +#else +#define SD_IS_HC() (0) +#define SD_GET_SPEED() (0) +#define sdInit() +#define sdMount() +#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); +DRESULT __disk_write(BYTE drv, const BYTE * buff, DWORD sector, UINT count); +#else +#define __disk_read disk_read +#define __disk_write disk_write +#endif + +// Flash Write driver +#define FLASH_PAGESIZE 256 +void unlockFlash(void); +void lockFlash(void); +void flashWrite(uint32_t * address, uint32_t * buffer); +uint32_t isFirmwareStart(const uint8_t * buffer); +uint32_t isBootloaderStart(const uint8_t * buffer); + +// SDRAM driver +void SDRAM_Init(void); + +// Pulses driver +#define INTERNAL_MODULE_ON() GPIO_SetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) +#define INTERNAL_MODULE_OFF() GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) +#define EXTERNAL_MODULE_ON() GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) +#define EXTERNAL_MODULE_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) +#define IS_INTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) == Bit_SET) +#define IS_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET) +#define IS_UART_MODULE(port) (port == INTERNAL_MODULE) + +void init_no_pulses(uint32_t port); +void disable_no_pulses(uint32_t port); +void init_ppm(uint32_t module_index); +void disable_ppm(uint32_t module_index); +void init_pxx(uint32_t module_index); +void disable_pxx(uint32_t module_index); +void init_dsm2(uint32_t module_index); +void disable_dsm2(uint32_t module_index); +void init_crossfire(uint32_t module_index); +void disable_crossfire(uint32_t module_index); + +// Trainer driver +void init_trainer_ppm(void); +void stop_trainer_ppm(void); +void init_trainer_capture(void); +void stop_trainer_capture(void); + +// Keys driver +enum EnumKeys +{ + KEY_PGUP, + KEY_PGDN, + KEY_ENTER, + KEY_MODEL, + KEY_UP = KEY_MODEL, + KEY_EXIT, + KEY_DOWN = KEY_EXIT, + KEY_TELEM, + KEY_RIGHT = KEY_TELEM, + KEY_RADIO, + KEY_LEFT = KEY_RADIO, + + TRM_BASE, + TRM_LH_DWN = TRM_BASE, + TRM_LH_UP, + TRM_LV_DWN, + TRM_LV_UP, + TRM_RV_DWN, + TRM_RV_UP, + TRM_RH_DWN, + TRM_RH_UP, + TRM_LS_DWN, + TRM_LS_UP, + TRM_RS_DWN, + TRM_RS_UP, + TRM_LAST = TRM_RS_UP, + + NUM_KEYS +}; + +enum EnumSwitches +{ + SW_SA, + SW_SB, + SW_SC, + SW_SD, + SW_SE, + SW_SF, + SW_SG, + SW_SH, + NUM_SWITCHES +}; +#define IS_3POS(x) ((x) != SW_SF && (x) != SW_SH) + +enum EnumSwitchesPositions +{ + SW_SA0, + SW_SA1, + SW_SA2, + SW_SB0, + SW_SB1, + SW_SB2, + SW_SC0, + SW_SC1, + SW_SC2, + SW_SD0, + SW_SD1, + SW_SD2, + SW_SE0, + SW_SE1, + SW_SE2, + SW_SF0, + SW_SF1, + SW_SF2, + SW_SG0, + SW_SG1, + SW_SG2, + SW_SH0, + SW_SH1, + SW_SH2, +}; +void keysInit(void); +uint8_t keyState(uint8_t index); +uint32_t switchState(uint8_t index); +uint32_t readKeys(void); +uint32_t readTrims(void); +#define TRIMS_PRESSED() (readTrims()) +#define KEYS_PRESSED() (readKeys()) +#define DBLKEYS_PRESSED_RGT_LFT(in) ((in & ((1<KR = 0xAAAA + #endif + #define WAS_RESET_BY_WATCHDOG() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF)) + #define WAS_RESET_BY_SOFTWARE() (RCC->CSR & RCC_CSR_SFTRSTF) + #define WAS_RESET_BY_WATCHDOG_OR_SOFTWARE() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF | RCC_CSR_SFTRSTF)) +#endif + +// ADC driver +#define NUM_POTS 3 +#define NUM_SLIDERS 4 +#define NUM_XPOTS 3 +enum Analogs { + STICK1, + STICK2, + STICK3, + STICK4, + POT_FIRST, + POT1 = POT_FIRST, + POT2, + POT3, + POT_LAST = POT3, + SLIDER1, + SLIDER2, + SLIDER3, + SLIDER4, + TX_VOLTAGE, + MOUSE1, + MOUSE2, + NUMBER_ANALOG +}; +#define IS_POT(x) ((x)>=POT_FIRST && (x)<=POT_LAST) +#define IS_SLIDER(x) ((x)>=SLIDER1 && (x)<=SLIDER4) +extern uint16_t adcValues[NUMBER_ANALOG]; +void adcInit(void); +void adcRead(void); +uint16_t getAnalogValue(uint8_t index); +uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps + +#if defined(__cplusplus) && !defined(SIMU) +extern "C" { +#endif + +// Power driver +void pwrInit(void); +uint32_t pwrCheck(void); +void pwrOn(void); +void pwrOff(void); +void pwrResetHandler(void); +uint32_t pwrPressed(void); +uint32_t pwrPressedDuration(void); +#define pwroffPressed() pwrPressed() +#if defined(SIMU) + #define UNEXPECTED_SHUTDOWN() (false) +#else + #define UNEXPECTED_SHUTDOWN() (powerupReason == DIRTY_SHUTDOWN) +#endif + +// Led driver +void ledOff(void); +void ledRed(void); +void ledBlue(void); + +// LCD driver +#define LCD_W 480 +#define LCD_H 272 +#define LCD_DEPTH 16 +void lcdInit(void); +void lcdRefresh(void); +void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color); +void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h); +void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h); +void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t h, uint32_t format); +void lcdStoreBackupBuffer(void); +int lcdRestoreBackupBuffer(void); +void lcdSetContrast(); +#define lcdOff(...) +#define lcdSetRefVolt(...) +#define lcdRefreshWait(...) + +// Backlight driver +void backlightInit(void); +#if defined(SIMU) +#define backlightEnable(...) +#else +void backlightEnable(uint8_t dutyCycle); +#endif +#define BACKLIGHT_ENABLE() backlightEnable(unexpectedShutdown ? 100 : 100-g_eeGeneral.backlightBright) +#define BACKLIGHT_DISABLE() backlightEnable(unexpectedShutdown ? 100 : g_eeGeneral.blOffBright) +#define isBacklightEnabled() true + +// USB driver +int usbPlugged(void); +void usbInit(void); +void usbStart(void); +void usbStop(void); +void usbSerialPutc(uint8_t c); +#define USB_NAME "FrSky Horus" +#define USB_MANUFACTURER 'F', 'r', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */ +#define USB_PRODUCT 'H', 'o', 'r', 'u', 's', ' ', ' ', ' ' /* 8 Bytes */ + +#if defined(__cplusplus) && !defined(SIMU) +} +#endif + +// Audio driver +void audioInit(void); +void audioConsumeCurrentBuffer(void); +#define audioDisableIrq() // interrupts must stay enabled on Horus +#define audioEnableIrq() // interrupts must stay enabled on Horus +#define setSampleRate(freq) +void setScaledVolume(uint8_t volume); +void setVolume(uint8_t volume); +int32_t getVolume(void); +#define VOLUME_LEVEL_MAX 23 +#define VOLUME_LEVEL_DEF 12 + +// Telemetry driver +#define TELEMETRY_FIFO_SIZE 512 +void telemetryPortInit(uint32_t baudrate, uint8_t mode); +void telemetryPortSetDirectionOutput(void); +void sportSendBuffer(uint8_t * buffer, uint32_t count); +uint8_t telemetryGetByte(uint8_t * byte); + +// Haptic driver +void hapticInit(void); +void hapticDone(void); +void hapticOff(void); +#define HAPTIC_OFF() hapticOff() +void hapticOn(uint32_t pwmPercent); + +// GPS driver +void gpsInit(uint32_t baudrate); +uint8_t gpsGetByte(uint8_t * byte); +#if defined(DEBUG) +extern uint8_t gpsTraceEnabled; +#endif +void gpsSendByte(uint8_t byte); + +// Second serial port driver +#define SERIAL2 +#define DEBUG_BAUDRATE 115200 +extern uint8_t serial2Mode; +void serial2Init(unsigned int mode, unsigned int protocol); +void serial2Putc(char c); +#define serial2TelemetryInit(protocol) serial2Init(UART_MODE_TELEMETRY, protocol) +void serial2SbusInit(void); +void serial2Stop(void); +#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE) +int sbusGetByte(uint8_t * byte); + +// BT driver +#define BLUETOOTH_DEFAULT_BAUDRATE 115200 +#define BLUETOOTH_FACTORY_BAUDRATE 9600 +uint8_t bluetoothReady(void); +void bluetoothInit(uint32_t baudrate); +void bluetoothWrite(const void * buffer, int len); +void bluetoothWriteString(const char * str); +int bluetoothRead(void * buffer, int len); +void bluetoothWakeup(void); +void bluetoothDone(void); + +#if defined(USB_JOYSTICK) && !defined(SIMU) +void usbJoystickUpdate(void); +#endif + +extern uint8_t currentTrainerMode; +void checkTrainerSettings(void); + +#if defined(__cplusplus) +#include "fifo.h" +#include "dmafifo.h" +extern DMAFifo<512> telemetryFifo; +extern DMAFifo<32> serial2RxFifo; +#endif + + +#endif // _BOARD_HORUS_H_ diff --git a/radio/src/targets/horus/diskio.cpp b/radio/src/targets/horus/diskio.cpp index d8a4cbdb4..47c2c9ca5 100644 --- a/radio/src/targets/horus/diskio.cpp +++ b/radio/src/targets/horus/diskio.cpp @@ -308,7 +308,7 @@ DRESULT disk_ioctl ( // TODO everything here should not be in the driver layer ... -FATFS g_FATFS_Obj __DMA; +FATFS g_FATFS_Obj __DMA; // initialized in boardInit() #if defined(LOG_TELEMETRY) FIL g_telemetryFile = {}; #endif diff --git a/radio/src/targets/horus/pwr_driver.cpp b/radio/src/targets/horus/pwr_driver.cpp index 685860976..9fed0f9ae 100644 --- a/radio/src/targets/horus/pwr_driver.cpp +++ b/radio/src/targets/horus/pwr_driver.cpp @@ -21,6 +21,10 @@ #include "pwr.h" #include "board.h" +uint32_t shutdownRequest; // Stores intentional shutdown to avoid reboot loop +uint32_t shutdownReason; // Used for detecting unexpected reboots regardless of reason +uint32_t powerupReason __NOINIT; // Stores power up reason beyond initialization for emergency mode activation + void pwrInit() { GPIO_InitTypeDef GPIO_InitStructure; @@ -70,6 +74,8 @@ void pwrInit() void pwrOn() { GPIO_SetBits(PWR_GPIO, PWR_ON_GPIO_PIN); + shutdownRequest = NO_SHUTDOWN_REQUEST; + shutdownReason = DIRTY_SHUTDOWN; } void pwrOff() @@ -87,6 +93,8 @@ void pwrOff() // Shutdown the Haptic hapticDone(); + shutdownRequest = SHUTDOWN_REQUEST; + shutdownReason = NORMAL_POWER_OFF; GPIO_ResetBits(PWR_GPIO, PWR_ON_GPIO_PIN); } @@ -104,13 +112,28 @@ void pwrResetHandler() __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. + // We get here whether we are powering up normally, we had an unexpected reboot or we have just powered down normally. + // We want: + // - In the 2nd case, to power ON as soon as possible if an unexpected reboot happened + // (we get there running on remaining capacitor charge, soft power having been cut by the RESET). + // - In the 3rd case, NOT power on as that would prevent from turning the system off. + // - The 1st case does not need to be handled here, but will be as a result of the handling for the 3rd case, see below. // - // 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()) { + // shutdownRequest is used to handle the 3rd case. If we really powered down on purpose this will still be set to SHUTDOWN_REQUEST + // as we left it in pwrOff(). If however we had an unexpected reboot, it would be set to NO_SHUTDOWN_REQUEST as we set it in pwrOn(). + // Any other value (e.g. resulting from data corruption) would also keep power on for safety, so this variable can NOT be used + // to detect an unexpected reboot (on a normal power on the contents of the variable are random). + // + // shutdownReason is used to differentiate between an unexpected reboot and a normal power on. We set it to DIRTY_SHUTDOWN in pwrOn() + // in anticipation of a potential reboot. Should there be one the value should be preserved and signal below that we rebooted unexpectedly. + // If it is NOT set to DIRTY_SHUTDOWN we likely had a normal boot and its contents are random. Due to the need to initialize it to detect a + // potential failure ASAP we cannot use it to determine in the firmware why we got there, it has to be buffered. + // + // powerupReason is there to cater for that, and is what is used in the firmware to decide whether we have to enter emergency mode. + // This variable needs to be in a RAM section that is not initialized or zeroed, since once we exit this pwrResetHandler() function the + // C runtime would otherwise overwrite it during program init. + + if (shutdownRequest != SHUTDOWN_REQUEST) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = PWR_ON_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; @@ -119,6 +142,10 @@ void pwrResetHandler() GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(PWR_GPIO, &GPIO_InitStructure); + if (shutdownReason == DIRTY_SHUTDOWN) { + powerupReason = DIRTY_SHUTDOWN; + } + pwrOn(); } } diff --git a/radio/src/targets/horus/stm32f4_flash.ld b/radio/src/targets/horus/stm32f4_flash.ld index 4bcc764a6..3f4d7985c 100644 --- a/radio/src/targets/horus/stm32f4_flash.ld +++ b/radio/src/targets/horus/stm32f4_flash.ld @@ -127,6 +127,13 @@ SECTIONS _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) : {