ARM: split out architecture specific parts for delay.c
(Hopefully) no functional change. Also remove these wd_reset()s in delay_us() to match the behaviour promised in delay.h. Not that this matters much, watchdog is disabled by default.
This commit is contained in:
parent
e2df7733ee
commit
6c31471ffd
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
\brief Delay routines, ARM specific part.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined TEACUP_C_INCLUDE && defined __ARMEL__
|
||||||
|
|
||||||
|
/** Delay in microseconds.
|
||||||
|
|
||||||
|
\param delay Time to wait in microseconds.
|
||||||
|
|
||||||
|
To Be Defined.
|
||||||
|
*/
|
||||||
|
void delay_us(uint16_t delay) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined TEACUP_C_INCLUDE && defined __ARMEL__ */
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
\brief Delay routines, AVR specific part.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined TEACUP_C_INCLUDE && defined __AVR__
|
||||||
|
|
||||||
|
#include <util/delay_basic.h>
|
||||||
|
|
||||||
|
#if F_CPU < 4000000UL
|
||||||
|
#error Delay functions on AVR only work with F_CPU >= 4000000UL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/** Delay in microseconds.
|
||||||
|
|
||||||
|
\param delay Time to wait in microseconds.
|
||||||
|
|
||||||
|
Calibrated in SimulAVR.
|
||||||
|
|
||||||
|
Accuracy on 20 MHz CPU clock: -1/+3 clock cycles over the whole range(!).
|
||||||
|
Accuracy on 16 MHz CPU clock: delay is about 0.8% too short.
|
||||||
|
|
||||||
|
Exceptions are delays of 0..2 on 20 MHz, which are all 0.75 us and delays
|
||||||
|
of 0..3 on 16 MHz, which are all 0.93us.
|
||||||
|
*/
|
||||||
|
void delay_us(uint16_t delay) {
|
||||||
|
// Compensate call overhead, as close as possible.
|
||||||
|
#define OVERHEAD_CALL_CLOCKS 39 // clock cycles
|
||||||
|
#define OVERHEAD_CALL_DIV ((OVERHEAD_CALL_CLOCKS / (F_CPU / 1000000)) + 1)
|
||||||
|
#define OVERHEAD_CALL_REM ((OVERHEAD_CALL_DIV * (F_CPU / 1000000)) - \
|
||||||
|
OVERHEAD_CALL_CLOCKS)
|
||||||
|
|
||||||
|
if (delay > OVERHEAD_CALL_DIV) {
|
||||||
|
delay -= OVERHEAD_CALL_DIV;
|
||||||
|
if (OVERHEAD_CALL_REM >= 2)
|
||||||
|
_delay_loop_2((OVERHEAD_CALL_REM + 2) / 4);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (delay > (65536L / (F_CPU / 4000000L))) {
|
||||||
|
#define OVERHEAD_LOOP_CLOCKS 13
|
||||||
|
|
||||||
|
_delay_loop_2(65536 - (OVERHEAD_LOOP_CLOCKS + 2) / 4);
|
||||||
|
delay -= (65536L / (F_CPU / 4000000L));
|
||||||
|
}
|
||||||
|
if (delay)
|
||||||
|
_delay_loop_2(delay * (F_CPU / 4000000L));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined TEACUP_C_INCLUDE && defined __AVR__ */
|
||||||
58
delay.c
58
delay.c
|
|
@ -4,60 +4,20 @@
|
||||||
\brief Delay routines
|
\brief Delay routines
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#define TEACUP_C_INCLUDE
|
||||||
#include <util/delay_basic.h>
|
#include "delay-avr.c"
|
||||||
|
#include "delay-arm.c"
|
||||||
|
#undef TEACUP_C_INCLUDE
|
||||||
|
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
|
|
||||||
#if F_CPU < 4000000UL
|
|
||||||
#error Delay functions only work with F_CPU >= 4000000UL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Delay in microseconds
|
/** Delay in milliseconds.
|
||||||
\param delay time to wait in microseconds
|
|
||||||
|
|
||||||
Calibrated in SimulAVR.
|
\param delay Time to wait in milliseconds.
|
||||||
|
|
||||||
Accuracy on 20 MHz CPU clock: -1/+3 clock cycles over the whole range(!).
|
Accuracy on AVR, 20 MHz: delay < 0.04% too long over the whole range.
|
||||||
Accuracy on 16 MHz CPU clock: delay is about 0.8% too short.
|
Accuracy on AVR, 16 MHz: delay < 0.8% too short over the whole range.
|
||||||
|
|
||||||
Exceptions are delays of 0..2 on 20 MHz, which are all 0.75 us and delays
|
|
||||||
of 0..3 on 16 MHz, which are all 0.93us.
|
|
||||||
*/
|
|
||||||
void delay_us(uint16_t delay) {
|
|
||||||
wd_reset();
|
|
||||||
|
|
||||||
// Compensate call overhead, as close as possible.
|
|
||||||
#define OVERHEAD_CALL_CLOCKS 39 // clock cycles
|
|
||||||
#define OVERHEAD_CALL_DIV ((OVERHEAD_CALL_CLOCKS / (F_CPU / 1000000)) + 1)
|
|
||||||
#define OVERHEAD_CALL_REM ((OVERHEAD_CALL_DIV * (F_CPU / 1000000)) - \
|
|
||||||
OVERHEAD_CALL_CLOCKS)
|
|
||||||
|
|
||||||
if (delay > OVERHEAD_CALL_DIV) {
|
|
||||||
delay -= OVERHEAD_CALL_DIV;
|
|
||||||
if (OVERHEAD_CALL_REM >= 2)
|
|
||||||
_delay_loop_2((OVERHEAD_CALL_REM + 2) / 4);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (delay > (65536L / (F_CPU / 4000000L))) {
|
|
||||||
#define OVERHEAD_LOOP_CLOCKS 13
|
|
||||||
|
|
||||||
_delay_loop_2(65536 - (OVERHEAD_LOOP_CLOCKS + 2) / 4);
|
|
||||||
delay -= (65536L / (F_CPU / 4000000L));
|
|
||||||
wd_reset();
|
|
||||||
}
|
|
||||||
if (delay)
|
|
||||||
_delay_loop_2(delay * (F_CPU / 4000000L));
|
|
||||||
wd_reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delay in microseconds
|
|
||||||
\param delay time to wait in milliseconds
|
|
||||||
|
|
||||||
Accuracy on 20 MHz: delay < 0.04% too long over the whole range.
|
|
||||||
Accuracy on 16 MHz: delay < 0.8% too short over the whole range.
|
|
||||||
*/
|
*/
|
||||||
void delay_ms(uint32_t delay) {
|
void delay_ms(uint32_t delay) {
|
||||||
wd_reset();
|
wd_reset();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue