Tx gate now terminated via a HW timer callback. Using max priority task for SW watchdog.

This commit is contained in:
Ray Jones 2019-11-22 21:30:45 +11:00
parent c649517805
commit c9298656fa
5 changed files with 87 additions and 55 deletions

View File

@ -116,6 +116,7 @@
#include <SPIFFS.h>
#include <nvs.h>
#include "Utility/MQTTsetup.h"
#include <FreeRTOS.h>
// SSID & password now stored in NV storage - these are still the default values.
//#define AP_SSID "Afterburner"
@ -221,9 +222,6 @@ bool bHaveWebClient = false;
bool bBTconnected = false;
long BootTime;
hw_timer_t *watchdogTimer = NULL;
hw_timer_t *JSONwatchdog = NULL;
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Bluetooth instantiation
//
@ -286,13 +284,39 @@ void parentKeyHandler(uint8_t event)
ScreenManager.keyHandler(event); // call into the Screen Manager
}
void interruptReboot()
{
ets_printf("Software watchdog reboot......\r\n");
esp_restart();
}
unsigned long WatchdogTick = -1;
unsigned long JSONWatchdogTick = -1;
void WatchdogTask(void * param)
{
for(;;) {
if(WatchdogTick >= 0) {
if(WatchdogTick == 0) {
interruptReboot();
}
else {
WatchdogTick--;
}
}
if(JSONWatchdogTick >= 0) {
if(JSONWatchdogTick == 0) {
interruptReboot();
}
else {
JSONWatchdogTick--;
}
}
vTaskDelay(10);
}
}
//**************************************************************************************************
//** **
//** WORKAROUND for crap ESP32 millis() standard function **
@ -455,17 +479,17 @@ void setup() {
setupGPIO();
#if USE_SW_WATCHDOG == 1 && USE_JTAG == 0
// create a watchdog timer
watchdogTimer = timerBegin(0, 80, true); //timer 0, divisor 80
timerAlarmWrite(watchdogTimer, 15000000, false); //set time in uS must be fed within this time or reboot
timerAttachInterrupt(watchdogTimer, &interruptReboot, true);
timerAlarmEnable(watchdogTimer); //enable interrupt
// create a high priority FreeRTOS task as a watchdog monitor
TaskHandle_t wdTask;
xTaskCreate(WatchdogTask,
"watchdogTask",
2000,
NULL,
configMAX_PRIORITIES-1,
&wdTask);
#endif
JSONwatchdog = timerBegin(1, 80, true);
timerAlarmWrite(JSONwatchdog, 60000000, false); //set time in uS must be fed within this time or reboot
timerAttachInterrupt(JSONwatchdog, &interruptReboot, true);
timerAlarmDisable(JSONwatchdog); //disable interrupt for now
JSONWatchdogTick = -1;
WatchdogTick = -1;
FilteredSamples.ipVolts.setRounding(0.1);
FilteredSamples.GlowAmps.setRounding(0.01);
@ -607,9 +631,7 @@ void loop()
case CommStates::Idle:
#if USE_SW_WATCHDOG == 1 && USE_JTAG == 0
feedWatchdog(); //reset timer (feed watchdog)
#endif
feedWatchdog(); // feed watchdog
doStreaming(); // do wifi, BT tx etc when NOT in midst of handling blue wire
// this especially avoids E-07 faults due to larger data transfers
@ -1752,28 +1774,22 @@ void ShowOTAScreen(int percent, eOTAmodes updateType)
void feedWatchdog()
{
#if USE_JTAG == 0
#if USE_SW_WATCHDOG == 1 && USE_JTAG == 0
// BEST NOT USE WATCHDOG WITH JTAG DEBUG :-)
uint64_t timeRem = timerRead(watchdogTimer);
if(timeRem > 500000) // 500ms
DebugPort.printf("WD time = %lld\r\n", timeRem); // print longer WD intervals
timerWrite(watchdogTimer, 0); //reset timer (feed watchdog)
timerAlarmWrite(watchdogTimer, 15000000, false); //set time in uS must be fed within this time or reboot
WatchdogTick = 1500;
#else
WatchdogTick = -1;
#endif
}
void doJSONwatchdog(int topup)
{
if(topup) {
timerWrite(JSONwatchdog, 0); //reset timer (feed watchdog)
uint64_t deathtime = topup * 1000000;
timerAlarmWrite(JSONwatchdog, deathtime, false); //set time in uS must be fed within this time or reboot
timerAlarmEnable(JSONwatchdog); //enable interrupt
}
else {
timerAlarmDisable(JSONwatchdog); //disable interrupt
}
if(topup) {
JSONWatchdogTick = topup * 100;
}
else {
JSONWatchdogTick = -1;
}
}

View File

@ -48,6 +48,9 @@ extern void DebugReportFrame(const char* hdr, const CProtocol&, const char* ftr)
// _____________________________________________________________________
// Tx Data |||||||||||||||
unsigned long CTxManage::m_nStartTime = 0;
int CTxManage::m_nTxGatePin = 0;
CTxManage::CTxManage(int TxGatePin, HardwareSerial& serial) :
m_BlueWireSerial(serial),
m_TxFrame(CProtocol::CtrlMode)
@ -58,12 +61,30 @@ CTxManage::CTxManage(int TxGatePin, HardwareSerial& serial) :
m_nStartTime = 0;
m_nTxGatePin = TxGatePin;
_rawCommand = 0;
m_HWTimer = NULL;
}
// static function used for the tx gate termination
void CTxManage::GateTerminate()
{
digitalWrite(m_nTxGatePin, LOW); // default to receive mode
m_nStartTime = 0; // cancel, we are DONE
}
void CTxManage::begin()
{
pinMode(m_nTxGatePin, OUTPUT);
digitalWrite(m_nTxGatePin, LOW); // default to receive mode
// use a hardware timer to terminate the Tx gate shortly after the completion of the 24 byte transmit packet
m_HWTimer = timerBegin(2, 80, true);
//set time in uS of Tx gate from when actual tx data bytes are loaded
// 240 bits @ 25000bps is 9.6ms, we'll use 9.7ms for a bit of tolerance
timerAlarmWrite(m_HWTimer, 10000-300, false);
timerAttachInterrupt(m_HWTimer, &GateTerminate, true);
timerAlarmDisable(m_HWTimer); //disable interrupt for now
timerSetAutoReload(m_HWTimer, false);
}
void
@ -231,37 +252,33 @@ CTxManage::PrepareFrame(const CProtocol& basisFrame, bool isBTCmaster)
void
CTxManage::Start(unsigned long timenow)
{
if(timenow == 0) // avoid a black hole if millis() has wrapped to zero
timenow++;
m_nStartTime = timenow;
m_nStartTime = timenow + m_nStartTime; // create a dwell period if an OEM controller is present after it's data exchange
m_nStartTime |= 1; // avoid a black hole if millis() has wrapped to zero
m_bTxPending = true;
}
// generate a Tx Gate, then send the TxFrame to the Blue wire
// Note the serial data is ISR driven, we need to hold off
// for a while to let teh buffewred dat clear before closing the Tx Gate.
// Note the serial data is ISR driven, we supply all 24 bytes to the Tx buffer which is then drained automatically
// the Tx Gate is closed shortly after the last byte is completed.
bool
CTxManage::CheckTx(unsigned long timenow)
{
if(m_nStartTime) {
if(m_nStartTime && m_bTxPending) {
long diff = timenow - m_nStartTime;
if(diff > m_nStartDelay) {
if(diff >= 0) { // dwell since OEM exchange has expired ?
// begin front porch of Tx gating pulse
digitalWrite(m_nTxGatePin, HIGH);
}
if(m_bTxPending && (diff > (m_nStartDelay + m_nFrontPorch))) {
// front porch expired, perform serial transmission
if(diff >= m_nFrontPorch) {
// front porch expired, start actual serial transmission
// Tx gate remains held high
// it is then brought low by the timer alarm callback, which also cancels m_nStartTime
m_bTxPending = false;
m_BlueWireSerial.write(m_TxFrame.Data, 24); // write native binary values
}
if(diff > (m_nStartDelay + m_nFrameTime)) {
// conclude Tx gating after (emperical) delay
digitalWrite(m_nTxGatePin, LOW);
m_nStartTime = 0; // cancel, we are DONE
timerWrite(m_HWTimer, 0); //reset tx gate timeout
timerAlarmEnable(m_HWTimer); // timeout will cause cessation of the Tx gate
}
}
return m_nStartTime == 0; // returns true when done

View File

@ -25,7 +25,7 @@ class CTxManage
{
const int m_nStartDelay = 20;
const int m_nFrameTime = 14;
const int m_nFrontPorch = 2;
const int m_nFrontPorch = 0;
public:
CTxManage(int TxGatePin, HardwareSerial& serial);
@ -37,6 +37,7 @@ public:
bool CheckTx(unsigned long timenow);
void begin();
const CProtocol& getFrame() const { return m_TxFrame; };
static void GateTerminate();
private:
HardwareSerial& m_BlueWireSerial;
@ -44,9 +45,11 @@ private:
bool m_bOnReq;
bool m_bOffReq;
bool m_bTxPending;
int m_nTxGatePin;
static int m_nTxGatePin;
uint8_t _rawCommand;
unsigned long m_nStartTime;
static unsigned long m_nStartTime;
hw_timer_t *m_HWTimer;
};

View File

@ -766,9 +766,7 @@ void onUploadProgression()
// handle file fragments of form upload
else if (upload.status == UPLOAD_FILE_WRITE) {
#if USE_SW_WATCHDOG == 1
feedWatchdog(); // we get stuck here for a while, don't let the watchdog bite!
#endif
int sts = BrowserUpload.fragment(upload);
if(sts < 0) {
sprintf(JSON, "{\"progress\":%d}", sts);

View File

@ -67,9 +67,7 @@ void initOTA(){
DebugPort.println("Start updating " + type);
DebugPort.handle(); // keep telnet spy alive
ShowOTAScreen();
#if USE_SW_WATCHDOG == 1
feedWatchdog(); // we get stuck here for a while, don't let the watchdog bite!
#endif
})
.onEnd([]() {
DebugPort.println("\nEnd");