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:
Markus Hitter 2015-07-26 14:53:48 +02:00
parent e2df7733ee
commit 6c31471ffd
3 changed files with 79 additions and 49 deletions

17
delay-arm.c Normal file
View File

@ -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__ */

53
delay-avr.c Normal file
View File

@ -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
View File

@ -4,60 +4,20 @@
\brief Delay routines
*/
#include <stdint.h>
#include <util/delay_basic.h>
#include "watchdog.h"
#define TEACUP_C_INCLUDE
#include "delay-avr.c"
#include "delay-arm.c"
#undef TEACUP_C_INCLUDE
#if F_CPU < 4000000UL
#error Delay functions only work with F_CPU >= 4000000UL
#endif
#include "watchdog.h"
/** Delay in microseconds
\param delay time to wait in microseconds
Calibrated in SimulAVR.
/** Delay in milliseconds.
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.
\param delay Time to wait in milliseconds.
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.
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.
*/
void delay_ms(uint32_t delay) {
wd_reset();