I have playing around with the idea of being able to write a custom Hardware Serial library like the SoftwareSerial library but can't seem to find the appropriate resources to get started. The problems I have been facing can be listed down below:
HardwareSerial default library in Arduino seems to be instantiated automatically by Arduino at runtime which would mean defining a separate instance using the default Hardware based serial communication (on pins D0 and D1, for example) very messy.
Is there any existing examples of an external library which is able to control the Hardware Serial on Arduino and define custom buffers and ISRs?
"Messy" is a good description. AVR interrupt vectors are defined at compile-time, have standard names, and are stored in flash, so once you include the arduino core, specifying your own ISRs is indeed messy.
Your best bet it to be willing to modify the Arduino core source, either to completely exclude the existing HW Serial code, or make the existing symbols "weak" so that user code overrides it.
Thanks westfw, I had the same feeling. The biggest factor I am trying to address is a way to obtain the data independent of the loop and delay inside loop which currently seems to be not possible because only Serial.dataavailable() method seems to be available to check for incoming data (and runs inside the loop) which will get limited based on user delay introduced and even end up losing serial data. If instead I could handle the data and store it in a buffer until the next loop runs that would solve this issue. Is there a way to maybe run a timed interrupt/handler inside a library and store the serial data there whenever it is available and then pass the latest data to the user using a custom library data available interface?
If instead I could handle the data and store it in a buffer until the next loop runs that would solve this issue.
The existing code DOES buffer 64bytes, and it's relatively trivial to increase that if all you need is a bit extra time.
Eliminating delays larger than 64 character times from you loop() might be more worthwhile.
There is already mechanism to save received data to the Rx buffer. Of course, it works during the delay also but the buffer is too short to keep bigger amount of data.
The solution for you could be to use millis() instead of delay() but the algorithm will be more complicated in result.
Another solution is to run yield() function during the delays and test for serial data or read out the data in this function. I think, it is less complicated algorithm for more complex program. The yield() is "predefined". All you need is to write your yield() implementation.
The last possibility, I think, is to use some of RTOS developed for the Arduino.
sidpil91:
The biggest factor I am trying to address is a way to obtain the data independent of the loop and delay inside loop which currently seems to be not possible because only Serial.dataavailable() method seems to be available to check for incoming data (and runs inside the loop) which will get limited based on user delay introduced and even end up losing serial data.
Programs should be written so that loop() can repeat hundreds or thousands of times per second. There is no reason that I can think of for needing a very slow loop() repeat frequency. Things that need it can be timed without blocking using millis() as illustrated in Several Things at a Time.
The examples in Serial Input Basics empty the serial input buffer every time they are called and will set a variable when the end of the message is detected. The code in the demo uses a 32 byte buffer but that can easily be extended.
If you really really do need to have long intervals between repeats of loop() then you can increase the size of the Serial Input Buffer.
If instead I could handle the data and store it in a buffer until the next loop runs that would solve this issue. Is there a way to maybe run a timed interrupt/handler inside a library and store the serial data there whenever it is available and then pass the latest data to the user using a custom library data available interface?
In general, you should handle the data as soon as possible. "Storing" the data for later use requires more precious RAM, as others have said. If only there were a way for you to do something like Serial.attachInterrupt...
... oh wait, I did that. Take a look at NeoHWSerial. It is the core HardwareSerial with one new method, attachInterrupt. You register a function that handles each character during the ISR. This is actually more efficient, because it saves copying the characters into the RX buffer, returning from the ISR, checking available from loop, and copying the characters out of the RX buffer.
And, like others have said, this is really a last-resort technique. If you are using delay, or you are using a while loop to wait for something, you need to restructure your program
If you are using a library that cannot be restructured (e.g., SdFat), and it takes a long time to complete some operation (e.g., a write can take 100ms), then the interrupt approach is the only way to avoid using extra RAM.
If switching cores is an option, I cannot recommend Cosa highly enough. It is object-oriented C++, correctly designed, cleanly coded and it supports almost all the hardware you would ever use. Its serial class allows attaching to the ISR.
Cheers,
/dev
Ironic note: The serialEvent routines used to be called from the ISR.