Reply
Posts: 67
Registered: ‎09-15-2015

Weirdo hardware reset occurs on function ordering change

Alright, this may be the strangest EFM8 issue I've seen thus far. I'm using the (new?) SiLabs_Startup() configuration when creating a new Simplicity Configurator project which invokes all the hardware configuration code before doing variable initialization. In my previous projects, this code was called in the main() function. Anyway, when I first built the project and started debugging, I was having issues with an EFM8SB1 getting stuck in a reset loop, and thought it might be a watchdog issue or something. However, I widdled down the Simplicity Configurator project to something very small that duplicates the problem.

 

I've removed all external libraries and sources; all I have is the standard SILABS_STARTUP.A51 file (note that SILABS_STARTUP is enabled), and this C source code:

 

void function2();

void function1() {
	int i = 0;
	function2();
	i = 0;
}

void function2() { }

void SiLabs_Startup() {
	function1();
}

int main() {
	while (1) { }
}

 

 

Again, if I compile the above code, my MCU gets stuck in a hardware reset loop once it returns from function1(). I've looked at the reset source, and it claims it's a hardware reset, not a watchdog timer issue.

 

Here's the assembly listing:

 

 

             ; FUNCTION function2 (BEGIN)
                                           ; SOURCE LINE # 5
0000 22                RET     
             ; FUNCTION function2 (END)

             ; FUNCTION function1 (BEGIN)
                                           ; SOURCE LINE # 7
                                           ; SOURCE LINE # 8
;---- Variable 'i' assigned to Register 'R6/R7' ----
0000 E4                CLR     A
0001 FF                MOV     R7,A
0002 FE                MOV     R6,A
                                           ; SOURCE LINE # 9
0003 020000      R     LJMP    function2
             ; FUNCTION function1 (END)

             ; FUNCTION SiLabs_Startup (BEGIN)
                                           ; SOURCE LINE # 13
                                           ; SOURCE LINE # 14
0000 020000      R     LJMP    function1
             ; FUNCTION SiLabs_Startup (END)

             ; FUNCTION main (BEGIN)
                                           ; SOURCE LINE # 17
0000         ?C0004:
                                           ; SOURCE LINE # 18
0000 80FE              SJMP    ?C0004
             ; FUNCTION main (END)

 

 

I can fix the problem by simply moving the function2() implementation above function1():

 

void function2();

void function2() { }

void function1() {
	int i = 0;
	function2();
	i = 0; // removing this line breaks the code again
}

void SiLabs_Startup() {
	function1();
}

int main() {
	while (1) { }
}

 

 

But, when I look at the assembly listing, I don't see anything different:

 

             ; FUNCTION function2 (BEGIN)
                                           ; SOURCE LINE # 3
0000 22                RET     
             ; FUNCTION function2 (END)

             ; FUNCTION function1 (BEGIN)
                                           ; SOURCE LINE # 5
                                           ; SOURCE LINE # 6
;---- Variable 'i' assigned to Register 'R6/R7' ----
0000 E4                CLR     A
0001 FF                MOV     R7,A
0002 FE                MOV     R6,A
                                           ; SOURCE LINE # 7
0003 020000      R     LJMP    function2
             ; FUNCTION function1 (END)

             ; FUNCTION SiLabs_Startup (BEGIN)
                                           ; SOURCE LINE # 11
                                           ; SOURCE LINE # 12
0000 020000      R     LJMP    function1
             ; FUNCTION SiLabs_Startup (END)

             ; FUNCTION main (BEGIN)
                                           ; SOURCE LINE # 15
0000         ?C0004:
                                           ; SOURCE LINE # 16
0000 80FE              SJMP    ?C0004
             ; FUNCTION main (END)

 

However! If I look at the actual program memory, the two programs are different:

02000312 0020787F E4F6D8FD 75810902 0023E4F5 08F50912 0025E4F5 08F50922 02001280 FE22FFFF (not working)        
02000312 0018787F E4F6D8FD 75810702 001BE4FF FE02001D 02001280 FE22FFFF (working)

 

I'm using a Toolstick debug adapter.

 

 

Note that when I remove the i = 0 assignment on line 8, the code breaks again.

 

Also note that that if I move the function1() call from SiLabs_Start() into main() { } my program works fine, too — no matter where function2() is defined.

 

What's going on here? Is my debugger getting silly and restarting the MCU?

Posts: 8,132
Registered: ‎08-13-2003

Re: Weirdo hardware reset occurs on function ordering change

all this is done before the Keil "C initializer" has run and it is no surprise strange things happen.

 

 

erik
<a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Genius</font></font> </a> CL
Posts: 27
Registered: ‎10-28-2015

Re: Weirdo hardware reset occurs on function ordering change

The bytes in the non-working memory dump and the assembly listing do not match.

 

You must show us the assembly listing of the code that you are actually executing.

 

As for the actual problem: the non-working code uses registers R0 and R1 in register bank 1 for the i variable, but that register bank is stored in memory locations 8-15, and that is where the default stack is located (before the initialization code initializes SP). So writing to i overwrites the return address on the stack.

 

(I don't know which compiler setting makes it use a different register bank. Interrupt handler?)

Highlighted
Posts: 466
Registered: ‎02-21-2014

Re: Weirdo hardware reset occurs on function ordering change

@erikm, you said something like this would happen.  I'm moving the init function back into main () for config projects (I had actually planned to do this before the next studio release - I wasn't aware that someone had published our SDK with the changes... d'oh).

 

@funkathustra, I'll pull this out of the SiLabs_Startup function in the newest version of the SDK (I think we'll have a release sometime next month). I would revert the init function to being called in main() in your project.