Uart input - reading with generator - possibly crashes depending on baud rate

hi all,

I have a Moteino board connected to imp001. Moteino has a 433 MHz radio and I am using the imp001 Device as a bridge to get the packets to the agent. The Moteino radio packet has up to 61 bytes. I added a 4-byte header and footer.

The code below works fine, nominally. However, when I started to test it by sending bad packets and also when I was at a higher baud rate the device would appear to get stuck and not read any more serial input. Also, it would often reboot on its own and this is not something I am used to seeing.

I experimented with lower and lower baud rates until I arrived at 14,400. Seems to work now. I can send a packet over uart that does not have the correct footer and the code will recover. I plan to experiment with other malformed packets and also set up two Moteino board to each send data. Possibly have one send good data and the other send bad data - though less frequently.

Generators are pretty tough for me to understand but I think my code started with a cut/paste from the imp community. One thing that bothers me is that it seems inefficient to read one byte, suspend the generator - wait for a callback from the uart, and start all over. So my questions;

  • is there a better concept that I should have done for reading the uart?
  • what could I look for so far as causes for the Device reboots? I had logged the imp.getmemoryfree() but I had a suspiction that this call may have actually caused my serial port issues by hogging resources.

`//Reads bytes from the serial port and echos to the agent.
//2014 November 19
//

//-------------------------UART CODE-------------------------{

//This is our UART function - it is implemented using the construct of “generator”

const _header = -1; // 0xFFFFFFFF header integer (32 bit signed)
const _footer = -16711936;// 0xFF00FF00 footer integer (32 bit signed)

imp_uart <- hardware.uart57;

function uart_generator(){

local headerorfooter = 1;

local returncode = null;
  local mybyte=0;
  
  local _blob = blob(65);//Big enough to handle the payload size of RFM69 radio (61 bytes) + a little more

while (true){
    
  returncode = null;
    
	  mybyte = imp_uart.read();
	  headerorfooter = ((headerorfooter<<8) | mybyte);//just keep shifting bytes in
	  
    if (headerorfooter == _header){     //until the header number is seen (4 bytes in a signed 32 bit integer equalling minus 1)
        
        _blob.seek(0,'b'); //pointer to beginning of blob
        
        headerorfooter=1;
        yield null;//1;//leave the loop here - it will resume when a new char comes in
       
        while (true){
          
          
            mybyte = imp_uart.read();
           
                
                headerorfooter = ((headerorfooter<<8) | mybyte);//just keep shifting bytes in
                if (headerorfooter == _footer){ 
                    
                   //put the result out and reset the result
                    headerorfooter=1;
                    
                    returncode =_blob;// sent to the calling function to indicate the progress
                    
                    break;
                    
                }
                
                else { 
                    
                    _blob.writen(mybyte,'b');//
                    
                    if (_blob.tell()>63){
                      _blob.seek(0,'b');
                     
                      headerorfooter=1;
                      returncode=null;
                     
                      server.log("bad packet");
                     
                      break;
                    }

                    yield null;//2;
                   
                }//end else
                          
        }//end while
    }
    yield returncode;//loop until you find the header
}

}

_uartReader <- uart_generator();

function call_uartReader (){

/*
results will come back as null until the generator senses first a header
and then a footer

it returns a blob which should be equivalent to the struct in the C code

it will have 3 extra bytes from the footer but these can just remain
unused
*/
local uart_result = 0;

uart_result = resume _uartReader;  //Calls the Generator to read the UART


if (uart_result){ //everything but null seems to be true
   
   
    agent.send("datapacket", uart_result);//a blob containing a single packet
    //acknowledge back to sending microcontroller that the packet came in
    imp_uart.write(0x21);//ack
    
    
}

}

//14400 is the fastest baud
local _speed = imp_uart.configure(14400, 8, PARITY_NONE, 1, NO_CTSRTS,call_uartReader);//

//}

function beat(){
server.log(“beat 20m”);
imp.wakeup(1200.0 beat);
}
beat();
`

Was there anything in the IDE device log about the restart reason? Can you please DM with the mac address? Thanks!

I don’t recall seeing any information about the restart reason.

I think you might need to watch out for uart.read() returning -1 when there are no bytes available, but when I run your code I also see:

[Exit Code] imp restarted, reason: error recovery

which looks like you might have found an impOS bug. I’ll raise a ticket.

ok, thanks for the quick help! I’ll work on handling uart reads that return -1

on second thought… I cannot treat -1 returned from uart.read() as an error because I am sending bytes through that port. A valid byte can be 0xFF so it seems that cannot help me.

I just checked my code and I think it only does one uart.read() for each callback so by definition there is data present.

IIRC, if you have

local value = hardware.uart12.read()

then if value equals 0xFF, that’s not an error, i.e. 0xFF is not -1. Squirrel integers are 32-bit signed, so -1 is actually 0xFFFFFFFF.