Sam Grove
/
canopen_slavenode
CANfestival - an open source CANopen framework
framework/src/canopen_timer.c@6:bc64031ac849, 2012-09-26 (annotated)
- Committer:
- sam_grove
- Date:
- Wed Sep 26 05:43:05 2012 +0000
- Revision:
- 6:bc64031ac849
- Parent:
- 0:6219434a0cb5
Change a typecast in can_mbed.cpp from unit8_t * to char * to fit the CANMessage constructor
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
sam_grove |
0:6219434a0cb5 | 1 | /* |
sam_grove |
0:6219434a0cb5 | 2 | This file is part of CanFestival, a library implementing CanOpen Stack. |
sam_grove |
0:6219434a0cb5 | 3 | |
sam_grove |
0:6219434a0cb5 | 4 | Copyright (C): Edouard TISSERANT and Francis DUPIN |
sam_grove |
0:6219434a0cb5 | 5 | |
sam_grove |
0:6219434a0cb5 | 6 | See COPYING file for copyrights details. |
sam_grove |
0:6219434a0cb5 | 7 | |
sam_grove |
0:6219434a0cb5 | 8 | This library is free software; you can redistribute it and/or |
sam_grove |
0:6219434a0cb5 | 9 | modify it under the terms of the GNU Lesser General Public |
sam_grove |
0:6219434a0cb5 | 10 | License as published by the Free Software Foundation; either |
sam_grove |
0:6219434a0cb5 | 11 | version 2.1 of the License, or (at your option) any later version. |
sam_grove |
0:6219434a0cb5 | 12 | |
sam_grove |
0:6219434a0cb5 | 13 | This library is distributed in the hope that it will be useful, |
sam_grove |
0:6219434a0cb5 | 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
sam_grove |
0:6219434a0cb5 | 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
sam_grove |
0:6219434a0cb5 | 16 | Lesser General Public License for more details. |
sam_grove |
0:6219434a0cb5 | 17 | |
sam_grove |
0:6219434a0cb5 | 18 | You should have received a copy of the GNU Lesser General Public |
sam_grove |
0:6219434a0cb5 | 19 | License along with this library; if not, write to the Free Software |
sam_grove |
0:6219434a0cb5 | 20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
sam_grove |
0:6219434a0cb5 | 21 | */ |
sam_grove |
0:6219434a0cb5 | 22 | /*! |
sam_grove |
0:6219434a0cb5 | 23 | ** @file timer.c |
sam_grove |
0:6219434a0cb5 | 24 | ** @author Edouard TISSERANT and Francis DUPIN |
sam_grove |
0:6219434a0cb5 | 25 | ** @date Tue Jun 5 09:32:32 2007 |
sam_grove |
0:6219434a0cb5 | 26 | ** |
sam_grove |
0:6219434a0cb5 | 27 | ** @brief |
sam_grove |
0:6219434a0cb5 | 28 | ** |
sam_grove |
0:6219434a0cb5 | 29 | ** |
sam_grove |
0:6219434a0cb5 | 30 | */ |
sam_grove |
0:6219434a0cb5 | 31 | |
sam_grove |
0:6219434a0cb5 | 32 | /* #define DEBUG_WAR_CONSOLE_ON */ |
sam_grove |
0:6219434a0cb5 | 33 | /* #define DEBUG_ERR_CONSOLE_ON */ |
sam_grove |
0:6219434a0cb5 | 34 | |
sam_grove |
0:6219434a0cb5 | 35 | #include <applicfg.h> |
sam_grove |
0:6219434a0cb5 | 36 | #include "canopen_timer.h" |
sam_grove |
0:6219434a0cb5 | 37 | |
sam_grove |
0:6219434a0cb5 | 38 | /* --------- The timer table --------- */ |
sam_grove |
0:6219434a0cb5 | 39 | s_timer_entry timers[MAX_NB_TIMER] = {{TIMER_FREE, NULL, NULL, 0, 0, 0},}; |
sam_grove |
0:6219434a0cb5 | 40 | |
sam_grove |
0:6219434a0cb5 | 41 | TIMEVAL total_sleep_time = TIMEVAL_MAX; |
sam_grove |
0:6219434a0cb5 | 42 | TIMER_HANDLE last_timer_raw = -1; |
sam_grove |
0:6219434a0cb5 | 43 | |
sam_grove |
0:6219434a0cb5 | 44 | #define min_val(a,b) ((a<b)?a:b) |
sam_grove |
0:6219434a0cb5 | 45 | |
sam_grove |
0:6219434a0cb5 | 46 | /*! |
sam_grove |
0:6219434a0cb5 | 47 | ** ------- Use this to declare a new alarm ------ |
sam_grove |
0:6219434a0cb5 | 48 | ** |
sam_grove |
0:6219434a0cb5 | 49 | ** @param d |
sam_grove |
0:6219434a0cb5 | 50 | ** @param id |
sam_grove |
0:6219434a0cb5 | 51 | ** @param callback |
sam_grove |
0:6219434a0cb5 | 52 | ** @param value |
sam_grove |
0:6219434a0cb5 | 53 | ** @param period |
sam_grove |
0:6219434a0cb5 | 54 | ** |
sam_grove |
0:6219434a0cb5 | 55 | ** @return |
sam_grove |
0:6219434a0cb5 | 56 | **/ |
sam_grove |
0:6219434a0cb5 | 57 | TIMER_HANDLE SetAlarm(CO_Data* d, UNS32 id, TimerCallback_t callback, TIMEVAL value, TIMEVAL period) |
sam_grove |
0:6219434a0cb5 | 58 | { |
sam_grove |
0:6219434a0cb5 | 59 | TIMER_HANDLE row_number; |
sam_grove |
0:6219434a0cb5 | 60 | s_timer_entry *row; |
sam_grove |
0:6219434a0cb5 | 61 | |
sam_grove |
0:6219434a0cb5 | 62 | /* in order to decide new timer setting we have to run over all timer rows */ |
sam_grove |
0:6219434a0cb5 | 63 | for(row_number=0, row=timers; row_number <= last_timer_raw + 1 && row_number < MAX_NB_TIMER; row_number++, row++) |
sam_grove |
0:6219434a0cb5 | 64 | { |
sam_grove |
0:6219434a0cb5 | 65 | if (callback && /* if something to store */ |
sam_grove |
0:6219434a0cb5 | 66 | row->state == TIMER_FREE) /* and empty row */ |
sam_grove |
0:6219434a0cb5 | 67 | { /* just store */ |
sam_grove |
0:6219434a0cb5 | 68 | TIMEVAL real_timer_value; |
sam_grove |
0:6219434a0cb5 | 69 | TIMEVAL elapsed_time; |
sam_grove |
0:6219434a0cb5 | 70 | |
sam_grove |
0:6219434a0cb5 | 71 | if (row_number == last_timer_raw + 1) last_timer_raw++; |
sam_grove |
0:6219434a0cb5 | 72 | |
sam_grove |
0:6219434a0cb5 | 73 | elapsed_time = getElapsedTime(); |
sam_grove |
0:6219434a0cb5 | 74 | /* set next wakeup alarm if new entry is sooner than others, or if it is alone */ |
sam_grove |
0:6219434a0cb5 | 75 | real_timer_value = value; |
sam_grove |
0:6219434a0cb5 | 76 | real_timer_value = min_val(real_timer_value, TIMEVAL_MAX); |
sam_grove |
0:6219434a0cb5 | 77 | |
sam_grove |
0:6219434a0cb5 | 78 | if (total_sleep_time > elapsed_time && total_sleep_time - elapsed_time > real_timer_value) |
sam_grove |
0:6219434a0cb5 | 79 | { |
sam_grove |
0:6219434a0cb5 | 80 | total_sleep_time = elapsed_time + real_timer_value; |
sam_grove |
0:6219434a0cb5 | 81 | setTimer(real_timer_value); |
sam_grove |
0:6219434a0cb5 | 82 | } |
sam_grove |
0:6219434a0cb5 | 83 | row->callback = callback; |
sam_grove |
0:6219434a0cb5 | 84 | row->d = d; |
sam_grove |
0:6219434a0cb5 | 85 | row->id = id; |
sam_grove |
0:6219434a0cb5 | 86 | row->val = value + elapsed_time; |
sam_grove |
0:6219434a0cb5 | 87 | row->interval = period; |
sam_grove |
0:6219434a0cb5 | 88 | row->state = TIMER_ARMED; |
sam_grove |
0:6219434a0cb5 | 89 | return row_number; |
sam_grove |
0:6219434a0cb5 | 90 | } |
sam_grove |
0:6219434a0cb5 | 91 | } |
sam_grove |
0:6219434a0cb5 | 92 | |
sam_grove |
0:6219434a0cb5 | 93 | return TIMER_NONE; |
sam_grove |
0:6219434a0cb5 | 94 | } |
sam_grove |
0:6219434a0cb5 | 95 | |
sam_grove |
0:6219434a0cb5 | 96 | /*! |
sam_grove |
0:6219434a0cb5 | 97 | ** ----- Use this to remove an alarm ---- |
sam_grove |
0:6219434a0cb5 | 98 | ** |
sam_grove |
0:6219434a0cb5 | 99 | ** @param handle |
sam_grove |
0:6219434a0cb5 | 100 | ** |
sam_grove |
0:6219434a0cb5 | 101 | ** @return |
sam_grove |
0:6219434a0cb5 | 102 | **/ |
sam_grove |
0:6219434a0cb5 | 103 | TIMER_HANDLE DelAlarm(TIMER_HANDLE handle) |
sam_grove |
0:6219434a0cb5 | 104 | { |
sam_grove |
0:6219434a0cb5 | 105 | /* Quick and dirty. system timer will continue to be trigged, but no action will be preformed. */ |
sam_grove |
0:6219434a0cb5 | 106 | MSG_WAR(0x3320, "DelAlarm. handle = ", handle); |
sam_grove |
0:6219434a0cb5 | 107 | if(handle != TIMER_NONE) |
sam_grove |
0:6219434a0cb5 | 108 | { |
sam_grove |
0:6219434a0cb5 | 109 | if(handle == last_timer_raw) |
sam_grove |
0:6219434a0cb5 | 110 | last_timer_raw--; |
sam_grove |
0:6219434a0cb5 | 111 | timers[handle].state = TIMER_FREE; |
sam_grove |
0:6219434a0cb5 | 112 | } |
sam_grove |
0:6219434a0cb5 | 113 | return TIMER_NONE; |
sam_grove |
0:6219434a0cb5 | 114 | } |
sam_grove |
0:6219434a0cb5 | 115 | |
sam_grove |
0:6219434a0cb5 | 116 | /*! |
sam_grove |
0:6219434a0cb5 | 117 | ** ------ TimeDispatch is called on each timer expiration ---- |
sam_grove |
0:6219434a0cb5 | 118 | ** |
sam_grove |
0:6219434a0cb5 | 119 | **/ |
sam_grove |
0:6219434a0cb5 | 120 | int tdcount=0; |
sam_grove |
0:6219434a0cb5 | 121 | void TimeDispatch(void) |
sam_grove |
0:6219434a0cb5 | 122 | { |
sam_grove |
0:6219434a0cb5 | 123 | TIMER_HANDLE i; |
sam_grove |
0:6219434a0cb5 | 124 | TIMEVAL next_wakeup = TIMEVAL_MAX; /* used to compute when should normaly occur next wakeup */ |
sam_grove |
0:6219434a0cb5 | 125 | /* First run : change timer state depending on time */ |
sam_grove |
0:6219434a0cb5 | 126 | /* Get time since timer signal */ |
sam_grove |
0:6219434a0cb5 | 127 | UNS32 overrun = (UNS32)getElapsedTime(); |
sam_grove |
0:6219434a0cb5 | 128 | |
sam_grove |
0:6219434a0cb5 | 129 | TIMEVAL real_total_sleep_time = total_sleep_time + overrun; |
sam_grove |
0:6219434a0cb5 | 130 | |
sam_grove |
0:6219434a0cb5 | 131 | s_timer_entry *row; |
sam_grove |
0:6219434a0cb5 | 132 | |
sam_grove |
0:6219434a0cb5 | 133 | for(i=0, row = timers; i <= last_timer_raw; i++, row++) |
sam_grove |
0:6219434a0cb5 | 134 | { |
sam_grove |
0:6219434a0cb5 | 135 | if (row->state & TIMER_ARMED) /* if row is active */ |
sam_grove |
0:6219434a0cb5 | 136 | { |
sam_grove |
0:6219434a0cb5 | 137 | if (row->val <= real_total_sleep_time) /* to be trigged */ |
sam_grove |
0:6219434a0cb5 | 138 | { |
sam_grove |
0:6219434a0cb5 | 139 | if (!row->interval) /* if simply outdated */ |
sam_grove |
0:6219434a0cb5 | 140 | { |
sam_grove |
0:6219434a0cb5 | 141 | row->state = TIMER_TRIG; /* ask for trig */ |
sam_grove |
0:6219434a0cb5 | 142 | } |
sam_grove |
0:6219434a0cb5 | 143 | else /* or period have expired */ |
sam_grove |
0:6219434a0cb5 | 144 | { |
sam_grove |
0:6219434a0cb5 | 145 | /* set val as interval, with 32 bit overrun correction, */ |
sam_grove |
0:6219434a0cb5 | 146 | /* modulo for 64 bit not available on all platforms */ |
sam_grove |
0:6219434a0cb5 | 147 | row->val = row->interval - (overrun % (UNS32)row->interval); |
sam_grove |
0:6219434a0cb5 | 148 | row->state = TIMER_TRIG_PERIOD; /* ask for trig, periodic */ |
sam_grove |
0:6219434a0cb5 | 149 | /* Check if this new timer value is the soonest */ |
sam_grove |
0:6219434a0cb5 | 150 | if(row->val < next_wakeup) |
sam_grove |
0:6219434a0cb5 | 151 | next_wakeup = row->val; |
sam_grove |
0:6219434a0cb5 | 152 | } |
sam_grove |
0:6219434a0cb5 | 153 | } |
sam_grove |
0:6219434a0cb5 | 154 | else |
sam_grove |
0:6219434a0cb5 | 155 | { |
sam_grove |
0:6219434a0cb5 | 156 | /* Each armed timer value in decremented. */ |
sam_grove |
0:6219434a0cb5 | 157 | row->val -= real_total_sleep_time; |
sam_grove |
0:6219434a0cb5 | 158 | |
sam_grove |
0:6219434a0cb5 | 159 | /* Check if this new timer value is the soonest */ |
sam_grove |
0:6219434a0cb5 | 160 | if(row->val < next_wakeup) |
sam_grove |
0:6219434a0cb5 | 161 | next_wakeup = row->val; |
sam_grove |
0:6219434a0cb5 | 162 | } |
sam_grove |
0:6219434a0cb5 | 163 | } |
sam_grove |
0:6219434a0cb5 | 164 | } |
sam_grove |
0:6219434a0cb5 | 165 | |
sam_grove |
0:6219434a0cb5 | 166 | /* Remember how much time we should sleep. */ |
sam_grove |
0:6219434a0cb5 | 167 | total_sleep_time = next_wakeup; |
sam_grove |
0:6219434a0cb5 | 168 | |
sam_grove |
0:6219434a0cb5 | 169 | /* Set timer to soonest occurence */ |
sam_grove |
0:6219434a0cb5 | 170 | setTimer(next_wakeup); |
sam_grove |
0:6219434a0cb5 | 171 | |
sam_grove |
0:6219434a0cb5 | 172 | /* Then trig them or not. */ |
sam_grove |
0:6219434a0cb5 | 173 | for(i=0, row = timers; i<=last_timer_raw; i++, row++) |
sam_grove |
0:6219434a0cb5 | 174 | { |
sam_grove |
0:6219434a0cb5 | 175 | if (row->state & TIMER_TRIG) |
sam_grove |
0:6219434a0cb5 | 176 | { |
sam_grove |
0:6219434a0cb5 | 177 | row->state &= ~TIMER_TRIG; /* reset trig state (will be free if not periodic) */ |
sam_grove |
0:6219434a0cb5 | 178 | if(row->callback) |
sam_grove |
0:6219434a0cb5 | 179 | (*row->callback)(row->d, row->id); /* trig ! */ |
sam_grove |
0:6219434a0cb5 | 180 | } |
sam_grove |
0:6219434a0cb5 | 181 | } |
sam_grove |
0:6219434a0cb5 | 182 | } |