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

MAGIC value for powerReason should be stored in RTC backup on Horus (#7096)

- Allows the radio main application to start correctly when coming from an app in RAM
- Refactoring of the `UNEXPECTED_SHUTDOWN()` process
- Saves the RTC battery as BACKUP RAM is not needed on normal shutdown
- On PWR OFF on an ALERT, the radio won't show the next alert before shutting down
- Bootloader flashable through the SD Manager
This commit is contained in:
Bertrand Songis 2019-11-21 11:50:33 +01:00 committed by GitHub
parent 103534bdcf
commit 4cdd17f0d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 235 additions and 190 deletions

View file

@ -148,11 +148,11 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/bitmaps/${GUI_DIR})
add_subdirectory(lua) add_subdirectory(lua)
include(gui/CMakeLists.txt) include(gui/CMakeLists.txt)
if(RAMBACKUP) if(RTC_BACKUP_RAM)
add_definitions(-DRAMBACKUP) add_definitions(-DRTC_BACKUP_RAM)
set(SRC ${SRC} storage/rlc.cpp) set(SRC ${SRC} storage/rlc.cpp)
set(FIRMWARE_SRC ${FIRMWARE_SRC} storage/rambackup.cpp) set(FIRMWARE_SRC ${FIRMWARE_SRC} storage/rtc_backup.cpp)
set(GTEST_SRC ${GTEST_SRC} ${RADIO_SRC_DIRECTORY}/storage/rambackup.cpp) set(GTEST_SRC ${GTEST_SRC} ${RADIO_SRC_DIRECTORY}/storage/rtc_backup.cpp)
endif() endif()
if(NOT LUA STREQUAL NO) if(NOT LUA STREQUAL NO)

View file

@ -762,11 +762,11 @@ const char * Bluetooth::flashFirmware(const char * filename)
pausePulses(); pausePulses();
bluetoothInit(BLUETOOTH_BOOTLOADER_BAUDRATE, true); // normal mode bluetoothInit(BLUETOOTH_BOOTLOADER_BAUDRATE, true); // normal mode
watchdogSuspend(1000); watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000); RTOS_WAIT_MS(1000);
bluetoothInit(BLUETOOTH_BOOTLOADER_BAUDRATE, false); // bootloader mode bluetoothInit(BLUETOOTH_BOOTLOADER_BAUDRATE, false); // bootloader mode
watchdogSuspend(1000); watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000); RTOS_WAIT_MS(1000);
const char * result = doFlashFirmware(filename); const char * result = doFlashFirmware(filename);
@ -785,7 +785,7 @@ const char * Bluetooth::flashFirmware(const char * filename)
drawProgressScreen(getBasename(filename), STR_MODULE_RESET, 0, 0); drawProgressScreen(getBasename(filename), STR_MODULE_RESET, 0, 0);
/* wait 1s off */ /* wait 1s off */
watchdogSuspend(1000); watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000); RTOS_WAIT_MS(1000);
state = BLUETOOTH_STATE_OFF; state = BLUETOOTH_STATE_OFF;

View file

@ -94,7 +94,7 @@ void readModelNotes()
menuTextView(event); menuTextView(event);
event = getEvent(); event = getEvent();
lcdRefresh(); lcdRefresh();
wdt_reset(); WDG_RESET();
} }
LED_ERROR_END(); LED_ERROR_END();

View file

@ -51,7 +51,7 @@ bool menuRadioPowerMeter(event_t event)
lcdRefresh(); lcdRefresh();
moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID); moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID);
/* wait 1s to resume normal operation before leaving */ /* wait 1s to resume normal operation before leaving */
watchdogSuspend(1000); watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000); RTOS_WAIT_MS(1000);
return false; return false;
} }

View file

@ -159,6 +159,10 @@ void onSdManagerMenu(const char * result)
getSelectionFullPath(lfn); getSelectionFullPath(lfn);
pushMenuTextView(lfn); pushMenuTextView(lfn);
} }
else if (result == STR_FLASH_BOOTLOADER) {
getSelectionFullPath(lfn);
bootloaderFlash(lfn);
}
else if (result == STR_FLASH_INTERNAL_MODULE) { else if (result == STR_FLASH_INTERNAL_MODULE) {
getSelectionFullPath(lfn); getSelectionFullPath(lfn);
FrskyDeviceFirmwareUpdate device(INTERNAL_MODULE); FrskyDeviceFirmwareUpdate device(INTERNAL_MODULE);
@ -278,6 +282,13 @@ bool menuRadioSdManager(event_t _event)
POPUP_MENU_ADD_ITEM(STR_ASSIGN_SPLASH); POPUP_MENU_ADD_ITEM(STR_ASSIGN_SPLASH);
} }
} }
if (!READ_ONLY() && !strcasecmp(ext, FIRMWARE_EXT)) {
TCHAR lfn[_MAX_LFN+1];
getSelectionFullPath(lfn);
if (isBootloader(lfn)) {
POPUP_MENU_ADD_ITEM(STR_FLASH_BOOTLOADER);
}
}
else if (!READ_ONLY() && !strcasecmp(ext, SPORT_FIRMWARE_EXT)) { else if (!READ_ONLY() && !strcasecmp(ext, SPORT_FIRMWARE_EXT)) {
if (HAS_SPORT_UPDATE_CONNECTOR()) if (HAS_SPORT_UPDATE_CONNECTOR())
POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_DEVICE); POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_DEVICE);

View file

@ -65,7 +65,7 @@ bool menuRadioSpectrumAnalyser(event_t event)
moduleState[g_moduleIdx].mode = MODULE_MODE_NORMAL; moduleState[g_moduleIdx].mode = MODULE_MODE_NORMAL;
} }
/* wait 1s to resume normal operation before leaving */ /* wait 1s to resume normal operation before leaving */
watchdogSuspend(1000); watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000); RTOS_WAIT_MS(1000);
return false; return false;
} }

View file

@ -74,11 +74,11 @@ void drawFatalErrorScreen(const char * message)
void runFatalErrorScreen(const char * message) void runFatalErrorScreen(const char * message)
{ {
while (1) { while (true) {
drawFatalErrorScreen(message); drawFatalErrorScreen(message);
backlightEnable(100); backlightEnable(100);
uint8_t refresh = false; uint8_t refresh = false;
while (1) { while (true) {
uint32_t pwr_check = pwrCheck(); uint32_t pwr_check = pwrCheck();
if (pwr_check == e_power_off) { if (pwr_check == e_power_off) {
boardOff(); boardOff();

View file

@ -50,7 +50,7 @@ void menuRadioPowerMeter(event_t event)
lcdRefresh(); lcdRefresh();
moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID); moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID);
/* wait 1s to resume normal operation before leaving */ /* wait 1s to resume normal operation before leaving */
watchdogSuspend(1000); watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000); RTOS_WAIT_MS(1000);
return; return;
} }

View file

@ -44,7 +44,7 @@ void menuRadioSpectrumAnalyser(event_t event)
lcdRefresh(); lcdRefresh();
moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID); moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID);
/* wait 1s to resume normal operation before leaving */ /* wait 1s to resume normal operation before leaving */
watchdogSuspend(1000); watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(1000); RTOS_WAIT_MS(1000);
return; return;
} }

View file

@ -44,7 +44,7 @@ void readModelNotes()
menuTextView(event); menuTextView(event);
event = getEvent(); event = getEvent();
lcdRefresh(); lcdRefresh();
wdt_reset(); WDG_RESET();
} }
LED_ERROR_END(); LED_ERROR_END();

View file

@ -27,7 +27,7 @@ bool isBootloader(const char * filename)
uint8_t buffer[1024]; uint8_t buffer[1024];
UINT count; UINT count;
if (f_read(&file, buffer, 1024, &count) != FR_OK || count != 1024) { if (f_read(&file, buffer, sizeof(buffer), &count) != FR_OK || count != sizeof(buffer)) {
return false; return false;
} }
@ -47,18 +47,18 @@ void bootloaderFlash(const char * filename)
unlockFlash(); unlockFlash();
} }
for (int i=0; i<BOOTLOADER_SIZE; i+=1024) { for (int i = 0; i < BOOTLOADER_SIZE; i += 1024) {
watchdogSuspend(100/*1s*/); watchdogSuspend(1000/*10s*/);
if (f_read(&file, buffer, 1024, &count) != FR_OK || count != 1024) { if (f_read(&file, buffer, sizeof(buffer), &count) != FR_OK || count != sizeof(buffer)) {
POPUP_WARNING(STR_SDCARD_ERROR); POPUP_WARNING(STR_SDCARD_ERROR);
break; break;
} }
if (i==0 && !isBootloaderStart(buffer)) { if (i == 0 && !isBootloaderStart(buffer)) {
POPUP_WARNING(STR_INCOMPATIBLE); POPUP_WARNING(STR_INCOMPATIBLE);
break; break;
} }
for (int j=0; j<1024; j+=FLASH_PAGESIZE) { for (int j = 0; j < 1024; j += FLASH_PAGESIZE) {
flashWrite(CONVERT_UINT_PTR(FIRMWARE_ADDRESS+i+j), (uint32_t *)(buffer+j)); flashWrite(CONVERT_UINT_PTR(FIRMWARE_ADDRESS + i + j), CONVERT_UINT_PTR(buffer + j));
} }
drawProgressScreen("Bootloader", STR_WRITING, i, BOOTLOADER_SIZE); drawProgressScreen("Bootloader", STR_WRITING, i, BOOTLOADER_SIZE);
#if defined(SIMU) #if defined(SIMU)
@ -68,6 +68,8 @@ void bootloaderFlash(const char * filename)
#endif #endif
} }
watchdogSuspend(0);
if (unlocked) { if (unlocked) {
lockFlash(); lockFlash();
unlocked = 0; unlocked = 0;

View file

@ -492,7 +492,7 @@ const char * FrskyDeviceFirmwareUpdate::flashFirmware(const char * filename)
drawProgressScreen(getBasename(filename), STR_DEVICE_RESET, 0, 0); drawProgressScreen(getBasename(filename), STR_DEVICE_RESET, 0, 0);
/* wait 2s off */ /* wait 2s off */
watchdogSuspend(2000); watchdogSuspend(1000 /*10s*/);
RTOS_WAIT_MS(2000); RTOS_WAIT_MS(2000);
const char * result = doFlashFirmware(filename); const char * result = doFlashFirmware(filename);
@ -515,7 +515,7 @@ const char * FrskyDeviceFirmwareUpdate::flashFirmware(const char * filename)
SPORT_UPDATE_POWER_OFF(); SPORT_UPDATE_POWER_OFF();
/* wait 2s off */ /* wait 2s off */
watchdogSuspend(2000); watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(2000); RTOS_WAIT_MS(2000);
telemetryClearFifo(); telemetryClearFifo();
@ -756,7 +756,7 @@ const char * FrskyChipFirmwareUpdate::flashFirmware(const char * filename, bool
if (wait) { if (wait) {
/* wait 2s off */ /* wait 2s off */
watchdogSuspend(2000); watchdogSuspend(1000 /*10s*/);
RTOS_WAIT_MS(2000); RTOS_WAIT_MS(2000);
} }
@ -776,7 +776,7 @@ const char * FrskyChipFirmwareUpdate::flashFirmware(const char * filename, bool
} }
/* wait 2s off */ /* wait 2s off */
watchdogSuspend(2000); watchdogSuspend(1000 /*10s*/);
RTOS_WAIT_MS(2000); RTOS_WAIT_MS(2000);
#if defined(HARDWARE_INTERNAL_MODULE) #if defined(HARDWARE_INTERNAL_MODULE)

View file

@ -195,7 +195,7 @@ const char * MultiFirmwareUpdateDriver::waitForInitialSync(bool& inverted) const
sendByte(CRC_EOP); sendByte(CRC_EOP);
getRxByte(byte); getRxByte(byte);
wdt_reset(); WDG_RESET();
} while((byte != STK_INSYNC) && --retries); } while((byte != STK_INSYNC) && --retries);
@ -270,7 +270,7 @@ const char * MultiFirmwareUpdateDriver::progPage(uint8_t* buffer, uint16_t size)
uint8_t retries = 4; uint8_t retries = 4;
do { do {
getRxByte(byte); getRxByte(byte);
wdt_reset(); WDG_RESET();
} while(!byte && --retries); } while(!byte && --retries);
if (!retries || (byte != STK_OK)) if (!retries || (byte != STK_OK))
@ -298,7 +298,7 @@ const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* lab
init(inverted); init(inverted);
/* wait 500ms for power on */ /* wait 500ms for power on */
watchdogSuspend(500); watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(500); RTOS_WAIT_MS(500);
result = waitForInitialSync(inverted); result = waitForInitialSync(inverted);
@ -533,7 +533,7 @@ bool multiFlashFirmware(uint8_t moduleIdx, const char * filename)
drawProgressScreen(getBasename(filename), STR_DEVICE_RESET, 0, 0); drawProgressScreen(getBasename(filename), STR_DEVICE_RESET, 0, 0);
/* wait 2s off */ /* wait 2s off */
watchdogSuspend(2000); watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(2000); RTOS_WAIT_MS(2000);
const char * result = driver->flashFirmware(&file, getBasename(filename)); const char * result = driver->flashFirmware(&file, getBasename(filename));
@ -557,7 +557,7 @@ bool multiFlashFirmware(uint8_t moduleIdx, const char * filename)
SPORT_UPDATE_POWER_OFF(); SPORT_UPDATE_POWER_OFF();
/* wait 2s off */ /* wait 2s off */
watchdogSuspend(2000); watchdogSuspend(500 /*5s*/);
RTOS_WAIT_MS(2000); RTOS_WAIT_MS(2000);
// reset telemetry protocol // reset telemetry protocol

View file

@ -189,7 +189,7 @@ bool waitKeysReleased()
#endif #endif
while (keyDown()) { while (keyDown()) {
wdt_reset(); WDG_RESET();
#if !defined(BOOT) #if !defined(BOOT)
if ((get_tmr10ms() - start) >= 300) { // wait no more than 3 seconds if ((get_tmr10ms() - start) >= 300) { // wait no more than 3 seconds

View file

@ -167,8 +167,8 @@ void checkEeprom()
#else #else
void checkEeprom() void checkEeprom()
{ {
#if defined(RAMBACKUP) && !defined(SIMU) #if defined(RTC_BACKUP_RAM) && !defined(SIMU)
if (TIME_TO_RAMBACKUP()) { if (TIME_TO_BACKUP_RAM()) {
rambackupWrite(); rambackupWrite();
rambackupDirtyMsk = 0; rambackupDirtyMsk = 0;
} }
@ -504,7 +504,7 @@ void perMain()
event_t evt = getEvent(false); event_t evt = getEvent(false);
#if defined(RAMBACKUP) #if defined(RTC_BACKUP_RAM)
if (globalData.unexpectedShutdown) { if (globalData.unexpectedShutdown) {
drawFatalErrorScreen(STR_EMERGENCY_MODE); drawFatalErrorScreen(STR_EMERGENCY_MODE);
return; return;

View file

@ -109,7 +109,7 @@ void per10ms()
if (watchdogTimeout) { if (watchdogTimeout) {
watchdogTimeout -= 1; watchdogTimeout -= 1;
wdt_reset(); // Retrigger hardware watchdog WDG_RESET(); // Retrigger hardware watchdog
} }
#if defined(GUI) #if defined(GUI)
@ -932,7 +932,7 @@ void checkAll()
tmr10ms_t tgtime = get_tmr10ms() + 500; tmr10ms_t tgtime = get_tmr10ms() + 500;
while (tgtime != get_tmr10ms()) { while (tgtime != get_tmr10ms()) {
RTOS_WAIT_MS(1); RTOS_WAIT_MS(1);
wdt_reset(); WDG_RESET();
} }
} }
@ -999,6 +999,8 @@ void checkThrottleStick()
#if defined(PWR_BUTTON_PRESS) #if defined(PWR_BUTTON_PRESS)
uint32_t power = pwrCheck(); uint32_t power = pwrCheck();
if (power == e_power_off) { if (power == e_power_off) {
drawSleepBitmap();
boardOff();
break; break;
} }
else if (power == e_power_press) { else if (power == e_power_press) {
@ -1016,7 +1018,7 @@ void checkThrottleStick()
doLoopCommonActions(); doLoopCommonActions();
wdt_reset(); WDG_RESET();
RTOS_WAIT_MS(10); RTOS_WAIT_MS(10);
} }
@ -1047,7 +1049,7 @@ void alert(const char * title, const char * msg , uint8_t sound)
bool refresh = false; bool refresh = false;
#endif #endif
while (1) { while (true) {
RTOS_WAIT_MS(10); RTOS_WAIT_MS(10);
if (keyDown()) // wait for key release if (keyDown()) // wait for key release
@ -1055,7 +1057,7 @@ void alert(const char * title, const char * msg , uint8_t sound)
doLoopCommonActions(); doLoopCommonActions();
wdt_reset(); WDG_RESET();
const uint32_t pwr_check = pwrCheck(); const uint32_t pwr_check = pwrCheck();
if (pwr_check == e_power_off) { if (pwr_check == e_power_off) {
@ -1858,6 +1860,10 @@ void opentxInit()
globalData.unexpectedShutdown = 1; globalData.unexpectedShutdown = 1;
} }
#if defined(RTC_BACKUP_RAM)
SET_POWER_REASON(0);
#endif
#if defined(SDCARD) #if defined(SDCARD)
// SDCARD related stuff, only done if not unexpectedShutdown // SDCARD related stuff, only done if not unexpectedShutdown
if (!globalData.unexpectedShutdown) { if (!globalData.unexpectedShutdown) {
@ -1909,7 +1915,7 @@ void opentxInit()
// handling of storage for radios that have no EEPROM // handling of storage for radios that have no EEPROM
#if !defined(EEPROM) #if !defined(EEPROM)
#if defined(RAMBACKUP) && !defined(SIMU) #if defined(RTC_BACKUP_RAM) && !defined(SIMU)
if (globalData.unexpectedShutdown) { if (globalData.unexpectedShutdown) {
// SDCARD not available, try to restore last model from RAM // SDCARD not available, try to restore last model from RAM
TRACE("rambackupRestore"); TRACE("rambackupRestore");
@ -1966,20 +1972,22 @@ void opentxInit()
opentxStart(); opentxStart();
} }
// TODO Horus does not need this #if !defined(RTC_BACKUP_RAM)
if (!g_eeGeneral.unexpectedShutdown) { if (!g_eeGeneral.unexpectedShutdown) {
g_eeGeneral.unexpectedShutdown = 1; g_eeGeneral.unexpectedShutdown = 1;
storageDirty(EE_GENERAL); storageDirty(EE_GENERAL);
} }
#endif
#if defined(GUI) #if defined(GUI)
lcdSetContrast(); lcdSetContrast();
#endif #endif
backlightOn(); backlightOn();
startPulses(); startPulses();
wdt_enable(WDTO_500MS); WDG_ENABLE(WDG_DURATION);
} }
#if defined(SIMU) #if defined(SIMU)
@ -2001,7 +2009,7 @@ int main()
// G: The WDT remains active after a WDT reset -- at maximum clock speed. So it's // G: The WDT remains active after a WDT reset -- at maximum clock speed. So it's
// important to disable it before commencing with system initialisation (or // important to disable it before commencing with system initialisation (or
// we could put a bunch more wdt_reset()s in. But I don't like that approach // we could put a bunch more WDG_RESET()s in. But I don't like that approach
// during boot up.) // during boot up.)
#if defined(PCBTARANIS) #if defined(PCBTARANIS)
g_eeGeneral.contrast = LCD_CONTRAST_DEFAULT; g_eeGeneral.contrast = LCD_CONTRAST_DEFAULT;
@ -2018,7 +2026,9 @@ int main()
#endif #endif
#if defined(SPLASH) && !defined(STARTUP_ANIMATION) #if defined(SPLASH) && !defined(STARTUP_ANIMATION)
if (!UNEXPECTED_SHUTDOWN()) {
drawSplash(); drawSplash();
}
#endif #endif
#if defined(PCBHORUS) #if defined(PCBHORUS)

View file

@ -443,7 +443,7 @@ bool Pxx2OtaUpdate::waitStep(uint8_t step, uint8_t timeout)
OtaUpdateInformation * destination = moduleState[module].otaUpdateInformation; OtaUpdateInformation * destination = moduleState[module].otaUpdateInformation;
uint8_t elapsed = 0; uint8_t elapsed = 0;
watchdogSuspend(100); watchdogSuspend(100 /*1s*/);
while (step != destination->step) { while (step != destination->step) {
if (elapsed++ > timeout) { if (elapsed++ > timeout) {
@ -532,7 +532,7 @@ void Pxx2OtaUpdate::flashFirmware(const char * filename)
{ {
pausePulses(); pausePulses();
watchdogSuspend(100); watchdogSuspend(100 /*1s*/);
RTOS_WAIT_MS(100); RTOS_WAIT_MS(100);
moduleState[module].mode = MODULE_MODE_OTA_UPDATE; moduleState[module].mode = MODULE_MODE_OTA_UPDATE;

View file

@ -729,7 +729,7 @@ void RlcFile::nextRlcWriteStep()
void RlcFile::flush() void RlcFile::flush()
{ {
while (!eepromIsTransferComplete()) while (!eepromIsTransferComplete())
wdt_reset(); WDG_RESET();
ENABLE_SYNC_WRITE(true); ENABLE_SYNC_WRITE(true);

View file

@ -0,0 +1,33 @@
/*
* 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 _RAM_BACKUP_H_
#define _RAM_BACKUP_H_
#include "definitions.h"
PACK(struct RamBackup {
uint16_t size;
uint8_t data[4094];
});
extern RamBackup * ramBackup;
#endif // _RAM_BACKUP_H_

View file

@ -38,11 +38,4 @@ const char * createModel();
const char * loadRadioSettings(const char * path); const char * loadRadioSettings(const char * path);
const char * loadRadioSettings(); const char * loadRadioSettings();
PACK(struct RamBackup {
uint16_t size;
uint8_t data[4094];
});
extern RamBackup * ramBackup;
#endif // _SDCARD_RAW_H_ #endif // _SDCARD_RAW_H_

View file

@ -23,7 +23,7 @@
#if defined(SIMU) #if defined(SIMU)
#define WRITE_DELAY_10MS 100 #define WRITE_DELAY_10MS 100
#elif defined(RAMBACKUP) #elif defined(RTC_BACKUP_RAM)
#define WRITE_DELAY_10MS 1500 /* 15s */ #define WRITE_DELAY_10MS 1500 /* 15s */
#elif defined(PCBTARANIS) #elif defined(PCBTARANIS)
#define WRITE_DELAY_10MS 500 #define WRITE_DELAY_10MS 500
@ -37,10 +37,11 @@ extern uint8_t storageDirtyMsk;
extern tmr10ms_t storageDirtyTime10ms; extern tmr10ms_t storageDirtyTime10ms;
#define TIME_TO_WRITE() (storageDirtyMsk && (tmr10ms_t)(get_tmr10ms() - storageDirtyTime10ms) >= (tmr10ms_t)WRITE_DELAY_10MS) #define TIME_TO_WRITE() (storageDirtyMsk && (tmr10ms_t)(get_tmr10ms() - storageDirtyTime10ms) >= (tmr10ms_t)WRITE_DELAY_10MS)
#if defined(RAMBACKUP) #if defined(RTC_BACKUP_RAM)
#include "storage/rtc_backup.h"
extern uint8_t rambackupDirtyMsk; extern uint8_t rambackupDirtyMsk;
extern tmr10ms_t rambackupDirtyTime10ms; extern tmr10ms_t rambackupDirtyTime10ms;
#define TIME_TO_RAMBACKUP() (rambackupDirtyMsk && (tmr10ms_t)(get_tmr10ms() - rambackupDirtyTime10ms) >= (tmr10ms_t)100) #define TIME_TO_BACKUP_RAM() (rambackupDirtyMsk && (tmr10ms_t)(get_tmr10ms() - rambackupDirtyTime10ms) >= (tmr10ms_t)100)
#endif #endif
void storageEraseAll(bool warn); void storageEraseAll(bool warn);
@ -64,7 +65,7 @@ void checkExternalAntenna();
#include "sdcard_raw.h" #include "sdcard_raw.h"
#endif #endif
#if defined(RAMBACKUP) #if defined(RTC_BACKUP_RAM)
void rambackupWrite(); void rambackupWrite();
bool rambackupRestore(); bool rambackupRestore();
unsigned int compress(uint8_t * dst, unsigned int dstsize, const uint8_t * src, unsigned int len); unsigned int compress(uint8_t * dst, unsigned int dstsize, const uint8_t * src, unsigned int len);

View file

@ -24,7 +24,7 @@
uint8_t storageDirtyMsk; uint8_t storageDirtyMsk;
tmr10ms_t storageDirtyTime10ms; tmr10ms_t storageDirtyTime10ms;
#if defined(RAMBACKUP) #if defined(RTC_BACKUP_RAM)
uint8_t rambackupDirtyMsk; uint8_t rambackupDirtyMsk;
tmr10ms_t rambackupDirtyTime10ms; tmr10ms_t rambackupDirtyTime10ms;
#endif #endif
@ -34,7 +34,7 @@ void storageDirty(uint8_t msk)
storageDirtyMsk |= msk; storageDirtyMsk |= msk;
storageDirtyTime10ms = get_tmr10ms(); storageDirtyTime10ms = get_tmr10ms();
#if defined(RAMBACKUP) #if defined(RTC_BACKUP_RAM)
rambackupDirtyMsk = storageDirtyMsk; rambackupDirtyMsk = storageDirtyMsk;
rambackupDirtyTime10ms = storageDirtyTime10ms; rambackupDirtyTime10ms = storageDirtyTime10ms;
#endif #endif

View file

@ -561,8 +561,7 @@ void checkSwitches()
bool refresh = false; bool refresh = false;
#endif #endif
while (1) { while (true) {
#if defined(PCBTARANIS) || defined(PCBHORUS) #if defined(PCBTARANIS) || defined(PCBHORUS)
#define GETADC_COUNT 1 #define GETADC_COUNT 1
#endif #endif
@ -749,6 +748,8 @@ void checkSwitches()
#if defined(PWR_BUTTON_PRESS) #if defined(PWR_BUTTON_PRESS)
uint32_t power = pwrCheck(); uint32_t power = pwrCheck();
if (power == e_power_off) { if (power == e_power_off) {
drawSleepBitmap();
boardOff();
break; break;
} }
else if (power == e_power_press) { else if (power == e_power_press) {
@ -767,7 +768,7 @@ void checkSwitches()
doLoopCommonActions(); doLoopCommonActions();
wdt_reset(); WDG_RESET();
RTOS_WAIT_MS(10); RTOS_WAIT_MS(10);
} }

View file

@ -8,6 +8,8 @@ if(CPU_TYPE_FULL STREQUAL STM32F429xI)
../f4/system_stm32f4xx.c ../f4/system_stm32f4xx.c
../../../../../targets/${TARGET_DIR}/startup_stm32f42_43xxx.s ../../../../../targets/${TARGET_DIR}/startup_stm32f42_43xxx.s
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rcc.c ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rcc.c
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rtc.c
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_pwr.c
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_syscfg.c ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_syscfg.c
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_gpio.c ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_gpio.c
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_exti.c ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_exti.c
@ -25,6 +27,8 @@ elseif(CPU_TYPE_FULL STREQUAL STM32F407xE)
../f4/system_stm32f4xx.c ../f4/system_stm32f4xx.c
../../../../../targets/${TARGET_DIR}/startup_stm32f40_41xxx.s ../../../../../targets/${TARGET_DIR}/startup_stm32f40_41xxx.s
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rcc.c ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rcc.c
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rtc.c
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_pwr.c
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_syscfg.c ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_syscfg.c
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_gpio.c ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_gpio.c
../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_exti.c ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_exti.c
@ -99,20 +103,16 @@ if(PCB STREQUAL X7 OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES)
) )
endif() endif()
if(NOT (PCB STREQUAL X10 OR PCB STREQUAL X12S)) if(PCB STREQUAL X10 OR PCB STREQUAL X12S)
set(BOOTLOADER_SRC
${BOOTLOADER_SRC}
../../../../../targets/${TARGET_DIR}/i2c_driver.cpp
)
remove_definitions(-DDEBUG)
else()
set(BOOTLOADER_SRC set(BOOTLOADER_SRC
${BOOTLOADER_SRC} ${BOOTLOADER_SRC}
../../../../../targets/${TARGET_DIR}/sdram_driver.c ../../../../../targets/${TARGET_DIR}/sdram_driver.c
../../../../../targets/common/arm/stm32/sdio_sd.c ../../../../../targets/common/arm/stm32/sdio_sd.c
../../../../../targets/common/arm/stm32/rtc_driver.cpp
../../../../../targets/${TARGET_DIR}/haptic_driver.cpp ../../../../../targets/${TARGET_DIR}/haptic_driver.cpp
../../../../../gui/${GUI_DIR}/bitmapbuffer.cpp ../../../../../gui/${GUI_DIR}/bitmapbuffer.cpp
../../../../../gui/${GUI_DIR}/rle.cpp ../../../../../gui/${GUI_DIR}/rle.cpp
../../../../../syscalls.c ../../../../../syscalls.c
) )
@ -123,12 +123,20 @@ else()
../../../../../serial.cpp ../../../../../serial.cpp
) )
endif() endif()
else()
set(BOOTLOADER_SRC
${BOOTLOADER_SRC}
../../../../../targets/${TARGET_DIR}/i2c_driver.cpp
)
remove_definitions(-DDEBUG)
endif() endif()
remove_definitions(-DDISK_CACHE) remove_definitions(-DDISK_CACHE)
remove_definitions(-DLUA) remove_definitions(-DLUA)
remove_definitions(-DCLI) remove_definitions(-DCLI)
remove_definitions(-DUSB_SERIAL) remove_definitions(-DUSB_SERIAL)
remove_definitions(-DWATCHDOG)
add_definitions(-DBOOT) add_definitions(-DBOOT)
set(CMAKE_EXE_LINKER_FLAGS "-mcpu=${MCU} -mthumb -nostartfiles -lm -T${RADIO_SRC_DIRECTORY}/targets/${TARGET_DIR}/stm32_ramboot.ld -Wl,-Map=bootloader.map,--cref,--no-warn-mismatch,--gc-sections") set(CMAKE_EXE_LINKER_FLAGS "-mcpu=${MCU} -mthumb -nostartfiles -lm -T${RADIO_SRC_DIRECTORY}/targets/${TARGET_DIR}/stm32_ramboot.ld -Wl,-Map=bootloader.map,--cref,--no-warn-mismatch,--gc-sections")

View file

@ -195,7 +195,7 @@ int main()
FRESULT fr; FRESULT fr;
uint32_t nameCount = 0; uint32_t nameCount = 0;
wdt_reset(); WDG_RESET();
RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | KEYS_RCC_AHB1Periph | RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph | KEYS_RCC_AHB1Periph |
LCD_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph | LCD_RCC_AHB1Periph | BACKLIGHT_RCC_AHB1Periph |
@ -215,7 +215,7 @@ int main()
#if defined(PCBHORUS) #if defined(PCBHORUS)
// wait a bit for the inputs to stabilize... // wait a bit for the inputs to stabilize...
for (uint32_t i = 0; i < 50000; i++) { for (uint32_t i = 0; i < 50000; i++) {
wdt_reset(); WDG_RESET();
} }
#endif #endif
@ -265,12 +265,12 @@ int main()
#if defined(PWR_BUTTON_PRESS) #if defined(PWR_BUTTON_PRESS)
// wait until power button is released // wait until power button is released
while (pwrPressed()) { while (pwrPressed()) {
wdt_reset(); WDG_RESET();
} }
#endif #endif
for (;;) { for (;;) {
wdt_reset(); WDG_RESET();
if (tenms) { if (tenms) {
tenms = 0; tenms = 0;
@ -506,16 +506,12 @@ int main()
lcdRefresh(); lcdRefresh();
lcdRefreshWait(); lcdRefreshWait();
#if !defined(EEPROM) #if defined(RTC_BACKUP_RAM)
// Use jump on radios with emergency mode rtcInit();
// to avoid triggering it with a soft reset RTC->BKP0R = SOFTRESET_REQUEST;
// Jump to proper application address
jumpTo(APP_START_ADDRESS);
#else
// Use software reset everywhere else
NVIC_SystemReset();
#endif #endif
NVIC_SystemReset();
} }
} }
@ -523,5 +519,5 @@ int main()
} }
#if defined(PCBHORUS) #if defined(PCBHORUS)
void *__dso_handle = 0; void *__dso_handle = nullptr;
#endif #endif

View file

@ -20,6 +20,13 @@
#include "opentx.h" #include "opentx.h"
void waitFlashIdle()
{
do {
WDG_RESET();
} while (FLASH->SR & FLASH_FLAG_BSY);
}
//After reset, write is not allowed in the Flash control register (FLASH_CR) to protect the //After reset, write is not allowed in the Flash control register (FLASH_CR) to protect the
//Flash memory against possible unwanted operations due, for example, to electric //Flash memory against possible unwanted operations due, for example, to electric
//disturbances. The following sequence is used to unlock this register: //disturbances. The following sequence is used to unlock this register:
@ -37,21 +44,16 @@ void unlockFlash()
void lockFlash() void lockFlash()
{ {
while (FLASH->SR & FLASH_SR_BSY); waitFlashIdle();
FLASH->CR |= FLASH_CR_LOCK; FLASH->CR |= FLASH_CR_LOCK;
} }
void waitFlashIdle()
{
while (FLASH->SR & FLASH_FLAG_BSY) {
wdt_reset();
}
}
#define SECTOR_MASK ((uint32_t)0xFFFFFF07) #define SECTOR_MASK ((uint32_t)0xFFFFFF07)
void eraseSector(uint32_t sector) void eraseSector(uint32_t sector)
{ {
WDG_ENABLE(3000); // some sectors may take > 1s to erase
waitFlashIdle(); waitFlashIdle();
FLASH->CR &= CR_PSIZE_MASK; FLASH->CR &= CR_PSIZE_MASK;
@ -66,9 +68,11 @@ void eraseSector(uint32_t sector)
/* if the erase operation is completed, disable the SER Bit */ /* if the erase operation is completed, disable the SER Bit */
FLASH->CR &= (~FLASH_CR_SER); FLASH->CR &= (~FLASH_CR_SER);
FLASH->CR &= SECTOR_MASK; FLASH->CR &= SECTOR_MASK;
WDG_ENABLE(WDG_DURATION);
} }
void flashWrite(uint32_t * address, uint32_t * buffer) // page size is 256 bytes void flashWrite(uint32_t * address, const uint32_t * buffer) // page size is 256 bytes
{ {
#define SECTOR_ADDRESS (((uint32_t)address) & 0xFFFFF) #define SECTOR_ADDRESS (((uint32_t)address) & 0xFFFFF)
@ -110,7 +114,6 @@ void flashWrite(uint32_t * address, uint32_t * buffer) // page size is 256 bytes
eraseSector(4 + FLASH_BANK); eraseSector(4 + FLASH_BANK);
} }
else if ((((uint32_t)address) & 0x3FFF) == 0) { else if ((((uint32_t)address) & 0x3FFF) == 0) {
// test other 16KB sectors // test other 16KB sectors
if (SECTOR_ADDRESS == 0x04000) { if (SECTOR_ADDRESS == 0x04000) {
eraseSector(1 + FLASH_BANK); eraseSector(1 + FLASH_BANK);
@ -141,7 +144,7 @@ void flashWrite(uint32_t * address, uint32_t * buffer) // page size is 256 bytes
/* Wait for operation to be completed */ /* Wait for operation to be completed */
waitFlashIdle(); waitFlashIdle();
FLASH->CR &= (~FLASH_CR_PG); FLASH->CR &= ~FLASH_CR_PG;
/* Check the written value */ /* Check the written value */
if (*address != *buffer) { if (*address != *buffer) {
@ -192,7 +195,7 @@ uint32_t isBootloaderStart(const uint8_t * buffer)
{ {
const uint32_t * block = (const uint32_t *)buffer; const uint32_t * block = (const uint32_t *)buffer;
for (int i=0; i<256; i++) { for (int i = 0; i < 256; i++) {
if (block[i] == 0x544F4F42/*BOOT*/) { if (block[i] == 0x544F4F42/*BOOT*/) {
return 1; return 1;
} }

View file

@ -59,17 +59,14 @@ void rtcGetTime(struct gtm * t)
void rtcInit() void rtcInit()
{ {
RTC_InitTypeDef RTC_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_BackupAccessCmd(ENABLE); PWR_BackupAccessCmd(ENABLE);
RCC_LSEConfig(RCC_LSE_ON); RCC_LSEConfig(RCC_LSE_ON);
// Prevent lockup in case of 32kHz oscillator failure // Prevent lockup in case of 32kHz oscillator failure
uint32_t i = 0; uint32_t i = 0;
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {
{ if (++i > 1000000)
if ( ++i > 1000000 )
return; return;
} }
@ -77,6 +74,9 @@ void rtcInit()
RCC_RTCCLKCmd(ENABLE); RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro(); RTC_WaitForSynchro();
#if !defined(BOOT)
RTC_InitTypeDef RTC_InitStruct;
// RTC time base = LSE / ((AsynchPrediv+1) * (SynchPrediv+1)) = 1 Hz*/ // RTC time base = LSE / ((AsynchPrediv+1) * (SynchPrediv+1)) = 1 Hz*/
RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24; RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
RTC_InitStruct.RTC_AsynchPrediv = 127; RTC_InitStruct.RTC_AsynchPrediv = 127;
@ -86,8 +86,9 @@ void rtcInit()
struct gtm utm; struct gtm utm;
rtcGetTime(&utm); rtcGetTime(&utm);
g_rtcTime = gmktime(&utm); g_rtcTime = gmktime(&utm);
#endif
#if defined(RAMBACKUP) #if defined(RTC_BACKUP_RAM) && !defined(BOOT)
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE);
PWR_BackupRegulatorCmd(ENABLE); PWR_BackupRegulatorCmd(ENABLE);
#endif #endif

View file

@ -14,7 +14,7 @@ set(GUI_DIR 480x272)
set(NAVIGATION_TYPE horus) set(NAVIGATION_TYPE horus)
set(TARGET_DIR horus) set(TARGET_DIR horus)
set(LINKER_SCRIPT targets/horus/stm32f4_flash.ld) set(LINKER_SCRIPT targets/horus/stm32f4_flash.ld)
set(RAMBACKUP YES) set(RTC_BACKUP_RAM YES)
set(LUA YES) set(LUA YES)
set(PPM_LIMITS_SYMETRICAL YES) set(PPM_LIMITS_SYMETRICAL YES)
set(USB_SERIAL ON CACHE BOOL "Enable USB serial (CDC)") set(USB_SERIAL ON CACHE BOOL "Enable USB serial (CDC)")

View file

@ -29,10 +29,6 @@ extern "C" {
} }
#endif #endif
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
HardwareOptions hardwareOptions; HardwareOptions hardwareOptions;
void watchdogInit(unsigned int duration) void watchdogInit(unsigned int duration)
@ -40,7 +36,7 @@ void watchdogInit(unsigned int duration)
IWDG->KR = 0x5555; // Unlock registers IWDG->KR = 0x5555; // Unlock registers
IWDG->PR = 3; // Divide by 32 => 1kHz clock IWDG->PR = 3; // Divide by 32 => 1kHz clock
IWDG->KR = 0x5555; // Unlock registers IWDG->KR = 0x5555; // Unlock registers
IWDG->RLR = duration; // 1.5 seconds nominal IWDG->RLR = duration;
IWDG->KR = 0xAAAA; // reload IWDG->KR = 0xAAAA; // reload
IWDG->KR = 0xCCCC; // start IWDG->KR = 0xCCCC; // start
} }
@ -173,6 +169,7 @@ void boardInit()
#endif #endif
ledInit(); ledInit();
#if defined(PCBX10) && !defined(RADIO_T16) #if defined(PCBX10) && !defined(RADIO_T16)
sportUpdateInit(); sportUpdateInit();
#endif #endif
@ -189,7 +186,7 @@ void boardOff()
backlightEnable(0); backlightEnable(0);
while (pwrPressed()) { while (pwrPressed()) {
wdt_reset(); WDG_RESET();
} }
SysTick->CTRL = 0; // turn off systick SysTick->CTRL = 0; // turn off systick
@ -209,8 +206,12 @@ void boardOff()
// Shutdown the Haptic // Shutdown the Haptic
hapticDone(); hapticDone();
shutdownRequest = SHUTDOWN_REQUEST; #if defined(RTC_BACKUP_RAM)
shutdownReason = NORMAL_POWER_OFF; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, DISABLE);
PWR_BackupRegulatorCmd(DISABLE);
#endif
RTC->BKP0R = SHUTDOWN_REQUEST;
pwrOff(); pwrOff();
} }

View file

@ -136,7 +136,7 @@ DRESULT __disk_write(BYTE drv, const BYTE * buff, DWORD sector, UINT count);
#define FLASH_PAGESIZE 256 #define FLASH_PAGESIZE 256
void unlockFlash(); void unlockFlash();
void lockFlash(); void lockFlash();
void flashWrite(uint32_t * address, uint32_t * buffer); void flashWrite(uint32_t * address, const 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);
@ -305,28 +305,22 @@ void rotaryEncoderInit();
void rotaryEncoderCheck(); void rotaryEncoderCheck();
// WDT driver // WDT driver
#define WDTO_500MS 500 #define WDG_DURATION 500 /*ms*/
extern uint32_t powerupReason;
#define SHUTDOWN_REQUEST 0xDEADBEEF
#define NO_SHUTDOWN_REQUEST ~SHUTDOWN_REQUEST
#define DIRTY_SHUTDOWN 0xCAFEDEAD
#define NORMAL_POWER_OFF ~DIRTY_SHUTDOWN
void watchdogInit(unsigned int duration); void watchdogInit(unsigned int duration);
#if defined(SIMU) #if defined(SIMU)
#define WAS_RESET_BY_WATCHDOG() (false) #define WAS_RESET_BY_WATCHDOG() (false)
#define WAS_RESET_BY_SOFTWARE() (false) #define WAS_RESET_BY_SOFTWARE() (false)
#define WAS_RESET_BY_WATCHDOG_OR_SOFTWARE() (false) #define WAS_RESET_BY_WATCHDOG_OR_SOFTWARE() (false)
#define wdt_enable(x) #define WDG_ENABLE(x)
#define wdt_reset() #define WDG_RESET()
#else #else
#if defined(WATCHDOG) #if defined(WATCHDOG)
#define wdt_enable(x) watchdogInit(x) #define WDG_ENABLE(x) watchdogInit(x)
#define wdt_reset() IWDG->KR = 0xAAAA #define WDG_RESET() IWDG->KR = 0xAAAA
#else #else
#define wdt_enable(x) #define WDG_ENABLE(x)
#define wdt_reset() #define WDG_RESET()
#endif #endif
#define WAS_RESET_BY_WATCHDOG() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF)) #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)
@ -453,14 +447,41 @@ extern volatile uint32_t pwm_interrupt_count;
#define BATTERY_MAX 115 // 11.5V #define BATTERY_MAX 115 // 11.5V
#endif #endif
#if defined(__cplusplus)
enum PowerReason {
SHUTDOWN_REQUEST = 0xDEADBEEF,
SOFTRESET_REQUEST = 0xCAFEDEAD,
};
constexpr uint32_t POWER_REASON_SIGNATURE = 0x0178746F;
inline bool UNEXPECTED_SHUTDOWN()
{
#if defined(SIMU) || defined(NO_UNEXPECTED_SHUTDOWN)
return false;
#else
if (WAS_RESET_BY_WATCHDOG())
return true;
else if (WAS_RESET_BY_SOFTWARE())
return RTC->BKP0R != SOFTRESET_REQUEST;
else
return RTC->BKP1R == POWER_REASON_SIGNATURE && RTC->BKP0R != SHUTDOWN_REQUEST;
#endif
}
inline void SET_POWER_REASON(uint32_t value)
{
RTC->BKP0R = value;
RTC->BKP1R = POWER_REASON_SIGNATURE;
}
#endif
#if defined(__cplusplus) && !defined(SIMU) #if defined(__cplusplus) && !defined(SIMU)
extern "C" { extern "C" {
#endif #endif
// Power driver // Power driver
#define SOFT_PWR_CTRL #define SOFT_PWR_CTRL
extern uint32_t shutdownRequest; // Stores intentional shutdown to avoid reboot loop
extern uint32_t shutdownReason; // Used for detecting unexpected reboots regardless of reason
void pwrInit(); void pwrInit();
uint32_t pwrCheck(); uint32_t pwrCheck();
void pwrOn(); void pwrOn();
@ -468,11 +489,6 @@ void pwrOff();
void pwrResetHandler(); void pwrResetHandler();
bool pwrPressed(); bool pwrPressed();
uint32_t pwrPressedDuration(); uint32_t pwrPressedDuration();
#if defined(SIMU) || defined(NO_UNEXPECTED_SHUTDOWN)
#define UNEXPECTED_SHUTDOWN() (false)
#else
#define UNEXPECTED_SHUTDOWN() ((powerupReason == DIRTY_SHUTDOWN) || WAS_RESET_BY_WATCHDOG_OR_SOFTWARE())
#endif
// Led driver // Led driver
void ledInit(); void ledInit();

View file

@ -2,8 +2,6 @@
#include "../../common/arm/stm32/bootloader/boot.h" #include "../../common/arm/stm32/bootloader/boot.h"
#include "../../common/arm/stm32/bootloader/bin_files.h" #include "../../common/arm/stm32/bootloader/bin_files.h"
#define SELECTED_COLOR (INVERS | TEXT_COLOR)
const uint8_t __bmp_plug_usb_rle[] { const uint8_t __bmp_plug_usb_rle[] {
#include "bmp_plug_usb.lbm" #include "bmp_plug_usb.lbm"
}; };
@ -48,7 +46,7 @@ void bootloaderInitScreen()
backlightEnable(BACKLIGHT_LEVEL_MAX); backlightEnable(BACKLIGHT_LEVEL_MAX);
//TODO: load/decompress bitmaps // TODO: load/decompress bitmaps
loadFonts(); loadFonts();
} }

View file

@ -19,6 +19,7 @@
*/ */
#include "board.h" #include "board.h"
#include "storage/rtc_backup.h"
void pwrInit() void pwrInit()
{ {
@ -81,9 +82,6 @@ void pwrOn()
GPIO_Init(PWR_ON_GPIO, &GPIO_InitStructure); GPIO_Init(PWR_ON_GPIO, &GPIO_InitStructure);
GPIO_SetBits(PWR_ON_GPIO, PWR_ON_GPIO_PIN); GPIO_SetBits(PWR_ON_GPIO, PWR_ON_GPIO_PIN);
shutdownRequest = NO_SHUTDOWN_REQUEST;
shutdownReason = DIRTY_SHUTDOWN;
} }
void pwrOff() void pwrOff()
@ -105,38 +103,7 @@ void pwrResetHandler()
__ASM volatile ("nop"); __ASM volatile ("nop");
__ASM volatile ("nop"); __ASM volatile ("nop");
// 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.
//
// 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.
// Only for X12, X10 power circuit causes inability to shut down on some samples.
#if defined(PCBX12S)
if (shutdownRequest != SHUTDOWN_REQUEST || WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) {
if (shutdownReason == DIRTY_SHUTDOWN) {
powerupReason = DIRTY_SHUTDOWN;
}
pwrOn();
}
#else
if (WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) { if (WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) {
pwrOn(); pwrOn();
} }
#endif
} }

View file

@ -51,6 +51,7 @@ DMA_TypeDef dma2;
USART_TypeDef Usart0, Usart1, Usart2, Usart3, Usart4; USART_TypeDef Usart0, Usart1, Usart2, Usart3, Usart4;
SysTick_Type systick; SysTick_Type systick;
ADC_Common_TypeDef adc; ADC_Common_TypeDef adc;
RTC_TypeDef rtc;
#else #else
Pio Pioa, Piob, Pioc; Pio Pioa, Piob, Pioc;
Pmc pmc; Pmc pmc;
@ -672,7 +673,7 @@ void lockFlash()
{ {
} }
void flashWrite(uint32_t *address, uint32_t *buffer) void flashWrite(uint32_t *address, const uint32_t *buffer)
{ {
simuSleep(100); simuSleep(100);
} }

View file

@ -86,6 +86,7 @@ extern DMA_Stream_TypeDef dma1_stream0, dma1_stream1, dma1_stream2, dma1_stream3
extern DMA_TypeDef dma2; extern DMA_TypeDef dma2;
extern SysTick_Type systick; extern SysTick_Type systick;
extern ADC_Common_TypeDef adc; extern ADC_Common_TypeDef adc;
extern RTC_TypeDef rtc;
#undef SysTick #undef SysTick
#define SysTick (&systick) #define SysTick (&systick)
#undef GPIOA #undef GPIOA
@ -166,6 +167,8 @@ extern ADC_Common_TypeDef adc;
#define DMA2 (&dma2) #define DMA2 (&dma2)
#undef ADC #undef ADC
#define ADC (&adc) #define ADC (&adc)
#undef RTC
#define RTC (&rtc)
#elif defined(PCBSKY9X) #elif defined(PCBSKY9X)
extern Pmc pmc; extern Pmc pmc;
#undef PMC #undef PMC

View file

@ -218,7 +218,7 @@ void stop_trainer_capture();
// Write Flash driver // Write Flash driver
#define FLASH_PAGESIZE 256 #define FLASH_PAGESIZE 256
void flashWrite(uint32_t * address, uint32_t * buffer); void flashWrite(uint32_t * address, const uint32_t * buffer);
// Keys driver // Keys driver
uint32_t switchState(uint8_t index); uint32_t switchState(uint8_t index);
@ -259,12 +259,12 @@ extern "C" {
// WDT driver // WDT driver
#if !defined(WATCHDOG) || defined(SIMU) #if !defined(WATCHDOG) || defined(SIMU)
#define wdt_enable(x) #define WDG_ENABLE(x)
#define wdt_reset() #define WDG_RESET()
#define IS_RESET_REASON_WATCHDOG() false #define IS_RESET_REASON_WATCHDOG() false
#else #else
#define wdt_enable(x) WDT->WDT_MR = 0x3FFF207F #define WDG_ENABLE(x) WDT->WDT_MR = 0x3FFF207F
#define wdt_reset() WDT->WDT_CR = 0xA5000001 #define WDG_RESET() WDT->WDT_CR = 0xA5000001
#define IS_RESET_REASON_WATCHDOG() ((ResetReason & RSTC_SR_RSTTYP) == (2 << 8)) #define IS_RESET_REASON_WATCHDOG() ((ResetReason & RSTC_SR_RSTTYP) == (2 << 8))
#endif #endif

View file

@ -22,7 +22,7 @@
uint32_t (*IAP_Function)(uint32_t, uint32_t); uint32_t (*IAP_Function)(uint32_t, uint32_t);
void flashWrite(uint32_t *address, uint32_t *buffer) // size is 256 bytes void flashWrite(uint32_t * address, const uint32_t * buffer) // size is 256 bytes
{ {
uint32_t FlashSectorNum; uint32_t FlashSectorNum;
uint32_t flash_cmd = 0; uint32_t flash_cmd = 0;

View file

@ -120,7 +120,7 @@ void lcdInit()
TC0->TC_CHANNEL[0].TC_CCR = 5; // Enable clock and trigger it (may only need trigger) TC0->TC_CHANNEL[0].TC_CCR = 5; // Enable clock and trigger it (may only need trigger)
while ( TC0->TC_CHANNEL[0].TC_CV < 36000 ) { while ( TC0->TC_CHANNEL[0].TC_CV < 36000 ) {
// Value depends on MCK/2 (used 18MHz) give 2mS delay // Value depends on MCK/2 (used 18MHz) give 2mS delay
wdt_reset(); // Wait WDG_RESET(); // Wait
} }
} }
} }

View file

@ -36,7 +36,7 @@ void watchdogInit(unsigned int duration)
IWDG->KR = 0x5555; // Unlock registers IWDG->KR = 0x5555; // Unlock registers
IWDG->PR = 3; // Divide by 32 => 1kHz clock IWDG->PR = 3; // Divide by 32 => 1kHz clock
IWDG->KR = 0x5555; // Unlock registers IWDG->KR = 0x5555; // Unlock registers
IWDG->RLR = duration; // 1.5 seconds nominal IWDG->RLR = duration;
IWDG->KR = 0xAAAA; // reload IWDG->KR = 0xAAAA; // reload
IWDG->KR = 0xCCCC; // start IWDG->KR = 0xCCCC; // start
} }
@ -222,7 +222,7 @@ void boardOff()
#if defined(PWR_BUTTON_PRESS) #if defined(PWR_BUTTON_PRESS)
while (pwrPressed()) { while (pwrPressed()) {
wdt_reset(); WDG_RESET();
} }
#endif #endif
@ -234,7 +234,7 @@ void boardOff()
__disable_irq(); __disable_irq();
while (1) { while (1) {
wdt_reset(); WDG_RESET();
#if defined(PWR_BUTTON_PRESS) #if defined(PWR_BUTTON_PRESS)
// X9E/X7 needs watchdog reset because CPU is still running while // X9E/X7 needs watchdog reset because CPU is still running while
// the power key is held pressed by the user. // the power key is held pressed by the user.

View file

@ -95,7 +95,7 @@ uint32_t sdMounted();
#define FLASH_PAGESIZE 256 #define FLASH_PAGESIZE 256
void unlockFlash(); void unlockFlash();
void lockFlash(); void lockFlash();
void flashWrite(uint32_t * address, uint32_t * buffer); void flashWrite(uint32_t * address, const 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);
@ -441,13 +441,13 @@ uint32_t readTrims();
#define KEYS_PRESSED() (readKeys()) #define KEYS_PRESSED() (readKeys())
// WDT driver // WDT driver
#define WDTO_500MS 500 #define WDG_DURATION 500 /*ms*/
#if !defined(WATCHDOG) || defined(SIMU) #if !defined(WATCHDOG) || defined(SIMU)
#define wdt_enable(x) #define WDG_ENABLE(x)
#define wdt_reset() #define WDG_RESET()
#else #else
#define wdt_enable(x) watchdogInit(x) #define WDG_ENABLE(x) watchdogInit(x)
#define wdt_reset() IWDG->KR = 0xAAAA #define WDG_RESET() IWDG->KR = 0xAAAA
#endif #endif
void watchdogInit(unsigned int duration); void watchdogInit(unsigned int duration);
#define WAS_RESET_BY_SOFTWARE() (RCC->CSR & RCC_CSR_SFTRSTF) #define WAS_RESET_BY_SOFTWARE() (RCC->CSR & RCC_CSR_SFTRSTF)

View file

@ -189,7 +189,7 @@ TASK_FUNCTION(mixerTask)
DEBUG_TIMER_STOP(debugTimerTelemetryWakeup); DEBUG_TIMER_STOP(debugTimerTelemetryWakeup);
if (heartbeat == HEART_WDT_CHECK) { if (heartbeat == HEART_WDT_CHECK) {
wdt_reset(); WDG_RESET();
heartbeat = 0; heartbeat = 0;
} }