EVE 1.0
mwork.h
Go to the documentation of this file.
1 #ifndef EVE_MWORK_H_INCLUDED
2 #define EVE_MWORK_H_INCLUDED
3 
4 /**********************************************************************/
5 /*
6  * Copyright (c) 2013-2015, Jetro AS
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modification,
10  * are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  * derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONRIBUTORS ``AS IS'' AND ANY EXPRESS
21  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
23  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
25  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
29  * OF SUCH DAMAGE.
30  *
31  * This file is part of the EVE platform.
32  */
33 
34  /**
35  * \file
36  * \brief Header file for the EVE millisecond-scale work scheduling.
37  *
38  * \author DT, Jetro AS
39  */ /******************************************************************/
40 
41 #include <stdbool.h>
42 #include <stdint.h>
43 #include <lib/dlist.h>
44 #include <core/work.h>
45 #include <nrf52.h>
46 #include <hal/nrf_rtc.h>
47 
48 /**
49  * \defgroup eve_mwork msec work scheduler
50  * \ingroup eve_scheduling
51  * \{
52  */
53 
54 /**********************************************************************/
55 /**
56  * Counter register width, bits.
57  */
58 #define MWORK_COUNTER_WIDTH (24)
59 
60 /**********************************************************************/
61 /**
62  * Amount of counter register LSB bits, reserved as synchronization quard
63  */
64 #define MWORK_GUARD_WIDTH (2)
65 
66 /**********************************************************************/
67 /**
68  * Effective width if counter register width, bits.
69  */
70 #define MWORK_EFFECTIVE_WIDTH (MWORK_COUNTER_WIDTH - MWORK_GUARD_WIDTH)
71 
72 /**********************************************************************/
73 /**
74  * Effective time mask.
75  */
76 #define MWORK_TIME_MASK ((1 << MWORK_EFFECTIVE_WIDTH) - 1)
77 
78 /**********************************************************************/
79 /**
80  * Round time by the effective width of the counter register.
81  */
82 #define MWORK_ROUND_TIME(tick) ((tick) & MWORK_TIME_MASK)
83 
84 /**********************************************************************/
85 /**
86  * Checks if mwork time span is negative.
87  */
88 #define MWORK_TIME_SPAN_IS_NEGATIVE(span) \
89  (((span) & (1 << (MWORK_EFFECTIVE_WIDTH - 1))) != 0)
90 
91 /**********************************************************************/
92 /**
93  * Converts a time interval, given in number of milliseconds, to the number of ticks.
94  *
95  * \param ms duration of the time interval, milliseconds
96  * \return number of ticks in the time interval
97  */
98 #define MWORK_MSEC(ms) MS_TO_TICKS(ms)
99 
100 /**********************************************************************/
101 /**
102  * Initializes a milliwork structure.
103  *
104  * The macro is used to initialize a millisecond-scale work (milliwork) structure instance.
105  *
106  * \param x milliwork structure
107  * \param callback milliwork callback
108  *
109  * Usage:
110  * \code
111  static void MyWorkCallback(struct mwork_t *Work);
112  struct mwork_t MyWork = MWORK_INIT(MyWork, MyWorkCallback);
113  * \endcode
114  */
115 #define MWORK_INIT(x, callback) \
116  { \
117  .work.link.next = &(x).work.link, \
118  .work.link.prev = &(x).work.link, \
119  .work.cb = (work_cb_t) (callback), \
120  }
121 
122 /**********************************************************************/
123 /**
124  * Initializes a milliwork structure. Typed version of \ref MWORK_INIT
125  */
126 #define MWORK_INIT_TYPED(x, callback) \
127  (struct mwork_t) MWORK_INIT(x, callback)
128 
129 /**********************************************************************/
130 /**
131  * Instantiates a milliwork structure.
132  *
133  * The macro is used to instantiate a work structure.
134  *
135  * \param x name of the milliwork structure
136  * \param callback the milliwork callback
137  *
138  * Usage:
139  * \code
140  static void MyWorkCallback(struct mwork_t *Work);
141  DECLARE_MWORK(MyWork, MyWorkCallback);
142  * \endcode
143  */
144 #define DECLARE_MWORK(x, callback) \
145  struct mwork_t x = MWORK_INIT(x, callback)
146 
147 /* Forward declaration */
148 struct mwork_t;
149 
150 /**********************************************************************/
151 /**
152  * Milliwork time type.
153  *
154  * Only \ref MWORK_EFFECTIVE_WIDTH LSB bits are used, while MSB of them becomes
155  * a sign bit, and the rest of the uint32_t is ignored by the framework.
156  * So, the max interval for the milliwork is 2^(24-2-1)-1 = 2097151 ticks,
157  * or ~34 min. Please use OS etimer for longer intervals.
158  */
159 typedef uint32_t mwork_time_t;
160 
161 /**********************************************************************/
162 /**
163  * Milliwork callback type.
164  *
165  * \param work pointer to the milliwork structure
166  */
167 typedef void (*mwork_cb_t)(struct mwork_t *work);
168 
169 /**********************************************************************/
170 /**
171  * Milliwork structure.
172  *
173  * EVE millisecond-scale work or `milliwork` is a function with an associated data structure,
174  * which can be scheduled for execution at specified time in future. The function is executed
175  * at the software interrupt execution level.
176  *
177  * The structure represents the milliwork instance.
178  *
179  * The structure must be instantiated in the RAM memory using
180  * one of \ref MWORK_INIT() or \ref DECLARE_MWORK().
181  */
182 struct mwork_t {
183  struct work_t work; /**< Underlaying work structure */
184  mwork_time_t at; /**< Point in time the milliwork is scheduled for */
185 };
186 
187 /**********************************************************************/
188 /**
189  * Returns the current timestamp, which can be used as a time reference in struct mwork_t::at
190  *
191  * Usage:
192  * \code
193  MyWork.at = mwork_now() + MWORK_MSEC(100);
194  mwork_schedule(&MyWork);
195  // The work is scheduled and will be executed 100 ms later.
196  * \endcode
197  *
198  * \return current timestamp in system ticks
199  */
200 static inline mwork_time_t mwork_now()
201 {
202  return nrf_rtc_counter_get(NRF_RTC1) >> MWORK_GUARD_WIDTH;
203 }
204 
205 /**********************************************************************/
206 /**
207  * Schedules a milliwork.
208  *
209  * The function schedules a milliwork for execution at the specified point in time.
210  * The milliwork will be executed at the software interrupt level, like a work item.
211  * It is allowed to schedule a milliwork in the past. In this case it is triggered
212  * for execution immediately.
213  *
214  * If two or more milliworks are scheduled for the same tick, they will be executed
215  * in the same order as thay were scheduled. Due to non-preemptive execution of work
216  * items and milliworks at the software interrupt level, the actual time when the
217  * milliwork execution starts can vary.
218  *
219  * If the milliwork structure, pointed by the `work` parameter is already scheduled
220  * for execution, then it is re-scheduled at the new time.
221  *
222  * A scheduled milliwork holds system at PM_LEVEL_LOWPWR power level.
223  *
224  * \param work pointer to the milliwork structure
225  */
226 void mwork_schedule(struct mwork_t *work);
227 
228 /**********************************************************************/
229 /**
230  * Cancels a scheduled milliwork.
231  *
232  * The function cancels a previously scheduled work.
233  *
234  * \param work pointer to the milliwork structure
235  */
236 void mwork_cancel(struct mwork_t *work);
237 
238 /**********************************************************************/
239 /**
240  * Checks if the milliwork is scheduled and pending execution.
241  *
242  * The function checks if the milliwork is scheduled for execution.
243  *
244  * \param work pointer to the milliwork structure
245  * \return true if the milliwork is scheduled for execution
246  * \return false if the milliwork is not scheduled
247  * \return false if the milliwork is being executed
248  */
249 static inline bool mwork_pending(struct mwork_t *work)
250 {
251  return !dlist_is_empty(&work->work.link);
252 }
253 
254 /**********************************************************************/
255 /**
256  * \internal
257  *
258  */ /******************************************************************/
259 
260 /**********************************************************************/
261 /**
262  * Milliwork timer
263  */
264 void mwork_timer(void);
265 
266 /** @} eve_mwork */
267 
268 #endif /* EVE_MWORK_H_INCLUDED */
struct work_t work
Definition: mwork.h:183
struct dlist_t link
Definition: work.h:141
Definition: mwork.h:182
void mwork_timer(void)
static mwork_time_t mwork_now()
Definition: mwork.h:200
The code implements Dummy Headed Doubly Linked Circularlist (DHDLC) primitive.
static int dlist_is_empty(struct dlist_t *list)
Definition: dlist.h:125
Header file for the EVE work scheduling.
void(* mwork_cb_t)(struct mwork_t *work)
Definition: mwork.h:167
static bool mwork_pending(struct mwork_t *work)
Definition: mwork.h:249
#define MWORK_GUARD_WIDTH
Definition: mwork.h:64
void mwork_schedule(struct mwork_t *work)
mwork_time_t at
Definition: mwork.h:184
Definition: work.h:140
void mwork_cancel(struct mwork_t *work)
uint32_t mwork_time_t
Definition: mwork.h:148