how to use HardwareSerial::_rx_complete_irq to store data?

i want to use 4 hardware serial port in Mega2560,the uart rx interrupte code as follow,and all ports share this handle. the receive data store in _rx_buffer[] and it is defined in the hardwareSerial Class. how to define my data array and store the data by this interrupt routing? Donot change the original source.

void HardwareSerial::_rx_complete_irq(void)
{
  if (bit_is_clear(*_ucsra, UPE0)) {
    // No Parity error, read byte and store it in the buffer if there is
    // room
    unsigned char c = *_udr;
    rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_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;
    }
  } else {
    // Parity error, read byte but discard it
    *_udr;
  };
}

and all ports share this handle.

No, they don't. Each has it's own copy of that method.

The data is stored in the buffer, where SerialN.available() will tell you how much data it contains.

Why do you think you need to know the nanosecond that a byte of serial data is added to the buffer?

PaulS: No, they don't. Each has it's own copy of that method.

The data is stored in the buffer, where SerialN.available() will tell you how much data it contains.

Why do you think you need to know the nanosecond that a byte of serial data is added to the buffer?

i need to make a CLI, to check the command finish byte,for example "\r\n".

waysleehh: i need to make a CLI, to check the command finish byte,for example "\r\n".

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data.

Just use a separate copy of the function for each hardware serial port that you want to use.

If your incoming data is terminated with \r\n in that order I would just treat the \n as the end-marker and afterwards discard the unwanted \r

...R

i need to make a CLI, to check the command finish byte,for example "\r\n".

Why do you need to know the nano-second that that character arrives? You couldn't DO anything about it until after the ISR finishes, anyway.

As long as you structure loop() so that it doesn't block (no delay(), no while statements that take forever, etc.), loop() will execute thousands of times per second, and you'll know, nearly as soon, as if you had learned it in the interrupt, AND you'll be able to do something with the Serial data.

PaulS: Why do you need to know the nano-second that that character arrives? You couldn't DO anything about it until after the ISR finishes, anyway.

As long as you structure loop() so that it doesn't block (no delay(), no while statements that take forever, etc.), loop() will execute thousands of times per second, and you'll know, nearly as soon, as if you had learned it in the interrupt, AND you'll be able to do something with the Serial data.

in my oppinion,loop() act as while(1),execute the funcitons one by one,is that right?

That is basically correct. Loop() is continuously called inside an endless loop in main().

Robin2: Have a look at the examples in Serial Input Basics - simple reliable ways to receive data.

Just use a separate copy of the function for each hardware serial port that you want to use.

If your incoming data is terminated with \r\n in that order I would just treat the \n as the end-marker and afterwards discard the unwanted \r

...R

actually, I have done this job finished in 1.0.6,it works well.The Serail ports' data received in four gloable variable,defined by hardwareserial.cpp.

when i turn to 1.6.9,the hardware serial library changed.with my poor C++ knowlege,i donot know where to get the Serial ports' data,even i do know four ports share one object method,there are none rx_buffer globle variables,should i define manually?

You are getting way to chummy with the internals of hardware serial. If you don't want code to break, use the published interface.

KeithRB: That is basically correct. Loop() is continuously called inside an endless loop in main().

so, if some functions in the loop() waste too much time to deal with,but that time some serial data comming,i must use ISR,instead of in the loop() to receive serial data.

KeithRB: You are getting way to chummy with the internals of hardware serial. If you don't want code to break, use the published interface.

I don't want to change the original source code of arduino,rather than in 1.0.6,so i need some one to teach me how to use the hardwareserial method in 1.6.9,how to get the received data on more than one ports?

I don't want to change the original source code of arduino

You would have to, to add capability to the method that you showed.

i need some one to teach me how to use the hardwareserial method

The method that you showed is called by the arrival of serial data on the port. That action triggers the ISR that you posted. NOTHING that you can do will cause that method to be called. You can not call that method from your code.

waysleehh: so, if some functions in the loop() waste too much time to deal with,but that time some serial data comming,i must use ISR,instead of in the loop() to receive serial data.

Only if you are going to overrun the buffer. That is the whole point of the ISR. Darn those functions in loop() that take too much time!

Oh, wait, you have total control over that!

Oh, wait, you have total control over that!

So, how do I make server.connect() faster?

By calling it judiciously. You can at least call it right after you have emptied the buffer.

PaulS: You would have to, to add capability to the method that you showed. The method that you showed is called by the arrival of serial data on the port. That action triggers the ISR that you posted. NOTHING that you can do will cause that method to be called. You can not call that method from your code.

i do know this!

perhaps my express info mistake all of you,my simple question is: where can i take these data out in the ISR received,because there are none global varialbes,which exsit in 1.0.6

//1.0.6 serial buffer define 
#if defined(USBCON)
  ring_buffer rx_buffer = { { 0 }, 0, 0};
  ring_buffer tx_buffer = { { 0 }, 0, 0};
#endif
#if defined(UBRRH) || defined(UBRR0H)
  ring_buffer rx_buffer  =  { { 0 }, 0, 0 };
  ring_buffer tx_buffer  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR1H)
  ring_buffer rx_buffer1  =  { { 0 }, 0, 0 };
  ring_buffer tx_buffer1  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR2H)
  ring_buffer rx_buffer2  =  { { 0 }, 0, 0 };
  ring_buffer tx_buffer2  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR3H)
  ring_buffer rx_buffer3  =  { { 0 }, 0, 0 };
  ring_buffer tx_buffer3  =  { { 0 }, 0, 0 };
#endif

in 1.6.9, four serial ISRs all called like this,take Serial1 for example.

ISR(UART1_RX_vect)
#elif defined(USART1_RX_vect)
ISR(USART1_RX_vect)
#else
#error "Don't know what the Data Register Empty vector is called for Serial1"
#endif
{
  Serial1._rx_complete_irq();
}

waysleehh: when i turn to 1.6.9,the hardware serial library changed.with my poor C++ knowlege,i donot know where to get the Serial ports' data,even i do know four ports share one object method,there are none rx_buffer globle variables,should i define manually?

It seems to me you are grossly over-thinking this. Just use the Serial commands to access the data. AFAIK the API is unchanged between 1.06 and 1.6.x

Did you look at the code in the link I gave you?

...R

KeithRB: By calling it judiciously. You can at least call it right after you have emptied the buffer.

Sorry, that does not always work.

Any time a library takes too long to do something, serial data can be lost. Depending on baud rates, "taking too long" can be as short as 6ms to 65ms. For example, writing to an SD card can take 100ms. If serial data is being received during that time, there is no way to avoid input buffer overflow with the standard Arduino libraries. Ok, there is one way, but is a little silly.

Restructuring a library so it blocks for a shorter period is rarely feasible. Changing the code structure from linear to interrupt-driven can be "challenging" if not impossible. This is the same Serial Input Basics problem we see over and over again.

The solution to input buffer overflow depends on what is being done with the serial data:

1) If you are just saving the raw characters so they can be forwarded or written to some device, you might as well increase the input buffer size. Go edit HardwareSerial.cpp (or associated files).

2) If you are parsing the characters into a more compact form (e.g., an int), the characters should be processed during the RX interrupt. Go get NeoHWSerial and call:

    NeoSerial.attachInterrupt( parsingFunction );

I do not think the OP should use this for parsing a command.

Cheers, /dev

@waysleehh, the typical loop polling should be fine, as stated in Robin2's reply #3. Cut and paste that example to work for 4 serial ports. You have given no reason that you need interrupts, and accessing the input buffers directly is a violation of the interface. Staaahhp. Reeeead Reply #3.

Cheers, /dev

Did you look at the code in the link I gave you?

of course i did! it's useful,and i also put it in a loop() for testing.thank you.

finnally, i changed the HardwareSerial.cpp/h files to achive my goal.using the Hardware ISR to receive the Serial data. it now working fine,just as 1.0.6 did.