Core panic in TxManage, concluding gate in timer callback - using digitalwrite is BAD @ ISRL!!!

Now use FreeRTOS queue to pass the actual event down.
This commit is contained in:
Ray Jones 2020-04-09 06:57:26 +10:00
parent 0ed7ba7e59
commit 4625f98cf3
2 changed files with 41 additions and 4 deletions

View File

@ -128,8 +128,8 @@
const int FirmwareRevision = 32;
const int FirmwareSubRevision = 0;
const int FirmwareMinorRevision = 0;
const char* FirmwareDate = "30 Mar 2020";
const int FirmwareMinorRevision = 3;
const char* FirmwareDate = "9 Apr 2020";
#ifdef ESP32

View File

@ -22,6 +22,7 @@
#include "TxManage.h"
#include "../Utility/NVStorage.h"
#include "../Utility/helpers.h"
#include "freertos/queue.h"
//#define DEBUG_THERMOSTAT
@ -51,6 +52,31 @@ extern void DebugReportFrame(const char* hdr, const CProtocol&, const char* ftr)
unsigned long CTxManage::m_nStartTime = 0;
int CTxManage::m_nTxGatePin = 0;
// Timer callback operates at ISRL
// this means we should avoid any function NOT in IRAM.
// Sadly digitalWrite falls into this category, so use a FreeRTOS queue
// to push the end event handling into a non ISRL task
static QueueHandle_t txGate_queue = NULL;
static int lclTxGatePin = 0;
// static function used for the tx gate termination
static void IRAM_ATTR GateTerminateCallback()
{
uint32_t gpio_num = lclTxGatePin;
xQueueSendFromISR(txGate_queue, &gpio_num, NULL);
}
static void TxGateConclude(void* arg)
{
uint32_t io_num;
for(;;) {
if(xQueueReceive(txGate_queue, &io_num, portMAX_DELAY)) {
digitalWrite(io_num, LOW); // terminate Tx Gate
}
}
}
CTxManage::CTxManage(int TxGatePin, HardwareSerial& serial) :
m_BlueWireSerial(serial),
m_TxFrame(CProtocol::CtrlMode)
@ -61,6 +87,7 @@ CTxManage::CTxManage(int TxGatePin, HardwareSerial& serial) :
m_bTxPending = false;
m_nStartTime = 0;
m_nTxGatePin = TxGatePin;
lclTxGatePin = TxGatePin;
_rawCommand = 0;
m_HWTimer = NULL;
}
@ -68,7 +95,9 @@ CTxManage::CTxManage(int TxGatePin, HardwareSerial& serial) :
// static function used for the tx gate termination
void CTxManage::GateTerminate()
{
digitalWrite(m_nTxGatePin, LOW); // default to receive mode
uint32_t gpio_num = m_nTxGatePin;
xQueueSendFromISR(txGate_queue, &gpio_num, NULL);
// digitalWrite(m_nTxGatePin, LOW); // default to receive mode
m_nStartTime = 0; // cancel, we are DONE
}
@ -78,12 +107,19 @@ void CTxManage::begin()
pinMode(m_nTxGatePin, OUTPUT);
digitalWrite(m_nTxGatePin, LOW); // default to receive mode
//create a queue to handle gpio event from isr
txGate_queue = xQueueCreate(10, sizeof(uint32_t));
//start gpio task
xTaskCreate(TxGateConclude, "Tx Gate Conclude", 2048, NULL, configMAX_PRIORITIES-2, NULL);
// 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);
// timerAttachInterrupt(m_HWTimer, &GateTerminate, true);
timerAttachInterrupt(m_HWTimer, &GateTerminateCallback, true);
timerAlarmDisable(m_HWTimer); //disable interrupt for now
timerSetAutoReload(m_HWTimer, false);
}
@ -299,6 +335,7 @@ CTxManage::CheckTx(unsigned long timenow)
// Tx gate remains held high
// it is then brought low by the timer alarm callback, which also cancels m_nStartTime
m_bTxPending = false;
m_nStartTime = 0;
m_BlueWireSerial.write(m_TxFrame.Data, 24); // write native binary values
timerWrite(m_HWTimer, 0); //reset tx gate timeout
timerAlarmEnable(m_HWTimer); // timeout will cause cessation of the Tx gate