allow to start m5 atom s3 without USB device connected

This commit is contained in:
andreas 2024-03-23 20:21:21 +01:00
parent 5b0b8ba799
commit d27e811317
5 changed files with 103 additions and 30 deletions

View File

@ -173,7 +173,7 @@ void GwChannel::toJson(GwJsonDocument &doc){
if (countIn) countIn->toJson(doc); if (countIn) countIn->toJson(doc);
} }
String GwChannel::toString(){ String GwChannel::toString(){
String rt="CH:"+name; String rt="CH"+name+"("+sourceId+"):";
rt+=enabled?"[ena]":"[dis]"; rt+=enabled?"[ena]":"[dis]";
rt+=NMEAin?"in,":""; rt+=NMEAin?"in,":"";
rt+=NMEAout?"out,":""; rt+=NMEAout?"out,":"";

View File

@ -35,12 +35,13 @@ class GwSerialLog : public GwLogWriter
int wp = 0; int wp = 0;
GwSerial *writer; GwSerial *writer;
bool disabled = false; bool disabled = false;
long flushTimeout=200;
public: public:
GwSerialLog(GwSerial *writer, bool disabled) GwSerialLog(GwSerial *writer, bool disabled,long flushTimeout=200)
{ {
this->writer = writer; this->writer = writer;
this->disabled = disabled; this->disabled = disabled;
this->flushTimeout=flushTimeout;
logBuffer = new char[bufferSize]; logBuffer = new char[bufferSize];
wp = 0; wp = 0;
} }
@ -63,16 +64,63 @@ public:
{ {
while (handled < wp) while (handled < wp)
{ {
writer->flush(); if ( !writer->flush(flushTimeout)) break;
size_t rt = writer->sendToClients(logBuffer + handled, -1, true); size_t rt = writer->sendToClients(logBuffer + handled, -1, true);
handled += rt; handled += rt;
} }
if (handled < wp){
if (handled > 0){
memmove(logBuffer,logBuffer+handled,wp-handled);
wp-=handled;
logBuffer[handled]=0;
}
return;
}
} }
wp = 0; wp = 0;
logBuffer[0] = 0; logBuffer[0] = 0;
} }
}; };
template<typename T>
class SerialWrapper : public GwChannelList::SerialWrapperBase{
private:
template<class C>
void beginImpl(C *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){}
void beginImpl(HardwareSerial *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){
s->begin(baud,config,rxPin,txPin);
}
template<class C>
void setError(C* s, GwLog *logger){}
void setError(HardwareSerial *s,GwLog *logger){
LOG_DEBUG(GwLog::LOG,"enable serial errors for channel %d",id);
s->onReceiveError([logger,this](hardwareSerial_error_t err){
LOG_DEBUG(GwLog::ERROR,"serial error on id %d: %d",this->id,(int)err);
});
}
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
void beginImpl(HWCDC *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){
s->begin(baud);
}
#endif
T *serial;
int id;
public:
SerialWrapper(T* s,int i):serial(s),id(i){}
virtual void begin(GwLog* logger,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1) override{
beginImpl(serial,baud,config,rxPin,txPin);
setError(serial,logger);
};
virtual Stream *getStream() override{
return serial;
}
virtual int getId() override{
return id;
}
};
GwChannelList::GwChannelList(GwLog *logger, GwConfigHandler *config){ GwChannelList::GwChannelList(GwLog *logger, GwConfigHandler *config){
this->logger=logger; this->logger=logger;
this->config=config; this->config=config;
@ -127,16 +175,16 @@ static SerialParam *getSerialParam(int id){
} }
void GwChannelList::addSerial(int id, int rx, int tx, int type){ void GwChannelList::addSerial(int id, int rx, int tx, int type){
if (id == 1){ if (id == 1){
addSerial(&Serial1,SERIAL1_CHANNEL_ID,type,rx,tx); addSerial(new SerialWrapper<decltype(Serial1)>(&Serial1,SERIAL1_CHANNEL_ID),type,rx,tx);
return; return;
} }
if (id == 2){ if (id == 2){
addSerial(&Serial2,SERIAL2_CHANNEL_ID,type,rx,tx); addSerial(new SerialWrapper<decltype(Serial2)>(&Serial2,SERIAL2_CHANNEL_ID),type,rx,tx);
return; return;
} }
LOG_DEBUG(GwLog::ERROR,"invalid serial config with id %d",id); LOG_DEBUG(GwLog::ERROR,"invalid serial config with id %d",id);
} }
void GwChannelList::addSerial(HardwareSerial *stream,int id,int type,int rx,int tx){ void GwChannelList::addSerial(GwChannelList::SerialWrapperBase *stream,int type,int rx,int tx){
const char *mode=nullptr; const char *mode=nullptr;
switch (type) switch (type)
{ {
@ -157,9 +205,10 @@ void GwChannelList::addSerial(HardwareSerial *stream,int id,int type,int rx,int
LOG_DEBUG(GwLog::ERROR,"unknown serial type %d",type); LOG_DEBUG(GwLog::ERROR,"unknown serial type %d",type);
return; return;
} }
addSerial(stream,id,mode,rx,tx); addSerial(stream,mode,rx,tx);
} }
void GwChannelList::addSerial(HardwareSerial *serialStream,int id,const String &mode,int rx,int tx){ void GwChannelList::addSerial(GwChannelList::SerialWrapperBase *serialStream,const String &mode,int rx,int tx){
int id=serialStream->getId();
for (auto &&it:theChannels){ for (auto &&it:theChannels){
if (it->isOwnSource(id)){ if (it->isOwnSource(id)){
LOG_DEBUG(GwLog::ERROR,"trying to re-add serial id=%d, ignoring",id); LOG_DEBUG(GwLog::ERROR,"trying to re-add serial id=%d, ignoring",id);
@ -201,8 +250,8 @@ void GwChannelList::addSerial(HardwareSerial *serialStream,int id,const String &
if (tx < 0) canWrite=false; if (tx < 0) canWrite=false;
LOG_DEBUG(GwLog::DEBUG,"serial set up: mode=%s,rx=%d,canRead=%d,tx=%d,canWrite=%d", LOG_DEBUG(GwLog::DEBUG,"serial set up: mode=%s,rx=%d,canRead=%d,tx=%d,canWrite=%d",
mode.c_str(),rx,(int)canRead,tx,(int)canWrite); mode.c_str(),rx,(int)canRead,tx,(int)canWrite);
serialStream->begin(config->getInt(param->baud,115200),SERIAL_8N1,rx,tx); serialStream->begin(logger,config->getInt(param->baud,115200),SERIAL_8N1,rx,tx);
GwSerial *serial = new GwSerial(logger, serialStream, id, canRead); GwSerial *serial = new GwSerial(logger, serialStream->getStream(), id, canRead);
LOG_DEBUG(GwLog::LOG, "starting serial %d ", id); LOG_DEBUG(GwLog::LOG, "starting serial %d ", id);
GwChannel *channel = new GwChannel(logger, param->name, id); GwChannel *channel = new GwChannel(logger, param->name, id);
channel->setImpl(serial); channel->setImpl(serial);
@ -241,6 +290,14 @@ void GwChannelList::preinit(){
} }
} }
} }
template<typename S>
long getFlushTimeout(S &s){
return 200;
}
template<>
long getFlushTimeout(HardwareSerial &s){
return 2000;
}
void GwChannelList::begin(bool fallbackSerial){ void GwChannelList::begin(bool fallbackSerial){
LOG_DEBUG(GwLog::DEBUG,"GwChannelList::begin"); LOG_DEBUG(GwLog::DEBUG,"GwChannelList::begin");
GwChannel *channel=NULL; GwChannel *channel=NULL;
@ -248,7 +305,7 @@ void GwChannelList::begin(bool fallbackSerial){
if (! fallbackSerial){ if (! fallbackSerial){
GwSerial *usb=new GwSerial(NULL,&USBSerial,USB_CHANNEL_ID); GwSerial *usb=new GwSerial(NULL,&USBSerial,USB_CHANNEL_ID);
USBSerial.begin(config->getInt(config->usbBaud)); USBSerial.begin(config->getInt(config->usbBaud));
logger->setWriter(new GwSerialLog(usb,config->getBool(config->usbActisense))); logger->setWriter(new GwSerialLog(usb,config->getBool(config->usbActisense),getFlushTimeout(USBSerial)));
logger->prefix="GWSERIAL:"; logger->prefix="GWSERIAL:";
channel=new GwChannel(logger,"USB",USB_CHANNEL_ID); channel=new GwChannel(logger,"USB",USB_CHANNEL_ID);
channel->setImpl(usb); channel->setImpl(usb);
@ -297,10 +354,12 @@ void GwChannelList::begin(bool fallbackSerial){
#define GWSERIAL_RX -1 #define GWSERIAL_RX -1
#endif #endif
#ifdef GWSERIAL_TYPE #ifdef GWSERIAL_TYPE
addSerial(&Serial1,SERIAL1_CHANNEL_ID,GWSERIAL_TYPE,GWSERIAL_RX,GWSERIAL_TX); setSerialError(&Serial1,SERIAL1_CHANNEL_ID,this->logger);
addSerial(new SerialWrapper<decltype(Serial1)>(&Serial1,SERIAL1_CHANNEL_ID),GWSERIAL_TYPE,GWSERIAL_RX,GWSERIAL_TX);
#else #else
#ifdef GWSERIAL_MODE #ifdef GWSERIAL_MODE
addSerial(&Serial1,SERIAL1_CHANNEL_ID,GWSERIAL_MODE,GWSERIAL_RX,GWSERIAL_TX); setSerialError(&Serial1,SERIAL1_CHANNEL_ID,this->logger);
addSerial(new SerialWrapper<decltype(Serial1)>(&Serial1,SERIAL1_CHANNEL_ID),GWSERIAL_MODE,GWSERIAL_RX,GWSERIAL_TX);
#endif #endif
#endif #endif
//serial 2 //serial 2
@ -311,10 +370,10 @@ void GwChannelList::begin(bool fallbackSerial){
#define GWSERIAL2_RX -1 #define GWSERIAL2_RX -1
#endif #endif
#ifdef GWSERIAL2_TYPE #ifdef GWSERIAL2_TYPE
addSerial(&Serial2,SERIAL2_CHANNEL_ID,GWSERIAL2_TYPE,GWSERIAL2_RX,GWSERIAL2_TX); addSerial(new SerialWrapper<decltype(Serial2)>(&Serial2,SERIAL2_CHANNEL_ID),GWSERIAL2_TYPE,GWSERIAL2_RX,GWSERIAL2_TX);
#else #else
#ifdef GWSERIAL2_MODE #ifdef GWSERIAL2_MODE
addSerial(&Serial2,SERIAL2_CHANNEL_ID,GWSERIAL2_MODE,GWSERIAL2_RX,GWSERIAL2_TX); addSerial(new SerialWrapper<decltype(Serial2)>(&Serial2,SERIAL2_CHANNEL_ID),GWSERIAL2_MODE,GWSERIAL2_RX,GWSERIAL2_TX);
#endif #endif
#endif #endif
//tcp client //tcp client

View File

@ -23,6 +23,12 @@ class GwSocketServer;
class GwTcpClient; class GwTcpClient;
class GwChannelList{ class GwChannelList{
private: private:
class SerialWrapperBase{
public:
virtual void begin(GwLog* logger,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1)=0;
virtual Stream *getStream()=0;
virtual int getId()=0;
};
GwLog *logger; GwLog *logger;
GwConfigHandler *config; GwConfigHandler *config;
typedef std::vector<GwChannel *> ChannelList; typedef std::vector<GwChannel *> ChannelList;
@ -30,8 +36,8 @@ class GwChannelList{
std::map<int,String> modes; std::map<int,String> modes;
GwSocketServer *sockets; GwSocketServer *sockets;
GwTcpClient *client; GwTcpClient *client;
void addSerial(HardwareSerial *stream,int id,const String &mode,int rx,int tx); void addSerial(SerialWrapperBase *stream,const String &mode,int rx,int tx);
void addSerial(HardwareSerial *stream,int id,int type,int rx,int tx); void addSerial(SerialWrapperBase *stream,int type,int rx,int tx);
public: public:
void addSerial(int id, int rx, int tx, int type); void addSerial(int id, int rx, int tx, int type);
GwChannelList(GwLog *logger, GwConfigHandler *config); GwChannelList(GwLog *logger, GwConfigHandler *config);

View File

@ -40,7 +40,7 @@ class GwSerialStream: public Stream{
GwSerial::GwSerial(GwLog *logger, HardwareSerial *s, int id,bool allowRead):serial(s) GwSerial::GwSerial(GwLog *logger, Stream *s, int id,bool allowRead):serial(s)
{ {
LOG_DEBUG(GwLog::DEBUG,"creating GwSerial %p id %d",this,id); LOG_DEBUG(GwLog::DEBUG,"creating GwSerial %p id %d",this,id);
this->id=id; this->id=id;
@ -54,10 +54,6 @@ GwSerial::GwSerial(GwLog *logger, HardwareSerial *s, int id,bool allowRead):seri
this->readBuffer=new GwBuffer(logger, GwBuffer::RX_BUFFER_SIZE,bufName+"rd"); this->readBuffer=new GwBuffer(logger, GwBuffer::RX_BUFFER_SIZE,bufName+"rd");
} }
buffer->reset("init"); buffer->reset("init");
serial->onReceiveError([this](hardwareSerial_error_t err){
GwLog *logger=this->logger;
LOG_DEBUG(GwLog::ERROR,"serial error on id %d: %d",this->id,(int)err);
});
initialized=true; initialized=true;
} }
GwSerial::~GwSerial() GwSerial::~GwSerial()
@ -119,11 +115,21 @@ void GwSerial::readMessages(GwMessageFetcher *writer){
writer->handleBuffer(readBuffer); writer->handleBuffer(readBuffer);
} }
void GwSerial::flush(){ bool GwSerial::flush(long max){
if (! isInitialized()) return; if (! isInitialized()) return false;
while (write() == GwBuffer::AGAIN){ if (! availableWrite) {
if ( serial->availableForWrite() < 1){
return false;
}
availableWrite=true;
}
auto start=millis();
while (millis() < (start+max)){
if (write() != GwBuffer::AGAIN) return true;
vTaskDelay(1); vTaskDelay(1);
} }
availableWrite=(serial->availableForWrite() > 0);
return false;
} }
Stream * GwSerial::getStream(bool partialWrite){ Stream * GwSerial::getStream(bool partialWrite){
return new GwSerialStream(this,partialWrite); return new GwSerialStream(this,partialWrite);

View File

@ -16,17 +16,19 @@ class GwSerial : public GwChannelInterface{
int id=-1; int id=-1;
int overflows=0; int overflows=0;
size_t enqueue(const uint8_t *data, size_t len,bool partial=false); size_t enqueue(const uint8_t *data, size_t len,bool partial=false);
HardwareSerial *serial; Stream *serial;
bool availableWrite=false; //if this is false we will wait for availabkleWrite until we flush again
public: public:
static const int bufferSize=200; static const int bufferSize=200;
GwSerial(GwLog *logger,HardwareSerial *stream,int id,bool allowRead=true); GwSerial(GwLog *logger,Stream *stream,int id,bool allowRead=true);
~GwSerial(); ~GwSerial();
bool isInitialized(); bool isInitialized();
virtual size_t sendToClients(const char *buf,int sourceId,bool partial=false); virtual size_t sendToClients(const char *buf,int sourceId,bool partial=false);
virtual void loop(bool handleRead=true,bool handleWrite=true); virtual void loop(bool handleRead=true,bool handleWrite=true);
virtual void readMessages(GwMessageFetcher *writer); virtual void readMessages(GwMessageFetcher *writer);
void flush(); bool flush(long millis=200);
virtual Stream *getStream(bool partialWrites); virtual Stream *getStream(bool partialWrites);
bool getAvailableWrite(){return availableWrite;}
friend GwSerialStream; friend GwSerialStream;
}; };
#endif #endif