We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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.