fix delay compilation. Takes some of madscifi's ideas yet still provides fallback functions for eg; homing which uses variable delays

This commit is contained in:
Michael Moon 2011-05-10 13:55:08 +10:00
parent 1b1aea7f41
commit 7a57b69cc1
3 changed files with 52 additions and 76 deletions

View File

@ -80,7 +80,7 @@ PROGID = arduino
PROGRAM = mendel
SOURCES = $(PROGRAM).c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c intercom.c pinio.c clock.c home.c crc.c
SOURCES = $(PROGRAM).c dda.c gcode_parse.c gcode_process.c timer.c temp.c sermsg.c dda_queue.c watchdog.c debug.c sersendf.c heater.c analog.c intercom.c pinio.c clock.c home.c crc.c delay.c
ARCH = avr-
CC = $(ARCH)gcc

35
delay.c Normal file
View File

@ -0,0 +1,35 @@
#include "delay.h"
/** \file
\brief Delay routines
*/
#include <util/delay_basic.h>
#include "watchdog.h"
/// delay microseconds
/// \param delay time to wait in microseconds
void delay_us(uint16_t delay) {
wd_reset();
while (delay > (65536L / (F_CPU / 4000000L))) {
_delay_loop_2(65534); // we use 65534 here to compensate for the time that the surrounding loop takes. TODO: exact figure needs tuning
delay -= (65536L / (F_CPU / 4000000L));
wd_reset();
}
_delay_loop_2(delay / (F_CPU / 4000000L));
wd_reset();
}
/// delay milliseconds
/// \param delay time to wait in milliseconds
void _delay_ms(uint32_t delay) {
wd_reset();
while (delay > 65) {
delay_us(64999);
delay -= 65;
wd_reset();
}
delay_us(delay * 1000);
wd_reset();
}

91
delay.h
View File

@ -2,88 +2,29 @@
#define _DELAY_H
#include <stdint.h>
#include <avr/builtins.h>
#include "watchdog.h"
#include <math.h>
#include <util/delay_basic.h>
// WAITING_DELAY is expressed in microseconds
#define WAITING_DELAY 10000
// Force delay functions to be inlined.
// Otherwise they will not work correctly.
static inline void delay_us(uint16_t us) __attribute__((always_inline));
static inline void delay(uint32_t delay) __attribute__((always_inline));
static inline void delay_ms( uint16_t delay ) __attribute__((always_inline));
void delay_us(uint16_t delay);
// Delay for a minimum of us microseconds.
// The parameter us MUST be a compile time constant.
// A compiler error will be issued in the case that
// it is not.
void _delay_ms(uint32_t delay);
void delay_us(uint16_t us)
{
// The floating point calculation will
// be completed during compilation, so
// there is no runtime floating point
// code generated.
uint32_t cycles = ceil( (double)F_CPU * us / 1000000.0 );
__builtin_avr_delay_cycles(cycles);
static void delay(uint32_t) __attribute__ ((always_inline));
inline void delay(uint32_t d) {
if (d >= (65536L / (F_CPU / 4000000L))) {
delay_us(d);
}
else
_delay_loop_2(d * (F_CPU / 4000000L));
}
// Delay for a minimum of us microseconds.
// If the watchdog functionality is enabled
// this function will reset the timer before
// and after the delay (and at least once every
// 65536 microseconds).
//
// This function is forced (see declaration above) to be inlined.
// The parameter us MUST be a compile time constant.
// A compiler error will be issued in the case that
// it is not.
void delay(uint32_t us)
{
int i;
wd_reset();
for( i = 0; i < us/65536; i++ )
{
delay_us(65535);
delay_us(1);
wd_reset();
}
if( us%65536 )
{
delay_us(us%65536);
wd_reset();
}
}
// Delay for a minimum of ms milliseconds.
// If the watchdog functionality is enabled
// this function will reset the timer before
// and after the delay (and at least once every
// 65000 microseconds).
//
// This function is forced (see declaration above) to be inlined.
// The parameter us MUST be a compile time constant.
// A compiler error will be issued in the case that
// it is not.
void delay_ms( uint16_t ms )
{
uint16_t i;
wd_reset();
for( i = 0; i < ms/65; i++ )
{
delay_us(65000);
wd_reset();
}
if( ms%65 )
{
delay_us((ms%65536)*1000);
wd_reset();
}
static void delay_ms(uint32_t) __attribute__ ((always_inline));
inline void delay_ms(uint32_t d) {
if (d > 65)
delay_ms(d);
else
delay_us(d * 1000);
}
#endif /* _DELAY_H */