1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-23 16:25:16 +03:00

Refactoring of startup code, mainly dealing with detection of unexpec… (#4275)

* Refactoring of startup code, mainly dealing with detection of unexpected restart/shutdown

* Added g_FATFS_Obj initialization [Horus]

* Fix normal startup

* Use g_eeGeneral.unexpectedShutdown only on radios that have PWRMANAGE defined
Fixes for radios that don't have power control.
Other fixes

* CLI test for new()

* [Horus] Reboot protection reworked to also handle non-WDT events

(cherry picked from commit fe9a52779d)

Conflicts:
	radio/src/targets/horus/board.h

* Reverting most of the changes

* Cleanup

* Added comment that explains apparent non usage of the wdt_disable() function

* More cleanup

* Missing include

* Compilation fix
This commit is contained in:
Damjan Adamic 2017-01-24 07:52:33 +01:00 committed by Bertrand Songis
parent bf15410bf1
commit b3f4870da7
9 changed files with 651 additions and 525 deletions

View file

@ -22,6 +22,7 @@
#include "diskio.h" #include "diskio.h"
#include <ctype.h> #include <ctype.h>
#include <malloc.h> #include <malloc.h>
#include <new>
#define CLI_COMMAND_MAX_ARGS 8 #define CLI_COMMAND_MAX_ARGS 8
#define CLI_COMMAND_MAX_LEN 256 #define CLI_COMMAND_MAX_LEN 256
@ -302,6 +303,62 @@ int cliTestSD(const char ** argv)
return 0; 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) int cliTrace(const char ** argv)
{ {
if (!strcmp(argv[1], "on")) { if (!strcmp(argv[1], "on")) {
@ -509,7 +566,7 @@ void printTaskSwitchLog()
uint32_t * tsl = new uint32_t[DEBUG_TASKS_LOG_SIZE]; uint32_t * tsl = new uint32_t[DEBUG_TASKS_LOG_SIZE];
if (!tsl) { if (!tsl) {
serialPrint("Not enough memory"); serialPrint("Not enough memory");
return 0; return;
} }
memcpy(tsl, taskSwitchLog, sizeof(taskSwitchLog)); memcpy(tsl, taskSwitchLog, sizeof(taskSwitchLog));
uint32_t * p = tsl + taskSwitchLogPos; uint32_t * p = tsl + taskSwitchLogPos;
@ -892,6 +949,7 @@ const CliCommand cliCommands[] = {
{ "set", cliSet, "<what> <value>" }, { "set", cliSet, "<what> <value>" },
{ "stackinfo", cliStackInfo, "" }, { "stackinfo", cliStackInfo, "" },
{ "meminfo", cliMemoryInfo, "" }, { "meminfo", cliMemoryInfo, "" },
{ "test", cliTest, "new | std::exception" },
{ "trace", cliTrace, "on | off" }, { "trace", cliTrace, "on | off" },
#if defined(PCBFLAMENCO) #if defined(PCBFLAMENCO)
{ "read_bq24195", cliReadBQ24195, "<register>" }, { "read_bq24195", cliReadBQ24195, "<register>" },

View file

@ -41,6 +41,12 @@
#define __SDRAM __DMA #define __SDRAM __DMA
#endif #endif
#if defined(PCBHORUS) && !defined(SIMU)
#define __NOINIT __attribute__((section(".noinit")))
#else
#define __NOINIT
#endif
#if defined(SIMU) || defined(CPUARM) || GCC_VERSION < 472 #if defined(SIMU) || defined(CPUARM) || GCC_VERSION < 472
typedef int32_t int24_t; typedef int32_t int24_t;
#else #else

View file

@ -2438,29 +2438,47 @@ void opentxInit(OPENTX_INIT_ARGS)
#if defined(RTCLOCK) && !defined(COPROCESSOR) #if defined(RTCLOCK) && !defined(COPROCESSOR)
rtcInit(); // RTC must be initialized before rambackupRestore() is called rtcInit(); // RTC must be initialized before rambackupRestore() is called
#endif #endif
#if defined(EEPROM) #if defined(EEPROM)
storageReadAll(); storageReadAll();
#endif #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()) { if (UNEXPECTED_SHUTDOWN()) {
TRACE("Unexpected Shutdown detected");
unexpectedShutdown = 1; unexpectedShutdown = 1;
} }
else {
#if defined(SDCARD) && !defined(PCBMEGA2560) #if defined(SDCARD) && !defined(PCBMEGA2560)
// SDCARD related stuff, only done if not unexpectedShutdown
if (!unexpectedShutdown) {
sdInit(); sdInit();
logsInit(); logsInit();
}
#endif #endif
}
#if defined(PCBHORUS) #if defined(PCBHORUS)
topbar = new Topbar(&g_model.topbarData); if (!unexpectedShutdown) {
LUA_INIT_THEMES_AND_WIDGETS(); // 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 #endif
// handling of storage for radios that have no EEPROM
#if !defined(EEPROM) #if !defined(EEPROM)
#if defined(RAMBACKUP) #if defined(RAMBACKUP)
if (UNEXPECTED_SHUTDOWN()) { if (unexpectedShutdown) {
// SDCARD not available, try to restore last model from RAM
TRACE("rambackupRestore");
rambackupRestore(); rambackupRestore();
} }
else { else {
@ -2469,7 +2487,7 @@ void opentxInit(OPENTX_INIT_ARGS)
#else #else
storageReadAll(); storageReadAll();
#endif #endif
#endif #endif // #if !defined(EEPROM)
#if defined(SERIAL2) #if defined(SERIAL2)
serial2Init(g_eeGeneral.serial2Mode, MODEL_TELEMETRY_PROTOCOL()); 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 (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on
if (!UNEXPECTED_SHUTDOWN()) { if (!unexpectedShutdown) {
opentxStart(); opentxStart();
} }
#if defined(CPUARM) || defined(CPUM2560) #if defined(CPUARM) || defined(CPUM2560)
// TODO Horus does not need this
if (!g_eeGeneral.unexpectedShutdown) { if (!g_eeGeneral.unexpectedShutdown) {
g_eeGeneral.unexpectedShutdown = 1; g_eeGeneral.unexpectedShutdown = 1;
storageDirty(EE_GENERAL); storageDirty(EE_GENERAL);
@ -2667,7 +2686,7 @@ int main()
drawSleepBitmap(); drawSleepBitmap();
opentxClose(); opentxClose();
boardOff(); // Only turn power off if necessary 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. 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 #endif

View file

@ -2,7 +2,7 @@
* Copyright (C) OpenTX * Copyright (C) OpenTX
* *
* Based on code named * 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 * er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x * gruvin9x - http://code.google.com/p/gruvin9x
* *
@ -37,7 +37,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include "debug.h"
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported variables * Exported variables
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
@ -50,11 +50,12 @@ extern int _heap_end;
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
extern void _exit( int status ) ; // extern void _exit( int status ) ;
extern void _kill( int pid, int sig ) ; // extern void _kill( int pid, int sig ) ;
extern int _getpid ( void ) ; // extern int _getpid ( void ) ;
unsigned char * heap = (unsigned char *)&_end; unsigned char * heap = (unsigned char *)&_end;
extern caddr_t _sbrk(int nbytes) extern caddr_t _sbrk(int nbytes)
{ {
if (heap + nbytes < (unsigned char *)&_heap_end) { if (heap + nbytes < (unsigned char *)&_heap_end) {
@ -70,84 +71,68 @@ extern caddr_t _sbrk(int nbytes)
extern int _gettimeofday(void *p1, void *p2) 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) 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 ; st->st_mode = S_IFCHR ;
return 0;
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) 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 ; return 0;
// for ( ; *ptr != 0 ; ptr++ )
for ( iIndex=0 ; iIndex < len ; iIndex++, ptr++ )
{
// TODO UART_PutChar( *ptr ) ;
}
return iIndex ;
} }
extern void _exit( int status ) extern void _exit(int status)
{ {
#if defined(SIMU) TRACE("_exit(%d)", status);
printf( "Exiting with status %d.\n", status ) ; for (;;);
#endif
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 ; return -1 ;
} }
//void _init (void)
//{
//}

View file

@ -156,6 +156,11 @@ void boardInit()
__enable_irq(); __enable_irq();
TRACE("\nHorus board started :)"); 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(); keysInit();
adcInit(); adcInit();

View file

@ -1,462 +1,481 @@
/* /*
* Copyright (C) OpenTX * Copyright (C) OpenTX
* *
* Based on code named * 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 * er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x * gruvin9x - http://code.google.com/p/gruvin9x
* *
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#ifndef _BOARD_HORUS_H_ #ifndef _BOARD_HORUS_H_
#define _BOARD_HORUS_H_ #define _BOARD_HORUS_H_
#include "stddef.h" #include "stddef.h"
#if defined(__cplusplus) && !defined(SIMU) #if defined(__cplusplus) && !defined(SIMU)
extern "C" { extern "C" {
#endif #endif
#if __clang__ #if __clang__
// clang is very picky about the use of "register" // clang is very picky about the use of "register"
// Tell clang to ignore the warnings for the following files // Tell clang to ignore the warnings for the following files
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-register" #pragma clang diagnostic ignored "-Wdeprecated-register"
#endif #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/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_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_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_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_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_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_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_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_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_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_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_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_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_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_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/stm32f4xx_dma2d.h"
#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/misc.h" #include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/STM32F4xx_StdPeriph_Driver/inc/misc.h"
#if __clang__ #if __clang__
// Restore warnings about registers // Restore warnings about registers
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif
#if !defined(SIMU) #if !defined(SIMU)
#include "usbd_cdc_core.h" #include "usbd_cdc_core.h"
#include "usbd_msc_core.h" #include "usbd_msc_core.h"
#include "usbd_hid_core.h" #include "usbd_hid_core.h"
#include "usbd_usr.h" #include "usbd_usr.h"
#include "usbd_desc.h" #include "usbd_desc.h"
#include "usb_conf.h" #include "usb_conf.h"
#include "usbd_conf.h" #include "usbd_conf.h"
#endif #endif
#include "hal.h" #include "hal.h"
#if defined(__cplusplus) && !defined(SIMU) #if defined(__cplusplus) && !defined(SIMU)
} }
#endif #endif
#define FLASHSIZE 0x80000 #define FLASHSIZE 0x80000
#define BOOTLOADER_SIZE 0x8000 #define BOOTLOADER_SIZE 0x8000
#define FIRMWARE_ADDRESS 0x08000000 #define FIRMWARE_ADDRESS 0x08000000
// HSI is at 168Mhz (over-drive is not enabled!) // HSI is at 168Mhz (over-drive is not enabled!)
#define PERI1_FREQUENCY 42000000 #define PERI1_FREQUENCY 42000000
#define PERI2_FREQUENCY 84000000 #define PERI2_FREQUENCY 84000000
#define TIMER_MULT_APB1 2 #define TIMER_MULT_APB1 2
#define TIMER_MULT_APB2 2 #define TIMER_MULT_APB2 2
#define strcpy_P strcpy #define strcpy_P strcpy
#define strcat_P strcat #define strcat_P strcat
extern uint16_t sessionTimer; extern uint16_t sessionTimer;
#define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE) #define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE)
#define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_RESET) #define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_RESET)
// Board driver // Board driver
void boardInit(void); void boardInit(void);
void boardOff(void); void boardOff(void);
// Delays driver // Delays driver
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void delaysInit(void); void delaysInit(void);
void delay_01us(uint16_t nb); void delay_01us(uint16_t nb);
void delay_us(uint16_t nb); void delay_us(uint16_t nb);
void delay_ms(uint32_t ms); void delay_ms(uint32_t ms);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
// PCBREV driver // PCBREV driver
#define IS_HORUS_PROD() GPIO_ReadInputDataBit(PCBREV_GPIO, PCBREV_GPIO_PIN) #define IS_HORUS_PROD() GPIO_ReadInputDataBit(PCBREV_GPIO, PCBREV_GPIO_PIN)
#if defined(SIMU) #if defined(SIMU)
#define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() true #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() true
#elif PCBREV >= 13 #elif PCBREV >= 13
#define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() IS_HORUS_PROD() #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() IS_HORUS_PROD()
#else #else
#define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() (!IS_HORUS_PROD()) #define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() (!IS_HORUS_PROD())
#endif #endif
// CPU Unique ID // CPU Unique ID
#define LEN_CPU_UID (3*8+2) #define LEN_CPU_UID (3*8+2)
void getCPUUniqueID(char * s); void getCPUUniqueID(char * s);
// SD driver // SD driver
#define BLOCK_SIZE 512 /* Block Size in Bytes */ #define BLOCK_SIZE 512 /* Block Size in Bytes */
#if !defined(SIMU) || defined(SIMU_DISKIO) #if !defined(SIMU) || defined(SIMU_DISKIO)
uint32_t sdIsHC(void); uint32_t sdIsHC(void);
uint32_t sdGetSpeed(void); uint32_t sdGetSpeed(void);
#define SD_IS_HC() (sdIsHC()) #define SD_IS_HC() (sdIsHC())
#define SD_GET_SPEED() (sdGetSpeed()) #define SD_GET_SPEED() (sdGetSpeed())
#define SD_GET_FREE_BLOCKNR() (sdGetFreeSectors()) #define SD_GET_FREE_BLOCKNR() (sdGetFreeSectors())
#define SD_CARD_PRESENT() (~SD_PRESENT_GPIO->IDR & SD_PRESENT_GPIO_PIN) #define SD_CARD_PRESENT() (~SD_PRESENT_GPIO->IDR & SD_PRESENT_GPIO_PIN)
void sdInit(void); void sdInit(void);
void sdMount(void); void sdMount(void);
void sdDone(void); void sdDone(void);
#define sdPoll10ms() #define sdPoll10ms()
uint32_t sdMounted(void); uint32_t sdMounted(void);
#else #else
#define SD_IS_HC() (0) #define SD_IS_HC() (0)
#define SD_GET_SPEED() (0) #define SD_GET_SPEED() (0)
#define sdInit() #define sdInit()
#define sdMount() #define sdMount()
#define sdDone() #define sdDone()
#define SD_CARD_PRESENT() true #define SD_CARD_PRESENT() true
#endif #endif
#if defined(DISK_CACHE) #if defined(DISK_CACHE)
#include "diskio.h" #include "diskio.h"
DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count); DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count);
DRESULT __disk_write(BYTE drv, const BYTE * buff, DWORD sector, UINT count); DRESULT __disk_write(BYTE drv, const BYTE * buff, DWORD sector, UINT count);
#else #else
#define __disk_read disk_read #define __disk_read disk_read
#define __disk_write disk_write #define __disk_write disk_write
#endif #endif
// Flash Write driver // Flash Write driver
#define FLASH_PAGESIZE 256 #define FLASH_PAGESIZE 256
void unlockFlash(void); void unlockFlash(void);
void lockFlash(void); void lockFlash(void);
void flashWrite(uint32_t * address, uint32_t * buffer); void flashWrite(uint32_t * address, uint32_t * buffer);
uint32_t isFirmwareStart(const uint8_t * buffer); uint32_t isFirmwareStart(const uint8_t * buffer);
uint32_t isBootloaderStart(const uint8_t * buffer); uint32_t isBootloaderStart(const uint8_t * buffer);
// SDRAM driver // SDRAM driver
void SDRAM_Init(void); void SDRAM_Init(void);
// Pulses driver // Pulses driver
#define INTERNAL_MODULE_ON() GPIO_SetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) #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 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_ON() GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
#define EXTERNAL_MODULE_OFF() GPIO_ResetBits(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_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_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET)
#define IS_UART_MODULE(port) (port == INTERNAL_MODULE) #define IS_UART_MODULE(port) (port == INTERNAL_MODULE)
void init_no_pulses(uint32_t port); void init_no_pulses(uint32_t port);
void disable_no_pulses(uint32_t port); void disable_no_pulses(uint32_t port);
void init_ppm(uint32_t module_index); void init_ppm(uint32_t module_index);
void disable_ppm(uint32_t module_index); void disable_ppm(uint32_t module_index);
void init_pxx(uint32_t module_index); void init_pxx(uint32_t module_index);
void disable_pxx(uint32_t module_index); void disable_pxx(uint32_t module_index);
void init_dsm2(uint32_t module_index); void init_dsm2(uint32_t module_index);
void disable_dsm2(uint32_t module_index); void disable_dsm2(uint32_t module_index);
void init_crossfire(uint32_t module_index); void init_crossfire(uint32_t module_index);
void disable_crossfire(uint32_t module_index); void disable_crossfire(uint32_t module_index);
// Trainer driver // Trainer driver
void init_trainer_ppm(void); void init_trainer_ppm(void);
void stop_trainer_ppm(void); void stop_trainer_ppm(void);
void init_trainer_capture(void); void init_trainer_capture(void);
void stop_trainer_capture(void); void stop_trainer_capture(void);
// Keys driver // Keys driver
enum EnumKeys enum EnumKeys
{ {
KEY_PGUP, KEY_PGUP,
KEY_PGDN, KEY_PGDN,
KEY_ENTER, KEY_ENTER,
KEY_MODEL, KEY_MODEL,
KEY_UP = KEY_MODEL, KEY_UP = KEY_MODEL,
KEY_EXIT, KEY_EXIT,
KEY_DOWN = KEY_EXIT, KEY_DOWN = KEY_EXIT,
KEY_TELEM, KEY_TELEM,
KEY_RIGHT = KEY_TELEM, KEY_RIGHT = KEY_TELEM,
KEY_RADIO, KEY_RADIO,
KEY_LEFT = KEY_RADIO, KEY_LEFT = KEY_RADIO,
TRM_BASE, TRM_BASE,
TRM_LH_DWN = TRM_BASE, TRM_LH_DWN = TRM_BASE,
TRM_LH_UP, TRM_LH_UP,
TRM_LV_DWN, TRM_LV_DWN,
TRM_LV_UP, TRM_LV_UP,
TRM_RV_DWN, TRM_RV_DWN,
TRM_RV_UP, TRM_RV_UP,
TRM_RH_DWN, TRM_RH_DWN,
TRM_RH_UP, TRM_RH_UP,
TRM_LS_DWN, TRM_LS_DWN,
TRM_LS_UP, TRM_LS_UP,
TRM_RS_DWN, TRM_RS_DWN,
TRM_RS_UP, TRM_RS_UP,
TRM_LAST = TRM_RS_UP, TRM_LAST = TRM_RS_UP,
NUM_KEYS NUM_KEYS
}; };
enum EnumSwitches enum EnumSwitches
{ {
SW_SA, SW_SA,
SW_SB, SW_SB,
SW_SC, SW_SC,
SW_SD, SW_SD,
SW_SE, SW_SE,
SW_SF, SW_SF,
SW_SG, SW_SG,
SW_SH, SW_SH,
NUM_SWITCHES NUM_SWITCHES
}; };
#define IS_3POS(x) ((x) != SW_SF && (x) != SW_SH) #define IS_3POS(x) ((x) != SW_SF && (x) != SW_SH)
enum EnumSwitchesPositions enum EnumSwitchesPositions
{ {
SW_SA0, SW_SA0,
SW_SA1, SW_SA1,
SW_SA2, SW_SA2,
SW_SB0, SW_SB0,
SW_SB1, SW_SB1,
SW_SB2, SW_SB2,
SW_SC0, SW_SC0,
SW_SC1, SW_SC1,
SW_SC2, SW_SC2,
SW_SD0, SW_SD0,
SW_SD1, SW_SD1,
SW_SD2, SW_SD2,
SW_SE0, SW_SE0,
SW_SE1, SW_SE1,
SW_SE2, SW_SE2,
SW_SF0, SW_SF0,
SW_SF1, SW_SF1,
SW_SF2, SW_SF2,
SW_SG0, SW_SG0,
SW_SG1, SW_SG1,
SW_SG2, SW_SG2,
SW_SH0, SW_SH0,
SW_SH1, SW_SH1,
SW_SH2, SW_SH2,
}; };
void keysInit(void); void keysInit(void);
uint8_t keyState(uint8_t index); uint8_t keyState(uint8_t index);
uint32_t switchState(uint8_t index); uint32_t switchState(uint8_t index);
uint32_t readKeys(void); uint32_t readKeys(void);
uint32_t readTrims(void); uint32_t readTrims(void);
#define TRIMS_PRESSED() (readTrims()) #define TRIMS_PRESSED() (readTrims())
#define KEYS_PRESSED() (readKeys()) #define KEYS_PRESSED() (readKeys())
#define DBLKEYS_PRESSED_RGT_LFT(in) ((in & ((1<<KEY_RIGHT) + (1<<KEY_LEFT))) == ((1<<KEY_RIGHT) + (1<<KEY_LEFT))) #define DBLKEYS_PRESSED_RGT_LFT(in) ((in & ((1<<KEY_RIGHT) + (1<<KEY_LEFT))) == ((1<<KEY_RIGHT) + (1<<KEY_LEFT)))
#define DBLKEYS_PRESSED_UP_DWN(in) ((in & ((1<<KEY_UP) + (1<<KEY_DOWN))) == ((1<<KEY_UP) + (1<<KEY_DOWN))) #define DBLKEYS_PRESSED_UP_DWN(in) ((in & ((1<<KEY_UP) + (1<<KEY_DOWN))) == ((1<<KEY_UP) + (1<<KEY_DOWN)))
#define DBLKEYS_PRESSED_RGT_UP(in) ((in & ((1<<KEY_RIGHT) + (1<<KEY_UP))) == ((1<<KEY_RIGHT) + (1<<KEY_UP))) #define DBLKEYS_PRESSED_RGT_UP(in) ((in & ((1<<KEY_RIGHT) + (1<<KEY_UP))) == ((1<<KEY_RIGHT) + (1<<KEY_UP)))
#define DBLKEYS_PRESSED_LFT_DWN(in) ((in & ((1<<KEY_LEFT) + (1<<KEY_DOWN))) == ((1<<KEY_LEFT) + (1<<KEY_DOWN))) #define DBLKEYS_PRESSED_LFT_DWN(in) ((in & ((1<<KEY_LEFT) + (1<<KEY_DOWN))) == ((1<<KEY_LEFT) + (1<<KEY_DOWN)))
// Rotary encoder driver // Rotary encoder driver
#define ROTARY_ENCODER_NAVIGATION #define ROTARY_ENCODER_NAVIGATION
void checkRotaryEncoder(void); void checkRotaryEncoder(void);
// WDT driver // WDT driver
#define WDTO_500MS 500 #define WDTO_500MS 500
#define wdt_disable() extern uint32_t powerupReason;
void watchdogInit(unsigned int duration);
#if defined(WATCHDOG_DISABLED) || defined(SIMU) #define SHUTDOWN_REQUEST 0xDEADBEEF
#define wdt_enable(x) #define NO_SHUTDOWN_REQUEST ~SHUTDOWN_REQUEST
#define wdt_reset() #define DIRTY_SHUTDOWN 0xCAFEDEAD
#else #define NORMAL_POWER_OFF ~DIRTY_SHUTDOWN
#define wdt_enable(x) watchdogInit(x)
#define wdt_reset() IWDG->KR = 0xAAAA #define wdt_disable()
#endif void watchdogInit(unsigned int duration);
#define WAS_RESET_BY_WATCHDOG() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF)) #if defined(SIMU)
#define WAS_RESET_BY_SOFTWARE() (RCC->CSR & RCC_CSR_SFTRSTF) #define WAS_RESET_BY_WATCHDOG() (false)
#define WAS_RESET_BY_WATCHDOG_OR_SOFTWARE() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF | RCC_CSR_SFTRSTF)) #define WAS_RESET_BY_SOFTWARE() (false)
#define WAS_RESET_BY_WATCHDOG_OR_SOFTWARE() (false)
// ADC driver #define wdt_enable(x)
#define NUM_POTS 3 #define wdt_reset()
#define NUM_SLIDERS 4 #else
#define NUM_XPOTS 3 #if defined(WATCHDOG_DISABLED)
enum Analogs { #define wdt_enable(x)
STICK1, #define wdt_reset()
STICK2, #else
STICK3, #define wdt_enable(x) watchdogInit(x)
STICK4, #define wdt_reset() IWDG->KR = 0xAAAA
POT_FIRST, #endif
POT1 = POT_FIRST, #define WAS_RESET_BY_WATCHDOG() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF))
POT2, #define WAS_RESET_BY_SOFTWARE() (RCC->CSR & RCC_CSR_SFTRSTF)
POT3, #define WAS_RESET_BY_WATCHDOG_OR_SOFTWARE() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF | RCC_CSR_SFTRSTF))
POT_LAST = POT3, #endif
SLIDER1,
SLIDER2, // ADC driver
SLIDER3, #define NUM_POTS 3
SLIDER4, #define NUM_SLIDERS 4
TX_VOLTAGE, #define NUM_XPOTS 3
MOUSE1, enum Analogs {
MOUSE2, STICK1,
NUMBER_ANALOG STICK2,
}; STICK3,
#define IS_POT(x) ((x)>=POT_FIRST && (x)<=POT_LAST) STICK4,
#define IS_SLIDER(x) ((x)>=SLIDER1 && (x)<=SLIDER4) POT_FIRST,
extern uint16_t adcValues[NUMBER_ANALOG]; POT1 = POT_FIRST,
void adcInit(void); POT2,
void adcRead(void); POT3,
uint16_t getAnalogValue(uint8_t index); POT_LAST = POT3,
uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps SLIDER1,
SLIDER2,
#if defined(__cplusplus) && !defined(SIMU) SLIDER3,
extern "C" { SLIDER4,
#endif TX_VOLTAGE,
MOUSE1,
// Power driver MOUSE2,
void pwrInit(void); NUMBER_ANALOG
uint32_t pwrCheck(void); };
void pwrOn(void); #define IS_POT(x) ((x)>=POT_FIRST && (x)<=POT_LAST)
void pwrOff(void); #define IS_SLIDER(x) ((x)>=SLIDER1 && (x)<=SLIDER4)
void pwrResetHandler(void); extern uint16_t adcValues[NUMBER_ANALOG];
uint32_t pwrPressed(void); void adcInit(void);
uint32_t pwrPressedDuration(void); void adcRead(void);
#define pwroffPressed() pwrPressed() uint16_t getAnalogValue(uint8_t index);
#define UNEXPECTED_SHUTDOWN() (WAS_RESET_BY_WATCHDOG() || g_eeGeneral.unexpectedShutdown) uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps
// Led driver #if defined(__cplusplus) && !defined(SIMU)
void ledOff(void); extern "C" {
void ledRed(void); #endif
void ledBlue(void);
// Power driver
// LCD driver void pwrInit(void);
#define LCD_W 480 uint32_t pwrCheck(void);
#define LCD_H 272 void pwrOn(void);
#define LCD_DEPTH 16 void pwrOff(void);
void lcdInit(void); void pwrResetHandler(void);
void lcdRefresh(void); uint32_t pwrPressed(void);
void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color); uint32_t pwrPressedDuration(void);
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); #define pwroffPressed() pwrPressed()
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); #if defined(SIMU)
void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t h, uint32_t format); #define UNEXPECTED_SHUTDOWN() (false)
void lcdStoreBackupBuffer(void); #else
int lcdRestoreBackupBuffer(void); #define UNEXPECTED_SHUTDOWN() (powerupReason == DIRTY_SHUTDOWN)
void lcdSetContrast(); #endif
#define lcdOff(...)
#define lcdSetRefVolt(...) // Led driver
#define lcdRefreshWait(...) void ledOff(void);
void ledRed(void);
// Backlight driver void ledBlue(void);
void backlightInit(void);
#if defined(SIMU) // LCD driver
#define backlightEnable(...) #define LCD_W 480
#else #define LCD_H 272
void backlightEnable(uint8_t dutyCycle); #define LCD_DEPTH 16
#endif void lcdInit(void);
#define BACKLIGHT_ENABLE() backlightEnable(unexpectedShutdown ? 100 : 100-g_eeGeneral.backlightBright) void lcdRefresh(void);
#define BACKLIGHT_DISABLE() backlightEnable(unexpectedShutdown ? 100 : g_eeGeneral.blOffBright) void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color);
#define isBacklightEnabled() true 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);
// USB driver void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t h, uint32_t format);
int usbPlugged(void); void lcdStoreBackupBuffer(void);
void usbInit(void); int lcdRestoreBackupBuffer(void);
void usbStart(void); void lcdSetContrast();
void usbStop(void); #define lcdOff(...)
void usbSerialPutc(uint8_t c); #define lcdSetRefVolt(...)
#define USB_NAME "FrSky Horus" #define lcdRefreshWait(...)
#define USB_MANUFACTURER 'F', 'r', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */
#define USB_PRODUCT 'H', 'o', 'r', 'u', 's', ' ', ' ', ' ' /* 8 Bytes */ // Backlight driver
void backlightInit(void);
#if defined(__cplusplus) && !defined(SIMU) #if defined(SIMU)
} #define backlightEnable(...)
#endif #else
void backlightEnable(uint8_t dutyCycle);
// Audio driver #endif
void audioInit(void); #define BACKLIGHT_ENABLE() backlightEnable(unexpectedShutdown ? 100 : 100-g_eeGeneral.backlightBright)
void audioConsumeCurrentBuffer(void); #define BACKLIGHT_DISABLE() backlightEnable(unexpectedShutdown ? 100 : g_eeGeneral.blOffBright)
#define audioDisableIrq() // interrupts must stay enabled on Horus #define isBacklightEnabled() true
#define audioEnableIrq() // interrupts must stay enabled on Horus
#define setSampleRate(freq) // USB driver
void setScaledVolume(uint8_t volume); int usbPlugged(void);
void setVolume(uint8_t volume); void usbInit(void);
int32_t getVolume(void); void usbStart(void);
#define VOLUME_LEVEL_MAX 23 void usbStop(void);
#define VOLUME_LEVEL_DEF 12 void usbSerialPutc(uint8_t c);
#define USB_NAME "FrSky Horus"
// Telemetry driver #define USB_MANUFACTURER 'F', 'r', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */
#define TELEMETRY_FIFO_SIZE 512 #define USB_PRODUCT 'H', 'o', 'r', 'u', 's', ' ', ' ', ' ' /* 8 Bytes */
void telemetryPortInit(uint32_t baudrate, uint8_t mode);
void telemetryPortSetDirectionOutput(void); #if defined(__cplusplus) && !defined(SIMU)
void sportSendBuffer(uint8_t * buffer, uint32_t count); }
uint8_t telemetryGetByte(uint8_t * byte); #endif
// Haptic driver // Audio driver
void hapticInit(void); void audioInit(void);
void hapticDone(void); void audioConsumeCurrentBuffer(void);
void hapticOff(void); #define audioDisableIrq() // interrupts must stay enabled on Horus
#define HAPTIC_OFF() hapticOff() #define audioEnableIrq() // interrupts must stay enabled on Horus
void hapticOn(uint32_t pwmPercent); #define setSampleRate(freq)
void setScaledVolume(uint8_t volume);
// GPS driver void setVolume(uint8_t volume);
void gpsInit(uint32_t baudrate); int32_t getVolume(void);
uint8_t gpsGetByte(uint8_t * byte); #define VOLUME_LEVEL_MAX 23
#if defined(DEBUG) #define VOLUME_LEVEL_DEF 12
extern uint8_t gpsTraceEnabled;
#endif // Telemetry driver
void gpsSendByte(uint8_t byte); #define TELEMETRY_FIFO_SIZE 512
void telemetryPortInit(uint32_t baudrate, uint8_t mode);
// Second serial port driver void telemetryPortSetDirectionOutput(void);
#define SERIAL2 void sportSendBuffer(uint8_t * buffer, uint32_t count);
#define DEBUG_BAUDRATE 115200 uint8_t telemetryGetByte(uint8_t * byte);
extern uint8_t serial2Mode;
void serial2Init(unsigned int mode, unsigned int protocol); // Haptic driver
void serial2Putc(char c); void hapticInit(void);
#define serial2TelemetryInit(protocol) serial2Init(UART_MODE_TELEMETRY, protocol) void hapticDone(void);
void serial2SbusInit(void); void hapticOff(void);
void serial2Stop(void); #define HAPTIC_OFF() hapticOff()
#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE) void hapticOn(uint32_t pwmPercent);
int sbusGetByte(uint8_t * byte);
// GPS driver
// BT driver void gpsInit(uint32_t baudrate);
#define BLUETOOTH_DEFAULT_BAUDRATE 115200 uint8_t gpsGetByte(uint8_t * byte);
#define BLUETOOTH_FACTORY_BAUDRATE 9600 #if defined(DEBUG)
uint8_t bluetoothReady(void); extern uint8_t gpsTraceEnabled;
void bluetoothInit(uint32_t baudrate); #endif
void bluetoothWrite(const void * buffer, int len); void gpsSendByte(uint8_t byte);
void bluetoothWriteString(const char * str);
int bluetoothRead(void * buffer, int len); // Second serial port driver
void bluetoothWakeup(void); #define SERIAL2
void bluetoothDone(void); #define DEBUG_BAUDRATE 115200
extern uint8_t serial2Mode;
#if defined(USB_JOYSTICK) && !defined(SIMU) void serial2Init(unsigned int mode, unsigned int protocol);
void usbJoystickUpdate(void); void serial2Putc(char c);
#endif #define serial2TelemetryInit(protocol) serial2Init(UART_MODE_TELEMETRY, protocol)
void serial2SbusInit(void);
extern uint8_t currentTrainerMode; void serial2Stop(void);
void checkTrainerSettings(void); #define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE)
int sbusGetByte(uint8_t * byte);
#if defined(__cplusplus)
#include "fifo.h" // BT driver
#include "dmafifo.h" #define BLUETOOTH_DEFAULT_BAUDRATE 115200
extern DMAFifo<512> telemetryFifo; #define BLUETOOTH_FACTORY_BAUDRATE 9600
extern DMAFifo<32> serial2RxFifo; uint8_t bluetoothReady(void);
#endif void bluetoothInit(uint32_t baudrate);
void bluetoothWrite(const void * buffer, int len);
void bluetoothWriteString(const char * str);
#endif // _BOARD_HORUS_H_ 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_

View file

@ -308,7 +308,7 @@ DRESULT disk_ioctl (
// TODO everything here should not be in the driver layer ... // 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) #if defined(LOG_TELEMETRY)
FIL g_telemetryFile = {}; FIL g_telemetryFile = {};
#endif #endif

View file

@ -21,6 +21,10 @@
#include "pwr.h" #include "pwr.h"
#include "board.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() void pwrInit()
{ {
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
@ -70,6 +74,8 @@ void pwrInit()
void pwrOn() void pwrOn()
{ {
GPIO_SetBits(PWR_GPIO, PWR_ON_GPIO_PIN); GPIO_SetBits(PWR_GPIO, PWR_ON_GPIO_PIN);
shutdownRequest = NO_SHUTDOWN_REQUEST;
shutdownReason = DIRTY_SHUTDOWN;
} }
void pwrOff() void pwrOff()
@ -87,6 +93,8 @@ void pwrOff()
// Shutdown the Haptic // Shutdown the Haptic
hapticDone(); hapticDone();
shutdownRequest = SHUTDOWN_REQUEST;
shutdownReason = NORMAL_POWER_OFF;
GPIO_ResetBits(PWR_GPIO, PWR_ON_GPIO_PIN); GPIO_ResetBits(PWR_GPIO, PWR_ON_GPIO_PIN);
} }
@ -104,13 +112,28 @@ void pwrResetHandler()
__ASM volatile ("nop"); __ASM volatile ("nop");
__ASM volatile ("nop"); __ASM volatile ("nop");
// Turn soft power ON now, but only if we got started because of the watchdog // We get here whether we are powering up normally, we had an unexpected reboot or we have just powered down normally.
// or software reset. If the radio was started by user pressing the power button // We want:
// then that button is providing power and we don't need to enable it here. // - 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 // shutdownRequest is used to handle the 3rd case. If we really powered down on purpose this will still be set to SHUTDOWN_REQUEST
// power on/off loop after being powered off by the user. (issue #2790) // 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().
if (WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) { // 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_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = PWR_ON_GPIO_PIN; GPIO_InitStructure.GPIO_Pin = PWR_ON_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
@ -119,6 +142,10 @@ void pwrResetHandler()
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(PWR_GPIO, &GPIO_InitStructure); GPIO_Init(PWR_GPIO, &GPIO_InitStructure);
if (shutdownReason == DIRTY_SHUTDOWN) {
powerupReason = DIRTY_SHUTDOWN;
}
pwrOn(); pwrOn();
} }
} }

View file

@ -127,6 +127,13 @@ SECTIONS
_ebss = .; /* define a global symbol at bss end */ _ebss = .; /* define a global symbol at bss end */
} >CCM } >CCM
/* Non-zeroed data section */
. = ALIGN(4);
.noinit (NOLOAD) :
{
*(.noinit)
} >CCM
/* collect all uninitialized .ccm sections */ /* collect all uninitialized .ccm sections */
.ram (NOLOAD) : .ram (NOLOAD) :
{ {