![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
Help with string construction |
Posted: Mon Jul 27, 2015 8:58 pm |
|
|
Hi Guys,
I'm trying to read some data from uart.
the exact length of received data is not fixed and end of data is identified by a delimiter.
I'm just wondering is there any memory efficient way to store the incoming packet (so that it only allocates just enough memory to hold the particular data), instead of using a one large char array assuming the maximum length a packet can have?
Thanks ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Tue Jul 28, 2015 12:35 am |
|
|
It's not going to be any more 'efficient' in terms of memory usage. Enough space is going to have to exist for the worst case somewhere, and dynamic allocation will mean more code, and more time.
Obviously what matters is that there is a known 'worst case'.
However do you have to store the string?.
I commonly don't. Instead use a 'parser'. A small circular buffer, just to allow for not being able to keep up at times, and code that is called whenever data is in this, walking forward through the data. So you start at the beginning on the message (state=START). Then as each character is received, the parser walks along, looking for particular keywords (state=SEARCH). When one is found and matched it takes the value and stores it in the corresponding variable (state=GETNUM, index=variable). When the delimiter is seen, all the values have already been extracted, checksum tested etc..
It's pointless to waste space holding a long string if you only want values from it. Even better, since the parser only handles one character at a time, it is fast, compared to the work of having to scan through the string in one go, after the whole message arrives.
Just a thought. |
|
![](templates/subSilver/images/spacer.gif) |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Tue Jul 28, 2015 2:47 am |
|
|
Ttelmah wrote: | It's not going to be any more 'efficient' in terms of memory usage. Enough space is going to have to exist for the worst case somewhere, and dynamic allocation will mean more code, and more time.
Obviously what matters is that there is a known 'worst case'.
However do you have to store the string?.
I commonly don't. Instead use a 'parser'. A small circular buffer, just to allow for not being able to keep up at times, and code that is called whenever data is in this, walking forward through the data. So you start at the beginning on the message (state=START). Then as each character is received, the parser walks along, looking for particular keywords (state=SEARCH). When one is found and matched it takes the value and stores it in the corresponding variable (state=GETNUM, index=variable). When the delimiter is seen, all the values have already been extracted, checksum tested etc..
It's pointless to waste space holding a long string if you only want values from it. Even better, since the parser only handles one character at a time, it is fast, compared to the work of having to scan through the string in one go, after the whole message arrives.
Just a thought. |
Thanks Ttelmah,
So you are suggesting a state machine mechanism. but wont doing all that process inside a interrupt routine cause interrupt to miss some data?
My plan was to simply gather data as they arive untill it detects the delimeter, then raise a data available flag and then do the processing on the data outside the interrupt routine, so while I'm processing interrupt routine is free to accept new data.
The data I'm receiving is bit different than in a normal packet.
Following is an example for my 1 complete packet delimited by '>'
Code: | 01 0C
41 0C 0F BD
> |
So it contains two new line characters in the middle of data.
Section I need to catch is first "0C" second "0C" and last "0F BD".
Number of sets from last part could be 1 or 2. (ex last part after second 0C is only BD, or last part after second 0C is 0F BD).
Then I have to convert chars to hex numbers and do a merging to get original data. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Tue Jul 28, 2015 3:23 am |
|
|
Yes.
You can do the state machine in the interrupt, since though the code is large, it only ever handles one state.
However generally you don't do this in the interrupt, but in the main code. That's the point of the ring buffer. It only has to store the maximum number of characters that could arrive between successive calls to the parser.
A typical section of the main loop, is:
Code: |
if (bkbhit(U2RX))
{ //UART2 (controller)
parse(bgetc(U2RX));
}
//and then on to the next operation.
|
|
|
![](templates/subSilver/images/spacer.gif) |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Thu Jul 30, 2015 10:21 am |
|
|
Ttelmah wrote: | Yes.
You can do the state machine in the interrupt, since though the code is large, it only ever handles one state.
However generally you don't do this in the interrupt, but in the main code. That's the point of the ring buffer. It only has to store the maximum number of characters that could arrive between successive calls to the parser.
A typical section of the main loop, is:
Code: |
if (bkbhit(U2RX))
{ //UART2 (controller)
parse(bgetc(U2RX));
}
//and then on to the next operation.
|
|
Thanks Ttelmah,
I'll implement it in this way ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|