Oddities with Energymicro's efm32

Uwe Kleine-König u.kleine-koenig at pengutronix.de
Tue Jan 29 17:25:27 EST 2013


Hello,

I'm stuck with debugging a problem on my GiantGecko board (Cortex-M3
efm32 SoC).

Up to now I used the flash built into the SoC. But as it only has a size
of 1 MiB I had to switch to the external flash---at least for
development.

I guess because of changed timing settings this triggers a problem with
the stack pointer. The following code is executed:

8c009e80 <update_process_times>:
8c009e80:       b570            push    {r4, r5, r6, lr}
8c009e82:       466b            mov     r3, sp
8c009e84:       f423 54ff       bic.w   r4, r3, #8160   ; 0x1fe0
8c009e88:       f024 041f       bic.w   r4, r4, #31
8c009e8c:       4606            mov     r6, r0
8c009e8e:       4810            ldr     r0, [pc, #64]   ; (8c009ed0 <update_process_times+0x50>)
8c009e90:       68e5            ldr     r5, [r4, #12]
8c009e92:       f7f8 fc9b       bl      8c0027cc <printascii>
8c009e96:       f5b4 5f00       cmp.w   r4, #8192       ; 0x2000
8c009e9a:       d806            bhi.n   8c009eaa <update_process_times+0x2a>
8c009e9c:       4668            mov     r0, sp
8c009e9e:       f7f8 fc6b       bl      8c002778 <printhex8>
8c009ea2:       480c            ldr     r0, [pc, #48]   ; (8c009ed4 <update_process_times+0x54>)
8c009ea4:       f7f8 fc92       bl      8c0027cc <printascii>
8c009ea8:       e7fe            b.n     8c009ea8 <update_process_times+0x28>

printascii is a function to print out a debug message, printhex prints
out the value of r0. The code corresponds to this C-Code:

#define THREAD_SIZE 8192
static inline struct thread_info *current_thread_info(void)
{       
        register unsigned long sp asm ("sp");
        return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}


void update_process_times(int user_tick)
{
	...
        printascii("up1\n");
        if (current_thread_info() <= 0x2000) {
                asm volatile("mov r0, sp\n" "bl printhex8" : : : "cc", "r0", "r1", "r2", "r3");
                printascii("br0ken\n");
                while (1) {}
        }
	...
}

That is the condition of the if is

	(sp & ~0x1fff) <= 0x2000

. If it triggers, the value of sp is printed. When the function in
question is called for the second time the condition is true and sp is
printed as 0x88009e88. The value of r4 is 0 then. The values on the
stack don't look reasonable:

	88009e70: 8c0ed2b8 8c01c75f 8c01c78d 88016980 
	88009e80: 88018de4 8c01c797 88016900 88016900 
	88009e90: 88016980 88018de4 0000001d 00000000 
	88009ea0: 00000000 8c00306b 8c00305d 8c01d0a5 
	88009eb0: 88018de4 88016980 88018de4 00000000 
	88009ec0: 88026820 00000000 88009f44 88009f70 
	88009ed0: 8c0ed2b1 8c01d1a7 88018de4 8c01e5c9 
	88009ee0: 0000001d 8c01cd6b 0000001d 8c000cdb 

which means that the value saved on the stack for lr would have been
0x88018de4 which is outside of the kernel image. It's a RAM address. So
sp probably was wrong when the function was entered, too. But even in
the case that the caller corrupted sp, why isn't it < 0x2000 when
printed out in the body of the if?

The code is run with irqs off (PRIMASK=1). So the only things that could
happen to influence sp between 0x8c009e82 and 0x8c009e9c are Reset, NMI
and HardFault. For each of them the handler wouldn't return, so they can
be ruled out.

The timing settings for flash and sram are copied from Energymicro's
Board Support Package, so they should be ok, too.

This is hard to debug because I cannot set breakpoints in the external
flash and I didn't get tracing up and running up to now. Also the
problem is very sensible to changes: If I add instrumentation to the
exception entry code the problem doesn't reproduce any more.

I'm out of ideas now. So if you have an idea that would be great. If you
want to reproduce I can provide you source code and/or binaries. Also if
you have questions or see a gap in my conclusions, don't hesitate to
contact me.

Thanks for your time,
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |



More information about the linux-arm-kernel mailing list