1 /***************************************************************************//**
2 * @file
3 * @brief System Peripheral API
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30
31 #include "em_system.h"
32 #include "sl_assert.h"
33 #include <stddef.h>
34 #if defined(SYSCFG_PRESENT)
35 #include "em_syscfg.h"
36 #endif
37 /***************************************************************************//**
38 * @addtogroup system
39 * @{
40 ******************************************************************************/
41
42 /*******************************************************************************
43 ********************************* DEFINES *********************************
44 ******************************************************************************/
45
46 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
47
48 /* Bit mask used to extract the part number value without the new naming
49 * bitfield. */
50 #define SYSCFG_CHIPREV_PARTNUMBER1 0xFE0
51 #define SYSCFG_CHIPREV_PARTNUMBER0 0xF
52
53 /* Bit mask to convert NON-SECURE to SECURE */
54 #define CONVERT_NS_TO_S (~(1 << 28U))
55
56 /** @endcond */
57
58 /*******************************************************************************
59 ************************** GLOBAL FUNCTIONS *******************************
60 ******************************************************************************/
61
62 /***************************************************************************//**
63 * @brief
64 * Get a chip major/minor revision.
65 *
66 * @param[out] rev
67 * A location to place the chip revision information.
68 ******************************************************************************/
SYSTEM_ChipRevisionGet(SYSTEM_ChipRevision_TypeDef * rev)69 void SYSTEM_ChipRevisionGet(SYSTEM_ChipRevision_TypeDef *rev)
70 {
71 #if defined(_SYSCFG_CHIPREV_FAMILY_MASK) || defined(_SYSCFG_CHIPREV_PARTNUMBER_MASK)
72 /* On series-2 (and higher) the revision info is in the SYSCFG->CHIPREV register. */
73 #if defined(CMU_CLKEN0_SYSCFG)
74 CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
75 #endif
76 uint32_t chiprev = SYSCFG_readChipRev();
77 #if defined(_SYSCFG_CHIPREV_PARTNUMBER_MASK)
78 rev->partNumber = ((chiprev & SYSCFG_CHIPREV_PARTNUMBER1) >> 5) | (chiprev & SYSCFG_CHIPREV_PARTNUMBER0);
79 #else
80 rev->family = (chiprev & _SYSCFG_CHIPREV_FAMILY_MASK) >> _SYSCFG_CHIPREV_FAMILY_SHIFT;
81 #endif
82 rev->major = (chiprev & _SYSCFG_CHIPREV_MAJOR_MASK) >> _SYSCFG_CHIPREV_MAJOR_SHIFT;
83 rev->minor = (chiprev & _SYSCFG_CHIPREV_MINOR_MASK) >> _SYSCFG_CHIPREV_MINOR_SHIFT;
84 #else
85 uint8_t tmp;
86
87 EFM_ASSERT(rev);
88
89 /* CHIP FAMILY bit [5:2] */
90 tmp = (uint8_t)(((ROMTABLE->PID1 & _ROMTABLE_PID1_FAMILYMSB_MASK)
91 >> _ROMTABLE_PID1_FAMILYMSB_SHIFT) << 2);
92 /* CHIP FAMILY bit [1:0] */
93 tmp |= (uint8_t)((ROMTABLE->PID0 & _ROMTABLE_PID0_FAMILYLSB_MASK)
94 >> _ROMTABLE_PID0_FAMILYLSB_SHIFT);
95 rev->family = tmp;
96
97 /* CHIP MAJOR bit [3:0] */
98 rev->major = (uint8_t)((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK)
99 >> _ROMTABLE_PID0_REVMAJOR_SHIFT);
100
101 /* CHIP MINOR bit [7:4] */
102 tmp = (uint8_t)(((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK)
103 >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);
104 /* CHIP MINOR bit [3:0] */
105 tmp |= (uint8_t)((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK)
106 >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);
107 rev->minor = tmp;
108 #endif
109 }
110
111 /***************************************************************************//**
112 * @brief
113 * Get a factory calibration value for a given peripheral register.
114 *
115 * @param[in] regAddress
116 * The peripheral calibration register address to get a calibration value for. If
117 * the calibration value is found, this register is updated with the
118 * calibration value.
119 *
120 * @return
121 * True if a calibration value exists, false otherwise.
122 ******************************************************************************/
SYSTEM_GetCalibrationValue(volatile uint32_t * regAddress)123 bool SYSTEM_GetCalibrationValue(volatile uint32_t *regAddress)
124 {
125 SYSTEM_CalAddrVal_TypeDef * p, * end;
126
127 uint32_t s_regAddress = (uint32_t)regAddress;
128 s_regAddress = s_regAddress & CONVERT_NS_TO_S;
129
130 #if defined(MSC_FLASH_CHIPCONFIG_MEM_BASE)
131 p = (SYSTEM_CalAddrVal_TypeDef *)MSC_FLASH_CHIPCONFIG_MEM_BASE;
132 end = (SYSTEM_CalAddrVal_TypeDef *)MSC_FLASH_CHIPCONFIG_MEM_END;
133 #else
134 p = (SYSTEM_CalAddrVal_TypeDef *)(DEVINFO_BASE & 0xFFFFF000U);
135 end = (SYSTEM_CalAddrVal_TypeDef *)DEVINFO_BASE;
136 #endif
137
138 for (; p < end; p++) {
139 if (p->address == 0) {
140 /* p->address == 0 marks the end of the table */
141 return false;
142 }
143 if (p->address == s_regAddress) {
144 *regAddress = p->calValue;
145 return true;
146 }
147 }
148 /* Nothing found for regAddress. */
149 return false;
150 }
151
152 /***************************************************************************//**
153 * @brief
154 * Get family security capability.
155 *
156 * @note
157 * This function retrieves the family security capability based on the
158 * device number. The device number is one letter and 3 digits:
159 * DEVICENUMBER = (alpha-'A')*1000 + numeric. i.e. 0d = "A000"; 1123d = "B123".
160 * The security capabilities are represented by ::SYSTEM_SecurityCapability_TypeDef.
161 *
162 * @return
163 * Security capability of MCU.
164 ******************************************************************************/
SYSTEM_GetSecurityCapability(void)165 SYSTEM_SecurityCapability_TypeDef SYSTEM_GetSecurityCapability(void)
166 {
167 SYSTEM_SecurityCapability_TypeDef sc;
168
169 #if (_SILICON_LABS_32B_SERIES == 0)
170 sc = securityCapabilityNA;
171 #elif (_SILICON_LABS_32B_SERIES == 1)
172 sc = securityCapabilityBasic;
173 #else
174 sc = securityCapabilityUnknown;
175 #endif
176
177 #if (_SILICON_LABS_32B_SERIES == 2)
178 uint16_t mcuFeatureSetMajor;
179 uint16_t deviceNumber;
180 deviceNumber = SYSTEM_GetPartNumber();
181 mcuFeatureSetMajor = 'A' + (deviceNumber / 1000);
182 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
183 // override feature set since BRD4182A Rev A00 -> rev B02 are marked "A"
184 mcuFeatureSetMajor = 'C';
185 #endif
186
187 switch (mcuFeatureSetMajor) {
188 case 'A':
189 sc = securityCapabilitySE;
190 break;
191
192 case 'B':
193 sc = securityCapabilityVault;
194 break;
195
196 case 'C':
197 sc = securityCapabilityRoT;
198 break;
199
200 default:
201 sc = securityCapabilityUnknown;
202 break;
203 }
204 #endif
205
206 return sc;
207 }
208
209 /***************************************************************************//**
210 * @brief
211 * Get the unique number for this device.
212 *
213 * @return
214 * Unique number for this device.
215 ******************************************************************************/
SYSTEM_GetUnique(void)216 uint64_t SYSTEM_GetUnique(void)
217 {
218 #if defined (_DEVINFO_EUI64H_MASK)
219 uint32_t tmp = DEVINFO->EUI64L;
220 return (uint64_t)((uint64_t)DEVINFO->EUI64H << 32) | tmp;
221 #elif defined(_DEVINFO_UNIQUEH_MASK)
222 uint32_t tmp = DEVINFO->UNIQUEL;
223 return (uint64_t)((uint64_t)DEVINFO->UNIQUEH << 32) | tmp;
224 #else
225 #error (em_system.c): Location of device unique number is not defined.
226 #endif
227 }
228
229 /***************************************************************************//**
230 * @brief
231 * Get the production revision for this part.
232 *
233 * @return
234 * Production revision for this part.
235 ******************************************************************************/
SYSTEM_GetProdRev(void)236 uint8_t SYSTEM_GetProdRev(void)
237 {
238 #if defined (_DEVINFO_PART_PROD_REV_MASK)
239 return (uint8_t)((DEVINFO->PART & _DEVINFO_PART_PROD_REV_MASK)
240 >> _DEVINFO_PART_PROD_REV_SHIFT);
241 #elif defined (_DEVINFO_INFO_PRODREV_MASK)
242 return (uint8_t)((DEVINFO->INFO & _DEVINFO_INFO_PRODREV_MASK)
243 >> _DEVINFO_INFO_PRODREV_SHIFT);
244 #else
245 #error (em_system.c): Location of production revision is not defined.
246 #endif
247 }
248
249 /***************************************************************************//**
250 * @brief
251 * Get the SRAM Base Address.
252 *
253 * @note
254 * This function is used to retrieve the base address of the SRAM.
255 *
256 * @return
257 * Base address SRAM (32-bit unsigned integer).
258 ******************************************************************************/
SYSTEM_GetSRAMBaseAddress(void)259 uint32_t SYSTEM_GetSRAMBaseAddress(void)
260 {
261 return (uint32_t)SRAM_BASE;
262 }
263
264 /***************************************************************************//**
265 * @brief
266 * Get the SRAM size (in KB).
267 *
268 * @note
269 * This function retrieves SRAM size by reading the chip device
270 * info structure. If your binary is made for one specific device only,
271 * use SRAM_SIZE instead.
272 *
273 * @return
274 * Size of internal SRAM (in KB).
275 ******************************************************************************/
SYSTEM_GetSRAMSize(void)276 uint16_t SYSTEM_GetSRAMSize(void)
277 {
278 uint16_t sizekb;
279
280 #if defined(_EFM32_GECKO_FAMILY)
281 /* Early Gecko devices had a bug where SRAM and Flash size were swapped. */
282 if (SYSTEM_GetProdRev() < 5) {
283 sizekb = (DEVINFO->MSIZE & _DEVINFO_MSIZE_FLASH_MASK)
284 >> _DEVINFO_MSIZE_FLASH_SHIFT;
285 }
286 #endif
287 sizekb = (uint16_t)((DEVINFO->MSIZE & _DEVINFO_MSIZE_SRAM_MASK)
288 >> _DEVINFO_MSIZE_SRAM_SHIFT);
289
290 #if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80) && defined(_EFR_DEVICE)
291 /* Do not include EFR32xG1 RAMH. */
292 sizekb--;
293 #endif
294
295 return sizekb;
296 }
297
298 /***************************************************************************//**
299 * @brief
300 * Get the flash size (in KB).
301 *
302 * @note
303 * This function retrieves flash size by reading the chip device
304 * info structure. If your binary is made for one specific device only,
305 * use FLASH_SIZE instead.
306 *
307 * @return
308 * Size of internal flash (in KB).
309 ******************************************************************************/
SYSTEM_GetFlashSize(void)310 uint16_t SYSTEM_GetFlashSize(void)
311 {
312 #if defined(_EFM32_GECKO_FAMILY)
313 /* Early Gecko devices had a bug where SRAM and Flash size were swapped. */
314 if (SYSTEM_GetProdRev() < 5) {
315 return (DEVINFO->MSIZE & _DEVINFO_MSIZE_SRAM_MASK)
316 >> _DEVINFO_MSIZE_SRAM_SHIFT;
317 }
318 #endif
319 return (uint16_t)((DEVINFO->MSIZE & _DEVINFO_MSIZE_FLASH_MASK)
320 >> _DEVINFO_MSIZE_FLASH_SHIFT);
321 }
322
323 /***************************************************************************//**
324 * @brief
325 * Get the flash page size in bytes.
326 *
327 * @note
328 * This function retrieves flash page size by reading the chip device
329 * info structure. If your binary is made for one specific device only,
330 * use FLASH_PAGE_SIZE instead.
331 *
332 * @return
333 * Page size of internal flash in bytes.
334 ******************************************************************************/
SYSTEM_GetFlashPageSize(void)335 uint32_t SYSTEM_GetFlashPageSize(void)
336 {
337 uint32_t tmp;
338
339 #if defined(_SILICON_LABS_32B_SERIES_0)
340
341 #if defined(_EFM32_GIANT_FAMILY)
342 if (SYSTEM_GetProdRev() < 18) {
343 /* Early Giant/Leopard devices did not have MEMINFO in DEVINFO. */
344 return FLASH_PAGE_SIZE;
345 }
346 #elif defined(_EFM32_ZERO_FAMILY)
347 if (SYSTEM_GetProdRev() < 24) {
348 /* Early Zero devices have an incorrect DEVINFO flash page size */
349 return FLASH_PAGE_SIZE;
350 }
351 #endif
352 #endif
353
354 #if defined(_DEVINFO_MEMINFO_FLASHPAGESIZE_MASK)
355 tmp = (DEVINFO->MEMINFO & _DEVINFO_MEMINFO_FLASHPAGESIZE_MASK)
356 >> _DEVINFO_MEMINFO_FLASHPAGESIZE_SHIFT;
357 #elif defined(_DEVINFO_MEMINFO_FLASH_PAGE_SIZE_MASK)
358 tmp = (DEVINFO->MEMINFO & _DEVINFO_MEMINFO_FLASH_PAGE_SIZE_MASK)
359 >> _DEVINFO_MEMINFO_FLASH_PAGE_SIZE_SHIFT;
360 #else
361 #error (em_system.c): Location of flash page size is not defined.
362 #endif
363
364 return 1UL << ((tmp + 10UL) & 0x1FUL);
365 }
366
367 /***************************************************************************//**
368 * @brief
369 * Get the MCU part number.
370 *
371 * @return
372 * The part number of MCU.
373 ******************************************************************************/
SYSTEM_GetPartNumber(void)374 uint16_t SYSTEM_GetPartNumber(void)
375 {
376 #if defined(_DEVINFO_PART_DEVICENUM_MASK)
377 return (uint16_t)((DEVINFO->PART & _DEVINFO_PART_DEVICENUM_MASK)
378 >> _DEVINFO_PART_DEVICENUM_SHIFT);
379 #elif defined(_DEVINFO_PART_DEVICE_NUMBER_MASK)
380 return (uint16_t)((DEVINFO->PART & _DEVINFO_PART_DEVICE_NUMBER_MASK)
381 >> _DEVINFO_PART_DEVICE_NUMBER_SHIFT);
382 #else
383 #error (em_system.c): Location of device part number is not defined.
384 #endif
385 }
386
387 /***************************************************************************//**
388 * @brief
389 * Get the calibration temperature (in degrees Celsius).
390 *
391 * @return
392 * Calibration temperature in Celsius.
393 ******************************************************************************/
SYSTEM_GetCalibrationTemperature(void)394 uint8_t SYSTEM_GetCalibrationTemperature(void)
395 {
396 #if defined(_DEVINFO_CAL_TEMP_MASK)
397 return (uint8_t)((DEVINFO->CAL & _DEVINFO_CAL_TEMP_MASK)
398 >> _DEVINFO_CAL_TEMP_SHIFT);
399 #elif defined(_DEVINFO_CALTEMP_TEMP_MASK)
400 return (uint8_t)((DEVINFO->CALTEMP & _DEVINFO_CALTEMP_TEMP_MASK)
401 >> _DEVINFO_CALTEMP_TEMP_SHIFT);
402 #else
403 #error (em_system.c): Location of calibration temperature is not defined.
404 #endif
405 }
406
407 /***************************************************************************//**
408 * @brief
409 * Get the MCU family identifier.
410 *
411 * @note
412 * This function retrieves family ID by reading the chip's device info
413 * structure in flash memory. Users can retrieve family ID directly
414 * by reading DEVINFO->PART item and decode with mask and shift
415 * \#defines defined in \<part_family\>_devinfo.h (refer to code
416 * below for details).
417 *
418 * @return
419 * Family identifier of MCU.
420 ******************************************************************************/
SYSTEM_GetFamily(void)421 SYSTEM_PartFamily_TypeDef SYSTEM_GetFamily(void)
422 {
423 #if defined(_DEVINFO_PART_FAMILY_MASK)
424 return (SYSTEM_PartFamily_TypeDef)
425 ((uint32_t)((DEVINFO->PART & (_DEVINFO_PART_FAMILY_MASK
426 | _DEVINFO_PART_FAMILYNUM_MASK))));
427 #elif defined(_DEVINFO_PART_DEVICE_FAMILY_MASK)
428 return (SYSTEM_PartFamily_TypeDef)
429 ((uint32_t)((DEVINFO->PART & _DEVINFO_PART_DEVICE_FAMILY_MASK)
430 >> _DEVINFO_PART_DEVICE_FAMILY_SHIFT));
431 #else
432 #error (em_system.h): Location of device family name is not defined.
433 #endif
434 }
435
436 /** @} (end addtogroup system) */
437