EVE 1.0
clk.h
Go to the documentation of this file.
1 #ifndef EVE_CLK_H_INCLUDED
2 #define EVE_CLK_H_INCLUDED
3 /**********************************************************************/
4 /*
5  * Copyright (c) 2013-2015, Jetro AS
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without modification,
9  * are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  * derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONRIBUTORS ``AS IS'' AND ANY EXPRESS
20  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
22  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
24  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28  * OF SUCH DAMAGE.
29  *
30  * This file is part of the EVE platform.
31  */
32 
33  /**
34  * \file
35  * \brief Header file for the EVE clock management framework.
36  *
37  * \author DT, Jetro AS
38  */ /******************************************************************/
39 
40 /* #define DEBUG_CLK */
41 
42 #include <stdbool.h>
43 #include <stdint.h>
44 #include <lib/dlist.h>
45 
46 /**
47  * \addtogroup clk
48  * @{
49  * EVE clock management framework.
50  */
51 
52 /**********************************************************************/
53 /**
54  * Indicates that the given clock should be kept running when system is in the suspend state.
55  *
56  * The modifier can be applied to level field of the \ref clk_lock_t instantiation
57  * to indicate that the clock should not be switched off at system suspend.
58  *
59  * Usage:
60  * \code
61  struct clk_lock_t MyPersistentClockLock = CLK_LOCK_INIT(CLK_PERSISTENT(CLK_LEVEL_XO), MyPersistentClockLock);
62  * \endcode
63  *
64  * \param x The actual clock level, \ref clk_level_t.
65  */
66 #define CLK_PERSISTENT(x) ((enum clk_level_t) ((x) | 0x80))
67 
68 /**********************************************************************/
69 /**
70  * Clock level.
71  *
72  * The system can use one two high frequency clock sources: a 64 MHz internal
73  * oscillator (RC) or a 32 MHz crystal oscillator (XO). The crystal oscillator
74  * typically gives better stability, but drains more power from battery.
75  *
76  * Clock level is an abstraction for the clock source the system is running on.
77  */
79 {
80  CLK_LEVEL_MIN, /**< Minimal possible clock level. */
81  CLK_LEVEL_RC = CLK_LEVEL_MIN, /**< System uses 64 MHz internal oscillator as a clock source. */
82  CLK_LEVEL_XO, /**< System uses 32 MHz crystal oscillator as a clock source. */
83  CLK_LEVEL__COUNT, /**< Number of elements in the \ref clk_level_t enum. */
84 };
85 
86 /**********************************************************************/
87 /**
88  * Clock lock structure.
89  *
90  * The clock lock structure represents a clock request for a given clock level.
91  * The structure must be instantiated in the RAM memory using
92  * one of \ref CLK_LOCK_INIT() or \ref DECLARE_CLK_LOCK().
93  * Note that the clock request is not active unless \ref CLK_LOCK() is called for it.
94  */
95 struct clk_lock_t
96 {
97 #ifdef DEBUG_CLK
98  const char *dbg_file; /**< Debug field: file name the lock was touched last time in */
99  int dbg_line; /**< Debug field: line number the lock was touched last time at */
100  struct dlist_t dbg_link; /**< Linked list of all locked requests at all lock levels */
101 #endif
102  struct dlist_t link; /**< Linked list of all locked requests at the given lock level */
103  uint8_t level; /**< \ref clk_level_t, the given lock level */
104  uint8_t locked; /**< Lock counter for the lock request */
105 };
106 
107 /**********************************************************************/
108 /** \def CLK_LOCK_INIT(l, clk)
109  * Initializes a clock lock structure.
110  *
111  * The macro is used to initialize a clock lock structure instance.
112  *
113  * \param l clock level
114  * \param clk clock lock structure
115  *
116  * Usage:
117  * \code
118  struct clk_lock_t MyXOClockLock = CLK_LOCK_INIT(CLK_LEVEL_XO, MyXOClockLock);
119  * \endcode
120  */
121 
122 /**********************************************************************/
123 /** \def CLK_LOCK(clk)
124  * Request the clock
125  *
126  * The macro is used to request clock at the given clock level.
127  *
128  * \param clk clock lock structure
129  *
130  * Usage:
131  * \code
132  CLK_LOCK(MyXOClockLock);
133  * \endcode
134  */
135 
136 /**********************************************************************/
137 /** \def CLK_UNLOCK(clk)
138  * Release the clock
139  *
140  * The macro is used to release clock at the given clock level.
141  *
142  * The clock actually continues to run after the last lock is released until
143  * \ref clk_relax() is called explicitly or by \ref pm_relax().
144  *
145  * \param clk clock lock structure
146  *
147  * Usage:
148  * \code
149  CLK_UNLOCK(MyXOClockLock);
150  * \endcode
151  */
152 
153 /**********************************************************************/
154 /** \def CLK_AUTO_LOCK(l)
155  * Declares an anonymous auto lock, which holds clock request in the auto variable visibility block
156  *
157  * \param l clock level
158  *
159  * Usage:
160  * \code
161  {
162  CLK_AUTO_LOCK(CLK_LEVEL_XO);
163  // Do something protected by the lock
164  }
165  // The lock is released here
166  * \endcode
167  *
168  * Note: taking in mind lazy nature of releasing the clock locks, use of auto clock locks is negligible.
169  */
170 
171 #ifdef DEBUG_CLK
172  #define CLK_LOCK_INIT(l, clk) \
173  { \
174  .dbg_link = DLIST_INIT(clk.dbg_link), \
175  .dbg_file = __FILE__, \
176  .dbg_line = __LINE__, \
177  .link = DLIST_INIT(clk.link), \
178  .level = l, \
179  .locked = 0, \
180  }
181  #define CLK_LOCK(pm) clk_lock_dbg(&pm, __FILE__, __LINE__)
182  #define CLK_UNLOCK(pm) clk_unlock_dbg(&pm, __FILE__, __LINE__)
183  #define CLK_AUTO_LOCK(l) \
184  inline void clk_unlock_dbg_adapter(struct clk_lock_t *clk) { clk_unlock_dbg(clk, __FILE__, __LINE__); } \
185  struct clk_lock_t EveClkAutoLock __attribute__((cleanup(clk_unlock_dbg_adapter))); \
186  do { EveClkAutoLock = (struct clk_lock_t) CLK_LOCK_INIT(l, EveClkAutoLock); } while (0)
187 #else
188  #define CLK_LOCK_INIT(l, clk) \
189  { \
190  .link = DLIST_INIT(clk.link), \
191  .level = l, \
192  .locked = 0, \
193  }
194  #define CLK_LOCK(clk) clk_lock(&clk)
195  #define CLK_UNLOCK(clk) clk_unlock(&clk)
196  #define CLK_AUTO_LOCK(l) \
197  struct clk_lock_t EveClkAutoLock __attribute__((cleanup(clk_unlock))); \
198  do { EveClkAutoLock = (struct clk_lock_t) CLK_LOCK_INIT(l, EveClkAutoLock); } while (0)
199 #endif
200 
201 /**********************************************************************/
202 /**
203  * Instantiates a clock lock structure.
204  *
205  * The macro is used to instantiate a clock lock structure.
206  *
207  * \param l clock level
208  * \param clk clock lock structure
209  *
210  * Usage:
211  * \code
212  DECLARE_CLK_LOCK(CLK_LEVEL_XO, MyXOClockLock);
213  * \endcode
214  */
215 #define DECLARE_CLK_LOCK(l, clk)\
216  static struct clk_lock_t clk = CLK_LOCK_INIT(l, clk)
217 
218 /**********************************************************************/
219 /**
220  * \internal
221  *
222  */ /******************************************************************/
223 
224 
225 /**********************************************************************/
226 /**
227  * Initializes the clock management framework.
228  */
229 void clk_init(void);
230 
231 /**********************************************************************/
232 /**
233  * Switches off released clocks and enters the lowest allowed clock level.
234  */
235 void clk_relax(void);
236 
237 /**********************************************************************/
238 /**
239  * Requests the clock.
240  *
241  * \param clk pointer to the clock lock structure
242  */
243 void clk_lock(struct clk_lock_t *clk);
244 
245 /**********************************************************************/
246 /**
247  * Releases the clock.
248  *
249  * \param clk pointer to the clock lock structure
250  */
251 void clk_unlock(struct clk_lock_t *clk);
252 
253 #ifdef DEBUG_CLK
254 /**********************************************************************/
255 /**
256  * Requests the clock: debug version.
257  *
258  * \param clk pointer to the clock lock structure
259  * \param file current file name
260  * \param line current line number
261  */
262  void clk_lock_dbg(struct clk_lock_t *clk, const char *file, int line);
263 
264 /**********************************************************************/
265 /**
266  * Releases the clock: debug version.
267  *
268  * \param clk pointer to the clock lock structure
269  * \param file current file name
270  * \param line current line number
271  */
272  void clk_unlock_dbg(struct clk_lock_t *clk, const char *file, int line);
273 #endif
274 
275 /** @} */ /* clk */
276 
277 #endif
void clk_lock(struct clk_lock_t *clk)
The code implements Dummy Headed Doubly Linked Circularlist (DHDLC) primitive.
void clk_init(void)
uint8_t level
Definition: clk.h:103
uint8_t locked
Definition: clk.h:104
Definition: clk.h:95
Definition: dlist.h:66
void clk_unlock(struct clk_lock_t *clk)
void clk_relax(void)
clk_level_t
Definition: clk.h:78
struct dlist_t link
Definition: clk.h:102