So, I have recently acquired a SAMC21 Xplained dev board to begin trying to learn to program for ARM. My previous experience is predominantly with PIC's. As an example application I have started an ASF Board project targeting the SAMC21 Xplained board and written the following main function:
#include <asf.h>
#include <stdbool.h>
int main (void) {
system_init();
SysTick_Config(SystemCoreClock/1000);
system_interrupt_enable(SYSTEM_INTERRUPT_SYSTICK);
while(true);
}
void SysTick_Handler(void) {
port_pin_toggle_output_level(LED_0_PIN);
}
When I start debugging I successfully reach main and execute the system_init() function. After that, the program counter hangs forever. The Disassembly looks like this:
int main (void) {
000004D0 ??? Memory out of bounds or read error
system_init();
000004D2 ldr r3, #60
000004D4 blx r3
SysTick_Config(SystemCoreClock/1000);
000004D6 ldr r3, #60
000004D8 ldr r0, [r3]
000004DA movs r1, #250
000004DC lsls r1, r1, #2
000004DE ldr r3, #56
000004E0 blx r3
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
000004E2 subs r0, #1
000004E4 ldr r3, #52
000004E6 cmp r0, r3
000004E8 bhi #26
SysTick->LOAD = ticks - 1; /* set reload register */
000004EA ldr r3, #52
000004EC str r0, [r3, #4]
SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
000004EE ldr r2, #52
000004F0 ldr r0, [r2, #32]
000004F2 lsls r0, r0, #8
000004F4 lsrs r0, r0, #8
000004F6 movs r1, #192
000004F8 lsls r1, r1, #24
000004FA orrs r1, r0
000004FC str r1, [r2, #32]
SysTick->VAL = 0; /* Load the SysTick Counter Value */
000004FE movs r2, #0
00000500 str r2, [r3, #8]
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
00000502 movs r2, #7
00000504 str r2, [r3]
NVIC->ISER[0] = (uint32_t)(1 << ((uint32_t)vector & 0x0000001f));
00000506 movs r2, #128
00000508 lsls r2, r2, #24
0000050A ldr r3, #28
0000050C str r2, [r3]
0000050E b #-4 // Debugger PC Hangs
00000510 lsls r1, r2, #16
00000512 movs r0, r0
00000514 movs r4, r0
00000516 movs r0, #0
00000518 lsls r1, r7, #20
0000051A movs r0, r0
0000051C ??? Memory out of bounds or read error
0000051E lsls r7, r7, #3
00000520 b #32
00000522 b #0
00000524 ??? Memory out of bounds or read error
00000526 b #0
00000528 b #512
0000052A b #0
port_base->OUTTGL.reg = pin_mask;
0000052C movs r2, #128
0000052E lsls r2, r2, #8
00000530 movs r3, #130
00000532 lsls r3, r3, #23
00000534 str r2, [r3, #28]
}
00000536 bx lr
I've added a comment to the line where the PC hangs (0x0000050E
). I'm confused because it looks like the b #-4
assembly instruction is behaving correctly by repeatedly branching to itself. What I don't understand is why it's there in the first place.
EDIT First off, thank you to everyone for the responses! Secondly, I should have included more of the code (sorry about that ) but wasn't sure what was relevant. I have edited my code above to show the entire main.c file. It almost looks like the while(true) has been misplaced in the code, but I'm still struggling to make sense of it.
Also adding some (hopefully!) useful snippets from my .lss file:
00000000 <_sfixed>:
* Initialize the System and update the SystemCoreClock variable.
*/
void SystemInit(void)
{
// Keep the default device state after reset
SystemCoreClock = __SYSTEM_CLOCK;
0: 20002030 .word 0x20002030
4: 00000441 .word 0x00000441
return;
}
8: 0000043d .word 0x0000043d
c: 0000043d .word 0x0000043d
...
2c: 0000043d .word 0x0000043d
...
38: 0000043d .word 0x0000043d
3c: 0000052d .word 0x0000052d
40: 0000043d .word 0x0000043d
44: 0000043d .word 0x0000043d
48: 0000043d .word 0x0000043d
4c: 0000043d .word 0x0000043d
50: 0000043d .word 0x0000043d
54: 0000043d .word 0x0000043d
58: 0000043d .word 0x0000043d
5c: 0000043d .word 0x0000043d
60: 0000043d .word 0x0000043d
64: 0000043d .word 0x0000043d
68: 0000043d .word 0x0000043d
6c: 0000043d .word 0x0000043d
70: 0000043d .word 0x0000043d
74: 0000043d .word 0x0000043d
78: 0000043d .word 0x0000043d
7c: 0000043d .word 0x0000043d
80: 0000043d .word 0x0000043d
84: 0000043d .word 0x0000043d
88: 0000043d .word 0x0000043d
8c: 0000043d .word 0x0000043d
90: 0000043d .word 0x0000043d
94: 0000043d .word 0x0000043d
98: 0000043d .word 0x0000043d
9c: 0000043d .word 0x0000043d
a0: 0000043d .word 0x0000043d
a4: 0000043d .word 0x0000043d
a8: 0000043d .word 0x0000043d
ac: 0000043d .word 0x0000043d
b0: 0000043d .word 0x0000043d
b4: 0000043d .word 0x0000043d
b8: 0000043d .word 0x0000043d
000004d0 <main>:
#include <asf.h>
#include <stdbool.h>
int main (void) {
4d0: b508 push {r3, lr}
system_init();
4d2: 4b0f ldr r3, [pc, #60] ; (510 <main+0x40>)
4d4: 4798 blx r3
SysTick_Config(SystemCoreClock/1000);
4d6: 4b0f ldr r3, [pc, #60] ; (514 <main+0x44>)
4d8: 6818 ldr r0, [r3, #0]
4da: 21fa movs r1, #250 ; 0xfa
4dc: 0089 lsls r1, r1, #2
4de: 4b0e ldr r3, [pc, #56] ; (518 <main+0x48>)
4e0: 4798 blx r3
must contain a vendor-specific implementation of this function.
*/
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
4e2: 3801 subs r0, #1
4e4: 4b0d ldr r3, [pc, #52] ; (51c <main+0x4c>)
4e6: 4298 cmp r0, r3
4e8: d80d bhi.n 506 <main+0x36>
SysTick->LOAD = ticks - 1; /* set reload register */
4ea: 4b0d ldr r3, [pc, #52] ; (520 <main+0x50>)
4ec: 6058 str r0, [r3, #4]
\param [in] priority Priority to set.
*/
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if(IRQn < 0) {
SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
4ee: 4a0d ldr r2, [pc, #52] ; (524 <main+0x54>)
4f0: 6a10 ldr r0, [r2, #32]
4f2: 0200 lsls r0, r0, #8
4f4: 0a00 lsrs r0, r0, #8
4f6: 21c0 movs r1, #192 ; 0xc0
4f8: 0609 lsls r1, r1, #24
4fa: 4301 orrs r1, r0
4fc: 6211 str r1, [r2, #32]
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = ticks - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
SysTick->VAL = 0; /* Load the SysTick Counter Value */
4fe: 2200 movs r2, #0
500: 609a str r2, [r3, #8]
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
502: 2207 movs r2, #7
504: 601a str r2, [r3, #0]
* \param[in] vector Interrupt vector to enable
*/
static inline void system_interrupt_enable(
const enum system_interrupt_vector vector)
{
NVIC->ISER[0] = (uint32_t)(1 << ((uint32_t)vector & 0x0000001f));
506: 2280 movs r2, #128 ; 0x80
508: 0612 lsls r2, r2, #24
50a: 4b07 ldr r3, [pc, #28] ; (528 <main+0x58>)
50c: 601a str r2, [r3, #0]
50e: e7fe b.n 50e <main+0x3e>
510: 00000411 .word 0x00000411
514: 20000004 .word 0x20000004
518: 00000539 .word 0x00000539
51c: 00ffffff .word 0x00ffffff
520: e000e010 .word 0xe000e010
524: e000ed00 .word 0xe000ed00
528: e000e100 .word 0xe000e100
0000052c <SysTick_Handler>:
{
PortGroup *const port_base = port_get_group_from_gpio_pin(gpio_pin);
uint32_t pin_mask = (1UL << (gpio_pin % 32));
/* Toggle pin output level */
port_base->OUTTGL.reg = pin_mask;
52c: 2280 movs r2, #128 ; 0x80
52e: 0212 lsls r2, r2, #8
530: 2382 movs r3, #130 ; 0x82
532: 05db lsls r3, r3, #23
534: 61da str r2, [r3, #28]
while(true);
}
void SysTick_Handler(void) {
port_pin_toggle_output_level(LED_0_PIN);
}
536: 4770 bx lr
Recently faced same systick issue. On analyzing and changing the linker script (.ld) the problem got resolved. I was using a custom linker script. Check your linker script, MSR, vector address (at location 0x0000003C)
User contributions licensed under CC BY-SA 3.0