Go Down

Topic: Add error checking to hardware serial library (Read 907 times) previous topic - next topic


I am working on some extensions to the serial library (error handling, set parity and word length).   Currently I think I am going to have to copy and rename every function in wiring_serial into a new library.   I have this working as a hack to wiring_serial, but I cant find an better way to do this.
FYI - as far as I can tell you cant simply read the UDR0 register from loop because it is cleared as the UART receives each new character.  It has to be read before the character is read.

Two questions:
1) please confirm that there is no way to "chain" an existing interrupt handler.  It looks like the compiler will only allow one ISR to a given interrupt.  When I say one ISR, I mean define the first ISR, grab a pointer to it, then re-define it with an second ISR which calls the original routine with a function pointer.   (standard interrupt chaining)  I was going to try this in inline assemler when I realized the interrupt vectors are stored in flash and could only be modified at great risk.  Basically, this is a useful capability, but the best way to get there seems to be to edit wiring_serial.  Anything else is even uglier -- creating a copy of wiring_serial with all different names etc.....

2) I would like to seriously propose the following mod to wiring_serial, this adds a couple of instructions and one byte variable, but it allows reasonable error checking on serial reads.  Basically the error byte is ORed until it is used so it indicates any errors for a group of serial reads.   Much faster than checking for errors after each read.

more info here or I can repost

Proposed changes
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__)
#if defined(__AVR_ATmega168__)
     unsigned char c = UDR0;
     unsigned char c = UDR;
// ************ 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;

Go Up