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   uint32_t chiprev = SYSCFG_readChipRev();
74 #if defined(_SYSCFG_CHIPREV_PARTNUMBER_MASK)
75   rev->partNumber = ((chiprev & SYSCFG_CHIPREV_PARTNUMBER1) >> 5) | (chiprev & SYSCFG_CHIPREV_PARTNUMBER0);
76 #else
77   rev->family = (chiprev & _SYSCFG_CHIPREV_FAMILY_MASK) >> _SYSCFG_CHIPREV_FAMILY_SHIFT;
78 #endif
79   rev->major  = (chiprev & _SYSCFG_CHIPREV_MAJOR_MASK)  >> _SYSCFG_CHIPREV_MAJOR_SHIFT;
80   rev->minor  = (chiprev & _SYSCFG_CHIPREV_MINOR_MASK)  >> _SYSCFG_CHIPREV_MINOR_SHIFT;
81 #else
82   uint8_t tmp;
83 
84   EFM_ASSERT(rev);
85 
86   /* CHIP FAMILY bit [5:2] */
87   tmp  = (uint8_t)(((ROMTABLE->PID1 & _ROMTABLE_PID1_FAMILYMSB_MASK)
88                     >> _ROMTABLE_PID1_FAMILYMSB_SHIFT) << 2);
89   /* CHIP FAMILY bit [1:0] */
90   tmp |=  (uint8_t)((ROMTABLE->PID0 & _ROMTABLE_PID0_FAMILYLSB_MASK)
91                     >> _ROMTABLE_PID0_FAMILYLSB_SHIFT);
92   rev->family = tmp;
93 
94   /* CHIP MAJOR bit [3:0] */
95   rev->major = (uint8_t)((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK)
96                          >> _ROMTABLE_PID0_REVMAJOR_SHIFT);
97 
98   /* CHIP MINOR bit [7:4] */
99   tmp  = (uint8_t)(((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK)
100                     >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);
101   /* CHIP MINOR bit [3:0] */
102   tmp |= (uint8_t)((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK)
103                    >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);
104   rev->minor = tmp;
105 #endif
106 }
107 
108 /***************************************************************************//**
109  * @brief
110  *    Get a factory calibration value for a given peripheral register.
111  *
112  * @param[in] regAddress
113  *    The peripheral calibration register address to get a calibration value for. If
114  *    the calibration value is found, this register is updated with the
115  *    calibration value.
116  *
117  * @return
118  *    True if a calibration value exists, false otherwise.
119  ******************************************************************************/
SYSTEM_GetCalibrationValue(volatile uint32_t * regAddress)120 bool SYSTEM_GetCalibrationValue(volatile uint32_t *regAddress)
121 {
122   SYSTEM_CalAddrVal_TypeDef * p, * end;
123 
124   uint32_t s_regAddress = (uint32_t)regAddress;
125   s_regAddress = s_regAddress & CONVERT_NS_TO_S;
126 
127 #if defined(MSC_FLASH_CHIPCONFIG_MEM_BASE)
128   p   = (SYSTEM_CalAddrVal_TypeDef *)MSC_FLASH_CHIPCONFIG_MEM_BASE;
129   end = (SYSTEM_CalAddrVal_TypeDef *)MSC_FLASH_CHIPCONFIG_MEM_END;
130 #else
131   p   = (SYSTEM_CalAddrVal_TypeDef *)(DEVINFO_BASE & 0xFFFFF000U);
132   end = (SYSTEM_CalAddrVal_TypeDef *)DEVINFO_BASE;
133 #endif
134 
135   for (; p < end; p++) {
136     if (p->address == 0) {
137       /* p->address == 0 marks the end of the table */
138       return false;
139     }
140     if (p->address == s_regAddress) {
141       *regAddress = p->calValue;
142       return true;
143     }
144   }
145   /* Nothing found for regAddress. */
146   return false;
147 }
148 
149 /***************************************************************************//**
150  * @brief
151  *   Get family security capability.
152  *
153  * @note
154  *   This function retrieves the family security capability based on the
155  *   device number. The device number is one letter and 3 digits:
156  *   DEVICENUMBER = (alpha-'A')*1000 + numeric. i.e. 0d = "A000"; 1123d = "B123".
157  *   The security capabilities are represented by ::SYSTEM_SecurityCapability_TypeDef.
158  *
159  * @return
160  *   Security capability of MCU.
161  ******************************************************************************/
SYSTEM_GetSecurityCapability(void)162 SYSTEM_SecurityCapability_TypeDef SYSTEM_GetSecurityCapability(void)
163 {
164   SYSTEM_SecurityCapability_TypeDef sc;
165 
166 #if (_SILICON_LABS_32B_SERIES == 0)
167   sc = securityCapabilityNA;
168 #elif (_SILICON_LABS_32B_SERIES == 1)
169   sc = securityCapabilityBasic;
170 #else
171   sc = securityCapabilityUnknown;
172 #endif
173 
174 #if (_SILICON_LABS_32B_SERIES == 2)
175   uint16_t mcuFeatureSetMajor;
176   uint16_t deviceNumber;
177   deviceNumber = SYSTEM_GetPartNumber();
178   mcuFeatureSetMajor = 'A' + (deviceNumber / 1000);
179 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
180   // override feature set since BRD4182A Rev A00 -> rev B02 are marked "A"
181   mcuFeatureSetMajor = 'C';
182 #endif
183 
184   switch (mcuFeatureSetMajor) {
185     case 'A':
186       sc = securityCapabilitySE;
187       break;
188 
189     case 'B':
190       sc = securityCapabilityVault;
191       break;
192 
193     case 'C':
194       sc = securityCapabilityRoT;
195       break;
196 
197     default:
198       sc = securityCapabilityUnknown;
199       break;
200   }
201 #endif
202 
203   return sc;
204 }
205 
206 /***************************************************************************//**
207  * @brief
208  *   Get the unique number for this device.
209  *
210  * @return
211  *   Unique number for this device.
212  ******************************************************************************/
SYSTEM_GetUnique(void)213 uint64_t SYSTEM_GetUnique(void)
214 {
215 #if defined (_DEVINFO_EUI64H_MASK)
216   uint32_t tmp = DEVINFO->EUI64L;
217   return (uint64_t)((uint64_t)DEVINFO->EUI64H << 32) | tmp;
218 #elif defined(_DEVINFO_UNIQUEH_MASK)
219   uint32_t tmp = DEVINFO->UNIQUEL;
220   return (uint64_t)((uint64_t)DEVINFO->UNIQUEH << 32) | tmp;
221 #else
222 #error (em_system.c): Location of device unique number is not defined.
223 #endif
224 }
225 
226 /***************************************************************************//**
227  * @brief
228  *   Get the production revision for this part.
229  *
230  * @return
231  *   Production revision for this part.
232  ******************************************************************************/
SYSTEM_GetProdRev(void)233 uint8_t SYSTEM_GetProdRev(void)
234 {
235 #if defined (_DEVINFO_PART_PROD_REV_MASK)
236   return (uint8_t)((DEVINFO->PART & _DEVINFO_PART_PROD_REV_MASK)
237                    >> _DEVINFO_PART_PROD_REV_SHIFT);
238 #elif defined (_DEVINFO_INFO_PRODREV_MASK)
239   return (uint8_t)((DEVINFO->INFO & _DEVINFO_INFO_PRODREV_MASK)
240                    >> _DEVINFO_INFO_PRODREV_SHIFT);
241 #else
242 #error (em_system.c): Location of production revision is not defined.
243 #endif
244 }
245 
246 /***************************************************************************//**
247  * @brief
248  *   Get the SRAM Base Address.
249  *
250  * @note
251  *   This function is used to retrieve the base address of the SRAM.
252  *
253  * @return
254  *   Base address SRAM (32-bit unsigned integer).
255  ******************************************************************************/
SYSTEM_GetSRAMBaseAddress(void)256 uint32_t SYSTEM_GetSRAMBaseAddress(void)
257 {
258   return (uint32_t)SRAM_BASE;
259 }
260 
261 /***************************************************************************//**
262  * @brief
263  *   Get the SRAM size (in KB).
264  *
265  * @note
266  *   This function retrieves SRAM size by reading the chip device
267  *   info structure. If your binary is made for one specific device only,
268  *   use SRAM_SIZE instead.
269  *
270  * @return
271  *   Size of internal SRAM (in KB).
272  ******************************************************************************/
SYSTEM_GetSRAMSize(void)273 uint16_t SYSTEM_GetSRAMSize(void)
274 {
275   uint16_t sizekb;
276 
277 #if defined(_EFM32_GECKO_FAMILY)
278   /* Early Gecko devices had a bug where SRAM and Flash size were swapped. */
279   if (SYSTEM_GetProdRev() < 5) {
280     sizekb = (DEVINFO->MSIZE & _DEVINFO_MSIZE_FLASH_MASK)
281              >> _DEVINFO_MSIZE_FLASH_SHIFT;
282   }
283 #endif
284   sizekb = (uint16_t)((DEVINFO->MSIZE & _DEVINFO_MSIZE_SRAM_MASK)
285                       >> _DEVINFO_MSIZE_SRAM_SHIFT);
286 
287 #if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80) && defined(_EFR_DEVICE)
288   /* Do not include EFR32xG1 RAMH. */
289   sizekb--;
290 #endif
291 
292   return sizekb;
293 }
294 
295 /***************************************************************************//**
296  * @brief
297  *   Get the flash size (in KB).
298  *
299  * @note
300  *   This function retrieves flash size by reading the chip device
301  *   info structure. If your binary is made for one specific device only,
302  *   use FLASH_SIZE instead.
303  *
304  * @return
305  *   Size of internal flash (in KB).
306  ******************************************************************************/
SYSTEM_GetFlashSize(void)307 uint16_t SYSTEM_GetFlashSize(void)
308 {
309 #if defined(_EFM32_GECKO_FAMILY)
310   /* Early Gecko devices had a bug where SRAM and Flash size were swapped. */
311   if (SYSTEM_GetProdRev() < 5) {
312     return (DEVINFO->MSIZE & _DEVINFO_MSIZE_SRAM_MASK)
313            >> _DEVINFO_MSIZE_SRAM_SHIFT;
314   }
315 #endif
316   return (uint16_t)((DEVINFO->MSIZE & _DEVINFO_MSIZE_FLASH_MASK)
317                     >> _DEVINFO_MSIZE_FLASH_SHIFT);
318 }
319 
320 /***************************************************************************//**
321  * @brief
322  *   Get the flash page size in bytes.
323  *
324  * @note
325  *   This function retrieves flash page size by reading the chip device
326  *   info structure. If your binary is made for one specific device only,
327  *   use FLASH_PAGE_SIZE instead.
328  *
329  * @return
330  *   Page size of internal flash in bytes.
331  ******************************************************************************/
SYSTEM_GetFlashPageSize(void)332 uint32_t SYSTEM_GetFlashPageSize(void)
333 {
334   uint32_t tmp;
335 
336 #if defined(_SILICON_LABS_32B_SERIES_0)
337 
338 #if defined(_EFM32_GIANT_FAMILY)
339   if (SYSTEM_GetProdRev() < 18) {
340     /* Early Giant/Leopard devices did not have MEMINFO in DEVINFO. */
341     return FLASH_PAGE_SIZE;
342   }
343 #elif defined(_EFM32_ZERO_FAMILY)
344   if (SYSTEM_GetProdRev() < 24) {
345     /* Early Zero devices have an incorrect DEVINFO flash page size */
346     return FLASH_PAGE_SIZE;
347   }
348 #endif
349 #endif
350 
351 #if defined(_DEVINFO_MEMINFO_FLASHPAGESIZE_MASK)
352   tmp = (DEVINFO->MEMINFO & _DEVINFO_MEMINFO_FLASHPAGESIZE_MASK)
353         >> _DEVINFO_MEMINFO_FLASHPAGESIZE_SHIFT;
354 #elif defined(_DEVINFO_MEMINFO_FLASH_PAGE_SIZE_MASK)
355   tmp = (DEVINFO->MEMINFO & _DEVINFO_MEMINFO_FLASH_PAGE_SIZE_MASK)
356         >> _DEVINFO_MEMINFO_FLASH_PAGE_SIZE_SHIFT;
357 #else
358 #error (em_system.c): Location of flash page size is not defined.
359 #endif
360 
361   return 1UL << ((tmp + 10UL) & 0x1FUL);
362 }
363 
364 /***************************************************************************//**
365  * @brief
366  *   Get the MCU part number.
367  *
368  * @return
369  *   The part number of MCU.
370  ******************************************************************************/
SYSTEM_GetPartNumber(void)371 uint16_t SYSTEM_GetPartNumber(void)
372 {
373 #if defined(_DEVINFO_PART_DEVICENUM_MASK)
374   return (uint16_t)((DEVINFO->PART & _DEVINFO_PART_DEVICENUM_MASK)
375                     >> _DEVINFO_PART_DEVICENUM_SHIFT);
376 #elif defined(_DEVINFO_PART_DEVICE_NUMBER_MASK)
377   return (uint16_t)((DEVINFO->PART & _DEVINFO_PART_DEVICE_NUMBER_MASK)
378                     >> _DEVINFO_PART_DEVICE_NUMBER_SHIFT);
379 #else
380 #error (em_system.c): Location of device part number is not defined.
381 #endif
382 }
383 
384 /***************************************************************************//**
385  * @brief
386  *   Get the calibration temperature (in degrees Celsius).
387  *
388  * @return
389  *   Calibration temperature in Celsius.
390  ******************************************************************************/
SYSTEM_GetCalibrationTemperature(void)391 uint8_t SYSTEM_GetCalibrationTemperature(void)
392 {
393 #if defined(_DEVINFO_CAL_TEMP_MASK)
394   return (uint8_t)((DEVINFO->CAL & _DEVINFO_CAL_TEMP_MASK)
395                    >> _DEVINFO_CAL_TEMP_SHIFT);
396 #elif defined(_DEVINFO_CALTEMP_TEMP_MASK)
397   return (uint8_t)((DEVINFO->CALTEMP & _DEVINFO_CALTEMP_TEMP_MASK)
398                    >> _DEVINFO_CALTEMP_TEMP_SHIFT);
399 #else
400 #error (em_system.c): Location of calibration temperature is not defined.
401 #endif
402 }
403 
404 /***************************************************************************//**
405  * @brief
406  *   Get the MCU family identifier.
407  *
408  * @note
409  *   This function retrieves family ID by reading the chip's device info
410  *   structure in flash memory. Users can retrieve family ID directly
411  *   by reading DEVINFO->PART item and decode with mask and shift
412  *   \#defines defined in \<part_family\>_devinfo.h (refer to code
413  *   below for details).
414  *
415  * @return
416  *   Family identifier of MCU.
417  ******************************************************************************/
SYSTEM_GetFamily(void)418 SYSTEM_PartFamily_TypeDef SYSTEM_GetFamily(void)
419 {
420 #if defined(_DEVINFO_PART_FAMILY_MASK)
421   return (SYSTEM_PartFamily_TypeDef)
422          ((uint32_t)((DEVINFO->PART & (_DEVINFO_PART_FAMILY_MASK
423                                        | _DEVINFO_PART_FAMILYNUM_MASK))));
424 #elif defined(_DEVINFO_PART_DEVICE_FAMILY_MASK)
425   return (SYSTEM_PartFamily_TypeDef)
426          ((uint32_t)((DEVINFO->PART & _DEVINFO_PART_DEVICE_FAMILY_MASK)
427                      >> _DEVINFO_PART_DEVICE_FAMILY_SHIFT));
428 #else
429   #error (em_system.h): Location of device family name is not defined.
430 #endif
431 }
432 
433 /** @} (end addtogroup system) */
434