]> git.sur5r.net Git - freertos/blob
939b5fcda2232fa262d68858eaad13af756569bc
[freertos] /
1 /***************************************************************************//**\r
2  * @file em_msc.h\r
3  * @brief Flash controller module (MSC) peripheral API\r
4  * @version 4.0.0\r
5  *******************************************************************************\r
6  * @section License\r
7  * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>\r
8  *******************************************************************************\r
9  *\r
10  * Permission is granted to anyone to use this software for any purpose,\r
11  * including commercial applications, and to alter it and redistribute it\r
12  * freely, subject to the following restrictions:\r
13  *\r
14  * 1. The origin of this software must not be misrepresented; you must not\r
15  *    claim that you wrote the original software.\r
16  * 2. Altered source versions must be plainly marked as such, and must not be\r
17  *    misrepresented as being the original software.\r
18  * 3. This notice may not be removed or altered from any source distribution.\r
19  *\r
20  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
21  * obligation to support this Software. Silicon Labs is providing the\r
22  * Software "AS IS", with no express or implied warranties of any kind,\r
23  * including, but not limited to, any implied warranties of merchantability\r
24  * or fitness for any particular purpose or warranties against infringement\r
25  * of any proprietary rights of a third party.\r
26  *\r
27  * Silicon Labs will not be liable for any consequential, incidental, or\r
28  * special damages, or any other relief, or for any claim by any third party,\r
29  * arising from your use of this Software.\r
30  *\r
31  ******************************************************************************/\r
32 \r
33 #ifndef __SILICON_LABS_EM_MSC_H__\r
34 #define __SILICON_LABS_EM_MSC_H__\r
35 \r
36 #include "em_device.h"\r
37 #if defined(MSC_COUNT) && (MSC_COUNT > 0)\r
38 \r
39 #include <stdint.h>\r
40 #include <stdbool.h>\r
41 #include "em_bitband.h"\r
42 \r
43 #ifdef __cplusplus\r
44 extern "C" {\r
45 #endif\r
46 \r
47 /***************************************************************************//**\r
48  * @addtogroup EM_Library\r
49  * @{\r
50  ******************************************************************************/\r
51 \r
52 /***************************************************************************//**\r
53  * @addtogroup MSC\r
54  * @brief Flash controller (MSC) peripheral API\r
55  * @{\r
56  ******************************************************************************/\r
57 \r
58 /*******************************************************************************\r
59  *************************   DEFINES   *****************************************\r
60  ******************************************************************************/\r
61 \r
62 /**\r
63  * @brief\r
64  *    The timeout used while waiting for the flash to become ready after\r
65  *    a write. This number indicates the number of iterations to perform before\r
66  *    issuing a timeout.\r
67  * @note\r
68  *    This timeout is set very large (in the order of 100x longer than\r
69  *    necessary). This is to avoid any corner cases.\r
70  *\r
71  */\r
72 #define MSC_PROGRAM_TIMEOUT    10000000ul\r
73 \r
74 /*******************************************************************************\r
75  *************************   TYPEDEFS   ****************************************\r
76  ******************************************************************************/\r
77 \r
78 /** Return codes for writing/erasing the flash */\r
79 typedef enum\r
80 {\r
81   mscReturnOk          = 0,  /**< Flash write/erase successful. */\r
82   mscReturnInvalidAddr = -1, /**< Invalid address. Write to an address that is not flash. */\r
83   mscReturnLocked      = -2, /**< Flash address is locked. */\r
84   mscReturnTimeOut     = -3, /**< Timeout while writing to flash. */\r
85   mscReturnUnaligned   = -4  /**< Unaligned access to flash. */\r
86 } MSC_Status_TypeDef;\r
87 \r
88 \r
89 #if defined( _MSC_READCTRL_BUSSTRATEGY_MASK )\r
90 /** Strategy for prioritized bus access */\r
91 typedef enum {\r
92   mscBusStrategyCPU = MSC_READCTRL_BUSSTRATEGY_CPU,       /**< Prioritize CPU bus accesses */\r
93   mscBusStrategyDMA = MSC_READCTRL_BUSSTRATEGY_DMA,       /**< Prioritize DMA bus accesses */\r
94   mscBusStrategyDMAEM1 = MSC_READCTRL_BUSSTRATEGY_DMAEM1, /**< Prioritize DMAEM1 for bus accesses */\r
95   mscBusStrategyNone = MSC_READCTRL_BUSSTRATEGY_NONE      /**< No unit has bus priority */\r
96 } MSC_BusStrategy_Typedef;\r
97 #endif\r
98 \r
99 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
100 /* Legacy type names */\r
101 #define mscBusStrategy_Typedef MSC_BusStrategy_Typedef\r
102 #define msc_Return_TypeDef MSC_Status_TypeDef\r
103 /** @endcond */\r
104 \r
105 /*******************************************************************************\r
106  *************************   PROTOTYPES   **************************************\r
107  ******************************************************************************/\r
108 \r
109 void MSC_Init(void);\r
110 void MSC_Deinit(void);\r
111 \r
112 /***************************************************************************//**\r
113  * @brief\r
114  *    Clear one or more pending MSC interrupts.\r
115  *\r
116  * @param[in] flags\r
117  *    Pending MSC intterupt source to clear. Use a bitwise logic OR combination\r
118  *   of valid interrupt flags for the MSC module (MSC_IF_nnn).\r
119  ******************************************************************************/\r
120 __STATIC_INLINE void MSC_IntClear(uint32_t flags)\r
121 {\r
122   MSC->IFC = flags;\r
123 }\r
124 \r
125 /***************************************************************************//**\r
126  * @brief\r
127  *   Disable one or more MSC interrupts.\r
128  *\r
129  * @param[in] flags\r
130  *   MSC interrupt sources to disable. Use a bitwise logic OR combination of\r
131  *   valid interrupt flags for the MSC module (MSC_IF_nnn).\r
132  ******************************************************************************/\r
133 __STATIC_INLINE void MSC_IntDisable(uint32_t flags)\r
134 {\r
135   MSC->IEN &= ~(flags);\r
136 }\r
137 \r
138 \r
139 /***************************************************************************//**\r
140  * @brief\r
141  *   Enable one or more MSC interrupts.\r
142  *\r
143  * @note\r
144  *   Depending on the use, a pending interrupt may already be set prior to\r
145  *   enabling the interrupt. Consider using MSC_IntClear() prior to enabling\r
146  *   if such a pending interrupt should be ignored.\r
147  *\r
148  * @param[in] flags\r
149  *   MSC interrupt sources to enable. Use a bitwise logic OR combination of\r
150  *   valid interrupt flags for the MSC module (MSC_IF_nnn).\r
151  ******************************************************************************/\r
152 __STATIC_INLINE void MSC_IntEnable(uint32_t flags)\r
153 {\r
154   MSC->IEN |= flags;\r
155 }\r
156 \r
157 \r
158 /***************************************************************************//**\r
159  * @brief\r
160  *   Get pending MSC interrupt flags.\r
161  *\r
162  * @note\r
163  *   The event bits are not cleared by the use of this function.\r
164  *\r
165  * @return\r
166  *   MSC interrupt sources pending. A bitwise logic OR combination of valid\r
167  *   interrupt flags for the MSC module (MSC_IF_nnn).\r
168  ******************************************************************************/\r
169 __STATIC_INLINE uint32_t MSC_IntGet(void)\r
170 {\r
171   return(MSC->IF);\r
172 }\r
173 \r
174 \r
175 /***************************************************************************//**\r
176  * @brief\r
177  *   Get enabled and pending MSC interrupt flags.\r
178  *   Useful for handling more interrupt sources in the same interrupt handler.\r
179  *\r
180  * @note\r
181  *   Interrupt flags are not cleared by the use of this function.\r
182  *\r
183  * @return\r
184  *   Pending and enabled MSC interrupt sources\r
185  *   The return value is the bitwise AND of\r
186  *   - the enabled interrupt sources in MSC_IEN and\r
187  *   - the pending interrupt flags MSC_IF\r
188  ******************************************************************************/\r
189 __STATIC_INLINE uint32_t MSC_IntGetEnabled(void)\r
190 {\r
191   uint32_t ien;\r
192 \r
193   ien = MSC->IEN;\r
194   return MSC->IF & ien;\r
195 }\r
196 \r
197 \r
198 /***************************************************************************//**\r
199  * @brief\r
200  *   Set one or more pending MSC interrupts from SW.\r
201  *\r
202  * @param[in] flags\r
203  *   MSC interrupt sources to set to pending. Use a bitwise logic OR combination of\r
204  *   valid interrupt flags for the MSC module (MSC_IF_nnn).\r
205  ******************************************************************************/\r
206 __STATIC_INLINE void MSC_IntSet(uint32_t flags)\r
207 {\r
208   MSC->IFS = flags;\r
209 }\r
210 \r
211 \r
212 #if defined( MSC_IF_CHOF ) && defined( MSC_IF_CMOF )\r
213 /***************************************************************************//**\r
214  * @brief\r
215  *   Starts measuring cache hit ratio.\r
216  * @details\r
217  *   This function starts the performance counters. It is defined inline to\r
218  *   minimize the impact of this code on the measurement itself.\r
219  ******************************************************************************/\r
220 __STATIC_INLINE void MSC_StartCacheMeasurement(void)\r
221 {\r
222   /* Clear CMOF and CHOF to catch these later */\r
223   MSC->IFC = MSC_IF_CHOF | MSC_IF_CMOF;\r
224 \r
225   /* Start performance counters */\r
226 #if defined( _MSC_CACHECMD_MASK )\r
227   MSC->CACHECMD = MSC_CACHECMD_STARTPC;\r
228 #else\r
229   MSC->CMD = MSC_CMD_STARTPC;\r
230 #endif\r
231 }\r
232 \r
233 \r
234 /***************************************************************************//**\r
235  * @brief\r
236  *   Stops measuring the hit rate.\r
237  * @note\r
238  *   This function is defined inline to minimize the impact of this\r
239  *   code on the measurement itself.\r
240  *   This code only works for relatively short sections of code. If you wish\r
241  *   to measure longer sections of code you need to implement a IRQ Handler for\r
242  *   The CHOF and CMOF overflow interrupts. Theses overflows needs to be\r
243  *   counted and included in the total.\r
244  *   The functions can then be implemented as follows:\r
245  * @verbatim\r
246  * volatile uint32_t hitOverflows\r
247  * volatile uint32_t missOverflows\r
248  *\r
249  * void MSC_IRQHandler(void)\r
250  * {\r
251  *   uint32_t flags;\r
252  *   flags = MSC->IF;\r
253  *   if (flags & MSC_IF_CHOF)\r
254  *   {\r
255  *      MSC->IFC = MSC_IF_CHOF;\r
256  *      hitOverflows++;\r
257  *   }\r
258  *   if (flags & MSC_IF_CMOF)\r
259  *   {\r
260  *     MSC->IFC = MSC_IF_CMOF;\r
261  *     missOverflows++;\r
262  *   }\r
263  * }\r
264  *\r
265  * void startPerformanceCounters(void)\r
266  * {\r
267  *   hitOverflows = 0;\r
268  *   missOverflows = 0;\r
269  *\r
270  *   MSC_IntEnable(MSC_IF_CHOF | MSC_IF_CMOF);\r
271  *   NVIC_EnableIRQ(MSC_IRQn);\r
272  *\r
273  *   MSC_StartCacheMeasurement();\r
274  * }\r
275  * @endverbatim\r
276  * @return\r
277  *   Returns -1 if there has been no cache accesses.\r
278  *   Returns -2 if there has been an overflow in the performance counters.\r
279  *   If not, it will return the percentage of hits versus misses.\r
280  ******************************************************************************/\r
281 __STATIC_INLINE int32_t MSC_GetCacheMeasurement(void)\r
282 {\r
283   int32_t total;\r
284   /* Stop the counter before computing the hit-rate */\r
285 #if defined( _MSC_CACHECMD_MASK )\r
286   MSC->CACHECMD = MSC_CACHECMD_STOPPC;\r
287 #else\r
288   MSC->CMD = MSC_CMD_STOPPC;\r
289 #endif\r
290 \r
291   /* Check for overflows in performance counters */\r
292   if (MSC->IF & (MSC_IF_CHOF | MSC_IF_CMOF))\r
293     return -2;\r
294 \r
295   /* Because the hits and misses are volatile, we need to split this up into\r
296    * two statements to avoid a compiler warning regarding the order of volatile\r
297    * accesses. */\r
298   total  = MSC->CACHEHITS;\r
299   total += MSC->CACHEMISSES;\r
300 \r
301   /* To avoid a division by zero. */\r
302   if (total == 0)\r
303     return -1;\r
304 \r
305   return (MSC->CACHEHITS * 100) / total;\r
306 }\r
307 \r
308 \r
309 /***************************************************************************//**\r
310  * @brief\r
311  *   Flush the contents of the instruction cache.\r
312  ******************************************************************************/\r
313 __STATIC_INLINE void MSC_FlushCache(void)\r
314 {\r
315 #if defined( _MSC_CACHECMD_MASK )\r
316   MSC->CACHECMD = MSC_CACHECMD_INVCACHE;\r
317 #else\r
318   MSC->CMD = MSC_CMD_INVCACHE;\r
319 #endif\r
320 }\r
321 \r
322 \r
323 /***************************************************************************//**\r
324  * @brief\r
325  *   Enable or disable instruction cache functionality\r
326  * @param[in] enable\r
327  *   Enable instruction cache. Default is on.\r
328  ******************************************************************************/\r
329 __STATIC_INLINE void MSC_EnableCache(bool enable)\r
330 {\r
331   BITBAND_Peripheral(&(MSC->READCTRL), _MSC_READCTRL_IFCDIS_SHIFT, ~enable);\r
332 }\r
333 \r
334 \r
335 #if defined( MSC_READCTRL_ICCDIS )\r
336 /***************************************************************************//**\r
337  * @brief\r
338  *   Enable or disable instruction cache functionality in IRQs\r
339  * @param[in] enable\r
340  *   Enable instruction cache. Default is on.\r
341  ******************************************************************************/\r
342 __STATIC_INLINE void MSC_EnableCacheIRQs(bool enable)\r
343 {\r
344   BITBAND_Peripheral(&(MSC->READCTRL), _MSC_READCTRL_ICCDIS_SHIFT, ~enable);\r
345 }\r
346 #endif\r
347 \r
348 \r
349 /***************************************************************************//**\r
350  * @brief\r
351  *   Enable or disable instruction cache flushing when writing to flash\r
352  * @param[in] enable\r
353  *   Enable automatic cache flushing. Default is on.\r
354  ******************************************************************************/\r
355 __STATIC_INLINE void MSC_EnableAutoCacheFlush(bool enable)\r
356 {\r
357   BITBAND_Peripheral(&(MSC->READCTRL), _MSC_READCTRL_AIDIS_SHIFT, ~enable);\r
358 }\r
359 #endif /* defined( MSC_IF_CHOF ) && defined( MSC_IF_CMOF ) */\r
360 \r
361 \r
362 #if defined( _MSC_READCTRL_BUSSTRATEGY_MASK )\r
363 /***************************************************************************//**\r
364  * @brief\r
365  *   Configure which unit should get priority on system bus.\r
366  * @param[in] mode\r
367  *   Unit to prioritize bus accesses for.\r
368  ******************************************************************************/\r
369 __STATIC_INLINE void MSC_BusStrategy(mscBusStrategy_Typedef mode)\r
370 {\r
371   MSC->READCTRL = (MSC->READCTRL & ~(_MSC_READCTRL_BUSSTRATEGY_MASK)) | mode;\r
372 }\r
373 #endif\r
374 \r
375 \r
376 #ifdef __CC_ARM  /* MDK-ARM compiler */\r
377 MSC_Status_TypeDef MSC_WriteWord(uint32_t *address, void const *data, uint32_t numBytes);\r
378 #if !defined( _EFM32_GECKO_FAMILY )\r
379 MSC_Status_TypeDef MSC_WriteWordFast(uint32_t *address, void const *data, uint32_t numBytes);\r
380 #endif\r
381 MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress);\r
382 \r
383 #if defined( _MSC_MASSLOCK_MASK )\r
384 MSC_Status_TypeDef MSC_MassErase(void);\r
385 #endif\r
386 #endif /* __CC_ARM */\r
387 \r
388 #ifdef __ICCARM__ /* IAR compiler */\r
389 __ramfunc MSC_Status_TypeDef MSC_WriteWord(uint32_t *address, void const *data, uint32_t numBytes);\r
390 #if !defined( _EFM32_GECKO_FAMILY )\r
391 __ramfunc MSC_Status_TypeDef MSC_WriteWordFast(uint32_t *address, void const *data, uint32_t numBytes);\r
392 #endif\r
393 __ramfunc MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress);\r
394 \r
395 #if defined( _MSC_MASSLOCK_MASK )\r
396 __ramfunc MSC_Status_TypeDef MSC_MassErase(void);\r
397 #endif\r
398 #endif /* __ICCARM__ */\r
399 \r
400 #ifdef __GNUC__  /* GCC based compilers */\r
401 #ifdef __CROSSWORKS_ARM  /* Rowley Crossworks (GCC based) */\r
402 MSC_Status_TypeDef MSC_WriteWord(uint32_t *address, void const *data, uint32_t numBytes) __attribute__ ((section(".fast")));\r
403 #if !defined( _EFM32_GECKO_FAMILY )\r
404 MSC_Status_TypeDef MSC_WriteWordFast(uint32_t *address, void const *data, uint32_t numBytes) __attribute__ ((section(".fast")));\r
405 #endif\r
406 MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress) __attribute__ ((section(".fast")));\r
407 \r
408 #if defined( _MSC_MASSLOCK_MASK )\r
409 MSC_Status_TypeDef MSC_MassErase(void) __attribute__ ((section(".fast")));\r
410 #endif\r
411 \r
412 #else /* GCC */\r
413 MSC_Status_TypeDef MSC_WriteWord(uint32_t *address, void const *data, uint32_t numBytes) __attribute__ ((section(".ram")));\r
414 #if !defined( _EFM32_GECKO_FAMILY )\r
415 MSC_Status_TypeDef MSC_WriteWordFast(uint32_t *address, void const *data, uint32_t numBytes) __attribute__ ((section(".ram")));\r
416 #endif\r
417 MSC_Status_TypeDef MSC_ErasePage(uint32_t *startAddress) __attribute__ ((section(".ram")));\r
418 \r
419 #if defined( _MSC_MASSLOCK_MASK )\r
420 MSC_Status_TypeDef MSC_MassErase(void) __attribute__ ((section(".ram")));\r
421 #endif\r
422 \r
423 #endif /* __GNUC__ */\r
424 #endif /* __CROSSWORKS_ARM */\r
425 \r
426 /** @} (end addtogroup MSC) */\r
427 /** @} (end addtogroup EM_Library) */\r
428 \r
429 #ifdef __cplusplus\r
430 }\r
431 #endif\r
432 \r
433 #endif /* defined(MSC_COUNT) && (MSC_COUNT > 0) */\r
434 #endif /* __SILICON_LABS_EM_MSC_H__ */\r