ARM: get delay.c in.

Accuracy is pretty good, see committed comments :-)

Code used for testing, in main():

  uint32_t i;

  SET_OUTPUT(PIO0_1);
  while (1) {
    // 10 seconds for each frequency, so we
    // can measure all three with one upload.
    for (i = 10000; i > 0; i--) {
      WRITE(PIO0_1, 1);
      delay_us(1000);
      WRITE(PIO0_1, 0);
      delay_us(1000);
    }
    for (i = 1000; i > 0; i--) {
      WRITE(PIO0_1, 1);
      delay_us(10000);
      WRITE(PIO0_1, 0);
      delay_us(10000);
    }
    for (i = 200; i > 0; i--) {
      WRITE(PIO0_1, 1);
      delay_us(65000);
      WRITE(PIO0_1, 0);
      delay_us(65000);
    }
  }
This commit is contained in:
Markus Hitter 2015-07-27 02:24:33 +02:00
parent 6c31471ffd
commit 8377de8d66
3 changed files with 41 additions and 2 deletions

View File

@ -97,7 +97,7 @@ TARGET = $(PROGRAM).hex
#SOURCES = $(wildcard *.c)
# Until the generic ARM port is completed, we'd have to wrap all sources
# in #ifdef __AVR__. To avoid this, build only a selection for now:
SOURCES = mendel.c cpu.c serial.c sermsg.c sersendf.c
SOURCES = mendel.c cpu.c serial.c sermsg.c sersendf.c delay.c
ifeq ($(MCU), lpc1114)
SOURCES += mbed-system_LPC11xx.c
endif

View File

@ -5,13 +5,51 @@
#if defined TEACUP_C_INCLUDE && defined __ARMEL__
#include "mbed-LPC11xx.h" // For __ASM() and __SYSTEM_CLOCK.
/** Delay in microseconds.
\param delay Time to wait in microseconds.
To Be Defined.
Execution times on ARM aren't as predictable as they could be, because
there's a code prefetch engine which can change timings depending on the
position of the code in Flash. We could use the System Tick Timer for this
task, but this timer is probably better used for more important tasks.
delay_us() and delay_ms() are used only rarely and not in a way which would
require high precision.
Nevertheless, calibrated on the oscilloscope. Measured accuracy:
delay_us(10) ...(100) ...(1000) ...(10000) ...(65000)
48 MHz 10.82 us 100.9 us 1.002 ms 10.01 ms 65.10 ms
CAUTION: this currently works for a 48 MHz clock, only! As other clock rates
appear, there's more math neccessary, see the AVR version. Or simply
a second implementation.
*/
void delay_us(uint16_t delay) {
#if __SYSTEM_CLOCK == 48000000UL
__ASM (".balign 16"); // No gambling with the prefetch engine.
while (delay) {
__ASM volatile (
" nop \n\t" // One nop before the loop slows about 2%.
" nop \n\t"
" movs r7, #4 \n\t" // One more loop round slows about 20%
"1: nop \n\t"
" sub r7, #1 \n\t"
" cmp r7, #0 \n\t"
" bne 1b \n\t"
:
:
: "r7", "cc"
);
delay--;
}
#else
#error No delay_us() implementation for this CPU clock frequency.
#endif
}
#endif /* defined TEACUP_C_INCLUDE && defined __ARMEL__ */

View File

@ -18,6 +18,7 @@
Accuracy on AVR, 20 MHz: delay < 0.04% too long over the whole range.
Accuracy on AVR, 16 MHz: delay < 0.8% too short over the whole range.
Accuracy on ARM, 48 MHz: delay < 0.1% too long over the whole range.
*/
void delay_ms(uint32_t delay) {
wd_reset();