]> git.sur5r.net Git - freertos/blob
cf4d495a732815ce4da6311fa43710bb69019765
[freertos] /
1 /***************************************************************************//**\r
2  * @file em_bus.h\r
3  * @brief RAM and peripheral bit-field set and clear API\r
4  * @version 4.2.1\r
5  *******************************************************************************\r
6  * @section License\r
7  * <b>(C) Copyright 2015 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_BUS__\r
34 #define __SILICON_LABS_EM_BUS__\r
35 \r
36 #include "em_device.h"\r
37 \r
38 #ifdef __cplusplus\r
39 extern "C" {\r
40 #endif\r
41 \r
42 /***************************************************************************//**\r
43  * @addtogroup EM_Library\r
44  * @{\r
45  ******************************************************************************/\r
46 \r
47 /***************************************************************************//**\r
48  * @addtogroup BUS\r
49  * @brief BUS RAM and register bit/field read/write API\r
50  * @{\r
51  ******************************************************************************/\r
52 \r
53 /***************************************************************************//**\r
54  * @brief\r
55  *   Perform a single-bit write operation on a 32-bit word in RAM\r
56  *\r
57  * @details\r
58  *   This function uses Cortex-M bit-banding hardware to perform an atomic\r
59  *   read-modify-write operation on a single bit write on a 32-bit word in RAM.\r
60  *   Please refer to the reference manual for further details about bit-banding.\r
61  *\r
62  * @note\r
63  *   This function is atomic on Cortex-M cores with bit-banding support. Bit-\r
64  *   banding is a multicycle read-modify-write bus operation. RAM bit-banding is\r
65  *   performed using the memory alias region at BITBAND_RAM_BASE.\r
66  *\r
67  * @param[in] addr Address of 32-bit word in RAM\r
68  *\r
69  * @param[in] bit Bit position to write, 0-31\r
70  *\r
71  * @param[in] val Value to set bit to, 0 or 1\r
72  ******************************************************************************/\r
73 __STATIC_INLINE void BUS_RamBitWrite(volatile uint32_t *addr,\r
74                                      unsigned int bit,\r
75                                      unsigned int val)\r
76 {\r
77 #if defined( BITBAND_RAM_BASE )\r
78   uint32_t aliasAddr =\r
79     BITBAND_RAM_BASE + (((uint32_t)addr - SRAM_BASE) * 32) + (bit * 4);\r
80 \r
81   *(volatile uint32_t *)aliasAddr = (uint32_t)val;\r
82 #else\r
83   uint32_t tmp = *addr;\r
84 \r
85   /* Make sure val is not more than 1, because we only want to set one bit. */\r
86   *addr = (tmp & ~(1 << bit)) | ((val & 1) << bit);\r
87 #endif\r
88 }\r
89 \r
90 \r
91 /***************************************************************************//**\r
92  * @brief\r
93  *   Perform a single-bit read operation on a 32-bit word in RAM\r
94  *\r
95  * @details\r
96  *   This function uses Cortex-M bit-banding hardware to perform an atomic\r
97  *   read operation on a single register bit. Please refer to the\r
98  *   reference manual for further details about bit-banding.\r
99  *\r
100  * @note\r
101  *   This function is atomic on Cortex-M cores with bit-banding support.\r
102  *   RAM bit-banding is performed using the memory alias region\r
103  *   at BITBAND_RAM_BASE.\r
104  *\r
105  * @param[in] addr RAM address\r
106  *\r
107  * @param[in] bit Bit position to read, 0-31\r
108  *\r
109  * @return\r
110  *     The requested bit shifted to bit position 0 in the return value\r
111  ******************************************************************************/\r
112 __STATIC_INLINE unsigned int BUS_RamBitRead(volatile const uint32_t *addr,\r
113                                             unsigned int bit)\r
114 {\r
115 #if defined( BITBAND_RAM_BASE )\r
116   uint32_t aliasAddr =\r
117     BITBAND_RAM_BASE + (((uint32_t)addr - SRAM_BASE) * 32) + (bit * 4);\r
118 \r
119   return *(volatile uint32_t *)aliasAddr;\r
120 #else\r
121   return ((*addr) >> bit) & 1;\r
122 #endif\r
123 }\r
124 \r
125 \r
126 /***************************************************************************//**\r
127  * @brief\r
128  *   Perform a single-bit write operation on a peripheral register\r
129  *\r
130  * @details\r
131  *   This function uses Cortex-M bit-banding hardware to perform an atomic\r
132  *   read-modify-write operation on a single register bit. Please refer to the\r
133  *   reference manual for further details about bit-banding.\r
134  *\r
135  * @note\r
136  *   This function is atomic on Cortex-M cores with bit-banding support. Bit-\r
137  *   banding is a multicycle read-modify-write bus operation. Peripheral register\r
138  *   bit-banding is performed using the memory alias region at BITBAND_PER_BASE.\r
139  *\r
140  * @param[in] addr Peripheral register address\r
141  *\r
142  * @param[in] bit Bit position to write, 0-31\r
143  *\r
144  * @param[in] val Value to set bit to, 0 or 1\r
145  ******************************************************************************/\r
146 __STATIC_INLINE void BUS_RegBitWrite(volatile uint32_t *addr,\r
147                                      unsigned int bit,\r
148                                      unsigned int val)\r
149 {\r
150 #if defined( BITBAND_PER_BASE )\r
151   uint32_t aliasAddr =\r
152     BITBAND_PER_BASE + (((uint32_t)addr - PER_MEM_BASE) * 32) + (bit * 4);\r
153 \r
154   *(volatile uint32_t *)aliasAddr = (uint32_t)val;\r
155 #else\r
156   uint32_t tmp = *addr;\r
157 \r
158   /* Make sure val is not more than 1, because we only want to set one bit. */\r
159   *addr = (tmp & ~(1 << bit)) | ((val & 1) << bit);\r
160 #endif\r
161 }\r
162 \r
163 \r
164 /***************************************************************************//**\r
165  * @brief\r
166  *   Perform a single-bit read operation on a peripheral register\r
167  *\r
168  * @details\r
169  *   This function uses Cortex-M bit-banding hardware to perform an atomic\r
170  *   read operation on a single register bit. Please refer to the\r
171  *   reference manual for further details about bit-banding.\r
172  *\r
173  * @note\r
174  *   This function is atomic on Cortex-M cores with bit-banding support.\r
175  *   Peripheral register bit-banding is performed using the memory alias\r
176  *   region at BITBAND_PER_BASE.\r
177  *\r
178  * @param[in] addr Peripheral register address\r
179  *\r
180  * @param[in] bit Bit position to read, 0-31\r
181  *\r
182  * @return\r
183  *     The requested bit shifted to bit position 0 in the return value\r
184  ******************************************************************************/\r
185 __STATIC_INLINE unsigned int BUS_RegBitRead(volatile const uint32_t *addr,\r
186                                             unsigned int bit)\r
187 {\r
188 #if defined( BITBAND_PER_BASE )\r
189   uint32_t aliasAddr =\r
190     BITBAND_PER_BASE + (((uint32_t)addr - PER_MEM_BASE) * 32) + (bit * 4);\r
191 \r
192   return *(volatile uint32_t *)aliasAddr;\r
193 #else\r
194   return ((*addr) >> bit) & 1;\r
195 #endif\r
196 }\r
197 \r
198 \r
199 /***************************************************************************//**\r
200  * @brief\r
201  *   Perform a masked set operation on peripheral register address.\r
202  *\r
203  * @details\r
204  *   Peripheral register masked set provides a single-cycle and atomic set\r
205  *   operation of a bit-mask in a peripheral register. All 1's in the mask are\r
206  *   set to 1 in the register. All 0's in the mask are not changed in the\r
207  *   register.\r
208  *   RAMs and special peripherals are not supported. Please refer to the\r
209  *   reference manual for further details about peripheral register field set.\r
210  *\r
211  * @note\r
212  *   This function is single-cycle and atomic on cores with peripheral bit set\r
213  *   and clear support. It uses the memory alias region at PER_BITSET_MEM_BASE.\r
214  *\r
215  * @param[in] addr Peripheral register address\r
216  *\r
217  * @param[in] mask Mask to set\r
218  ******************************************************************************/\r
219 __STATIC_INLINE void BUS_RegMaskedSet(volatile uint32_t *addr,\r
220                                       uint32_t mask)\r
221 {\r
222 #if defined( PER_BITSET_MEM_BASE )\r
223   uint32_t aliasAddr = PER_BITSET_MEM_BASE + ((uint32_t)addr - PER_MEM_BASE);\r
224   *(volatile uint32_t *)aliasAddr = mask;\r
225 #else\r
226   *addr |= mask;\r
227 #endif\r
228 }\r
229 \r
230 \r
231 /***************************************************************************//**\r
232  * @brief\r
233  *   Perform a masked clear operation on peripheral register address.\r
234  *\r
235  * @details\r
236  *   Peripheral register masked clear provides a single-cycle and atomic clear\r
237  *   operation of a bit-mask in a peripheral register. All 1's in the mask are\r
238  *   set to 0 in the register.\r
239  *   All 0's in the mask are not changed in the register.\r
240  *   RAMs and special peripherals are not supported. Please refer to the\r
241  *   reference manual for further details about peripheral register field clear.\r
242  *\r
243  * @note\r
244  *   This function is single-cycle and atomic on cores with peripheral bit set\r
245  *   and clear support. It uses the memory alias region at PER_BITCLR_MEM_BASE.\r
246  *\r
247  * @param[in] addr Peripheral register address\r
248  *\r
249  * @param[in] mask Mask to clear\r
250  ******************************************************************************/\r
251 __STATIC_INLINE void BUS_RegMaskedClear(volatile uint32_t *addr,\r
252                                         uint32_t mask)\r
253 {\r
254 #if defined( PER_BITCLR_MEM_BASE )\r
255   uint32_t aliasAddr = PER_BITCLR_MEM_BASE + ((uint32_t)addr - PER_MEM_BASE);\r
256   *(volatile uint32_t *)aliasAddr = mask;\r
257 #else\r
258   *addr &= ~mask;\r
259 #endif\r
260 }\r
261 \r
262 \r
263 /***************************************************************************//**\r
264  * @brief\r
265  *   Perform peripheral register masked clear and value write.\r
266  *\r
267  * @details\r
268  *   This function first clears the mask in the peripheral register, then\r
269  *   writes the value. Typically the mask is a bit-field in the register, and\r
270  *   the value val is within the mask.\r
271  *\r
272  * @note\r
273  *   This operation is not atomic. Note that the mask is first set to 0 before\r
274  *   the val is set.\r
275  *\r
276  * @param[in] addr Peripheral register address\r
277  *\r
278  * @param[in] mask Peripheral register mask\r
279  *\r
280  * @param[in] val Peripheral register value. The value must be shifted to the\r
281                   correct bit position in the register.\r
282  ******************************************************************************/\r
283 __STATIC_INLINE void BUS_RegMaskedWrite(volatile uint32_t *addr,\r
284                                         uint32_t mask,\r
285                                         uint32_t val)\r
286 {\r
287 #if defined( PER_BITCLR_MEM_BASE )\r
288   BUS_RegMaskedClear(addr, mask);\r
289   BUS_RegMaskedSet(addr, val);\r
290 #else\r
291   *addr = (*addr & ~mask) | val;\r
292 #endif\r
293 }\r
294 \r
295 \r
296 /***************************************************************************//**\r
297  * @brief\r
298  *   Perform a peripheral register masked read\r
299  *\r
300  * @details\r
301  *   Read an unshifted and masked value from a peripheral register.\r
302  *\r
303  * @note\r
304  *   This operation is not hardware accelerated.\r
305  *\r
306  * @param[in] addr Peripheral register address\r
307  *\r
308  * @param[in] mask Peripheral register mask\r
309  *\r
310  * @return\r
311  *   Unshifted and masked register value\r
312  ******************************************************************************/\r
313 __STATIC_INLINE uint32_t BUS_RegMaskedRead(volatile const uint32_t *addr,\r
314                                            uint32_t mask)\r
315 {\r
316   return *addr & mask;\r
317 }\r
318 \r
319 \r
320 /** @} (end addtogroup BUS) */\r
321 /** @} (end addtogroup EM_Library) */\r
322 \r
323 #ifdef __cplusplus\r
324 }\r
325 #endif\r
326 \r
327 #endif /* __SILICON_LABS_EM_BUS__ */\r