Wello guys,
Im trying to manipulate the stack pointer and after the return of the "go_to_func" function the program will return to the start of "func" function and turn on the PORTD bit 3. I had tried the code below and it's dosen't work, the program still returns to main and turned on the PORTD bit 2. Am i missing something or i have a wrong perspective about how the stack works ?
PS: Im using the Atmel Studio 7.0 for Atmega328p ( Arduino uno )
#include <avr/io.h>
typedef unsigned char uint8;
typedef unsigned short int uint16;
/*
call go_to_func SP -> | somewhere in main |
*sp = (uint16_t)function; SP -> | start of func |
*/
void func( void )
{
/* PORTD ==> | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | */
PORTD = 0x08 ;
}
void go_to_func( void (*function)(void) )
{
uint16 *sp = (uint16*)SP ;
*sp = (uint16)function;
/* after the return i want the SP to point to the start of func() */
}
int main(void)
{
/* DDRD ==> | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | */
DDRD |= 0x0C ;
go_to_func(func);
/* PORTD ==> | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | */
PORTD = 0x04 ;
while (1)
{
}
}
Update: Hi i make an update where i made the functions noinline so in the assembly file the call apear now, but when i pass the "func" address to the "go_to_func" i expect to pass the value 90 which is the start of "func" but the program pass the value 72 ( at this line --> ldi r24, 0x48 )
#define CALL_FCT __attribute__ ((noinline))
void CALL_FCT func( void )
{
/* PORTD ==> | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | */
PORTD = 0x08 ;
90: 88 e0 ldi r24, 0x08 ; 8
92: 8b b9 out 0x0b, r24 ; 11
94: 08 95 ret
00000096 <go_to_func>:
}
void CALL_FCT go_to_func( void (*function)(void) )
{
func_addr = (uint16)function ;
96: 90 93 01 01 sts 0x0101, r25 ; 0x800101 <_edata+0x1>
9a: 80 93 00 01 sts 0x0100, r24 ; 0x800100 <_edata>
SP = (uint16)(&func_addr);
9e: 80 e0 ldi r24, 0x00 ; 0
a0: 91 e0 ldi r25, 0x01 ; 1
a2: 9e bf out 0x3e, r25 ; 62
a4: 8d bf out 0x3d, r24 ; 61
a6: 08 95 ret
000000a8 <main>:
}
int CALL_FCT main(void)
{
/* DDRD ==> | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | */
DDRD |= 0x0C ;
a8: 8a b1 in r24, 0x0a ; 10
aa: 8c 60 ori r24, 0x0C ; 12
ac: 8a b9 out 0x0a, r24 ; 10
go_to_func(func);
ae: 88 e4 ldi r24, 0x48 ; 72
b0: 90 e0 ldi r25, 0x00 ; 0
b2: 0e 94 4b 00 call 0x96 ; 0x96 <go_to_func>
/* PORTD ==> | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | */
PORTD = 0x04 ;
b6: 84 e0 ldi r24, 0x04 ; 4
b8: 8b b9 out 0x0b, r24 ; 11
ba: ff cf rjmp .-2 ; 0xba <main+0x12>
000000bc <_exit>:
bc: f8 94 cli
000000be <__stop_program>:
be: ff cf rjmp .-2 ; 0xbe <__stop_program>