diff --git a/radio/src/Makefile b/radio/src/Makefile index 3212d851c..82eddef95 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -361,6 +361,10 @@ SIMU_DISKIO = NO # Values = NO, YES SIMU_AUDIO = NO +# Enable Watchdog test (DANGEROUS) +# Values = NO, YES +WATCHDOG_TEST = NO + #------- END BUILD OPTIONS --------------------------- # Define programs and commands. @@ -1023,6 +1027,9 @@ ifeq ($(PCB), TARANIS) ifeq ($(MIXERS_MONITOR), YES) CPPDEFS += -DMIXERS_MONITOR endif + ifeq ($(WATCHDOG_TEST), YES) + CPPDEFS += -DWATCHDOG_TEST + endif endif CC = $(TRGT)gcc diff --git a/radio/src/gui/Taranis/view_statistics.cpp b/radio/src/gui/Taranis/view_statistics.cpp index 29c01f0ee..8f5777ea7 100755 --- a/radio/src/gui/Taranis/view_statistics.cpp +++ b/radio/src/gui/Taranis/view_statistics.cpp @@ -105,6 +105,15 @@ void menuStatisticsDebug(uint8_t event) { TITLE(STR_MENUDEBUG); +#if defined(WATCHDOG_TEST) + if (s_warning_result) { + s_warning_result = 0; + // do a user requested watchdog test + TRACE("Performing watchdog test"); + pausePulses(); + } +#endif + switch(event) { case EVT_KEY_LONG(KEY_ENTER): @@ -136,6 +145,15 @@ void menuStatisticsDebug(uint8_t event) case EVT_KEY_FIRST(KEY_EXIT): chainMenu(menuMainView); break; +#if defined(WATCHDOG_TEST) + case EVT_KEY_LONG(KEY_MENU): + { + POPUP_CONFIRMATION("Test the watchdog?"); + const char * w = "The radio will reset!"; + SET_WARNING_INFO(w, strlen(w), 0); + } + break; +#endif } lcd_putsLeft(MENU_DEBUG_Y_FREE_RAM, "Free Mem"); diff --git a/radio/src/loadboot.cpp b/radio/src/loadboot.cpp index f4dbd0feb..f71fbd520 100644 --- a/radio/src/loadboot.cpp +++ b/radio/src/loadboot.cpp @@ -89,24 +89,33 @@ const uint8_t BootCode[] = { __attribute__ ((section(".bootrodata"), used)) void _bootStart() { - // turn soft power ON now - RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // Enable portD clock - GPIOD->BSRRL = 1; - GPIOD->MODER = (GPIOD->MODER & 0xFFFFFFFC) | 1; - #if defined(REV9E) - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; // Enable portC clock - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN; // Enable portG clock + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIODEN; #else - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; // Enable portC clock - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN; // Enable portE clock + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIODEN; #endif + // these two NOPs are needed (see STM32F errata sheet) before the peripheral + // register can be written after the peripheral clock was enabled + __ASM volatile ("nop"); + __ASM volatile ("nop"); + + // Turn soft power ON now + GPIOD->BSRRL = 1; // set PWR_GPIO_PIN_ON pin to 1 + GPIOD->MODER = (GPIOD->MODER & 0xFFFFFFFC) | 1; // General purpose output mode + + // TRIMS_GPIO_PIN_LHR is on PG0 on 9XE and on PE3 on Taranis + // TRIMS_GPIO_PIN_RHL is on PC1 on all versions + + // turn on pull-ups on trim keys GPIOC->PUPDR = 0x00000004; +#if defined(REV9E) + GPIOG->PUPDR = 0x00000001; +#else GPIOE->PUPDR = 0x00000040; +#endif - uint32_t i; - for (i = 0; i < 50000; i += 1) { + for (uint32_t i = 0; i < 50000; i += 1) { bwdt_reset(); } diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index f3f5938f9..2d28abebd 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1260,12 +1260,7 @@ void alert(const pm_char * t, const pm_char *s MESSAGE_SOUND_ARG) #if defined(PCBTARANIS) && defined(REV9E) uint32_t pwr_check = pwrCheck(); if (pwr_check == e_power_off) { - // TODO this is quick & dirty - lcdOff(); - BACKLIGHT_OFF(); - topLcdOff(); - SysTick->CTRL = 0; // turn off systick - pwrOff(); + boardOff(); } else if (pwr_check == e_power_press) { refresh = true; @@ -1276,7 +1271,7 @@ void alert(const pm_char * t, const pm_char *s MESSAGE_SOUND_ARG) } #else if (pwrCheck() == e_power_off) { - pwrOff(); // turn power off now + boardOff(); // turn power off now } #endif } @@ -2577,7 +2572,7 @@ int main(void) opentxClose(); lcd_clear() ; lcdRefresh() ; - pwrOff(); // Only turn power off if necessary + boardOff(); // Only turn power off if necessary wdt_disable(); 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/opentx.h b/radio/src/opentx.h index 7ef82bdfb..f9bae86ae 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -291,33 +291,39 @@ #include "debug.h" #if defined(SIMU) -#include "targets/simu/simpgmspace.h" + #include "targets/simu/simpgmspace.h" #elif defined(CPUARM) -typedef const unsigned char pm_uchar; -typedef const char pm_char; -typedef const uint16_t pm_uint16_t; -typedef const uint8_t pm_uint8_t; -typedef const int16_t pm_int16_t; -typedef const int8_t pm_int8_t; -#define pgm_read_byte(address_short) (*(uint8_t*)(address_short)) -#define PSTR(adr) adr -#define PROGMEM -#define pgm_read_adr(x) *(x) -#define cli() -#define sei() -extern void boardInit(); + typedef const unsigned char pm_uchar; + typedef const char pm_char; + typedef const uint16_t pm_uint16_t; + typedef const uint8_t pm_uint8_t; + typedef const int16_t pm_int16_t; + typedef const int8_t pm_int8_t; + #define pgm_read_byte(address_short) (*(uint8_t*)(address_short)) + #define PSTR(adr) adr + #define PROGMEM + #define pgm_read_adr(x) *(x) + #define cli() + #define sei() + extern void boardInit(); + #if defined(PCBTARANIS) + extern void boardOff(); + #else + #define boardOff() pwrOff(); + #endif #else -#include -#include -#include "pgmtypes.h" + #define boardOff() pwrOff(); + #include + #include + #include "pgmtypes.h" -#include -#include -#include -#define F_CPU 16000000UL // 16 MHz -#include -#define pgm_read_adr(address_short) pgm_read_word(address_short) -#include + #include + #include + #include + #define F_CPU 16000000UL // 16 MHz + #include + #define pgm_read_adr(address_short) pgm_read_word(address_short) + #include #endif #if defined(PCBTARANIS) diff --git a/radio/src/targets/simu/simpgmspace.h b/radio/src/targets/simu/simpgmspace.h index 2785c08e2..0b7523494 100644 --- a/radio/src/targets/simu/simpgmspace.h +++ b/radio/src/targets/simu/simpgmspace.h @@ -377,6 +377,7 @@ void eepromReadBlock (uint8_t * pointer_ram, uint32_t address, uint32_t size); #define wdt_enable(...) sleep(1/*ms*/) #define wdt_reset() sleep(1/*ms*/) #define boardInit() +#define boardOff() #define OS_MutexID pthread_mutex_t extern OS_MutexID audioMutex; diff --git a/radio/src/targets/taranis/board_taranis.cpp b/radio/src/targets/taranis/board_taranis.cpp index 25cb19f48..4d103d15e 100644 --- a/radio/src/targets/taranis/board_taranis.cpp +++ b/radio/src/targets/taranis/board_taranis.cpp @@ -156,7 +156,7 @@ void boardInit() #endif #if defined(REV9E) - if (!(RCC->CSR & (RCC_CSR_SFTRSTF | RCC_CSR_WDGRSTF))) { + if (!WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) { lcd_clear(); lcd_bmp(76, 2, bmp_lock, 0, 60); lcdRefresh(); @@ -187,7 +187,7 @@ void boardInit() lcdRefreshWait(); } if (duration < PWR_PRESS_DURATION_MIN || duration >= PWR_PRESS_DURATION_MAX) { - pwrOff(); + boardOff(); } } else { @@ -198,8 +198,27 @@ void boardInit() backlightInit(); #endif } + +void boardOff() +{ + BACKLIGHT_OFF(); +#if defined(REV9E) + topLcdOff(); #endif +#if defined(REV9E) + while (pwrPressed()) { + wdt_reset(); + } +#endif + + lcdOff(); + SysTick->CTRL = 0; // turn off systick + pwrOff(); +} + +#endif // #if !defined(SIMU) + #if defined(USB_JOYSTICK) && !defined(SIMU) extern USB_OTG_CORE_HANDLE USB_OTG_dev; diff --git a/radio/src/targets/taranis/board_taranis.h b/radio/src/targets/taranis/board_taranis.h index e33217b8c..e1171e99b 100644 --- a/radio/src/targets/taranis/board_taranis.h +++ b/radio/src/targets/taranis/board_taranis.h @@ -236,8 +236,9 @@ void checkRotaryEncoder(void); void watchdogInit(unsigned int duration); #define wdt_enable(x) watchdogInit(1500) #define wdt_reset() IWDG->KR = 0xAAAA -#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_SOFTWARE() (RCC->CSR & RCC_CSR_SFTRSTF) +#define WAS_RESET_BY_WATCHDOG() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF)) +#define WAS_RESET_BY_WATCHDOG_OR_SOFTWARE() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF | RCC_CSR_SFTRSTF)) #endif // ADC driver diff --git a/radio/src/targets/taranis/lcd_driver.cpp b/radio/src/targets/taranis/lcd_driver.cpp index 4ad229b7e..0ea21d8c5 100644 --- a/radio/src/targets/taranis/lcd_driver.cpp +++ b/radio/src/targets/taranis/lcd_driver.cpp @@ -363,7 +363,7 @@ void lcdInit() { LCD_Hardware_Init(); - if (WAS_RESET_BY_WATCHDOG()|WAS_RESET_BY_SOFTWARE()) return; //no need to reset LCD module + if (WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) return; //no need to reset LCD module //reset LCD module LCD_RST_LOW(); @@ -400,7 +400,7 @@ void lcdInitFinish() initialization (without reset) is also recommended by the data sheet. */ - if (!WAS_RESET_BY_WATCHDOG() && !WAS_RESET_BY_SOFTWARE()) { + if (!WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) { #if !defined(BOOT) while(g_tmr10ms < (RESET_WAIT_DELAY_MS/10)) {}; //wait measured from the power-on #else diff --git a/radio/src/targets/taranis/pwr_driver.c b/radio/src/targets/taranis/pwr_driver.c index b02ba3b14..1d2038a5d 100644 --- a/radio/src/targets/taranis/pwr_driver.c +++ b/radio/src/targets/taranis/pwr_driver.c @@ -37,11 +37,11 @@ #include "board_taranis.h" #include "../../pwr.h" -extern volatile uint32_t g_tmr10ms; -#define get_tmr10ms() g_tmr10ms - void pwrInit() { + // if any changes are done to the PWR PIN or pwrOn() function + // then the same changes must be done in _bootStart() + GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = PWR_GPIO_PIN_ON; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; @@ -84,23 +84,33 @@ void pwrOff() { GPIO_ResetBits(PWR_GPIO, PWR_GPIO_PIN_ON); + // disable interrupts + __disable_irq(); + + #if defined(REV9E) - // 9E needs watchdog reset because CPU is still running while the power - // key is held pressed by the user - while (1) { + // 9E needs watchdog reset because CPU is still running while + // the power key is held pressed by the user. + // The power key should be released by now, but we must make sure + while (pwrPressed()) { wdt_reset(); -#if 0 - // It doesn't work correctly, if we press long on the pwr button, the radio restarts when the button is released - PWR->CR |= PWR_CR_CWUF; - /* Select STANDBY mode */ - PWR->CR |= PWR_CR_PDDS; - /* Set SLEEPDEEP bit of Cortex System Control Register */ - SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; - /* Request Wait For Event */ - __WFE(); -#endif } + // Put the CPU into sleep to reduce the consumption, + // it might help with the RTC reset issue + PWR->CR |= PWR_CR_CWUF; + /* Select STANDBY mode */ + PWR->CR |= PWR_CR_PDDS; + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + /* Request Wait For Event */ + __WFE(); #endif + + while(1) { + wdt_reset(); + } + + //this function must not return! } #if defined(REV9E) diff --git a/radio/src/tasks_arm.cpp b/radio/src/tasks_arm.cpp index 8d3762411..25e25cf61 100644 --- a/radio/src/tasks_arm.cpp +++ b/radio/src/tasks_arm.cpp @@ -196,12 +196,7 @@ void menusTask(void * pdata) #endif opentxClose(); - -#if !defined(SIMU) - SysTick->CTRL = 0; // turn off systick -#endif - - pwrOff(); // Only turn power off if necessary + boardOff(); // Only turn power off if necessary } extern void audioTask(void* pdata);