I'd need to set individual ring buffer sizes in hardware serial library.
Can anyone advise how to cahnge the HardwareSerial code to do this.
I've tried hacking it but my current knowledge of c isn't adequate. I'm not using Serial2 and 3 and I have managed to exclude these and this sves some RAM but I'd real;ly like Serial to have asmall riung buffer whilst Serial1 has a large one > 1024.
Any help appreciated.
Why?
RX_BUFFER_SIZE is a constant across all serial objects.
You'd have to add a member variable to the class, initialise that with "begin" and modify the source to use the variable instead of the constant.
Edit: oops, and modify the ring_buffer initialisation to malloc the memory for "buffer".
In fact, I think ring_buffer is the thing to modify.
Again, really, why?
Thanks for the response.
Why... I'm running very low on RAM. I have a high speed serial input with no flow control on SERIAL1 and lots of work to do once a receive a complete message.
Why... I'm running very low on RAM
So, instead of using 2 * 128 bytes of RAM, you want to use 1024 + x bytes of RAM?
Yes, because 128 bytes overflows before my message processing code can get back to service the SERIAL1 buffer. As I understand it I can't get an interrupt when this buffer is near full.
In any case I'm using an Ethernet shield and I guess that may take preference?
So even if I split my processing task into sections, polled the buffer to find out how near full it is, and double buffered the incoming serial stream I don't think it would work.
Serial (0) is only used for outgoing diagnostics so I really don't need an input buffer at all on that. So 1024 + 0 would do.
So 1024 + 0 would do.
But that's still four times more memory than you're using at the moment, and you say you're running short of RAM.
Why not just read it more frequently, and do your buffering in your sketch?
Thanks for that suggestion. I've now implemented a 4ms Timer2 interrupt routine to empty the serial ring buffer into my own 1024 character buffer. This works fine (once I realised that I'd have to use ISR_NOBLOCK to allow the UART to interrupt the Timer2 interrupt routine and not miss incoming characters).
Thanks for the help.
I am working on exactly the same task with exactly the same issue. I am using a 644P with two hardware serial ports and therefore some wasted buffer space as well. The 644P has only 4kb RAM, so I didn't create a different buffer, but I'm switching to the 1280 because I am very low on RAM. I also looked at reducing the size of the unneeded buffers but realized with it would only save me as much as 128 bytes, not enough.
My plan for after the switch to the 1280 is to hack HardwareSerial.cpp to increase the appropriate buffer to 256 bytes. For now I found a different solution, but if you would post the code that empties the 128 byte buffer that wiuld be really great.
How fast is your data coming in? Mine is binary data streaming non-stop at 19,200.
How can you say that 4Kb of RAM is not enought?
A ton of strings in RAM or what?
Senso:
How can you say that 4Kb of RAM is not enought?
A ton of strings in RAM or what?
I don't know, how can you say 20 cubic inches is not enough? How about 30 square feet? 1 mile? It all depends upon what you're doing. 1 mile is plenty of space for my yard, but if you're flying airplanes you need a 5 mile separation.
It is entirely conceivable that someone can write an app that needs more than 4KB of RAM.
In my case I need to maintain a table of data that can be read with very high performance. The contents are not known at compile time so progmem is out, and EEPROM on this chip is not big enough anyhow because the data is at least 1,500 bytes and some are bigger.
Throw in a stream of data coming in at high speed and you need a good size buffer. Throw in a lot of variables, even the narrowest types possible for any given purpose, and it all adds up. Before you know it, you're low on RAM.
Below is an extract from my code for an Arduino Mega 2560. It declares a ring buffer, initialises Timer2 to have a 256 prescaler and interrupt on overflow. The Timer2 ISR transfers characters from the SERIAL1 buffer (could be adapter to other ports). The main loop code is just a diagnostic but I hope it shows how one could access characters in the 1280 character ring buffer.
In my application the baud rate is 56,700. Arduino Mega 2560 runs at 16 Mhz and if prescaler is set to 256 and Overflow occurs at 256 counts. So there are 16,000,0O0/(256 * 256) = 244 Overflows per second or a period of 4 ms. 57,600 baud, ~ 6000 characters/s, ~24 characters in 4 ms
My program uses nearly 8K of RAM and none of my strings are in RAM. I've just got to have lots of dynamically accessible arrays for the data processing I'm doing. Is there an extension RAM shield? The ratio of RAM size to code size on a Mega 2560 seems imbalanced - I'm only using 55,244 of code of the available 258,048, yet I'm pinched on RAM.
I've hacked the HardwareSerial driver to eliminate ring buffers not used. This can save n * 128 bytes of RAM (n is number of buffers eliminated). I don't use SERIAL2 or SERIAL3.
Code extract...
In the sketch's .h file
#define BUFFER_SIZE 1280
struct ring_buffer
{
unsigned char buffer[BUFFER_SIZE];
int writeIndex;
int readIndex;
}
In the sketch:
...
char incomingByte;
boolean bufferFull;
ring_buffer rxBuffer = {{0}, 0, 0};
...
void setup()
{
...
//Timer2 Settings: Timer Prescaler /256, WGM mode 0
TCCR2A = 0;
TCCR2B = 1<<CS22 | 1<<CS21;
//Timer2 Overflow Interrupt Enable
TIMSK2 = 1<<TOIE2;
//reset timer
TCNT2 = 0;
sei();
...
}
void loop()
{
...
if (bufferFull) {
Serial.println("buffer full"); // diagnostic only - probably want to do something more useful with the error
bufferFull = false;
}
while (charactersAvailable() > 0) {
incomingByte = rxBuffer.buffer[rxBuffer.readIndex];
rxBuffer.readIndex = (rxBuffer.readIndex + 1) % BUFFER_SIZE;
Serial.print(incomingByte); // diagnostic only - probably want to do something more useful with the incoming bytes
}
...
}
//****************************************************************
// Aruino Mega 2560 runs at 16 Mhz and if prescaler is set to 256 and Overflow occurs at 256 counts,
// so there are 16,000,0O0/(256 * 256) = 244 Overflows per second or a period of 4 ms
// 57,600 baud, ~ 6000 characters/s, ~24 characters in 4 ms
//
ISR(TIMER2_OVF_vect, ISR_NOBLOCK) { // ISR_NOBLOCK allows UART interrupts to be serviced immediately
char c;
int i;
// if we should be storing the received character into the location
// just before the readIndex (meaning that the writeIndex would advance to the
// current location of the readIndex), we're about to overflow the buffer
// and so we don't write the character or advance the writeIndex.
while (Serial1.available() > 0) {
c = Serial1.read();
i = (rxBuffer.writeIndex + 1) % BUFFER_SIZE;
if (i != rxBuffer.readIndex) {
rxBuffer.buffer[rxBuffer.writeIndex] = c;
rxBuffer.writeIndex = i;
}
else {
bufferFull = true;
}
}
}
uint16_t charactersAvailable() {
return ((BUFFER_SIZE + rxBuffer.writeIndex - rxBuffer.readIndex) % BUFFER_SIZE);
}
KineticaRT:
My program uses nearly 8K of RAM and none of my strings are in RAM. I've just got to have lots of dynamically accessible arrays for the data processing I'm doing. Is there an extension RAM shield? The ratio of RAM size to code size on a Mega 2560 seems imbalanced - I'm only using 55,244 of code of the available 258,048, yet I'm pinched on RAM.I've hacked the HardwareSerial driver to eliminate ring buffers not used. This can save n * 128 bytes of RAM (n is number of buffers eliminated). I don't use SERIAL2 or SERIAL3.
Thanks!!
You may want to have a look at the Atmel 1284P. It has only two hardware serial ports but it has 16K of internal sram and clocks up to 20 MHz! I'm in the process of switching to it. Thanks to Crossroads who pointed it out to me.
I was going to say the same thing until I read to the bottom and saw you had already recommended it ![]()
1284P all the way - I am using one at the moment.
Thanks for the recommendation. Unfortunately I've already purchased a few original Arduino Mega 2560s for my project. Next time I'll look at the 1280P; but is there an off-the-shelf Arduino compatible board that uses a 1280P?
Sorry I meant to say 1284P. So many numbers...
Well, I guess not really. There is this:
If you could find a board with a DIP 644P you could swap it for the 1284P, since the two are pin compatible. You would have to install the boot loader.
If you want a cheap development board for the 1284P, these are available from places like Sparkfun.
This Olimex board is actually designed for the old ATMega8535, however that is pin compatible with the 644P and the 1284P.
I have 2 of these and they are great. They have ICSP and JTAG (if you want JTAG), with socketed crystal so you can put in whatever you want easily, and RS232 etc. Very handy.
I just soldered on a FTDI header and put a cap in and away you go, ICSP to put the bootloader in etc.
Obviously not plug compatible with the Arduino, however that may not be an issue.
Thats a nice board!
Crossroads is selling one of them.
Constantin:
Crossroads is selling one of them.
One of what?