Go Down

Topic: Any chance serial drops zeros? (Read 1 time) previous topic - next topic

drspectro

Hey vputz
I got a test routine that will report errors on the UART running.   First cut is NOT pretty - requires editing the wiring serial file.
However it is only about 10 lines of code.  

There HAS to be a better way to link this, but as a quick test it seems to work.  I have tested by grounding the RX line while dumping data from Hyperterminal and it definitely throws an error.....  

No time tonight to upload, but I will get this posted tomorrow.   I am also going to try to figure out a clean way to do this as a separate library rather than editing wiring.  

drspectro

Kluge to check for serial receive errors -- seems to work on my bench top....

the status byte is ORed with the new status after every each character is received.  When you check the status after receiving a number of bytes, if the error bits are not set, then there were no errors.  If there were errors at any time since the previous status check the error bits will be set.  This is much faster than checking for errors after every byte and shouldnt throw off buffering too much.
The routine to read the status register resets the variable to 0 each time it is called.

Finally -- only bits 2-4 indicate errors. I mask them in the test program.  
**********************
NOTE this involves editing the wiring serial library.  Not something you want to do for your production code.   I dont know the "official" warnings on this, but be sure you make backup copies so you can put the original files back.

I am still researching the "correct" way to do this, and this shouldnt cause any problems as long as you put the original files back.
**********************

Part 1 - Edit wiring_serial.c
Code: [Select]

// this stuff is near the top of the files
int rx_buffer_head = 0;
int rx_buffer_tail = 0;
//  ********begining of first change*******
// new status variable here
byte status_reg = 0;

//function to return status byte
//status variable reset to 0 with each call
int serialStatus(void)
{
 int temp;
 temp = status_reg;
 status_reg = 0;
 return temp;
}
//  ******end of  first change*********
void beginSerial(long baud)

//**** second change ***********
//  skip further down the file to make this change
//  modify the interrupt/signal routine
// ****************************
#if defined(__AVR_ATmega168__)
SIGNAL(SIG_USART_RECV)
#else
SIGNAL(SIG_UART_RECV)
#endif
{
#if defined(__AVR_ATmega168__)
     unsigned char c = UDR0;
#else
     unsigned char c = UDR;
#endif
// ************ begin second change *********
//get status byte
              status_reg = status_reg | UCSR0A;
//************  end second change  **********
     int i = (rx_buffer_head + 1) % RX_BUFFER_SIZE;

     // if we should be storing the received character into the location
     // just before the tail (meaning that the head would advance to the
     // current location of the tail), we're about to overflow the buffer
     // and so we don't write the character or advance the head.
     if (i != rx_buffer_tail) {
           rx_buffer[rx_buffer_head] = c;
           rx_buffer_head = i;
     }
}



Part 2 -- edit wiring.h
Code: [Select]

// you should problably put this near the other serial declarations
int serialStatus(void);


Part 3 -- Demo program
Code: [Select]

// reads a serial character then echos it back
// checks the status byte before each read
// you really should only check status at the end of a packet
// the delays are probably not necessary
int read_char;
int status;
void setup()
{
 Serial.begin(9600);
 
 // prints title with ending line break
 Serial.println("Serial Test");

 // wait for the long string to be sent
 delay(100);
 
// pinMode(ledPin, OUTPUT);
 
}


void loop()
{
 if (Serial.available() > 0)
 { status = serialStatus();
// only bits 2-4 indicate errors  mask the others with 0x1C
// bit 2 = parity
// bit 3 = data overrun
// bit 4 = frame error
   status = status & 0x1C;
   read_char = Serial.read();
   Serial.print("*");
   Serial.print(read_char, BYTE);
   delay(100);
 }
else
  {delay(25);}

if (status != 0)
 {Serial.print("#");
  Serial.print(status);
  Serial.print("#");
 }
}

vputz

Nice work, drspectro--if I have time I'll give it a run this weekend.  The app is for more general deployment so I'll probably stick with what I've got (ie check for errors at the packet level rather than byte level) but this is a good addition to the toolkit.

drspectro

Thanks vputz
If you get a chance to try this for a test I would be really curious what you find out.  I tested with a dead short, so it will be interesting to see how a more realistic failure looks.

I posted in the software section for how to code this "legally"; or if it would be a candidate for a core change.   I think the best "legal" way to do this is to essentialy copy the wiring_serial library to a new name say "test_serial" with new function names.   Then as long as you only used functions from the new library, the orignial library should not link.

Only problem is, I cant figure out how to make it compile when I do the rename.

Go Up