Delay¶
Accurate Blocking Delay¶
This blocking delay is created using arm-none-eabi-as to produce the machine code which is then INLINED into a Forth Word.
Note
While the delay is being used, the CPU is not available to do anything else.
To see the same thing done using Interactive Assembly see Interactive Assembly Blocking Delay
Why do it this way ?¶
The reason that the millisecond blocking delay is done this way rather than in pure Forth is because it can be done in about half the binary code size compared to a pure Forth Word. Another reason is that sometimes maximum speed is required and this means using minimal instructions in the Forth Word. The delay example is a great way to demonstrate how to achieve this.
Note
The THUMB Instruction Set is used here
Using Pure Forth Instead¶
The pure Forth way is certainly much faster to write and debug compared to the alternate methods.
The “delay” Word below uses the common “do-loop”.
: delay
0 do loop
;
Disassembly¶
see delay
2000068A: B500 push { lr }
2000068C: B430 push { r4 r5 }
2000068E: 2400 movs r4 #0
20000690: 0035 lsls r5 r6 #0
20000692: CF40 ldmia r7 { r6 }
20000694: 3401 adds r4 #1
20000696: 42AC cmp r4 r5
20000698: D1FC bne 20000694
2000069A: BC30 pop { r4 r5 }
2000069C: BD00 pop { pc }
Bytes: 20 ok.
Delay Measurments¶
Timing measurements were performed using the on chip Systick counter set to a count of 0.1ms using a Interrupt.
Input |
Delay |
Period |
Comments |
---|---|---|---|
10000000 |
6.5359 |
seconds |
uncalibrated |
The Method below produces the following delays:¶
105.2nS @ 48Mhz
631.2nS @ 8Mhz
Note
Although very accurate due to the small loop, the accuracy will be affected by many factors such as the cache, interrupts and the stability of the clock. All blocking loop delays are affected by these things, but they are fine for general purpose delays of a known time period such a providing a minimum pulse width for a LCD display, blinking a LED and so on. If greater accuracy is required, consider using a Timer Peripheral instead.
In this example the delay Word is named “105ns” for use on a 48MHz system.
Delay Code¶
: 105ns ( u -- ) \ 105.2ns delay @ 48mhz clock
[
$3e01 h, \ subs r6, #1
$46c0 h, \ nop
$d1fc h, \ bne.n 8 <loop>
] drop
;
Disassembly¶
see 105ns
20000688: B500 push { lr }
2000068A: 3E01 subs r6 #1
2000068C: 46C0 mov r8 r8
2000068E: D1FC bne 2000068A
20000690: CF40 ldmia r7 { r6 }
20000692: BD00 pop { pc }
Bytes: 12 ok.
Delay Measurments¶
Timing measurements were performed using the on chip Systick counter set to a count of 0.1ms using a Interrupt.
This delay should work for a minium delay of 105.2 nS to a maximum delay of 451.86 seconds (7.53 Minutes)
Input |
Delay |
Period |
Comments |
---|---|---|---|
1 |
105.2 |
ns |
CALCULATED (too small to measure with systick) |
1000 |
0.1052 |
ms |
CALCULATED (too small to measure with systick) |
1000000 |
0.1052 |
seconds |
|
10000000 |
1.0521 |
seconds |
|
$00FFFFFF |
1.7651 |
seconds |
|
$0FFFFFFF |
28.2415 |
seconds |
|
$FFFFFFFF |
451.8640 |
seconds |
(7.531067 minutes) |
Millisecond Delay¶
The ms Word calls the 105ns Word and is scaled for 1 ms.
: ms ( u -- ) \ for a 48 Mhz clock
9505 * 105ns
;
Example usage¶
This lights the green LED on a Discovery board (clocked at 48MHz) for exactly 1 second.
: green-led-on-1-second ( -- ) green-on 1000 ms green-off ;
How to Inline code¶
See also
Write the code in Assembler¶
Compile the code with arm-none-eabi-as¶
Test the Code in GDB¶
Note: the code shown here is slightly different to the actual “Delay Code” above because I have inserted a fake “Top Of Stack” line to supply R6 with a delay value of 0x2 for the debugging session. When this code is used with Forth, R6 will already contain a valid number from the user program so the fake TOS isn’t required.
GDB talks to the actual MCU via SWD and single steps thru the program on the actual chip, displaying register contents and following the program flow on the actual chip.
It’s incredible to think that this facility which once used to cost tens of thousands of dollars is available in a MCU costing $0.56 USD and that the GNU software is Free.
Cut and Paste the Machine Code into a Forth Word¶
The paste must be edited to suit Forth as seen in the “Delay Code” above.