handle bus recovery in driver class

This commit is contained in:
andreas 2023-08-25 20:14:26 +02:00
parent f5e48fcab3
commit 0d5215e00f
3 changed files with 40 additions and 23 deletions

View File

@ -5,9 +5,12 @@
#define LOGID(id) ((id >> 8) & 0x1ffff) #define LOGID(id) ((id >> 8) & 0x1ffff)
Nmea2kTwai::Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin): static const int TIMEOUT_OFFLINE=256; //# of timeouts to consider offline
tNMEA2000(),RxPin(_RxPin),TxPin(_TxPin)
Nmea2kTwai::Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin, unsigned long recP):
tNMEA2000(),RxPin(_RxPin),TxPin(_TxPin),recoveryPeriod(recP)
{ {
lastRecoveryCheck=millis();
} }
bool Nmea2kTwai::CANSendFrame(unsigned long id, unsigned char len, const unsigned char *buf, bool wait_sent) bool Nmea2kTwai::CANSendFrame(unsigned long id, unsigned char len, const unsigned char *buf, bool wait_sent)
@ -21,7 +24,7 @@ bool Nmea2kTwai::CANSendFrame(unsigned long id, unsigned char len, const unsigne
esp_err_t rt=twai_transmit(&message,0); esp_err_t rt=twai_transmit(&message,0);
if (rt != ESP_OK){ if (rt != ESP_OK){
if (rt == ESP_ERR_TIMEOUT){ if (rt == ESP_ERR_TIMEOUT){
txTimeouts++; if (txTimeouts < TIMEOUT_OFFLINE) txTimeouts++;
} }
logDebug(LOG_MSG,"twai transmit for %ld failed: %x",LOGID(id),(int)rt); logDebug(LOG_MSG,"twai transmit for %ld failed: %x",LOGID(id),(int)rt);
return false; return false;
@ -111,11 +114,31 @@ Nmea2kTwai::Status Nmea2kTwai::getStatus(){
rt.rx_missed=state.rx_missed_count; rt.rx_missed=state.rx_missed_count;
rt.rx_overrun=state.rx_overrun_count; rt.rx_overrun=state.rx_overrun_count;
rt.tx_timeouts=txTimeouts; rt.tx_timeouts=txTimeouts;
if (rt.tx_timeouts > 256 && rt.state == ST_RUNNING){ if (rt.tx_timeouts >= TIMEOUT_OFFLINE && rt.state == ST_RUNNING){
rt.state=ST_OFFLINE; rt.state=ST_OFFLINE;
} }
return rt; return rt;
} }
bool Nmea2kTwai::checkRecovery(){
if (recoveryPeriod == 0) return false; //no check
unsigned long now=millis();
if ((lastRecoveryCheck+recoveryPeriod) > now) return false;
lastRecoveryCheck=now;
Status canState=getStatus();
bool strt=false;
if (canState.state != Nmea2kTwai::ST_RUNNING){
if (canState.state == Nmea2kTwai::ST_BUS_OFF){
strt=true;
bool rt=startRecovery();
logDebug(LOG_INFO,"start can recovery - result %d",(int)rt);
}
if (canState.state == Nmea2kTwai::ST_STOPPED){
bool rt=CANOpen();
logDebug(LOG_INFO,"restart can driver - result %d",(int)rt);
}
}
return strt;
}
bool Nmea2kTwai::startRecovery(){ bool Nmea2kTwai::startRecovery(){
esp_err_t rt=twai_driver_uninstall(); esp_err_t rt=twai_driver_uninstall();

View File

@ -5,7 +5,7 @@
class Nmea2kTwai : public tNMEA2000{ class Nmea2kTwai : public tNMEA2000{
public: public:
Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin); Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin, unsigned long recP=0);
typedef enum{ typedef enum{
ST_STOPPED, ST_STOPPED,
ST_RUNNING, ST_RUNNING,
@ -25,7 +25,7 @@ class Nmea2kTwai : public tNMEA2000{
STATE state=ST_ERROR; STATE state=ST_ERROR;
} Status; } Status;
Status getStatus(); Status getStatus();
bool startRecovery(); bool checkRecovery();
static const char * stateStr(const STATE &st); static const char * stateStr(const STATE &st);
virtual bool CANOpen(); virtual bool CANOpen();
virtual ~Nmea2kTwai(){}; virtual ~Nmea2kTwai(){};
@ -47,9 +47,12 @@ class Nmea2kTwai : public tNMEA2000{
private: private:
void initDriver(); void initDriver();
bool startRecovery();
gpio_num_t TxPin; gpio_num_t TxPin;
gpio_num_t RxPin; gpio_num_t RxPin;
uint32_t txTimeouts=0; uint32_t txTimeouts=0;
unsigned long recoveryPeriod=0;
unsigned long lastRecoveryCheck=0;
}; };
#endif #endif

View File

@ -110,12 +110,13 @@ GwLog logger(LOGLEVEL,NULL);
GwConfigHandler config(&logger); GwConfigHandler config(&logger);
#include "Nmea2kTwai.h" #include "Nmea2kTwai.h"
static const unsigned long CAN_RECOVERY_PERIOD=3000; //ms
class Nmea2kTwaiLog : public Nmea2kTwai{ class Nmea2kTwaiLog : public Nmea2kTwai{
private: private:
GwLog* logger; GwLog* logger;
public: public:
Nmea2kTwaiLog(gpio_num_t _TxPin, gpio_num_t _RxPin, GwLog *l): Nmea2kTwaiLog(gpio_num_t _TxPin, gpio_num_t _RxPin, unsigned long recoveryPeriod,GwLog *l):
Nmea2kTwai(_TxPin,_RxPin),logger(l){} Nmea2kTwai(_TxPin,_RxPin,recoveryPeriod),logger(l){}
virtual void logDebug(int level, const char *fmt,...){ virtual void logDebug(int level, const char *fmt,...){
va_list args; va_list args;
va_start(args,fmt); va_start(args,fmt);
@ -125,7 +126,7 @@ class Nmea2kTwaiLog : public Nmea2kTwai{
}; };
Nmea2kTwai &NMEA2000=*(new Nmea2kTwaiLog(ESP32_CAN_TX_PIN,ESP32_CAN_RX_PIN,&logger)); Nmea2kTwai &NMEA2000=*(new Nmea2kTwaiLog(ESP32_CAN_TX_PIN,ESP32_CAN_RX_PIN,CAN_RECOVERY_PERIOD,&logger));
#ifdef GWBUTTON_PIN #ifdef GWBUTTON_PIN
bool fixedApPass=false; bool fixedApPass=false;
@ -838,8 +839,7 @@ void handleSendAndRead(bool handleRead){
TimeMonitor monitor(20,0.2); TimeMonitor monitor(20,0.2);
unsigned long lastHeapReport=0; unsigned long lastHeapReport=0;
unsigned long lastCanRecovery=0; unsigned long lastCanStatus=0;
static const unsigned long CAN_RECOVERY_PERIOD=3000; //ms
void loop() { void loop() {
monitor.reset(); monitor.reset();
GWSYNCHRONIZED(&mainLock); GWSYNCHRONIZED(&mainLock);
@ -848,6 +848,7 @@ void loop() {
gwWifi.loop(); gwWifi.loop();
unsigned long now=millis(); unsigned long now=millis();
monitor.setTime(2); monitor.setTime(2);
NMEA2000.checkRecovery();
if (HEAP_REPORT_TIME > 0 && now > (lastHeapReport+HEAP_REPORT_TIME)){ if (HEAP_REPORT_TIME > 0 && now > (lastHeapReport+HEAP_REPORT_TIME)){
lastHeapReport=now; lastHeapReport=now;
if (logger.isActive(GwLog::DEBUG)){ if (logger.isActive(GwLog::DEBUG)){
@ -858,8 +859,8 @@ void loop() {
logger.logDebug(GwLog::DEBUG,"Main loop %s",monitor.getLog().c_str()); logger.logDebug(GwLog::DEBUG,"Main loop %s",monitor.getLog().c_str());
} }
} }
if (now > (lastCanRecovery + CAN_RECOVERY_PERIOD)){ if (now > (lastCanStatus + CAN_RECOVERY_PERIOD)){
lastCanRecovery=now; lastCanStatus=now;
Nmea2kTwai::Status canState=NMEA2000.getStatus(); Nmea2kTwai::Status canState=NMEA2000.getStatus();
logger.logDebug(GwLog::DEBUG, logger.logDebug(GwLog::DEBUG,
"can state %s, rxerr %d, txerr %d, txfail %d, txtimeout %d, rxmiss %d, rxoverrun %d", "can state %s, rxerr %d, txerr %d, txfail %d, txtimeout %d, rxmiss %d, rxoverrun %d",
@ -870,16 +871,6 @@ void loop() {
canState.tx_timeouts, canState.tx_timeouts,
canState.rx_missed, canState.rx_missed,
canState.rx_overrun); canState.rx_overrun);
if (canState.state != Nmea2kTwai::ST_RUNNING){
if (canState.state == Nmea2kTwai::ST_BUS_OFF){
bool rt=NMEA2000.startRecovery();
logger.logDebug(GwLog::LOG,"start can recovery - result %d",(int)rt);
}
if (canState.state == Nmea2kTwai::ST_STOPPED){
bool rt=NMEA2000.CANOpen();
logger.logDebug(GwLog::LOG,"restart can driver - result %d",(int)rt);
}
}
} }
monitor.setTime(3); monitor.setTime(3);
channels.allChannels([](GwChannel *c){ channels.allChannels([](GwChannel *c){