It is quite possible that while reading in serial data, something could screw it up and lead to garbage coming across and being stored.
How so? Whilst error detection/correction is pretty much required in low level wireless applications, your GSM will do the over-the-air error handling. The only possible errors you could get are between the GSM module and microcontroller. Unless there is a long cable, a bad connection, massive interference, or mismatched clocks, errors on a serial line are rare. I wouldn't worry about checking the serial data for errors - unless you mean typo's in your SMS commands? In which case reading it in twice won't make a difference.
I understand your thinking - "what if" scenarios are good to try and catch possible problems with robustness before they start, but error checking the serial line is most likely a waste of time.
First things first - get something working. A few of has have provided a rough outline:
- Interrupts to handle reading in the data, setting a flag for the main routine when you reach the end of the message.
- Main routine scans through message to find commands, and either processes them as it finds them, or sets flags (one for each command) and stores data for them
- then, if you haven't done so, go through each command.
So to start with, the interrupt routine. You could create a second software UART on your AVR as debug, that spits back out the SMS it just read in, to check that the interrupt works, and it raises a flag once it has got to the end of the message.
Then a routine to check for "commands". Are you deciding on the format of these commands or are they some sort of standard? Assuming that each command starts on a new line, you can use the CR (carriage return 0x0D) character as a place to check for known commands.
Then of course is just a routine for each command.
I think many of us here have done something similar - perhaps with varying complexity - and there is more than one way to go about it, as you've found. With an 8-bit micro, things like message queues, whilst robust, might be rather bloated. But then again the '328 has a whopping 32KB of flash.
Re: circular buffer. A circular buffer has two pointers, or 'heads' as some people call them. One write pointer, which points to the location where data is to be written, and one read pointer. When you write to it, you simply write a value to the array entry the write pointer is pointing to, then increment the write pointer. And with reading, you read the value that the read pointer is pointing to, then increment the pointer. There are ways to handle over-run and under-run, as well as bounds (if your array has 16 entries, values 0 to 15, then you want to make sure your value is within that). It can get quite complicated, but often they are fairly simple.
In your case, if you can afford the RAM usage - assuming your 90 character limit - I would just read in the entire message, perhaps store the message size. If you're expecting to receive a message whilst handling the previous one, then a ping pong buffer could be used. That simply means, one buffer is used to read in a message, once it has been read, the micro flags that buffer to be the one to be read, whilst falging the other buffer to be used to read in another message. So it ping pongs between buffers - you can read in another message, whilst handling the other. With 2KB of SRAM on the atmega, 180 bytes isn't much for the buffer.