From 6a1117a8d85a6c029808a22ae53be1387ff2ce92 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 15 Oct 2025 00:32:55 +0700 Subject: refactor sltb009a to family efm32 --- hw/bsp/efm32/FreeRTOSConfig/FreeRTOSConfig.h | 150 ++++++ hw/bsp/efm32/boards/sltb009a/board.cmake | 8 + hw/bsp/efm32/boards/sltb009a/board.h | 49 ++ hw/bsp/efm32/boards/sltb009a/board.mk | 9 + hw/bsp/efm32/family.c | 713 ++++++++++++++++++++++++++ hw/bsp/efm32/family.cmake | 107 ++++ hw/bsp/efm32/family.mk | 39 ++ hw/bsp/sltb009a/board.mk | 44 -- hw/bsp/sltb009a/sltb009a.c | 721 --------------------------- 9 files changed, 1075 insertions(+), 765 deletions(-) create mode 100644 hw/bsp/efm32/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/efm32/boards/sltb009a/board.cmake create mode 100644 hw/bsp/efm32/boards/sltb009a/board.h create mode 100644 hw/bsp/efm32/boards/sltb009a/board.mk create mode 100644 hw/bsp/efm32/family.c create mode 100644 hw/bsp/efm32/family.cmake create mode 100644 hw/bsp/efm32/family.mk delete mode 100644 hw/bsp/sltb009a/board.mk delete mode 100644 hw/bsp/sltb009a/sltb009a.c diff --git a/hw/bsp/efm32/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/efm32/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..0b3e7cd2d --- /dev/null +++ b/hw/bsp/efm32/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "em_device.h" +#endif + +/* Cortex-M4F port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*8*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +// EFM32GG12B has 3 priority bits +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<PWRCTRL = (immediate_switch ? EMU_PWRCTRL_IMMEDIATEPWRSWITCH : 0) | EMU_PWRCTRL_REGPWRSEL_DVDD | EMU_PWRCTRL_ANASW_AVDD; +} + +static void emu_reg_init(float target_voltage) +{ + if(target_voltage < 2300.f || target_voltage >= 3800.f) + return; + + uint8_t level = ((target_voltage - 2300.f) / 100.f); + + EMU->R5VCTRL = EMU_R5VCTRL_INPUTMODE_AUTO; + + EMU->R5VOUTLEVEL = level; /* Reg output to 3.3V*/ +} + +static void emu_dcdc_init(float target_voltage, float max_ln_current, float max_lp_current, float max_reverse_current) +{ + if(target_voltage < 1800.f || target_voltage >= 3000.f) + return; + + if(max_ln_current <= 0.f || max_ln_current > 200.f) + return; + + if(max_lp_current <= 0.f || max_lp_current > 10000.f) + return; + + if(max_reverse_current < 0.f || max_reverse_current > 160.f) + return; + + // Low Power & Low Noise current limit + uint8_t lp_bias = 0; + + if(max_lp_current < 75.f) + lp_bias = 0; + else if(max_lp_current < 500.f) + lp_bias = 1; + else if(max_lp_current < 2500.f) + lp_bias = 2; + else + lp_bias = 3; + + EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_LPCMPBIASEM234H_MASK) | ((uint32_t)lp_bias << _EMU_DCDCMISCCTRL_LPCMPBIASEM234H_SHIFT); + EMU->DCDCMISCCTRL |= EMU_DCDCMISCCTRL_LNFORCECCM; // Force CCM to prevent reverse current + EMU->DCDCLPCTRL |= EMU_DCDCLPCTRL_LPVREFDUTYEN; // Enable duty cycling of the bias for LP mode + EMU->DCDCLNFREQCTRL = (EMU->DCDCLNFREQCTRL & ~_EMU_DCDCLNFREQCTRL_RCOBAND_MASK) | 4; // Set RCO Band to 7MHz + + uint8_t fet_count = 0; + + if(max_ln_current < 20.f) + fet_count = 4; + else if(max_ln_current >= 20.f && max_ln_current < 40.f) + fet_count = 8; + else + fet_count = 16; + + EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_NFETCNT_MASK) | ((uint32_t)(fet_count - 1) << _EMU_DCDCMISCCTRL_NFETCNT_SHIFT); + EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_PFETCNT_MASK) | ((uint32_t)(fet_count - 1) << _EMU_DCDCMISCCTRL_PFETCNT_SHIFT); + + uint8_t ln_current_limit = (((max_ln_current + 40.f) * 1.5f) / (5.f * fet_count)) - 1; + uint8_t lp_current_limit = 1; // Recommended value + + EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~(_EMU_DCDCMISCCTRL_LNCLIMILIMSEL_MASK | _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_MASK)) | ((uint32_t)ln_current_limit << _EMU_DCDCMISCCTRL_LNCLIMILIMSEL_SHIFT) | ((uint32_t)lp_current_limit << _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_SHIFT); + + uint8_t z_det_limit = ((max_reverse_current + 40.f) * 1.5f) / (2.5f * fet_count); + + EMU->DCDCZDETCTRL = (EMU->DCDCZDETCTRL & ~_EMU_DCDCZDETCTRL_ZDETILIMSEL_MASK) | ((uint32_t)z_det_limit << _EMU_DCDCZDETCTRL_ZDETILIMSEL_SHIFT); + + EMU->DCDCCLIMCTRL |= EMU_DCDCCLIMCTRL_BYPLIMEN; // Enable bypass current limiter to prevent overcurrent when switching modes + + // Output Voltage + if(target_voltage > 1800.f) + { + float max_vout = 3000.f; + float min_vout = 1800.f; + float diff_vout = max_vout - min_vout; + + uint8_t ln_vref_high = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_MASK) >> _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_SHIFT; + uint8_t ln_vref_low = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_SHIFT; + + uint8_t ln_vref = ((target_voltage - min_vout) * (float)(ln_vref_high - ln_vref_low)) / diff_vout; + ln_vref += ln_vref_low; + + EMU->DCDCLNVCTRL = (ln_vref << _EMU_DCDCLNVCTRL_LNVREF_SHIFT) | EMU_DCDCLNVCTRL_LNATT; + + uint8_t lp_vref_low = 0; + uint8_t lp_vref_high = 0; + + switch(lp_bias) + { + case 0: + { + lp_vref_high = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_SHIFT; + lp_vref_low = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_SHIFT; + } + break; + case 1: + { + lp_vref_high = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_SHIFT; + lp_vref_low = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_SHIFT; + } + break; + case 2: + { + lp_vref_high = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_SHIFT; + lp_vref_low = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_SHIFT; + } + break; + case 3: + { + lp_vref_high = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_SHIFT; + lp_vref_low = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_SHIFT; + } + break; + } + + uint8_t lp_vref = ((target_voltage - min_vout) * (float)(lp_vref_high - lp_vref_low)) / diff_vout; + lp_vref += lp_vref_low; + + EMU->DCDCLPVCTRL = (lp_vref << _EMU_DCDCLPVCTRL_LPVREF_SHIFT) | EMU_DCDCLPVCTRL_LPATT; + } + else + { + float max_vout = 1800.f; + float min_vout = 1200.f; + float diff_vout = max_vout - min_vout; + + uint8_t ln_vref_high = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_SHIFT; + uint8_t ln_vref_low = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_SHIFT; + + uint8_t ln_vref = ((target_voltage - min_vout) * (float)(ln_vref_high - ln_vref_low)) / diff_vout; + ln_vref += ln_vref_low; + + EMU->DCDCLNVCTRL = ln_vref << _EMU_DCDCLNVCTRL_LNVREF_SHIFT; + + uint8_t lp_vref_low = 0; + uint8_t lp_vref_high = 0; + + switch(lp_bias) + { + case 0: + { + lp_vref_high = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_SHIFT; + lp_vref_low = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_SHIFT; + } + break; + case 1: + { + lp_vref_high = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_SHIFT; + lp_vref_low = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_SHIFT; + } + break; + case 2: + { + lp_vref_high = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_SHIFT; + lp_vref_low = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_SHIFT; + } + break; + case 3: + { + lp_vref_high = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_SHIFT; + lp_vref_low = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_SHIFT; + } + break; + } + + uint8_t lp_vref = ((target_voltage - min_vout) * (float)(lp_vref_high - lp_vref_low)) / diff_vout; + lp_vref += lp_vref_low; + + EMU->DCDCLPVCTRL = lp_vref << _EMU_DCDCLPVCTRL_LPVREF_SHIFT; + } + + EMU->DCDCLPCTRL = (EMU->DCDCLPCTRL & ~_EMU_DCDCLPCTRL_LPCMPHYSSELEM234H_MASK) | (((DEVINFO->DCDCLPCMPHYSSEL1 & (((uint32_t)0xFF) << (lp_bias * 8))) >> (lp_bias * 8)) << _EMU_DCDCLPCTRL_LPCMPHYSSELEM234H_SHIFT); + + while(EMU->DCDCSYNC & EMU_DCDCSYNC_DCDCCTRLBUSY); // Wait for configuration to write + + // Calibration + //EMU->DCDCLNCOMPCTRL = 0x57204077; // Compensation for 1uF DCDC capacitor + EMU->DCDCLNCOMPCTRL = 0xB7102137; // Compensation for 4.7uF DCDC capacitor + + // Enable DCDC converter + EMU->DCDCCTRL = EMU_DCDCCTRL_DCDCMODEEM4_EM4LOWPOWER | EMU_DCDCCTRL_DCDCMODEEM23_EM23LOWPOWER | EMU_DCDCCTRL_DCDCMODE_LOWNOISE; + + // Switch digital domain to DVDD + EMU->PWRCTRL = EMU_PWRCTRL_REGPWRSEL_DVDD | EMU_PWRCTRL_ANASW_AVDD; +} + +static void cmu_hfxo_startup_calib(uint16_t ib_trim, uint16_t c_tune) +{ + if(CMU->STATUS & CMU_STATUS_HFXOENS) + return; + + CMU->HFXOSTARTUPCTRL = (CMU->HFXOSTARTUPCTRL & ~(_CMU_HFXOSTARTUPCTRL_CTUNE_MASK | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK)) | (((uint32_t)c_tune << _CMU_HFXOSTARTUPCTRL_CTUNE_SHIFT) & _CMU_HFXOSTARTUPCTRL_CTUNE_MASK) | (((uint32_t)ib_trim << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT) & _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK); +} + +static void cmu_hfxo_steady_calib(uint16_t ib_trim, uint16_t c_tune) +{ + if(CMU->STATUS & CMU_STATUS_HFXOENS) + return; + + CMU->HFXOSTEADYSTATECTRL = (CMU->HFXOSTEADYSTATECTRL & ~(_CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK | _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK)) | (((uint32_t)c_tune << _CMU_HFXOSTEADYSTATECTRL_CTUNE_SHIFT) & _CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK) | (((uint32_t)ib_trim << _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_SHIFT) & _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK); +} + +static void cmu_hfrco_calib(uint32_t calibration) +{ + if(CMU->STATUS & CMU_STATUS_DPLLENS) + return; + + while(CMU->SYNCBUSY & CMU_SYNCBUSY_HFRCOBSY); + + CMU->HFRCOCTRL = calibration; + + while(CMU->SYNCBUSY & CMU_SYNCBUSY_HFRCOBSY); +} + +static void cmu_ushfrco_calib(uint8_t enable, uint32_t calibration) +{ + if(CMU->USBCRCTRL & CMU_USBCRCTRL_USBCREN) + return; + + if(!enable) + { + CMU->OSCENCMD = CMU_OSCENCMD_USHFRCODIS; + while(CMU->STATUS & CMU_STATUS_USHFRCOENS); + + return; + } + + while(CMU->SYNCBUSY & CMU_SYNCBUSY_USHFRCOBSY); + + CMU->USHFRCOCTRL = calibration | CMU_USHFRCOCTRL_FINETUNINGEN; + + while(CMU->SYNCBUSY & CMU_SYNCBUSY_USHFRCOBSY); + + if(enable && !(CMU->STATUS & CMU_STATUS_USHFRCOENS)) + { + CMU->OSCENCMD = CMU_OSCENCMD_USHFRCOEN; + + while(!(CMU->STATUS & CMU_STATUS_USHFRCORDY)); + } +} + +static void cmu_auxhfrco_calib(uint8_t enable, uint32_t calibration) +{ + if(!enable) + { + CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCODIS; + while(CMU->STATUS & CMU_STATUS_AUXHFRCOENS); + + return; + } + + while(CMU->SYNCBUSY & CMU_SYNCBUSY_AUXHFRCOBSY); + + CMU->AUXHFRCOCTRL = calibration; + + while(CMU->SYNCBUSY & CMU_SYNCBUSY_AUXHFRCOBSY); + + if(enable && !(CMU->STATUS & CMU_STATUS_AUXHFRCOENS)) + { + CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN; + + while(!(CMU->STATUS & CMU_STATUS_AUXHFRCORDY)); + } +} + + +static void cmu_init(void) +{ + // Change SDIO clock to HFXO if HFRCO selected and disable it + CMU->SDIOCTRL = CMU_SDIOCTRL_SDIOCLKDIS | CMU_SDIOCTRL_SDIOCLKSEL_HFXO; + while(CMU->STATUS & CMU_STATUS_SDIOCLKENS); + + // Change QSPI clock to HFXO if HFRCO selected and disable it + CMU->QSPICTRL = CMU_QSPICTRL_QSPI0CLKDIS | CMU_QSPICTRL_QSPI0CLKSEL_HFXO; + while(CMU->STATUS & CMU_STATUS_QSPI0CLKENS); + + // Disable DPLL if enabled + if(CMU->STATUS & CMU_STATUS_DPLLENS) + { + CMU->OSCENCMD = CMU_OSCENCMD_DPLLDIS; + while(CMU->STATUS & CMU_STATUS_DPLLENS); + } + + // Disable HFXO if enabled + if(CMU->STATUS & CMU_STATUS_HFXOENS) + { + CMU->OSCENCMD = CMU_OSCENCMD_HFXODIS; + while(CMU->STATUS & CMU_STATUS_HFXOENS); + } + + // Setup HFXO + CMU->HFXOCTRL = CMU_HFXOCTRL_PEAKDETMODE_AUTOCMD | CMU_HFXOCTRL_MODE_XTAL; + CMU->HFXOCTRL1 = CMU_HFXOCTRL1_PEAKDETTHR_DEFAULT; + CMU->HFXOSTEADYSTATECTRL |= CMU_HFXOSTEADYSTATECTRL_PEAKMONEN; + CMU->HFXOTIMEOUTCTRL = (7 << _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_SHIFT) | (8 << _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_SHIFT) | (12 << _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_SHIFT); + + // Enable HFXO and wait for it to be ready + CMU->OSCENCMD = CMU_OSCENCMD_HFXOEN; + while(!(CMU->STATUS & CMU_STATUS_HFXORDY)); + + // Switch main clock to HFXO and wait for it to be selected + CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFXO; + while((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) != CMU_HFCLKSTATUS_SELECTED_HFXO); + + // Calibrate HFRCO for 72MHz and enable tuning by PLL + cmu_hfrco_calib((DEVINFO->HFRCOCAL16) | CMU_HFRCOCTRL_FINETUNINGEN); + + // Setup the PLL + CMU->DPLLCTRL = CMU_DPLLCTRL_REFSEL_HFXO | CMU_DPLLCTRL_AUTORECOVER | CMU_DPLLCTRL_EDGESEL_RISE | CMU_DPLLCTRL_MODE_FREQLL; + // 72MHz = 50MHz (HFXO) * 1.44 (144/100) + CMU->DPLLCTRL1 = (143 << _CMU_DPLLCTRL1_N_SHIFT) | (99 << _CMU_DPLLCTRL1_M_SHIFT); // fHFRCO = fHFXO * (N + 1) / (M + 1) + + // Enable the DPLL and wait for it to be ready + CMU->OSCENCMD = CMU_OSCENCMD_DPLLEN; + while(!(CMU->STATUS & CMU_STATUS_DPLLRDY)); + + // Config peripherals for the new frequency (freq > 32MHz) + CMU->CTRL |= CMU_CTRL_WSHFLE; + + // Set prescalers + CMU->HFPRESC = CMU_HFPRESC_HFCLKLEPRESC_DIV2 | CMU_HFPRESC_PRESC_NODIVISION; + CMU->HFBUSPRESC = 1 << _CMU_HFBUSPRESC_PRESC_SHIFT; + CMU->HFCOREPRESC = 0 << _CMU_HFCOREPRESC_PRESC_SHIFT; + CMU->HFPERPRESC = 1 << _CMU_HFPERPRESC_PRESC_SHIFT; + CMU->HFEXPPRESC = 0 << _CMU_HFEXPPRESC_PRESC_SHIFT; + CMU->HFPERPRESCB = 0 << _CMU_HFPERPRESCB_PRESC_SHIFT; + CMU->HFPERPRESCC = 1 << _CMU_HFPERPRESCC_PRESC_SHIFT; + + // Enable clock to peripherals + CMU->CTRL |= CMU_CTRL_HFPERCLKEN; + + // Switch main clock to HFRCO and wait for it to be selected + CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFRCO; + while((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) != CMU_HFCLKSTATUS_SELECTED_HFRCO); + + // LFA Clock + CMU->LFACLKSEL = CMU_LFACLKSEL_LFA_LFRCO; + + // LFB Clock + CMU->LFBCLKSEL = CMU_LFBCLKSEL_LFB_LFRCO; + + // LFC Clock + CMU->LFCCLKSEL = CMU_LFCCLKSEL_LFC_LFRCO; + + // LFE Clock + CMU->LFECLKSEL = CMU_LFECLKSEL_LFE_ULFRCO; +} + +static void systick_init(void) +{ + SysTick->LOAD = (72000000 / 1000) - 1; + SysTick->VAL = 0; + SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk; + + SCB->SHP[11] = 7 << (8 - __NVIC_PRIO_BITS); // Set priority 3,1 (min) +} + +static void gpio_init(void) +{ + CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_GPIO; + + // NC - Not Connected (not available in mcu package) + // NR - Not routed (no routing to pin on pcb, floating) + // NU - Not used (not currently in use) + + // Port A + GPIO->P[0].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) + | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT); + GPIO->P[0].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NU + | GPIO_P_MODEL_MODE1_DISABLED // NU + | GPIO_P_MODEL_MODE2_DISABLED // NU + | GPIO_P_MODEL_MODE3_DISABLED // NU + | GPIO_P_MODEL_MODE4_DISABLED // NU + | GPIO_P_MODEL_MODE5_DISABLED // NU + | GPIO_P_MODEL_MODE6_DISABLED // NU + | GPIO_P_MODEL_MODE7_DISABLED; // NC + GPIO->P[0].MODEH = GPIO_P_MODEH_MODE8_DISABLED // GPIO - MIC_ENABLE + | GPIO_P_MODEH_MODE9_DISABLED // NC + | GPIO_P_MODEH_MODE10_DISABLED // NC + | GPIO_P_MODEH_MODE11_DISABLED // NC + | GPIO_P_MODEH_MODE12_WIREDAND // LED0R + | GPIO_P_MODEH_MODE13_WIREDAND // LED0B + | GPIO_P_MODEH_MODE14_WIREDAND // LED0G + | GPIO_P_MODEH_MODE15_DISABLED; // NU + GPIO->P[0].DOUT = 0x7000; // Leds off By default + GPIO->P[0].OVTDIS = 0; + + // Port B + GPIO->P[1].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) + | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT); + GPIO->P[1].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC + | GPIO_P_MODEL_MODE1_DISABLED // NC + | GPIO_P_MODEL_MODE2_DISABLED // NC + | GPIO_P_MODEL_MODE3_DISABLED // NU + | GPIO_P_MODEL_MODE4_DISABLED // NU + | GPIO_P_MODEL_MODE5_DISABLED // NU + | GPIO_P_MODEL_MODE6_DISABLED // NU + | GPIO_P_MODEL_MODE7_DISABLED; // MAIN_LFXTAL_P + GPIO->P[1].MODEH = GPIO_P_MODEH_MODE8_DISABLED // MAIN_LFXTAL_N + | GPIO_P_MODEH_MODE9_DISABLED // NC + | GPIO_P_MODEH_MODE10_DISABLED // NC + | GPIO_P_MODEH_MODE11_DISABLED // PDM_DAT0 - MIC_DATA + | GPIO_P_MODEH_MODE12_DISABLED // PDM_CLK - MIC_CLOCK + | GPIO_P_MODEH_MODE13_DISABLED // MAIN_HFXTAL_P + | GPIO_P_MODEH_MODE14_DISABLED // MAIN_HFXTAL_N + | GPIO_P_MODEH_MODE15_DISABLED; // NC + GPIO->P[1].DOUT = 0; + GPIO->P[1].OVTDIS = 0; + + // Port C + GPIO->P[2].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) + | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (7 << _GPIO_P_CTRL_SLEWRATE_SHIFT); + GPIO->P[2].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC + | GPIO_P_MODEL_MODE1_DISABLED // NC + | GPIO_P_MODEL_MODE2_DISABLED // NC + | GPIO_P_MODEL_MODE3_DISABLED // NC + | GPIO_P_MODEL_MODE4_DISABLED // NU + | GPIO_P_MODEL_MODE5_DISABLED // NU + | GPIO_P_MODEL_MODE6_DISABLED // NC + | GPIO_P_MODEL_MODE7_DISABLED; // NC + GPIO->P[2].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NC + | GPIO_P_MODEH_MODE9_DISABLED // NC + | GPIO_P_MODEH_MODE10_DISABLED // NC + | GPIO_P_MODEH_MODE11_DISABLED // NC + | GPIO_P_MODEH_MODE12_DISABLED // NC + | GPIO_P_MODEH_MODE13_DISABLED // NC + | GPIO_P_MODEH_MODE14_DISABLED // NC + | GPIO_P_MODEH_MODE15_DISABLED; // NC + GPIO->P[2].DOUT = 0; + GPIO->P[2].OVTDIS = 0; + + // Port D + GPIO->P[3].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) + | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT); + GPIO->P[3].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NU + | GPIO_P_MODEL_MODE1_DISABLED // NU + | GPIO_P_MODEL_MODE2_DISABLED // NU + | GPIO_P_MODEL_MODE3_DISABLED // NU + | GPIO_P_MODEL_MODE4_DISABLED // NU + | GPIO_P_MODEL_MODE5_INPUT // GPIO - BTN0 + | GPIO_P_MODEL_MODE6_WIREDAND // LED1R + | GPIO_P_MODEL_MODE7_DISABLED; // NU + GPIO->P[3].MODEH = GPIO_P_MODEH_MODE8_INPUT // GPIO - BTN1 + | GPIO_P_MODEH_MODE9_DISABLED // NC + | GPIO_P_MODEH_MODE10_DISABLED // NC + | GPIO_P_MODEH_MODE11_DISABLED // NC + | GPIO_P_MODEH_MODE12_DISABLED // NC + | GPIO_P_MODEH_MODE13_DISABLED // NC + | GPIO_P_MODEH_MODE14_DISABLED // NC + | GPIO_P_MODEH_MODE15_DISABLED; // NC + GPIO->P[3].DOUT = 0; + GPIO->P[3].OVTDIS = 0; + + // Port E + GPIO->P[4].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) + | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT); + GPIO->P[4].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC + | GPIO_P_MODEL_MODE1_DISABLED // NC + | GPIO_P_MODEL_MODE2_DISABLED // NC + | GPIO_P_MODEL_MODE3_DISABLED // NC + | GPIO_P_MODEL_MODE4_DISABLED // NU + | GPIO_P_MODEL_MODE5_DISABLED // NU + | GPIO_P_MODEL_MODE6_DISABLED // NU + | GPIO_P_MODEL_MODE7_DISABLED; // NU + GPIO->P[4].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NU + | GPIO_P_MODEH_MODE9_DISABLED // NU + | GPIO_P_MODEH_MODE10_DISABLED // NU + | GPIO_P_MODEH_MODE11_DISABLED // NU + | GPIO_P_MODEH_MODE12_WIREDAND // LED1B + | GPIO_P_MODEH_MODE13_DISABLED // NU + | GPIO_P_MODEH_MODE14_DISABLED // NU + | GPIO_P_MODEH_MODE15_DISABLED; // NU + GPIO->P[4].DOUT = 0; + GPIO->P[4].OVTDIS = 0; + + // Port F + GPIO->P[5].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) + | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT); + GPIO->P[5].MODEL = GPIO_P_MODEL_MODE0_PUSHPULL // SWCLK + | GPIO_P_MODEL_MODE1_PUSHPULL // SWDIO + | GPIO_P_MODEL_MODE2_PUSHPULL // SWO + | GPIO_P_MODEL_MODE3_DISABLED // NC + | GPIO_P_MODEL_MODE4_DISABLED // NC + | GPIO_P_MODEL_MODE5_DISABLED // NU + | GPIO_P_MODEL_MODE6_DISABLED // NC + | GPIO_P_MODEL_MODE7_DISABLED; // NC + GPIO->P[5].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NC + | GPIO_P_MODEH_MODE9_DISABLED // NC + | GPIO_P_MODEH_MODE10_DISABLED // USB N + | GPIO_P_MODEH_MODE11_DISABLED // USB P + | GPIO_P_MODEH_MODE12_WIREDAND // LED1G + | GPIO_P_MODEH_MODE13_DISABLED // NC + | GPIO_P_MODEH_MODE14_DISABLED // NC + | GPIO_P_MODEH_MODE15_DISABLED; // NC + GPIO->P[5].DOUT = 0; + + GPIO->P[5].OVTDIS = 0; + + // Debugger Route + GPIO->ROUTEPEN &= ~(GPIO_ROUTEPEN_TDIPEN | GPIO_ROUTEPEN_TDOPEN); // Disable JTAG + GPIO->ROUTEPEN |= GPIO_ROUTEPEN_SWVPEN; // Enable SWO + GPIO->ROUTELOC0 = GPIO_ROUTELOC0_SWVLOC_LOC0; // SWO on PF2 + + // External interrupts + GPIO->EXTIPSELL = GPIO_EXTIPSELL_EXTIPSEL0_PORTE // NU + | GPIO_EXTIPSELL_EXTIPSEL1_PORTB // NU + | GPIO_EXTIPSELL_EXTIPSEL2_PORTB // NU + | GPIO_EXTIPSELL_EXTIPSEL3_PORTB // NU + | GPIO_EXTIPSELL_EXTIPSEL4_PORTA // NU + | GPIO_EXTIPSELL_EXTIPSEL5_PORTA // NU + | GPIO_EXTIPSELL_EXTIPSEL6_PORTC // NU + | GPIO_EXTIPSELL_EXTIPSEL7_PORTC; // NU + GPIO->EXTIPSELH = GPIO_EXTIPSELH_EXTIPSEL8_PORTA // NU + | GPIO_EXTIPSELH_EXTIPSEL9_PORTE // NU + | GPIO_EXTIPSELH_EXTIPSEL10_PORTF // NU + | GPIO_EXTIPSELH_EXTIPSEL11_PORTA // NU + | GPIO_EXTIPSELH_EXTIPSEL12_PORTA // NU + | GPIO_EXTIPSELH_EXTIPSEL13_PORTE // NU + | GPIO_EXTIPSELH_EXTIPSEL14_PORTF // NU + | GPIO_EXTIPSELH_EXTIPSEL15_PORTA; // NU + + GPIO->EXTIPINSELL = GPIO_EXTIPINSELL_EXTIPINSEL0_PIN3 // NU + | GPIO_EXTIPINSELL_EXTIPINSEL1_PIN1 // NU + | GPIO_EXTIPINSELL_EXTIPINSEL2_PIN2 // NU + | GPIO_EXTIPINSELL_EXTIPINSEL3_PIN3 // NU + | GPIO_EXTIPINSELL_EXTIPINSEL4_PIN6 // NU + | GPIO_EXTIPINSELL_EXTIPINSEL5_PIN7 // NU + | GPIO_EXTIPINSELL_EXTIPINSEL6_PIN4 // NU + | GPIO_EXTIPINSELL_EXTIPINSEL7_PIN7; // NU + GPIO->EXTIPINSELH = GPIO_EXTIPINSELH_EXTIPINSEL8_PIN8 // NU + | GPIO_EXTIPINSELH_EXTIPINSEL9_PIN9 // NU + | GPIO_EXTIPINSELH_EXTIPINSEL10_PIN11 // NU + | GPIO_EXTIPINSELH_EXTIPINSEL11_PIN8 // NU + | GPIO_EXTIPINSELH_EXTIPINSEL12_PIN13 // NU + | GPIO_EXTIPINSELH_EXTIPINSEL13_PIN15 // NU + | GPIO_EXTIPINSELH_EXTIPINSEL14_PIN12 // NU + | GPIO_EXTIPINSELH_EXTIPINSEL15_PIN12; // NU + +} + +/*--------------------------------------------------------------------*/ +/* Board Init */ +/*--------------------------------------------------------------------*/ + +void board_init(void) +{ + + emu_dcdc_init(1800.f, 50.f, 100.f, 0.f); // Init DC-DC converter (1.8 V, 50 mA active, 100 uA sleep, 0 mA reverse limit) + emu_init(0); + emu_reg_init(3300.f); // set output regulator to 3.3V + + cmu_hfxo_startup_calib(0x200, 0x145); // Config HFXO Startup for 1280 uA, 36 pF (18 pF + 2 pF CLOAD) + cmu_hfxo_steady_calib(0x009, 0x145); // Config HFXO Steady for 12 uA, 36 pF (18 pF + 2 pF CLOAD) + + cmu_init(); // Init Clock Management Unit + + cmu_ushfrco_calib(1, DEVINFO->USHFRCOCAL13); // Enable and calibrate USHFRCO for 48 MHz + cmu_auxhfrco_calib(1, DEVINFO->AUXHFRCOCAL11); // Enable and calibrate AUXHFRCO for 32 MHz + + CMU->USBCRCTRL = CMU_USBCRCTRL_USBCREN; // enable USB clock recovery + CMU->USBCTRL = CMU_USBCTRL_USBCLKSEL_USHFRCO | CMU_USBCTRL_USBCLKEN; // select USHFRCO as USB Phy clock source and enable it + + CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_USB; // enable USB peripheral clock + + systick_init(); // Init system tick + + gpio_init(); // Init IOs + +} + +/*--------------------------------------------------------------------*/ +/* Board porting API */ +/*--------------------------------------------------------------------*/ + +void board_led_write(bool state) +{ + // Combine red and blue for pink Because it looks good :) + GPIO->P[LED_PORT].DOUT = (GPIO->P[LED_PORT].DOUT & ~((1 << LED_PIN_R) | (1 << LED_PIN_B))) | (state << LED_PIN_R) | (state << LED_PIN_B); +} + +uint32_t board_button_read(void) +{ + return !!(GPIO->P[BUTTON_PORT].DIN & (1 << BUTTON_PIN)); +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + (void) buf; (void) len; + return 0; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler(void) +{ + system_ticks++; +} + +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(char *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/hw/bsp/efm32/family.cmake b/hw/bsp/efm32/family.cmake new file mode 100644 index 000000000..f5afd6fe4 --- /dev/null +++ b/hw/bsp/efm32/family.cmake @@ -0,0 +1,107 @@ +include_guard() + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# EFM32_FAMILY should be set by board.cmake (e.g. efm32gg12b) +string(TOUPPER ${EFM32_FAMILY} EFM32_FAMILY_UPPER) +set(SILABS_CMSIS ${TOP}/hw/mcu/silabs/cmsis-dfp-${EFM32_FAMILY}/Device/SiliconLabs/${EFM32_FAMILY_UPPER}) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS EFM32GG CACHE INTERNAL "") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + set(LD_FILE_GNU ${SILABS_CMSIS}/Source/GCC/${EFM32_FAMILY}.ld) + set(LD_FILE_Clang ${LD_FILE_GNU}) + + if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) + message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") + endif () + + set(STARTUP_FILE_GNU ${SILABS_CMSIS}/Source/GCC/startup_${EFM32_FAMILY}.S) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${SILABS_CMSIS}/Source/system_${EFM32_FAMILY}.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMSIS_5}/CMSIS/Core/Include + ${SILABS_CMSIS}/Include + ) + + target_compile_definitions(${BOARD_TARGET} PUBLIC + __STARTUP_CLEAR_BSS + __START=main + ${EFM32_MCU} + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_EFM32GG) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/efm32/family.mk b/hw/bsp/efm32/family.mk new file mode 100644 index 000000000..f115b6bd4 --- /dev/null +++ b/hw/bsp/efm32/family.mk @@ -0,0 +1,39 @@ +include $(TOP)/$(BOARD_PATH)/board.mk + +CFLAGS += \ + -flto \ + -mthumb \ + -mcpu=cortex-m4 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib -nostartfiles \ + -D__STARTUP_CLEAR_BSS \ + -D__START=main \ + -DCFG_TUSB_MCU=OPT_MCU_EFM32GG + +CPU_CORE ?= cortex-m4 + +# EFM32_FAMILY should be set by board.mk (e.g. efm32gg12b) +SILABS_CMSIS = hw/mcu/silabs/cmsis-dfp-$(EFM32_FAMILY)/Device/SiliconLabs/$(shell echo $(EFM32_FAMILY) | tr a-z A-Z) + +LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs + +# All source paths should be relative to the top level. +LD_FILE = $(SILABS_CMSIS)/Source/GCC/$(EFM32_FAMILY).ld + +SRC_C += \ + $(SILABS_CMSIS)/Source/system_$(EFM32_FAMILY).c \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ + src/portable/synopsys/dwc2/hcd_dwc2.c \ + src/portable/synopsys/dwc2/dwc2_common.c \ + +SRC_S += \ + $(SILABS_CMSIS)/Source/GCC/startup_$(EFM32_FAMILY).S + +INC += \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + $(TOP)/$(SILABS_CMSIS)/Include \ + $(TOP)/$(BOARD_PATH) + +# For freeRTOS port source +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F diff --git a/hw/bsp/sltb009a/board.mk b/hw/bsp/sltb009a/board.mk deleted file mode 100644 index 5dd7a158f..000000000 --- a/hw/bsp/sltb009a/board.mk +++ /dev/null @@ -1,44 +0,0 @@ -CFLAGS += \ - -flto \ - -mthumb \ - -mcpu=cortex-m4 \ - -mfloat-abi=hard \ - -mfpu=fpv4-sp-d16 \ - -nostdlib -nostartfiles \ - -D__STARTUP_CLEAR_BSS \ - -D__START=main \ - -DEFM32GG12B810F1024GM64 \ - -DCFG_TUSB_MCU=OPT_MCU_EFM32GG - -# mcu driver cause following warnings -#CFLAGS += -Wno-error=unused-parameter - -SILABS_FAMILY = efm32gg12b -SILABS_CMSIS = hw/mcu/silabs/cmsis-dfp-$(SILABS_FAMILY)/Device/SiliconLabs/$(shell echo $(SILABS_FAMILY) | tr a-z A-Z) - -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs - -# All source paths should be relative to the top level. -LD_FILE = $(SILABS_CMSIS)/Source/GCC/$(SILABS_FAMILY).ld - -SRC_C += \ - $(SILABS_CMSIS)/Source/system_$(SILABS_FAMILY).c \ - src/portable/synopsys/dwc2/dcd_dwc2.c \ - src/portable/synopsys/dwc2/hcd_dwc2.c \ - src/portable/synopsys/dwc2/dwc2_common.c \ - -SRC_S += \ - $(SILABS_CMSIS)/Source/GCC/startup_$(SILABS_FAMILY).S - -INC += \ - $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ - $(TOP)/$(SILABS_CMSIS)/Include \ - $(TOP)/hw/bsp/$(BOARD) - -# For freeRTOS port source -FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F - -# For flash-jlink target -JLINK_DEVICE = EFM32GG12B810F1024 - -flash: flash-jlink diff --git a/hw/bsp/sltb009a/sltb009a.c b/hw/bsp/sltb009a/sltb009a.c deleted file mode 100644 index 23ef6d7cd..000000000 --- a/hw/bsp/sltb009a/sltb009a.c +++ /dev/null @@ -1,721 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021 Rafael Silva (@perigoso) - * Copyright (c) 2021 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "../board_api.h" - -#include "em_device.h" - -/*--------------------------------------------------------------------*/ -/* MACRO TYPEDEF CONSTANT ENUM */ -/*--------------------------------------------------------------------*/ - -#define LED_PORT 0 // A -#define LED_PIN_R 12 // 12 -#define LED_PIN_B 13 // 13 -#define LED_PIN_G 14 // 14 -#define LED_STATE_ON 0 // active-low - -#define BUTTON_PORT 3 // D -#define BUTTON_PIN 5 // 5 -#define BUTTON_STATE_ACTIVE 0 // active-low - -/*--------------------------------------------------------------------*/ -/* Forward USB interrupt events to TinyUSB IRQ Handler */ -/*--------------------------------------------------------------------*/ - -void USB_IRQHandler(void) -{ - tud_int_handler(0); -} - -/*--------------------------------------------------------------------*/ -/* Fault Handlers */ -/*--------------------------------------------------------------------*/ - -void HardFault_Handler(void) -{ - asm("bkpt"); -} - -void MemManage_Handler(void) -{ - asm("bkpt"); -} - -void BusFault_Handler(void) -{ - asm("bkpt"); -} - -void UsageFault_Handler(void) -{ - asm("bkpt"); -} - -/*--------------------------------------------------------------------*/ -/* Startup */ -/*--------------------------------------------------------------------*/ - -// Required by __libc_init_array in startup code if we are compiling using -// -nostdlib/-nostartfiles. -void _init(void) -{ - -} - -/*--------------------------------------------------------------------*/ -/* Initing Funcs */ -/*--------------------------------------------------------------------*/ - -void emu_init(uint8_t immediate_switch) -{ - EMU->PWRCTRL = (immediate_switch ? EMU_PWRCTRL_IMMEDIATEPWRSWITCH : 0) | EMU_PWRCTRL_REGPWRSEL_DVDD | EMU_PWRCTRL_ANASW_AVDD; -} - -void emu_reg_init(float target_voltage) -{ - if(target_voltage < 2300.f || target_voltage >= 3800.f) - return; - - uint8_t level = ((target_voltage - 2300.f) / 100.f); - - EMU->R5VCTRL = EMU_R5VCTRL_INPUTMODE_AUTO; - - EMU->R5VOUTLEVEL = level; /* Reg output to 3.3V*/ -} - -void emu_dcdc_init(float target_voltage, float max_ln_current, float max_lp_current, float max_reverse_current) -{ - if(target_voltage < 1800.f || target_voltage >= 3000.f) - return; - - if(max_ln_current <= 0.f || max_ln_current > 200.f) - return; - - if(max_lp_current <= 0.f || max_lp_current > 10000.f) - return; - - if(max_reverse_current < 0.f || max_reverse_current > 160.f) - return; - - // Low Power & Low Noise current limit - uint8_t lp_bias = 0; - - if(max_lp_current < 75.f) - lp_bias = 0; - else if(max_lp_current < 500.f) - lp_bias = 1; - else if(max_lp_current < 2500.f) - lp_bias = 2; - else - lp_bias = 3; - - EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_LPCMPBIASEM234H_MASK) | ((uint32_t)lp_bias << _EMU_DCDCMISCCTRL_LPCMPBIASEM234H_SHIFT); - EMU->DCDCMISCCTRL |= EMU_DCDCMISCCTRL_LNFORCECCM; // Force CCM to prevent reverse current - EMU->DCDCLPCTRL |= EMU_DCDCLPCTRL_LPVREFDUTYEN; // Enable duty cycling of the bias for LP mode - EMU->DCDCLNFREQCTRL = (EMU->DCDCLNFREQCTRL & ~_EMU_DCDCLNFREQCTRL_RCOBAND_MASK) | 4; // Set RCO Band to 7MHz - - uint8_t fet_count = 0; - - if(max_ln_current < 20.f) - fet_count = 4; - else if(max_ln_current >= 20.f && max_ln_current < 40.f) - fet_count = 8; - else - fet_count = 16; - - EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_NFETCNT_MASK) | ((uint32_t)(fet_count - 1) << _EMU_DCDCMISCCTRL_NFETCNT_SHIFT); - EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_PFETCNT_MASK) | ((uint32_t)(fet_count - 1) << _EMU_DCDCMISCCTRL_PFETCNT_SHIFT); - - uint8_t ln_current_limit = (((max_ln_current + 40.f) * 1.5f) / (5.f * fet_count)) - 1; - uint8_t lp_current_limit = 1; // Recommended value - - EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~(_EMU_DCDCMISCCTRL_LNCLIMILIMSEL_MASK | _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_MASK)) | ((uint32_t)ln_current_limit << _EMU_DCDCMISCCTRL_LNCLIMILIMSEL_SHIFT) | ((uint32_t)lp_current_limit << _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_SHIFT); - - uint8_t z_det_limit = ((max_reverse_current + 40.f) * 1.5f) / (2.5f * fet_count); - - EMU->DCDCZDETCTRL = (EMU->DCDCZDETCTRL & ~_EMU_DCDCZDETCTRL_ZDETILIMSEL_MASK) | ((uint32_t)z_det_limit << _EMU_DCDCZDETCTRL_ZDETILIMSEL_SHIFT); - - EMU->DCDCCLIMCTRL |= EMU_DCDCCLIMCTRL_BYPLIMEN; // Enable bypass current limiter to prevent overcurrent when switching modes - - // Output Voltage - if(target_voltage > 1800.f) - { - float max_vout = 3000.f; - float min_vout = 1800.f; - float diff_vout = max_vout - min_vout; - - uint8_t ln_vref_high = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_MASK) >> _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_SHIFT; - uint8_t ln_vref_low = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_SHIFT; - - uint8_t ln_vref = ((target_voltage - min_vout) * (float)(ln_vref_high - ln_vref_low)) / diff_vout; - ln_vref += ln_vref_low; - - EMU->DCDCLNVCTRL = (ln_vref << _EMU_DCDCLNVCTRL_LNVREF_SHIFT) | EMU_DCDCLNVCTRL_LNATT; - - uint8_t lp_vref_low = 0; - uint8_t lp_vref_high = 0; - - switch(lp_bias) - { - case 0: - { - lp_vref_high = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_SHIFT; - lp_vref_low = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_SHIFT; - } - break; - case 1: - { - lp_vref_high = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_SHIFT; - lp_vref_low = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_SHIFT; - } - break; - case 2: - { - lp_vref_high = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_SHIFT; - lp_vref_low = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_SHIFT; - } - break; - case 3: - { - lp_vref_high = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_SHIFT; - lp_vref_low = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_SHIFT; - } - break; - } - - uint8_t lp_vref = ((target_voltage - min_vout) * (float)(lp_vref_high - lp_vref_low)) / diff_vout; - lp_vref += lp_vref_low; - - EMU->DCDCLPVCTRL = (lp_vref << _EMU_DCDCLPVCTRL_LPVREF_SHIFT) | EMU_DCDCLPVCTRL_LPATT; - } - else - { - float max_vout = 1800.f; - float min_vout = 1200.f; - float diff_vout = max_vout - min_vout; - - uint8_t ln_vref_high = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_SHIFT; - uint8_t ln_vref_low = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_SHIFT; - - uint8_t ln_vref = ((target_voltage - min_vout) * (float)(ln_vref_high - ln_vref_low)) / diff_vout; - ln_vref += ln_vref_low; - - EMU->DCDCLNVCTRL = ln_vref << _EMU_DCDCLNVCTRL_LNVREF_SHIFT; - - uint8_t lp_vref_low = 0; - uint8_t lp_vref_high = 0; - - switch(lp_bias) - { - case 0: - { - lp_vref_high = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_SHIFT; - lp_vref_low = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_SHIFT; - } - break; - case 1: - { - lp_vref_high = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_SHIFT; - lp_vref_low = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_SHIFT; - } - break; - case 2: - { - lp_vref_high = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_SHIFT; - lp_vref_low = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_SHIFT; - } - break; - case 3: - { - lp_vref_high = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_SHIFT; - lp_vref_low = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_SHIFT; - } - break; - } - - uint8_t lp_vref = ((target_voltage - min_vout) * (float)(lp_vref_high - lp_vref_low)) / diff_vout; - lp_vref += lp_vref_low; - - EMU->DCDCLPVCTRL = lp_vref << _EMU_DCDCLPVCTRL_LPVREF_SHIFT; - } - - EMU->DCDCLPCTRL = (EMU->DCDCLPCTRL & ~_EMU_DCDCLPCTRL_LPCMPHYSSELEM234H_MASK) | (((DEVINFO->DCDCLPCMPHYSSEL1 & (((uint32_t)0xFF) << (lp_bias * 8))) >> (lp_bias * 8)) << _EMU_DCDCLPCTRL_LPCMPHYSSELEM234H_SHIFT); - - while(EMU->DCDCSYNC & EMU_DCDCSYNC_DCDCCTRLBUSY); // Wait for configuration to write - - // Calibration - //EMU->DCDCLNCOMPCTRL = 0x57204077; // Compensation for 1uF DCDC capacitor - EMU->DCDCLNCOMPCTRL = 0xB7102137; // Compensation for 4.7uF DCDC capacitor - - // Enable DCDC converter - EMU->DCDCCTRL = EMU_DCDCCTRL_DCDCMODEEM4_EM4LOWPOWER | EMU_DCDCCTRL_DCDCMODEEM23_EM23LOWPOWER | EMU_DCDCCTRL_DCDCMODE_LOWNOISE; - - // Switch digital domain to DVDD - EMU->PWRCTRL = EMU_PWRCTRL_REGPWRSEL_DVDD | EMU_PWRCTRL_ANASW_AVDD; -} - -void cmu_hfxo_startup_calib(uint16_t ib_trim, uint16_t c_tune) -{ - if(CMU->STATUS & CMU_STATUS_HFXOENS) - return; - - CMU->HFXOSTARTUPCTRL = (CMU->HFXOSTARTUPCTRL & ~(_CMU_HFXOSTARTUPCTRL_CTUNE_MASK | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK)) | (((uint32_t)c_tune << _CMU_HFXOSTARTUPCTRL_CTUNE_SHIFT) & _CMU_HFXOSTARTUPCTRL_CTUNE_MASK) | (((uint32_t)ib_trim << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT) & _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK); -} - -void cmu_hfxo_steady_calib(uint16_t ib_trim, uint16_t c_tune) -{ - if(CMU->STATUS & CMU_STATUS_HFXOENS) - return; - - CMU->HFXOSTEADYSTATECTRL = (CMU->HFXOSTEADYSTATECTRL & ~(_CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK | _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK)) | (((uint32_t)c_tune << _CMU_HFXOSTEADYSTATECTRL_CTUNE_SHIFT) & _CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK) | (((uint32_t)ib_trim << _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_SHIFT) & _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK); -} - -void cmu_hfrco_calib(uint32_t calibration) -{ - if(CMU->STATUS & CMU_STATUS_DPLLENS) - return; - - while(CMU->SYNCBUSY & CMU_SYNCBUSY_HFRCOBSY); - - CMU->HFRCOCTRL = calibration; - - while(CMU->SYNCBUSY & CMU_SYNCBUSY_HFRCOBSY); -} - -void cmu_ushfrco_calib(uint8_t enable, uint32_t calibration) -{ - if(CMU->USBCRCTRL & CMU_USBCRCTRL_USBCREN) - return; - - if(!enable) - { - CMU->OSCENCMD = CMU_OSCENCMD_USHFRCODIS; - while(CMU->STATUS & CMU_STATUS_USHFRCOENS); - - return; - } - - while(CMU->SYNCBUSY & CMU_SYNCBUSY_USHFRCOBSY); - - CMU->USHFRCOCTRL = calibration | CMU_USHFRCOCTRL_FINETUNINGEN; - - while(CMU->SYNCBUSY & CMU_SYNCBUSY_USHFRCOBSY); - - if(enable && !(CMU->STATUS & CMU_STATUS_USHFRCOENS)) - { - CMU->OSCENCMD = CMU_OSCENCMD_USHFRCOEN; - - while(!(CMU->STATUS & CMU_STATUS_USHFRCORDY)); - } -} - -void cmu_auxhfrco_calib(uint8_t enable, uint32_t calibration) -{ - if(!enable) - { - CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCODIS; - while(CMU->STATUS & CMU_STATUS_AUXHFRCOENS); - - return; - } - - while(CMU->SYNCBUSY & CMU_SYNCBUSY_AUXHFRCOBSY); - - CMU->AUXHFRCOCTRL = calibration; - - while(CMU->SYNCBUSY & CMU_SYNCBUSY_AUXHFRCOBSY); - - if(enable && !(CMU->STATUS & CMU_STATUS_AUXHFRCOENS)) - { - CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN; - - while(!(CMU->STATUS & CMU_STATUS_AUXHFRCORDY)); - } -} - - -void cmu_init(void) -{ - // Change SDIO clock to HFXO if HFRCO selected and disable it - CMU->SDIOCTRL = CMU_SDIOCTRL_SDIOCLKDIS | CMU_SDIOCTRL_SDIOCLKSEL_HFXO; - while(CMU->STATUS & CMU_STATUS_SDIOCLKENS); - - // Change QSPI clock to HFXO if HFRCO selected and disable it - CMU->QSPICTRL = CMU_QSPICTRL_QSPI0CLKDIS | CMU_QSPICTRL_QSPI0CLKSEL_HFXO; - while(CMU->STATUS & CMU_STATUS_QSPI0CLKENS); - - // Disable DPLL if enabled - if(CMU->STATUS & CMU_STATUS_DPLLENS) - { - CMU->OSCENCMD = CMU_OSCENCMD_DPLLDIS; - while(CMU->STATUS & CMU_STATUS_DPLLENS); - } - - // Disable HFXO if enabled - if(CMU->STATUS & CMU_STATUS_HFXOENS) - { - CMU->OSCENCMD = CMU_OSCENCMD_HFXODIS; - while(CMU->STATUS & CMU_STATUS_HFXOENS); - } - - // Setup HFXO - CMU->HFXOCTRL = CMU_HFXOCTRL_PEAKDETMODE_AUTOCMD | CMU_HFXOCTRL_MODE_XTAL; - CMU->HFXOCTRL1 = CMU_HFXOCTRL1_PEAKDETTHR_DEFAULT; - CMU->HFXOSTEADYSTATECTRL |= CMU_HFXOSTEADYSTATECTRL_PEAKMONEN; - CMU->HFXOTIMEOUTCTRL = (7 << _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_SHIFT) | (8 << _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_SHIFT) | (12 << _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_SHIFT); - - // Enable HFXO and wait for it to be ready - CMU->OSCENCMD = CMU_OSCENCMD_HFXOEN; - while(!(CMU->STATUS & CMU_STATUS_HFXORDY)); - - // Switch main clock to HFXO and wait for it to be selected - CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFXO; - while((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) != CMU_HFCLKSTATUS_SELECTED_HFXO); - - // Calibrate HFRCO for 72MHz and enable tuning by PLL - cmu_hfrco_calib((DEVINFO->HFRCOCAL16) | CMU_HFRCOCTRL_FINETUNINGEN); - - // Setup the PLL - CMU->DPLLCTRL = CMU_DPLLCTRL_REFSEL_HFXO | CMU_DPLLCTRL_AUTORECOVER | CMU_DPLLCTRL_EDGESEL_RISE | CMU_DPLLCTRL_MODE_FREQLL; - // 72MHz = 50MHz (HFXO) * 1.44 (144/100) - CMU->DPLLCTRL1 = (143 << _CMU_DPLLCTRL1_N_SHIFT) | (99 << _CMU_DPLLCTRL1_M_SHIFT); // fHFRCO = fHFXO * (N + 1) / (M + 1) - - // Enable the DPLL and wait for it to be ready - CMU->OSCENCMD = CMU_OSCENCMD_DPLLEN; - while(!(CMU->STATUS & CMU_STATUS_DPLLRDY)); - - // Config peripherals for the new frequency (freq > 32MHz) - CMU->CTRL |= CMU_CTRL_WSHFLE; - - // Set prescalers - CMU->HFPRESC = CMU_HFPRESC_HFCLKLEPRESC_DIV2 | CMU_HFPRESC_PRESC_NODIVISION; - CMU->HFBUSPRESC = 1 << _CMU_HFBUSPRESC_PRESC_SHIFT; - CMU->HFCOREPRESC = 0 << _CMU_HFCOREPRESC_PRESC_SHIFT; - CMU->HFPERPRESC = 1 << _CMU_HFPERPRESC_PRESC_SHIFT; - CMU->HFEXPPRESC = 0 << _CMU_HFEXPPRESC_PRESC_SHIFT; - CMU->HFPERPRESCB = 0 << _CMU_HFPERPRESCB_PRESC_SHIFT; - CMU->HFPERPRESCC = 1 << _CMU_HFPERPRESCC_PRESC_SHIFT; - - // Enable clock to peripherals - CMU->CTRL |= CMU_CTRL_HFPERCLKEN; - - // Switch main clock to HFRCO and wait for it to be selected - CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFRCO; - while((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) != CMU_HFCLKSTATUS_SELECTED_HFRCO); - - // LFA Clock - CMU->LFACLKSEL = CMU_LFACLKSEL_LFA_LFRCO; - - // LFB Clock - CMU->LFBCLKSEL = CMU_LFBCLKSEL_LFB_LFRCO; - - // LFC Clock - CMU->LFCCLKSEL = CMU_LFCCLKSEL_LFC_LFRCO; - - // LFE Clock - CMU->LFECLKSEL = CMU_LFECLKSEL_LFE_ULFRCO; -} - -void systick_init(void) -{ - SysTick->LOAD = (72000000 / 1000) - 1; - SysTick->VAL = 0; - SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk; - - SCB->SHP[11] = 7 << (8 - __NVIC_PRIO_BITS); // Set priority 3,1 (min) -} - -void gpio_init(void) -{ - CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_GPIO; - - // NC - Not Connected (not available in mcu package) - // NR - Not routed (no routing to pin on pcb, floating) - // NU - Not used (not currently in use) - - // Port A - GPIO->P[0].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) - | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT); - GPIO->P[0].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NU - | GPIO_P_MODEL_MODE1_DISABLED // NU - | GPIO_P_MODEL_MODE2_DISABLED // NU - | GPIO_P_MODEL_MODE3_DISABLED // NU - | GPIO_P_MODEL_MODE4_DISABLED // NU - | GPIO_P_MODEL_MODE5_DISABLED // NU - | GPIO_P_MODEL_MODE6_DISABLED // NU - | GPIO_P_MODEL_MODE7_DISABLED; // NC - GPIO->P[0].MODEH = GPIO_P_MODEH_MODE8_DISABLED // GPIO - MIC_ENABLE - | GPIO_P_MODEH_MODE9_DISABLED // NC - | GPIO_P_MODEH_MODE10_DISABLED // NC - | GPIO_P_MODEH_MODE11_DISABLED // NC - | GPIO_P_MODEH_MODE12_WIREDAND // LED0R - | GPIO_P_MODEH_MODE13_WIREDAND // LED0B - | GPIO_P_MODEH_MODE14_WIREDAND // LED0G - | GPIO_P_MODEH_MODE15_DISABLED; // NU - GPIO->P[0].DOUT = 0x7000; // Leds off By default - GPIO->P[0].OVTDIS = 0; - - // Port B - GPIO->P[1].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) - | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT); - GPIO->P[1].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC - | GPIO_P_MODEL_MODE1_DISABLED // NC - | GPIO_P_MODEL_MODE2_DISABLED // NC - | GPIO_P_MODEL_MODE3_DISABLED // NU - | GPIO_P_MODEL_MODE4_DISABLED // NU - | GPIO_P_MODEL_MODE5_DISABLED // NU - | GPIO_P_MODEL_MODE6_DISABLED // NU - | GPIO_P_MODEL_MODE7_DISABLED; // MAIN_LFXTAL_P - GPIO->P[1].MODEH = GPIO_P_MODEH_MODE8_DISABLED // MAIN_LFXTAL_N - | GPIO_P_MODEH_MODE9_DISABLED // NC - | GPIO_P_MODEH_MODE10_DISABLED // NC - | GPIO_P_MODEH_MODE11_DISABLED // PDM_DAT0 - MIC_DATA - | GPIO_P_MODEH_MODE12_DISABLED // PDM_CLK - MIC_CLOCK - | GPIO_P_MODEH_MODE13_DISABLED // MAIN_HFXTAL_P - | GPIO_P_MODEH_MODE14_DISABLED // MAIN_HFXTAL_N - | GPIO_P_MODEH_MODE15_DISABLED; // NC - GPIO->P[1].DOUT = 0; - GPIO->P[1].OVTDIS = 0; - - // Port C - GPIO->P[2].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) - | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (7 << _GPIO_P_CTRL_SLEWRATE_SHIFT); - GPIO->P[2].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC - | GPIO_P_MODEL_MODE1_DISABLED // NC - | GPIO_P_MODEL_MODE2_DISABLED // NC - | GPIO_P_MODEL_MODE3_DISABLED // NC - | GPIO_P_MODEL_MODE4_DISABLED // NU - | GPIO_P_MODEL_MODE5_DISABLED // NU - | GPIO_P_MODEL_MODE6_DISABLED // NC - | GPIO_P_MODEL_MODE7_DISABLED; // NC - GPIO->P[2].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NC - | GPIO_P_MODEH_MODE9_DISABLED // NC - | GPIO_P_MODEH_MODE10_DISABLED // NC - | GPIO_P_MODEH_MODE11_DISABLED // NC - | GPIO_P_MODEH_MODE12_DISABLED // NC - | GPIO_P_MODEH_MODE13_DISABLED // NC - | GPIO_P_MODEH_MODE14_DISABLED // NC - | GPIO_P_MODEH_MODE15_DISABLED; // NC - GPIO->P[2].DOUT = 0; - GPIO->P[2].OVTDIS = 0; - - // Port D - GPIO->P[3].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) - | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT); - GPIO->P[3].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NU - | GPIO_P_MODEL_MODE1_DISABLED // NU - | GPIO_P_MODEL_MODE2_DISABLED // NU - | GPIO_P_MODEL_MODE3_DISABLED // NU - | GPIO_P_MODEL_MODE4_DISABLED // NU - | GPIO_P_MODEL_MODE5_INPUT // GPIO - BTN0 - | GPIO_P_MODEL_MODE6_WIREDAND // LED1R - | GPIO_P_MODEL_MODE7_DISABLED; // NU - GPIO->P[3].MODEH = GPIO_P_MODEH_MODE8_INPUT // GPIO - BTN1 - | GPIO_P_MODEH_MODE9_DISABLED // NC - | GPIO_P_MODEH_MODE10_DISABLED // NC - | GPIO_P_MODEH_MODE11_DISABLED // NC - | GPIO_P_MODEH_MODE12_DISABLED // NC - | GPIO_P_MODEH_MODE13_DISABLED // NC - | GPIO_P_MODEH_MODE14_DISABLED // NC - | GPIO_P_MODEH_MODE15_DISABLED; // NC - GPIO->P[3].DOUT = 0; - GPIO->P[3].OVTDIS = 0; - - // Port E - GPIO->P[4].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) - | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT); - GPIO->P[4].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC - | GPIO_P_MODEL_MODE1_DISABLED // NC - | GPIO_P_MODEL_MODE2_DISABLED // NC - | GPIO_P_MODEL_MODE3_DISABLED // NC - | GPIO_P_MODEL_MODE4_DISABLED // NU - | GPIO_P_MODEL_MODE5_DISABLED // NU - | GPIO_P_MODEL_MODE6_DISABLED // NU - | GPIO_P_MODEL_MODE7_DISABLED; // NU - GPIO->P[4].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NU - | GPIO_P_MODEH_MODE9_DISABLED // NU - | GPIO_P_MODEH_MODE10_DISABLED // NU - | GPIO_P_MODEH_MODE11_DISABLED // NU - | GPIO_P_MODEH_MODE12_WIREDAND // LED1B - | GPIO_P_MODEH_MODE13_DISABLED // NU - | GPIO_P_MODEH_MODE14_DISABLED // NU - | GPIO_P_MODEH_MODE15_DISABLED; // NU - GPIO->P[4].DOUT = 0; - GPIO->P[4].OVTDIS = 0; - - // Port F - GPIO->P[5].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT) - | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT); - GPIO->P[5].MODEL = GPIO_P_MODEL_MODE0_PUSHPULL // SWCLK - | GPIO_P_MODEL_MODE1_PUSHPULL // SWDIO - | GPIO_P_MODEL_MODE2_PUSHPULL // SWO - | GPIO_P_MODEL_MODE3_DISABLED // NC - | GPIO_P_MODEL_MODE4_DISABLED // NC - | GPIO_P_MODEL_MODE5_DISABLED // NU - | GPIO_P_MODEL_MODE6_DISABLED // NC - | GPIO_P_MODEL_MODE7_DISABLED; // NC - GPIO->P[5].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NC - | GPIO_P_MODEH_MODE9_DISABLED // NC - | GPIO_P_MODEH_MODE10_DISABLED // USB N - | GPIO_P_MODEH_MODE11_DISABLED // USB P - | GPIO_P_MODEH_MODE12_WIREDAND // LED1G - | GPIO_P_MODEH_MODE13_DISABLED // NC - | GPIO_P_MODEH_MODE14_DISABLED // NC - | GPIO_P_MODEH_MODE15_DISABLED; // NC - GPIO->P[5].DOUT = 0; - - GPIO->P[5].OVTDIS = 0; - - // Debugger Route - GPIO->ROUTEPEN &= ~(GPIO_ROUTEPEN_TDIPEN | GPIO_ROUTEPEN_TDOPEN); // Disable JTAG - GPIO->ROUTEPEN |= GPIO_ROUTEPEN_SWVPEN; // Enable SWO - GPIO->ROUTELOC0 = GPIO_ROUTELOC0_SWVLOC_LOC0; // SWO on PF2 - - // External interrupts - GPIO->EXTIPSELL = GPIO_EXTIPSELL_EXTIPSEL0_PORTE // NU - | GPIO_EXTIPSELL_EXTIPSEL1_PORTB // NU - | GPIO_EXTIPSELL_EXTIPSEL2_PORTB // NU - | GPIO_EXTIPSELL_EXTIPSEL3_PORTB // NU - | GPIO_EXTIPSELL_EXTIPSEL4_PORTA // NU - | GPIO_EXTIPSELL_EXTIPSEL5_PORTA // NU - | GPIO_EXTIPSELL_EXTIPSEL6_PORTC // NU - | GPIO_EXTIPSELL_EXTIPSEL7_PORTC; // NU - GPIO->EXTIPSELH = GPIO_EXTIPSELH_EXTIPSEL8_PORTA // NU - | GPIO_EXTIPSELH_EXTIPSEL9_PORTE // NU - | GPIO_EXTIPSELH_EXTIPSEL10_PORTF // NU - | GPIO_EXTIPSELH_EXTIPSEL11_PORTA // NU - | GPIO_EXTIPSELH_EXTIPSEL12_PORTA // NU - | GPIO_EXTIPSELH_EXTIPSEL13_PORTE // NU - | GPIO_EXTIPSELH_EXTIPSEL14_PORTF // NU - | GPIO_EXTIPSELH_EXTIPSEL15_PORTA; // NU - - GPIO->EXTIPINSELL = GPIO_EXTIPINSELL_EXTIPINSEL0_PIN3 // NU - | GPIO_EXTIPINSELL_EXTIPINSEL1_PIN1 // NU - | GPIO_EXTIPINSELL_EXTIPINSEL2_PIN2 // NU - | GPIO_EXTIPINSELL_EXTIPINSEL3_PIN3 // NU - | GPIO_EXTIPINSELL_EXTIPINSEL4_PIN6 // NU - | GPIO_EXTIPINSELL_EXTIPINSEL5_PIN7 // NU - | GPIO_EXTIPINSELL_EXTIPINSEL6_PIN4 // NU - | GPIO_EXTIPINSELL_EXTIPINSEL7_PIN7; // NU - GPIO->EXTIPINSELH = GPIO_EXTIPINSELH_EXTIPINSEL8_PIN8 // NU - | GPIO_EXTIPINSELH_EXTIPINSEL9_PIN9 // NU - | GPIO_EXTIPINSELH_EXTIPINSEL10_PIN11 // NU - | GPIO_EXTIPINSELH_EXTIPINSEL11_PIN8 // NU - | GPIO_EXTIPINSELH_EXTIPINSEL12_PIN13 // NU - | GPIO_EXTIPINSELH_EXTIPINSEL13_PIN15 // NU - | GPIO_EXTIPINSELH_EXTIPINSEL14_PIN12 // NU - | GPIO_EXTIPINSELH_EXTIPINSEL15_PIN12; // NU - -} - -/*--------------------------------------------------------------------*/ -/* Board Init */ -/*--------------------------------------------------------------------*/ - -void board_init(void) -{ - - emu_dcdc_init(1800.f, 50.f, 100.f, 0.f); // Init DC-DC converter (1.8 V, 50 mA active, 100 uA sleep, 0 mA reverse limit) - emu_init(0); - emu_reg_init(3300.f); // set output regulator to 3.3V - - cmu_hfxo_startup_calib(0x200, 0x145); // Config HFXO Startup for 1280 uA, 36 pF (18 pF + 2 pF CLOAD) - cmu_hfxo_steady_calib(0x009, 0x145); // Config HFXO Steady for 12 uA, 36 pF (18 pF + 2 pF CLOAD) - - cmu_init(); // Init Clock Management Unit - - cmu_ushfrco_calib(1, DEVINFO->USHFRCOCAL13); // Enable and calibrate USHFRCO for 48 MHz - cmu_auxhfrco_calib(1, DEVINFO->AUXHFRCOCAL11); // Enable and calibrate AUXHFRCO for 32 MHz - - CMU->USBCRCTRL = CMU_USBCRCTRL_USBCREN; // enable USB clock recovery - CMU->USBCTRL = CMU_USBCTRL_USBCLKSEL_USHFRCO | CMU_USBCTRL_USBCLKEN; // select USHFRCO as USB Phy clock source and enable it - - CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_USB; // enable USB peripheral clock - - systick_init(); // Init system tick - - gpio_init(); // Init IOs - -} - -/*--------------------------------------------------------------------*/ -/* Board porting API */ -/*--------------------------------------------------------------------*/ - -void board_led_write(bool state) -{ - // Combine red and blue for pink Because it looks good :) - GPIO->P[LED_PORT].DOUT = (GPIO->P[LED_PORT].DOUT & ~((1 << LED_PIN_R) | (1 << LED_PIN_B))) | (state << LED_PIN_R) | (state << LED_PIN_B); -} - -uint32_t board_button_read(void) -{ - return !!(GPIO->P[BUTTON_PORT].DIN & (1 << BUTTON_PIN)); -} - -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -int board_uart_write(void const * buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; -void SysTick_Handler(void) -{ - system_ticks++; -} - -uint32_t board_millis(void) -{ - return system_ticks; -} -#endif - -#ifdef USE_FULL_ASSERT -/** - * @brief Reports the name of the source file and the source line number - * where the assert_param error has occurred. - * @param file: pointer to the source file name - * @param line: assert_param error line source number - * @retval None - */ -void assert_failed(char *file, uint32_t line) -{ - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line number, - tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ - /* USER CODE END 6 */ -} -#endif /* USE_FULL_ASSERT */ -- cgit v1.3.1