diff --git a/ports/stm32f10x/mstimer-init.c b/ports/stm32f10x/mstimer-init.c index 41184a72..6e594da4 100644 --- a/ports/stm32f10x/mstimer-init.c +++ b/ports/stm32f10x/mstimer-init.c @@ -29,64 +29,19 @@ #include #include "hardware.h" #include "bacnet/basic/sys/mstimer.h" -#include "bacnet/basic/sys/debug.h" /* counter for the various timers */ static volatile unsigned long Millisecond_Counter; -static volatile struct mstimer_callback_data_t *Callback_Head; - -/** - * Activate the LED - */ -static void timer_debug_on(void) -{ - GPIO_WriteBit(GPIOB, GPIO_Pin_13, Bit_SET); -} - -/** - * Deactivate the LED - */ -static void timer_debug_off(void) -{ - GPIO_WriteBit(GPIOB, GPIO_Pin_13, Bit_RESET); -} - -/** - * Toggle the state of the debug LED - */ -static void timer_debug_toggle(void) -{ - static bool state = false; - - if (state) { - timer_debug_off(); - state = false; - } else { - timer_debug_on(); - state = true; - } -} /** * Handles the interrupt from the timer */ void SysTick_Handler(void) { - struct mstimer_callback_data_t *cb; - /* increment the tick count */ Millisecond_Counter++; - cb = (struct mstimer_callback_data_t *)Callback_Head; - while (cb) { - if (mstimer_expired(&cb->timer)) { - cb->callback(); - if (mstimer_interval(&cb->timer) > 0) { - mstimer_reset(&cb->timer); - } - } - cb = cb->next; - } - timer_debug_toggle(); + /* run any callbacks */ + mstimer_callback_handler(); } /** @@ -99,58 +54,16 @@ unsigned long mstimer_now(void) return Millisecond_Counter; } -/** - * Configures and enables a repeating callback function - * - * @param cb - pointer to a #mstimer_callback_data_t - * @param callback - pointer to a #timer_callback_function function - * @param milliseconds - how often to call the function - * - * @return true if successfully added and enabled - */ -void mstimer_callback(struct mstimer_callback_data_t *new_cb, - mstimer_callback_function callback, - unsigned long milliseconds) -{ - struct mstimer_callback_data_t *cb; - - if (new_cb) { - new_cb->callback = callback; - mstimer_set(&new_cb->timer, milliseconds); - } - if (Callback_Head) { - cb = (struct mstimer_callback_data_t *)Callback_Head; - while (cb) { - if (!cb->next) { - cb->next = new_cb; - break; - } else { - cb = cb->next; - } - } - } else { - Callback_Head = new_cb; - } -} - /** * Timer setup for 1 millisecond timer */ void mstimer_init(void) { - GPIO_InitTypeDef GPIO_InitStructure; - - GPIO_StructInit(&GPIO_InitStructure); - /* Configure the Receive LED */ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; - GPIO_Init(GPIOB, &GPIO_InitStructure); - /* Setup SysTick Timer for 1ms interrupts */ if (SysTick_Config(SystemCoreClock / 1000)) { - /* Capture error */ - while (1) - ; + while (1) { + /* config error? return 1 = failed, 0 = successful */ + } } + NVIC_EnableIRQ(SysTick_IRQn); } diff --git a/ports/stm32f4xx/mstimer-init.c b/ports/stm32f4xx/mstimer-init.c index baa3fc80..2faeab9f 100644 --- a/ports/stm32f4xx/mstimer-init.c +++ b/ports/stm32f4xx/mstimer-init.c @@ -34,36 +34,16 @@ /* counter for the various timers */ static volatile unsigned long Millisecond_Counter; -static volatile struct mstimer_callback_data_t *Callback_Head; - -/** - * Toggle the state of the debug LED - */ -static void timer_debug_toggle(void) -{ - led_toggle(LED_LD1); -} /** * Handles the interrupt from the timer */ void SysTick_Handler(void) { - struct mstimer_callback_data_t *cb; - /* increment the tick count */ Millisecond_Counter++; - cb = (struct mstimer_callback_data_t *)Callback_Head; - while (cb) { - if (mstimer_expired(&cb->timer)) { - cb->callback(); - if (mstimer_interval(&cb->timer) > 0) { - mstimer_reset(&cb->timer); - } - } - cb = cb->next; - } - timer_debug_toggle(); + /* run any callbacks */ + mstimer_callback_handler(); } /** @@ -76,40 +56,6 @@ unsigned long mstimer_now(void) return Millisecond_Counter; } -/** - * Configures and enables a repeating callback function - * - * @param cb - pointer to a #mstimer_callback_data_t - * @param callback - pointer to a #timer_callback_function function - * @param milliseconds - how often to call the function - * - * @return true if successfully added and enabled - */ -void mstimer_callback(struct mstimer_callback_data_t *new_cb, - mstimer_callback_function callback, - unsigned long milliseconds) -{ - struct mstimer_callback_data_t *cb; - - if (new_cb) { - new_cb->callback = callback; - mstimer_set(&new_cb->timer, milliseconds); - } - if (Callback_Head) { - cb = (struct mstimer_callback_data_t *)Callback_Head; - while (cb) { - if (!cb->next) { - cb->next = new_cb; - break; - } else { - cb = cb->next; - } - } - } else { - Callback_Head = new_cb; - } -} - /** * Timer setup for 1 millisecond timer */ @@ -117,9 +63,9 @@ void mstimer_init(void) { /* Setup SysTick Timer for 1ms interrupts */ if (SysTick_Config(SystemCoreClock / 1000)) { - /* Capture error */ - while (1) - ; + while (1) { + /* config error? return 1 = failed, 0 = successful */ + } } NVIC_EnableIRQ(SysTick_IRQn); } diff --git a/ports/xplained/mstimer-init.c b/ports/xplained/mstimer-init.c index 06bec0b6..0c93e512 100644 --- a/ports/xplained/mstimer-init.c +++ b/ports/xplained/mstimer-init.c @@ -35,32 +35,31 @@ #include "tc.h" #include "bacnet/basic/sys/mstimer.h" -/* define which timer counter we are using */ -#define MY_TIMER TCE0 +/* define which timer for the counter we are using */ +#define MS_TIMER_COUNTER TCE0 +/* define which timer for the callback we are using */ +#define MS_TIMER_CALLBACK TCE1 /* counter for the base timer */ static volatile uint32_t Millisecond_Counter; -/* callback data head of list */ -static volatile struct mstimer_callback_data_t *Callback_Head; /** - * Handles the interrupt from the timer + * Handles an interrupt from a hardware millisecond timer */ -static void my_callback(void) +static void my_counter_handler(void) { - struct mstimer_callback_data_t *cb; - Millisecond_Counter++; - cb = (struct mstimer_callback_data_t *)Callback_Head; - while (cb) { - if (mstimer_expired(&cb->timer)) { - cb->callback(); - if (mstimer_interval(&cb->timer) > 0) { - mstimer_reset(&cb->timer); - } - } - cb = cb->next; - } +} + +/** + * Handles an interrupt from a hardware millisecond timer + */ +static void my_callback_handler(void) +{ + /* callback might go too long; prevent re-entrency by disable IRQ source */ + tc_set_overflow_interrupt_level(&MS_TIMER_CALLBACK, TC_INT_LVL_OFF); + mstimer_callback_handler(); + tc_set_overflow_interrupt_level(&MS_TIMER_CALLBACK, TC_INT_LVL_LO); } /** @@ -72,49 +71,13 @@ unsigned long mstimer_now(void) { uint32_t timer_value; /* return value */ - tc_set_overflow_interrupt_level(&MY_TIMER, TC_INT_LVL_OFF); + tc_set_overflow_interrupt_level(&MS_TIMER_COUNTER, TC_INT_LVL_OFF); timer_value = Millisecond_Counter; - tc_set_overflow_interrupt_level(&MY_TIMER, TC_INT_LVL_LO); + tc_set_overflow_interrupt_level(&MS_TIMER_COUNTER, TC_INT_LVL_LO); return timer_value; } -/** - * Configures and enables a repeating callback function - * - * @param new_cb - pointer to #mstimer_callback_data_t - * @param callback - pointer to a #timer_callback_function function - * @param milliseconds - how often to call the function - * - * @return true if successfully added and enabled - */ -void mstimer_callback(struct mstimer_callback_data_t *new_cb, - mstimer_callback_function callback, - unsigned long milliseconds) -{ - struct mstimer_callback_data_t *cb; - - tc_set_overflow_interrupt_level(&MY_TIMER, TC_INT_LVL_OFF); - if (new_cb) { - new_cb->callback = callback; - mstimer_set(&new_cb->timer, milliseconds); - } - if (Callback_Head) { - cb = (struct mstimer_callback_data_t *)Callback_Head; - while (cb) { - if (!cb->next) { - cb->next = new_cb; - break; - } else { - cb = cb->next; - } - } - } else { - Callback_Head = new_cb; - } - tc_set_overflow_interrupt_level(&MY_TIMER, TC_INT_LVL_LO); -} - /** * Timer setup for 1 millisecond timer */ @@ -122,13 +85,25 @@ void mstimer_init(void) { unsigned long period; - tc_enable(&MY_TIMER); - tc_set_overflow_interrupt_callback(&MY_TIMER, my_callback); - tc_set_wgm(&MY_TIMER, TC_WG_NORMAL); - tc_write_count(&MY_TIMER, 1); - period = sysclk_get_peripheral_bus_hz(&MY_TIMER); + tc_enable(&MS_TIMER_COUNTER); + tc_set_overflow_interrupt_callback(&MS_TIMER_COUNTER, + mstimer_counter_handler); + tc_set_wgm(&MS_TIMER_COUNTER, TC_WG_NORMAL); + tc_write_count(&MS_TIMER_COUNTER, 1); + period = sysclk_get_peripheral_bus_hz(&MS_TIMER_COUNTER); period /= 1000; - tc_write_period(&MY_TIMER, period); - tc_set_overflow_interrupt_level(&MY_TIMER, TC_INT_LVL_LO); - tc_write_clock_source(&MY_TIMER, TC_CLKSEL_DIV1_gc); + tc_write_period(&MS_TIMER_COUNTER, period); + tc_set_overflow_interrupt_level(&MS_TIMER_COUNTER, TC_INT_LVL_LO); + tc_write_clock_source(&MS_TIMER_COUNTER, TC_CLKSEL_DIV1_gc); + + tc_enable(&MS_TIMER_CALLBACK); + tc_set_overflow_interrupt_callback(&MS_TIMER_CALLBACK, + my_callback_handler); + tc_set_wgm(&MS_TIMER_CALLBACK, TC_WG_NORMAL); + tc_write_count(&MS_TIMER_CALLBACK, 1); + period = sysclk_get_peripheral_bus_hz(&MS_TIMER_CALLBACK); + period /= 1000; + tc_write_period(&MS_TIMER_CALLBACK, period); + tc_set_overflow_interrupt_level(&MS_TIMER_CALLBACK, TC_INT_LVL_LO); + tc_write_clock_source(&MS_TIMER_CALLBACK, TC_CLKSEL_DIV1_gc); } diff --git a/src/bacnet/basic/sys/mstimer.c b/src/bacnet/basic/sys/mstimer.c index 38a2fef3..9fabb4c1 100644 --- a/src/bacnet/basic/sys/mstimer.c +++ b/src/bacnet/basic/sys/mstimer.c @@ -22,6 +22,60 @@ #include #include "bacnet/basic/sys/mstimer.h" +/* callback data head of list */ +static struct mstimer_callback_data_t *Callback_Head; + +/** + * Handles an interrupt from a hardware millisecond timer + */ +void mstimer_callback_handler(void) +{ + struct mstimer_callback_data_t *cb; + + cb = (struct mstimer_callback_data_t *)Callback_Head; + while (cb) { + if (mstimer_expired(&cb->timer)) { + cb->callback(); + if (mstimer_interval(&cb->timer) > 0) { + mstimer_reset(&cb->timer); + } + } + cb = cb->next; + } +} + +/** + * Configures and enables a repeating callback function + * + * @param new_cb - pointer to #mstimer_callback_data_t + * @param callback - pointer to a #timer_callback_function function + * @param milliseconds - how often to call the function + */ +void mstimer_callback(struct mstimer_callback_data_t *new_cb, + mstimer_callback_function callback, + unsigned long milliseconds) +{ + struct mstimer_callback_data_t *cb; + + if (new_cb) { + new_cb->callback = callback; + mstimer_set(&new_cb->timer, milliseconds); + } + if (Callback_Head) { + cb = (struct mstimer_callback_data_t *)Callback_Head; + while (cb) { + if (!cb->next) { + cb->next = new_cb; + break; + } else { + cb = cb->next; + } + } + } else { + Callback_Head = new_cb; + } +} + /** * @brief Set a timer for a time sometime in the future * diff --git a/src/bacnet/basic/sys/mstimer.h b/src/bacnet/basic/sys/mstimer.h index 997e0134..3a1a8c42 100644 --- a/src/bacnet/basic/sys/mstimer.h +++ b/src/bacnet/basic/sys/mstimer.h @@ -35,8 +35,9 @@ struct mstimer { unsigned long interval; }; +/* optional callback function form */ typedef void (*mstimer_callback_function) (void); -/* callback data structure */ +/* optional callback data structure */ struct mstimer_callback_data_t; struct mstimer_callback_data_t { struct mstimer timer; @@ -62,15 +63,18 @@ BACNET_STACK_EXPORT unsigned long mstimer_elapsed(struct mstimer *t); BACNET_STACK_EXPORT unsigned long mstimer_interval(struct mstimer *t); -/* HAL implementation */ -BACNET_STACK_EXPORT -unsigned long mstimer_now(void); +/* optional callback timer support for embedded systems */ BACNET_STACK_EXPORT void mstimer_callback( struct mstimer_callback_data_t *cb, mstimer_callback_function callback, unsigned long milliseconds); BACNET_STACK_EXPORT +void mstimer_callback_handler(void); +/* HAL implementation */ +BACNET_STACK_EXPORT +unsigned long mstimer_now(void); +BACNET_STACK_EXPORT void mstimer_init(void); #ifdef __cplusplus