1 /***************************************************************************//**
2  * @file
3  * @brief Universal asynchronous receiver/transmitter (EUSART) peripheral API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2023 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 "sl_hal_system.h"
32 #include "sl_hal_syscfg.h"
33 #include "em_device.h"
34 #include <stdbool.h>
35 #if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
36 #include "sl_se_manager.h"
37 #include "sli_se_manager_device_data.h"
38 #endif
39 #include "sl_status.h"
40 #include "sl_assert.h"
41 /***************************************************************************//**
42  * @addtogroup system
43  * @{
44  ******************************************************************************/
45 
46 /*******************************************************************************
47  **************************   DEFINES            *******************************
48  ******************************************************************************/
49 
50 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
51 
52 /* Bit mask used to extract the part number value without the new naming
53  * bitfield. */
54 #define SYSCFG_CHIPREV_PARTNUMBER1  0xFE0
55 #define SYSCFG_CHIPREV_PARTNUMBER0  0xF
56 
57 /** @endcond */
58 
59 #define HFRCO_DPLL_FREQUENCY_TABLE_SIZE  11
60 
61 #define DEVINFO_TEMPERATURE_CALTEMP_INTEGER_SHIFT  4
62 
63 /*******************************************************************************
64  *******************************   TYPEDEF   ***********************************
65  ******************************************************************************/
66 
67 #if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
68 typedef struct hfrco_dpll_cal_element {
69   uint32_t min_freq;
70   uint32_t max_freq;
71 } hfrco_dpll_cal_element_t;
72 #endif
73 
74 /*******************************************************************************
75  ******************************   CONSTANTS   **********************************
76  ******************************************************************************/
77 const sl_hal_system_devinfo_adc_t SL_HAL_SYSTEM_DEVINFO_ADC_RESET_VALUES = {
78   .cal_data = {
79     .trim_vros0 = 0,
80     .trim_vros1 = 0,
81     .trim_gain_4x = 0,
82     .trim_gain_0x3_int = 0
83   },
84   .offset = {
85     .trim_off_1x = 0,
86     .trim_off_2x = 0,
87     .trim_off_4x = 0
88   }
89 };
90 
91 const sl_hal_system_devinfo_temperature_t SL_HAL_SYSTEM_DEVINFO_TEMPERATURE_RESET_VALUES = {
92   .emu_temp_room = 0,
93   .cal_temp = 0
94 };
95 
96 #if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
97 static const hfrco_dpll_cal_element_t HFRCO_DPLL_FREQUENCY_TABLE[HFRCO_DPLL_FREQUENCY_TABLE_SIZE] = {
98   { .min_freq = 16000000, .max_freq = 20000000 }, // 18MHz calibration central frequency
99   { .min_freq = 20000000, .max_freq = 24500000 }, // 22MHz calibration central frequency
100   { .min_freq = 24500000, .max_freq = 30000000 }, // 27MHz calibration central frequency
101   { .min_freq = 30000000, .max_freq = 36000000 }, // 33MHz calibration central frequency
102   { .min_freq = 36000000, .max_freq = 42500000 }, // 39MHz calibration central frequency
103   { .min_freq = 42500000, .max_freq = 50500000 }, // 46MHz calibration central frequency
104   { .min_freq = 50500000, .max_freq = 60000000 }, // 55MHz calibration central frequency
105   { .min_freq = 60000000, .max_freq = 70000000 }, // 65MHz calibration central frequency
106   { .min_freq = 70000000, .max_freq = 80000000 }, // 75MHz calibration central frequency
107   { .min_freq = 80000000, .max_freq = 90000000 }, // 85MHz calibration central frequency
108   { .min_freq = 90000000, .max_freq = 100000000 } // 95MHz calibration central frequency
109 };
110 #endif
111 
112 /*******************************************************************************
113  ******************************   UTILITY  *************************************
114  ******************************************************************************/
115 
116 #if defined(_SILICON_LABS_32B_SERIES_2)
117 /***************************************************************************//**
118  * @brief Get the nth ASCII character of a specified number.
119  *
120  * @param[in] input_number
121  *    The number where the digit will be taken.
122  *
123  * @param[in] position
124  *    The digit position.
125  *
126  * @return
127  *    The ASCII value of the specified digit.
128  ******************************************************************************/
sli_get_n_digit(uint16_t input_number,uint8_t position)129 char sli_get_n_digit(uint16_t input_number, uint8_t position)
130 {
131   uint32_t exp[] = { 10, 100, 1000, 10000, 100000 };
132   uint32_t number = input_number;
133 
134   if (position > 4) {
135     EFM_ASSERT(false);
136     return '0';
137   }
138 
139   number = (number % exp[position]);
140 
141   if (position != 0) {
142     number = number / (exp[position - 1]);
143   }
144 
145   return (char)number + '0';
146 }
147 #endif
148 
149 #if defined(_DEVINFO_PART0_DIECODE0_MASK) && defined(_SILICON_LABS_SECURITY_FEATURE_VAULT)
150 /***************************************************************************//**
151  * @brief Convert hexadecimal ASCII character to integer value.
152  *
153  * @param[in] character
154  *    The character to be coverted to a number.
155  *
156  * @return
157  *    The uint8_t value of the character given in parameter.
158  ******************************************************************************/
sli_hex_ascii_to_value(char character)159 uint8_t sli_hex_ascii_to_value(char character)
160 {
161   if (character >= '0' && character <= '9') {
162     return character - '0';
163   } else if (character >= 'A' && character <= 'F') {
164     return character - 'A';
165   }
166 
167   return 0U;
168 }
169 #endif
170 
171 /*******************************************************************************
172  **************************   GLOBAL FUNCTIONS   *******************************
173  ******************************************************************************/
174 
175 /*******************************************************************************
176  * @brief Get CHIPREV register.
177  ******************************************************************************/
sl_hal_system_get_chip_revision(sl_hal_system_chip_revision_t * rev)178 void sl_hal_system_get_chip_revision(sl_hal_system_chip_revision_t *rev)
179 {
180 #if defined(CMU_CLKEN0_SYSCFG)
181   CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
182 #endif
183 
184   uint32_t chip_rev = sl_hal_syscfg_read_chip_rev();
185 
186   rev->minor = (chip_rev & _SYSCFG_CHIPREV_MINOR_MASK) >> _SYSCFG_CHIPREV_MINOR_SHIFT;
187   rev->major = (chip_rev & _SYSCFG_CHIPREV_MAJOR_MASK) >> _SYSCFG_CHIPREV_MAJOR_SHIFT;
188 #if defined(_SYSCFG_CHIPREV_PARTNUMBER_MASK)
189   rev->part_number = ((chip_rev & SYSCFG_CHIPREV_PARTNUMBER1) >> 5) | (chip_rev & SYSCFG_CHIPREV_PARTNUMBER0);
190   rev->family = (uint16_t)0xFFFF;
191 #elif defined(_SYSCFG_CHIPREV_FAMILY_MASK)
192   rev->part_number = (uint16_t)0xFFFF;
193   rev->family = (chip_rev & _SYSCFG_CHIPREV_FAMILY_MASK) >> _SYSCFG_CHIPREV_FAMILY_SHIFT;
194 #else
195   #error No Chip Revision Part Number or Family
196 #endif
197 }
198 
199 /***************************************************************************//**
200  * @brief Get the MCU family identifier.
201  ******************************************************************************/
sl_hal_system_get_family(void)202 sl_hal_system_part_family_t sl_hal_system_get_family(void)
203 {
204 #if defined(_DEVINFO_PART_FAMILY_MASK)
205   return (DEVINFO->PART & (_DEVINFO_PART_FAMILY_MASK
206                            | _DEVINFO_PART_FAMILYNUM_MASK));
207 #else
208   return (DEVINFO->PART0 & (_DEVINFO_PART0_PROTOCOL_MASK
209                             | _DEVINFO_PART0_SERIES_MASK
210                             | _DEVINFO_PART0_DIECODE0_MASK));
211 #endif
212 }
213 
214 /***************************************************************************//**
215  * @brief Get DEVINFO revision.
216  ******************************************************************************/
sl_hal_system_get_devinfo_rev(void)217 uint8_t sl_hal_system_get_devinfo_rev(void)
218 {
219 #if defined(_DEVINFO_INFO_DEVINFOREV_MASK)
220   return (uint8_t)((DEVINFO->INFO & _DEVINFO_INFO_DEVINFOREV_MASK)
221                    >> _DEVINFO_INFO_DEVINFOREV_SHIFT);
222 #elif defined(_DEVINFO_REVISION_DEVINFOREV_MASK)
223   return (uint8_t)((DEVINFO->REVISION & _DEVINFO_REVISION_DEVINFOREV_MASK)
224                    >> _DEVINFO_REVISION_DEVINFOREV_SHIFT);
225 #else
226 #error (sl_hal_system.c): Location of devinfo revision is not defined.
227 #endif
228 }
229 
230 /***************************************************************************//**
231  * @brief Get the default factory calibration value for HFRCO oscillator.
232  ******************************************************************************/
sl_hal_system_get_hfrco_default_calibration(void)233 uint32_t sl_hal_system_get_hfrco_default_calibration(void)
234 {
235 #if defined(_DEVINFO_HFRCOCALDEFAULT_MASK)
236   return DEVINFO->HFRCOCALDEFAULT;
237 #else
238   return 0;
239 #endif
240 }
241 
242 /***************************************************************************//**
243  * @brief Get the speed factory calibration value for HFRCO oscillator.
244  ******************************************************************************/
sl_hal_system_get_hfrco_speed_calibration(void)245 uint32_t sl_hal_system_get_hfrco_speed_calibration(void)
246 {
247 #if defined(_DEVINFO_HFRCOCALSPEED_MASK)
248   return DEVINFO->HFRCOCALSPEED;
249 #else
250   return 0;
251 #endif
252 }
253 
254 /***************************************************************************//**
255  * @brief Get the HFRCO calibration based on the frequency band.
256  ******************************************************************************/
sl_hal_system_get_hfrcodpll_band_calibration(uint32_t frequency)257 uint32_t sl_hal_system_get_hfrcodpll_band_calibration(uint32_t frequency)
258 {
259 #if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
260   sl_status_t status;
261   uint8_t band_index = 0xFF;
262   sl_se_command_context_t se_command_ctx;
263   sli_se_device_data_t otp_section_id = (sli_se_device_data_t)(SLI_SE_DEVICE_DATA_DI0 + DEVINFO_GP_FRAGMENT_INDEX);
264   uint32_t offset;
265   uint32_t calibration_value = 0;
266 
267   for (uint8_t i = 0; i < HFRCO_DPLL_FREQUENCY_TABLE_SIZE; i++) {
268     if ((frequency >= HFRCO_DPLL_FREQUENCY_TABLE[i].min_freq)
269         && (frequency <= HFRCO_DPLL_FREQUENCY_TABLE[i].max_freq)) {
270       band_index = i;
271       break;
272     }
273   }
274 
275   if (band_index >= HFRCO_DPLL_FREQUENCY_TABLE_SIZE) {
276     return 0;
277   }
278 
279   // Calculate memory offset based on the band index we want.
280   offset = (band_index * 4) + DEVINFO_GP_HFRCODPLLBAND0_OFFSET;
281 
282   // Initialize command context
283   status = sl_se_init_command_context(&se_command_ctx);
284   if (status != SL_STATUS_OK) {
285     return 0;
286   }
287 
288   // Send the SE command to retrieve the HFRCODPLL calibration for a given band from the DEVINFO OTP section
289   status = sli_se_device_data_read_word(&se_command_ctx, otp_section_id, offset, &calibration_value);
290   if (status != SL_STATUS_OK) {
291     return 0;
292   }
293 
294   return calibration_value;
295 #else
296   (void)frequency;
297   return 0;
298 #endif
299 }
300 
301 /***************************************************************************//**
302  * Get a factory calibration value for HFRCOCEM23 oscillator.
303  ******************************************************************************/
sl_hal_system_get_hfrcoem23_calibration(void)304 uint32_t sl_hal_system_get_hfrcoem23_calibration(void)
305 {
306 #if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
307   sl_status_t status;
308   sl_se_command_context_t se_command_ctx;
309   sli_se_device_data_t otp_section_id = (sli_se_device_data_t)(SLI_SE_DEVICE_DATA_DI0 + DEVINFO_GP_FRAGMENT_INDEX);
310   uint32_t offset = DEVINFO_GP_HFRCOEM23DEFAULT_OFFSET;
311   uint32_t calibration_value = 0;
312 
313   // Initialize command context
314   status = sl_se_init_command_context(&se_command_ctx);
315   if (status != SL_STATUS_OK) {
316     return 0;
317   }
318 
319   // Send the SE command to retrieve the HFRCOEM23 calibration from the DEVINFO OTP section
320   status = sli_se_device_data_read_word(&se_command_ctx, otp_section_id, offset, &calibration_value);
321   if (status != SL_STATUS_OK) {
322     return 0;
323   }
324 
325   return calibration_value;
326 #else
327   return 0;
328 #endif
329 }
330 
331 /***************************************************************************//**
332  * @brief Get a factory calibration value for HFXOCAL.
333  ******************************************************************************/
sl_hal_system_get_hfxocal(void)334 uint32_t sl_hal_system_get_hfxocal(void)
335 {
336 #if defined(_DEVINFO_HFXOCAL_MASK)
337   return DEVINFO->HFXOCAL;
338 #else
339   return 0;
340 #endif
341 }
342 
343 /***************************************************************************//**
344  * @brief Get family security capability.
345  ******************************************************************************/
sl_hal_system_get_security_capability(void)346 sl_hal_system_security_capability_t sl_hal_system_get_security_capability(void)
347 {
348   sl_hal_system_security_capability_t sc = SL_SYSTEM_SECURITY_CAPABILITY_UNKNOWN;
349 
350   uint16_t mcu_feature_set_major;
351   uint16_t device_number;
352   device_number = sl_hal_system_get_part_number();
353   mcu_feature_set_major = 'A' + (device_number / 1000);
354 #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
355   // override feature set since BRD4182A Rev A00 -> rev B02 are marked "A"
356   mcu_feature_set_major = 'C';
357 #endif
358 
359   switch (mcu_feature_set_major) {
360     case 'A':
361       sc = SL_SYSTEM_SECURITY_CAPABILITY_SE;
362       break;
363 
364     case 'B':
365       sc = SL_SYSTEM_SECURITY_CAPABILITY_VAULT;
366       break;
367 
368     case 'C':
369       sc = SL_SYSTEM_SECURITY_CAPABILITY_ROT;
370       break;
371 
372     default:
373       sc = SL_SYSTEM_SECURITY_CAPABILITY_UNKNOWN;
374       break;
375   }
376 
377   return sc;
378 }
379 
380 /***************************************************************************//**
381  * @brief Get the unique number for this device.
382  ******************************************************************************/
sl_hal_system_get_unique(void)383 uint64_t sl_hal_system_get_unique(void)
384 {
385   uint32_t tmp = DEVINFO->EUI64L;
386   return ((uint64_t)DEVINFO->EUI64H << 32) | tmp;
387 }
388 
389 /***************************************************************************//**
390  * @brief Get the production revision for this part.
391  ******************************************************************************/
sl_hal_system_get_prod_rev(void)392 uint8_t sl_hal_system_get_prod_rev(void)
393 {
394 #if defined(_DEVINFO_INFO_PRODREV_MASK)
395   return (uint8_t)((DEVINFO->INFO & _DEVINFO_INFO_PRODREV_MASK)
396                    >> _DEVINFO_INFO_PRODREV_SHIFT);
397 #elif defined(_DEVINFO_REVISION_PRODREV_MASK)
398   return (uint8_t)((DEVINFO->REVISION & _DEVINFO_REVISION_PRODREV_MASK)
399                    >> _DEVINFO_REVISION_PRODREV_SHIFT);
400 #else
401 #error (sl_hal_system.c): Location of production revision is not defined.
402 #endif
403 }
404 
405 /***************************************************************************//**
406  * @brief Get the SRAM Base Address.
407  ******************************************************************************/
sl_hal_system_get_sram_base_address(void)408 uint32_t sl_hal_system_get_sram_base_address(void)
409 {
410   return SRAM_BASE;
411 }
412 
413 /***************************************************************************//**
414  * @brief Get the SRAM size (in KB).
415  ******************************************************************************/
sl_hal_system_get_sram_size(void)416 uint16_t sl_hal_system_get_sram_size(void)
417 {
418 #if defined(_DEVINFO_MSIZE_SRAM_MASK)
419   return (uint16_t)((DEVINFO->MSIZE & _DEVINFO_MSIZE_SRAM_MASK)
420                     >> _DEVINFO_MSIZE_SRAM_SHIFT);
421 #elif defined(_DEVINFO_EMBSIZE_RAM_MASK)
422   return (uint16_t)((DEVINFO->EMBSIZE & _DEVINFO_EMBSIZE_RAM_MASK)
423                     >> _DEVINFO_EMBSIZE_RAM_SHIFT);
424 #else
425   #error (sl_hal_system.c): Location of SRAM Size is not defined.
426 #endif
427 }
428 
429 /***************************************************************************//**
430  * @brief Get the flash size (in KB).
431  ******************************************************************************/
sl_hal_system_get_flash_size(void)432 uint16_t sl_hal_system_get_flash_size(void)
433 {
434 #if defined(_DEVINFO_MSIZE_FLASH_MASK)
435   return (uint16_t)((DEVINFO->MSIZE & _DEVINFO_MSIZE_FLASH_MASK)
436                     >> _DEVINFO_MSIZE_FLASH_SHIFT);
437 #elif defined(_DEVINFO_STACKMSIZE_FLASH_MASK)
438   uint16_t stacked_flach_size = (uint16_t)((DEVINFO->STACKMSIZE & _DEVINFO_STACKMSIZE_FLASH_MASK)
439                                            >> _DEVINFO_STACKMSIZE_FLASH_SHIFT);
440 
441   if (stacked_flach_size == 0) {
442     // Defined in linker script for external flash provided by customers.
443     extern uint32_t __flash_size__;
444     // Get flash size in kB.
445     stacked_flach_size = (uint16_t)(uintptr_t)&__flash_size__ / 1024;
446   }
447 
448   return stacked_flach_size;
449 #endif
450 }
451 
452 /***************************************************************************//**
453  * @brief Get the flash page size in bytes.
454  ******************************************************************************/
sl_hal_system_get_flash_page_size(void)455 uint32_t sl_hal_system_get_flash_page_size(void)
456 {
457 #if defined(_DEVINFO_MEMINFO_FLASHPAGESIZE_MASK)
458   uint32_t tmp;
459   tmp = (DEVINFO->MEMINFO & _DEVINFO_MEMINFO_FLASHPAGESIZE_MASK)
460         >> _DEVINFO_MEMINFO_FLASHPAGESIZE_SHIFT;
461   return 1UL << ((tmp + 10UL) & 0x1FUL);
462 #else
463   // Defined in linker script for external flash provided by customers.
464   extern uint32_t __flash_page_size__;
465   return (uintptr_t)&__flash_page_size__;
466 #endif
467 }
468 
469 /***************************************************************************//**
470  * @brief Get the MCU part number.
471  ******************************************************************************/
sl_hal_system_get_part_number(void)472 uint16_t sl_hal_system_get_part_number(void)
473 {
474 #if defined(_DEVINFO_PART_DEVICENUM_MASK)
475   return (uint16_t)((DEVINFO->PART & _DEVINFO_PART_DEVICENUM_MASK)
476                     >> _DEVINFO_PART_DEVICENUM_SHIFT);
477 #elif defined(_DEVINFO_PART0_DIECODE0_MASK) && defined(_SILICON_LABS_SECURITY_FEATURE_VAULT)
478   // Encode features to the series 2 format.
479   // Add security level vault high for SIxG301.
480   uint16_t device_number = 1000;
481   uint32_t register_value = (DEVINFO->PART1 & _DEVINFO_PART1_FEATURE1_MASK) >> _DEVINFO_PART1_FEATURE1_SHIFT;
482 
483   device_number = sli_hex_ascii_to_value((char)register_value) * 100;
484 
485   register_value = (DEVINFO->PART1 & _DEVINFO_PART1_FEATURE2_MASK) >> _DEVINFO_PART1_FEATURE2_SHIFT;
486   device_number += sli_hex_ascii_to_value((char)register_value) * 10;
487 
488   register_value = (DEVINFO->PART2 & _DEVINFO_PART2_FEATURE3_MASK) >> _DEVINFO_PART2_FEATURE3_SHIFT;
489   device_number += sli_hex_ascii_to_value((char)register_value);
490 
491   return device_number;
492 #else
493 #error (em_system.c): Location of device part number is not defined.
494 #endif
495 }
496 
497 /***************************************************************************//**
498  * @brief Get the SoC or MCU features.
499  ******************************************************************************/
sl_hal_system_get_part_features(void)500 sl_hal_system_features_t sl_hal_system_get_part_features(void)
501 {
502   sl_hal_system_features_t part_features = { .feature1 = '0', .feature2 = '0', .feature3 = '0' };
503 
504 #if defined(_SILICON_LABS_32B_SERIES_2)
505   uint16_t device_number = ((DEVINFO->PART & _DEVINFO_PART_DEVICENUM_MASK) >> _DEVINFO_PART_DEVICENUM_SHIFT);
506 
507   part_features.feature1 = sli_get_n_digit(device_number, 2);
508   part_features.feature2 = sli_get_n_digit(device_number, 1);
509   part_features.feature3 = sli_get_n_digit(device_number, 0);
510 
511 #elif defined(_SILICON_LABS_32B_SERIES_3)
512 
513   part_features.feature1 = (DEVINFO->PART1 & _DEVINFO_PART1_FEATURE1_MASK) >> _DEVINFO_PART1_FEATURE1_SHIFT;
514   part_features.feature2 = (DEVINFO->PART1 & _DEVINFO_PART1_FEATURE2_MASK) >> _DEVINFO_PART1_FEATURE2_SHIFT;
515   part_features.feature3 = (DEVINFO->PART2 & _DEVINFO_PART2_FEATURE3_MASK) >> _DEVINFO_PART2_FEATURE3_SHIFT;
516 
517 #else
518 #error Not defined for this die.
519 #endif
520 
521   return part_features;
522 }
523 
524 /***************************************************************************//**
525  * @brief Get the temperature information.
526  ******************************************************************************/
sl_hal_system_get_temperature_info(sl_hal_system_devinfo_temperature_t * info)527 void sl_hal_system_get_temperature_info(sl_hal_system_devinfo_temperature_t *info)
528 {
529 #if defined(_DEVINFO_CALTEMP_MASK) || defined(_DEVINFO_EMUTEMP_MASK)
530 #if defined(_DEVINFO_CALTEMP_TEMP_MASK)
531   info->cal_temp = ((DEVINFO->CALTEMP & _DEVINFO_CALTEMP_TEMP_MASK)
532                     >> _DEVINFO_CALTEMP_TEMP_SHIFT);
533 #else
534   info->cal_temp = 0;
535 #endif
536 #if defined(_DEVINFO_EMUTEMP_EMUTEMPROOM_MASK)
537   info->emu_temp_room = ((DEVINFO->EMUTEMP & _DEVINFO_EMUTEMP_EMUTEMPROOM_MASK)
538                          >> _DEVINFO_EMUTEMP_EMUTEMPROOM_SHIFT);
539 #else
540   info->emu_temp_room = 0;
541 #endif
542 #elif defined (_SILICON_LABS_32B_SERIES_3_CONFIG_301)
543   sl_status_t status;
544   sl_se_command_context_t se_command_ctx;
545   sli_se_device_data_t otp_section_id = (sli_se_device_data_t)(SLI_SE_DEVICE_DATA_DI0 + DEVINFO_GP_FRAGMENT_INDEX);
546   uint32_t offset = DEVINFO_GP_TEMPERATURE_OFFSET;
547 
548   // Initialize command context
549   status = sl_se_init_command_context(&se_command_ctx);
550   if (status != SL_STATUS_OK) {
551     *info = SL_HAL_SYSTEM_DEVINFO_TEMPERATURE_RESET_VALUES;
552     return;
553   }
554 
555   // Send the SE command to retrieve the temperature information from the DEVINFO OTP section
556   status = sli_se_device_data_read_word(&se_command_ctx, otp_section_id, offset, (uint32_t*)info);
557   if (status != SL_STATUS_OK) {
558     *info = SL_HAL_SYSTEM_DEVINFO_TEMPERATURE_RESET_VALUES;
559     return;
560   }
561 
562   // Divide the temperature by 16 to retrieve only the integer part of the temperature value.
563   info->cal_temp = info->cal_temp >> DEVINFO_TEMPERATURE_CALTEMP_INTEGER_SHIFT;
564 #else
565   (void)info;
566 #endif
567 }
568 
569 /*******************************************************************************
570  * @brief Reads CHIPREV register.
571  ******************************************************************************/
sl_hal_syscfg_read_chip_rev(void)572 uint32_t sl_hal_syscfg_read_chip_rev(void)
573 {
574 #if defined(SL_TRUSTZONE_NONSECURE)
575   return sli_tz_syscfg_read_chiprev_register();
576 #else
577   return SYSCFG->CHIPREV;
578 #endif
579 }
580 
581 /*******************************************************************************
582  * @brief Set SYSTICEXTCLKEN bit in CFGSYSTIC to one.
583  ******************************************************************************/
sl_hal_syscfg_set_systicextclken_cfgsystic(void)584 void sl_hal_syscfg_set_systicextclken_cfgsystic(void)
585 {
586 #if defined(SL_TRUSTZONE_NONSECURE)
587   sli_tz_syscfg_set_systicextclken_cfgsystic();
588 #else
589   SYSCFG->CFGSYSTIC = (SYSCFG->CFGSYSTIC | _SYSCFG_CFGSYSTIC_SYSTICEXTCLKEN_MASK);
590 #endif
591 }
592 
593 /*******************************************************************************
594  * @brief Clear SYSTICEXTCLKEN bit in CFGSYSTIC to zero.
595  ******************************************************************************/
sl_hal_syscfg_clear_systicextclken_cfgsystic(void)596 void sl_hal_syscfg_clear_systicextclken_cfgsystic(void)
597 {
598 #if defined(SL_TRUSTZONE_NONSECURE)
599   sli_tz_syscfg_clear_systicextclken_cfgsystic();
600 #else
601   SYSCFG->CFGSYSTIC = (SYSCFG->CFGSYSTIC & ~_SYSCFG_CFGSYSTIC_SYSTICEXTCLKEN_MASK);
602 #endif
603 }
604 
605 #if defined(__FPU_PRESENT) && (__FPU_PRESENT == 1)
606 /***************************************************************************//**
607  * @brief Set floating point co-processor (FPU) access mode.
608  ******************************************************************************/
sl_hal_system_fpu_set_access_mode(sl_hal_system_fpu_access_t access_mode)609 void sl_hal_system_fpu_set_access_mode(sl_hal_system_fpu_access_t access_mode)
610 {
611   SCB->CPACR = (SCB->CPACR & ~(0xFUL << 20)) | access_mode;
612 }
613 #endif
614 
615 /***************************************************************************//**
616  * @brief Get the ADC calibration info.
617  ******************************************************************************/
sl_hal_system_get_adc_calibration_info(sl_hal_system_devinfo_adc_t * info)618 void sl_hal_system_get_adc_calibration_info(sl_hal_system_devinfo_adc_t *info)
619 {
620 #if defined(_SILICON_LABS_32B_SERIES_3_CONFIG_301)
621   sl_status_t status;
622   sl_se_command_context_t se_command_ctx;
623   sli_se_device_data_t otp_section_id = (sli_se_device_data_t)(SLI_SE_DEVICE_DATA_DI0 + DEVINFO_GP_FRAGMENT_INDEX);
624   uint32_t offset = DEVINFO_GP_ADC0CALDATA_OFFSET;
625   EFM_ASSERT(info != NULL);
626 
627   // Initialize command context
628   status = sl_se_init_command_context(&se_command_ctx);
629   if (status != SL_STATUS_OK) {
630     *info = SL_HAL_SYSTEM_DEVINFO_ADC_RESET_VALUES;
631     return;
632   }
633 
634   // Send the SE command to retrieve the ADC calibration from the DEVINFO OTP section
635   status = sli_se_device_data_read_chunk(&se_command_ctx,
636                                          otp_section_id,
637                                          offset,
638                                          sizeof(sl_hal_system_devinfo_adc_offset_t),
639                                          info);
640   if (status != SL_STATUS_OK) {
641     *info = SL_HAL_SYSTEM_DEVINFO_ADC_RESET_VALUES;
642     return;
643   }
644 #else
645   *info = SL_HAL_SYSTEM_DEVINFO_ADC_RESET_VALUES;
646 #endif
647 }
648 
649 /** @} (end addtogroup system) */
650