| Author |
Message |
|
|
Posted: Feb 24, 2012 - 03:37 PM |
|

Joined: Nov 15, 2011
Posts: 19
|
|
Hello,
I'm writing a quite complex program based on a FSM from
http://www.gedan.net/2009/03/18/finite-state-machine-matrix-style-c-implementation-function-pointers-addon/
I use it for touchscreen navigation between menus.
It uses a function pointer to call void function(void) functions to do an action.
When the action is executed and finished, I don't return to the main loop, but get a reset. It seems that the AVR is forgetting where to return to. So the stack pointer has the wrong value I suppose? Is there any way I can fix this?
main calls stateEval calls action using function pointer calls some subfunctions of action. So it is 4 levels of calling. |
|
|
| |
|
|
|
|
|
Posted: Feb 24, 2012 - 03:53 PM |
|


Joined: Jul 18, 2005
Posts: 62348
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
As I peer into my crystal ball I see a mega64 or mega128 operating in mega103 mode.
Am I right? Do I win the £5?
(if I'm wrong it could still be code built for the wrong target).
BTW from the article you linked:
Code:
void main() {
void (*fp)();
fp functionPointer = function_a;
(*fp)(); //prints "a"
fp functionPointer = function_b;
(*fp)(); //prints "b"
}
It seems to me the first line of main() is missing the word typedef? They also use the fn_ptr in a cumbersome way, I'd go with:
Code:
typedef void (*fp)(void);
int main(void) {
fp functionPointer = function_a;
fp(); //prints "a"
functionPointer = function_b;
fp(); //prints "b"
}
|
_________________
|
| |
|
|
|
|
|
Posted: Feb 24, 2012 - 03:57 PM |
|

Joined: Nov 15, 2011
Posts: 19
|
|
|
|
|
|
|
Posted: Feb 24, 2012 - 03:58 PM |
|


Joined: Jul 18, 2005
Posts: 62348
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
| You are trying to post % signs - replace them with % instead. |
_________________
|
| |
|
|
|
|
|
Posted: Feb 24, 2012 - 03:58 PM |
|

Joined: Oct 29, 2006
Posts: 2654
|
|
| Does avrfreaks have information on pseudo-resets where a beginner is likely to find it? |
_________________ Michael Hennebry
Iluvatar is the better part of Valar.
|
| |
|
|
|
|
|
Posted: Feb 24, 2012 - 04:06 PM |
|

Joined: Nov 15, 2011
Posts: 19
|
|
Ok pastebin then..
I use an ATXmega256A3B and the project settings are correct. I'm using AVRstudio 5 and the JTAGiceMK2 debugger.
As mentioned the application is a touchscreen. In my action routine I want to input settings, So detecting key presses and building the pressed number. When I leave the function fillwithspaces commented, it works. When I uncomment fillwithspaces the reset occurs.
Action function
http://pastebin.com/DUpp16Sg
Fill with spaces function
http://pastebin.com/CEgn08KH
Thanks in advance. |
|
|
| |
|
|
|
|
|
Posted: Feb 24, 2012 - 04:13 PM |
|


Joined: Jul 18, 2005
Posts: 62348
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
You still haven't answered the mega128 question.
Anyway not sure what those two code snippets are supposed to show. Neither appears to be using a function pointer though I can see that the second one is one of those hugely dangerous routines designed to wreak havoc. You might want to consider including something to prevent you writing beyond the limits of whatever the char * is pointing at. Just as you can do:
Code:
char text[3];
strcpy(text, "hello world");
and wreak havoc it is very unwise to use char *'s without some kind of bounds limiting mechanism. (which is why strncpy() exists) |
_________________
|
| |
|
|
|
|
|
Posted: Feb 24, 2012 - 04:24 PM |
|

Joined: Nov 15, 2011
Posts: 19
|
|
The number I need to make is 8 numbers wide. Always. So there isn't the problem I think. I've never heard of Mega103 mode. I use the ATXMEGA256AB I did a quick search and found that mega103 mode is for mega128 devices and is set in the fuse bits?
In the "fillwithspaces" function I give the size as second parameter. So perhaps you mean that if I give the wrong size I will overwrite other important code. I guess there could be a problem with my sizes then... |
|
|
| |
|
|
|
|
|
Posted: Feb 24, 2012 - 04:29 PM |
|


Joined: Jul 18, 2005
Posts: 62348
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
You are right the m64/m128/m103 thing doesn't apply but we couldn't have possibly known that until you identified the AVR. It is the main reason we see on this message board for AVR programs that can CALL but that cannot RET however.
I guess I don't win £5.
Anyway I'd still suspect you are writing through a rogue pointer and corrupting other things in memory. When one of those things is a RAM based function pointer things get very nasty (which is why MISRA won't let you use them!) |
_________________
|
| |
|
|
|
|
|
Posted: Feb 24, 2012 - 04:37 PM |
|

Joined: Nov 15, 2011
Posts: 19
|
|
I've changed
Code:
fillwithspaces(buf,9);
To
Code:
fillwithspaces(buf,8);
And it works. Is there a quick and dirty way to never make this mistake again? Digging up the strcpy() function and looking at its protection perhaps. Or is it wrong to pass the address? |
|
|
| |
|
|
|
|
|
Posted: Feb 24, 2012 - 06:15 PM |
|

Joined: Mar 12, 2004
Posts: 1205
Location: Portland, OR, USA
|
|
|
The_Dutchman wrote:
And it works. Is there a quick and dirty way to never make this mistake again?
The change prevented fillwithspaces() from overwriting whatever follows the buffer in RAM. You can avoid issues like this if you use the sizeof operator, e.g.:
Code:
char myBuf[9];
...
fillwithspaces(myBuf, sizeof(myBuf) - 1);
The -1 allows for the fact fillwithspaces() writes a null following the specified number of spaces.
Alternately, you could modify fillwithspaces() so that it writes one fewer space than the supplied parameter value, filling the last byte with a null. |
_________________ Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net
|
| |
|
|
|
|
|
Posted: Feb 24, 2012 - 06:23 PM |
|


Joined: Jul 18, 2005
Posts: 62348
Location: (using avr-gcc in) Finchingfield, Essex, England
|
|
When you pass a char* (or anything* in fact)then as long as you pass the max length of the destination the routine can be written to stop before it would write beyond the valid space the pointer is pointing to.
That's how strncpy() differs from strcpy(). There's an additional parameter to say "come what may don't write more than this many bytes to the destination pointer". Inside the routine every time you p++ you dest_len-- and if it reaches 0 you return. You might also want to return a code to say "gave up early because length limit reached". |
_________________
|
| |
|
|
|
|
|
Posted: Feb 24, 2012 - 09:24 PM |
|

Joined: Nov 17, 2004
Posts: 13848
Location: Vancouver, BC
|
|
| But you still need to pass in a valid value for the number of elements. If you tell strncpy() to copy a max of 20 bytes when the pointer only holds 10, you are still in trouble. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|