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 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- ARCH = avr-
CC = $(ARCH)gcc 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 #define _DELAY_H
#include <stdint.h> #include <stdint.h>
#include <avr/builtins.h> #include <util/delay_basic.h>
#include "watchdog.h"
#include <math.h>
// WAITING_DELAY is expressed in microseconds
#define WAITING_DELAY 10000 #define WAITING_DELAY 10000
// Force delay functions to be inlined. void delay_us(uint16_t delay);
// 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));
// Delay for a minimum of us microseconds. void _delay_ms(uint32_t delay);
// The parameter us MUST be a compile time constant.
// A compiler error will be issued in the case that
// it is not.
void delay_us(uint16_t us) static void delay(uint32_t) __attribute__ ((always_inline));
{ inline void delay(uint32_t d) {
// The floating point calculation will if (d >= (65536L / (F_CPU / 4000000L))) {
// be completed during compilation, so delay_us(d);
// there is no runtime floating point }
// code generated. else
uint32_t cycles = ceil( (double)F_CPU * us / 1000000.0 ); _delay_loop_2(d * (F_CPU / 4000000L));
__builtin_avr_delay_cycles(cycles);
} }
// Delay for a minimum of us microseconds. static void delay_ms(uint32_t) __attribute__ ((always_inline));
// If the watchdog functionality is enabled inline void delay_ms(uint32_t d) {
// this function will reset the timer before if (d > 65)
// and after the delay (and at least once every delay_ms(d);
// 65536 microseconds). else
// delay_us(d * 1000);
// 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();
}
} }
#endif /* _DELAY_H */ #endif /* _DELAY_H */