Hi,
Here the modified code to start/stop the buffering process, after 1 week of test "on field" all is ok.
SerialBuffered.cpp
SerialBuffered::SerialBuffered( size_t bufferSize, PinName tx, PinName rx ) : Serial( tx, rx )
{
m_buffSize = 0;
m_contentStart = 0;
m_contentEnd = 0;
m_timeout = 1.0;
flagStopSerialBuffered = true;
attach( this, &SerialBuffered::handleInterrupt );
m_buff = (uint8_t *) malloc( bufferSize );
if( m_buff == NULL )
{
//loggerSerial.printf("SerialBuffered - failed to alloc buffer size %d\r\n", (int) bufferSize );
//debugNewLine("SerialBuffered - failed to alloc buffer\n");
}
else
{
m_buffSize = bufferSize;
}
}
void SerialBuffered::stop()
{
flagStopSerialBuffered = false;
}
void SerialBuffered::start()
{
flagStopSerialBuffered = true;
}
void SerialBuffered::flush()
{
m_contentEnd = 0;
m_contentStart = 0;
}
SerialBuffered::~SerialBuffered()
{
if( m_buff )
free( m_buff );
}
void SerialBuffered::setTimeout( float seconds )
{
m_timeout = seconds;
}
size_t SerialBuffered::readBytes( uint8_t *bytes, size_t requested )
{
int i = 0;
for( ; i < requested; )
{
int c = getc();
if( c < 0 )
break;
bytes[i] = c;
i++;
}
return i;
}
int SerialBuffered::getc()
{
m_timer.reset();
m_timer.start();
while( m_contentStart == m_contentEnd )
{
wait_ms( 1 );
if( m_timeout > 0 && m_timer.read() > m_timeout )
return EOF;
}
m_timer.stop();
uint8_t result = m_buff[m_contentStart++];
m_contentStart = m_contentStart % m_buffSize;
return result;
}
int SerialBuffered::readable()
{
return m_contentStart != m_contentEnd ;
}
void SerialBuffered::handleInterrupt()
{
if (flagStopSerialBuffered == true) //la reception est active
{
while(Serial::readable())
{
if( m_contentStart == (m_contentEnd +1) % m_buffSize)
{
//debugNewLine("SerialBuffered - buffer overrun, data lost!\n");
Serial::getc();
}
else
{
m_buff[ m_contentEnd ++ ] = Serial::getc();
m_contentEnd = m_contentEnd % m_buffSize;
}
}
}
else
{
//Received caracter need to be read !
Serial::getc()
}
}
SerialBuffered.h
#pragma once
// This is a buffered serial reading class, using the serial interrupt introduced in mbed library version 18 on 17/11/09
// In the simplest case, construct it with a buffer size at least equal to the largest message you
// expect your program to receive in one go.
class SerialBuffered : public Serial
{
public:
SerialBuffered( size_t bufferSize, PinName tx, PinName rx );
virtual ~SerialBuffered();
int getc(); // will block till the next character turns up, or return -1 if there is a timeout
int readable(); // returns 1 if there is a character available to read, 0 otherwise
void setTimeout( float seconds ); // maximum time in seconds that getc() should block
// while waiting for a character
// Pass -1 to disable the timeout.
size_t readBytes( uint8_t *bytes, size_t requested ); // read requested bytes into a buffer,
// return number actually read,
// which may be less than requested if there has been a timeout
void stop();
void start();
void flush();
private:
void handleInterrupt();
uint8_t *m_buff; // points at a circular buffer, containing data from m_contentStart, for m_contentSize bytes, wrapping when you get to the end
uint16_t m_contentStart; // index of first bytes of content
uint16_t m_contentEnd; // index of bytes after last byte of content
uint16_t m_buffSize;
float m_timeout;
Timer m_timer;
bool flagStopSerialBuffered;
};
Init in main.cpp for example :
SerialBuffered *serialStream = new SerialBuffered(100, p13, p14);
serialStream ->baud( 1200 );
serialStream ->format(7,serialStream->Even,1);
serialStream ->setTimeout( 1 );
serialStream ->stop();
To start the buffer process, use the serial and stop the buffering process :
serialStream->flush();
serialStream->start();
//Here your "serial" parsing code...
serialStream->stop();
Thank you Andy for your idea.
Chris.
Hi !
I have some trouble in the serial stream decoding in my datalogger, i use the Richard Sewell's SerialBuffered code, and it's much better, thank you Richard.
I could initialize the object and use all functions, now my serial stream decoding routine works very well, but how to "stop" the SerialBuffer interrupt ? my datalogger catch a serial stream, after decoding i need to do lots of thing in the decoded data, send the data on a SdCard, on the net, ...
With the original Richard's code, the buffer continue to grown and be full very quickly if i stop to read the serial, and the code never go out from the interrupt (SerialBuffered::handleInterrupt())
I would like to start/stop the "buffering process" when i want or create/destroy the SerialBuffered object when i need to read my serial stream.
Richard use attach( this, &SerialBuffered::handleInterrupt ); in the class constructor, is it possible to "detach", or destroy the object and to be sure the interrupt is stopped ?
I'm not very comfortable with mBed...
If you have an idea.
Thank you.
Chris.