From 8a9ba904e4215b92930a6d71c06c97514bcc6688 Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Mon, 24 Feb 2014 20:30:22 +0100 Subject: [PATCH] use callout from aversive --- callout.c | 329 ----------------------------------------------------- callout.h | 264 ------------------------------------------ commands.c | 21 ++-- main.c | 9 +- main.h | 2 +- 5 files changed, 14 insertions(+), 611 deletions(-) delete mode 100644 callout.c delete mode 100644 callout.h diff --git a/callout.c b/callout.c deleted file mode 100644 index d87d9f7..0000000 --- a/callout.c +++ /dev/null @@ -1,329 +0,0 @@ -/*- - * Copyright (c) <2010>, Intel Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * - Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "callout.h" - -#ifdef CALLOUT_STATS -#define __TIMER_STAT_ADD(cm, field, x) cm->stats.field += x -#else -#define __TIMER_STAT_ADD(cm, field, x) do { } while(0) -#endif - -#ifdef CALLOUT_DEBUG -#define callout_dprintf_P(fmt, ...) printf_P(PSTR("%s(): " fmt), __FUNCTION__, \ - __VA_ARGS__) -#else -#define callout_dprintf_P(...) do { } while (0) -#endif - -/* Initialize a callout manager */ -int -callout_manager_init(struct callout_manager *cm, get_time_t *get_time) -{ - if (get_time == NULL) - return -1; - memset(cm, 0, sizeof(*cm)); - cm->get_time = get_time; - TAILQ_INIT(&cm->pending_list); - return 0; -} - -/* Initialize the timer handle tim for use */ -void -callout_init(struct callout *tim) -{ - memset(tim, 0, sizeof(*tim)); -} - -/* - * add in list (timer must not already be in a list) - */ -static void -callout_add(struct callout_manager *cm, struct callout *tim) -{ - struct callout *t; - - callout_dprintf_P(PSTR("cm=%p tim=%p\r\n"), cm, tim); - - /* list is empty */ - if (TAILQ_EMPTY(&cm->pending_list)) { - TAILQ_INSERT_HEAD(&cm->pending_list, tim, next); - return; - } - - /* 'tim' expires before first entry */ - t = TAILQ_FIRST(&cm->pending_list); - if ((int16_t)(tim->expire - t->expire) < 0) { - TAILQ_INSERT_HEAD(&cm->pending_list, tim, next); - return; - } - - /* find an element that will expire after 'tim' */ - TAILQ_FOREACH(t, &cm->pending_list, next) { - if ((int16_t)(tim->expire - t->expire) < 0) { - TAILQ_INSERT_BEFORE(t, tim, next); - return; - } - } - - /* not found, insert at the end of the list */ - TAILQ_INSERT_TAIL(&cm->pending_list, tim, next); -} - -/* - * del from list (timer must be in a list) - */ -static void -callout_del(struct callout_manager *cm, struct callout *tim) -{ - callout_dprintf_P(PSTR("cm=%p tim=%p\r\n"), cm, tim); - TAILQ_REMOVE(&cm->pending_list, tim, next); -} - -/* Reset and start the timer associated with the timer handle tim */ -static int -__callout_reset(struct callout_manager *cm, struct callout *tim, uint16_t expire, - uint16_t period, callout_cb_t fct, void *arg) -{ - callout_dprintf_P(PSTR("cm=%p tim=%p expire=%d period=%d\r\n"), - cm, tim, expire, period); - - __TIMER_STAT_ADD(cm, reset, 1); - cm->updated = 1; - - /* remove it from list */ - if (tim->scheduled == 1 && tim->running == 0) { - callout_del(cm, tim); - __TIMER_STAT_ADD(cm, pending, -1); - } - - tim->period = period; - tim->expire = expire; - tim->f = fct; - tim->arg = arg; - tim->scheduled = 1; - tim->running = 0; - - __TIMER_STAT_ADD(cm, pending, 1); - callout_add(cm, tim); - - return 0; -} - -/* Reset and start the timer associated with the timer handle tim */ -int -callout_reset(struct callout_manager *cm, struct callout *tim, uint16_t ticks, - enum callout_type type, callout_cb_t fct, void *arg) -{ - uint16_t cur_time = cm->get_time(); - return __callout_reset(cm, tim, ticks + cur_time, - type == PERIODICAL ? ticks : 0, fct, arg); -} - -/* Stop the timer associated with the timer handle tim */ -void -callout_stop(struct callout_manager *cm, struct callout *tim) -{ - callout_dprintf_P(PSTR("cm=%p tim=%p\r\n"), cm, tim); - - __TIMER_STAT_ADD(cm, stop, 1); - cm->updated = 1; - - /* remove it from list */ - if (tim->scheduled == 1 && tim->running == 0) { - callout_del(cm, tim); - __TIMER_STAT_ADD(cm, pending, -1); - } -} - -/* Test the PENDING status of the timer handle tim */ -int -callout_pending(struct callout *tim) -{ - return tim->scheduled == 1; -} - -/* must be called periodically, run all timer that expired */ -void callout_manage(struct callout_manager *cm) -{ - struct callout_list expired_list; - struct callout *tim; - uint16_t cur_time = cm->get_time(); - - callout_dprintf_P(PSTR("cm=%p\r\n"), cm); - - TAILQ_INIT(&expired_list); - __TIMER_STAT_ADD(cm, manage, 1); - - /* move all expired timers in a local list */ - while (!TAILQ_EMPTY(&cm->pending_list)) { - tim = TAILQ_FIRST(&cm->pending_list); - - if ((int16_t)(cur_time - tim->expire) < 0) - break; - - TAILQ_REMOVE(&cm->pending_list, tim, next); - TAILQ_INSERT_TAIL(&expired_list, tim, next); - } - - /* for each timer of 'expired' list, execute callback */ - while (!TAILQ_EMPTY(&expired_list)) { - tim = TAILQ_FIRST(&expired_list); - TAILQ_REMOVE(&expired_list, tim, next); - - cm->updated = 0; - - /* execute callback function with list unlocked */ - __TIMER_STAT_ADD(cm, pending, -1); - __TIMER_STAT_ADD(cm, running, 1); - tim->running = 1; - tim->f(cm, tim, tim->arg); - __TIMER_STAT_ADD(cm, running, -1); - - /* the timer was stopped or reloaded by the callback - * function, we have nothing to do here */ - if (cm->updated == 1) - continue; - - tim->running = 0; - tim->scheduled = 0; - - /* if timer type is periodical, reschedule */ - if (tim->period != 0) { - __callout_reset(cm, tim, cur_time + tim->period, - tim->period, tim->f, tim->arg); - } - } -} - -/* dump statistics about timers */ -void callout_dump_stats(struct callout_manager *cm) -{ -#ifdef CALLOUT_STATS - printf_P(PSTR("Timer statistics:\r\n")); - printf_P(PSTR(" reset = %d\r\n"), cm->stats.reset); - printf_P(PSTR(" stop = %d\r\n"), cm->stats.stop); - printf_P(PSTR(" manage = %d\r\n"), cm->stats.manage); - printf_P(PSTR(" pending = %d\r\n"), cm->stats.pending); - printf_P(PSTR(" running = %d\r\n"), cm->stats.running); -#else - printf_P(PSTR("No timer statistics, CALLOUT_STATS is disabled\r\n")); -#endif -} - -#if 0 - -/******************************/ - -#include -#include - -static uint16_t get_time(void) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - return tv.tv_sec; -} - -static void cb1(struct callout_manager *cm, struct callout *tim, void *arg); -static void cb2(struct callout_manager *cm, struct callout *tim, void *arg); -static void cb3(struct callout_manager *cm, struct callout *tim, void *arg); - -static void cb1(struct callout_manager *cm, struct callout *tim, void *arg) -{ - static int cnt; - arg = arg; /* silent compiler */ - - printf_P(PSTR("cb1\r\n")); - callout_dump_stats(cm); - if (++cnt >= 4) - callout_stop(cm, tim); -} - -static void cb2(struct callout_manager *cm, struct callout *tim, void *arg) -{ - static int cnt; - struct callout *t3 = arg; - - printf_P(PSTR("cb2\r\n")); - if (++cnt < 3) - callout_reset(cm, tim, 5, SINGLE, cb2, arg); - else - callout_reset(cm, t3, 1, SINGLE, cb3, NULL); -} - -static void cb3(struct callout_manager *cm, struct callout *tim, void *arg) -{ - cm = cm; /* silent compiler */ - tim = tim; /* silent compiler */ - arg = arg; /* silent compiler */ - - printf_P(PSTR("cb3\r\n")); -} - -int main(void) -{ - struct callout_manager cm; - struct callout t1, t2, t3; - int i; - - if (callout_manager_init(&cm, get_time) < 0) - return -1; - - callout_init(&t1); - callout_init(&t2); - callout_init(&t3); - - callout_reset(&cm, &t1, 3, PERIODICAL, cb1, NULL); - callout_reset(&cm, &t2, 5, SINGLE, cb2, &t3); - - for (i = 0; i < 18; i++) { - callout_manage(&cm); - sleep(1); - } - - callout_dump_stats(&cm); - return 0; -} - -#endif diff --git a/callout.h b/callout.h deleted file mode 100644 index dca98dd..0000000 --- a/callout.h +++ /dev/null @@ -1,264 +0,0 @@ -/*- - * Copyright (c) <2010>, Intel Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * - Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _CALLOUT_H_ -#define _CALLOUT_H_ - -#define CALLOUT_STATS -//#define CALLOUT_DEBUG - -/** - * @file - * Callout - * - * This library provides a timer service to Aversive. Instead of beeing - * called from interrupt (like the scheduler lib does), these kind of timers - * are not preemptive and should (for instance) be called from a main-loop. - * - * - Timers can be periodic or single (one-shot). - * - * This library provides an interface to add, delete and restart a - * timer. The API is based on the BSD callout(9) with few - * differences. - * - */ - -#ifdef CALLOUT_STATS -/** - * A structure that stores the timer statistics (per-lcore). - */ -struct callout_debug_stats { - uint16_t reset; /**< Number of success calls to callout_reset(). */ - uint16_t stop; /**< Number of success calls to callout_stop(). */ - uint16_t manage; /**< Number of calls to callout_manage(). */ - uint16_t pending; /**< Number of pending timers. */ - uint16_t running; /**< Number of running timers. */ -}; -extern struct callout_debug_stats callout_debug_stats; -#endif - -struct callout; -struct callout_manager; - -/** - * Callback function for the timer. - */ -typedef void (callout_cb_t)(struct callout_manager *, struct callout *, void *); - -/** - * A structure describing a timer in RTE. - */ -struct callout -{ - TAILQ_ENTRY(callout) next; /**< Next and prev in list. */ - - uint8_t periodical: 1; /**< timer is periodical or not */ - uint8_t scheduled: 1; /**< true if timer is scheduled */ - uint8_t running: 1; /**< true if cb func is beeing executed */ - uint8_t reserved: 5; - - uint16_t period; /**< Period of timer (0 if not periodic). */ - uint16_t expire; /**< Time when timer expire. */ - callout_cb_t *f; /**< Callback function. */ - void *arg; /**< Argument to callback function. */ -}; - -/** - * a list of timers - */ -TAILQ_HEAD(callout_list, callout); - -/** - * A static initializer for a timer structure. - */ -#define CALLOUT_INITIALIZER { } - -/** - * Function used by a callout manager to get a time reference - */ -typedef uint16_t (get_time_t)(void); - -/** - * A instance of callout manager (it is possible to have several) - */ -struct callout_manager { - get_time_t *get_time; - uint8_t updated: 1; - uint8_t reserved: 7; - uint16_t prev_time; - struct callout_list pending_list; -#ifdef CALLOUT_STATS - /* statistics */ - struct callout_debug_stats stats; -#endif -}; - -/** - * Initialize a callout manager - * - * @param cm - * The uninitialized callout manager structure. - * @param get_time - * Pointer to a function that returns a time reference (unsigned 16 bits) - * @return - * - 0 on success - * - negative on error - */ -int -callout_manager_init(struct callout_manager *cm, get_time_t *get_time); - -/** - * Initialize a timer handle. - * - * The callout_init() function initializes the timer handle tim - * for use. No operations can be performed on the timer before it is - * initialized. - * - * @param tim - * The timer to initialize. - */ -void callout_init(struct callout *tim); - -/** - * Timer type: Periodic or single (one-shot). - */ -enum callout_type { - SINGLE, - PERIODICAL -}; - -/** - * Reset and start the timer associated with the timer handle. - * - * The callout_reset() function resets and starts the timer - * associated with the timer handle tim. When the timer expires after - * ticks/hz seconds, the function specified by *fct* will be called - * with the argument *arg* on core *tim_lcore*. - * - * If the timer associated with the timer handle is already running - * (in the RUNNING state), the function will fail. The user has to check - * the return value of the function to see if there is a chance that the - * timer is in the RUNNING state. - * - * If the timer is being configured on another core (the CONFIG state), - * it will also fail. - * - * If the timer is pending or stopped, it will be rescheduled with the - * new parameters. - * - * @param tim - * The timer handle. - * @param ticks - * The number of cycles (see rte_get_hpet_hz()) before the callback - * function is called. - * @param type - * The type can be either: - * - PERIODICAL: The timer is automatically reloaded after execution - * (returns to the PENDING state) - * - SINGLE: The timer is one-shot, that is, the timer goes to a - * STOPPED state after execution. - * @param tim_lcore - * The ID of the lcore where the timer callback function has to be - * executed. If tim_lcore is LCORE_ID_ANY, the timer library will - * launch it on a different core for each call (round-robin). - * @param fct - * The callback function of the timer. - * @param arg - * The user argument of the callback function. - * @return - * - 0: Success; the timer is scheduled. - * - (-1): Timer is in the RUNNING or CONFIG state. - */ -int callout_reset(struct callout_manager *cm, struct callout *tim, - uint16_t ticks, enum callout_type type, - callout_cb_t fct, void *arg); - - -/** - * Stop a timer. - * - * The callout_stop() function stops the timer associated with the - * timer handle tim. It may fail if the timer is currently running or - * being configured. - * - * If the timer is pending or stopped (for instance, already expired), - * the function will succeed. The timer handle tim must have been - * initialized using callout_init(), otherwise, undefined behavior - * will occur. - * - * This function can be called safely from a timer callback. If it - * succeeds, the timer is not referenced anymore by the timer library - * and the timer structure can be freed (even in the callback - * function). - * - * @param tim - * The timer handle. - */ -void callout_stop(struct callout_manager *cm, struct callout *tim); - - -/** - * Test if a timer is pending. - * - * The callout_pending() function tests the PENDING status - * of the timer handle tim. A PENDING timer is one that has been - * scheduled and whose function has not yet been called. - * - * @param tim - * The timer handle. - * @return - * - 0: The timer is not pending. - * - 1: The timer is pending. - */ -int callout_pending(struct callout *tim); - -/** - * Manage the timer list and execute callback functions. - * - * This function must be called periodically from all cores - * main_loop(). It browses the list of pending timers and runs all - * timers that are expired. - * - * The precision of the timer depends on the call frequency of this - * function. However, the more often the function is called, the more - * it will use CPU resources. - */ -void callout_manage(struct callout_manager *cm); - -/** - * Dump statistics about timers. - */ -void callout_dump_stats(struct callout_manager *cm); - -#endif /* _CALLOUT_H_ */ diff --git a/commands.c b/commands.c index 2e02551..df76f47 100644 --- a/commands.c +++ b/commands.c @@ -73,7 +73,7 @@ static struct callout range_event; static int range_count = 100; static int range_cur_count = 0; -static void monitor_cb(struct callout_manager *cm, +static void monitor_cb(struct callout_mgr *cm, struct callout *clt, void *dummy) { (void)clt; @@ -84,12 +84,10 @@ static void monitor_cb(struct callout_manager *cm, xbeeapp_send_atcmd(monitor_current->atcmd, NULL, 0, 0, NULL, NULL); monitor_current = LIST_NEXT(monitor_current, next); - callout_reset(cm, &monitor_event, - monitor_period_ms / monitor_count, - SINGLE, monitor_cb, NULL); + callout_reschedule(cm, clt, monitor_period_ms / monitor_count); } -static void range_cb(struct callout_manager *cm, +static void range_cb(struct callout_mgr *cm, struct callout *clt, void *dummy) { (void)cm; @@ -124,9 +122,7 @@ static void range_cb(struct callout_manager *cm, return; } - callout_reset(cm, &range_event, - range_period_ms, - SINGLE, range_cb, NULL); + callout_reschedule(cm, clt, range_period_ms); #endif } @@ -744,9 +740,8 @@ static void cmd_range_parsed(void *parsed_result, void *data) return; } range_cur_count = range_count; - callout_init(&range_event); - callout_reset(&cm, &range_event, 0, - SINGLE, range_cb, NULL); + callout_init(&range_event, range_cb, NULL, 0); + callout_schedule(&cm, &range_event, 0); /* immediate */ range_running = 1; } else if (!strcmp(res->action, "end")) { @@ -994,8 +989,8 @@ static void cmd_monitor_parsed(void *parsed_result, void *data) printf_P(PSTR("no regs to be monitored\r\n")); return; } - callout_init(&monitor_event); - callout_reset(&cm, &monitor_event, 0, SINGLE, monitor_cb, NULL); + callout_init(&monitor_event, monitor_cb, NULL, 0); + callout_schedule(&cm, &monitor_event, 0); /* immediate */ monitor_running = 1; monitor_current = LIST_FIRST(&xbee_monitor_list); printf_P(PSTR("monitor cb: %S %s\r\n"), diff --git a/main.c b/main.c index c3511b5..3959ee4 100644 --- a/main.c +++ b/main.c @@ -58,7 +58,7 @@ struct xbeeboard xbeeboard; volatile uint16_t global_ms; -struct callout_manager cm; +struct callout_mgr cm; #define TIMEOUT_MS 1000 @@ -501,7 +501,7 @@ void xbee_stdin_disable(void) xbee_cmdline_input_enabled = 0; } -static void evt_timeout(struct callout_manager *cm, struct callout *clt, +static void evt_timeout(struct callout_mgr *cm, struct callout *clt, void *arg) { struct xbee_ctx *ctx = arg; @@ -521,7 +521,8 @@ static void evt_timeout(struct callout_manager *cm, struct callout *clt, void xbee_load_timeout(struct xbee_ctx *ctx) { - callout_reset(&cm, &ctx->timeout, TIMEOUT_MS, SINGLE, evt_timeout, ctx); + callout_init(&ctx->timeout, evt_timeout, ctx, 0); + callout_schedule(&cm, &ctx->timeout, TIMEOUT_MS); } void xbee_unload_timeout(struct xbee_ctx *ctx) @@ -656,7 +657,7 @@ int main(void) spi_servo_init(); beep_init(); - callout_manager_init(&cm, get_time_ms); + callout_mgr_init(&cm, get_time_ms); //callout_reset(&cm, &t1, 500, PERIODICAL, do_led_blink, NULL); /* initialize libxbee */ diff --git a/main.h b/main.h index 1ad2c0b..f77a535 100644 --- a/main.h +++ b/main.h @@ -100,7 +100,7 @@ extern int xbee_raw; extern int xbee_hexdump; extern int xbee_debug; -extern struct callout_manager cm; +extern struct callout_mgr cm; void bootloader(void); -- 2.39.5