I was pretty good with x86 assembly a quarter century ago and just started learning ARM due to a possible teaching opportunity. So I started auditing a class. Task is simple. Trying to do a delay by counting down value in register subroutine (not proper but should be working). Set LED pin high, call delay, set LED pin low, call delay, repeat. We have a blink pattern.
This is the delay subroutine:
AREA program, CODE, READONLY
EXPORT delay
;Takes value from R1 to perform delay
delay
PUSH {R0-R7, LR}
delay1
SUBS R1, R1, #1
BNE delay1
POP {R0-R7, PC}
END
Main routine Level1 is an infinite loop to repeat the pattern.
AREA PROGRAM, CODE, READONLY
INCLUDE LPC11xx.inc
IMPORT delay
EXPORT Level1
Level1
PUSH{R0-R7,LR}
; Set the initial output on PIO1_5, PIO1_6, PIO1_7 as high
; 24.9s for 50 periods with 0 EORS instructions
; 24.9s for 50 periods with 1 EORS instructions
; 16.0s for 50 periods with 2 EORS instructions
; 15.7s for 50 periods with 3 EORS instructions
; 16.4s for 50 periods with 4 EORS instructions
; 15.6s for 50 periods with 5 EORS instructions
; 24.8s for 50 periods with 6 EORS instructions
; 24.9s for 50 periods with 7 EORS instructions
; 24.9s for 50 periods with 8 EORS instructions
; 25.5s for 50 periods with 9 EORS instructions
; 13.7s for 50 periods with 10 EORS instructions
; 16.4s for 50 periods with 11 EORS
; 16.8s for 50 periods with 12 EORS
;EORS R2, R2; Uncommenting causing 1s period, commenting causing 2s period, if R1=1.5M.
;MOVS R2,#0;
; Load the address of GPIO1DATA(last unmasked address base+0x3FFC) into R0
LDR R0, =(GPIO1DATA); GPIO1DATA Base + 0x3FFC, address 0x5001 3FFC, Table 174, page 192
; Load the value (1) at bit location 5, 6 and 7 to set PIO1_5, PIO1_6, PIO1_7 high
MOVS R7, #(0x7); Three pins were set to 1, not lined up with pins 5-7, but later will
MOVS R7, R7, LSL #5 ; Pins 5 thru 7 pins start with bit 5.
main_loop
LDR R1, [R0]
ORRS R1,R7;
; Store the value of R1 into GPIO1DATA
STR R1, [R0];
;EORS R1, R1
;----delay-----
LDR R1, =1500000; delay1 has 2 instructions and should take 2 cycles to run. Then with the assumption of 12MHz clock, 6M cycles should be 12M instructions, .i.e. 1 second, not 2 seconds.
BL delay;
; Load the value (0) at bit location 5, 6 and 7 to set PIO1_5, PIO1_6, PIO1_7 low
MVNS R7, R7;
LDR R1,[R0]
ANDS R1,R7
; Store the value of R1 into GPIO1DATA
STR R1, [R0];
LDR R1, =1500000; The whole cycle takes 4 seconds, 2 sec on and 2 sec off. 0.7s for 2 subs 1 bne and R1=1.2M
BL delay;
MVNS R7, R7;
ADDS R2, #1
B main_loop
POP {R0-R7,PC}
END
The offending line is EORS R2, R2. It is NOT in the delay subroutine so it is NOT called during the register countdown. My comments before the line explains what I saw, regarding the delay period. If I have 0 or 1 such line, or 6-8 lines of EORS R2, R2, delay is about 2Hz. If I have 2-5 or 11, 12 lines of EORS R2, R2, I got about 3Hz. I carefully timed the LEDs for 50 cycles for each test. I've observed this on someone else's laptop with my breadboard, built a second breadboard with everything new. Others confirmed that adding some unimportant instructions caused some unexplainable changes to delays but they were students so they didn't investigate. I'm trying to understand ARM as a new architecture and will hopefully be an instructor so the motive to understand unexplainable behavior is there.