Unexpected delay changes with LPC1114 cortex-M0 assembly code

I'm new to the ARM architecture. I have Keil uVision and LPC1114/102 with ST Link V2 programmer on a breadboard.

What I wanted to do: making a delay subroutine by counting down a value in a register to zero (it's not proper delay but should in principle work, consistently I think).

What I observed: I could blink an LED on and off toggling the LED pin and calling the delay subroutine between toggles.

What else I noticed: the delay amount isn't stable. I added a few lines of instructions, outside the delay subroutine, and the delay frequency could change largely, depending on how many lines of instructions I added. They are repeated lines of EORS R2, R2 for instance, just to see how the delays are affected.

My delay subroutine takes the input from R1, for example 1.5 million to count down to zero:

 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

My code "Level1" calls delay after turning on an LED, and calls delay after turning the LED off. This is repeated so I get a blinking LED.

Line 20 has the offending instruction EORS R2, R2. If I don't include it, or include just it, the observed LED blinking is 2Hz (0.25 second on, 0.25 seconds off). If I include 2 to 5 repeated lines of this instruction, I get the faster blink of about 3Hz. If I include 6-9 repeated lines of EORS, back to 2Hz blink. If I include 10-12 lines of EORS, 3Hz.

I carefully counted 50 periods in each case. The EORS instructions have no effect on the delay and all they do is wasting a few CPU cycles. The actual delay has 1.5million count down to zero with SUBS and BNE so the EORS lines are NOT repeated 1.5 million times.

 AREA PROGRAM, CODE, READONLY
 INCLUDE	LPC11xx.inc
 IMPORT delay
 EXPORT Level1

Level1
	PUSH{R0-R7,LR}
	; 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.
	; Set the initial output on PIO1_5, PIO1_6, PIO1_7 as high
    ; 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

I believe the initialization code was provided by Keil and this was a C project that I added this assembly code by adding a BL in the init code after SystemInit and before __main. I can provide the project zip if needed.

A bit of background. I'm auditing an MCU architecture and ASM class so I can potentially take over next year as the instructor. I've given up on IA-32 ASM over a quarter of century ago after some extensive studies and coding (back then called X86 X386). It's been interesting with ARM so far but if I were to teach this, I can't leave stones un-turned. And It's not just me. I had the class TA run his code he had from 2 years ago on my board and had him add useless lines (he tried other instructions than EORS) and he observed similar inconsistent blinking frequencies when commenting/uncommenting those lines. I also asked other students in the class. They more or less admitted observing some unexpected delay timing but simply wanted to get their labs done. I even got a new MCU from a tube of new parts, built a new set up on a new breadboard, also enabled CLKOUT to watch and confirm the clock isn't magically changing. I am using RC + PLL for 12MHz in pure ASM projects and RC + PLL for 48MHz for C/C+ASM projects. Similar issues in both kinds of projects.

Parents Reply Children
No data