I am trying to blink an LED on LPC4088(Datasheet) and I have properly prepared my peripheral registers already. Now is the time to blink an LED and this is the loop which should do it:
blink:
@ In register SET1 (0x20098038) we set bits:
@ bit 13 = 1 > sets pin P1_13 to high state
ldr r0, =0x20098038
ldr r1, [r0]
ldr r2, =0x2000
orr r1, r2
str r1, [r0]
@ NO DELAY NEEDED FOR DEBUG
@ In register CLR1 (0x2009803C) we set bits:
@ bit 13 = 1 > sets pin P1_13 to low state
ldr r0, =0x2009803C
ldr r1, [r0]
ldr r2, =0x2000
orr r1, r2
str r1, [r0]
@ NO DELAY NEEDED FOR DEBUG
b blink
When I checked the execution of the code in debugger I noticed that first part of the loop (before first @ NO DELAY NEEDED FOR DEBUG
) executes fine and LED is turned on exactly when command str r1, [r0]
is executed.
Now comes the second part of the loop (after first @ NO DELAY NEEDED FOR DEBUG
) and when I try to execute ldr r0, =0x2009803C
LED won't turn off. Instead my program directly jumps to the first part of the loop and would execute ldr r0, =0x20098038
in the next step. So instructions:
ldr r1, [r0]
ldr r2, =0x2000
orr r1, r2
str r1, [r0]
in the second part of the loop are never executed...
This code worked perfectly fine in C code previously... Does anyone spot a mistake, because I can't. Do I somehow overwrite registers? Could it be that my compiler optimises the code somehow?
You are not allowed to read from register CLR1
at address 2009803c
, as it is write-only (see the user manual). As a result you get a fault (I'm not sure exactly which one, probably MemManageFault, or BusFault). Normally it would jump to a fault handler, but from the behavior you see it seems to restart the program.
The solution is not to read the SET
or CLR
registers, you should just write the pattern of bits you want to set or clear.