diff options
author | rtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2> | 2016-03-02 16:03:25 +0000 |
---|---|---|
committer | rtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2> | 2016-03-02 16:03:25 +0000 |
commit | f21c49aea28a5ac5c93ef59b518137ee4e72679e (patch) | |
tree | 60d22767fd27fc64abbdad764493592f0f0ff53f /FreeRTOS/Demo | |
parent | ad6b48f5235da9f179b3584011e5e5d6dd6f9c93 (diff) | |
download | freertos-f21c49aea28a5ac5c93ef59b518137ee4e72679e.tar.gz |
Add Pearl Gecko demo.
Fix build error when configSUPPORT_STATIC_ALLOCATION and configNUM_THREAD_LOCAL_STORAGE_POINTERS were greater than zero at the same time.
Allow the pdMS_TO_TICKS macro to be overridden by a definition in FreeRTOSConfig.h.
git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@2422 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
Diffstat (limited to 'FreeRTOS/Demo')
22 files changed, 9974 insertions, 10 deletions
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/Low_Power_Demo/low_power_tick_management_BURTC.c b/FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/Low_Power_Demo/low_power_tick_management_BURTC.c index c097bebc8..218dd7a4c 100644 --- a/FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/Low_Power_Demo/low_power_tick_management_BURTC.c +++ b/FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/Low_Power_Demo/low_power_tick_management_BURTC.c @@ -81,7 +81,6 @@ #include "em_burtc.h"
#include "em_rmu.h"
#include "em_int.h"
-#include "em_rtc.h"
#include "sleep.h"
/* SEE THE COMMENTS ABOVE THE DEFINITION OF configCREATE_LOW_POWER_DEMO IN
@@ -323,18 +322,18 @@ void BURTC_IRQHandler( void ) {
ulTickFlag = pdTRUE;
- if( RTC_CompareGet( 0 ) != ulReloadValueForOneTick )
+ if( BURTC_CompareGet( 0 ) != ulReloadValueForOneTick )
{
- /* Set RTC interrupt to one RTOS tick period. */
+ /* Set BURTC interrupt to one RTOS tick period. */
BURTC_Enable( false );
BURTC_CompareSet( 0, ulReloadValueForOneTick );
BURTC_Enable( true );
}
- BURTC_IntClear( _RTC_IFC_MASK );
+ BURTC_IntClear( _BURTC_IFC_MASK );
- /* Critical section which protect incrementing the tick*/
- ( void ) portSET_INTERRUPT_MASK_FROM_ISR();
+ /* Critical section which protect incrementing the tick. */
+ portDISABLE_INTERRUPTS();
{
if( xTaskIncrementTick() != pdFALSE )
{
@@ -342,7 +341,7 @@ void BURTC_IRQHandler( void ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
- portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
+ portENABLE_INTERRUPTS();
}
#endif /* ( configCREATE_LOW_POWER_DEMO == 1 ) */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/Low_Power_Demo/low_power_tick_management_RTC.c b/FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/Low_Power_Demo/low_power_tick_management_RTC.c index 4644e061d..47fb7a9d1 100644 --- a/FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/Low_Power_Demo/low_power_tick_management_RTC.c +++ b/FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/Low_Power_Demo/low_power_tick_management_RTC.c @@ -356,8 +356,8 @@ void RTC_IRQHandler( void ) RTC_IntClear( _RTC_IFC_MASK );
- /* Critical section which protect incrementing the tick*/
- ( void ) portSET_INTERRUPT_MASK_FROM_ISR();
+ /* Critical section which protect incrementing the tick. */
+ portDISABLE_INTERRUPTS();
{
if( xTaskIncrementTick() != pdFALSE )
{
@@ -365,7 +365,7 @@ void RTC_IRQHandler( void ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
- portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );
+ portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/.cproject b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/.cproject new file mode 100644 index 000000000..072724a5d --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/.cproject @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?>
+
+<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="com.silabs.ide.si32.gcc.debug#com.silabs.ide.si32.gcc:4.8.3.20131129">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.silabs.ide.si32.gcc.debug#com.silabs.ide.si32.gcc:4.8.3.20131129" moduleId="org.eclipse.cdt.core.settings" name="GNU ARM v4.8.3 - Debug">
+ <macros>
+ <stringMacro name="StudioToolchainPath" type="VALUE_PATH_DIR" value="${StudioToolchainPathFromID:com.silabs.ide.si32.gcc:4.8.3.20131129}"/>
+ <stringMacro name="StudioSdkPath" type="VALUE_PATH_DIR" value="${StudioSdkPathFromID:com.silabs.sdk.si32.efm32.sls:2.0.10}"/>
+ </macros>
+ <externalSettings/>
+ <extensions>
+ <extension id="com.silabs.ide.debug.core.S37" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="com.silabs.ide.debug.core.BIN" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="com.silabs.ide.debug.core.HEX" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule buildConfig.stockConfigId="com.silabs.ide.si32.gcc.debug#com.silabs.ide.si32.gcc:4.8.3.20131129" cppBuildConfig.builtinIncludes="studio:/sdk/kits/SLSTK3401A_EFM32PG/config/ studio:/sdk/CMSIS/Include/ studio:/sdk/emlib/inc/ studio:/sdk/kits/common/bsp/ studio:/sdk/kits/common/drivers/ studio:/sdk/Device/SiliconLabs/EFM32PG1B/Include/ studio:/sdk/kits/SLSTK3401A_EFM32PG/config/ studio:/sdk/CMSIS/Include/ studio:/sdk/emlib/inc/ studio:/sdk/kits/common/bsp/ studio:/sdk/kits/common/drivers/ studio:/sdk/Device/SiliconLabs/EFM32PG1B/Include/" cppBuildConfig.builtinLibraryFiles="" cppBuildConfig.builtinLibraryNames="" cppBuildConfig.builtinLibraryObjects="" cppBuildConfig.builtinLibraryPaths="" cppBuildConfig.builtinMacros="EFM32PG1B200F256GM48 EFM32PG1B200F256GM48 DEBUG" moduleId="com.silabs.ide.project.core" projectCommon.referencedModules="[{"module":"<project:MModule xmlns:project=\"http://www.silabs.com/sls/Project.ecore\" builtin=\"true\" id=\"com.silabs.ide.si32.sdk.efm32.v2.common.emlib\">\r\n <inclusions pattern=\"emlib/em_assert.c\"/>\r\n <inclusions pattern=\"emlib/em_system.c\"/>\r\n <inclusions pattern=\"emlib/em_cmu.c\"/>\r\n <inclusions pattern=\"emlib/em_emu.c\"/>\r\n <inclusions pattern=\"emlib/em_gpio.c\"/>\r\n</project:MModule>","builtinExcludes":[],"builtin":true,"builtinSources":["emlib/em_assert.c","emlib/em_cmu.c","emlib/em_emu.c","emlib/em_gpio.c","emlib/em_system.c"]},{"module":"<project:MModule xmlns:project=\"http://www.silabs.com/sls/Project.ecore\" builtin=\"true\" id=\"com.silabs.ide.si32.sdk.efm32.v2.part\">\r\n <inclusions pattern=\"CMSIS/.*/startup_.*_.*.s\"/>\r\n <inclusions pattern=\"CMSIS/.*/system_.*.c\"/>\r\n</project:MModule>","builtinExcludes":[],"builtin":true,"builtinSources":["CMSIS/efm32pg1b/startup_gcc_efm32pg1b.s","CMSIS/efm32pg1b/system_efm32pg1b.c"]},{"module":"<project:MModule xmlns:project=\"http://www.silabs.com/sls/Project.ecore\" builtin=\"true\" id=\"com.silabs.ide.si32.sdk.efm32.v2.common.CMSIS\">\r\n <exclusions pattern=\".*\"/>\r\n</project:MModule>","builtinExcludes":[],"builtin":true,"builtinSources":[]},{"module":"<project:MModule xmlns:project=\"http://www.silabs.com/sls/Project.ecore\" builtin=\"true\" id=\"com.silabs.ide.si32.sdk.efm32.v2.kit\">\r\n <exclusions pattern=\".*\"/>\r\n</project:MModule>","builtinExcludes":[],"builtin":true,"builtinSources":[]},{"module":"<project:MModule xmlns:project=\"http://www.silabs.com/sls/Project.ecore\" builtin=\"true\" id=\"com.silabs.ide.si32.sdk.efm32.v2.common.drivers\">\r\n <exclusions pattern=\".*\"/>\r\n</project:MModule>","builtinExcludes":[],"builtin":true,"builtinSources":[]},{"module":"<project:MModule xmlns:project=\"http://www.silabs.com/sls/Project.ecore\" builtin=\"true\" id=\"com.silabs.ide.si32.sdk.efm32.v2.common.bsp\">\r\n <inclusions pattern=\"BSP/bsp_stk_leds.c\"/>\r\n</project:MModule>","builtinExcludes":[],"builtin":true,"builtinSources":["BSP/bsp_stk_leds.c"]}]" projectCommon.toolchainId="com.silabs.ide.si32.gcc:4.8.3.20131129"/>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" description="" id="com.silabs.ide.si32.gcc.debug#com.silabs.ide.si32.gcc:4.8.3.20131129" name="GNU ARM v4.8.3 - Debug" parent="com.silabs.ide.si32.gcc.cdt.managedbuild.config.gnu.exe">
+ <folderInfo id="com.silabs.ide.si32.gcc.debug#com.silabs.ide.si32.gcc:4.8.3.20131129." name="/" resourcePath="">
+ <toolChain id="com.silabs.ide.si32.gcc.cdt.managedbuild.toolchain.exe.1210947266" name="Si32 GNU ARM" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.toolchain.exe">
+ <option id="com.silabs.ide.si32.gcc.cdt.managedbuild.toolchain.debug.level.1491015159" name="Debug Level" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.toolchain.debug.level" value="com.silabs.ide.si32.gcc.cdt.managedbuild.toolchain.debug.level.default" valueType="enumerated"/>
+ <targetPlatform binaryParser="org.eclipse.cdt.core.ELF;org.eclipse.cdt.core.GNU_ELF;com.silabs.ide.debug.core.BIN;com.silabs.ide.debug.core.HEX;com.silabs.ide.debug.core.S37" id="com.silabs.ide.si32.gcc.cdt.managedbuild.target.gnu.platform.base.1072192348" isAbstract="false" name="Debug Platform" osList="win32,linux,macosx" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.target.gnu.platform.base"/>
+ <builder buildPath="${workspace_loc:/RTOSDemo}/GNU ARM v4.8.3 - Debug" id="com.silabs.ide.si32.gcc.cdt.managedbuild.target.gnu.builder.base.1216179401" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Si32 GNU ARM Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.target.gnu.builder.base"/>
+ <tool id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.base.1347880376" name="GNU ARM C Compiler" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.base">
+ <option id="gnu.c.compiler.option.optimization.level.1992790616" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" value="gnu.c.optimization.level.none" valueType="enumerated"/>
+ <option id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.def.symbols.515358055" name="Defined symbols (-D)" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.def.symbols" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="DEBUG_EFM=1"/>
+ <listOptionValue builtIn="false" value="SLEEP_LOWEST_ENERGY_MODE_DEFAULT=sleepEM2"/>
+ <listOptionValue builtIn="false" value="EFM32PG1B200F256GM48=1"/>
+ <listOptionValue builtIn="false" value="DEBUG=1"/>
+ </option>
+ <option id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.debug.builtin.1313176957" name="Always branch to builtin functions (-fno-builtin)" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.debug.builtin" value="true" valueType="boolean"/>
+ <option id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.debug.prolog.1172189815" name="Generate debugger-friendly prologs (-mno-sched-prolog)" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.debug.prolog" value="true" valueType="boolean"/>
+ <option id="gnu.c.compiler.option.include.paths.1242792235" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/SLSTK3401A_EFM32PG/config""/>
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/CMSIS/Include""/>
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/emlib/inc""/>
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/common/bsp""/>
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/common/drivers""/>
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/Device/SiliconLabs/EFM32PG1B/Include""/>
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}}""/>
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/FreeRTOS_Source/include}""/>
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/GCC/ARM_CM3}""/>
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/Full_Demo/Standard_Demo_Tasks/include}""/>
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/SilLabs_Source/emdrv/sleep/inc}""/>
+ </option>
+ <option id="gnu.c.compiler.option.warnings.extrawarn.257881085" name="Extra warnings (-Wextra)" superClass="gnu.c.compiler.option.warnings.extrawarn" value="true" valueType="boolean"/>
+ <inputType id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.input.1657907187" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+ <tool id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.cpp.compiler.base.404002511" name="GNU ARM C++ Compiler" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.cpp.compiler.base">
+ <option id="gnu.cpp.compiler.option.optimization.level.1331292595" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
+ <option id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.cpp.compiler.debug.builtin.1708445238" name="Always branch to builtin functions (-fno-builtin)" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.cpp.compiler.debug.builtin" value="true" valueType="boolean"/>
+ <option id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.cpp.compiler.debug.prolog.437089423" name="Generate debugger-friendly prologs (-mno-sched-prolog)" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.cpp.compiler.debug.prolog" value="true" valueType="boolean"/>
+ </tool>
+ <tool id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.assembler.base.146600794" name="GNU ARM Assembler" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.assembler.base">
+ <option id="gnu.both.asm.option.include.paths.1966239528" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/SLSTK3401A_EFM32PG/examples/blink""/>
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/SLSTK3401A_EFM32PG/config""/>
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/CMSIS/Include""/>
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/emlib/inc""/>
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/common/bsp""/>
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/common/drivers""/>
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/Device/SiliconLabs/EFM32PG1B/Include""/>
+ </option>
+ <option id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.as.def.symbols.2072246944" name="Defined symbols (-D)" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.as.def.symbols" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="EFM32PG1B200F256GM48=1"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.80652597" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+ </tool>
+ <tool id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.linker.base.467472350" name="GNU ARM C Linker" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.linker.base">
+ <option id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.linker.nostdlibs.1491099628" name="No startup or default libs (-nostdlib)" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.linker.nostdlibs" value="false" valueType="boolean"/>
+ <option id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.linker.category.ordering.selection.1386626351" name="Linker input ordering" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.linker.category.ordering.selection" value="./emlib/em_assert.o;./emlib/em_cmu.o;./emlib/em_emu.o;./emlib/em_gpio.o;./emlib/em_rtc.o;./emlib/em_system.o;./emdrv/sleep/src/sleep.o;./Low_Power_Demo/low_power_tick_management_RTC.o;./Low_Power_Demo/main_low_power.o;./Full_Demo/Standard_Demo_Tasks/EventGroupsDemo.o;./Full_Demo/Standard_Demo_Tasks/GenQTest.o;./Full_Demo/Standard_Demo_Tasks/StaticAllocation.o;./Full_Demo/Standard_Demo_Tasks/TaskNotify.o;./Full_Demo/Standard_Demo_Tasks/TimerDemo.o;./Full_Demo/Standard_Demo_Tasks/blocktim.o;./Full_Demo/Standard_Demo_Tasks/dynamic.o;./Full_Demo/Standard_Demo_Tasks/flop.o;./Full_Demo/Standard_Demo_Tasks/recmutex.o;./Full_Demo/Standard_Demo_Tasks/semtest.o;./Full_Demo/RegTest.o;./Full_Demo/main_full.o;./FreeRTOS_Source/portable/MemMang/heap_4.o;./FreeRTOS_Source/portable/GCC/ARM_CM3/port.o;./FreeRTOS_Source/event_groups.o;./FreeRTOS_Source/list.o;./FreeRTOS_Source/queue.o;./FreeRTOS_Source/tasks.o;./FreeRTOS_Source/timers.o;./CMSIS/efm32pg1b/startup_gcc_efm32pg1b.o;./CMSIS/efm32pg1b/system_efm32pg1b.o;./BSP/bsp_stk_leds.o;./main.o" valueType="string"/>
+ <inputType id="cdt.managedbuild.tool.gnu.c.linker.input.673598100" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+ </inputType>
+ </tool>
+ <tool id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.cpp.linker.base.737185930" name="GNU ARM C++ Linker" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.cpp.linker.base"/>
+ <tool id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.archiver.base.1305574197" name="GNU ARM Archiver" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.archiver.base"/>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="com.silabs.ide.project.core" projectCommon.buildArtifactType="EXE" projectCommon.kitId="com.silabs.kit.si32.efm32.efm32pg.slstk3401a" projectCommon.partId="com.silabs.mcu.si32.efm32.efm32pg1b.efm32pg1b200f256gm48" projectCommon.sdkId="com.silabs.sdk.si32.efm32.sls:2.0.10"/>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="RTOSDemo.com.silabs.ide.project.core.cdt.cdtMbsProjectType.476959829" name="SLS CDT Project" projectType="com.silabs.ide.project.core.cdt.cdtMbsProjectType"/>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ <scannerConfigBuildInfo instanceId="com.silabs.ide.si32.gcc.debug#com.silabs.ide.si32.gcc:4.8.3.20131129;com.silabs.ide.si32.gcc.debug#com.silabs.ide.si32.gcc:4.8.3.20131129.;com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.base.1347880376;com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.input.1657907187">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ </scannerConfigBuildInfo>
+ </storageModule>
+ <storageModule moduleId="refreshScope"/>
+</cproject>
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/.project b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/.project new file mode 100644 index 000000000..c257d44c8 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/.project @@ -0,0 +1,241 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>RTOSDemo</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <triggers>clean,full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+ <triggers>full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>com.silabs.ide.project.core.SLSProjectNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ </natures>
+ <linkedResources>
+ <link>
+ <name>FreeRTOS_Source</name>
+ <type>2</type>
+ <locationURI>FREERTOS_ROOT/FreeRTOS/Source</locationURI>
+ </link>
+ <link>
+ <name>Full_Demo/Standard_Demo_Tasks</name>
+ <type>2</type>
+ <locationURI>FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal</locationURI>
+ </link>
+ <link>
+ <name>Full_Demo/Standard_Demo_Tasks/include</name>
+ <type>2</type>
+ <locationURI>FREERTOS_ROOT/FreeRTOS/Demo/Common/include</locationURI>
+ </link>
+ </linkedResources>
+ <filteredResources>
+ <filter>
+ <id>1455990187566</id>
+ <name>FreeRTOS_Source</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-event_groups.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1455990187573</id>
+ <name>FreeRTOS_Source</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-queue.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1455990187577</id>
+ <name>FreeRTOS_Source</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-tasks.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1455990187582</id>
+ <name>FreeRTOS_Source</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-timers.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1455990187588</id>
+ <name>FreeRTOS_Source</name>
+ <type>9</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-include</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1455990187592</id>
+ <name>FreeRTOS_Source</name>
+ <type>9</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-portable</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1455990187597</id>
+ <name>FreeRTOS_Source</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-list.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>FreeRTOS_Source/portable</name>
+ <type>9</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-MemMang</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>FreeRTOS_Source/portable</name>
+ <type>9</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-GCC</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>Full_Demo/Standard_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-flop.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>Full_Demo/Standard_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-dynamic.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>Full_Demo/Standard_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-blocktim.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>Full_Demo/Standard_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-GenQTest.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>Full_Demo/Standard_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-TimerDemo.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>Full_Demo/Standard_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-EventGroupsDemo.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>Full_Demo/Standard_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-TaskNotify.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>Full_Demo/Standard_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-recmutex.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>Full_Demo/Standard_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-semtest.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>0</id>
+ <name>Full_Demo/Standard_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-StaticAllocation.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1455989277852</id>
+ <name>FreeRTOS_Source/portable/GCC</name>
+ <type>9</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-ARM_CM3</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1455989313240</id>
+ <name>FreeRTOS_Source/portable/MemMang</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-heap_4.c</arguments>
+ </matcher>
+ </filter>
+ </filteredResources>
+ <variableList>
+ <variable>
+ <name>FREERTOS_ROOT</name>
+ <value>$%7BPARENT-3-PROJECT_LOC%7D</value>
+ </variable>
+ </variableList>
+</projectDescription>
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/FreeRTOSConfig.h b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/FreeRTOSConfig.h new file mode 100644 index 000000000..def429af8 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/FreeRTOSConfig.h @@ -0,0 +1,237 @@ +/*
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "em_chip.h"
+#include "em_cmu.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.
+ *----------------------------------------------------------*/
+
+
+/* Set configCREATE_LOW_POWER_DEMO as follows:
+ *
+ * 0: Build the full test and demo application.
+ * 1: Build the simple blinky tickless low power demo, generating the tick
+ * interrupt from the RTCC. EM2 will be entered. The LXFO clock is used.
+ * See the comments at the top of main.c, main_full.c and main_low_power.c for
+ * more information.
+ */
+#define configCREATE_LOW_POWER_DEMO 1
+
+/* Some configuration is dependent on the demo being built. */
+#if( configCREATE_LOW_POWER_DEMO == 0 )
+
+ /* Tickless mode is not used. */
+
+ /* Some of the standard demo test tasks assume a tick rate of 1KHz, even
+ though that is faster than would normally be warranted by a real
+ application. */
+ #define configTICK_RATE_HZ ( 1000 )
+
+ /* The full demo always has tasks to run so the tick will never be turned
+ off. The blinky demo will use the default tickless idle implementation to
+ turn the tick off. */
+ #define configUSE_TICKLESS_IDLE 0
+
+ /* Hook function related definitions. */
+ #define configUSE_TICK_HOOK ( 1 )
+ #define configCHECK_FOR_STACK_OVERFLOW ( 1 )
+ #define configUSE_MALLOC_FAILED_HOOK ( 1 )
+ #define configUSE_IDLE_HOOK ( 1 )
+
+ #define configENERGY_MODE ( sleepEM3 )
+
+#else
+
+ /* Tickless idle mode, generating RTOS tick interrupts from the RTC, fed
+ by the LXFO clock. */
+
+ /* The slow clock used to generate the tick interrupt in the low power demo
+ runs at 32768/8=4096Hz. Ensure the tick rate is a multiple of the clock. */
+ #define configTICK_RATE_HZ ( 128 )
+
+ /* The low power demo uses the tickless idle feature. */
+ #define configUSE_TICKLESS_IDLE 1
+
+ /* Hook function related definitions. */
+ #define configUSE_TICK_HOOK ( 0 )
+ #define configCHECK_FOR_STACK_OVERFLOW ( 0 )
+ #define configUSE_MALLOC_FAILED_HOOK ( 0 )
+ #define configUSE_IDLE_HOOK ( 0 )
+
+#endif
+
+/* Main functions*/
+#define configUSE_PREEMPTION ( 1 )
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION ( 1 )
+#define configSUPPORT_STATIC_ALLOCATION ( 1 )
+#define configCPU_CLOCK_HZ ( CMU_ClockFreqGet( cmuClock_CORE ) )
+#define configMAX_PRIORITIES ( 6 )
+#define configMINIMAL_STACK_SIZE (( unsigned short ) 130)
+#define configTOTAL_HEAP_SIZE (( size_t )(25000))
+#define configMAX_TASK_NAME_LEN ( 10 )
+#define configUSE_TRACE_FACILITY ( 0 )
+#define configUSE_16_BIT_TICKS ( 0 )
+#define configIDLE_SHOULD_YIELD ( 0 )
+#define configUSE_MUTEXES ( 1 )
+#define configUSE_RECURSIVE_MUTEXES ( 1 )
+#define configUSE_COUNTING_SEMAPHORES ( 1 )
+#define configUSE_ALTERNATIVE_API ( 0 )/* Deprecated! */
+#define configQUEUE_REGISTRY_SIZE ( 10 )
+#define configUSE_QUEUE_SETS ( 0 )
+
+/* Run time stats gathering related definitions. */
+#define configGENERATE_RUN_TIME_STATS ( 0 )
+
+/* Co-routine related definitions. */
+#define configUSE_CO_ROUTINES ( 0 )
+#define configMAX_CO_ROUTINE_PRIORITIES ( 1 )
+
+/* Software timer related definitions. */
+#define configUSE_TIMERS ( 1 )
+#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) /* Highest priority */
+#define configTIMER_QUEUE_LENGTH ( 10 )
+#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )
+
+/* Cortex-M specific definitions. */
+#ifdef __NVIC_PRIO_BITS
+ /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
+ #define configPRIO_BITS __NVIC_PRIO_BITS
+#else
+ #define configPRIO_BITS 3 /* 7 priority levels */
+#endif
+
+/* The lowest interrupt priority that can be used in a call to a "set priority"
+function. */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x07
+
+/* The highest interrupt priority that can be used by any interrupt service
+routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
+INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
+PRIORITY THAN THIS! (higher priorities are lower numeric values. */
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x05
+
+/* Interrupt priorities used by the kernel port layer itself. These are generic
+to all Cortex-M ports, and do not rely on any particular library functions. */
+#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
+See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
+
+
+/* Optional functions - most linkers will remove unused functions anyway. */
+#define INCLUDE_vTaskPrioritySet ( 1 )
+#define INCLUDE_uxTaskPriorityGet ( 1 )
+#define INCLUDE_vTaskDelete ( 1 )
+#define INCLUDE_vTaskSuspend ( 1 )
+#define INCLUDE_xResumeFromISR ( 1 )
+#define INCLUDE_vTaskDelayUntil ( 1 )
+#define INCLUDE_vTaskDelay ( 1 )
+#define INCLUDE_xTaskGetSchedulerState ( 1 )
+#define INCLUDE_xTaskGetCurrentTaskHandle ( 1 )
+#define INCLUDE_uxTaskGetStackHighWaterMark ( 0 )
+#define INCLUDE_xTaskGetIdleTaskHandle ( 0 )
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle ( 0 )
+#define INCLUDE_pcTaskGetTaskName ( 0 )
+#define INCLUDE_eTaskGetState ( 1 )
+#define INCLUDE_xTimerPendFunctionCall ( 1 )
+
+/* Stop if an assertion fails. */
+#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
+
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
+standard names. */
+#define vPortSVCHandler SVC_Handler
+#define xPortPendSVHandler PendSV_Handler
+#define xPortSysTickHandler SysTick_Handler
+
+/* For the linker. */
+#define fabs __builtin_fabs
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* FREERTOS_CONFIG_H */
+
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Full_Demo/RegTest.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Full_Demo/RegTest.c new file mode 100644 index 000000000..08e231926 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Full_Demo/RegTest.c @@ -0,0 +1,228 @@ +/*
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/*
+ * "Reg test" tasks - These fill the registers with known values, then check
+ * that each register maintains its expected value for the lifetime of the
+ * task. Each task uses a different set of values. The reg test tasks execute
+ * with a very low priority, so get preempted very frequently. A register
+ * containing an unexpected value is indicative of an error in the context
+ * switching mechanism.
+ */
+
+void vRegTest1Implementation( void ) __attribute__ ((naked));
+void vRegTest2Implementation( void ) __attribute__ ((naked));
+
+void vRegTest1Implementation( void )
+{
+ __asm volatile
+ (
+ ".extern ulRegTest1LoopCounter \n"
+ "/* Fill the core registers with known values. */ \n"
+ "mov r0, #100 \n"
+ "mov r1, #101 \n"
+ "mov r2, #102 \n"
+ "mov r3, #103 \n"
+ "mov r4, #104 \n"
+ "mov r5, #105 \n"
+ "mov r6, #106 \n"
+ "mov r7, #107 \n"
+ "mov r8, #108 \n"
+ "mov r9, #109 \n"
+ "mov r10, #110 \n"
+ "mov r11, #111 \n"
+ "mov r12, #112 \n"
+
+ "reg1_loop: \n"
+
+ "/* Check each register has maintained its expected value. */ \n"
+ "cmp r0, #100 \n"
+ "bne reg1_error_loop \n"
+ "cmp r1, #101 \n"
+ "bne reg1_error_loop \n"
+ "cmp r2, #102 \n"
+ "bne reg1_error_loop \n"
+ "cmp r3, #103 \n"
+ "bne reg1_error_loop \n"
+ "cmp r4, #104 \n"
+ "bne reg1_error_loop \n"
+ "cmp r5, #105 \n"
+ "bne reg1_error_loop \n"
+ "cmp r6, #106 \n"
+ "bne reg1_error_loop \n"
+ "cmp r7, #107 \n"
+ "bne reg1_error_loop \n"
+ "cmp r8, #108 \n"
+ "bne reg1_error_loop \n"
+ "cmp r9, #109 \n"
+ "bne reg1_error_loop \n"
+ "cmp r10, #110 \n"
+ "bne reg1_error_loop \n"
+ "cmp r11, #111 \n"
+ "bne reg1_error_loop \n"
+ "cmp r12, #112 \n"
+ "bne reg1_error_loop \n"
+
+ "/* Everything passed, increment the loop counter. */ \n"
+ "push { r0-r1 } \n"
+ "ldr r0, =ulRegTest1LoopCounter \n"
+ "ldr r1, [r0] \n"
+ "adds r1, r1, #1 \n"
+ "str r1, [r0] \n"
+ "pop { r0-r1 } \n"
+
+ "/* Start again. */ \n"
+ "b reg1_loop \n"
+
+ "reg1_error_loop: \n"
+ "/* If this line is hit then there was an error in a core register value. \n"
+ "The loop ensures the loop counter stops incrementing. */ \n"
+ "b reg1_error_loop \n"
+ "nop "
+ ); /* __asm volatile. */
+}
+/*-----------------------------------------------------------*/
+
+void vRegTest2Implementation( void )
+{
+ __asm volatile
+ (
+ ".extern ulRegTest2LoopCounter \n"
+ "/* Set all the core registers to known values. */ \n"
+ "mov r0, #-1 \n"
+ "mov r1, #1 \n"
+ "mov r2, #2 \n"
+ "mov r3, #3 \n"
+ "mov r4, #4 \n"
+ "mov r5, #5 \n"
+ "mov r6, #6 \n"
+ "mov r7, #7 \n"
+ "mov r8, #8 \n"
+ "mov r9, #9 \n"
+ "mov r10, #10 \n"
+ "mov r11, #11 \n"
+ "mov r12, #12 \n"
+
+ "reg2_loop: \n"
+
+ "cmp r0, #-1 \n"
+ "bne reg2_error_loop \n"
+ "cmp r1, #1 \n"
+ "bne reg2_error_loop \n"
+ "cmp r2, #2 \n"
+ "bne reg2_error_loop \n"
+ "cmp r3, #3 \n"
+ "bne reg2_error_loop \n"
+ "cmp r4, #4 \n"
+ "bne reg2_error_loop \n"
+ "cmp r5, #5 \n"
+ "bne reg2_error_loop \n"
+ "cmp r6, #6 \n"
+ "bne reg2_error_loop \n"
+ "cmp r7, #7 \n"
+ "bne reg2_error_loop \n"
+ "cmp r8, #8 \n"
+ "bne reg2_error_loop \n"
+ "cmp r9, #9 \n"
+ "bne reg2_error_loop \n"
+ "cmp r10, #10 \n"
+ "bne reg2_error_loop \n"
+ "cmp r11, #11 \n"
+ "bne reg2_error_loop \n"
+ "cmp r12, #12 \n"
+ "bne reg2_error_loop \n"
+
+ "/* Increment the loop counter to indicate this test is still functioning \n"
+ "correctly. */ \n"
+ "push { r0-r1 } \n"
+ "ldr r0, =ulRegTest2LoopCounter \n"
+ "ldr r1, [r0] \n"
+ "adds r1, r1, #1 \n"
+ "str r1, [r0] \n"
+
+ "/* Yield to increase test coverage. */ \n"
+ "movs r0, #0x01 \n"
+ "ldr r1, =0xe000ed04 /*NVIC_INT_CTRL */ \n"
+ "lsl r0, r0, #28 /* Shift to PendSV bit */ \n"
+ "str r0, [r1] \n"
+ "dsb \n"
+
+ "pop { r0-r1 } \n"
+
+ "/* Start again. */ \n"
+ "b reg2_loop \n"
+
+ "reg2_error_loop: \n"
+ "/* If this line is hit then there was an error in a core register value. \n"
+ "This loop ensures the loop counter variable stops incrementing. */ \n"
+ "b reg2_error_loop \n"
+ ); /* __asm volatile */
+}
+/*-----------------------------------------------------------*/
+
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Full_Demo/main_full.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Full_Demo/main_full.c new file mode 100644 index 000000000..67ccd0a16 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Full_Demo/main_full.c @@ -0,0 +1,414 @@ +/*
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/******************************************************************************
+ * NOTE 1: This project provides two demo applications. A simple blinky style
+ * project that demonstrates the tickless low power features of FreeRTOS, and a
+ * more comprehensive test and demo application. The configCREATE_LOW_POWER_DEMO
+ * setting in FreeRTOSConifg.h is used to select between the two, and to select
+ * the clock used when tickless mode is used. See the notes on using
+ * conifgCREATE_LOW_POWER_DEMO in main.c. This file implements the
+ * comprehensive test and demo version.
+ *
+ * NOTE 2: This file only contains the source code that is specific to the
+ * full demo. Generic functions, such FreeRTOS hook functions, and functions
+ * required to configure the hardware, are defined in main.c.
+ *
+ ******************************************************************************
+ *
+ * main_full() creates all the demo application tasks and software timers, then
+ * starts the scheduler. The web documentation provides more details of the
+ * standard demo application tasks, which provide no particular functionality,
+ * but do provide a good example of how to use the FreeRTOS API.
+ *
+ * In addition to the standard demo tasks, the following tasks and tests are
+ * defined and/or created within this file:
+ *
+ * "Reg test" tasks - These fill both the core and floating point registers with
+ * known values, then check that each register maintains its expected value for
+ * the lifetime of the task. Each task uses a different set of values. The reg
+ * test tasks execute with a very low priority, so get preempted very
+ * frequently. A register containing an unexpected value is indicative of an
+ * error in the context switching mechanism.
+ *
+ * "Check" task - The check task period is initially set to three seconds. The
+ * task checks that all the standard demo tasks, and the register check tasks,
+ * are not only still executing, but are executing without reporting any errors.
+ * If the check task discovers that a task has either stalled, or reported an
+ * error, then it changes its own execution period from the initial three
+ * seconds, to just 200ms. The check task also toggles an LED each time it is
+ * called. This provides a visual indication of the system status: If the LED
+ * toggles every three seconds, then no issues have been discovered. If the LED
+ * toggles every 200ms, then an issue has been discovered with at least one
+ * task.
+ */
+
+/* Standard includes. */
+#include <stdio.h>
+
+/* Kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "timers.h"
+#include "semphr.h"
+
+/* SiLabs includes. */
+#include "bsp.h"
+
+/* Standard demo application includes. */
+#include "flop.h"
+#include "semtest.h"
+#include "dynamic.h"
+#include "blocktim.h"
+#include "GenQTest.h"
+#include "recmutex.h"
+#include "TimerDemo.h"
+#include "EventGroupsDemo.h"
+#include "TaskNotify.h"
+#include "StaticAllocation.h"
+
+/* Priorities for the demo application tasks. */
+#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1UL )
+#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3UL )
+#define mainFLOP_TASK_PRIORITY ( tskIDLE_PRIORITY )
+#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
+
+/* A block time of zero simply means "don't block". */
+#define mainDONT_BLOCK ( 0UL )
+
+/* The period after which the check timer will expire, in ms, provided no errors
+have been reported by any of the standard demo tasks. ms are converted to the
+equivalent in ticks using the portTICK_PERIOD_MS constant. */
+#define mainNO_ERROR_CHECK_TASK_PERIOD ( 3000UL / portTICK_PERIOD_MS )
+
+/* The period at which the check timer will expire, in ms, if an error has been
+reported in one of the standard demo tasks. ms are converted to the equivalent
+in ticks using the portTICK_PERIOD_MS constant. */
+#define mainERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 200UL )
+
+/* Parameters that are passed into the register check tasks solely for the
+purpose of ensuring parameters are passed into tasks correctly. */
+#define mainREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x12345678 )
+#define mainREG_TEST_TASK_2_PARAMETER ( ( void * ) 0x87654321 )
+
+/* The base period used by the timer test tasks. */
+#define mainTIMER_TEST_PERIOD ( 50 )
+
+/* The LED toggled by the check task. */
+#define mainTASK_LED ( 0 )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Called by main() to run the full demo (as opposed to the blinky demo) when
+ * mainCREATE_LOW_POWER_DEMO is set to 0.
+ */
+void main_full( void );
+
+/*
+ * The check task, as described at the top of this file.
+ */
+static void prvCheckTask( void *pvParameters );
+
+/*
+ * Some of the tests and demo tasks executed by the full demo include
+ * interaction from an interrupt - for which the tick interrupt is used via the
+ * tick hook function.
+ */
+void vFullDemoTickHook( void );
+
+/*
+ * Register check tasks, and the tasks used to write over and check the contents
+ * of the FPU registers, as described at the top of this file. The nature of
+ * these files necessitates that they are written in an assembly file, but the
+ * entry points are kept in the C file for the convenience of checking the task
+ * parameter.
+ */
+static void prvRegTestTaskEntry1( void *pvParameters );
+extern void vRegTest1Implementation( void );
+static void prvRegTestTaskEntry2( void *pvParameters );
+extern void vRegTest2Implementation( void );
+
+/*-----------------------------------------------------------*/
+
+/* The following two variables are used to communicate the status of the
+register check tasks to the check task. If the variables keep incrementing,
+then the register check tasks have not discovered any errors. If a variable
+stops incrementing, then an error has been found. */
+volatile unsigned long ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL;
+
+/* The variable incremented in lieu of having a proper LED outout. */
+extern volatile uint32_t ulLED;
+
+/*-----------------------------------------------------------*/
+
+void main_full( void )
+{
+ /* Start all the other standard demo/test tasks. They have no particular
+ functionality, but do demonstrate how to use the FreeRTOS API and test the
+ kernel port. */
+ vStartDynamicPriorityTasks();
+ vCreateBlockTimeTasks();
+ vStartGenericQueueTasks( tskIDLE_PRIORITY );
+ vStartRecursiveMutexTasks();
+ vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
+ vStartMathTasks( mainFLOP_TASK_PRIORITY );
+ vStartTimerDemoTask( mainTIMER_TEST_PERIOD );
+ vStartEventGroupTasks();
+ vStartTaskNotifyTask();
+ vStartStaticallyAllocatedTasks();
+
+ /* Create the register check tasks, as described at the top of this file */
+ xTaskCreate( prvRegTestTaskEntry1, "Reg1", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_1_PARAMETER, tskIDLE_PRIORITY, NULL );
+ xTaskCreate( prvRegTestTaskEntry2, "Reg2", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL );
+
+ /* Create the task that performs the 'check' functionality, as described at
+ the top of this file. */
+ xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
+
+ /* Start the scheduler. */
+ vTaskStartScheduler();
+
+ /* If all is well, the scheduler will now be running, and the following
+ line will never be reached. If the following line does execute, then
+ there was insufficient FreeRTOS heap memory available for the Idle and/or
+ timer tasks to be created. See the memory management section on the
+ FreeRTOS web site for more details on the FreeRTOS heap
+ http://www.freertos.org/a00111.html. */
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+static void prvCheckTask( void *pvParameters )
+{
+TickType_t xDelayPeriod = mainNO_ERROR_CHECK_TASK_PERIOD;
+TickType_t xLastExecutionTime;
+static unsigned long ulLastRegTest1Value = 0, ulLastRegTest2Value = 0;
+unsigned long ulErrorFound = pdFALSE;
+
+ /* Just to stop compiler warnings. */
+ ( void ) pvParameters;
+
+ /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()
+ works correctly. */
+ xLastExecutionTime = xTaskGetTickCount();
+
+ /* Cycle for ever, delaying then checking all the other tasks are still
+ operating without error. The onboard LED is toggled on each iteration.
+ If an error is detected then the delay period is decreased from
+ mainNO_ERROR_CHECK_TASK_PERIOD to mainERROR_CHECK_TASK_PERIOD. This has the
+ effect of increasing the rate at which the onboard LED toggles, and in so
+ doing gives visual feedback of the system status. */
+ for( ;; )
+ {
+ /* Delay until it is time to execute again. */
+ vTaskDelayUntil( &xLastExecutionTime, xDelayPeriod );
+
+ /* Check all the demo tasks (other than the flash tasks) to ensure
+ that they are all still running, and that none have detected an error. */
+ if( xAreMathsTaskStillRunning() != pdTRUE )
+ {
+ ulErrorFound = 1UL << 1UL;
+ }
+
+ if( xAreDynamicPriorityTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound = 1UL << 2UL;
+ }
+
+ if( xAreStaticAllocationTasksStillRunning() != pdPASS )
+ {
+ ulErrorFound = 1UL << 3UL;
+ }
+
+ if ( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound = 1UL << 4UL;
+ }
+
+ if ( xAreGenericQueueTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound = 1UL << 5UL;
+ }
+
+ if ( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound = 1UL << 6UL;
+ }
+
+ if( xAreSemaphoreTasksStillRunning() != pdTRUE )
+ {
+ ulErrorFound = 1UL << 8UL;
+ }
+
+ if( xAreTimerDemoTasksStillRunning( ( TickType_t ) xDelayPeriod ) != pdPASS )
+ {
+ ulErrorFound = 1UL << 9UL;
+ }
+
+ if( xAreEventGroupTasksStillRunning() != pdPASS )
+ {
+ ulErrorFound = 1UL << 12UL;
+ }
+
+ if( xAreTaskNotificationTasksStillRunning() != pdPASS )
+ {
+ ulErrorFound = 1UL << 14UL;
+ }
+
+ /* Check that the register test 1 task is still running. */
+ if( ulLastRegTest1Value == ulRegTest1LoopCounter )
+ {
+ ulErrorFound = 1UL << 15UL;
+ }
+ ulLastRegTest1Value = ulRegTest1LoopCounter;
+
+ /* Check that the register test 2 task is still running. */
+ if( ulLastRegTest2Value == ulRegTest2LoopCounter )
+ {
+ ulErrorFound = 1UL << 16UL;
+ }
+ ulLastRegTest2Value = ulRegTest2LoopCounter;
+
+ /* Toggle the check LED to give an indication of the system status. If
+ the LED toggles every mainNO_ERROR_CHECK_TASK_PERIOD milliseconds then
+ everything is ok. A faster toggle indicates an error. */
+ BSP_LedToggle( mainTASK_LED );
+
+ if( ulErrorFound != pdFALSE )
+ {
+ /* An error has been detected in one of the tasks - flash the LED
+ at a higher frequency to give visible feedback that something has
+ gone wrong. */
+ xDelayPeriod = mainERROR_CHECK_TASK_PERIOD;
+ }
+
+ configASSERT( ulErrorFound == pdFALSE );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvRegTestTaskEntry1( void *pvParameters )
+{
+ /* Although the regtest task is written in assembler, its entry point is
+ written in C for convenience of checking the task parameter is being passed
+ in correctly. */
+ if( pvParameters == mainREG_TEST_TASK_1_PARAMETER )
+ {
+ /* Start the part of the test that is written in assembler. */
+ vRegTest1Implementation();
+ }
+
+ /* The following line will only execute if the task parameter is found to
+ be incorrect. The check timer will detect that the regtest loop counter is
+ not being incremented and flag an error. */
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+static void prvRegTestTaskEntry2( void *pvParameters )
+{
+ /* Although the regtest task is written in assembler, its entry point is
+ written in C for convenience of checking the task parameter is being passed
+ in correctly. */
+ if( pvParameters == mainREG_TEST_TASK_2_PARAMETER )
+ {
+ /* Start the part of the test that is written in assembler. */
+ vRegTest2Implementation();
+ }
+
+ /* The following line will only execute if the task parameter is found to
+ be incorrect. The check timer will detect that the regtest loop counter is
+ not being incremented and flag an error. */
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+void vFullDemoTickHook( void )
+{
+ /* Some of the tests and demo tasks executed by the full demo include
+ interaction from an interrupt - for which the tick interrupt is used via
+ the tick hook function. */
+
+ /* The full demo includes a software timer demo/test that requires
+ prodding periodically from the tick interrupt. */
+ vTimerPeriodicISRTests();
+
+ /* Call the periodic event group from ISR demo. */
+ vPeriodicEventGroupsProcessing();
+
+ /* Call the code that 'gives' a task notification from an ISR. */
+ xNotifyTaskFromISR();
+}
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Low_Power_Demo/low_power_tick_management_RTCC.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Low_Power_Demo/low_power_tick_management_RTCC.c new file mode 100644 index 000000000..6e75baed9 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Low_Power_Demo/low_power_tick_management_RTCC.c @@ -0,0 +1,382 @@ +/*
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/* Standard inlcludes. */
+#include <limits.h>
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* SiLabs library includes. */
+#include "em_cmu.h"
+#include "em_rtcc.h"
+#include "em_rmu.h"
+#include "em_int.h"
+#include "sleep.h"
+
+/* SEE THE COMMENTS ABOVE THE DEFINITION OF configCREATE_LOW_POWER_DEMO IN
+FreeRTOSConfig.h
+This file contains functions that will override the default implementations
+in the RTOS port layer. Therefore only build this file if the low power demo
+is being built. */
+#if( configCREATE_LOW_POWER_DEMO == 1 )
+
+/* The RTCC channel used to generate the tick interrupt. */
+#define lpRTCC_CHANNEL ( 1 )
+
+/* 32768 clock divided by 1. Don't use a prescale if errata RTCC_E201
+applies. */
+#define mainTIMER_FREQUENCY_HZ ( 32768UL )
+
+/*
+ * The low power demo does not use the SysTick, so override the
+ * vPortSetupTickInterrupt() function with an implementation that configures
+ * a low power clock source. NOTE: This function name must not be changed as
+ * it is called from the RTOS portable layer.
+ */
+void vPortSetupTimerInterrupt( void );
+
+/*
+ * Override the default definition of vPortSuppressTicksAndSleep() that is
+ * weakly defined in the FreeRTOS Cortex-M port layer with a version that
+ * manages the RTC clock, as the tick is generated from the low power RTC
+ * and not the SysTick as would normally be the case on a Cortex-M.
+ */
+void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
+
+/*-----------------------------------------------------------*/
+
+/* Calculate how many clock increments make up a single tick period. */
+static const uint32_t ulReloadValueForOneTick = ( mainTIMER_FREQUENCY_HZ / configTICK_RATE_HZ );
+
+/* Will hold the maximum number of ticks that can be suppressed. */
+static uint32_t xMaximumPossibleSuppressedTicks = 0;
+
+/* Flag set from the tick interrupt to allow the sleep processing to know if
+sleep mode was exited because of a timer interrupt or a different interrupt. */
+static volatile uint32_t ulTickFlag = pdFALSE;
+
+/* As the clock is only 32KHz, it is likely a value of 1 will be enough. */
+static const uint32_t ulStoppedTimerCompensation = 0UL;
+
+/* RTCC configuration structures. */
+static const RTCC_Init_TypeDef xRTCInitStruct =
+{
+ false, /* Don't start counting when init complete. */
+ false, /* Disable counter during debug halt. */
+ false, /* Don't care. */
+ true, /* Enable counter wrap on ch. 1 CCV value. */
+ rtccCntPresc_1, /* NOTE: Do not use a pre-scale if errata RTCC_E201 applies. */
+ rtccCntTickPresc, /* Count using the clock input directly. */
+#if defined(_RTCC_CTRL_BUMODETSEN_MASK)
+ false, /* Disable storing RTCC counter value in RTCC_CCV2 upon backup mode entry. */
+#endif
+ false, /* Oscillator fail detection disabled. */
+ rtccCntModeNormal, /* Use RTCC in normal mode (increment by 1 on each tick) and not in calendar mode. */
+ false /* Don't care. */
+};
+
+static const RTCC_CCChConf_TypeDef xRTCCChannel1InitStruct =
+{
+ rtccCapComChModeCompare, /* Use Compare mode. */
+ rtccCompMatchOutActionPulse,/* Don't care. */
+ rtccPRSCh0, /* PRS not used. */
+ rtccInEdgeNone, /* Capture Input not used. */
+ rtccCompBaseCnt, /* Compare with Base CNT register. */
+ 0, /* Compare mask. */
+ rtccDayCompareModeMonth /* Don't care. */
+};
+
+/*-----------------------------------------------------------*/
+
+void vPortSetupTimerInterrupt( void )
+{
+ /* Configure the RTCC to generate the RTOS tick interrupt. */
+
+ /* The maximum number of ticks that can be suppressed depends on the clock
+ frequency. */
+ xMaximumPossibleSuppressedTicks = ULONG_MAX / ulReloadValueForOneTick;
+
+ /* Ensure LE modules are accessible. */
+ CMU_ClockEnable( cmuClock_CORELE, true );
+
+ /* Use LFXO. */
+ CMU_ClockSelectSet( cmuClock_LFE, cmuSelect_LFXO );
+
+ /* Enable clock to the RTC module. */
+ CMU_ClockEnable( cmuClock_RTCC, true );
+
+ /* Use channel 1 to generate the RTOS tick interrupt. */
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValueForOneTick );
+
+ RTCC_Init( &xRTCInitStruct );
+ RTCC_ChannelInit( lpRTCC_CHANNEL, &xRTCCChannel1InitStruct );
+ RTCC_EM4WakeupEnable( true );
+
+ /* Disable RTCC interrupt. */
+ RTCC_IntDisable( _RTCC_IF_MASK );
+ RTCC_IntClear( _RTCC_IF_MASK );
+ RTCC->CNT = _RTCC_CNT_RESETVALUE;
+
+ /* The tick interrupt must be set to the lowest priority possible. */
+ NVIC_SetPriority( RTCC_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY );
+ NVIC_ClearPendingIRQ( RTCC_IRQn );
+ NVIC_EnableIRQ( RTCC_IRQn );
+ RTCC_IntEnable( RTCC_IEN_CC1 );
+ RTCC_Enable( true );
+}
+/*-----------------------------------------------------------*/
+
+void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
+{
+uint32_t ulReloadValue, ulCompleteTickPeriods, ulCountBeforeSleep, ulCountAfterSleep;
+eSleepModeStatus eSleepAction;
+TickType_t xModifiableIdleTime;
+
+ /* THIS FUNCTION IS CALLED WITH THE SCHEDULER SUSPENDED. */
+
+ /* Make sure the RTC reload value does not overflow the counter. */
+ if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
+ {
+ xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
+ }
+
+ /* Calculate the reload value required to wait xExpectedIdleTime tick
+ periods. */
+ ulReloadValue = ulReloadValueForOneTick * xExpectedIdleTime;
+ if( ulReloadValue > ulStoppedTimerCompensation )
+ {
+ /* Compensate for the fact that the RTC is going to be stopped
+ momentarily. */
+ ulReloadValue -= ulStoppedTimerCompensation;
+ }
+
+ /* Stop the RTC momentarily. The time the RTC is stopped for is accounted
+ for as best it can be, but using the tickless mode will inevitably result
+ in some tiny drift of the time maintained by the kernel with respect to
+ calendar time. The count is latched before stopping the timer as stopping
+ the timer appears to clear the count. */
+ ulCountBeforeSleep = RTCC_CounterGet();
+ RTCC_Enable( false );
+
+ /* If this function is re-entered before one complete tick period then the
+ reload value might be set to take into account a partial time slice, but
+ just reading the count assumes it is counting up to a full ticks worth - so
+ add in the difference if any. */
+ ulCountBeforeSleep += ( ulReloadValueForOneTick - RTCC_ChannelCCVGet( lpRTCC_CHANNEL ) );
+
+ /* Enter a critical section but don't use the taskENTER_CRITICAL() method as
+ that will mask interrupts that should exit sleep mode. */
+ INT_Disable();
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
+
+ /* The tick flag is set to false before sleeping. If it is true when sleep
+ mode is exited then sleep mode was probably exited because the tick was
+ suppressed for the entire xExpectedIdleTime period. */
+ ulTickFlag = pdFALSE;
+
+ /* If a context switch is pending then abandon the low power entry as the
+ context switch might have been pended by an external interrupt that requires
+ processing. */
+ eSleepAction = eTaskConfirmSleepModeStatus();
+ if( eSleepAction == eAbortSleep )
+ {
+ /* Restart tick and count up to whatever was left of the current time
+ slice. */
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ( ulReloadValueForOneTick - ulCountBeforeSleep ) + ulStoppedTimerCompensation );
+ RTCC_Enable( true );
+
+ /* Re-enable interrupts - see comments above the cpsid instruction()
+ above. */
+ INT_Enable();
+ }
+ else
+ {
+ /* Adjust the reload value to take into account that the current time
+ slice is already partially complete. */
+ ulReloadValue -= ulCountBeforeSleep;
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValue );
+
+ /* Restart the RTC. */
+ RTCC_Enable( true );
+
+ /* Allow the application to define some pre-sleep processing. */
+ xModifiableIdleTime = xExpectedIdleTime;
+ configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
+
+ /* xExpectedIdleTime being set to 0 by configPRE_SLEEP_PROCESSING()
+ means the application defined code has already executed the WAIT
+ instruction. */
+ if( xModifiableIdleTime > 0 )
+ {
+ __asm volatile( "dsb" );
+ SLEEP_Sleep();
+ __asm volatile( "isb" );
+ }
+
+ /* Allow the application to define some post sleep processing. */
+ configPOST_SLEEP_PROCESSING( xModifiableIdleTime );
+
+ /* Stop RTC. Again, the time the SysTick is stopped for is accounted
+ for as best it can be, but using the tickless mode will inevitably
+ result in some tiny drift of the time maintained by the kernel with
+ respect to calendar time. The count value is latched before stopping
+ the timer as stopping the timer appears to clear the count. */
+ ulCountAfterSleep = RTCC_CounterGet();
+ RTCC_Enable( false );
+
+ /* Re-enable interrupts - see comments above the cpsid instruction()
+ above. */
+ INT_Enable();
+ __asm volatile( "dsb" );
+ __asm volatile( "isb" );
+
+ if( ulTickFlag != pdFALSE )
+ {
+ /* The tick interrupt has already executed, although because this
+ function is called with the scheduler suspended the actual tick
+ processing will not occur until after this function has exited.
+ Reset the reload value with whatever remains of this tick period. */
+ ulReloadValue = ulReloadValueForOneTick - ulCountAfterSleep;
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValue );
+
+ /* The tick interrupt handler will already have pended the tick
+ processing in the kernel. As the pending tick will be processed as
+ soon as this function exits, the tick value maintained by the tick
+ is stepped forward by one less than the time spent sleeping. The
+ actual stepping of the tick appears later in this function. */
+ ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
+ }
+ else
+ {
+ /* Something other than the tick interrupt ended the sleep. How
+ many complete tick periods passed while the processor was
+ sleeping? Add back in the adjustment that was made to the reload
+ value to account for the fact that a time slice was part way through
+ when this function was called. */
+ ulCountAfterSleep += ulCountBeforeSleep;
+ ulCompleteTickPeriods = ulCountAfterSleep / ulReloadValueForOneTick;
+
+ /* The reload value is set to whatever fraction of a single tick
+ period remains. */
+ ulCountAfterSleep -= ( ulCompleteTickPeriods * ulReloadValueForOneTick );
+ ulReloadValue = ulReloadValueForOneTick - ulCountAfterSleep;
+
+ if( ulReloadValue == 0 )
+ {
+ /* There is no fraction remaining. */
+ ulReloadValue = ulReloadValueForOneTick;
+ ulCompleteTickPeriods++;
+ }
+
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValue );
+ }
+
+ /* Restart the RTC so it runs up to the alarm value. The alarm value
+ will get set to the value required to generate exactly one tick period
+ the next time the RTC interrupt executes. */
+ RTCC_Enable( true );
+
+ /* Wind the tick forward by the number of tick periods that the CPU
+ remained in a low power state. */
+ vTaskStepTick( ulCompleteTickPeriods );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void RTCC_IRQHandler( void )
+{
+ ulTickFlag = pdTRUE;
+
+ if( RTCC_ChannelCCVGet( lpRTCC_CHANNEL ) != ulReloadValueForOneTick )
+ {
+ /* Set RTC interrupt to one RTOS tick period. */
+ RTCC_Enable( false );
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValueForOneTick );
+ RTCC_Enable( true );
+ }
+
+ RTCC_IntClear( _RTCC_IF_MASK );
+
+ /* Critical section which protect incrementing the tick*/
+ portDISABLE_INTERRUPTS();
+ {
+ if( xTaskIncrementTick() != pdFALSE )
+ {
+ /* Pend a context switch. */
+ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
+ }
+ }
+ portENABLE_INTERRUPTS();
+}
+/*-----------------------------------------------------------*/
+
+#endif /* ( configCREATE_LOW_POWER_DEMO == 1 ) */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Low_Power_Demo/main_low_power.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Low_Power_Demo/main_low_power.c new file mode 100644 index 000000000..3fffc65ae --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/Low_Power_Demo/main_low_power.c @@ -0,0 +1,236 @@ +/*
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/******************************************************************************
+ * NOTE 1: This project provides two demo applications. A simple blinky demo
+ * that demonstrates tickless low power operation, and a more comprehensive
+ * test and demo application. The configCREATE_LOW_POWER_DEMO setting in
+ * FreeRTOSConfig.h is used to select between the two, and to select the clock
+ * used when tickless low power operation is demonstrated. See the notes on
+ * using configCREATE_LOW_POWER_DEMO in main.c. This file implements the low
+ * power version.
+ *
+ * NOTE 2: This file only contains the source code that is specific to the
+ * low power demo. Generic functions, such FreeRTOS hook functions, and
+ * functions required to configure the hardware are defined in main.c.
+ ******************************************************************************
+ *
+ * main_low_power() creates one queue, and two tasks. It then starts the
+ * scheduler.
+ *
+ * The Queue Send Task:
+ * The queue send task is implemented by the prvQueueSendTask() function in
+ * this file. It sends the value 100 to the queue every second.
+ *
+ * The Queue Receive Task:
+ * The queue receive task is implemented by the prvQueueReceiveTask() function
+ * in this file. prvQueueReceiveTask() blocks on the queue, blipping (quickly
+ * turn on then off again) the LED each time it received the value 100 from the
+ * queue send task. The queue send task writes to the queue every second, so
+ * the LED will blip once a second.
+ *
+ * The RTOS tick is turned off when the queue send task and queue receive task
+ * are both in the Blocked state.
+ *
+ */
+
+
+/* Kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* SiLabs includes. */
+#include "bsp.h"
+
+/* Priorities at which the tasks are created. */
+#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
+#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
+
+/* The rate at which data is sent to the queue. The 200ms value is converted
+to ticks using the portTICK_PERIOD_MS constant. */
+#define mainQUEUE_SEND_FREQUENCY_MS pdMS_TO_TICKS( 1000 )
+
+/* The number of items the queue can hold. This is 1 as the receive task
+will remove items as they are added, meaning the send task should always find
+the queue empty. */
+#define mainQUEUE_LENGTH ( 1 )
+
+/* The LED toggled by the Rx task. */
+#define mainTASK_LED ( 0 )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Called by main when mainCREATE_LOW_POWER_DEMO is set to 1 in
+ * main.c.
+ */
+void main_low_power( void );
+
+/*
+ * The tasks as described in the comments at the top of this file.
+ */
+static void prvQueueReceiveTask( void *pvParameters );
+static void prvQueueSendTask( void *pvParameters );
+
+/*-----------------------------------------------------------*/
+
+/* The queue used by both tasks. */
+static QueueHandle_t xQueue = NULL;
+
+/*-----------------------------------------------------------*/
+
+void main_low_power( void )
+{
+ /* Create the queue. */
+ xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
+
+ if( xQueue != NULL )
+ {
+ /* Start the two tasks as described in the comments at the top of this
+ file. */
+ xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */
+ "Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
+ configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
+ NULL, /* The parameter passed to the task - not used in this case. */
+ mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */
+ NULL ); /* The task handle is not required, so NULL is passed. */
+
+ xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
+
+ /* Start the tasks and timer running. */
+ vTaskStartScheduler();
+ }
+
+ /* If all is well, the scheduler will now be running, and the following
+ line will never be reached. If the following line does execute, then
+ there was insufficient FreeRTOS heap memory available for the Idle and/or
+ timer tasks to be created. See the memory management section on the
+ FreeRTOS web site for more details on the FreeRTOS heap
+ http://www.freertos.org/a00111.html. */
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+static void prvQueueSendTask( void *pvParameters )
+{
+TickType_t xNextWakeTime;
+const uint32_t ulValueToSend = 100UL;
+
+ /* Remove compiler warning about unused parameter. */
+ ( void ) pvParameters;
+
+ /* Initialise xNextWakeTime - this only needs to be done once. */
+ xNextWakeTime = xTaskGetTickCount();
+
+ for( ;; )
+ {
+ /* Place this task in the blocked state until it is time to run again. */
+ vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );
+
+ /* Send to the queue - causing the queue receive task to unblock and
+ toggle the LED. 0 is used as the block time so the sending operation
+ will not block - it shouldn't need to block as the queue should always
+ be empty at this point in the code. */
+ xQueueSend( xQueue, &ulValueToSend, 0U );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvQueueReceiveTask( void *pvParameters )
+{
+uint32_t ulReceivedValue;
+const uint32_t ulExpectedValue = 100UL;
+const TickType_t xShortDelay = pdMS_TO_TICKS( 10 );
+
+ /* Remove compiler warning about unused parameter. */
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /* Wait until something arrives in the queue - this task will block
+ indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
+ FreeRTOSConfig.h. */
+ xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
+
+ /* To get here something must have been received from the queue, but
+ is it the expected value? If it is, toggle the LED. */
+ if( ulReceivedValue == ulExpectedValue )
+ {
+ /* Turn the LED on for a brief time only so it doens't distort the
+ energy reading. */
+ BSP_LedSet( mainTASK_LED );
+ vTaskDelay( xShortDelay );
+ BSP_LedClear( mainTASK_LED );
+ ulReceivedValue = 0U;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/BSP/bsp_stk_leds.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/BSP/bsp_stk_leds.c new file mode 100644 index 000000000..d972e3bf0 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/BSP/bsp_stk_leds.c @@ -0,0 +1,117 @@ +/***************************************************************************//**
+ * @file
+ * @brief Board support package API for GPIO leds on STK's.
+ * @version 4.2.1
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * This file is licensed under the Silabs License Agreement. See the file
+ * "Silabs_License_Agreement.txt" for details. Before using this software for
+ * any purpose, you must agree to the terms of that agreement.
+ *
+ ******************************************************************************/
+
+
+
+#include "em_device.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "bsp.h"
+
+#if defined( BSP_GPIO_LEDS )
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+typedef struct
+{
+ GPIO_Port_TypeDef port;
+ unsigned int pin;
+} tLedArray;
+
+static const tLedArray ledArray[ BSP_NO_OF_LEDS ] = BSP_GPIO_LEDARRAY_INIT;
+
+int BSP_LedsInit(void)
+{
+ int i;
+
+ CMU_ClockEnable(cmuClock_HFPER, true);
+ CMU_ClockEnable(cmuClock_GPIO, true);
+ for ( i=0; i<BSP_NO_OF_LEDS; i++ )
+ {
+ GPIO_PinModeSet(ledArray[i].port, ledArray[i].pin, gpioModePushPull, 0);
+ }
+ return BSP_STATUS_OK;
+}
+
+uint32_t BSP_LedsGet(void)
+{
+ int i;
+ uint32_t retVal, mask;
+
+ for ( i=0, retVal=0, mask=0x1; i<BSP_NO_OF_LEDS; i++, mask <<= 1 )
+ {
+ if (GPIO_PinOutGet(ledArray[i].port, ledArray[i].pin))
+ retVal |= mask;
+ }
+ return retVal;
+}
+
+int BSP_LedsSet(uint32_t leds)
+{
+ int i;
+ uint32_t mask;
+
+ for ( i=0, mask=0x1; i<BSP_NO_OF_LEDS; i++, mask <<= 1 )
+ {
+ if ( leds & mask )
+ GPIO_PinOutSet(ledArray[i].port, ledArray[i].pin);
+ else
+ GPIO_PinOutClear(ledArray[i].port, ledArray[i].pin);
+ }
+ return BSP_STATUS_OK;
+}
+
+int BSP_LedClear(int ledNo)
+{
+ if ((ledNo >= 0) && (ledNo < BSP_NO_OF_LEDS))
+ {
+ GPIO_PinOutClear(ledArray[ledNo].port, ledArray[ledNo].pin);
+ return BSP_STATUS_OK;
+ }
+ return BSP_STATUS_ILLEGAL_PARAM;
+}
+
+int BSP_LedGet(int ledNo)
+{
+ int retVal = BSP_STATUS_ILLEGAL_PARAM;
+
+ if ((ledNo >= 0) && (ledNo < BSP_NO_OF_LEDS))
+ {
+ retVal = (int)GPIO_PinOutGet(ledArray[ledNo].port, ledArray[ledNo].pin);
+ }
+ return retVal;
+}
+
+int BSP_LedSet(int ledNo)
+{
+ if ((ledNo >= 0) && (ledNo < BSP_NO_OF_LEDS))
+ {
+ GPIO_PinOutSet(ledArray[ledNo].port, ledArray[ledNo].pin);
+ return BSP_STATUS_OK;
+ }
+ return BSP_STATUS_ILLEGAL_PARAM;
+}
+
+int BSP_LedToggle(int ledNo)
+{
+ if ((ledNo >= 0) && (ledNo < BSP_NO_OF_LEDS))
+ {
+ GPIO_PinOutToggle(ledArray[ledNo].port, ledArray[ledNo].pin);
+ return BSP_STATUS_OK;
+ }
+ return BSP_STATUS_ILLEGAL_PARAM;
+}
+
+/** @endcond */
+#endif /* BSP_GPIO_LEDS */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/CMSIS/efm32pg1b/startup_gcc_efm32pg1b.s b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/CMSIS/efm32pg1b/startup_gcc_efm32pg1b.s new file mode 100644 index 000000000..d9e8a9d3a --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/CMSIS/efm32pg1b/startup_gcc_efm32pg1b.s @@ -0,0 +1,317 @@ +/* @file startup_efm32pg1b.S
+ * @brief startup file for Silicon Labs EFM32PG1B devices.
+ * For use with GCC for ARM Embedded Processors
+ * @version 4.2.1
+ * Date: 12 June 2014
+ *
+ */
+/* Copyright (c) 2011 - 2014 ARM LIMITED
+
+ All rights reserved.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ - Neither the name of ARM nor the names of its contributors may be used
+ to endorse or promote products derived from this software without
+ specific prior written permission.
+ *
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ ---------------------------------------------------------------------------*/
+
+ .syntax unified
+ .arch armv7-m
+ .section .stack
+ .align 3
+#ifdef __STACK_SIZE
+ .equ Stack_Size, __STACK_SIZE
+#else
+ .equ Stack_Size, 0x00000400
+#endif
+ .globl __StackTop
+ .globl __StackLimit
+__StackLimit:
+ .space Stack_Size
+ .size __StackLimit, . - __StackLimit
+__StackTop:
+ .size __StackTop, . - __StackTop
+
+ .section .heap
+ .align 3
+#ifdef __HEAP_SIZE
+ .equ Heap_Size, __HEAP_SIZE
+#else
+ .equ Heap_Size, 0x00000C00
+#endif
+ .globl __HeapBase
+ .globl __HeapLimit
+__HeapBase:
+ .if Heap_Size
+ .space Heap_Size
+ .endif
+ .size __HeapBase, . - __HeapBase
+__HeapLimit:
+ .size __HeapLimit, . - __HeapLimit
+
+ .section .vectors
+ .align 2
+ .globl __Vectors
+__Vectors:
+ .long __StackTop /* Top of Stack */
+ .long Reset_Handler /* Reset Handler */
+ .long NMI_Handler /* NMI Handler */
+ .long HardFault_Handler /* Hard Fault Handler */
+ .long MemManage_Handler /* MPU Fault Handler */
+ .long BusFault_Handler /* Bus Fault Handler */
+ .long UsageFault_Handler /* Usage Fault Handler */
+ .long Default_Handler /* Reserved */
+ .long Default_Handler /* Reserved */
+ .long Default_Handler /* Reserved */
+ .long Default_Handler /* Reserved */
+ .long SVC_Handler /* SVCall Handler */
+ .long DebugMon_Handler /* Debug Monitor Handler */
+ .long Default_Handler /* Reserved */
+ .long PendSV_Handler /* PendSV Handler */
+ .long SysTick_Handler /* SysTick Handler */
+
+ /* External interrupts */
+ .long EMU_IRQHandler /* 0 - EMU */
+ .long Default_Handler /* 1 - Reserved */
+ .long WDOG0_IRQHandler /* 2 - WDOG0 */
+ .long Default_Handler /* 3 - Reserved */
+ .long Default_Handler /* 4 - Reserved */
+ .long Default_Handler /* 5 - Reserved */
+ .long Default_Handler /* 6 - Reserved */
+ .long Default_Handler /* 7 - Reserved */
+ .long LDMA_IRQHandler /* 8 - LDMA */
+ .long GPIO_EVEN_IRQHandler /* 9 - GPIO_EVEN */
+ .long TIMER0_IRQHandler /* 10 - TIMER0 */
+ .long USART0_RX_IRQHandler /* 11 - USART0_RX */
+ .long USART0_TX_IRQHandler /* 12 - USART0_TX */
+ .long ACMP0_IRQHandler /* 13 - ACMP0 */
+ .long ADC0_IRQHandler /* 14 - ADC0 */
+ .long IDAC0_IRQHandler /* 15 - IDAC0 */
+ .long I2C0_IRQHandler /* 16 - I2C0 */
+ .long GPIO_ODD_IRQHandler /* 17 - GPIO_ODD */
+ .long TIMER1_IRQHandler /* 18 - TIMER1 */
+ .long USART1_RX_IRQHandler /* 19 - USART1_RX */
+ .long USART1_TX_IRQHandler /* 20 - USART1_TX */
+ .long LEUART0_IRQHandler /* 21 - LEUART0 */
+ .long PCNT0_IRQHandler /* 22 - PCNT0 */
+ .long CMU_IRQHandler /* 23 - CMU */
+ .long MSC_IRQHandler /* 24 - MSC */
+ .long CRYPTO_IRQHandler /* 25 - CRYPTO */
+ .long LETIMER0_IRQHandler /* 26 - LETIMER0 */
+ .long Default_Handler /* 27 - Reserved */
+ .long Default_Handler /* 28 - Reserved */
+ .long RTCC_IRQHandler /* 29 - RTCC */
+ .long Default_Handler /* 30 - Reserved */
+ .long CRYOTIMER_IRQHandler /* 31 - CRYOTIMER */
+ .long Default_Handler /* 32 - Reserved */
+ .long FPUEH_IRQHandler /* 33 - FPUEH */
+
+
+ .size __Vectors, . - __Vectors
+
+ .text
+ .thumb
+ .thumb_func
+ .align 2
+ .globl Reset_Handler
+ .type Reset_Handler, %function
+Reset_Handler:
+#ifndef __NO_SYSTEM_INIT
+ ldr r0, =SystemInit
+ blx r0
+#endif
+
+/* Firstly it copies data from read only memory to RAM. There are two schemes
+ * to copy. One can copy more than one sections. Another can only copy
+ * one section. The former scheme needs more instructions and read-only
+ * data to implement than the latter.
+ * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */
+
+#ifdef __STARTUP_COPY_MULTIPLE
+/* Multiple sections scheme.
+ *
+ * Between symbol address __copy_table_start__ and __copy_table_end__,
+ * there are array of triplets, each of which specify:
+ * offset 0: LMA of start of a section to copy from
+ * offset 4: VMA of start of a section to copy to
+ * offset 8: size of the section to copy. Must be multiply of 4
+ *
+ * All addresses must be aligned to 4 bytes boundary.
+ */
+ ldr r4, =__copy_table_start__
+ ldr r5, =__copy_table_end__
+
+.L_loop0:
+ cmp r4, r5
+ bge .L_loop0_done
+ ldr r1, [r4]
+ ldr r2, [r4, #4]
+ ldr r3, [r4, #8]
+
+.L_loop0_0:
+ subs r3, #4
+ ittt ge
+ ldrge r0, [r1, r3]
+ strge r0, [r2, r3]
+ bge .L_loop0_0
+
+ adds r4, #12
+ b .L_loop0
+
+.L_loop0_done:
+#else
+/* Single section scheme.
+ *
+ * The ranges of copy from/to are specified by following symbols
+ * __etext: LMA of start of the section to copy from. Usually end of text
+ * __data_start__: VMA of start of the section to copy to
+ * __data_end__: VMA of end of the section to copy to
+ *
+ * All addresses must be aligned to 4 bytes boundary.
+ */
+ ldr r1, =__etext
+ ldr r2, =__data_start__
+ ldr r3, =__data_end__
+
+.L_loop1:
+ cmp r2, r3
+ ittt lt
+ ldrlt r0, [r1], #4
+ strlt r0, [r2], #4
+ blt .L_loop1
+#endif /*__STARTUP_COPY_MULTIPLE */
+
+/* This part of work usually is done in C library startup code. Otherwise,
+ * define this macro to enable it in this startup.
+ *
+ * There are two schemes too. One can clear multiple BSS sections. Another
+ * can only clear one section. The former is more size expensive than the
+ * latter.
+ *
+ * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
+ * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later.
+ */
+#ifdef __STARTUP_CLEAR_BSS_MULTIPLE
+/* Multiple sections scheme.
+ *
+ * Between symbol address __copy_table_start__ and __copy_table_end__,
+ * there are array of tuples specifying:
+ * offset 0: Start of a BSS section
+ * offset 4: Size of this BSS section. Must be multiply of 4
+ */
+ ldr r3, =__zero_table_start__
+ ldr r4, =__zero_table_end__
+
+.L_loop2:
+ cmp r3, r4
+ bge .L_loop2_done
+ ldr r1, [r3]
+ ldr r2, [r3, #4]
+ movs r0, 0
+
+.L_loop2_0:
+ subs r2, #4
+ itt ge
+ strge r0, [r1, r2]
+ bge .L_loop2_0
+ adds r3, #8
+ b .L_loop2
+.L_loop2_done:
+#elif defined (__STARTUP_CLEAR_BSS)
+/* Single BSS section scheme.
+ *
+ * The BSS section is specified by following symbols
+ * __bss_start__: start of the BSS section.
+ * __bss_end__: end of the BSS section.
+ *
+ * Both addresses must be aligned to 4 bytes boundary.
+ */
+ ldr r1, =__bss_start__
+ ldr r2, =__bss_end__
+
+ movs r0, 0
+.L_loop3:
+ cmp r1, r2
+ itt lt
+ strlt r0, [r1], #4
+ blt .L_loop3
+#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
+
+#ifndef __START
+#define __START _start
+#endif
+ bl __START
+
+ .pool
+ .size Reset_Handler, . - Reset_Handler
+
+ .align 1
+ .thumb_func
+ .weak Default_Handler
+ .type Default_Handler, %function
+Default_Handler:
+ b .
+ .size Default_Handler, . - Default_Handler
+
+/* Macro to define default handlers. Default handler
+ * will be weak symbol and just dead loops. They can be
+ * overwritten by other handlers */
+ .macro def_irq_handler handler_name
+ .weak \handler_name
+ .set \handler_name, Default_Handler
+ .endm
+
+ def_irq_handler NMI_Handler
+ def_irq_handler HardFault_Handler
+ def_irq_handler MemManage_Handler
+ def_irq_handler BusFault_Handler
+ def_irq_handler UsageFault_Handler
+ def_irq_handler SVC_Handler
+ def_irq_handler DebugMon_Handler
+ def_irq_handler PendSV_Handler
+ def_irq_handler SysTick_Handler
+
+
+ def_irq_handler EMU_IRQHandler
+ def_irq_handler WDOG0_IRQHandler
+ def_irq_handler LDMA_IRQHandler
+ def_irq_handler GPIO_EVEN_IRQHandler
+ def_irq_handler TIMER0_IRQHandler
+ def_irq_handler USART0_RX_IRQHandler
+ def_irq_handler USART0_TX_IRQHandler
+ def_irq_handler ACMP0_IRQHandler
+ def_irq_handler ADC0_IRQHandler
+ def_irq_handler IDAC0_IRQHandler
+ def_irq_handler I2C0_IRQHandler
+ def_irq_handler GPIO_ODD_IRQHandler
+ def_irq_handler TIMER1_IRQHandler
+ def_irq_handler USART1_RX_IRQHandler
+ def_irq_handler USART1_TX_IRQHandler
+ def_irq_handler LEUART0_IRQHandler
+ def_irq_handler PCNT0_IRQHandler
+ def_irq_handler CMU_IRQHandler
+ def_irq_handler MSC_IRQHandler
+ def_irq_handler CRYPTO_IRQHandler
+ def_irq_handler LETIMER0_IRQHandler
+ def_irq_handler RTCC_IRQHandler
+ def_irq_handler CRYOTIMER_IRQHandler
+ def_irq_handler FPUEH_IRQHandler
+
+ .end
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/CMSIS/efm32pg1b/system_efm32pg1b.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/CMSIS/efm32pg1b/system_efm32pg1b.c new file mode 100644 index 000000000..c2b611326 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/CMSIS/efm32pg1b/system_efm32pg1b.c @@ -0,0 +1,383 @@ +/***************************************************************************//**
+ * @file system_efm32pg1b.c
+ * @brief CMSIS Cortex-M3/M4 System Layer for EFM32 devices.
+ * @version 4.2.1
+ ******************************************************************************
+ * @section License
+ * <b>Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com</b>
+ ******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software.@n
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.@n
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Laboratories, Inc.
+ * has no obligation to support this Software. Silicon Laboratories, Inc. is
+ * providing the Software "AS IS", with no express or implied warranties of any
+ * kind, including, but not limited to, any implied warranties of
+ * merchantability or fitness for any particular purpose or warranties against
+ * infringement of any proprietary rights of a third party.
+ *
+ * Silicon Laboratories, Inc. will not be liable for any consequential,
+ * incidental, or special damages, or any other relief, or for any claim by
+ * any third party, arising from your use of this Software.
+ *
+ *****************************************************************************/
+
+#include <stdint.h>
+#include "em_device.h"
+
+/*******************************************************************************
+ ****************************** DEFINES ************************************
+ ******************************************************************************/
+
+/** LFRCO frequency, tuned to below frequency during manufacturing. */
+#define EFM32_LFRCO_FREQ (32768UL)
+#define EFM32_ULFRCO_FREQ (1000UL)
+
+/*******************************************************************************
+ ************************** LOCAL VARIABLES ********************************
+ ******************************************************************************/
+
+/* System oscillator frequencies. These frequencies are normally constant */
+/* for a target, but they are made configurable in order to allow run-time */
+/* handling of different boards. The crystal oscillator clocks can be set */
+/* compile time to a non-default value by defining respective EFM_nFXO_FREQ */
+/* values according to board design. By defining the EFM_nFXO_FREQ to 0, */
+/* one indicates that the oscillator is not present, in order to save some */
+/* SW footprint. */
+
+#ifndef EFM32_HFRCO_MAX_FREQ
+#define EFM32_HFRCO_MAX_FREQ (38000000UL)
+#endif
+
+#ifndef EFM32_HFXO_FREQ
+#define EFM32_HFXO_FREQ (40000000UL)
+#endif
+
+#ifndef EFM32_HFRCO_STARTUP_FREQ
+#define EFM32_HFRCO_STARTUP_FREQ (19000000UL)
+#endif
+
+
+/* Do not define variable if HF crystal oscillator not present */
+#if (EFM32_HFXO_FREQ > 0UL)
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+/** System HFXO clock. */
+static uint32_t SystemHFXOClock = EFM32_HFXO_FREQ;
+/** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */
+#endif
+
+#ifndef EFM32_LFXO_FREQ
+#define EFM32_LFXO_FREQ (EFM32_LFRCO_FREQ)
+#endif
+/* Do not define variable if LF crystal oscillator not present */
+#if (EFM32_LFXO_FREQ > 0UL)
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+/** System LFXO clock. */
+static uint32_t SystemLFXOClock = 32768UL;
+/** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */
+#endif
+
+
+/*******************************************************************************
+ ************************** GLOBAL VARIABLES *******************************
+ ******************************************************************************/
+
+/**
+ * @brief
+ * System System Clock Frequency (Core Clock).
+ *
+ * @details
+ * Required CMSIS global variable that must be kept up-to-date.
+ */
+uint32_t SystemCoreClock;
+
+
+/**
+ * @brief
+ * System HFRCO frequency
+ *
+ * @note
+ * This is an EFM32 proprietary variable, not part of the CMSIS definition.
+ *
+ * @details
+ * Frequency of the system HFRCO oscillator
+ */
+uint32_t SystemHfrcoFreq = EFM32_HFRCO_STARTUP_FREQ;
+
+
+/*******************************************************************************
+ ************************** GLOBAL FUNCTIONS *******************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief
+ * Get the current core clock frequency.
+ *
+ * @details
+ * Calculate and get the current core clock frequency based on the current
+ * configuration. Assuming that the SystemCoreClock global variable is
+ * maintained, the core clock frequency is stored in that variable as well.
+ * This function will however calculate the core clock based on actual HW
+ * configuration. It will also update the SystemCoreClock global variable.
+ *
+ * @note
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.
+ *
+ * @return
+ * The current core clock frequency in Hz.
+ ******************************************************************************/
+uint32_t SystemCoreClockGet(void)
+{
+ uint32_t ret;
+ uint32_t presc;
+
+ ret = SystemHFClockGet();
+ presc = (CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK) >>
+ _CMU_HFCOREPRESC_PRESC_SHIFT;
+ ret /= (presc + 1);
+
+ /* Keep CMSIS system clock variable up-to-date */
+ SystemCoreClock = ret;
+
+ return ret;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Get the maximum core clock frequency.
+ *
+ * @note
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.
+ *
+ * @return
+ * The maximum core clock frequency in Hz.
+ ******************************************************************************/
+uint32_t SystemMaxCoreClockGet(void)
+{
+ return (EFM32_HFRCO_MAX_FREQ > EFM32_HFXO_FREQ ? \
+ EFM32_HFRCO_MAX_FREQ : EFM32_HFXO_FREQ);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Get the current HFCLK frequency.
+ *
+ * @note
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.
+ *
+ * @return
+ * The current HFCLK frequency in Hz.
+ ******************************************************************************/
+uint32_t SystemHFClockGet(void)
+{
+ uint32_t ret;
+
+ switch (CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK)
+ {
+ case CMU_HFCLKSTATUS_SELECTED_LFXO:
+#if (EFM32_LFXO_FREQ > 0)
+ ret = SystemLFXOClock;
+#else
+ /* We should not get here, since core should not be clocked. May */
+ /* be caused by a misconfiguration though. */
+ ret = 0;
+#endif
+ break;
+
+ case CMU_HFCLKSTATUS_SELECTED_LFRCO:
+ ret = EFM32_LFRCO_FREQ;
+ break;
+
+ case CMU_HFCLKSTATUS_SELECTED_HFXO:
+#if (EFM32_HFXO_FREQ > 0)
+ ret = SystemHFXOClock;
+#else
+ /* We should not get here, since core should not be clocked. May */
+ /* be caused by a misconfiguration though. */
+ ret = 0;
+#endif
+ break;
+
+ default: /* CMU_HFCLKSTATUS_SELECTED_HFRCO */
+ ret = SystemHfrcoFreq;
+ break;
+ }
+
+ return ret;
+}
+
+
+/**************************************************************************//**
+ * @brief
+ * Get high frequency crystal oscillator clock frequency for target system.
+ *
+ * @note
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.
+ *
+ * @return
+ * HFXO frequency in Hz.
+ *****************************************************************************/
+uint32_t SystemHFXOClockGet(void)
+{
+ /* External crystal oscillator present? */
+#if (EFM32_HFXO_FREQ > 0)
+ return SystemHFXOClock;
+#else
+ return 0;
+#endif
+}
+
+
+/**************************************************************************//**
+ * @brief
+ * Set high frequency crystal oscillator clock frequency for target system.
+ *
+ * @note
+ * This function is mainly provided for being able to handle target systems
+ * with different HF crystal oscillator frequencies run-time. If used, it
+ * should probably only be used once during system startup.
+ *
+ * @note
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.
+ *
+ * @param[in] freq
+ * HFXO frequency in Hz used for target.
+ *****************************************************************************/
+void SystemHFXOClockSet(uint32_t freq)
+{
+ /* External crystal oscillator present? */
+#if (EFM32_HFXO_FREQ > 0)
+ SystemHFXOClock = freq;
+
+ /* Update core clock frequency if HFXO is used to clock core */
+ if ((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) == CMU_HFCLKSTATUS_SELECTED_HFXO)
+ {
+ /* The function will update the global variable */
+ SystemCoreClockGet();
+ }
+#else
+ (void)freq; /* Unused parameter */
+#endif
+}
+
+
+/**************************************************************************//**
+ * @brief
+ * Initialize the system.
+ *
+ * @details
+ * Do required generic HW system init.
+ *
+ * @note
+ * This function is invoked during system init, before the main() routine
+ * and any data has been initialized. For this reason, it cannot do any
+ * initialization of variables etc.
+ *****************************************************************************/
+void SystemInit(void)
+{
+#if (__FPU_PRESENT == 1)
+ /* Set floating point coprosessor access mode. */
+ SCB->CPACR |= ((3UL << 10 * 2) | /* set CP10 Full Access */
+ (3UL << 11 * 2)); /* set CP11 Full Access */
+#endif
+}
+
+
+/**************************************************************************//**
+ * @brief
+ * Get low frequency RC oscillator clock frequency for target system.
+ *
+ * @note
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.
+ *
+ * @return
+ * LFRCO frequency in Hz.
+ *****************************************************************************/
+uint32_t SystemLFRCOClockGet(void)
+{
+ /* Currently we assume that this frequency is properly tuned during */
+ /* manufacturing and is not changed after reset. If future requirements */
+ /* for re-tuning by user, we can add support for that. */
+ return EFM32_LFRCO_FREQ;
+}
+
+
+/**************************************************************************//**
+ * @brief
+ * Get ultra low frequency RC oscillator clock frequency for target system.
+ *
+ * @note
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.
+ *
+ * @return
+ * ULFRCO frequency in Hz.
+ *****************************************************************************/
+uint32_t SystemULFRCOClockGet(void)
+{
+ /* The ULFRCO frequency is not tuned, and can be very inaccurate */
+ return EFM32_ULFRCO_FREQ;
+}
+
+
+/**************************************************************************//**
+ * @brief
+ * Get low frequency crystal oscillator clock frequency for target system.
+ *
+ * @note
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.
+ *
+ * @return
+ * LFXO frequency in Hz.
+ *****************************************************************************/
+uint32_t SystemLFXOClockGet(void)
+{
+ /* External crystal oscillator present? */
+#if (EFM32_LFXO_FREQ > 0)
+ return SystemLFXOClock;
+#else
+ return 0;
+#endif
+}
+
+
+/**************************************************************************//**
+ * @brief
+ * Set low frequency crystal oscillator clock frequency for target system.
+ *
+ * @note
+ * This function is mainly provided for being able to handle target systems
+ * with different HF crystal oscillator frequencies run-time. If used, it
+ * should probably only be used once during system startup.
+ *
+ * @note
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.
+ *
+ * @param[in] freq
+ * LFXO frequency in Hz used for target.
+ *****************************************************************************/
+void SystemLFXOClockSet(uint32_t freq)
+{
+ /* External crystal oscillator present? */
+#if (EFM32_LFXO_FREQ > 0)
+ SystemLFXOClock = freq;
+
+ /* Update core clock frequency if LFXO is used to clock core */
+ if ((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) == CMU_HFCLKSTATUS_SELECTED_LFXO)
+ {
+ /* The function will update the global variable */
+ SystemCoreClockGet();
+ }
+#else
+ (void)freq; /* Unused parameter */
+#endif
+}
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emdrv/sleep/inc/sleep.h b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emdrv/sleep/inc/sleep.h new file mode 100644 index 000000000..c0b182fd2 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emdrv/sleep/inc/sleep.h @@ -0,0 +1,265 @@ +/***************************************************************************//**
+ * @file sleep.h
+ * @brief Energy Modes management driver
+ * @version 4.2.1
+ * @details
+ * This is a energy modes management module consisting of sleep.c and sleep.h
+ * source files. The main purpose of the module is to ease energy
+ * optimization with a simple API. The module allows the system to always sleep
+ * in the lowest possible energy mode. Users could set up callbacks that are
+ * being called before and after each and every sleep. A counting semaphore is
+ * available for each low energy mode (EM1/EM2/EM3) to protect certain system
+ * states from being corrupted. This semaphore has limit set to maximum 255 locks.
+ *
+ * The module provides the following public API to the users:
+ * SLEEP_Init()
+ * SLEEP_Sleep()
+ * SLEEP_SleepBlockBegin()
+ * SLEEP_SleepBlockEnd()
+ * SLEEP_ForceSleepInEM4()
+ *
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * This file is licensed under the Silabs License Agreement. See the file
+ * "Silabs_License_Agreement.txt" for details. Before using this software for
+ * any purpose, you must agree to the terms of that agreement.
+ *
+ ******************************************************************************/
+
+#ifndef __SLEEP_H
+#define __SLEEP_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* Device specific header file(s). */
+#include "em_device.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * @addtogroup EM_Drivers
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup SLEEP
+ * @brief Energy Modes management driver.
+ * @details
+ * This is a energy modes management module consisting of sleep.c and sleep.h
+ * source files. The main purpose of the module is to ease energy
+ * optimization with a simple API. The module allows the system to always sleep
+ * in the lowest possible energy mode. Users could set up callbacks that are
+ * being called before and after each and every sleep. A counting semaphore is
+ * available for each low energy mode (EM1/EM2/EM3) to protect certain system
+ * states from being corrupted. This semaphore has limit set to maximum 255 locks.
+ * @{
+ ******************************************************************************/
+
+/*******************************************************************************
+ ******************************* MACROS ************************************
+ ******************************************************************************/
+
+
+/*******************************************************************************
+ **************************** CONFIGURATION ********************************
+ ******************************************************************************/
+
+/** Enable/disable the HW block for protecting accidental setting of low energy
+ * modes (recommended to be set to true). */
+#ifndef SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED
+#define SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED true
+#endif
+
+/** Enable/disable calling wakeup callback after EM4 reset. */
+#ifndef SLEEP_EM4_WAKEUP_CALLBACK_ENABLED
+#define SLEEP_EM4_WAKEUP_CALLBACK_ENABLED true
+#endif
+
+/** Configure default lowest energy mode that the system can be set to.
+ * Possible values:
+ * @li sleepEM1 - EM1, the CPU core is turned off.
+ * @li sleepEM2 - EM2, like EM1 + all HF clocks are turned off, LF clocks are on.
+ * @li sleepEM3 - EM3, like EM2 + LF clocks are off, RAM retention, GPIO and ACMP
+ * interrupt is on. */
+#ifndef SLEEP_LOWEST_ENERGY_MODE_DEFAULT
+#define SLEEP_LOWEST_ENERGY_MODE_DEFAULT sleepEM3
+#endif
+
+/*******************************************************************************
+ ****************************** TYPEDEFS ***********************************
+ ******************************************************************************/
+
+/** Status value used for showing the Energy Mode the device is currently in. */
+typedef enum
+{
+ /** Status value for EM0. */
+ sleepEM0 = 0,
+
+ /** Status value for EM1. */
+ sleepEM1 = 1,
+
+ /** Status value for EM2. */
+ sleepEM2 = 2,
+
+ /** Status value for EM3. */
+ sleepEM3 = 3,
+
+ /** Status value for EM4. */
+ sleepEM4 = 4
+} SLEEP_EnergyMode_t;
+
+/** Callback function pointer type. */
+typedef void (*SLEEP_CbFuncPtr_t)(SLEEP_EnergyMode_t);
+
+
+/*******************************************************************************
+ ****************************** PROTOTYPES *********************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief
+ * Initialize the Sleep module.
+ *
+ * @details
+ * Use this function to initialize the Sleep module, should be called
+ * only once! Pointers to sleep and wake-up callback functions shall be
+ * provided when calling this function.
+ * If SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to true, this function checks
+ * for the cause of the reset that implicitly called it and calls the wakeup
+ * callback if the reset was a wakeup from EM4 (does not work on Gecko MCU).
+ *
+ * @param[in] pSleepCb
+ * Pointer to the callback function that is being called before the device is
+ * going to sleep.
+ *
+ * @param[in] pWakeUpCb
+ * Pointer to the callback function that is being called after wake up.
+ ******************************************************************************/
+void SLEEP_Init(SLEEP_CbFuncPtr_t pSleepCb, SLEEP_CbFuncPtr_t pWakeUpCb);
+
+/***************************************************************************//**
+ * @brief
+ * Gets the lowest energy mode that the system is allowed to be set to.
+ *
+ * @details
+ * This function uses the low energy mode block counters to determine the
+ * lowest possible that the system is allowed to be set to.
+ *
+ * @return
+ * Lowest energy mode that the system can be set to. Possible values:
+ * @li sleepEM0
+ * @li sleepEM1
+ * @li sleepEM2
+ * @li sleepEM3
+ ******************************************************************************/
+SLEEP_EnergyMode_t SLEEP_LowestEnergyModeGet(void);
+
+/***************************************************************************//**
+ * @brief
+ * Sets the system to sleep into the lowest possible energy mode.
+ *
+ * @details
+ * This function takes care of the system states protected by the sleep block
+ * provided by SLEEP_SleepBlockBegin() / SLEEP_SleepBlockEnd(). It allows
+ * the system to go into the lowest possible energy mode that the device can
+ * be set into at the time of the call of this function.
+ * This function will not go lower than EM3 because leaving EM4 requires
+ * resetting MCU. To enter into EM4 call SLEEP_ForceSleepInEM4().
+ *
+ * @return
+ * Energy Mode that was entered. Possible values:
+ * @li sleepEM0
+ * @li sleepEM1
+ * @li sleepEM2
+ * @li sleepEM3
+ ******************************************************************************/
+SLEEP_EnergyMode_t SLEEP_Sleep(void);
+
+
+/***************************************************************************//**
+ * @brief
+ * Force the device to go to EM4 without doing any checks.
+ *
+ * @details
+ * This function unblocks the low energy sleep block then goes to EM4.
+ *
+ * @note
+ * Regular RAM is not retained in EM4 and the wake up causes a reset.
+ * If the configuration option SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to
+ * true, the SLEEP_Init() function checks for the reset cause and calls the
+ * EM4 wakeup callback.
+ ******************************************************************************/
+void SLEEP_ForceSleepInEM4(void);
+
+
+/***************************************************************************//**
+ * @brief
+ * Begin sleep block in the requested energy mode.
+ *
+ * @details
+ * Blocking a critical system state from a certain energy mode makes sure that
+ * the system is not set to that energy mode while the block is not being
+ * released.
+ * Every SLEEP_SleepBlockBegin() increases the corresponding counter and
+ * every SLEEP_SleepBlockEnd() decreases it.
+ *
+ * Example:\code
+ * SLEEP_SleepBlockBegin(sleepEM2); // do not allow EM2 or higher
+ * // do some stuff that requires EM1 at least, like ADC sampling
+ * SLEEP_SleepBlockEnd(sleepEM2); // remove restriction for EM2\endcode
+ *
+ * @note
+ * Be aware that there is limit of maximum blocks nesting to 255.
+ *
+ * @param[in] eMode
+ * Energy mode to begin to block. Possible values:
+ * @li sleepEM1 - Begin to block the system from being set to EM1 (and EM2..4).
+ * @li sleepEM2 - Begin to block the system from being set to EM2 (and EM3/EM4).
+ * @li sleepEM3 - Begin to block the system from being set to EM3 (and EM4).
+ ******************************************************************************/
+void SLEEP_SleepBlockBegin(SLEEP_EnergyMode_t eMode);
+
+
+/***************************************************************************//**
+ * @brief
+ * End sleep block in the requested energy mode.
+ *
+ * @details
+ * Release restriction for entering certain energy mode. Every call of this
+ * function reduce blocking counter by 1. Once the counter for specific energy
+ * mode is 0 and all counters for lower energy modes are 0 as well, using
+ * particular energy mode is allowed.
+ * Every SLEEP_SleepBlockBegin() increases the corresponding counter and
+ * every SLEEP_SleepBlockEnd() decreases it.
+ *
+ * Example:\code
+ * // at start all energy modes are allowed
+ * SLEEP_SleepBlockBegin(sleepEM2); // EM2, EM3, EM4 are blocked
+ * SLEEP_SleepBlockBegin(sleepEM1); // EM1, EM2, EM3, EM4 are blocked
+ * SLEEP_SleepBlockBegin(sleepEM1); // EM1, EM2, EM3, EM4 are blocked
+ * SLEEP_SleepBlockEnd(sleepEM2); // still EM1, EM2, EM3, EM4 are blocked
+ * SLEEP_SleepBlockEnd(sleepEM1); // still EM1, EM2, EM3, EM4 are blocked
+ * SLEEP_SleepBlockEnd(sleepEM1); // all energy modes are allowed now\endcode
+ *
+ * @param[in] eMode
+ * Energy mode to end to block. Possible values:
+ * @li sleepEM1 - End to block the system from being set to EM1 (and EM2..4).
+ * @li sleepEM2 - End to block the system from being set to EM2 (and EM3/EM4).
+ * @li sleepEM3 - End to block the system from being set to EM3 (and EM4).
+ ******************************************************************************/
+void SLEEP_SleepBlockEnd(SLEEP_EnergyMode_t eMode);
+
+
+/** @} (end addtogroup SLEEP) */
+/** @} (end addtogroup EM_Drivers) */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __SLEEP_H */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emdrv/sleep/src/sleep.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emdrv/sleep/src/sleep.c new file mode 100644 index 000000000..556ec6ba2 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emdrv/sleep/src/sleep.c @@ -0,0 +1,427 @@ +/***************************************************************************//**
+ * @file sleep.c
+ * @brief Energy Modes management driver.
+ * @version 4.2.1
+ * @details
+ * This is a energy modes management module consisting of sleep.c and sleep.h
+ * source files. The main purpose of the module is to ease energy
+ * optimization with a simple API. The module allows the system to always sleep
+ * in the lowest possible energy mode. Users could set up callbacks that are
+ * being called before and after each and every sleep. A counting semaphore is
+ * available for each low energy mode (EM1/EM2/EM3) to protect certain system
+ * states from being corrupted. This semaphore has limit set to maximum 255 locks.
+ *
+ * The module provides the following public API to the users:
+ * SLEEP_Init()
+ * SLEEP_Sleep()
+ * SLEEP_SleepBlockBegin()
+ * SLEEP_SleepBlockEnd()
+ * SLEEP_ForceSleepInEM4()
+ *
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * This file is licensed under the Silabs License Agreement. See the file
+ * "Silabs_License_Agreement.txt" for details. Before using this software for
+ * any purpose, you must agree to the terms of that agreement.
+ *
+ ******************************************************************************/
+
+
+/* Chip specific header file(s). */
+#include "em_device.h"
+#include "em_assert.h"
+#include "em_int.h"
+#include "em_rmu.h"
+#include "em_emu.h"
+
+/* Module header file(s). */
+#include "sleep.h"
+
+/* stdlib is needed for NULL definition */
+#include <stdlib.h>
+
+/***************************************************************************//**
+ * @addtogroup EM_Drivers
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup SLEEP
+ * @brief Energy Modes management driver.
+ * @details
+ * This is a energy modes management module consisting of sleep.c and sleep.h
+ * source files. The main purpose of the module is to ease energy
+ * optimization with a simple API. The module allows the system to always sleep
+ * in the lowest possible energy mode. Users could set up callbacks that are
+ * being called before and after each and every sleep. A counting semaphore is
+ * available for each low energy mode (EM1/EM2/EM3) to protect certain system
+ * states from being corrupted. This semaphore has limit set to maximum 255 locks.
+ * @{
+ ******************************************************************************/
+
+/*******************************************************************************
+ ******************************* MACROS ************************************
+ ******************************************************************************/
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+/* Number of low energy modes (EM1, EM2, EM3). Note: EM4 sleep/wakeup is handled
+ * differently therefore it is not part of the list! */
+#define SLEEP_NUMOF_LOW_ENERGY_MODES 3U
+
+
+
+/*******************************************************************************
+ ****************************** TYPEDEFS ***********************************
+ ******************************************************************************/
+
+
+/*******************************************************************************
+ ****************************** CONSTANTS **********************************
+ ******************************************************************************/
+
+
+/*******************************************************************************
+ ******************************* STATICS ***********************************
+ ******************************************************************************/
+
+/* Callback functions to call before and after sleep. */
+static SLEEP_CbFuncPtr_t sleepCallback = NULL;
+static SLEEP_CbFuncPtr_t wakeUpCallback = NULL;
+
+/* Sleep block counter array representing the nested sleep blocks for the low
+ * energy modes (EM1/EM2/EM3). Array index 0 corresponds to EM1, 1 to EM2 and 2
+ * to EM3 accordingly.
+ *
+ * Note:
+ * - EM4 sleep/wakeup is handled differently therefore it is not part of the
+ * list!
+ * - Max. number of sleep block nesting is 255. */
+static uint8_t sleepBlockCnt[SLEEP_NUMOF_LOW_ENERGY_MODES];
+
+/*******************************************************************************
+ ****************************** PROTOTYPES *********************************
+ ******************************************************************************/
+
+static void SLEEP_EnterEMx(SLEEP_EnergyMode_t eMode);
+//static SLEEP_EnergyMode_t SLEEP_LowestEnergyModeGet(void);
+
+/** @endcond */
+
+/*******************************************************************************
+ *************************** GLOBAL FUNCTIONS ******************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief
+ * Initialize the Sleep module.
+ *
+ * @details
+ * Use this function to initialize the Sleep module, should be called
+ * only once! Pointers to sleep and wake-up callback functions shall be
+ * provided when calling this function.
+ * If SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to true, this function checks
+ * for the cause of the reset that implicitly called it and calls the wakeup
+ * callback if the reset was a wakeup from EM4 (does not work on Gecko MCU).
+ *
+ * @param[in] pSleepCb
+ * Pointer to the callback function that is being called before the device is
+ * going to sleep.
+ *
+ * @param[in] pWakeUpCb
+ * Pointer to the callback function that is being called after wake up.
+ ******************************************************************************/
+void SLEEP_Init(SLEEP_CbFuncPtr_t pSleepCb, SLEEP_CbFuncPtr_t pWakeUpCb)
+{
+ /* Initialize callback functions. */
+ sleepCallback = pSleepCb;
+ wakeUpCallback = pWakeUpCb;
+
+ /* Reset sleep block counters. Note: not using for() saves code! */
+ sleepBlockCnt[0U] = 0U;
+ sleepBlockCnt[1U] = 0U;
+ sleepBlockCnt[2U] = 0U;
+
+#if (SLEEP_EM4_WAKEUP_CALLBACK_ENABLED == true) && defined(RMU_RSTCAUSE_EM4WURST)
+ /* Check if the Init() happened after an EM4 reset. */
+ if (RMU_ResetCauseGet() & RMU_RSTCAUSE_EM4WURST)
+ {
+ /* Clear the cause of the reset. */
+ RMU_ResetCauseClear();
+ /* Call wakeup callback with EM4 parameter. */
+ if (NULL != wakeUpCallback)
+ {
+ wakeUpCallback(sleepEM4);
+ }
+ }
+#endif
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Sets the system to sleep into the lowest possible energy mode.
+ *
+ * @details
+ * This function takes care of the system states protected by the sleep block
+ * provided by SLEEP_SleepBlockBegin() / SLEEP_SleepBlockEnd(). It allows
+ * the system to go into the lowest possible energy mode that the device can
+ * be set into at the time of the call of this function.
+ * This function will not go lower than EM3 because leaving EM4 requires
+ * resetting MCU. To enter into EM4 call SLEEP_ForceSleepInEM4().
+ *
+ * @return
+ * Energy Mode that was entered. Possible values:
+ * @li sleepEM0
+ * @li sleepEM1
+ * @li sleepEM2
+ * @li sleepEM3
+ ******************************************************************************/
+SLEEP_EnergyMode_t SLEEP_Sleep(void)
+{
+ SLEEP_EnergyMode_t allowedEM;
+
+ INT_Disable();
+
+ allowedEM = SLEEP_LowestEnergyModeGet();
+
+ if ((allowedEM >= sleepEM1) && (allowedEM <= sleepEM3))
+ {
+ SLEEP_EnterEMx(allowedEM);
+ }
+ else
+ {
+ allowedEM = sleepEM0;
+ }
+
+ INT_Enable();
+
+ return(allowedEM);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Force the device to go to EM4 without doing any checks.
+ *
+ * @details
+ * This function unblocks the low energy sleep block then goes to EM4.
+ *
+ * @note
+ * Regular RAM is not retained in EM4 and the wake up causes a reset.
+ * If the configuration option SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to
+ * true, the SLEEP_Init() function checks for the reset cause and calls the
+ * EM4 wakeup callback.
+ ******************************************************************************/
+void SLEEP_ForceSleepInEM4(void)
+{
+#if (SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED == true)
+ /* Unblock the EM2/EM3/EM4 block in the EMU. */
+ EMU_EM2UnBlock();
+#endif
+
+ /* Request entering to EM4. */
+ SLEEP_EnterEMx(sleepEM4);
+}
+
+/***************************************************************************//**
+ * @brief
+ * Begin sleep block in the requested energy mode.
+ *
+ * @details
+ * Blocking a critical system state from a certain energy mode makes sure that
+ * the system is not set to that energy mode while the block is not being
+ * released.
+ * Every SLEEP_SleepBlockBegin() increases the corresponding counter and
+ * every SLEEP_SleepBlockEnd() decreases it.
+ *
+ * Example:\code
+ * SLEEP_SleepBlockBegin(sleepEM2); // do not allow EM2 or higher
+ * // do some stuff that requires EM1 at least, like ADC sampling
+ * SLEEP_SleepBlockEnd(sleepEM2); // remove restriction for EM2\endcode
+ *
+ * @note
+ * Be aware that there is limit of maximum blocks nesting to 255.
+ *
+ * @param[in] eMode
+ * Energy mode to begin to block. Possible values:
+ * @li sleepEM1 - Begin to block the system from being set to EM1 (and EM2..4).
+ * @li sleepEM2 - Begin to block the system from being set to EM2 (and EM3/EM4).
+ * @li sleepEM3 - Begin to block the system from being set to EM3 (and EM4).
+ ******************************************************************************/
+void SLEEP_SleepBlockBegin(SLEEP_EnergyMode_t eMode)
+{
+ EFM_ASSERT((eMode >= sleepEM1) && (eMode < sleepEM4));
+ EFM_ASSERT((sleepBlockCnt[(uint8_t) eMode - 1U]) < 255U);
+
+ /* Increase the sleep block counter of the selected energy mode. */
+ sleepBlockCnt[(uint8_t) eMode - 1U]++;
+
+#if (SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED == true)
+ /* Block EM2/EM3 sleep if the EM2 block begins. */
+ if (eMode == sleepEM2)
+ {
+ EMU_EM2Block();
+ }
+#endif
+}
+
+/***************************************************************************//**
+ * @brief
+ * End sleep block in the requested energy mode.
+ *
+ * @details
+ * Release restriction for entering certain energy mode. Every call of this
+ * function reduce blocking counter by 1. Once the counter for specific energy
+ * mode is 0 and all counters for lower energy modes are 0 as well, using
+ * particular energy mode is allowed.
+ * Every SLEEP_SleepBlockBegin() increases the corresponding counter and
+ * every SLEEP_SleepBlockEnd() decreases it.
+ *
+ * Example:\code
+ * // at start all energy modes are allowed
+ * SLEEP_SleepBlockBegin(sleepEM2); // EM2, EM3, EM4 are blocked
+ * SLEEP_SleepBlockBegin(sleepEM1); // EM1, EM2, EM3, EM4 are blocked
+ * SLEEP_SleepBlockBegin(sleepEM1); // EM1, EM2, EM3, EM4 are blocked
+ * SLEEP_SleepBlockEnd(sleepEM2); // still EM1, EM2, EM3, EM4 are blocked
+ * SLEEP_SleepBlockEnd(sleepEM1); // still EM1, EM2, EM3, EM4 are blocked
+ * SLEEP_SleepBlockEnd(sleepEM1); // all energy modes are allowed now\endcode
+ *
+ * @param[in] eMode
+ * Energy mode to end to block. Possible values:
+ * @li sleepEM1 - End to block the system from being set to EM1 (and EM2..4).
+ * @li sleepEM2 - End to block the system from being set to EM2 (and EM3/EM4).
+ * @li sleepEM3 - End to block the system from being set to EM3 (and EM4).
+ ******************************************************************************/
+void SLEEP_SleepBlockEnd(SLEEP_EnergyMode_t eMode)
+{
+ EFM_ASSERT((eMode >= sleepEM1) && (eMode < sleepEM4));
+
+ /* Decrease the sleep block counter of the selected energy mode. */
+ if (sleepBlockCnt[(uint8_t) eMode - 1U] > 0U)
+ {
+ sleepBlockCnt[(uint8_t) eMode - 1U]--;
+ }
+
+#if (SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED == true)
+ /* Check if the EM2/EM3 block should be unblocked in the EMU. */
+ if (0U == sleepBlockCnt[(uint8_t) sleepEM2 - 1U])
+ {
+ EMU_EM2UnBlock();
+ }
+#endif
+}
+
+/***************************************************************************//**
+ * @brief
+ * Gets the lowest energy mode that the system is allowed to be set to.
+ *
+ * @details
+ * This function uses the low energy mode block counters to determine the
+ * lowest possible that the system is allowed to be set to.
+ *
+ * @return
+ * Lowest energy mode that the system can be set to. Possible values:
+ * @li sleepEM0
+ * @li sleepEM1
+ * @li sleepEM2
+ * @li sleepEM3
+ ******************************************************************************/
+SLEEP_EnergyMode_t SLEEP_LowestEnergyModeGet(void)
+{
+ SLEEP_EnergyMode_t tmpLowestEM = sleepEM0;
+
+ /* Check which is the lowest energy mode that the system can be set to. */
+ if (0U == sleepBlockCnt[(uint8_t) sleepEM1 - 1U])
+ {
+ tmpLowestEM = sleepEM1;
+ if (0U == sleepBlockCnt[(uint8_t) sleepEM2 - 1U])
+ {
+ tmpLowestEM = sleepEM2;
+ if (0U == sleepBlockCnt[(uint8_t) sleepEM3 - 1U])
+ {
+ tmpLowestEM = sleepEM3;
+ }
+ }
+ }
+
+ /* Compare with the default lowest energy mode setting. */
+ if (SLEEP_LOWEST_ENERGY_MODE_DEFAULT < tmpLowestEM)
+ {
+ tmpLowestEM = SLEEP_LOWEST_ENERGY_MODE_DEFAULT;
+ }
+
+ return tmpLowestEM;
+}
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+/***************************************************************************//**
+ * @brief
+ * Call the callbacks and enter the requested energy mode.
+ *
+ * @details
+ * This function is not part of the API, therefore it shall not be called by
+ * the user directly as it doesn not have any checks if the system is ready
+ * for sleep!
+ *
+ * @note
+ * The EM4 wakeup callback is not being called from this function because
+ * waking up from EM4 causes a reset.
+ * If SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to true, SLEEP_Init() function
+ * checks for the cause of the reset and calls the wakeup callback if the
+ * reset was a wakeup from EM4.
+ ******************************************************************************/
+static void SLEEP_EnterEMx(SLEEP_EnergyMode_t eMode)
+{
+ EFM_ASSERT((eMode > sleepEM0) && (eMode <= sleepEM4));
+
+ /* Call sleepCallback() before going to sleep. */
+ if (NULL != sleepCallback)
+ {
+ /* Call the callback before going to sleep. */
+ sleepCallback(eMode);
+ }
+
+ /* Enter the requested energy mode. */
+ switch (eMode)
+ {
+ case sleepEM1:
+ {
+ EMU_EnterEM1();
+ } break;
+
+ case sleepEM2:
+ {
+ EMU_EnterEM2(true);
+ } break;
+
+ case sleepEM3:
+ {
+ EMU_EnterEM3(true);
+ } break;
+
+ case sleepEM4:
+ {
+ EMU_EnterEM4();
+ } break;
+
+ default:
+ {
+ /* Don't do anything, stay in EM0. */
+ } break;
+ }
+
+ /* Call the callback after waking up from sleep. */
+ if (NULL != wakeUpCallback)
+ {
+ wakeUpCallback(eMode);
+ }
+}
+/** @endcond */
+
+/** @} (end addtogroup SLEEP */
+/** @} (end addtogroup EM_Drivers) */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_assert.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_assert.c new file mode 100644 index 000000000..9e9d99fad --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_assert.c @@ -0,0 +1,69 @@ +/***************************************************************************//**
+ * @file em_assert.c
+ * @brief Assert API
+ * @version 4.2.1
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+
+#include "em_assert.h"
+
+#if defined(DEBUG_EFM)
+
+/***************************************************************************//**
+ * @brief
+ * EFM internal assert handling.
+ *
+ * This function is invoked through EFM_ASSERT() macro usage only, it should
+ * not be used explicitly.
+ *
+ * Currently this implementation only enters an indefinite loop, allowing
+ * the use of a debugger to determine cause of failure. By defining
+ * DEBUG_EFM_USER to the preprocessor for all files, a user defined version
+ * of this function must be defined and will be invoked instead, possibly
+ * providing output of assertion location.
+ *
+ * Please notice that this function is not used unless DEBUG_EFM is defined
+ * during preprocessing of EFM_ASSERT() usage.
+ *
+ * @par file
+ * Name of source file where assertion failed.
+ *
+ * @par line
+ * Line number in source file where assertion failed.
+ ******************************************************************************/
+void assertEFM(const char *file, int line)
+{
+ (void)file; /* Unused parameter */
+ (void)line; /* Unused parameter */
+
+ while (1)
+ ;
+}
+
+#endif /* DEBUG_EFM */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_cmu.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_cmu.c new file mode 100644 index 000000000..93473ba48 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_cmu.c @@ -0,0 +1,3786 @@ +/***************************************************************************//**
+ * @file em_cmu.c
+ * @brief Clock management unit (CMU) Peripheral API
+ * @version 4.2.1
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+#include "em_cmu.h"
+#if defined( CMU_PRESENT )
+
+#include <stddef.h>
+#include <limits.h>
+#include "em_assert.h"
+#include "em_bus.h"
+#include "em_emu.h"
+#include "em_system.h"
+
+/***************************************************************************//**
+ * @addtogroup EM_Library
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup CMU
+ * @brief Clock management unit (CMU) Peripheral API
+ * @{
+ ******************************************************************************/
+
+/*******************************************************************************
+ ****************************** DEFINES ************************************
+ ******************************************************************************/
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+/** Maximum allowed core frequency when using 0 wait-states on flash access. */
+#define CMU_MAX_FREQ_0WS 26000000
+/** Maximum allowed core frequency when using 1 wait-states on flash access */
+#define CMU_MAX_FREQ_1WS 40000000
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )
+/** Maximum allowed core frequency when using 0 wait-states on flash access. */
+#define CMU_MAX_FREQ_0WS 16000000
+/** Maximum allowed core frequency when using 1 wait-states on flash access */
+#define CMU_MAX_FREQ_1WS 32000000
+#else
+#error "Unkown MCU platform."
+#endif
+
+#if defined( CMU_CTRL_HFLE )
+/** Maximum frequency for HFLE needs to be enabled on Giant, Leopard and
+ Wonder. */
+#if defined( _EFM32_WONDER_FAMILY ) \
+ || defined( _EZR32_LEOPARD_FAMILY ) \
+ || defined( _EZR32_WONDER_FAMILY )
+#define CMU_MAX_FREQ_HFLE() 24000000
+#elif defined ( _EFM32_GIANT_FAMILY )
+#define CMU_MAX_FREQ_HFLE() (maxFreqHfle())
+#else
+#error Invalid part/device.
+#endif
+#endif
+
+/*******************************************************************************
+ ************************** LOCAL VARIABLES ********************************
+ ******************************************************************************/
+
+#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )
+static CMU_AUXHFRCOFreq_TypeDef auxHfrcoFreq = cmuAUXHFRCOFreq_19M0Hz;
+#endif
+
+/** @endcond */
+
+/*******************************************************************************
+ ************************** LOCAL FUNCTIONS ********************************
+ ******************************************************************************/
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+/***************************************************************************//**
+ * @brief
+ * Get the AUX clock frequency. Used by MSC flash programming and LESENSE,
+ * by default also as debug clock.
+ *
+ * @return
+ * AUX Frequency in Hz
+ ******************************************************************************/
+static uint32_t auxClkGet(void)
+{
+ uint32_t ret;
+
+#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )
+ ret = auxHfrcoFreq;
+
+#elif defined( _CMU_AUXHFRCOCTRL_BAND_MASK )
+ /* All Geckos from TG and newer */
+ switch(CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK)
+ {
+ case CMU_AUXHFRCOCTRL_BAND_1MHZ:
+ ret = 1000000;
+ break;
+
+ case CMU_AUXHFRCOCTRL_BAND_7MHZ:
+ ret = 7000000;
+ break;
+
+ case CMU_AUXHFRCOCTRL_BAND_11MHZ:
+ ret = 11000000;
+ break;
+
+ case CMU_AUXHFRCOCTRL_BAND_14MHZ:
+ ret = 14000000;
+ break;
+
+ case CMU_AUXHFRCOCTRL_BAND_21MHZ:
+ ret = 21000000;
+ break;
+
+#if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ )
+ case CMU_AUXHFRCOCTRL_BAND_28MHZ:
+ ret = 28000000;
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ ret = 0;
+ break;
+ }
+
+#else
+ /* Gecko has a fixed 14Mhz AUXHFRCO clock */
+ ret = 14000000;
+
+#endif
+
+ return ret;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Get the Debug Trace clock frequency
+ *
+ * @return
+ * Debug Trace frequency in Hz
+ ******************************************************************************/
+static uint32_t dbgClkGet(void)
+{
+ uint32_t ret;
+ CMU_Select_TypeDef clk;
+
+ /* Get selected clock source */
+ clk = CMU_ClockSelectGet(cmuClock_DBG);
+
+ switch(clk)
+ {
+ case cmuSelect_HFCLK:
+ ret = SystemHFClockGet();
+#if defined( _CMU_CTRL_HFCLKDIV_MASK )
+ /* Family with an additional divider. */
+ ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)
+ >> _CMU_CTRL_HFCLKDIV_SHIFT));
+#endif
+ break;
+
+ case cmuSelect_AUXHFRCO:
+ ret = auxClkGet();
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Configure flash access wait states in order to support given core clock
+ * frequency.
+ *
+ * @param[in] coreFreq
+ * Core clock frequency to configure flash wait-states for
+ ******************************************************************************/
+static void flashWaitStateControl(uint32_t coreFreq)
+{
+ uint32_t mode;
+ bool mscLocked;
+#if defined( MSC_READCTRL_MODE_WS0SCBTP )
+ bool scbtpEn; /* Suppressed Conditional Branch Target Prefetch setting. */
+#endif
+
+ /* Make sure the MSC is unlocked */
+ mscLocked = MSC->LOCK;
+ MSC->LOCK = MSC_UNLOCK_CODE;
+
+ /* Get mode and SCBTP enable */
+ mode = MSC->READCTRL & _MSC_READCTRL_MODE_MASK;
+#if defined( MSC_READCTRL_MODE_WS0SCBTP )
+ switch(mode)
+ {
+ case MSC_READCTRL_MODE_WS0:
+ case MSC_READCTRL_MODE_WS1:
+#if defined( MSC_READCTRL_MODE_WS2 )
+ case MSC_READCTRL_MODE_WS2:
+#endif
+ scbtpEn = false;
+ break;
+
+ default: /* WSxSCBTP */
+ scbtpEn = true;
+ break;
+ }
+#endif
+
+
+ /* Set mode based on the core clock frequency and SCBTP enable */
+#if defined( MSC_READCTRL_MODE_WS0SCBTP )
+ if (false)
+ {
+ }
+#if defined( MSC_READCTRL_MODE_WS2 )
+ else if (coreFreq > CMU_MAX_FREQ_1WS)
+ {
+ mode = (scbtpEn ? MSC_READCTRL_MODE_WS2SCBTP : MSC_READCTRL_MODE_WS2);
+ }
+#endif
+ else if ((coreFreq <= CMU_MAX_FREQ_1WS) && (coreFreq > CMU_MAX_FREQ_0WS))
+ {
+ mode = (scbtpEn ? MSC_READCTRL_MODE_WS1SCBTP : MSC_READCTRL_MODE_WS1);
+ }
+ else
+ {
+ mode = (scbtpEn ? MSC_READCTRL_MODE_WS0SCBTP : MSC_READCTRL_MODE_WS0);
+ }
+
+#else /* If MODE and SCBTP is in separate register fields */
+
+ if (false)
+ {
+ }
+#if defined( MSC_READCTRL_MODE_WS2 )
+ else if (coreFreq > CMU_MAX_FREQ_1WS)
+ {
+ mode = MSC_READCTRL_MODE_WS2;
+ }
+#endif
+ else if ((coreFreq <= CMU_MAX_FREQ_1WS) && (coreFreq > CMU_MAX_FREQ_0WS))
+ {
+ mode = MSC_READCTRL_MODE_WS1;
+ }
+ else
+ {
+ mode = MSC_READCTRL_MODE_WS0;
+ }
+#endif
+
+ /* BUS_RegMaskedWrite cannot be used here as it would temporarely set the
+ mode field to WS0 */
+ MSC->READCTRL = (MSC->READCTRL &~_MSC_READCTRL_MODE_MASK) | mode;
+
+ if (mscLocked)
+ {
+ MSC->LOCK = 0;
+ }
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Configure flash access wait states to most conservative setting for
+ * this target. Retain SCBTP (Suppressed Conditional Branch Target Prefetch)
+ * setting.
+ ******************************************************************************/
+static void flashWaitStateMax(void)
+{
+ flashWaitStateControl(SystemMaxCoreClockGet());
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Get the LFnCLK frequency based on current configuration.
+ *
+ * @param[in] lfClkBranch
+ * Selected LF branch
+ *
+ * @return
+ * The LFnCLK frequency in Hz. If no LFnCLK is selected (disabled), 0 is
+ * returned.
+ ******************************************************************************/
+static uint32_t lfClkGet(CMU_Clock_TypeDef lfClkBranch)
+{
+ uint32_t sel;
+ uint32_t ret = 0;
+
+ switch (lfClkBranch)
+ {
+ case cmuClock_LFA:
+ case cmuClock_LFB:
+#if defined( _CMU_LFCCLKEN0_MASK )
+ case cmuClock_LFC:
+#endif
+#if defined( _CMU_LFECLKSEL_MASK )
+ case cmuClock_LFE:
+#endif
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+
+ sel = CMU_ClockSelectGet(lfClkBranch);
+
+ /* Get clock select field */
+ switch (lfClkBranch)
+ {
+ case cmuClock_LFA:
+#if defined( _CMU_LFCLKSEL_MASK )
+ sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK) >> _CMU_LFCLKSEL_LFA_SHIFT;
+#elif defined( _CMU_LFACLKSEL_MASK )
+ sel = (CMU->LFACLKSEL & _CMU_LFACLKSEL_LFA_MASK) >> _CMU_LFACLKSEL_LFA_SHIFT;
+#else
+ EFM_ASSERT(0);
+#endif
+ break;
+
+ case cmuClock_LFB:
+#if defined( _CMU_LFCLKSEL_MASK )
+ sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK) >> _CMU_LFCLKSEL_LFB_SHIFT;
+#elif defined( _CMU_LFBCLKSEL_MASK )
+ sel = (CMU->LFBCLKSEL & _CMU_LFBCLKSEL_LFB_MASK) >> _CMU_LFBCLKSEL_LFB_SHIFT;
+#else
+ EFM_ASSERT(0);
+#endif
+ break;
+
+#if defined( _CMU_LFCCLKEN0_MASK )
+ case cmuClock_LFC:
+ sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK) >> _CMU_LFCLKSEL_LFC_SHIFT;
+ break;
+#endif
+
+#if defined( _CMU_LFECLKSEL_MASK )
+ case cmuClock_LFE:
+ sel = (CMU->LFECLKSEL & _CMU_LFECLKSEL_LFE_MASK) >> _CMU_LFECLKSEL_LFE_SHIFT;
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+
+ /* Get clock frequency */
+#if defined( _CMU_LFCLKSEL_MASK )
+ switch (sel)
+ {
+ case _CMU_LFCLKSEL_LFA_LFRCO:
+ ret = SystemLFRCOClockGet();
+ break;
+
+ case _CMU_LFCLKSEL_LFA_LFXO:
+ ret = SystemLFXOClockGet();
+ break;
+
+#if defined( _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2 )
+ case _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:
+#if defined( CMU_CTRL_HFLE )
+ /* Family which can use an extra div 4 divider */
+ /* (and must if >32MHz) or HFLE is set. */
+ if(((CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK)
+ == CMU_HFCORECLKDIV_HFCORECLKLEDIV_DIV4)
+ || (CMU->CTRL & CMU_CTRL_HFLE))
+ {
+ ret = SystemCoreClockGet() / 4U;
+ }
+ else
+ {
+ ret = SystemCoreClockGet() / 2U;
+ }
+#else
+ ret = SystemCoreClockGet() / 2U;
+#endif
+ break;
+#endif
+
+ case _CMU_LFCLKSEL_LFA_DISABLED:
+ ret = 0;
+#if defined( CMU_LFCLKSEL_LFAE )
+ /* Check LF Extended bit setting for LFA or LFB ULFRCO clock */
+ if ((lfClkBranch == cmuClock_LFA) || (lfClkBranch == cmuClock_LFB))
+ {
+ if (CMU->LFCLKSEL >> (lfClkBranch == cmuClock_LFA
+ ? _CMU_LFCLKSEL_LFAE_SHIFT
+ : _CMU_LFCLKSEL_LFBE_SHIFT))
+ {
+ ret = SystemULFRCOClockGet();
+ }
+ }
+#endif
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ ret = 0U;
+ break;
+ }
+#endif /* _CMU_LFCLKSEL_MASK */
+
+#if defined( _CMU_LFACLKSEL_MASK )
+ switch (sel)
+ {
+ case _CMU_LFACLKSEL_LFA_LFRCO:
+ ret = SystemLFRCOClockGet();
+ break;
+
+ case _CMU_LFACLKSEL_LFA_LFXO:
+ ret = SystemLFXOClockGet();
+ break;
+
+ case _CMU_LFACLKSEL_LFA_ULFRCO:
+ ret = SystemULFRCOClockGet();
+ break;
+
+#if defined( _CMU_LFACLKSEL_LFA_HFCLKLE )
+ case _CMU_LFACLKSEL_LFA_HFCLKLE:
+ ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK)
+ == CMU_HFPRESC_HFCLKLEPRESC_DIV4)
+ ? SystemCoreClockGet() / 4U
+ : SystemCoreClockGet() / 2U;
+ break;
+#elif defined( _CMU_LFBCLKSEL_LFB_HFCLKLE )
+ case _CMU_LFBCLKSEL_LFB_HFCLKLE:
+ ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK)
+ == CMU_HFPRESC_HFCLKLEPRESC_DIV4)
+ ? SystemCoreClockGet() / 4U
+ : SystemCoreClockGet() / 2U;
+ break;
+#endif
+
+ case _CMU_LFACLKSEL_LFA_DISABLED:
+ ret = 0;
+ break;
+ }
+#endif
+
+ return ret;
+}
+
+
+#if defined( CMU_CTRL_HFLE ) \
+ && !defined( _EFM32_WONDER_FAMILY ) \
+ && !defined( _EZR32_LEOPARD_FAMILY ) \
+ && !defined( _EZR32_WONDER_FAMILY )
+/***************************************************************************//**
+ * @brief
+ * Return max allowed frequency for low energy peripherals.
+ ******************************************************************************/
+static uint32_t maxFreqHfle(void)
+{
+ uint16_t majorMinorRev;
+
+ switch (SYSTEM_GetFamily())
+ {
+ case systemPartFamilyEfm32Leopard:
+ /* CHIP MAJOR bit [5:0] */
+ majorMinorRev = (((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK)
+ >> _ROMTABLE_PID0_REVMAJOR_SHIFT) << 8);
+ /* CHIP MINOR bit [7:4] */
+ majorMinorRev |= (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK)
+ >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);
+ /* CHIP MINOR bit [3:0] */
+ majorMinorRev |= ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK)
+ >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);
+
+ if (majorMinorRev >= 0x0204)
+ return 24000000;
+ else
+ return 32000000;
+
+ case systemPartFamilyEfm32Giant:
+ return 32000000;
+
+ default:
+ /* Invalid device family. */
+ EFM_ASSERT(false);
+ return 0;
+ }
+}
+#endif
+
+
+/***************************************************************************//**
+ * @brief
+ * Wait for ongoing sync of register(s) to low frequency domain to complete.
+ *
+ * @param[in] mask
+ * Bitmask corresponding to SYNCBUSY register defined bits, indicating
+ * registers that must complete any ongoing synchronization.
+ ******************************************************************************/
+__STATIC_INLINE void syncReg(uint32_t mask)
+{
+ /* Avoid deadlock if modifying the same register twice when freeze mode is */
+ /* activated. */
+ if (CMU->FREEZE & CMU_FREEZE_REGFREEZE)
+ return;
+
+ /* Wait for any pending previous write operation to have been completed */
+ /* in low frequency domain */
+ while (CMU->SYNCBUSY & mask)
+ {
+ }
+}
+
+
+#if defined(USB_PRESENT)
+/***************************************************************************//**
+ * @brief
+ * Get the USBC frequency
+ *
+ * @return
+ * USBC frequency in Hz
+ ******************************************************************************/
+static uint32_t usbCClkGet(void)
+{
+ uint32_t ret;
+ CMU_Select_TypeDef clk;
+
+ /* Get selected clock source */
+ clk = CMU_ClockSelectGet(cmuClock_USBC);
+
+ switch(clk)
+ {
+ case cmuSelect_LFXO:
+ ret = SystemLFXOClockGet();
+ break;
+ case cmuSelect_LFRCO:
+ ret = SystemLFRCOClockGet();
+ break;
+ case cmuSelect_HFCLK:
+ ret = SystemHFClockGet();
+ break;
+ default:
+ /* Clock is not enabled */
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+#endif
+
+
+/** @endcond */
+
+/*******************************************************************************
+ ************************** GLOBAL FUNCTIONS *******************************
+ ******************************************************************************/
+
+#if defined( _CMU_AUXHFRCOCTRL_BAND_MASK )
+/***************************************************************************//**
+ * @brief
+ * Get AUXHFRCO band in use.
+ *
+ * @return
+ * AUXHFRCO band in use.
+ ******************************************************************************/
+CMU_AUXHFRCOBand_TypeDef CMU_AUXHFRCOBandGet(void)
+{
+ return (CMU_AUXHFRCOBand_TypeDef)((CMU->AUXHFRCOCTRL
+ & _CMU_AUXHFRCOCTRL_BAND_MASK)
+ >> _CMU_AUXHFRCOCTRL_BAND_SHIFT);
+}
+#endif /* _CMU_AUXHFRCOCTRL_BAND_MASK */
+
+
+#if defined( _CMU_AUXHFRCOCTRL_BAND_MASK )
+/***************************************************************************//**
+ * @brief
+ * Set AUXHFRCO band and the tuning value based on the value in the
+ * calibration table made during production.
+ *
+ * @param[in] band
+ * AUXHFRCO band to activate.
+ ******************************************************************************/
+void CMU_AUXHFRCOBandSet(CMU_AUXHFRCOBand_TypeDef band)
+{
+ uint32_t tuning;
+
+ /* Read tuning value from calibration table */
+ switch (band)
+ {
+ case cmuAUXHFRCOBand_1MHz:
+ tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND1_MASK)
+ >> _DEVINFO_AUXHFRCOCAL0_BAND1_SHIFT;
+ break;
+
+ case cmuAUXHFRCOBand_7MHz:
+ tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND7_MASK)
+ >> _DEVINFO_AUXHFRCOCAL0_BAND7_SHIFT;
+ break;
+
+ case cmuAUXHFRCOBand_11MHz:
+ tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND11_MASK)
+ >> _DEVINFO_AUXHFRCOCAL0_BAND11_SHIFT;
+ break;
+
+ case cmuAUXHFRCOBand_14MHz:
+ tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND14_MASK)
+ >> _DEVINFO_AUXHFRCOCAL0_BAND14_SHIFT;
+ break;
+
+ case cmuAUXHFRCOBand_21MHz:
+ tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND21_MASK)
+ >> _DEVINFO_AUXHFRCOCAL1_BAND21_SHIFT;
+ break;
+
+#if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ )
+ case cmuAUXHFRCOBand_28MHz:
+ tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND28_MASK)
+ >> _DEVINFO_AUXHFRCOCAL1_BAND28_SHIFT;
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ return;
+ }
+
+ /* Set band/tuning */
+ CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL &
+ ~(_CMU_AUXHFRCOCTRL_BAND_MASK
+ | _CMU_AUXHFRCOCTRL_TUNING_MASK))
+ | (band << _CMU_AUXHFRCOCTRL_BAND_SHIFT)
+ | (tuning << _CMU_AUXHFRCOCTRL_TUNING_SHIFT);
+
+}
+#endif /* _CMU_AUXHFRCOCTRL_BAND_MASK */
+
+
+#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )
+/**************************************************************************//**
+ * @brief
+ * Get a pointer to the AUXHFRCO frequency calibration word in DEVINFO
+ *
+ * @param[in] freq
+ * Frequency in Hz
+ *
+ * @return
+ * AUXHFRCO calibration word for a given frequency
+ *****************************************************************************/
+static uint32_t CMU_AUXHFRCODevinfoGet(CMU_AUXHFRCOFreq_TypeDef freq)
+{
+ switch (freq)
+ {
+ /* 1, 2 and 4MHz share the same calibration word */
+ case cmuAUXHFRCOFreq_1M0Hz:
+ case cmuAUXHFRCOFreq_2M0Hz:
+ case cmuAUXHFRCOFreq_4M0Hz:
+ return DEVINFO->AUXHFRCOCAL0;
+
+ case cmuAUXHFRCOFreq_7M0Hz:
+ return DEVINFO->AUXHFRCOCAL3;
+
+ case cmuAUXHFRCOFreq_13M0Hz:
+ return DEVINFO->AUXHFRCOCAL6;
+
+ case cmuAUXHFRCOFreq_16M0Hz:
+ return DEVINFO->AUXHFRCOCAL7;
+
+ case cmuAUXHFRCOFreq_19M0Hz:
+ return DEVINFO->AUXHFRCOCAL8;
+
+ case cmuAUXHFRCOFreq_26M0Hz:
+ return DEVINFO->AUXHFRCOCAL10;
+
+ case cmuAUXHFRCOFreq_32M0Hz:
+ return DEVINFO->AUXHFRCOCAL11;
+
+ case cmuAUXHFRCOFreq_38M0Hz:
+ return DEVINFO->AUXHFRCOCAL12;
+
+ default: /* cmuAUXHFRCOFreq_UserDefined */
+ return 0;
+ }
+}
+#endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */
+
+
+#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )
+/***************************************************************************//**
+ * @brief
+ * Get AUXHFRCO frequency enumeration in use
+ *
+ * @return
+ * AUXHFRCO frequency enumeration in use
+ ******************************************************************************/
+CMU_AUXHFRCOFreq_TypeDef CMU_AUXHFRCOFreqGet(void)
+{
+ return auxHfrcoFreq;
+}
+#endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */
+
+
+#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )
+/***************************************************************************//**
+ * @brief
+ * Set AUXHFRCO calibration for the selected target frequency
+ *
+ * @param[in] frequency
+ * AUXHFRCO frequency to set
+ ******************************************************************************/
+void CMU_AUXHFRCOFreqSet(CMU_AUXHFRCOFreq_TypeDef freq)
+{
+ uint32_t freqCal;
+
+ /* Get DEVINFO index, set global auxHfrcoFreq */
+ freqCal = CMU_AUXHFRCODevinfoGet(freq);
+ EFM_ASSERT((freqCal != 0) && (freqCal != UINT_MAX));
+ auxHfrcoFreq = freq;
+
+ /* Wait for any previous sync to complete, and then set calibration data
+ for the selected frequency. */
+ while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_AUXHFRCOBSY_SHIFT));
+
+ /* Set divider in AUXHFRCOCTRL for 1, 2 and 4MHz */
+ switch(freq)
+ {
+ case cmuAUXHFRCOFreq_1M0Hz:
+ freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)
+ | CMU_AUXHFRCOCTRL_CLKDIV_DIV4;
+ break;
+
+ case cmuAUXHFRCOFreq_2M0Hz:
+ freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)
+ | CMU_AUXHFRCOCTRL_CLKDIV_DIV2;
+ break;
+
+ case cmuAUXHFRCOFreq_4M0Hz:
+ freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)
+ | CMU_AUXHFRCOCTRL_CLKDIV_DIV1;
+ break;
+
+ default:
+ break;
+ }
+ CMU->AUXHFRCOCTRL = freqCal;
+}
+#endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */
+
+
+/***************************************************************************//**
+ * @brief
+ * Calibrate clock.
+ *
+ * @details
+ * Run a calibration for HFCLK against a selectable reference clock. Please
+ * refer to the reference manual, CMU chapter, for further details.
+ *
+ * @note
+ * This function will not return until calibration measurement is completed.
+ *
+ * @param[in] HFCycles
+ * The number of HFCLK cycles to run calibration. Increasing this number
+ * increases precision, but the calibration will take more time.
+ *
+ * @param[in] ref
+ * The reference clock used to compare HFCLK with.
+ *
+ * @return
+ * The number of ticks the reference clock after HFCycles ticks on the HF
+ * clock.
+ ******************************************************************************/
+uint32_t CMU_Calibrate(uint32_t HFCycles, CMU_Osc_TypeDef ref)
+{
+ EFM_ASSERT(HFCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));
+
+ /* Set reference clock source */
+ switch (ref)
+ {
+ case cmuOsc_LFXO:
+ CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFXO;
+ break;
+
+ case cmuOsc_LFRCO:
+ CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFRCO;
+ break;
+
+ case cmuOsc_HFXO:
+ CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFXO;
+ break;
+
+ case cmuOsc_HFRCO:
+ CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFRCO;
+ break;
+
+ case cmuOsc_AUXHFRCO:
+ CMU->CALCTRL = CMU_CALCTRL_UPSEL_AUXHFRCO;
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ return 0;
+ }
+
+ /* Set top value */
+ CMU->CALCNT = HFCycles;
+
+ /* Start calibration */
+ CMU->CMD = CMU_CMD_CALSTART;
+
+#if defined( CMU_STATUS_CALRDY )
+ /* Wait until calibration completes */
+ while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALRDY_SHIFT))
+ {
+ }
+#else
+ /* Wait until calibration completes */
+ while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT))
+ {
+ }
+#endif
+
+ return CMU->CALCNT;
+}
+
+
+#if defined( _CMU_CALCTRL_UPSEL_MASK ) && defined( _CMU_CALCTRL_DOWNSEL_MASK )
+/***************************************************************************//**
+ * @brief
+ * Configure clock calibration
+ *
+ * @details
+ * Configure a calibration for a selectable clock source against another
+ * selectable reference clock.
+ * Refer to the reference manual, CMU chapter, for further details.
+ *
+ * @note
+ * After configuration, a call to CMU_CalibrateStart() is required, and
+ * the resulting calibration value can be read out with the
+ * CMU_CalibrateCountGet() function call.
+ *
+ * @param[in] downCycles
+ * The number of downSel clock cycles to run calibration. Increasing this
+ * number increases precision, but the calibration will take more time.
+ *
+ * @param[in] downSel
+ * The clock which will be counted down downCycles
+ *
+ * @param[in] upSel
+ * The reference clock, the number of cycles generated by this clock will
+ * be counted and added up, the result can be given with the
+ * CMU_CalibrateCountGet() function call.
+ ******************************************************************************/
+void CMU_CalibrateConfig(uint32_t downCycles, CMU_Osc_TypeDef downSel,
+ CMU_Osc_TypeDef upSel)
+{
+ /* Keep untouched configuration settings */
+ uint32_t calCtrl = CMU->CALCTRL
+ & ~(_CMU_CALCTRL_UPSEL_MASK | _CMU_CALCTRL_DOWNSEL_MASK);
+
+ /* 20 bits of precision to calibration count register */
+ EFM_ASSERT(downCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));
+
+ /* Set down counting clock source - down counter */
+ switch (downSel)
+ {
+ case cmuOsc_LFXO:
+ calCtrl |= CMU_CALCTRL_DOWNSEL_LFXO;
+ break;
+
+ case cmuOsc_LFRCO:
+ calCtrl |= CMU_CALCTRL_DOWNSEL_LFRCO;
+ break;
+
+ case cmuOsc_HFXO:
+ calCtrl |= CMU_CALCTRL_DOWNSEL_HFXO;
+ break;
+
+ case cmuOsc_HFRCO:
+ calCtrl |= CMU_CALCTRL_DOWNSEL_HFRCO;
+ break;
+
+ case cmuOsc_AUXHFRCO:
+ calCtrl |= CMU_CALCTRL_DOWNSEL_AUXHFRCO;
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+
+ /* Set top value to be counted down by the downSel clock */
+ CMU->CALCNT = downCycles;
+
+ /* Set reference clock source - up counter */
+ switch (upSel)
+ {
+ case cmuOsc_LFXO:
+ calCtrl |= CMU_CALCTRL_UPSEL_LFXO;
+ break;
+
+ case cmuOsc_LFRCO:
+ calCtrl |= CMU_CALCTRL_UPSEL_LFRCO;
+ break;
+
+ case cmuOsc_HFXO:
+ calCtrl |= CMU_CALCTRL_UPSEL_HFXO;
+ break;
+
+ case cmuOsc_HFRCO:
+ calCtrl |= CMU_CALCTRL_UPSEL_HFRCO;
+ break;
+
+ case cmuOsc_AUXHFRCO:
+ calCtrl |= CMU_CALCTRL_UPSEL_AUXHFRCO;
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+
+ CMU->CALCTRL = calCtrl;
+}
+#endif
+
+
+/***************************************************************************//**
+ * @brief
+ * Get calibration count register
+ * @note
+ * If continuous calibrartion mode is active, calibration busy will almost
+ * always be off, and we just need to read the value, where the normal case
+ * would be that this function call has been triggered by the CALRDY
+ * interrupt flag.
+ * @return
+ * Calibration count, the number of UPSEL clocks (see CMU_CalibrateConfig)
+ * in the period of DOWNSEL oscillator clock cycles configured by a previous
+ * write operation to CMU->CALCNT
+ ******************************************************************************/
+uint32_t CMU_CalibrateCountGet(void)
+{
+ /* Wait until calibration completes, UNLESS continuous calibration mode is */
+ /* active */
+#if defined( CMU_CALCTRL_CONT )
+ if (!BUS_RegBitRead(&CMU->CALCTRL, _CMU_CALCTRL_CONT_SHIFT))
+ {
+#if defined( CMU_STATUS_CALRDY )
+ /* Wait until calibration completes */
+ while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALRDY_SHIFT))
+ {
+ }
+#else
+ /* Wait until calibration completes */
+ while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT))
+ {
+ }
+#endif
+ }
+#else
+ while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT))
+ {
+ }
+#endif
+ return CMU->CALCNT;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Get clock divisor/prescaler.
+ *
+ * @param[in] clock
+ * Clock point to get divisor/prescaler for. Notice that not all clock points
+ * have a divisor/prescaler. Please refer to CMU overview in reference manual.
+ *
+ * @return
+ * The current clock point divisor/prescaler. 1 is returned
+ * if @p clock specifies a clock point without a divisor/prescaler.
+ ******************************************************************************/
+CMU_ClkDiv_TypeDef CMU_ClockDivGet(CMU_Clock_TypeDef clock)
+{
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ return 1 + (uint32_t)CMU_ClockPrescGet(clock);
+
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )
+ uint32_t divReg;
+ CMU_ClkDiv_TypeDef ret;
+
+ /* Get divisor reg id */
+ divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;
+
+ switch (divReg)
+ {
+#if defined( _CMU_CTRL_HFCLKDIV_MASK )
+ case CMU_HFCLKDIV_REG:
+ ret = 1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)
+ >> _CMU_CTRL_HFCLKDIV_SHIFT);
+ break;
+#endif
+
+ case CMU_HFPERCLKDIV_REG:
+ ret = (CMU_ClkDiv_TypeDef)((CMU->HFPERCLKDIV
+ & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)
+ >> _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);
+ ret = CMU_Log2ToDiv(ret);
+ break;
+
+ case CMU_HFCORECLKDIV_REG:
+ ret = (CMU_ClkDiv_TypeDef)((CMU->HFCORECLKDIV
+ & _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK)
+ >> _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);
+ ret = CMU_Log2ToDiv(ret);
+ break;
+
+ case CMU_LFAPRESC0_REG:
+ switch (clock)
+ {
+ case cmuClock_RTC:
+ ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK)
+ >> _CMU_LFAPRESC0_RTC_SHIFT);
+ ret = CMU_Log2ToDiv(ret);
+ break;
+
+#if defined(_CMU_LFAPRESC0_LETIMER0_MASK)
+ case cmuClock_LETIMER0:
+ ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)
+ >> _CMU_LFAPRESC0_LETIMER0_SHIFT);
+ ret = CMU_Log2ToDiv(ret);
+ break;
+#endif
+
+#if defined(_CMU_LFAPRESC0_LCD_MASK)
+ case cmuClock_LCDpre:
+ ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)
+ >> _CMU_LFAPRESC0_LCD_SHIFT)
+ + CMU_DivToLog2(cmuClkDiv_16));
+ ret = CMU_Log2ToDiv(ret);
+ break;
+#endif
+
+#if defined(_CMU_LFAPRESC0_LESENSE_MASK)
+ case cmuClock_LESENSE:
+ ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK)
+ >> _CMU_LFAPRESC0_LESENSE_SHIFT);
+ ret = CMU_Log2ToDiv(ret);
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ ret = cmuClkDiv_1;
+ break;
+ }
+ break;
+
+ case CMU_LFBPRESC0_REG:
+ switch (clock)
+ {
+#if defined(_CMU_LFBPRESC0_LEUART0_MASK)
+ case cmuClock_LEUART0:
+ ret = (CMU_ClkDiv_TypeDef)((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)
+ >> _CMU_LFBPRESC0_LEUART0_SHIFT);
+ ret = CMU_Log2ToDiv(ret);
+ break;
+#endif
+
+#if defined(_CMU_LFBPRESC0_LEUART1_MASK)
+ case cmuClock_LEUART1:
+ ret = (CMU_ClkDiv_TypeDef)((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)
+ >> _CMU_LFBPRESC0_LEUART1_SHIFT);
+ ret = CMU_Log2ToDiv(ret);
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ ret = cmuClkDiv_1;
+ break;
+ }
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ ret = cmuClkDiv_1;
+ break;
+ }
+
+ return ret;
+#endif
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Set clock divisor/prescaler.
+ *
+ * @note
+ * If setting a LF clock prescaler, synchronization into the low frequency
+ * domain is required. If the same register is modified before a previous
+ * update has completed, this function will stall until the previous
+ * synchronization has completed. Please refer to CMU_FreezeEnable() for
+ * a suggestion on how to reduce stalling time in some use cases.
+ *
+ * @param[in] clock
+ * Clock point to set divisor/prescaler for. Notice that not all clock points
+ * have a divisor/prescaler, please refer to CMU overview in the reference
+ * manual.
+ *
+ * @param[in] div
+ * The clock divisor to use (<= cmuClkDiv_512).
+ ******************************************************************************/
+void CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div)
+{
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ CMU_ClockPrescSet(clock, (CMU_ClkPresc_TypeDef)(div - 1));
+
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )
+ uint32_t freq;
+ uint32_t divReg;
+
+ /* Get divisor reg id */
+ divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;
+
+ switch (divReg)
+ {
+#if defined( _CMU_CTRL_HFCLKDIV_MASK )
+ case CMU_HFCLKDIV_REG:
+ EFM_ASSERT((div>=cmuClkDiv_1) && (div<=cmuClkDiv_8));
+
+ /* Configure worst case wait states for flash access before setting divisor */
+ flashWaitStateMax();
+
+ /* Set divider */
+ CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFCLKDIV_MASK)
+ | ((div-1) << _CMU_CTRL_HFCLKDIV_SHIFT);
+
+ /* Update CMSIS core clock variable */
+ /* (The function will update the global variable) */
+ freq = SystemCoreClockGet();
+
+ /* Optimize flash access wait state setting for current core clk */
+ flashWaitStateControl(freq);
+ break;
+#endif
+
+ case CMU_HFPERCLKDIV_REG:
+ EFM_ASSERT((div >= cmuClkDiv_1) && (div <= cmuClkDiv_512));
+ /* Convert to correct scale */
+ div = CMU_DivToLog2(div);
+ CMU->HFPERCLKDIV = (CMU->HFPERCLKDIV & ~_CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)
+ | (div << _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);
+ break;
+
+ case CMU_HFCORECLKDIV_REG:
+ EFM_ASSERT(div <= cmuClkDiv_512);
+
+ /* Configure worst case wait states for flash access before setting divisor */
+ flashWaitStateMax();
+
+#if defined( CMU_CTRL_HFLE )
+ /* Clear HFLE and set DIV2 factor for peripheral clock
+ when running at frequencies lower than or equal to CMU_MAX_FREQ_HFLE. */
+ if ((CMU_ClockFreqGet(cmuClock_HF) / div) <= CMU_MAX_FREQ_HFLE())
+ {
+ /* Clear CMU HFLE */
+ BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 0);
+
+ /* Set DIV2 factor for peripheral clock */
+ BUS_RegBitWrite(&CMU->HFCORECLKDIV,
+ _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 0);
+ }
+ else
+ {
+ /* Set CMU HFLE */
+ BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1);
+
+ /* Set DIV4 factor for peripheral clock */
+ BUS_RegBitWrite(&CMU->HFCORECLKDIV,
+ _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);
+ }
+#endif
+
+ /* Convert to correct scale */
+ div = CMU_DivToLog2(div);
+
+ CMU->HFCORECLKDIV = (CMU->HFCORECLKDIV
+ & ~_CMU_HFCORECLKDIV_HFCORECLKDIV_MASK)
+ | (div << _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);
+
+ /* Update CMSIS core clock variable */
+ /* (The function will update the global variable) */
+ freq = SystemCoreClockGet();
+
+ /* Optimize flash access wait state setting for current core clk */
+ flashWaitStateControl(freq);
+ break;
+
+ case CMU_LFAPRESC0_REG:
+ switch (clock)
+ {
+ case cmuClock_RTC:
+ EFM_ASSERT(div <= cmuClkDiv_32768);
+
+ /* LF register about to be modified require sync. busy check */
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);
+
+ /* Convert to correct scale */
+ div = CMU_DivToLog2(div);
+
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK)
+ | (div << _CMU_LFAPRESC0_RTC_SHIFT);
+ break;
+
+#if defined(_CMU_LFAPRESC0_LETIMER0_MASK)
+ case cmuClock_LETIMER0:
+ EFM_ASSERT(div <= cmuClkDiv_32768);
+
+ /* LF register about to be modified require sync. busy check */
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);
+
+ /* Convert to correct scale */
+ div = CMU_DivToLog2(div);
+
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK)
+ | (div << _CMU_LFAPRESC0_LETIMER0_SHIFT);
+ break;
+#endif
+
+#if defined(LCD_PRESENT)
+ case cmuClock_LCDpre:
+ EFM_ASSERT((div >= cmuClkDiv_16) && (div <= cmuClkDiv_128));
+
+ /* LF register about to be modified require sync. busy check */
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);
+
+ /* Convert to correct scale */
+ div = CMU_DivToLog2(div);
+
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LCD_MASK)
+ | ((div - CMU_DivToLog2(cmuClkDiv_16))
+ << _CMU_LFAPRESC0_LCD_SHIFT);
+ break;
+#endif /* defined(LCD_PRESENT) */
+
+#if defined(LESENSE_PRESENT)
+ case cmuClock_LESENSE:
+ EFM_ASSERT(div <= cmuClkDiv_8);
+
+ /* LF register about to be modified require sync. busy check */
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);
+
+ /* Convert to correct scale */
+ div = CMU_DivToLog2(div);
+
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LESENSE_MASK)
+ | (div << _CMU_LFAPRESC0_LESENSE_SHIFT);
+ break;
+#endif /* defined(LESENSE_PRESENT) */
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+ break;
+
+ case CMU_LFBPRESC0_REG:
+ switch (clock)
+ {
+#if defined(_CMU_LFBPRESC0_LEUART0_MASK)
+ case cmuClock_LEUART0:
+ EFM_ASSERT(div <= cmuClkDiv_8);
+
+ /* LF register about to be modified require sync. busy check */
+ syncReg(CMU_SYNCBUSY_LFBPRESC0);
+
+ /* Convert to correct scale */
+ div = CMU_DivToLog2(div);
+
+ CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK)
+ | (((uint32_t)div) << _CMU_LFBPRESC0_LEUART0_SHIFT);
+ break;
+#endif
+
+#if defined(_CMU_LFBPRESC0_LEUART1_MASK)
+ case cmuClock_LEUART1:
+ EFM_ASSERT(div <= cmuClkDiv_8);
+
+ /* LF register about to be modified require sync. busy check */
+ syncReg(CMU_SYNCBUSY_LFBPRESC0);
+
+ /* Convert to correct scale */
+ div = CMU_DivToLog2(div);
+
+ CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK)
+ | (((uint32_t)div) << _CMU_LFBPRESC0_LEUART1_SHIFT);
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+#endif
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Enable/disable a clock.
+ *
+ * @details
+ * In general, module clocking is disabled after a reset. If a module
+ * clock is disabled, the registers of that module are not accessible and
+ * reading from such registers may return undefined values. Writing to
+ * registers of clock disabled modules have no effect. One should normally
+ * avoid accessing module registers of a module with a disabled clock.
+ *
+ * @note
+ * If enabling/disabling a LF clock, synchronization into the low frequency
+ * domain is required. If the same register is modified before a previous
+ * update has completed, this function will stall until the previous
+ * synchronization has completed. Please refer to CMU_FreezeEnable() for
+ * a suggestion on how to reduce stalling time in some use cases.
+ *
+ * @param[in] clock
+ * The clock to enable/disable. Notice that not all defined clock
+ * points have separate enable/disable control, please refer to CMU overview
+ * in reference manual.
+ *
+ * @param[in] enable
+ * @li true - enable specified clock.
+ * @li false - disable specified clock.
+ ******************************************************************************/
+void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
+{
+ volatile uint32_t *reg;
+ uint32_t bit;
+ uint32_t sync = 0;
+
+ /* Identify enable register */
+ switch ((clock >> CMU_EN_REG_POS) & CMU_EN_REG_MASK)
+ {
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ case CMU_CTRL_EN_REG:
+ reg = &CMU->CTRL;
+ break;
+#endif
+
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )
+ case CMU_HFCORECLKEN0_EN_REG:
+ reg = &CMU->HFCORECLKEN0;
+#if defined( CMU_CTRL_HFLE )
+ /* Set HFLE and DIV4 factor for peripheral clock when
+ running at frequencies higher than or equal to CMU_MAX_FREQ_HFLE. */
+ if ( CMU_ClockFreqGet(cmuClock_CORE) > CMU_MAX_FREQ_HFLE())
+ {
+ /* Enable CMU HFLE */
+ BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1);
+
+ /* Set DIV4 factor for peripheral clock */
+ BUS_RegBitWrite(&CMU->HFCORECLKDIV,
+ _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);
+ }
+#endif
+ break;
+#endif
+
+#if defined( _CMU_HFBUSCLKEN0_MASK )
+ case CMU_HFBUSCLKEN0_EN_REG:
+ reg = &CMU->HFBUSCLKEN0;
+ break;
+#endif
+
+#if defined( _CMU_HFRADIOCLKEN0_MASK )
+ case CMU_HFRADIOCLKEN0_EN_REG:
+ reg = &CMU->HFRADIOCLKEN0;
+ break;
+#endif
+
+#if defined( _CMU_HFPERCLKDIV_MASK )
+ case CMU_HFPERCLKDIV_EN_REG:
+ reg = &CMU->HFPERCLKDIV;
+ break;
+#endif
+
+ case CMU_HFPERCLKEN0_EN_REG:
+ reg = &CMU->HFPERCLKEN0;
+ break;
+
+ case CMU_LFACLKEN0_EN_REG:
+ reg = &CMU->LFACLKEN0;
+ sync = CMU_SYNCBUSY_LFACLKEN0;
+ break;
+
+ case CMU_LFBCLKEN0_EN_REG:
+ reg = &CMU->LFBCLKEN0;
+ sync = CMU_SYNCBUSY_LFBCLKEN0;
+ break;
+
+#if defined( _CMU_LFCCLKEN0_MASK )
+ case CMU_LFCCLKEN0_EN_REG:
+ reg = &CMU->LFCCLKEN0;
+ sync = CMU_SYNCBUSY_LFCCLKEN0;
+ break;
+#endif
+
+#if defined( _CMU_LFECLKEN0_MASK )
+ case CMU_LFECLKEN0_EN_REG:
+ reg = &CMU->LFECLKEN0;
+ sync = CMU_SYNCBUSY_LFECLKEN0;
+ break;
+#endif
+
+ case CMU_PCNT_EN_REG:
+ reg = &CMU->PCNTCTRL;
+ break;
+
+ default: /* Cannot enable/disable clock point */
+ EFM_ASSERT(0);
+ return;
+ }
+
+ /* Get bit position used to enable/disable */
+ bit = (clock >> CMU_EN_BIT_POS) & CMU_EN_BIT_MASK;
+
+ /* LF synchronization required? */
+ if (sync)
+ {
+ syncReg(sync);
+ }
+
+ /* Set/clear bit as requested */
+ BUS_RegBitWrite(reg, bit, enable);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Get clock frequency for a clock point.
+ *
+ * @param[in] clock
+ * Clock point to fetch frequency for.
+ *
+ * @return
+ * The current frequency in Hz.
+ ******************************************************************************/
+uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)
+{
+ uint32_t ret;
+
+ switch(clock & (CMU_CLK_BRANCH_MASK << CMU_CLK_BRANCH_POS))
+ {
+ case (CMU_HF_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = SystemHFClockGet();
+#if defined( _CMU_CTRL_HFCLKDIV_MASK )
+ /* Family with an additional divider. */
+ ret = ret / (1U + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)
+ >> _CMU_CTRL_HFCLKDIV_SHIFT));
+#endif
+#if defined( _CMU_HFPRESC_MASK )
+ ret = ret / (1U + ((CMU->HFPRESC & _CMU_HFPRESC_PRESC_MASK)
+ >> _CMU_HFPRESC_PRESC_SHIFT));
+#endif
+ break;
+
+ case (CMU_HFPER_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = SystemHFClockGet();
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )
+#if defined( _CMU_CTRL_HFCLKDIV_MASK )
+ /* Family with an additional divider. */
+ ret = ret / (1U + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)
+ >> _CMU_CTRL_HFCLKDIV_SHIFT));
+#endif
+ ret >>= (CMU->HFPERCLKDIV & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)
+ >> _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT;
+#elif defined( _SILICON_LABS_32B_PLATFORM_2 )
+ ret /= 1U + ((CMU->HFPERPRESC & _CMU_HFPERPRESC_PRESC_MASK)
+ >> _CMU_HFPERPRESC_PRESC_SHIFT);
+#endif
+ break;
+
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+#if defined( _CMU_HFRADIOPRESC_PRESC_MASK )
+ case (CMU_HFRADIO_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = SystemHFClockGet();
+ ret /= 1U + ((CMU->HFRADIOPRESC & _CMU_HFRADIOPRESC_PRESC_MASK)
+ >> _CMU_HFRADIOPRESC_PRESC_SHIFT);
+ break;
+#endif
+
+#if defined( CRYPTO_PRESENT ) \
+ || defined( LDMA_PRESENT ) \
+ || defined( GPCRC_PRESENT ) \
+ || defined( PRS_PRESENT ) \
+ || defined( GPIO_PRESENT )
+ case (CMU_HFBUS_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = SystemHFClockGet();
+ break;
+#endif
+
+ case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = SystemHFClockGet();
+ ret /= 1U + ((CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK)
+ >> _CMU_HFCOREPRESC_PRESC_SHIFT);
+ break;
+
+ case (CMU_HFEXP_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = SystemHFClockGet();
+ ret /= 1U + ((CMU->HFEXPPRESC & _CMU_HFEXPPRESC_PRESC_MASK)
+ >> _CMU_HFEXPPRESC_PRESC_SHIFT);
+ break;
+#endif
+
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )
+#if defined(AES_PRESENT) \
+ || defined(DMA_PRESENT) \
+ || defined(EBI_PRESENT) \
+ || defined(USB_PRESENT)
+ case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ {
+ ret = SystemCoreClockGet();
+ } break;
+#endif
+#endif
+
+ case (CMU_LFA_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = lfClkGet(cmuClock_LFA);
+ break;
+
+#if defined( _CMU_LFACLKEN0_RTC_MASK )
+ case (CMU_RTC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = lfClkGet(cmuClock_LFA);
+ ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK)
+ >> _CMU_LFAPRESC0_RTC_SHIFT;
+ break;
+#endif
+
+#if defined( _CMU_LFECLKEN0_RTCC_MASK )
+ case (CMU_RTCC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = lfClkGet(cmuClock_LFE);
+ break;
+#endif
+
+#if defined( _CMU_LFACLKEN0_LETIMER0_MASK )
+ case (CMU_LETIMER0_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = lfClkGet(cmuClock_LFA);
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )
+ ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)
+ >> _CMU_LFAPRESC0_LETIMER0_SHIFT;
+#elif defined( _SILICON_LABS_32B_PLATFORM_2 )
+ ret /= CMU_Log2ToDiv((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)
+ >> _CMU_LFAPRESC0_LETIMER0_SHIFT);
+#endif
+ break;
+#endif
+
+#if defined(_CMU_LFACLKEN0_LCD_MASK)
+ case (CMU_LCDPRE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = lfClkGet(cmuClock_LFA);
+ ret >>= ((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)
+ >> _CMU_LFAPRESC0_LCD_SHIFT)
+ + CMU_DivToLog2(cmuClkDiv_16);
+ break;
+
+ case (CMU_LCD_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = lfClkGet(cmuClock_LFA);
+ ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)
+ >> _CMU_LFAPRESC0_LCD_SHIFT;
+ ret /= 1U + ((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK)
+ >> _CMU_LCDCTRL_FDIV_SHIFT);
+ break;
+#endif
+
+#if defined(_CMU_LFACLKEN0_LESENSE_MASK)
+ case (CMU_LESENSE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = lfClkGet(cmuClock_LFA);
+ ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK)
+ >> _CMU_LFAPRESC0_LESENSE_SHIFT;
+ break;
+#endif
+
+ case (CMU_LFB_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = lfClkGet(cmuClock_LFB);
+ break;
+
+#if defined( _CMU_LFBCLKEN0_LEUART0_MASK )
+ case (CMU_LEUART0_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = lfClkGet(cmuClock_LFB);
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )
+ ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)
+ >> _CMU_LFBPRESC0_LEUART0_SHIFT;
+#elif defined( _SILICON_LABS_32B_PLATFORM_2 )
+ ret /= CMU_Log2ToDiv((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)
+ >> _CMU_LFBPRESC0_LEUART0_SHIFT);
+#endif
+ break;
+#endif
+
+#if defined( _CMU_LFBCLKEN0_LEUART1_MASK )
+ case (CMU_LEUART1_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = lfClkGet(cmuClock_LFB);
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )
+ ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)
+ >> _CMU_LFBPRESC0_LEUART1_SHIFT;
+#elif defined( _SILICON_LABS_32B_PLATFORM_2 )
+ ret /= CMU_Log2ToDiv((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)
+ >> _CMU_LFBPRESC0_LEUART1_SHIFT);
+#endif
+ break;
+#endif
+
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ case (CMU_LFE_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = lfClkGet(cmuClock_LFE);
+ break;
+#endif
+
+ case (CMU_DBG_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = dbgClkGet();
+ break;
+
+ case (CMU_AUX_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = auxClkGet();
+ break;
+
+#if defined(USB_PRESENT)
+ case (CMU_USBC_CLK_BRANCH << CMU_CLK_BRANCH_POS):
+ ret = usbCClkGet();
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+/***************************************************************************//**
+ * @brief
+ * Get clock prescaler.
+ *
+ * @param[in] clock
+ * Clock point to get the prescaler for. Notice that not all clock points
+ * have a prescaler. Please refer to CMU overview in reference manual.
+ *
+ * @return
+ * The prescaler value of the current clock point. 0 is returned
+ * if @p clock specifies a clock point without a prescaler.
+ ******************************************************************************/
+uint32_t CMU_ClockPrescGet(CMU_Clock_TypeDef clock)
+{
+ uint32_t prescReg;
+ uint32_t ret;
+
+ /* Get prescaler register id. */
+ prescReg = (clock >> CMU_PRESC_REG_POS) & CMU_PRESC_REG_MASK;
+
+ switch (prescReg)
+ {
+ case CMU_HFPRESC_REG:
+ ret = ((CMU->HFPRESC & _CMU_HFPRESC_PRESC_MASK)
+ >> _CMU_HFPRESC_PRESC_SHIFT);
+ break;
+
+ case CMU_HFEXPPRESC_REG:
+ ret = ((CMU->HFEXPPRESC & _CMU_HFEXPPRESC_PRESC_MASK)
+ >> _CMU_HFEXPPRESC_PRESC_SHIFT);
+ break;
+
+ case CMU_HFCLKLEPRESC_REG:
+ ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK)
+ >> _CMU_HFPRESC_HFCLKLEPRESC_SHIFT);
+ break;
+
+ case CMU_HFPERPRESC_REG:
+ ret = ((CMU->HFPERPRESC & _CMU_HFPERPRESC_PRESC_MASK)
+ >> _CMU_HFPERPRESC_PRESC_SHIFT);
+ break;
+
+#if defined( _CMU_HFRADIOPRESC_PRESC_MASK )
+ case CMU_HFRADIOPRESC_REG:
+ ret = ((CMU->HFRADIOPRESC & _CMU_HFRADIOPRESC_PRESC_MASK)
+ >> _CMU_HFRADIOPRESC_PRESC_SHIFT);
+ break;
+#endif
+
+ case CMU_HFCOREPRESC_REG:
+ ret = ((CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK)
+ >> _CMU_HFCOREPRESC_PRESC_SHIFT);
+ break;
+
+ case CMU_LFAPRESC0_REG:
+ switch (clock)
+ {
+#if defined( _CMU_LFAPRESC0_LETIMER0_MASK )
+ case cmuClock_LETIMER0:
+ ret = (((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)
+ >> _CMU_LFAPRESC0_LETIMER0_SHIFT));
+ /* Convert the exponent to prescaler value. */
+ ret = CMU_Log2ToDiv(ret) - 1U;
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ ret = 0U;
+ break;
+ }
+ break;
+
+ case CMU_LFBPRESC0_REG:
+ switch (clock)
+ {
+#if defined( _CMU_LFBPRESC0_LEUART0_MASK )
+ case cmuClock_LEUART0:
+ ret = (((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)
+ >> _CMU_LFBPRESC0_LEUART0_SHIFT));
+ /* Convert the exponent to prescaler value. */
+ ret = CMU_Log2ToDiv(ret) - 1U;
+ break;
+#endif
+
+#if defined( _CMU_LFBPRESC0_LEUART1_MASK )
+ case cmuClock_LEUART1:
+ ret = (((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)
+ >> _CMU_LFBPRESC0_LEUART1_SHIFT));
+ /* Convert the exponent to prescaler value. */
+ ret = CMU_Log2ToDiv(ret) - 1U;
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ ret = 0U;
+ break;
+ }
+ break;
+
+ case CMU_LFEPRESC0_REG:
+ switch (clock)
+ {
+#if defined( RTCC_PRESENT )
+ case cmuClock_RTCC:
+ /* No need to compute with LFEPRESC0_RTCC - DIV1 is the only */
+ /* allowed value. Convert the exponent to prescaler value. */
+ ret = _CMU_LFEPRESC0_RTCC_DIV1;
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ ret = 0U;
+ break;
+#endif
+ }
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ ret = 0U;
+ break;
+ }
+
+ return ret;
+}
+#endif
+
+
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+/***************************************************************************//**
+ * @brief
+ * Set clock prescaler.
+ *
+ * @note
+ * If setting a LF clock prescaler, synchronization into the low frequency
+ * domain is required. If the same register is modified before a previous
+ * update has completed, this function will stall until the previous
+ * synchronization has completed. Please refer to CMU_FreezeEnable() for
+ * a suggestion on how to reduce stalling time in some use cases.
+ *
+ * @param[in] clock
+ * Clock point to set prescaler for. Notice that not all clock points
+ * have a prescaler, please refer to CMU overview in the reference manual.
+ *
+ * @param[in] presc
+ * The clock prescaler to use.
+ ******************************************************************************/
+void CMU_ClockPrescSet(CMU_Clock_TypeDef clock, CMU_ClkPresc_TypeDef presc)
+{
+ uint32_t freq;
+ uint32_t prescReg;
+
+ /* Get divisor reg id */
+ prescReg = (clock >> CMU_PRESC_REG_POS) & CMU_PRESC_REG_MASK;
+
+ switch (prescReg)
+ {
+ case CMU_HFPRESC_REG:
+ EFM_ASSERT(presc < 32U);
+
+ CMU->HFPRESC = (CMU->HFPRESC & ~_CMU_HFPRESC_PRESC_MASK)
+ | (presc << _CMU_HFPRESC_PRESC_SHIFT);
+ break;
+
+ case CMU_HFEXPPRESC_REG:
+ EFM_ASSERT(presc < 32U);
+
+ CMU->HFEXPPRESC = (CMU->HFEXPPRESC & ~_CMU_HFEXPPRESC_PRESC_MASK)
+ | (presc << _CMU_HFEXPPRESC_PRESC_SHIFT);
+ break;
+
+ case CMU_HFCLKLEPRESC_REG:
+ EFM_ASSERT(presc < 2U);
+
+ /* Specifies the clock divider for HFCLKLE. When running at frequencies
+ * higher than 32 MHz, this must be set to DIV4. */
+ CMU->HFPRESC = (CMU->HFPRESC & ~_CMU_HFPRESC_HFCLKLEPRESC_MASK)
+ | (presc << _CMU_HFPRESC_HFCLKLEPRESC_SHIFT);
+ break;
+
+ case CMU_HFPERPRESC_REG:
+ EFM_ASSERT(presc < 512U);
+
+ CMU->HFPERPRESC = (CMU->HFPERPRESC & ~_CMU_HFPERPRESC_PRESC_MASK)
+ | (presc << _CMU_HFPERPRESC_PRESC_SHIFT);
+ break;
+
+#if defined( _CMU_HFRADIOPRESC_PRESC_MASK )
+ case CMU_HFRADIOPRESC_REG:
+ EFM_ASSERT(presc < 512U);
+
+ CMU->HFRADIOPRESC = (CMU->HFRADIOPRESC & ~_CMU_HFRADIOPRESC_PRESC_MASK)
+ | (presc << _CMU_HFRADIOPRESC_PRESC_SHIFT);
+ break;
+#endif
+
+ case CMU_HFCOREPRESC_REG:
+ EFM_ASSERT(presc < 512U);
+
+ /* Configure worst case wait states for flash access before setting
+ * the prescaler. */
+ flashWaitStateControl(CMU_MAX_FREQ_0WS + 1);
+
+ CMU->HFCOREPRESC = (CMU->HFCOREPRESC & ~_CMU_HFCOREPRESC_PRESC_MASK)
+ | (presc << _CMU_HFCOREPRESC_PRESC_SHIFT);
+
+ /* Update CMSIS core clock variable */
+ /* (The function will update the global variable) */
+ freq = SystemCoreClockGet();
+
+ /* Optimize flash access wait state setting for current core clk */
+ flashWaitStateControl(freq);
+ break;
+
+ case CMU_LFAPRESC0_REG:
+ switch (clock)
+ {
+#if defined( RTC_PRESENT )
+ case cmuClock_RTC:
+ EFM_ASSERT(presc <= 32768U);
+
+ /* Convert prescaler value to DIV exponent scale. */
+ presc = CMU_PrescToLog2(presc);
+
+ /* LF register about to be modified require sync. Busy check. */
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);
+
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK)
+ | (presc << _CMU_LFAPRESC0_RTC_SHIFT);
+ break;
+#endif
+
+#if defined( RTCC_PRESENT )
+ case cmuClock_RTCC:
+#if defined( _CMU_LFEPRESC0_RTCC_MASK )
+ /* DIV1 is the only accepted value. */
+ EFM_ASSERT(presc <= 0U);
+
+ /* LF register about to be modified require sync. Busy check.. */
+ syncReg(CMU_SYNCBUSY_LFEPRESC0);
+
+ CMU->LFEPRESC0 = (CMU->LFEPRESC0 & ~_CMU_LFEPRESC0_RTCC_MASK)
+ | (presc << _CMU_LFEPRESC0_RTCC_SHIFT);
+#else
+ EFM_ASSERT(presc <= 32768U);
+
+ /* Convert prescaler value to DIV exponent scale. */
+ presc = CMU_PrescToLog2(presc);
+
+ /* LF register about to be modified require sync. Busy check. */
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);
+
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTCC_MASK)
+ | (presc << _CMU_LFAPRESC0_RTCC_SHIFT);
+#endif
+ break;
+#endif
+
+#if defined( _CMU_LFAPRESC0_LETIMER0_MASK )
+ case cmuClock_LETIMER0:
+ EFM_ASSERT(presc <= 32768U);
+
+ /* Convert prescaler value to DIV exponent scale. */
+ presc = CMU_PrescToLog2(presc);
+
+ /* LF register about to be modified require sync. Busy check. */
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);
+
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK)
+ | (presc << _CMU_LFAPRESC0_LETIMER0_SHIFT);
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+ break;
+
+ case CMU_LFBPRESC0_REG:
+ switch (clock)
+ {
+#if defined( _CMU_LFBPRESC0_LEUART0_MASK )
+ case cmuClock_LEUART0:
+ EFM_ASSERT(presc <= 8U);
+
+ /* Convert prescaler value to DIV exponent scale. */
+ presc = CMU_PrescToLog2(presc);
+
+ /* LF register about to be modified require sync. Busy check. */
+ syncReg(CMU_SYNCBUSY_LFBPRESC0);
+
+ CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK)
+ | (presc << _CMU_LFBPRESC0_LEUART0_SHIFT);
+ break;
+#endif
+
+#if defined( _CMU_LFBPRESC0_LEUART1_MASK )
+ case cmuClock_LEUART1:
+ EFM_ASSERT(presc <= 8U);
+
+ /* Convert prescaler value to DIV exponent scale. */
+ presc = CMU_PrescToLog2(presc);
+
+ /* LF register about to be modified require sync. Busy check. */
+ syncReg(CMU_SYNCBUSY_LFBPRESC0);
+
+ CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK)
+ | (presc << _CMU_LFBPRESC0_LEUART1_SHIFT);
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+ break;
+
+ case CMU_LFEPRESC0_REG:
+ switch (clock)
+ {
+#if defined( _CMU_LFEPRESC0_RTCC_MASK )
+ case cmuClock_RTCC:
+ EFM_ASSERT(presc <= 0U);
+
+ /* LF register about to be modified require sync. Busy check. */
+ syncReg(CMU_SYNCBUSY_LFEPRESC0);
+
+ CMU->LFEPRESC0 = (CMU->LFEPRESC0 & ~_CMU_LFEPRESC0_RTCC_MASK)
+ | (presc << _CMU_LFEPRESC0_RTCC_SHIFT);
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+}
+#endif
+
+
+/***************************************************************************//**
+ * @brief
+ * Get currently selected reference clock used for a clock branch.
+ *
+ * @param[in] clock
+ * Clock branch to fetch selected ref. clock for. One of:
+ * @li #cmuClock_HF
+ * @li #cmuClock_LFA
+ * @li #cmuClock_LFB @if _CMU_LFCLKSEL_LFAE_ULFRCO
+ * @li #cmuClock_LFC
+ * @endif @if _SILICON_LABS_32B_PLATFORM_2
+ * @li #cmuClock_LFE
+ * @endif
+ * @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT
+ * @li #cmuClock_USBC
+ * @endif
+ *
+ * @return
+ * Reference clock used for clocking selected branch, #cmuSelect_Error if
+ * invalid @p clock provided.
+ ******************************************************************************/
+CMU_Select_TypeDef CMU_ClockSelectGet(CMU_Clock_TypeDef clock)
+{
+ CMU_Select_TypeDef ret = cmuSelect_Disabled;
+ uint32_t selReg;
+
+ selReg = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;
+
+ switch (selReg)
+ {
+ case CMU_HFCLKSEL_REG:
+#if defined( _CMU_HFCLKSEL_HF_MASK )
+ switch (CMU->HFCLKSEL & _CMU_HFCLKSEL_HF_MASK)
+ {
+ case CMU_HFCLKSEL_HF_LFXO:
+ ret = cmuSelect_LFXO;
+ break;
+
+ case CMU_HFCLKSEL_HF_LFRCO:
+ ret = cmuSelect_LFRCO;
+ break;
+
+ case CMU_HFCLKSEL_HF_HFXO:
+ ret = cmuSelect_HFXO;
+ break;
+
+ default:
+ ret = cmuSelect_HFRCO;
+ break;
+ }
+#else
+ switch (CMU->STATUS
+ & (CMU_STATUS_HFRCOSEL
+ | CMU_STATUS_HFXOSEL
+ | CMU_STATUS_LFRCOSEL
+#if defined( CMU_STATUS_USHFRCODIV2SEL )
+ | CMU_STATUS_USHFRCODIV2SEL
+#endif
+ | CMU_STATUS_LFXOSEL))
+ {
+ case CMU_STATUS_LFXOSEL:
+ ret = cmuSelect_LFXO;
+ break;
+
+ case CMU_STATUS_LFRCOSEL:
+ ret = cmuSelect_LFRCO;
+ break;
+
+ case CMU_STATUS_HFXOSEL:
+ ret = cmuSelect_HFXO;
+ break;
+
+#if defined( CMU_STATUS_USHFRCODIV2SEL )
+ case CMU_STATUS_USHFRCODIV2SEL:
+ ret = cmuSelect_USHFRCODIV2;
+ break;
+#endif
+
+ default:
+ ret = cmuSelect_HFRCO;
+ break;
+ }
+#endif
+ break;
+
+ case CMU_LFACLKSEL_REG:
+#if defined( _CMU_LFCLKSEL_MASK )
+ switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK)
+ {
+ case CMU_LFCLKSEL_LFA_LFRCO:
+ ret = cmuSelect_LFRCO;
+ break;
+
+ case CMU_LFCLKSEL_LFA_LFXO:
+ ret = cmuSelect_LFXO;
+ break;
+
+#if defined( CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2 )
+ case CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:
+ ret = cmuSelect_CORELEDIV2;
+ break;
+#endif
+
+ default:
+#if defined( CMU_LFCLKSEL_LFAE )
+ if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFAE_MASK)
+ {
+ ret = cmuSelect_ULFRCO;
+ break;
+ }
+#else
+ ret = cmuSelect_Disabled;
+#endif
+ break;
+ }
+#endif /* _CMU_LFCLKSEL_MASK */
+
+#if defined( _CMU_LFACLKSEL_MASK )
+ switch (CMU->LFACLKSEL & _CMU_LFACLKSEL_LFA_MASK)
+ {
+ case CMU_LFACLKSEL_LFA_LFRCO:
+ ret = cmuSelect_LFRCO;
+ break;
+
+ case CMU_LFACLKSEL_LFA_LFXO:
+ ret = cmuSelect_LFXO;
+ break;
+
+ case CMU_LFACLKSEL_LFA_ULFRCO:
+ ret = cmuSelect_ULFRCO;
+ break;
+
+#if defined( _CMU_LFACLKSEL_LFA_HFCLKLE )
+ case CMU_LFACLKSEL_LFA_HFCLKLE:
+ ret = cmuSelect_HFCLKLE;
+ break;
+#endif
+
+ default:
+ ret = cmuSelect_Disabled;
+ break;
+ }
+#endif
+ break;
+
+ case CMU_LFBCLKSEL_REG:
+#if defined( _CMU_LFCLKSEL_MASK )
+ switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK)
+ {
+ case CMU_LFCLKSEL_LFB_LFRCO:
+ ret = cmuSelect_LFRCO;
+ break;
+
+ case CMU_LFCLKSEL_LFB_LFXO:
+ ret = cmuSelect_LFXO;
+ break;
+
+#if defined( CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2 )
+ case CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2:
+ ret = cmuSelect_CORELEDIV2;
+ break;
+#endif
+
+#if defined( CMU_LFCLKSEL_LFB_HFCLKLE )
+ case CMU_LFCLKSEL_LFB_HFCLKLE:
+ ret = cmuSelect_HFCLKLE;
+ break;
+#endif
+
+ default:
+#if defined( CMU_LFCLKSEL_LFBE )
+ if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFBE_MASK)
+ {
+ ret = cmuSelect_ULFRCO;
+ break;
+ }
+#else
+ ret = cmuSelect_Disabled;
+#endif
+ break;
+ }
+#endif /* _CMU_LFCLKSEL_MASK */
+
+#if defined( _CMU_LFBCLKSEL_MASK )
+ switch (CMU->LFBCLKSEL & _CMU_LFBCLKSEL_LFB_MASK)
+ {
+ case CMU_LFBCLKSEL_LFB_LFRCO:
+ ret = cmuSelect_LFRCO;
+ break;
+
+ case CMU_LFBCLKSEL_LFB_LFXO:
+ ret = cmuSelect_LFXO;
+ break;
+
+ case CMU_LFBCLKSEL_LFB_ULFRCO:
+ ret = cmuSelect_ULFRCO;
+ break;
+
+ case CMU_LFBCLKSEL_LFB_HFCLKLE:
+ ret = cmuSelect_HFCLKLE;
+ break;
+
+ default:
+ ret = cmuSelect_Disabled;
+ break;
+ }
+#endif
+ break;
+
+#if defined( _CMU_LFCLKSEL_LFC_MASK )
+ case CMU_LFCCLKSEL_REG:
+ switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK)
+ {
+ case CMU_LFCLKSEL_LFC_LFRCO:
+ ret = cmuSelect_LFRCO;
+ break;
+
+ case CMU_LFCLKSEL_LFC_LFXO:
+ ret = cmuSelect_LFXO;
+ break;
+
+ default:
+ ret = cmuSelect_Disabled;
+ break;
+ }
+ break;
+#endif
+
+#if defined( _CMU_LFECLKSEL_LFE_MASK )
+ case CMU_LFECLKSEL_REG:
+ switch (CMU->LFECLKSEL & _CMU_LFECLKSEL_LFE_MASK)
+ {
+ case CMU_LFECLKSEL_LFE_LFRCO:
+ ret = cmuSelect_LFRCO;
+ break;
+
+ case CMU_LFECLKSEL_LFE_LFXO:
+ ret = cmuSelect_LFXO;
+ break;
+
+ case CMU_LFECLKSEL_LFE_ULFRCO:
+ ret = cmuSelect_ULFRCO;
+ break;
+
+#if defined ( _CMU_LFECLKSEL_LFE_HFCLKLE )
+ case CMU_LFECLKSEL_LFE_HFCLKLE:
+ ret = cmuSelect_HFCLKLE;
+ break;
+#endif
+
+ default:
+ ret = cmuSelect_Disabled;
+ break;
+ }
+ break;
+#endif /* CMU_LFECLKSEL_REG */
+
+ case CMU_DBGCLKSEL_REG:
+#if defined( _CMU_DBGCLKSEL_DBG_MASK )
+ switch (CMU->DBGCLKSEL & _CMU_DBGCLKSEL_DBG_MASK)
+ {
+ case CMU_DBGCLKSEL_DBG_HFCLK:
+ ret = cmuSelect_HFCLK;
+ break;
+
+ case CMU_DBGCLKSEL_DBG_AUXHFRCO:
+ ret = cmuSelect_AUXHFRCO;
+ break;
+ }
+#else
+ ret = cmuSelect_AUXHFRCO;
+#endif /* CMU_DBGCLKSEL_DBG */
+
+#if defined( _CMU_CTRL_DBGCLK_MASK )
+ switch(CMU->CTRL & _CMU_CTRL_DBGCLK_MASK)
+ {
+ case CMU_CTRL_DBGCLK_AUXHFRCO:
+ ret = cmuSelect_AUXHFRCO;
+ break;
+
+ case CMU_CTRL_DBGCLK_HFCLK:
+ ret = cmuSelect_HFCLK;
+ break;
+ }
+#else
+ ret = cmuSelect_AUXHFRCO;
+#endif
+ break;
+
+
+#if defined( USB_PRESENT )
+ case CMU_USBCCLKSEL_REG:
+ switch (CMU->STATUS
+ & (CMU_STATUS_USBCLFXOSEL
+#if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)
+ | CMU_STATUS_USBCHFCLKSEL
+#endif
+#if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)
+ | CMU_STATUS_USBCUSHFRCOSEL
+#endif
+ | CMU_STATUS_USBCLFRCOSEL))
+ {
+#if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)
+ case CMU_STATUS_USBCHFCLKSEL:
+ ret = cmuSelect_HFCLK;
+ break;
+#endif
+
+#if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)
+ case CMU_STATUS_USBCUSHFRCOSEL:
+ ret = cmuSelect_USHFRCO;
+ break;
+#endif
+
+ case CMU_STATUS_USBCLFXOSEL:
+ ret = cmuSelect_LFXO;
+ break;
+
+ case CMU_STATUS_USBCLFRCOSEL:
+ ret = cmuSelect_LFRCO;
+ break;
+
+ default:
+ ret = cmuSelect_Disabled;
+ break;
+ }
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ ret = cmuSelect_Error;
+ break;
+ }
+
+ return ret;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Select reference clock/oscillator used for a clock branch.
+ *
+ * @details
+ * Notice that if a selected reference is not enabled prior to selecting its
+ * use, it will be enabled, and this function will wait for the selected
+ * oscillator to be stable. It will however NOT be disabled if another
+ * reference clock is selected later.
+ *
+ * This feature is particularly important if selecting a new reference
+ * clock for the clock branch clocking the core, otherwise the system
+ * may halt.
+ *
+ * @param[in] clock
+ * Clock branch to select reference clock for. One of:
+ * @li #cmuClock_HF
+ * @li #cmuClock_LFA
+ * @li #cmuClock_LFB @if _CMU_LFCLKSEL_LFAE_ULFRCO
+ * @li #cmuClock_LFC
+ * @endif @if _SILICON_LABS_32B_PLATFORM_2
+ * @li #cmuClock_LFE
+ * @endif
+ * @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT
+ * @li #cmuClock_USBC
+ * @endif
+ *
+ * @param[in] ref
+ * Reference selected for clocking, please refer to reference manual for
+ * for details on which reference is available for a specific clock branch.
+ * @li #cmuSelect_HFRCO
+ * @li #cmuSelect_LFRCO
+ * @li #cmuSelect_HFXO
+ * @li #cmuSelect_LFXO
+ * @li #cmuSelect_CORELEDIV2
+ * @li #cmuSelect_AUXHFRCO
+ * @li #cmuSelect_HFCLK @ifnot DOXYDOC_EFM32_GECKO_FAMILY
+ * @li #cmuSelect_ULFRCO
+ * @endif
+ ******************************************************************************/
+void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)
+{
+ uint32_t select = cmuOsc_HFRCO;
+ CMU_Osc_TypeDef osc = cmuOsc_HFRCO;
+ uint32_t freq;
+ uint32_t tmp;
+ uint32_t selRegId;
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ volatile uint32_t *selReg = NULL;
+#endif
+#if defined( CMU_LFCLKSEL_LFAE_ULFRCO )
+ uint32_t lfExtended = 0;
+#endif
+
+ selRegId = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;
+
+ switch (selRegId)
+ {
+ case CMU_HFCLKSEL_REG:
+ switch (ref)
+ {
+ case cmuSelect_LFXO:
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ select = CMU_HFCLKSEL_HF_LFXO;
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )
+ select = CMU_CMD_HFCLKSEL_LFXO;
+#endif
+ osc = cmuOsc_LFXO;
+ break;
+
+ case cmuSelect_LFRCO:
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ select = CMU_HFCLKSEL_HF_LFRCO;
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )
+ select = CMU_CMD_HFCLKSEL_LFRCO;
+#endif
+ osc = cmuOsc_LFRCO;
+ break;
+
+ case cmuSelect_HFXO:
+ osc = cmuOsc_HFXO;
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ select = CMU_HFCLKSEL_HF_HFXO;
+ /* Adjust HFXO buffer current for high frequencies, */
+ /* enable WSHFLE for frequencies above 32MHz. */
+ if (SystemHFXOClockGet() > 32000000)
+ {
+ CMU->CTRL |= CMU_CTRL_WSHFLE;
+ }
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )
+ select = CMU_CMD_HFCLKSEL_HFXO;
+#if defined( CMU_CTRL_HFLE )
+ /* Adjust HFXO buffer current for high frequencies, */
+ /* enable HFLE for frequencies above CMU_MAX_FREQ_HFLE. */
+ if(SystemHFXOClockGet() > CMU_MAX_FREQ_HFLE())
+ {
+ CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK)
+ | CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ
+ /* Must have HFLE enabled to access some LE peripherals >=32MHz */
+ | CMU_CTRL_HFLE;
+
+ /* Set HFLE and DIV4 factor for peripheral clock if HFCORE */
+ /* clock for LE is enabled. */
+ if (CMU->HFCORECLKEN0 & CMU_HFCORECLKEN0_LE)
+ {
+ BUS_RegBitWrite(&CMU->HFCORECLKDIV,
+ _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);
+ }
+ }
+ else
+ {
+ /* This can happen if the user configures the EFM32_HFXO_FREQ to */
+ /* use another oscillator frequency */
+ CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK)
+ | CMU_CTRL_HFXOBUFCUR_BOOSTUPTO32MHZ;
+ }
+#endif
+#endif
+ break;
+
+ case cmuSelect_HFRCO:
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ select = CMU_HFCLKSEL_HF_HFRCO;
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )
+ select = CMU_CMD_HFCLKSEL_HFRCO;
+#endif
+ osc = cmuOsc_HFRCO;
+ break;
+
+#if defined( CMU_CMD_HFCLKSEL_USHFRCODIV2 )
+ case cmuSelect_USHFRCODIV2:
+ select = CMU_CMD_HFCLKSEL_USHFRCODIV2;
+ osc = cmuOsc_USHFRCO;
+ break;
+#endif
+
+#if defined( CMU_LFCLKSEL_LFAE_ULFRCO ) || defined( CMU_LFACLKSEL_LFA_ULFRCO )
+ case cmuSelect_ULFRCO:
+ /* ULFRCO cannot be used as HFCLK */
+ EFM_ASSERT(0);
+ return;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ return;
+ }
+
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */
+ CMU_OscillatorEnable(osc, true, true);
+
+ /* Configure worst case wait states for flash access before selecting */
+ flashWaitStateMax();
+
+ /* Switch to selected oscillator */
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ CMU->HFCLKSEL = select;
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )
+ CMU->CMD = select;
+#endif
+
+ /* Keep EMU module informed */
+ EMU_UpdateOscConfig();
+
+ /* Update CMSIS core clock variable */
+ /* (The function will update the global variable) */
+ freq = SystemCoreClockGet();
+
+ /* Optimize flash access wait state setting for currently selected core clk */
+ flashWaitStateControl(freq);
+ break;
+
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ case CMU_LFACLKSEL_REG:
+ selReg = (selReg == NULL) ? &CMU->LFACLKSEL : selReg;
+#if !defined( _CMU_LFACLKSEL_LFA_HFCLKLE )
+ /* HFCLKCLE can not be used as LFACLK */
+ EFM_ASSERT(ref != cmuSelect_HFCLKLE);
+#endif
+ case CMU_LFECLKSEL_REG:
+ selReg = (selReg == NULL) ? &CMU->LFECLKSEL : selReg;
+#if !defined( _CMU_LFECLKSEL_LFE_HFCLKLE )
+ /* HFCLKCLE can not be used as LFECLK */
+ EFM_ASSERT(ref != cmuSelect_HFCLKLE);
+#endif
+ case CMU_LFBCLKSEL_REG:
+ selReg = (selReg == NULL) ? &CMU->LFBCLKSEL : selReg;
+ switch (ref)
+ {
+ case cmuSelect_Disabled:
+ tmp = _CMU_LFACLKSEL_LFA_DISABLED;
+ break;
+
+ case cmuSelect_LFXO:
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */
+ CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
+ tmp = _CMU_LFACLKSEL_LFA_LFXO;
+ break;
+
+ case cmuSelect_LFRCO:
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */
+ CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
+ tmp = _CMU_LFACLKSEL_LFA_LFRCO;
+ break;
+
+ case cmuSelect_HFCLKLE:
+ /* Ensure HFCORE to LE clocking is enabled */
+ BUS_RegBitWrite(&CMU->HFBUSCLKEN0, _CMU_HFBUSCLKEN0_LE_SHIFT, 1);
+ tmp = _CMU_LFBCLKSEL_LFB_HFCLKLE;
+
+ /* If core frequency is > 32MHz enable WSHFLE */
+ freq = SystemCoreClockGet();
+ if (freq > 32000000U)
+ {
+ /* Enable CMU HFLE */
+ BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_WSHFLE_SHIFT, 1);
+
+ /* Enable DIV4 factor for peripheral clock */
+ BUS_RegBitWrite(&CMU->HFPRESC, _CMU_HFPRESC_HFCLKLEPRESC_SHIFT, 1);
+ }
+ break;
+
+ case cmuSelect_ULFRCO:
+ /* ULFRCO is always on, there is no need to enable it. */
+ tmp = _CMU_LFACLKSEL_LFA_ULFRCO;
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ return;
+ }
+ *selReg = tmp;
+ break;
+
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )
+ case CMU_LFACLKSEL_REG:
+ case CMU_LFBCLKSEL_REG:
+ switch (ref)
+ {
+ case cmuSelect_Disabled:
+ tmp = _CMU_LFCLKSEL_LFA_DISABLED;
+ break;
+
+ case cmuSelect_LFXO:
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */
+ CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
+ tmp = _CMU_LFCLKSEL_LFA_LFXO;
+ break;
+
+ case cmuSelect_LFRCO:
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */
+ CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
+ tmp = _CMU_LFCLKSEL_LFA_LFRCO;
+ break;
+
+ case cmuSelect_CORELEDIV2:
+ /* Ensure HFCORE to LE clocking is enabled */
+ BUS_RegBitWrite(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_LE_SHIFT, 1);
+ tmp = _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2;
+#if defined( CMU_CTRL_HFLE )
+ /* If core frequency is higher than CMU_MAX_FREQ_HFLE on
+ Giant/Leopard/Wonder, enable HFLE and DIV4. */
+ freq = SystemCoreClockGet();
+ if(freq > CMU_MAX_FREQ_HFLE())
+ {
+ /* Enable CMU HFLE */
+ BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1);
+
+ /* Enable DIV4 factor for peripheral clock */
+ BUS_RegBitWrite(&CMU->HFCORECLKDIV,
+ _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);
+ }
+#endif
+ break;
+
+#if defined( CMU_LFCLKSEL_LFAE_ULFRCO )
+ case cmuSelect_ULFRCO:
+ /* ULFRCO is always enabled */
+ tmp = _CMU_LFCLKSEL_LFA_DISABLED;
+ lfExtended = 1;
+ break;
+#endif
+
+ default:
+ /* Illegal clock source for LFA/LFB selected */
+ EFM_ASSERT(0);
+ return;
+ }
+
+ /* Apply select */
+ if (selRegId == CMU_LFACLKSEL_REG)
+ {
+#if defined( _CMU_LFCLKSEL_LFAE_MASK )
+ CMU->LFCLKSEL = (CMU->LFCLKSEL
+ & ~(_CMU_LFCLKSEL_LFA_MASK | _CMU_LFCLKSEL_LFAE_MASK))
+ | (tmp << _CMU_LFCLKSEL_LFA_SHIFT)
+ | (lfExtended << _CMU_LFCLKSEL_LFAE_SHIFT);
+#else
+ CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFA_MASK)
+ | (tmp << _CMU_LFCLKSEL_LFA_SHIFT);
+#endif
+ }
+ else
+ {
+#if defined( _CMU_LFCLKSEL_LFBE_MASK )
+ CMU->LFCLKSEL = (CMU->LFCLKSEL
+ & ~(_CMU_LFCLKSEL_LFB_MASK | _CMU_LFCLKSEL_LFBE_MASK))
+ | (tmp << _CMU_LFCLKSEL_LFB_SHIFT)
+ | (lfExtended << _CMU_LFCLKSEL_LFBE_SHIFT);
+#else
+ CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFB_MASK)
+ | (tmp << _CMU_LFCLKSEL_LFB_SHIFT);
+#endif
+ }
+ break;
+
+#if defined( _CMU_LFCLKSEL_LFC_MASK )
+ case CMU_LFCCLKSEL_REG:
+ switch(ref)
+ {
+ case cmuSelect_Disabled:
+ tmp = _CMU_LFCLKSEL_LFA_DISABLED;
+ break;
+
+ case cmuSelect_LFXO:
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */
+ CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
+ tmp = _CMU_LFCLKSEL_LFC_LFXO;
+ break;
+
+ case cmuSelect_LFRCO:
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */
+ CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
+ tmp = _CMU_LFCLKSEL_LFC_LFRCO;
+ break;
+
+ default:
+ /* Illegal clock source for LFC selected */
+ EFM_ASSERT(0);
+ return;
+ }
+
+ /* Apply select */
+ CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFC_MASK)
+ | (tmp << _CMU_LFCLKSEL_LFC_SHIFT);
+ break;
+#endif
+#endif
+
+#if defined( CMU_DBGCLKSEL_DBG ) || defined( CMU_CTRL_DBGCLK )
+ case CMU_DBGCLKSEL_REG:
+ switch(ref)
+ {
+#if defined( CMU_DBGCLKSEL_DBG )
+ case cmuSelect_AUXHFRCO:
+ /* Select AUXHFRCO as debug clock */
+ CMU->DBGCLKSEL = CMU_DBGCLKSEL_DBG_AUXHFRCO;
+ break;
+
+ case cmuSelect_HFCLK:
+ /* Select divided HFCLK as debug clock */
+ CMU->DBGCLKSEL = CMU_DBGCLKSEL_DBG_HFCLK;
+ break;
+#endif
+
+#if defined( CMU_CTRL_DBGCLK )
+ case cmuSelect_AUXHFRCO:
+ /* Select AUXHFRCO as debug clock */
+ CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))
+ | CMU_CTRL_DBGCLK_AUXHFRCO;
+ break;
+
+ case cmuSelect_HFCLK:
+ /* Select divided HFCLK as debug clock */
+ CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))
+ | CMU_CTRL_DBGCLK_HFCLK;
+ break;
+#endif
+
+ default:
+ /* Illegal clock source for debug selected */
+ EFM_ASSERT(0);
+ return;
+ }
+ break;
+#endif
+
+#if defined(USB_PRESENT)
+ case CMU_USBCCLKSEL_REG:
+ switch(ref)
+ {
+ case cmuSelect_LFXO:
+ /* Select LFXO as clock source for USB, can only be used in sleep mode */
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */
+ CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
+
+ /* Switch oscillator */
+ CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO;
+
+ /* Wait until clock is activated */
+ while((CMU->STATUS & CMU_STATUS_USBCLFXOSEL)==0)
+ {
+ }
+ break;
+
+ case cmuSelect_LFRCO:
+ /* Select LFRCO as clock source for USB, can only be used in sleep mode */
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */
+ CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);
+
+ /* Switch oscillator */
+ CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO;
+
+ /* Wait until clock is activated */
+ while((CMU->STATUS & CMU_STATUS_USBCLFRCOSEL)==0)
+ {
+ }
+ break;
+
+#if defined( CMU_STATUS_USBCHFCLKSEL )
+ case cmuSelect_HFCLK:
+ /* Select undivided HFCLK as clock source for USB */
+ /* Oscillator must already be enabled to avoid a core lockup */
+ CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;
+ /* Wait until clock is activated */
+ while((CMU->STATUS & CMU_STATUS_USBCHFCLKSEL)==0)
+ {
+ }
+ break;
+#endif
+
+#if defined( CMU_CMD_USBCCLKSEL_USHFRCO )
+ case cmuSelect_USHFRCO:
+ /* Select USHFRCO as clock source for USB */
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */
+ CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);
+
+ /* Switch oscillator */
+ CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO;
+
+ /* Wait until clock is activated */
+ while((CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL)==0)
+ {
+ }
+ break;
+#endif
+
+ default:
+ /* Illegal clock source for USB */
+ EFM_ASSERT(0);
+ return;
+ }
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+}
+
+
+/**************************************************************************//**
+ * @brief
+ * CMU low frequency register synchronization freeze control.
+ *
+ * @details
+ * Some CMU registers requires synchronization into the low frequency (LF)
+ * domain. The freeze feature allows for several such registers to be
+ * modified before passing them to the LF domain simultaneously (which
+ * takes place when the freeze mode is disabled).
+ *
+ * Another usage scenario of this feature, is when using an API (such
+ * as the CMU API) for modifying several bit fields consecutively in the
+ * same register. If freeze mode is enabled during this sequence, stalling
+ * can be avoided.
+ *
+ * @note
+ * When enabling freeze mode, this function will wait for all current
+ * ongoing CMU synchronization to LF domain to complete (Normally
+ * synchronization will not be in progress.) However for this reason, when
+ * using freeze mode, modifications of registers requiring LF synchronization
+ * should be done within one freeze enable/disable block to avoid unecessary
+ * stalling.
+ *
+ * @param[in] enable
+ * @li true - enable freeze, modified registers are not propagated to the
+ * LF domain
+ * @li false - disable freeze, modified registers are propagated to LF
+ * domain
+ *****************************************************************************/
+void CMU_FreezeEnable(bool enable)
+{
+ if (enable)
+ {
+ /* Wait for any ongoing LF synchronization to complete. This is just to */
+ /* protect against the rare case when a user */
+ /* - modifies a register requiring LF sync */
+ /* - then enables freeze before LF sync completed */
+ /* - then modifies the same register again */
+ /* since modifying a register while it is in sync progress should be */
+ /* avoided. */
+ while (CMU->SYNCBUSY)
+ {
+ }
+
+ CMU->FREEZE = CMU_FREEZE_REGFREEZE;
+ }
+ else
+ {
+ CMU->FREEZE = 0;
+ }
+}
+
+
+#if defined( _CMU_HFRCOCTRL_BAND_MASK )
+/***************************************************************************//**
+ * @brief
+ * Get HFRCO band in use.
+ *
+ * @return
+ * HFRCO band in use.
+ ******************************************************************************/
+CMU_HFRCOBand_TypeDef CMU_HFRCOBandGet(void)
+{
+ return (CMU_HFRCOBand_TypeDef)((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK)
+ >> _CMU_HFRCOCTRL_BAND_SHIFT);
+}
+#endif /* _CMU_HFRCOCTRL_BAND_MASK */
+
+
+#if defined( _CMU_HFRCOCTRL_BAND_MASK )
+/***************************************************************************//**
+ * @brief
+ * Set HFRCO band and the tuning value based on the value in the calibration
+ * table made during production.
+ *
+ * @param[in] band
+ * HFRCO band to activate.
+ ******************************************************************************/
+void CMU_HFRCOBandSet(CMU_HFRCOBand_TypeDef band)
+{
+ uint32_t tuning;
+ uint32_t freq;
+ CMU_Select_TypeDef osc;
+
+ /* Read tuning value from calibration table */
+ switch (band)
+ {
+ case cmuHFRCOBand_1MHz:
+ tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND1_MASK)
+ >> _DEVINFO_HFRCOCAL0_BAND1_SHIFT;
+ break;
+
+ case cmuHFRCOBand_7MHz:
+ tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND7_MASK)
+ >> _DEVINFO_HFRCOCAL0_BAND7_SHIFT;
+ break;
+
+ case cmuHFRCOBand_11MHz:
+ tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND11_MASK)
+ >> _DEVINFO_HFRCOCAL0_BAND11_SHIFT;
+ break;
+
+ case cmuHFRCOBand_14MHz:
+ tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND14_MASK)
+ >> _DEVINFO_HFRCOCAL0_BAND14_SHIFT;
+ break;
+
+ case cmuHFRCOBand_21MHz:
+ tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND21_MASK)
+ >> _DEVINFO_HFRCOCAL1_BAND21_SHIFT;
+ break;
+
+#if defined( _CMU_HFRCOCTRL_BAND_28MHZ )
+ case cmuHFRCOBand_28MHz:
+ tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND28_MASK)
+ >> _DEVINFO_HFRCOCAL1_BAND28_SHIFT;
+ break;
+#endif
+
+ default:
+ EFM_ASSERT(0);
+ return;
+ }
+
+ /* If HFRCO is used for core clock, we have to consider flash access WS. */
+ osc = CMU_ClockSelectGet(cmuClock_HF);
+ if (osc == cmuSelect_HFRCO)
+ {
+ /* Configure worst case wait states for flash access before setting divider */
+ flashWaitStateMax();
+ }
+
+ /* Set band/tuning */
+ CMU->HFRCOCTRL = (CMU->HFRCOCTRL &
+ ~(_CMU_HFRCOCTRL_BAND_MASK | _CMU_HFRCOCTRL_TUNING_MASK))
+ | (band << _CMU_HFRCOCTRL_BAND_SHIFT)
+ | (tuning << _CMU_HFRCOCTRL_TUNING_SHIFT);
+
+ /* If HFRCO is used for core clock, optimize flash WS */
+ if (osc == cmuSelect_HFRCO)
+ {
+ /* Update CMSIS core clock variable and get current core clock */
+ /* (The function will update the global variable) */
+ /* NOTE! We need at least 21 cycles before setting zero wait state to flash */
+ /* (i.e. WS0) when going from the 28MHz to 1MHz in the HFRCO band */
+ freq = SystemCoreClockGet();
+
+ /* Optimize flash access wait state setting for current core clk */
+ flashWaitStateControl(freq);
+ }
+}
+#endif /* _CMU_HFRCOCTRL_BAND_MASK */
+
+
+#if defined( _CMU_HFRCOCTRL_FREQRANGE_MASK )
+/**************************************************************************//**
+ * @brief
+ * Get a pointer to the HFRCO frequency calibration word in DEVINFO
+ *
+ * @param[in] freq
+ * Frequency in Hz
+ *
+ * @return
+ * HFRCO calibration word for a given frequency
+ *****************************************************************************/
+static uint32_t CMU_HFRCODevinfoGet(CMU_HFRCOFreq_TypeDef freq)
+{
+ switch (freq)
+ {
+ /* 1, 2 and 4MHz share the same calibration word */
+ case cmuHFRCOFreq_1M0Hz:
+ case cmuHFRCOFreq_2M0Hz:
+ case cmuHFRCOFreq_4M0Hz:
+ return DEVINFO->HFRCOCAL0;
+
+ case cmuHFRCOFreq_7M0Hz:
+ return DEVINFO->HFRCOCAL3;
+
+ case cmuHFRCOFreq_13M0Hz:
+ return DEVINFO->HFRCOCAL6;
+
+ case cmuHFRCOFreq_16M0Hz:
+ return DEVINFO->HFRCOCAL7;
+
+ case cmuHFRCOFreq_19M0Hz:
+ return DEVINFO->HFRCOCAL8;
+
+ case cmuHFRCOFreq_26M0Hz:
+ return DEVINFO->HFRCOCAL10;
+
+ case cmuHFRCOFreq_32M0Hz:
+ return DEVINFO->HFRCOCAL11;
+
+ case cmuHFRCOFreq_38M0Hz:
+ return DEVINFO->HFRCOCAL12;
+
+ default: /* cmuHFRCOFreq_UserDefined */
+ return 0;
+ }
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Get HFRCO frequency enumeration in use
+ *
+ * @return
+ * HFRCO frequency enumeration in use
+ ******************************************************************************/
+CMU_HFRCOFreq_TypeDef CMU_HFRCOFreqGet(void)
+{
+ return (CMU_HFRCOFreq_TypeDef)SystemHfrcoFreq;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Set HFRCO calibration for the selected target frequency
+ *
+ * @param[in] freq
+ * HFRCO frequency band to set
+ ******************************************************************************/
+void CMU_HFRCOFreqSet(CMU_HFRCOFreq_TypeDef freq)
+{
+ uint32_t freqCal;
+
+ /* Get DEVINFO index, set CMSIS frequency SystemHfrcoFreq */
+ freqCal = CMU_HFRCODevinfoGet(freq);
+ EFM_ASSERT((freqCal != 0) && (freqCal != UINT_MAX));
+ SystemHfrcoFreq = (uint32_t)freq;
+
+ /* Set max wait-states while changing core clock */
+ if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO)
+ {
+ flashWaitStateMax();
+ }
+
+ /* Wait for any previous sync to complete, and then set calibration data
+ for the selected frequency. */
+ while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_HFRCOBSY_SHIFT));
+
+ /* Check for valid calibration data */
+ EFM_ASSERT(freqCal != UINT_MAX);
+
+ /* Set divider in HFRCOCTRL for 1, 2 and 4MHz */
+ switch(freq)
+ {
+ case cmuHFRCOFreq_1M0Hz:
+ freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)
+ | CMU_HFRCOCTRL_CLKDIV_DIV4;
+ break;
+
+ case cmuHFRCOFreq_2M0Hz:
+ freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)
+ | CMU_HFRCOCTRL_CLKDIV_DIV2;
+ break;
+
+ case cmuHFRCOFreq_4M0Hz:
+ freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)
+ | CMU_HFRCOCTRL_CLKDIV_DIV1;
+ break;
+
+ default:
+ break;
+ }
+ CMU->HFRCOCTRL = freqCal;
+
+ /* Optimize flash access wait-state configuration for this frequency, */
+ /* if HFRCO is reference for core clock. */
+ if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO)
+ {
+ flashWaitStateControl((uint32_t)freq);
+ }
+}
+#endif /* _CMU_HFRCOCTRL_FREQRANGE_MASK */
+
+#if defined( _CMU_HFRCOCTRL_SUDELAY_MASK )
+/***************************************************************************//**
+ * @brief
+ * Get the HFRCO startup delay.
+ *
+ * @details
+ * Please refer to the reference manual for further details.
+ *
+ * @return
+ * The startup delay in use.
+ ******************************************************************************/
+uint32_t CMU_HFRCOStartupDelayGet(void)
+{
+ return (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_SUDELAY_MASK)
+ >> _CMU_HFRCOCTRL_SUDELAY_SHIFT;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Set the HFRCO startup delay.
+ *
+ * @details
+ * Please refer to the reference manual for further details.
+ *
+ * @param[in] delay
+ * The startup delay to set (<= 31).
+ ******************************************************************************/
+void CMU_HFRCOStartupDelaySet(uint32_t delay)
+{
+ EFM_ASSERT(delay <= 31);
+
+ delay &= _CMU_HFRCOCTRL_SUDELAY_MASK >> _CMU_HFRCOCTRL_SUDELAY_SHIFT;
+ CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_SUDELAY_MASK))
+ | (delay << _CMU_HFRCOCTRL_SUDELAY_SHIFT);
+}
+#endif
+
+
+#if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK )
+/***************************************************************************//**
+ * @brief
+ * Enable or disable HFXO autostart
+ *
+ * @param[in] enRACStartSel
+ * If true, HFXO is automatically started and selected upon RAC wakeup.
+ * If false, HFXO is not started or selected automatically upon RAC wakeup.
+ *
+ * @param[in] enEM0EM1Start
+ * If true, HFXO is automatically started upon entering EM0/EM1 entry from
+ * EM2/EM3. HFXO selection has to be handled by the user.
+ * If false, HFXO is not started automatically when entering EM0/EM1.
+ *
+ * @param[in] enEM0EM1StartSel
+ * If true, HFXO is automatically started and immediately selected upon
+ * entering EM0/EM1 entry from EM2/EM3. Note that this option stalls the use of
+ * HFSRCCLK until HFXO becomes ready.
+ * If false, HFXO is not started or selected automatically when entering
+ * EM0/EM1.
+ ******************************************************************************/
+void CMU_HFXOAutostartEnable(bool enRACStartSel,
+ bool enEM0EM1Start,
+ bool enEM0EM1StartSel)
+{
+ uint32_t hfxoCtrl;
+ hfxoCtrl = CMU->HFXOCTRL & ~(_CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK
+ | _CMU_HFXOCTRL_AUTOSTARTEM0EM1_MASK
+ | _CMU_HFXOCTRL_AUTOSTARTSELEM0EM1_MASK);
+
+ hfxoCtrl |= (enRACStartSel ? CMU_HFXOCTRL_AUTOSTARTRDYSELRAC : 0)
+ | (enEM0EM1Start ? CMU_HFXOCTRL_AUTOSTARTEM0EM1 : 0)
+ | (enEM0EM1StartSel ? CMU_HFXOCTRL_AUTOSTARTSELEM0EM1 : 0);
+
+ CMU->HFXOCTRL = hfxoCtrl;
+}
+#endif /* _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK */
+
+
+#if defined( _CMU_HFXOCTRL_MASK )
+/**************************************************************************//**
+ * @brief
+ * Set HFXO control registers
+ *
+ * @note
+ * HFXO configuration should be obtained from a configuration tool,
+ * app note or xtal datasheet. This function disables the HFXO to ensure
+ * a valid state before update.
+ *
+ * @param[in] hfxoInit
+ * HFXO setup parameters
+ *****************************************************************************/
+void CMU_HFXOInit(CMU_HFXOInit_TypeDef *hfxoInit)
+{
+ uint32_t ishReg;
+ uint32_t ishMax;
+
+ /* Do not disable HFXO if it is currently selected as HF/Core clock */
+ EFM_ASSERT(CMU_ClockSelectGet(cmuClock_HF) != cmuSelect_HFXO);
+
+ /* HFXO must be disabled before reconfiguration */
+ CMU_OscillatorEnable(cmuOsc_HFXO, false, false);
+
+ /* Apply control settings */
+ BUS_RegMaskedWrite(&CMU->HFXOCTRL,
+ _CMU_HFXOCTRL_LOWPOWER_MASK
+#if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK )
+ | _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK
+#endif
+ | _CMU_HFXOCTRL_AUTOSTARTEM0EM1_MASK
+ | _CMU_HFXOCTRL_AUTOSTARTSELEM0EM1_MASK,
+ (hfxoInit->lowPowerMode
+ ? CMU_HFXOCTRL_LOWPOWER : 0)
+#if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK )
+ | (hfxoInit->autoStartSelOnRacWakeup
+ ? CMU_HFXOCTRL_AUTOSTARTRDYSELRAC : 0)
+#endif
+ | (hfxoInit->autoStartEm01
+ ? CMU_HFXOCTRL_AUTOSTARTEM0EM1 : 0)
+ | (hfxoInit->autoSelEm01
+ ? CMU_HFXOCTRL_AUTOSTARTSELEM0EM1 : 0));
+
+ /* Set XTAL tuning parameters */
+
+ /* Set peak detection threshold in CMU_HFXOCTRL1_PEAKDETTHR[2:0] (hidden). */
+ BUS_RegMaskedWrite((volatile uint32_t *)0x400E4028, 0x7, hfxoInit->thresholdPeakDetect);
+
+ /* Set tuning for startup and steady state */
+ BUS_RegMaskedWrite(&CMU->HFXOSTARTUPCTRL,
+ _CMU_HFXOSTARTUPCTRL_CTUNE_MASK
+ | _CMU_HFXOSTARTUPCTRL_REGISHWARM_MASK
+ | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK
+ | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCOREWARM_MASK,
+ (hfxoInit->ctuneStartup
+ << _CMU_HFXOSTARTUPCTRL_CTUNE_SHIFT)
+ | (hfxoInit->regIshStartup
+ << _CMU_HFXOSTARTUPCTRL_REGISHWARM_SHIFT)
+ | (hfxoInit->xoCoreBiasTrimStartup
+ << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT)
+ | 0x4 /* Recommended tuning */
+ << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCOREWARM_SHIFT);
+
+ /* Adjust CMU_HFXOSTEADYSTATECTRL_REGISHUPPER according to regIshSteadyState.
+ Saturate at max value. Please see the reference manual page 433 and Section
+ 12.5.10 CMU_HFXOSTEADYSTATECTRL for more details. */
+ ishReg = hfxoInit->regIshSteadyState + 3;
+ ishMax = _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK
+ >> _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_SHIFT;
+ ishReg = ishReg > ishMax ? ishMax : ishReg;
+ ishReg <<= _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_SHIFT;
+
+ BUS_RegMaskedWrite(&CMU->HFXOSTEADYSTATECTRL,
+ _CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK
+ | _CMU_HFXOSTEADYSTATECTRL_REGISH_MASK
+ | _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK
+ | _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK,
+ (hfxoInit->ctuneSteadyState
+ << _CMU_HFXOSTEADYSTATECTRL_CTUNE_SHIFT)
+ | (hfxoInit->regIshSteadyState
+ << _CMU_HFXOSTEADYSTATECTRL_REGISH_SHIFT)
+ | (hfxoInit->xoCoreBiasTrimSteadyState
+ << _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_SHIFT)
+ | ishReg);
+
+ /* Set timeouts */
+ BUS_RegMaskedWrite(&CMU->HFXOTIMEOUTCTRL,
+ _CMU_HFXOTIMEOUTCTRL_SHUNTOPTTIMEOUT_MASK
+ | _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_MASK
+ | _CMU_HFXOTIMEOUTCTRL_WARMSTEADYTIMEOUT_MASK
+ | _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_MASK
+ | _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_MASK,
+ (hfxoInit->timeoutShuntOptimization
+ << _CMU_HFXOTIMEOUTCTRL_SHUNTOPTTIMEOUT_SHIFT)
+ | (hfxoInit->timeoutPeakDetect
+ << _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_SHIFT)
+ | (hfxoInit->timeoutWarmSteady
+ << _CMU_HFXOTIMEOUTCTRL_WARMSTEADYTIMEOUT_SHIFT)
+ | (hfxoInit->timeoutSteady
+ << _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_SHIFT)
+ | (hfxoInit->timeoutStartup
+ << _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_SHIFT));
+}
+#endif
+
+
+/***************************************************************************//**
+ * @brief
+ * Get the LCD framerate divisor (FDIV) setting.
+ *
+ * @return
+ * The LCD framerate divisor.
+ ******************************************************************************/
+uint32_t CMU_LCDClkFDIVGet(void)
+{
+#if defined( LCD_PRESENT )
+ return (CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >> _CMU_LCDCTRL_FDIV_SHIFT;
+#else
+ return 0;
+#endif /* defined(LCD_PRESENT) */
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Set the LCD framerate divisor (FDIV) setting.
+ *
+ * @note
+ * The FDIV field (CMU LCDCTRL register) should only be modified while the
+ * LCD module is clock disabled (CMU LFACLKEN0.LCD bit is 0). This function
+ * will NOT modify FDIV if the LCD module clock is enabled. Please refer to
+ * CMU_ClockEnable() for disabling/enabling LCD clock.
+ *
+ * @param[in] div
+ * The FDIV setting to use.
+ ******************************************************************************/
+void CMU_LCDClkFDIVSet(uint32_t div)
+{
+#if defined( LCD_PRESENT )
+ EFM_ASSERT(div <= cmuClkDiv_128);
+
+ /* Do not allow modification if LCD clock enabled */
+ if (CMU->LFACLKEN0 & CMU_LFACLKEN0_LCD)
+ {
+ return;
+ }
+
+ div <<= _CMU_LCDCTRL_FDIV_SHIFT;
+ div &= _CMU_LCDCTRL_FDIV_MASK;
+ CMU->LCDCTRL = (CMU->LCDCTRL & ~_CMU_LCDCTRL_FDIV_MASK) | div;
+#else
+ (void)div; /* Unused parameter */
+#endif /* defined(LCD_PRESENT) */
+}
+
+
+#if defined( _CMU_LFXOCTRL_MASK )
+/**************************************************************************//**
+ * @brief
+ * Set LFXO control registers
+ *
+ * @note
+ * LFXO configuration should be obtained from a configuration tool,
+ * app note or xtal datasheet. This function disables the LFXO to ensure
+ * a valid state before update.
+ *
+ * @param[in] lfxoInit
+ * LFXO setup parameters
+ *****************************************************************************/
+void CMU_LFXOInit(CMU_LFXOInit_TypeDef *lfxoInit)
+{
+ /* Do not disable LFXO if it is currently selected as HF/Core clock */
+ EFM_ASSERT(CMU_ClockSelectGet(cmuClock_HF) != cmuSelect_LFXO);
+
+ /* LFXO must be disabled before reconfiguration */
+ CMU_OscillatorEnable(cmuOsc_LFXO, false, false);
+
+ BUS_RegMaskedWrite(&CMU->LFXOCTRL,
+ _CMU_LFXOCTRL_TUNING_MASK
+ | _CMU_LFXOCTRL_GAIN_MASK
+ | _CMU_LFXOCTRL_TIMEOUT_MASK,
+ (lfxoInit->ctune << _CMU_LFXOCTRL_TUNING_SHIFT)
+ | (lfxoInit->gain << _CMU_LFXOCTRL_GAIN_SHIFT)
+ | (lfxoInit->timeout << _CMU_LFXOCTRL_TIMEOUT_SHIFT));
+}
+#endif
+
+
+/***************************************************************************//**
+ * @brief
+ * Enable/disable oscillator.
+ *
+ * @note
+ * WARNING: When this function is called to disable either cmuOsc_LFXO or
+ * cmuOsc_HFXO the LFXOMODE or HFXOMODE fields of the CMU_CTRL register
+ * are reset to the reset value. I.e. if external clock sources are selected
+ * in either LFXOMODE or HFXOMODE fields, the configuration will be cleared
+ * and needs to be reconfigured if needed later.
+ *
+ * @param[in] osc
+ * The oscillator to enable/disable.
+ *
+ * @param[in] enable
+ * @li true - enable specified oscillator.
+ * @li false - disable specified oscillator.
+ *
+ * @param[in] wait
+ * Only used if @p enable is true.
+ * @li true - wait for oscillator start-up time to timeout before returning.
+ * @li false - do not wait for oscillator start-up time to timeout before
+ * returning.
+ ******************************************************************************/
+void CMU_OscillatorEnable(CMU_Osc_TypeDef osc, bool enable, bool wait)
+{
+ uint32_t rdyBitPos;
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ uint32_t ensBitPos;
+#endif
+ uint32_t enBit;
+ uint32_t disBit;
+
+ switch (osc)
+ {
+ case cmuOsc_HFRCO:
+ enBit = CMU_OSCENCMD_HFRCOEN;
+ disBit = CMU_OSCENCMD_HFRCODIS;
+ rdyBitPos = _CMU_STATUS_HFRCORDY_SHIFT;
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ ensBitPos = _CMU_STATUS_HFRCOENS_SHIFT;
+#endif
+ break;
+
+ case cmuOsc_HFXO:
+ enBit = CMU_OSCENCMD_HFXOEN;
+ disBit = CMU_OSCENCMD_HFXODIS;
+ rdyBitPos = _CMU_STATUS_HFXORDY_SHIFT;
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ ensBitPos = _CMU_STATUS_HFXOENS_SHIFT;
+#endif
+ break;
+
+ case cmuOsc_AUXHFRCO:
+ enBit = CMU_OSCENCMD_AUXHFRCOEN;
+ disBit = CMU_OSCENCMD_AUXHFRCODIS;
+ rdyBitPos = _CMU_STATUS_AUXHFRCORDY_SHIFT;
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ ensBitPos = _CMU_STATUS_AUXHFRCOENS_SHIFT;
+#endif
+ break;
+
+ case cmuOsc_LFRCO:
+ enBit = CMU_OSCENCMD_LFRCOEN;
+ disBit = CMU_OSCENCMD_LFRCODIS;
+ rdyBitPos = _CMU_STATUS_LFRCORDY_SHIFT;
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ ensBitPos = _CMU_STATUS_LFRCOENS_SHIFT;
+#endif
+ break;
+
+ case cmuOsc_LFXO:
+ enBit = CMU_OSCENCMD_LFXOEN;
+ disBit = CMU_OSCENCMD_LFXODIS;
+ rdyBitPos = _CMU_STATUS_LFXORDY_SHIFT;
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ ensBitPos = _CMU_STATUS_LFXOENS_SHIFT;
+#endif
+ break;
+
+#if defined( _CMU_STATUS_USHFRCOENS_MASK )
+ case cmuOsc_USHFRCO:
+ enBit = CMU_OSCENCMD_USHFRCOEN;
+ disBit = CMU_OSCENCMD_USHFRCODIS;
+ rdyBitPos = _CMU_STATUS_USHFRCORDY_SHIFT;
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ ensBitPos = _CMU_STATUS_USHFRCOENS_SHIFT;
+#endif
+ break;
+#endif
+
+#if defined( CMU_LFCLKSEL_LFAE_ULFRCO )
+ case cmuOsc_ULFRCO:
+ /* ULFRCO is always enabled, and cannot be turned off */
+ return;
+#endif
+
+ default:
+ /* Undefined clock source */
+ EFM_ASSERT(0);
+ return;
+ }
+
+ if (enable)
+ {
+ CMU->OSCENCMD = enBit;
+
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ /* Always wait for ENS to go high */
+ while (!BUS_RegBitRead(&CMU->STATUS, ensBitPos))
+ {
+ }
+#endif
+
+ /* Wait for clock to become ready after enable */
+ if (wait)
+ {
+ while (!BUS_RegBitRead(&CMU->STATUS, rdyBitPos));
+#if defined( _CMU_STATUS_HFXOSHUNTOPTRDY_MASK )
+ /* Wait for shunt current optimization to complete */
+ if ((osc == cmuOsc_HFXO)
+ && (BUS_RegMaskedRead(&CMU->HFXOCTRL,
+ _CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK)
+ == CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_AUTOCMD))
+ {
+ while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_HFXOSHUNTOPTRDY_SHIFT))
+ {
+ }
+ /* Assert on failed peak detection. Incorrect HFXO initialization parameters
+ caused startup to fail. Please review parameters. */
+ EFM_ASSERT(BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_HFXOPEAKDETRDY_SHIFT));
+ }
+#endif
+ }
+ }
+ else
+ {
+ CMU->OSCENCMD = disBit;
+
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ /* Always wait for ENS to go low */
+ while (BUS_RegBitRead(&CMU->STATUS, ensBitPos))
+ {
+ }
+#endif
+ }
+
+ /* Keep EMU module informed */
+ EMU_UpdateOscConfig();
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Get oscillator frequency tuning setting.
+ *
+ * @param[in] osc
+ * Oscillator to get tuning value for, one of:
+ * @li #cmuOsc_LFRCO
+ * @li #cmuOsc_HFRCO
+ * @li #cmuOsc_AUXHFRCO
+ *
+ * @return
+ * The oscillator frequency tuning setting in use.
+ ******************************************************************************/
+uint32_t CMU_OscillatorTuningGet(CMU_Osc_TypeDef osc)
+{
+ uint32_t ret;
+
+ switch (osc)
+ {
+ case cmuOsc_LFRCO:
+ ret = (CMU->LFRCOCTRL & _CMU_LFRCOCTRL_TUNING_MASK)
+ >> _CMU_LFRCOCTRL_TUNING_SHIFT;
+ break;
+
+ case cmuOsc_HFRCO:
+ ret = (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_TUNING_MASK)
+ >> _CMU_HFRCOCTRL_TUNING_SHIFT;
+ break;
+
+ case cmuOsc_AUXHFRCO:
+ ret = (CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_TUNING_MASK)
+ >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT;
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Set the oscillator frequency tuning control.
+ *
+ * @note
+ * Oscillator tuning is done during production, and the tuning value is
+ * automatically loaded after a reset. Changing the tuning value from the
+ * calibrated value is for more advanced use.
+ *
+ * @param[in] osc
+ * Oscillator to set tuning value for, one of:
+ * @li #cmuOsc_LFRCO
+ * @li #cmuOsc_HFRCO
+ * @li #cmuOsc_AUXHFRCO
+ *
+ * @param[in] val
+ * The oscillator frequency tuning setting to use.
+ ******************************************************************************/
+void CMU_OscillatorTuningSet(CMU_Osc_TypeDef osc, uint32_t val)
+{
+ switch (osc)
+ {
+ case cmuOsc_LFRCO:
+ EFM_ASSERT(val <= (_CMU_LFRCOCTRL_TUNING_MASK
+ >> _CMU_LFRCOCTRL_TUNING_SHIFT));
+ val &= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT);
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_LFRCOBSY_SHIFT));
+#endif
+ CMU->LFRCOCTRL = (CMU->LFRCOCTRL & ~(_CMU_LFRCOCTRL_TUNING_MASK))
+ | (val << _CMU_LFRCOCTRL_TUNING_SHIFT);
+ break;
+
+ case cmuOsc_HFRCO:
+ EFM_ASSERT(val <= (_CMU_HFRCOCTRL_TUNING_MASK
+ >> _CMU_HFRCOCTRL_TUNING_SHIFT));
+ val &= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT);
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_HFRCOBSY_SHIFT))
+ {
+ }
+#endif
+ CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_TUNING_MASK))
+ | (val << _CMU_HFRCOCTRL_TUNING_SHIFT);
+ break;
+
+ case cmuOsc_AUXHFRCO:
+ EFM_ASSERT(val <= (_CMU_AUXHFRCOCTRL_TUNING_MASK
+ >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT));
+ val &= (_CMU_AUXHFRCOCTRL_TUNING_MASK >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT);
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )
+ while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_AUXHFRCOBSY_SHIFT))
+ {
+ }
+#endif
+ CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL & ~(_CMU_AUXHFRCOCTRL_TUNING_MASK))
+ | (val << _CMU_AUXHFRCOCTRL_TUNING_SHIFT);
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ break;
+ }
+}
+
+
+/**************************************************************************//**
+ * @brief
+ * Determine if currently selected PCNTn clock used is external or LFBCLK.
+ *
+ * @param[in] instance
+ * PCNT instance number to get currently selected clock source for.
+ *
+ * @return
+ * @li true - selected clock is external clock.
+ * @li false - selected clock is LFBCLK.
+ *****************************************************************************/
+bool CMU_PCNTClockExternalGet(unsigned int instance)
+{
+ uint32_t setting;
+
+ switch (instance)
+ {
+#if defined( _CMU_PCNTCTRL_PCNT0CLKEN_MASK )
+ case 0:
+ setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT0CLKSEL_PCNT0S0;
+ break;
+
+#if defined( _CMU_PCNTCTRL_PCNT1CLKEN_MASK )
+ case 1:
+ setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT1CLKSEL_PCNT1S0;
+ break;
+
+#if defined( _CMU_PCNTCTRL_PCNT2CLKEN_MASK )
+ case 2:
+ setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT2CLKSEL_PCNT2S0;
+ break;
+#endif
+#endif
+#endif
+
+ default:
+ setting = 0;
+ break;
+ }
+ return (setting ? true : false);
+}
+
+
+/**************************************************************************//**
+ * @brief
+ * Select PCNTn clock.
+ *
+ * @param[in] instance
+ * PCNT instance number to set selected clock source for.
+ *
+ * @param[in] external
+ * Set to true to select external clock, false to select LFBCLK.
+ *****************************************************************************/
+void CMU_PCNTClockExternalSet(unsigned int instance, bool external)
+{
+#if defined( PCNT_PRESENT )
+ uint32_t setting = 0;
+
+ EFM_ASSERT(instance < PCNT_COUNT);
+
+ if (external)
+ {
+ setting = 1;
+ }
+
+ BUS_RegBitWrite(&(CMU->PCNTCTRL), (instance * 2) + 1, setting);
+
+#else
+ (void)instance; /* Unused parameter */
+ (void)external; /* Unused parameter */
+#endif
+}
+
+
+#if defined( _CMU_USHFRCOCONF_BAND_MASK )
+/***************************************************************************//**
+ * @brief
+ * Get USHFRCO band in use.
+ *
+ * @return
+ * USHFRCO band in use.
+ ******************************************************************************/
+CMU_USHFRCOBand_TypeDef CMU_USHFRCOBandGet(void)
+{
+ return (CMU_USHFRCOBand_TypeDef)((CMU->USHFRCOCONF
+ & _CMU_USHFRCOCONF_BAND_MASK)
+ >> _CMU_USHFRCOCONF_BAND_SHIFT);
+}
+#endif
+
+#if defined( _CMU_USHFRCOCONF_BAND_MASK )
+/***************************************************************************//**
+ * @brief
+ * Set USHFRCO band to use.
+ *
+ * @param[in] band
+ * USHFRCO band to activate.
+ ******************************************************************************/
+void CMU_USHFRCOBandSet(CMU_USHFRCOBand_TypeDef band)
+{
+ uint32_t tuning;
+ uint32_t fineTuning;
+ CMU_Select_TypeDef osc;
+
+ /* Cannot switch band if USHFRCO is already selected as HF clock. */
+ osc = CMU_ClockSelectGet(cmuClock_HF);
+ EFM_ASSERT((CMU_USHFRCOBandGet() != band) && (osc != cmuSelect_USHFRCO));
+
+ /* Read tuning value from calibration table */
+ switch (band)
+ {
+ case cmuUSHFRCOBand_24MHz:
+ tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND24_TUNING_MASK)
+ >> _DEVINFO_USHFRCOCAL0_BAND24_TUNING_SHIFT;
+ fineTuning = (DEVINFO->USHFRCOCAL0
+ & _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_MASK)
+ >> _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_SHIFT;
+ break;
+
+ case cmuUSHFRCOBand_48MHz:
+ tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND48_TUNING_MASK)
+ >> _DEVINFO_USHFRCOCAL0_BAND48_TUNING_SHIFT;
+ fineTuning = (DEVINFO->USHFRCOCAL0
+ & _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_MASK)
+ >> _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_SHIFT;
+ /* Enable the clock divider before switching the band from 24 to 48MHz */
+ BUS_RegBitWrite(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 0);
+ break;
+
+ default:
+ EFM_ASSERT(0);
+ return;
+ }
+
+ /* Set band and tuning */
+ CMU->USHFRCOCONF = (CMU->USHFRCOCONF & ~_CMU_USHFRCOCONF_BAND_MASK)
+ | (band << _CMU_USHFRCOCONF_BAND_SHIFT);
+ CMU->USHFRCOCTRL = (CMU->USHFRCOCTRL & ~_CMU_USHFRCOCTRL_TUNING_MASK)
+ | (tuning << _CMU_USHFRCOCTRL_TUNING_SHIFT);
+ CMU->USHFRCOTUNE = (CMU->USHFRCOTUNE & ~_CMU_USHFRCOTUNE_FINETUNING_MASK)
+ | (fineTuning << _CMU_USHFRCOTUNE_FINETUNING_SHIFT);
+
+ /* Disable the clock divider after switching the band from 48 to 24MHz */
+ if (band == cmuUSHFRCOBand_24MHz)
+ {
+ BUS_RegBitWrite(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 1);
+ }
+}
+#endif
+
+
+
+/** @} (end addtogroup CMU) */
+/** @} (end addtogroup EM_Library) */
+#endif /* __EM_CMU_H */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_emu.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_emu.c new file mode 100644 index 000000000..254890066 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_emu.c @@ -0,0 +1,1805 @@ +/***************************************************************************//**
+ * @file em_emu.c
+ * @brief Energy Management Unit (EMU) Peripheral API
+ * @version 4.2.1
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+#include <limits.h>
+
+#include "em_emu.h"
+#if defined( EMU_PRESENT ) && ( EMU_COUNT > 0 )
+
+#include "em_cmu.h"
+#include "em_system.h"
+#include "em_assert.h"
+
+/***************************************************************************//**
+ * @addtogroup EM_Library
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup EMU
+ * @brief Energy Management Unit (EMU) Peripheral API
+ * @{
+ ******************************************************************************/
+
+/* Consistency check, since restoring assumes similar bitpositions in */
+/* CMU OSCENCMD and STATUS regs */
+#if (CMU_STATUS_AUXHFRCOENS != CMU_OSCENCMD_AUXHFRCOEN)
+#error Conflict in AUXHFRCOENS and AUXHFRCOEN bitpositions
+#endif
+#if (CMU_STATUS_HFXOENS != CMU_OSCENCMD_HFXOEN)
+#error Conflict in HFXOENS and HFXOEN bitpositions
+#endif
+#if (CMU_STATUS_LFRCOENS != CMU_OSCENCMD_LFRCOEN)
+#error Conflict in LFRCOENS and LFRCOEN bitpositions
+#endif
+#if (CMU_STATUS_LFXOENS != CMU_OSCENCMD_LFXOEN)
+#error Conflict in LFXOENS and LFXOEN bitpositions
+#endif
+
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+/* Fix for errata EMU_E107 - non-WIC interrupt masks. */
+#if defined( _EFM32_GECKO_FAMILY )
+#define ERRATA_FIX_EMU_E107_EN
+#define NON_WIC_INT_MASK_0 (~(0x0dfc0323U))
+#define NON_WIC_INT_MASK_1 (~(0x0U))
+
+#elif defined( _EFM32_TINY_FAMILY )
+#define ERRATA_FIX_EMU_E107_EN
+#define NON_WIC_INT_MASK_0 (~(0x001be323U))
+#define NON_WIC_INT_MASK_1 (~(0x0U))
+
+#elif defined( _EFM32_GIANT_FAMILY )
+#define ERRATA_FIX_EMU_E107_EN
+#define NON_WIC_INT_MASK_0 (~(0xff020e63U))
+#define NON_WIC_INT_MASK_1 (~(0x00000046U))
+
+#elif defined( _EFM32_WONDER_FAMILY )
+#define ERRATA_FIX_EMU_E107_EN
+#define NON_WIC_INT_MASK_0 (~(0xff020e63U))
+#define NON_WIC_INT_MASK_1 (~(0x00000046U))
+
+#else
+/* Zero Gecko and future families are not affected by errata EMU_E107 */
+#endif
+
+/* Fix for errata EMU_E108 - High Current Consumption on EM4 Entry. */
+#if defined( _EFM32_HAPPY_FAMILY )
+#define ERRATA_FIX_EMU_E108_EN
+#endif
+/** @endcond */
+
+
+#if defined( _EMU_DCDCCTRL_MASK )
+/* DCDCTODVDD output range min/max */
+#define PWRCFG_DCDCTODVDD_VMIN 1200
+#define PWRCFG_DCDCTODVDD_VMAX 3000
+typedef enum
+{
+ errataFixDcdcHsInit,
+ errataFixDcdcHsTrimSet,
+ errataFixDcdcHsLnWaitDone
+} errataFixDcdcHs_TypeDef;
+errataFixDcdcHs_TypeDef errataFixDcdcHsState = errataFixDcdcHsInit;
+#endif
+
+/*******************************************************************************
+ ************************** LOCAL VARIABLES ********************************
+ ******************************************************************************/
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+/**
+ * CMU configured oscillator selection and oscillator enable status. When a
+ * user configures oscillators, this varaiable shall shadow the configuration.
+ * It is used by the EMU module in order to be able to restore the oscillator
+ * config after having been in certain energy modes (since HW may automatically
+ * alter config when going into an energy mode). It is the responsibility of
+ * the CMU module to keep it up-to-date (or a user if not using the CMU API
+ * for oscillator control).
+ */
+static uint32_t cmuStatus;
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )
+static uint16_t cmuHfclkStatus;
+#endif
+#if defined( _EMU_DCDCCTRL_MASK )
+static uint16_t dcdcMaxCurrent_mA;
+static uint16_t dcdcOutput_mVout;
+#endif
+
+/** @endcond */
+
+
+/*******************************************************************************
+ ************************** LOCAL FUNCTIONS ********************************
+ ******************************************************************************/
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+/***************************************************************************//**
+ * @brief
+ * Restore oscillators and core clock after having been in EM2 or EM3.
+ ******************************************************************************/
+static void emuRestore(void)
+{
+ uint32_t oscEnCmd;
+ uint32_t cmuLocked;
+
+ /* Although we could use the CMU API for most of the below handling, we */
+ /* would like this function to be as efficient as possible. */
+
+ /* CMU registers may be locked */
+ cmuLocked = CMU->LOCK & CMU_LOCK_LOCKKEY_LOCKED;
+ CMU_Unlock();
+
+ /* AUXHFRCO are automatically disabled (except if using debugger). */
+ /* HFRCO, USHFRCO and HFXO are automatically disabled. */
+ /* LFRCO/LFXO may be disabled by SW in EM3. */
+ /* Restore according to status prior to entering energy mode. */
+ oscEnCmd = 0;
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_HFRCOENS) ? CMU_OSCENCMD_HFRCOEN : 0);
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_AUXHFRCOENS) ? CMU_OSCENCMD_AUXHFRCOEN : 0);
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_LFRCOENS) ? CMU_OSCENCMD_LFRCOEN : 0);
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_HFXOENS) ? CMU_OSCENCMD_HFXOEN : 0);
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_LFXOENS) ? CMU_OSCENCMD_LFXOEN : 0);
+#if defined( _CMU_STATUS_USHFRCOENS_MASK )
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_USHFRCOENS) ? CMU_OSCENCMD_USHFRCOEN : 0);
+#endif
+ CMU->OSCENCMD = oscEnCmd;
+
+
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )
+ /* Restore oscillator used for clocking core */
+ switch (cmuHfclkStatus & _CMU_HFCLKSTATUS_SELECTED_MASK)
+ {
+ case CMU_HFCLKSTATUS_SELECTED_LFRCO:
+ /* HFRCO could only be selected if the autostart HFXO feature is not
+ * enabled, otherwise the HFXO would be started and selected automatically.
+ * Note: this error hook helps catching erroneous oscillator configurations,
+ * when the AUTOSTARTSELEM0EM1 is set in CMU_HFXOCTRL. */
+ if (!(CMU->HFXOCTRL & CMU_HFXOCTRL_AUTOSTARTSELEM0EM1))
+ {
+ /* Wait for LFRCO to stabilize */
+ while (!(CMU->STATUS & CMU_STATUS_LFRCORDY))
+ ;
+ CMU->HFCLKSEL = CMU_HFCLKSEL_HF_LFRCO;
+ }
+ else
+ {
+ EFM_ASSERT(0);
+ }
+ break;
+
+ case CMU_HFCLKSTATUS_SELECTED_LFXO:
+ /* Wait for LFXO to stabilize */
+ while (!(CMU->STATUS & CMU_STATUS_LFXORDY))
+ ;
+ CMU->HFCLKSEL = CMU_HFCLKSEL_HF_LFXO;
+ break;
+
+ case CMU_HFCLKSTATUS_SELECTED_HFXO:
+ /* Wait for HFXO to stabilize */
+ while (!(CMU->STATUS & CMU_STATUS_HFXORDY))
+ ;
+ CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFXO;
+ break;
+
+ default: /* CMU_HFCLKSTATUS_SELECTED_HFRCO */
+ /* If core clock was HFRCO core clock, it is automatically restored to */
+ /* state prior to entering energy mode. No need for further action. */
+ break;
+ }
+#else
+ switch (cmuStatus & (CMU_STATUS_HFRCOSEL
+ | CMU_STATUS_HFXOSEL
+ | CMU_STATUS_LFRCOSEL
+#if defined( CMU_STATUS_USHFRCODIV2SEL )
+ | CMU_STATUS_USHFRCODIV2SEL
+#endif
+ | CMU_STATUS_LFXOSEL))
+ {
+ case CMU_STATUS_LFRCOSEL:
+ /* Wait for LFRCO to stabilize */
+ while (!(CMU->STATUS & CMU_STATUS_LFRCORDY))
+ ;
+ CMU->CMD = CMU_CMD_HFCLKSEL_LFRCO;
+ break;
+
+ case CMU_STATUS_LFXOSEL:
+ /* Wait for LFXO to stabilize */
+ while (!(CMU->STATUS & CMU_STATUS_LFXORDY))
+ ;
+ CMU->CMD = CMU_CMD_HFCLKSEL_LFXO;
+ break;
+
+ case CMU_STATUS_HFXOSEL:
+ /* Wait for HFXO to stabilize */
+ while (!(CMU->STATUS & CMU_STATUS_HFXORDY))
+ ;
+ CMU->CMD = CMU_CMD_HFCLKSEL_HFXO;
+ break;
+
+#if defined( CMU_STATUS_USHFRCODIV2SEL )
+ case CMU_STATUS_USHFRCODIV2SEL:
+ /* Wait for USHFRCO to stabilize */
+ while (!(CMU->STATUS & CMU_STATUS_USHFRCORDY))
+ ;
+ CMU->CMD = _CMU_CMD_HFCLKSEL_USHFRCODIV2;
+ break;
+#endif
+
+ default: /* CMU_STATUS_HFRCOSEL */
+ /* If core clock was HFRCO core clock, it is automatically restored to */
+ /* state prior to entering energy mode. No need for further action. */
+ break;
+ }
+
+ /* If HFRCO was disabled before entering Energy Mode, turn it off again */
+ /* as it is automatically enabled by wake up */
+ if ( ! (cmuStatus & CMU_STATUS_HFRCOENS) )
+ {
+ CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS;
+ }
+#endif
+ /* Restore CMU register locking */
+ if (cmuLocked)
+ {
+ CMU_Lock();
+ }
+}
+
+
+#if defined( ERRATA_FIX_EMU_E107_EN )
+/* Get enable conditions for errata EMU_E107 fix. */
+static __INLINE bool getErrataFixEmuE107En(void)
+{
+ /* SYSTEM_ChipRevisionGet could have been used here, but we would like a
+ * faster implementation in this case.
+ */
+ uint16_t majorMinorRev;
+
+ /* CHIP MAJOR bit [3:0] */
+ majorMinorRev = ((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK)
+ >> _ROMTABLE_PID0_REVMAJOR_SHIFT)
+ << 8;
+ /* CHIP MINOR bit [7:4] */
+ majorMinorRev |= ((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK)
+ >> _ROMTABLE_PID2_REVMINORMSB_SHIFT)
+ << 4;
+ /* CHIP MINOR bit [3:0] */
+ majorMinorRev |= (ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK)
+ >> _ROMTABLE_PID3_REVMINORLSB_SHIFT;
+
+#if defined( _EFM32_GECKO_FAMILY )
+ return (majorMinorRev <= 0x0103);
+#elif defined( _EFM32_TINY_FAMILY )
+ return (majorMinorRev <= 0x0102);
+#elif defined( _EFM32_GIANT_FAMILY )
+ return (majorMinorRev <= 0x0103) || (majorMinorRev == 0x0204);
+#elif defined( _EFM32_WONDER_FAMILY )
+ return (majorMinorRev == 0x0100);
+#else
+ /* Zero Gecko and future families are not affected by errata EMU_E107 */
+ return false;
+#endif
+}
+#endif
+
+
+#if defined( _EMU_DCDCCTRL_MASK )
+/* LP prepare / LN restore P/NFET count */
+static void maxCurrentUpdate(void);
+#define DCDC_LP_PFET_CNT 7
+#define DCDC_LP_NFET_CNT 15
+void dcdcFetCntSet(bool lpModeSet)
+{
+ uint32_t tmp;
+ static uint32_t emuDcdcMiscCtrlReg;
+
+ if (lpModeSet)
+ {
+ emuDcdcMiscCtrlReg = EMU->DCDCMISCCTRL;
+ tmp = EMU->DCDCMISCCTRL
+ & ~(_EMU_DCDCMISCCTRL_PFETCNT_MASK | _EMU_DCDCMISCCTRL_NFETCNT_MASK);
+ tmp |= (DCDC_LP_PFET_CNT << _EMU_DCDCMISCCTRL_PFETCNT_SHIFT)
+ | (DCDC_LP_NFET_CNT << _EMU_DCDCMISCCTRL_NFETCNT_SHIFT);
+ EMU->DCDCMISCCTRL = tmp;
+ maxCurrentUpdate();
+ }
+ else
+ {
+ EMU->DCDCMISCCTRL = emuDcdcMiscCtrlReg;
+ maxCurrentUpdate();
+ }
+}
+
+void dcdcHsFixLnBlock(void)
+{
+#define EMU_DCDCSTATUS (* (volatile uint32_t *)(EMU_BASE + 0x7C))
+ if (errataFixDcdcHsState == errataFixDcdcHsTrimSet)
+ {
+ /* Wait for LNRUNNING */
+ if ((EMU->DCDCCTRL & ~_EMU_DCDCCTRL_DCDCMODE_MASK) == EMU_DCDCCTRL_DCDCMODE_LOWNOISE)
+ {
+ while (!(EMU_DCDCSTATUS & (0x1 << 16)));
+ }
+ errataFixDcdcHsState = errataFixDcdcHsLnWaitDone;
+ }
+}
+#endif
+
+
+/** @endcond */
+
+
+/*******************************************************************************
+ ************************** GLOBAL FUNCTIONS *******************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief
+ * Enter energy mode 2 (EM2).
+ *
+ * @details
+ * When entering EM2, the high frequency clocks are disabled, ie HFXO, HFRCO
+ * and AUXHFRCO (for AUXHFRCO, see exception note below). When re-entering
+ * EM0, HFRCO is re-enabled and the core will be clocked by the configured
+ * HFRCO band. This ensures a quick wakeup from EM2.
+ *
+ * However, prior to entering EM2, the core may have been using another
+ * oscillator than HFRCO. The @p restore parameter gives the user the option
+ * to restore all HF oscillators according to state prior to entering EM2,
+ * as well as the clock used to clock the core. This restore procedure is
+ * handled by SW. However, since handled by SW, it will not be restored
+ * before completing the interrupt function(s) waking up the core!
+ *
+ * @note
+ * If restoring core clock to use the HFXO oscillator, which has been
+ * disabled during EM2 mode, this function will stall until the oscillator
+ * has stabilized. Stalling time can be reduced by adding interrupt
+ * support detecting stable oscillator, and an asynchronous switch to the
+ * original oscillator. See CMU documentation. Such a feature is however
+ * outside the scope of the implementation in this function.
+ * @par
+ * If HFXO is re-enabled by this function, and NOT used to clock the core,
+ * this function will not wait for HFXO to stabilize. This must be considered
+ * by the application if trying to use features relying on that oscillator
+ * upon return.
+ * @par
+ * If a debugger is attached, the AUXHFRCO will not be disabled if enabled
+ * upon entering EM2. It will thus remain enabled when returning to EM0
+ * regardless of the @p restore parameter.
+ * @par
+ * If HFXO autostart and select is enabled by using CMU_HFXOAutostartEnable(),
+ * the starting and selecting of the core clocks will be identical to the user
+ * independently of the value of the @p restore parameter when waking up on
+ * the wakeup sources corresponding to the autostart and select setting.
+ *
+ * @param[in] restore
+ * @li true - restore oscillators and clocks, see function details.
+ * @li false - do not restore oscillators and clocks, see function details.
+ * @par
+ * The @p restore option should only be used if all clock control is done
+ * via the CMU API.
+ ******************************************************************************/
+void EMU_EnterEM2(bool restore)
+{
+#if defined( ERRATA_FIX_EMU_E107_EN )
+ bool errataFixEmuE107En;
+ uint32_t nonWicIntEn[2];
+#endif
+
+ /* Auto-update CMU status just in case before entering energy mode. */
+ /* This variable is normally kept up-to-date by the CMU API. */
+ cmuStatus = CMU->STATUS;
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )
+ cmuHfclkStatus = (uint16_t)(CMU->HFCLKSTATUS);
+#endif
+
+ /* Enter Cortex deep sleep mode */
+ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+
+ /* Fix for errata EMU_E107 - store non-WIC interrupt enable flags.
+ Disable the enabled non-WIC interrupts. */
+#if defined( ERRATA_FIX_EMU_E107_EN )
+ errataFixEmuE107En = getErrataFixEmuE107En();
+ if (errataFixEmuE107En)
+ {
+ nonWicIntEn[0] = NVIC->ISER[0] & NON_WIC_INT_MASK_0;
+ NVIC->ICER[0] = nonWicIntEn[0];
+#if (NON_WIC_INT_MASK_1 != (~(0x0U)))
+ nonWicIntEn[1] = NVIC->ISER[1] & NON_WIC_INT_MASK_1;
+ NVIC->ICER[1] = nonWicIntEn[1];
+#endif
+ }
+#endif
+
+#if defined( _EMU_DCDCCTRL_MASK )
+ dcdcFetCntSet(true);
+ dcdcHsFixLnBlock();
+#endif
+
+ __WFI();
+
+#if defined( _EMU_DCDCCTRL_MASK )
+ dcdcFetCntSet(false);
+#endif
+
+ /* Fix for errata EMU_E107 - restore state of non-WIC interrupt enable flags. */
+#if defined( ERRATA_FIX_EMU_E107_EN )
+ if (errataFixEmuE107En)
+ {
+ NVIC->ISER[0] = nonWicIntEn[0];
+#if (NON_WIC_INT_MASK_1 != (~(0x0U)))
+ NVIC->ISER[1] = nonWicIntEn[1];
+#endif
+ }
+#endif
+
+ /* Restore oscillators/clocks if specified */
+ if (restore)
+ {
+ emuRestore();
+ }
+ /* If not restoring, and original clock was not HFRCO, we have to */
+ /* update CMSIS core clock variable since core clock has changed */
+ /* to using HFRCO. */
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )
+ else if ((cmuHfclkStatus & _CMU_HFCLKSTATUS_SELECTED_MASK)
+ != CMU_HFCLKSTATUS_SELECTED_HFRCO)
+#else
+ else if (!(cmuStatus & CMU_STATUS_HFRCOSEL))
+#endif
+ {
+ SystemCoreClockUpdate();
+ }
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Enter energy mode 3 (EM3).
+ *
+ * @details
+ * When entering EM3, the high frequency clocks are disabled by HW, ie HFXO,
+ * HFRCO and AUXHFRCO (for AUXHFRCO, see exception note below). In addition,
+ * the low frequency clocks, ie LFXO and LFRCO are disabled by SW. When
+ * re-entering EM0, HFRCO is re-enabled and the core will be clocked by the
+ * configured HFRCO band. This ensures a quick wakeup from EM3.
+ *
+ * However, prior to entering EM3, the core may have been using another
+ * oscillator than HFRCO. The @p restore parameter gives the user the option
+ * to restore all HF/LF oscillators according to state prior to entering EM3,
+ * as well as the clock used to clock the core. This restore procedure is
+ * handled by SW. However, since handled by SW, it will not be restored
+ * before completing the interrupt function(s) waking up the core!
+ *
+ * @note
+ * If restoring core clock to use an oscillator other than HFRCO, this
+ * function will stall until the oscillator has stabilized. Stalling time
+ * can be reduced by adding interrupt support detecting stable oscillator,
+ * and an asynchronous switch to the original oscillator. See CMU
+ * documentation. Such a feature is however outside the scope of the
+ * implementation in this function.
+ * @par
+ * If HFXO/LFXO/LFRCO are re-enabled by this function, and NOT used to clock
+ * the core, this function will not wait for those oscillators to stabilize.
+ * This must be considered by the application if trying to use features
+ * relying on those oscillators upon return.
+ * @par
+ * If a debugger is attached, the AUXHFRCO will not be disabled if enabled
+ * upon entering EM3. It will thus remain enabled when returning to EM0
+ * regardless of the @p restore parameter.
+ *
+ * @param[in] restore
+ * @li true - restore oscillators and clocks, see function details.
+ * @li false - do not restore oscillators and clocks, see function details.
+ * @par
+ * The @p restore option should only be used if all clock control is done
+ * via the CMU API.
+ ******************************************************************************/
+void EMU_EnterEM3(bool restore)
+{
+ uint32_t cmuLocked;
+
+#if defined( ERRATA_FIX_EMU_E107_EN )
+ bool errataFixEmuE107En;
+ uint32_t nonWicIntEn[2];
+#endif
+
+ /* Auto-update CMU status just in case before entering energy mode. */
+ /* This variable is normally kept up-to-date by the CMU API. */
+ cmuStatus = CMU->STATUS;
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )
+ cmuHfclkStatus = (uint16_t)(CMU->HFCLKSTATUS);
+#endif
+
+ /* CMU registers may be locked */
+ cmuLocked = CMU->LOCK & CMU_LOCK_LOCKKEY_LOCKED;
+ CMU_Unlock();
+
+ /* Disable LF oscillators */
+ CMU->OSCENCMD = CMU_OSCENCMD_LFXODIS | CMU_OSCENCMD_LFRCODIS;
+
+ /* Restore CMU register locking */
+ if (cmuLocked)
+ {
+ CMU_Lock();
+ }
+
+ /* Enter Cortex deep sleep mode */
+ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+
+ /* Fix for errata EMU_E107 - store non-WIC interrupt enable flags.
+ Disable the enabled non-WIC interrupts. */
+#if defined( ERRATA_FIX_EMU_E107_EN )
+ errataFixEmuE107En = getErrataFixEmuE107En();
+ if (errataFixEmuE107En)
+ {
+ nonWicIntEn[0] = NVIC->ISER[0] & NON_WIC_INT_MASK_0;
+ NVIC->ICER[0] = nonWicIntEn[0];
+#if (NON_WIC_INT_MASK_1 != (~(0x0U)))
+ nonWicIntEn[1] = NVIC->ISER[1] & NON_WIC_INT_MASK_1;
+ NVIC->ICER[1] = nonWicIntEn[1];
+#endif
+
+ }
+#endif
+
+#if defined( _EMU_DCDCCTRL_MASK )
+ dcdcFetCntSet(true);
+ dcdcHsFixLnBlock();
+#endif
+
+ __WFI();
+
+#if defined( _EMU_DCDCCTRL_MASK )
+ dcdcFetCntSet(false);
+#endif
+
+ /* Fix for errata EMU_E107 - restore state of non-WIC interrupt enable flags. */
+#if defined( ERRATA_FIX_EMU_E107_EN )
+ if (errataFixEmuE107En)
+ {
+ NVIC->ISER[0] = nonWicIntEn[0];
+#if (NON_WIC_INT_MASK_1 != (~(0x0U)))
+ NVIC->ISER[1] = nonWicIntEn[1];
+#endif
+ }
+#endif
+
+ /* Restore oscillators/clocks if specified */
+ if (restore)
+ {
+ emuRestore();
+ }
+ /* If not restoring, and original clock was not HFRCO, we have to */
+ /* update CMSIS core clock variable since core clock has changed */
+ /* to using HFRCO. */
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )
+ else if ((cmuHfclkStatus & _CMU_HFCLKSTATUS_SELECTED_MASK)
+ != CMU_HFCLKSTATUS_SELECTED_HFRCO)
+#else
+ else if (!(cmuStatus & CMU_STATUS_HFRCOSEL))
+#endif
+ {
+ SystemCoreClockUpdate();
+ }
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Enter energy mode 4 (EM4).
+ *
+ * @note
+ * Only a power on reset or external reset pin can wake the device from EM4.
+ ******************************************************************************/
+void EMU_EnterEM4(void)
+{
+ int i;
+
+#if defined( _EMU_EM4CTRL_EM4ENTRY_SHIFT )
+ uint32_t em4seq2 = (EMU->EM4CTRL & ~_EMU_EM4CTRL_EM4ENTRY_MASK)
+ | (2 << _EMU_EM4CTRL_EM4ENTRY_SHIFT);
+ uint32_t em4seq3 = (EMU->EM4CTRL & ~_EMU_EM4CTRL_EM4ENTRY_MASK)
+ | (3 << _EMU_EM4CTRL_EM4ENTRY_SHIFT);
+#else
+ uint32_t em4seq2 = (EMU->CTRL & ~_EMU_CTRL_EM4CTRL_MASK)
+ | (2 << _EMU_CTRL_EM4CTRL_SHIFT);
+ uint32_t em4seq3 = (EMU->CTRL & ~_EMU_CTRL_EM4CTRL_MASK)
+ | (3 << _EMU_CTRL_EM4CTRL_SHIFT);
+#endif
+
+ /* Make sure register write lock is disabled */
+ EMU_Unlock();
+
+#if defined( ERRATA_FIX_EMU_E108_EN )
+ /* Fix for errata EMU_E108 - High Current Consumption on EM4 Entry. */
+ __disable_irq();
+ *(volatile uint32_t *)0x400C80E4 = 0;
+#endif
+
+#if defined( _EMU_DCDCCTRL_MASK )
+ dcdcFetCntSet(true);
+ dcdcHsFixLnBlock();
+#endif
+
+ for (i = 0; i < 4; i++)
+ {
+#if defined( _EMU_EM4CTRL_EM4ENTRY_SHIFT )
+ EMU->EM4CTRL = em4seq2;
+ EMU->EM4CTRL = em4seq3;
+ }
+ EMU->EM4CTRL = em4seq2;
+#else
+ EMU->CTRL = em4seq2;
+ EMU->CTRL = em4seq3;
+ }
+ EMU->CTRL = em4seq2;
+#endif
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Power down memory block.
+ *
+ * @param[in] blocks
+ * Specifies a logical OR of bits indicating memory blocks to power down.
+ * Bit 0 selects block 1, bit 1 selects block 2, etc. Memory block 0 cannot
+ * be disabled. Please refer to the reference manual for available
+ * memory blocks for a device.
+ *
+ * @note
+ * Only a reset can make the specified memory block(s) available for use
+ * after having been powered down. Function will be void for devices not
+ * supporting this feature.
+ ******************************************************************************/
+void EMU_MemPwrDown(uint32_t blocks)
+{
+#if defined( _EMU_MEMCTRL_POWERDOWN_MASK )
+ EFM_ASSERT(blocks <= (_EMU_MEMCTRL_POWERDOWN_MASK
+ >> _EMU_MEMCTRL_POWERDOWN_SHIFT));
+ EMU->MEMCTRL = blocks;
+
+#elif defined( _EMU_MEMCTRL_RAMPOWERDOWN_MASK ) \
+ && defined( _EMU_MEMCTRL_RAMHPOWERDOWN_MASK ) \
+ && defined( _EMU_MEMCTRL_SEQRAMPOWERDOWN_MASK )
+ EFM_ASSERT((blocks & (_EMU_MEMCTRL_RAMPOWERDOWN_MASK
+ | _EMU_MEMCTRL_RAMHPOWERDOWN_MASK
+ | _EMU_MEMCTRL_SEQRAMPOWERDOWN_MASK))
+ == blocks);
+ EMU->MEMCTRL = blocks;
+
+#elif defined( _EMU_MEMCTRL_RAMPOWERDOWN_MASK )
+ EFM_ASSERT((blocks & _EMU_MEMCTRL_RAMPOWERDOWN_MASK) == blocks);
+ EMU->MEMCTRL = blocks;
+
+#elif defined( _EMU_RAM0CTRL_RAMPOWERDOWN_MASK )
+ EFM_ASSERT((blocks & _EMU_RAM0CTRL_RAMPOWERDOWN_MASK) == blocks);
+ EMU->RAM0CTRL = blocks;
+
+#else
+ (void)blocks;
+#endif
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Update EMU module with CMU oscillator selection/enable status.
+ *
+ * @details
+ * When entering EM2 and EM3, the HW may change the core clock oscillator
+ * used, as well as disabling some oscillators. The user may optionally select
+ * to restore the oscillators after waking up from EM2 and EM3 through the
+ * SW API.
+ *
+ * However, in order to support this in a safe way, the EMU module must
+ * be kept up-to-date on the actual selected configuration. The CMU
+ * module must keep the EMU module up-to-date.
+ *
+ * This function is mainly intended for internal use by the CMU module,
+ * but if the applications changes oscillator configurations without
+ * using the CMU API, this function can be used to keep the EMU module
+ * up-to-date.
+ ******************************************************************************/
+void EMU_UpdateOscConfig(void)
+{
+ /* Fetch current configuration */
+ cmuStatus = CMU->STATUS;
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )
+ cmuHfclkStatus = (uint16_t)(CMU->HFCLKSTATUS);
+#endif
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Update EMU module with Energy Mode 2 and 3 configuration
+ *
+ * @param[in] em23Init
+ * Energy Mode 2 and 3 configuration structure
+ ******************************************************************************/
+void EMU_EM23Init(EMU_EM23Init_TypeDef *em23Init)
+{
+#if defined( _EMU_CTRL_EMVREG_MASK )
+ EMU->CTRL = em23Init->em23VregFullEn ? (EMU->CTRL | EMU_CTRL_EMVREG)
+ : (EMU->CTRL & ~EMU_CTRL_EMVREG);
+#elif defined( _EMU_CTRL_EM23VREG_MASK )
+ EMU->CTRL = em23Init->em23VregFullEn ? (EMU->CTRL | EMU_CTRL_EM23VREG)
+ : (EMU->CTRL & ~EMU_CTRL_EM23VREG);
+#else
+ (void)em23Init;
+#endif
+}
+
+
+#if defined( _EMU_EM4CONF_MASK ) || defined( _EMU_EM4CTRL_MASK )
+/***************************************************************************//**
+ * @brief
+ * Update EMU module with Energy Mode 4 configuration
+ *
+ * @param[in] em4Init
+ * Energy Mode 4 configuration structure
+ ******************************************************************************/
+void EMU_EM4Init(EMU_EM4Init_TypeDef *em4Init)
+{
+#if defined( _EMU_EM4CONF_MASK )
+ /* Init for platforms with EMU->EM4CONF register */
+ uint32_t em4conf = EMU->EM4CONF;
+
+ /* Clear fields that will be reconfigured */
+ em4conf &= ~(_EMU_EM4CONF_LOCKCONF_MASK
+ | _EMU_EM4CONF_OSC_MASK
+ | _EMU_EM4CONF_BURTCWU_MASK
+ | _EMU_EM4CONF_VREGEN_MASK);
+
+ /* Configure new settings */
+ em4conf |= (em4Init->lockConfig << _EMU_EM4CONF_LOCKCONF_SHIFT)
+ | (em4Init->osc)
+ | (em4Init->buRtcWakeup << _EMU_EM4CONF_BURTCWU_SHIFT)
+ | (em4Init->vreg << _EMU_EM4CONF_VREGEN_SHIFT);
+
+ /* Apply configuration. Note that lock can be set after this stage. */
+ EMU->EM4CONF = em4conf;
+
+#elif defined( _EMU_EM4CTRL_MASK )
+ /* Init for platforms with EMU->EM4CTRL register */
+
+ uint32_t em4ctrl = EMU->EM4CTRL;
+
+ em4ctrl &= ~(_EMU_EM4CTRL_RETAINLFXO_MASK
+ | _EMU_EM4CTRL_RETAINLFRCO_MASK
+ | _EMU_EM4CTRL_RETAINULFRCO_MASK
+ | _EMU_EM4CTRL_EM4STATE_MASK
+ | _EMU_EM4CTRL_EM4IORETMODE_MASK);
+
+ em4ctrl |= (em4Init->retainLfxo ? EMU_EM4CTRL_RETAINLFXO : 0)
+ | (em4Init->retainLfrco ? EMU_EM4CTRL_RETAINLFRCO : 0)
+ | (em4Init->retainUlfrco ? EMU_EM4CTRL_RETAINULFRCO : 0)
+ | (em4Init->em4State ? EMU_EM4CTRL_EM4STATE_EM4H : 0)
+ | (em4Init->pinRetentionMode);
+
+ EMU->EM4CTRL = em4ctrl;
+#endif
+}
+#endif
+
+
+#if defined( BU_PRESENT )
+/***************************************************************************//**
+ * @brief
+ * Configure Backup Power Domain settings
+ *
+ * @param[in] bupdInit
+ * Backup power domain initialization structure
+ ******************************************************************************/
+void EMU_BUPDInit(EMU_BUPDInit_TypeDef *bupdInit)
+{
+ uint32_t reg;
+
+ /* Set power connection configuration */
+ reg = EMU->PWRCONF & ~(_EMU_PWRCONF_PWRRES_MASK
+ | _EMU_PWRCONF_VOUTSTRONG_MASK
+ | _EMU_PWRCONF_VOUTMED_MASK
+ | _EMU_PWRCONF_VOUTWEAK_MASK);
+
+ reg |= bupdInit->resistor
+ | (bupdInit->voutStrong << _EMU_PWRCONF_VOUTSTRONG_SHIFT)
+ | (bupdInit->voutMed << _EMU_PWRCONF_VOUTMED_SHIFT)
+ | (bupdInit->voutWeak << _EMU_PWRCONF_VOUTWEAK_SHIFT);
+
+ EMU->PWRCONF = reg;
+
+ /* Set backup domain inactive mode configuration */
+ reg = EMU->BUINACT & ~(_EMU_BUINACT_PWRCON_MASK);
+ reg |= (bupdInit->inactivePower);
+ EMU->BUINACT = reg;
+
+ /* Set backup domain active mode configuration */
+ reg = EMU->BUACT & ~(_EMU_BUACT_PWRCON_MASK);
+ reg |= (bupdInit->activePower);
+ EMU->BUACT = reg;
+
+ /* Set power control configuration */
+ reg = EMU->BUCTRL & ~(_EMU_BUCTRL_PROBE_MASK
+ | _EMU_BUCTRL_BODCAL_MASK
+ | _EMU_BUCTRL_STATEN_MASK
+ | _EMU_BUCTRL_EN_MASK);
+
+ /* Note use of ->enable to both enable BUPD, use BU_VIN pin input and
+ release reset */
+ reg |= bupdInit->probe
+ | (bupdInit->bodCal << _EMU_BUCTRL_BODCAL_SHIFT)
+ | (bupdInit->statusPinEnable << _EMU_BUCTRL_STATEN_SHIFT)
+ | (bupdInit->enable << _EMU_BUCTRL_EN_SHIFT);
+
+ /* Enable configuration */
+ EMU->BUCTRL = reg;
+
+ /* If enable is true, enable BU_VIN input power pin, if not disable it */
+ EMU_BUPinEnable(bupdInit->enable);
+
+ /* If enable is true, release BU reset, if not keep reset asserted */
+ BUS_RegBitWrite(&(RMU->CTRL), _RMU_CTRL_BURSTEN_SHIFT, !bupdInit->enable);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Configure Backup Power Domain BOD Threshold value
+ * @note
+ * These values are precalibrated
+ * @param[in] mode Active or Inactive mode
+ * @param[in] value
+ ******************************************************************************/
+void EMU_BUThresholdSet(EMU_BODMode_TypeDef mode, uint32_t value)
+{
+ EFM_ASSERT(value<8);
+ EFM_ASSERT(value<=(_EMU_BUACT_BUEXTHRES_MASK>>_EMU_BUACT_BUEXTHRES_SHIFT));
+
+ switch(mode)
+ {
+ case emuBODMode_Active:
+ EMU->BUACT = (EMU->BUACT & ~_EMU_BUACT_BUEXTHRES_MASK)
+ | (value<<_EMU_BUACT_BUEXTHRES_SHIFT);
+ break;
+ case emuBODMode_Inactive:
+ EMU->BUINACT = (EMU->BUINACT & ~_EMU_BUINACT_BUENTHRES_MASK)
+ | (value<<_EMU_BUINACT_BUENTHRES_SHIFT);
+ break;
+ }
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Configure Backup Power Domain BOD Threshold Range
+ * @note
+ * These values are precalibrated
+ * @param[in] mode Active or Inactive mode
+ * @param[in] value
+ ******************************************************************************/
+void EMU_BUThresRangeSet(EMU_BODMode_TypeDef mode, uint32_t value)
+{
+ EFM_ASSERT(value < 4);
+ EFM_ASSERT(value<=(_EMU_BUACT_BUEXRANGE_MASK>>_EMU_BUACT_BUEXRANGE_SHIFT));
+
+ switch(mode)
+ {
+ case emuBODMode_Active:
+ EMU->BUACT = (EMU->BUACT & ~_EMU_BUACT_BUEXRANGE_MASK)
+ | (value<<_EMU_BUACT_BUEXRANGE_SHIFT);
+ break;
+ case emuBODMode_Inactive:
+ EMU->BUINACT = (EMU->BUINACT & ~_EMU_BUINACT_BUENRANGE_MASK)
+ | (value<<_EMU_BUINACT_BUENRANGE_SHIFT);
+ break;
+ }
+}
+#endif
+
+
+#if defined( _EMU_DCDCCTRL_MASK )
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+/***************************************************************************//**
+ * @brief
+ * Load DCDC calibration constants from DI page. Const means calibration
+ * data that does not change depending on other configuration parameters.
+ *
+ * @return
+ * False if calibration registers are locked
+ ******************************************************************************/
+static bool ConstCalibrationLoad(void)
+{
+ uint32_t val;
+ volatile uint32_t *reg;
+
+ /* DI calib data in flash */
+ volatile uint32_t* const diCal_EMU_DCDCLNFREQCTRL = (volatile uint32_t *)(0x0FE08038);
+ volatile uint32_t* const diCal_EMU_DCDCLNVCTRL = (volatile uint32_t *)(0x0FE08040);
+ volatile uint32_t* const diCal_EMU_DCDCLPCTRL = (volatile uint32_t *)(0x0FE08048);
+ volatile uint32_t* const diCal_EMU_DCDCLPVCTRL = (volatile uint32_t *)(0x0FE08050);
+ volatile uint32_t* const diCal_EMU_DCDCTRIM0 = (volatile uint32_t *)(0x0FE08058);
+ volatile uint32_t* const diCal_EMU_DCDCTRIM1 = (volatile uint32_t *)(0x0FE08060);
+
+ if (DEVINFO->DCDCLPVCTRL0 != UINT_MAX)
+ {
+ val = *(diCal_EMU_DCDCLNFREQCTRL + 1);
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCLNFREQCTRL;
+ *reg = val;
+
+ val = *(diCal_EMU_DCDCLNVCTRL + 1);
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCLNVCTRL;
+ *reg = val;
+
+ val = *(diCal_EMU_DCDCLPCTRL + 1);
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCLPCTRL;
+ *reg = val;
+
+ val = *(diCal_EMU_DCDCLPVCTRL + 1);
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCLPVCTRL;
+ *reg = val;
+
+ val = *(diCal_EMU_DCDCTRIM0 + 1);
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCTRIM0;
+ *reg = val;
+
+ val = *(diCal_EMU_DCDCTRIM1 + 1);
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCTRIM1;
+ *reg = val;
+
+ return true;
+ }
+ EFM_ASSERT(false);
+ /* Return when assertions are disabled */
+ return false;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Set recommended and validated current optimization settings
+ *
+ ******************************************************************************/
+void ValidatedConfigSet(void)
+{
+#define EMU_DCDCSMCTRL (* (volatile uint32_t *)(EMU_BASE + 0x44))
+
+ uint32_t dcdcTiming;
+ SYSTEM_PartFamily_TypeDef family;
+ SYSTEM_ChipRevision_TypeDef rev;
+
+ /* Enable duty cycling of the bias */
+ EMU->DCDCLPCTRL |= EMU_DCDCLPCTRL_LPVREFDUTYEN;
+
+ /* Set low-noise RCO for EFM32 and EFR32 */
+#if defined( _EFR_DEVICE )
+ /* 7MHz is recommended for all EFR32 parts with DCDC */
+ EMU->DCDCLNFREQCTRL = (EMU->DCDCLNFREQCTRL & ~_EMU_DCDCLNFREQCTRL_RCOBAND_MASK)
+ | (EMU_DcdcLnRcoBand_7MHz << _EMU_DCDCLNFREQCTRL_RCOBAND_SHIFT);
+#else
+ /* 3MHz is recommended for all EFM32 parts with DCDC */
+ EMU->DCDCLNFREQCTRL = (EMU->DCDCLNFREQCTRL & ~_EMU_DCDCLNFREQCTRL_RCOBAND_MASK)
+ | (EMU_DcdcLnRcoBand_3MHz << _EMU_DCDCLNFREQCTRL_RCOBAND_SHIFT);
+#endif
+
+ EMU->DCDCTIMING &= ~_EMU_DCDCTIMING_DUTYSCALE_MASK;
+
+ family = SYSTEM_GetFamily();
+ SYSTEM_ChipRevisionGet(&rev);
+ if ((((family >= systemPartFamilyMighty1P)
+ && (family <= systemPartFamilyFlex1V))
+ || (family == systemPartFamilyEfm32Pearl1B)
+ || (family == systemPartFamilyEfm32Jade1B))
+ && ((rev.major == 1) && (rev.minor < 3))
+ && (errataFixDcdcHsState == errataFixDcdcHsInit))
+ {
+ /* LPCMPWAITDIS = 1 */
+ EMU_DCDCSMCTRL |= 1;
+
+ dcdcTiming = EMU->DCDCTIMING;
+ dcdcTiming &= ~(_EMU_DCDCTIMING_LPINITWAIT_MASK
+ |_EMU_DCDCTIMING_LNWAIT_MASK
+ |_EMU_DCDCTIMING_BYPWAIT_MASK);
+
+ dcdcTiming |= ((180 << _EMU_DCDCTIMING_LPINITWAIT_SHIFT)
+ | (12 << _EMU_DCDCTIMING_LNWAIT_SHIFT)
+ | (180 << _EMU_DCDCTIMING_BYPWAIT_SHIFT));
+ EMU->DCDCTIMING = dcdcTiming;
+
+ errataFixDcdcHsState = errataFixDcdcHsTrimSet;
+ }
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Calculate and update EMU->DCDCMISCCTRL for maximum DCDC current based
+ * on the slice configuration and user set maximum.
+ ******************************************************************************/
+static void maxCurrentUpdate(void)
+{
+ uint32_t lncLimImSel;
+ uint32_t lpcLimImSel;
+ uint32_t pFetCnt;
+
+ pFetCnt = (EMU->DCDCMISCCTRL & _EMU_DCDCMISCCTRL_PFETCNT_MASK)
+ >> _EMU_DCDCMISCCTRL_PFETCNT_SHIFT;
+
+ /* Equation from Reference Manual section 11.5.20, in the register
+ field description for LNCLIMILIMSEL and LPCLIMILIMSEL. */
+ lncLimImSel = (dcdcMaxCurrent_mA / (5 * (pFetCnt + 1))) - 1;
+ /* 80mA as recommended in Application Note AN0948 */
+ lpcLimImSel = (80 / (5 * (pFetCnt + 1))) - 1;
+
+ lncLimImSel <<= _EMU_DCDCMISCCTRL_LNCLIMILIMSEL_SHIFT;
+ lpcLimImSel <<= _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_SHIFT;
+ EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~(_EMU_DCDCMISCCTRL_LNCLIMILIMSEL_MASK
+ | _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_MASK))
+ | (lncLimImSel | lpcLimImSel);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Set static variable that holds the user set maximum current. Update
+ * DCDC configuration.
+ *
+ * @param[in] mAmaxCurrent
+ * Maximum allowed current drawn by the DCDC from VREGVDD in mA.
+ ******************************************************************************/
+static void maxCurrentSet(uint32_t mAmaxCurrent)
+{
+ dcdcMaxCurrent_mA = mAmaxCurrent;
+ maxCurrentUpdate();
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Load EMU_DCDCLPCTRL_LPCMPHYSSEL depending on LP bias, LP feedback
+ * attenuation and DEVINFOREV.
+ *
+ * @param[in] attSet
+ * LP feedback attenuation.
+ * @param[in] lpCmpBias
+ * lpCmpBias selection
+ ******************************************************************************/
+static bool LpCmpHystCalibrationLoad(bool lpAttenuation, uint32_t lpCmpBias)
+{
+ uint8_t devinfoRev;
+ uint32_t lpcmpHystSel;
+
+ /* Get calib data revision */
+ devinfoRev = SYSTEM_GetDevinfoRev();
+
+ /* Load LPATT indexed calibration data */
+ if (devinfoRev < 4)
+ {
+ lpcmpHystSel = DEVINFO->DCDCLPCMPHYSSEL0;
+
+ if (lpAttenuation)
+ {
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL0_LPCMPHYSSELLPATT1_MASK)
+ >> _DEVINFO_DCDCLPCMPHYSSEL0_LPCMPHYSSELLPATT1_SHIFT;
+ }
+ else
+ {
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL0_LPCMPHYSSELLPATT0_MASK)
+ >> _DEVINFO_DCDCLPCMPHYSSEL0_LPCMPHYSSELLPATT0_SHIFT;
+ }
+ }
+ /* devinfoRev >= 4
+ Load LPCMPBIAS indexed calibration data */
+ else
+ {
+ lpcmpHystSel = DEVINFO->DCDCLPCMPHYSSEL1;
+ switch (lpCmpBias)
+ {
+ case _EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS0:
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS0_MASK)
+ >> _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS0_SHIFT;
+ break;
+
+ case _EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS1:
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS1_MASK)
+ >> _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS1_SHIFT;
+ break;
+
+ case _EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS2:
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS2_MASK)
+ >> _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS2_SHIFT;
+ break;
+
+ case _EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS3:
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS3_MASK)
+ >> _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS3_SHIFT;
+ break;
+
+ default:
+ EFM_ASSERT(false);
+ /* Return when assertions are disabled */
+ return false;
+ }
+ }
+
+ /* Make sure the sel value is within the field range. */
+ lpcmpHystSel <<= _EMU_DCDCLPCTRL_LPCMPHYSSEL_SHIFT;
+ if (lpcmpHystSel & ~_EMU_DCDCLPCTRL_LPCMPHYSSEL_MASK)
+ {
+ EFM_ASSERT(false);
+ /* Return when assertions are disabled */
+ return false;
+ }
+ EMU->DCDCLPCTRL = (EMU->DCDCLPCTRL & ~_EMU_DCDCLPCTRL_LPCMPHYSSEL_MASK) | lpcmpHystSel;
+
+ return true;
+}
+
+
+/** @endcond */
+
+/***************************************************************************//**
+ * @brief
+ * Set DCDC regulator operating mode
+ *
+ * @param[in] dcdcMode
+ * DCDC mode
+ ******************************************************************************/
+void EMU_DCDCModeSet(EMU_DcdcMode_TypeDef dcdcMode)
+{
+ while(EMU->DCDCSYNC & EMU_DCDCSYNC_DCDCCTRLBUSY);
+ BUS_RegBitWrite(&EMU->DCDCCLIMCTRL, _EMU_DCDCCLIMCTRL_BYPLIMEN_SHIFT, dcdcMode == emuDcdcMode_Bypass ? 0 : 1);
+ EMU->DCDCCTRL = (EMU->DCDCCTRL & ~_EMU_DCDCCTRL_DCDCMODE_MASK) | dcdcMode;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Configure DCDC regulator
+ *
+ * @note
+ * Use the function EMU_DCDCPowerDown() to if the power circuit is configured
+ * for NODCDC as decribed in Section 11.3.4.3 in the Reference Manual.
+ *
+ * @param[in] dcdcInit
+ * DCDC initialization structure
+ *
+ * @return
+ * True if initialization parameters are valid
+ ******************************************************************************/
+bool EMU_DCDCInit(EMU_DCDCInit_TypeDef *dcdcInit)
+{
+ uint32_t lpCmpBiasSel;
+
+ /* Set external power configuration. This enables writing to the other
+ DCDC registers. */
+ EMU->PWRCFG = dcdcInit->powerConfig;
+
+ /* EMU->PWRCFG is write-once and POR reset only. Check that
+ we could set the desired power configuration. */
+ if ((EMU->PWRCFG & _EMU_PWRCFG_PWRCFG_MASK) != dcdcInit->powerConfig)
+ {
+ /* If this assert triggers unexpectedly, please power cycle the
+ kit to reset the power configuration. */
+ EFM_ASSERT(false);
+ /* Return when assertions are disabled */
+ return false;
+ }
+
+ /* Load DCDC calibration data from the DI page */
+ ConstCalibrationLoad();
+
+ /* Check current parameters */
+ EFM_ASSERT(dcdcInit->maxCurrent_mA <= 200);
+ EFM_ASSERT(dcdcInit->em01LoadCurrent_mA <= dcdcInit->maxCurrent_mA);
+
+ /* DCDC low-noise supports max 200mA */
+ if (dcdcInit->dcdcMode == emuDcdcMode_LowNoise)
+ {
+ EFM_ASSERT(dcdcInit->em01LoadCurrent_mA <= 200);
+ }
+
+ /* EM2, 3 and 4 current above 100uA is not supported */
+ EFM_ASSERT(dcdcInit->em234LoadCurrent_uA <= 100);
+
+ /* Decode LP comparator bias for EM0/1 and EM2/3 */
+ lpCmpBiasSel = EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS1;
+ if (dcdcInit->em234LoadCurrent_uA <= 10)
+ {
+ lpCmpBiasSel = EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS0;
+ }
+
+ /* Set DCDC low-power mode comparator bias selection */
+ EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~(_EMU_DCDCMISCCTRL_LPCMPBIAS_MASK
+ | _EMU_DCDCMISCCTRL_LNFORCECCM_MASK))
+ | ((uint32_t)lpCmpBiasSel
+ | (uint32_t)dcdcInit->lnTransientMode);
+
+ /* Set recommended and validated current optimization settings */
+ ValidatedConfigSet();
+
+ /* Set the maximum current that the DCDC can draw from the power source */
+ maxCurrentSet(dcdcInit->maxCurrent_mA);
+
+ /* Optimize LN slice based on given load current estimate */
+ EMU_DCDCOptimizeSlice(dcdcInit->em01LoadCurrent_mA);
+
+ /* Set DCDC output voltage */
+ dcdcOutput_mVout = dcdcInit->mVout;
+ if (!EMU_DCDCOutputVoltageSet(dcdcOutput_mVout, true, true))
+ {
+ EFM_ASSERT(false);
+ /* Return when assertions are disabled */
+ return false;
+ }
+
+ /* Set EM0 DCDC operating mode. Output voltage set in EMU_DCDCOutputVoltageSet()
+ above takes effect if mode is changed from bypass here. */
+ EMU_DCDCModeSet(dcdcInit->dcdcMode);
+
+ /* Select analog peripheral power supply */
+ BUS_RegBitWrite(&EMU->PWRCTRL, _EMU_PWRCTRL_ANASW_SHIFT, dcdcInit->anaPeripheralPower ? 1 : 0);
+
+ return true;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Set DCDC output voltage
+ *
+ * @param[in] mV
+ * Target DCDC output voltage in mV
+ *
+ * @return
+ * True if the mV parameter is valid
+ ******************************************************************************/
+bool EMU_DCDCOutputVoltageSet(uint32_t mV,
+ bool setLpVoltage,
+ bool setLnVoltage)
+{
+#if defined( _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_MASK )
+
+ bool validOutVoltage;
+ uint8_t lnMode;
+ bool attSet;
+ uint32_t attMask;
+ uint32_t vrefLow = 0;
+ uint32_t vrefHigh = 0;
+ uint32_t vrefVal = 0;
+ uint32_t mVlow = 0;
+ uint32_t mVhigh = 0;
+ uint32_t vrefShift;
+ uint32_t lpcmpBias;
+ volatile uint32_t* ctrlReg;
+
+ /* Check that the set voltage is within valid range.
+ Voltages are obtained from the datasheet. */
+ validOutVoltage = false;
+ if ((EMU->PWRCFG & _EMU_PWRCFG_PWRCFG_MASK) == EMU_PWRCFG_PWRCFG_DCDCTODVDD)
+ {
+ validOutVoltage = ((mV >= PWRCFG_DCDCTODVDD_VMIN)
+ && (mV <= PWRCFG_DCDCTODVDD_VMAX));
+ }
+
+ if (!validOutVoltage)
+ {
+ EFM_ASSERT(false);
+ /* Return when assertions are disabled */
+ return false;
+ }
+
+ /* Populate both LP and LN registers, set control reg pointer and VREF shift. */
+ for (lnMode = 0; lnMode <= 1; lnMode++)
+ {
+ if (((lnMode == 0) && !setLpVoltage)
+ || ((lnMode == 1) && !setLnVoltage))
+ {
+ continue;
+ }
+
+ ctrlReg = (lnMode ? &EMU->DCDCLNVCTRL : &EMU->DCDCLPVCTRL);
+ vrefShift = (lnMode ? _EMU_DCDCLNVCTRL_LNVREF_SHIFT
+ : _EMU_DCDCLPVCTRL_LPVREF_SHIFT);
+
+ /* Set attenuation to use */
+ attSet = (mV > 1800);
+ if (attSet)
+ {
+ mVlow = 1800;
+ mVhigh = 3000;
+ attMask = (lnMode ? EMU_DCDCLNVCTRL_LNATT : EMU_DCDCLPVCTRL_LPATT);
+ }
+ else
+ {
+ mVlow = 1200;
+ mVhigh = 1800;
+ attMask = 0;
+ }
+
+ /* Get 2-point calib data from DEVINFO, calculate trimming and set voltege */
+ if (lnMode)
+ {
+ /* Set low-noise DCDC output voltage tuning */
+ if (attSet)
+ {
+ vrefLow = DEVINFO->DCDCLNVCTRL0;
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_MASK)
+ >> _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_SHIFT;
+ vrefLow = (vrefLow & _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_MASK)
+ >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_SHIFT;
+ }
+ else
+ {
+ vrefLow = DEVINFO->DCDCLNVCTRL0;
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_MASK)
+ >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_SHIFT;
+ vrefLow = (vrefLow & _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_MASK)
+ >> _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_SHIFT;
+ }
+ }
+ else
+ {
+ /* Set low-power DCDC output voltage tuning */
+
+ /* Get LPCMPBIAS and make sure masks are not overlayed */
+ lpcmpBias = EMU->DCDCMISCCTRL & _EMU_DCDCMISCCTRL_LPCMPBIAS_MASK;
+ EFM_ASSERT(!(_EMU_DCDCMISCCTRL_LPCMPBIAS_MASK & attMask));
+ switch (attMask | lpcmpBias)
+ {
+ case EMU_DCDCLPVCTRL_LPATT | EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS0:
+ vrefLow = DEVINFO->DCDCLPVCTRL2;
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_MASK)
+ >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_SHIFT;
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_MASK)
+ >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_SHIFT;
+ break;
+
+ case EMU_DCDCLPVCTRL_LPATT | EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS1:
+ vrefLow = DEVINFO->DCDCLPVCTRL2;
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_MASK)
+ >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_SHIFT;
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_MASK)
+ >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_SHIFT;
+ break;
+
+ case EMU_DCDCLPVCTRL_LPATT | EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS2:
+ vrefLow = DEVINFO->DCDCLPVCTRL3;
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_MASK)
+ >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_SHIFT;
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_MASK)
+ >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_SHIFT;
+ break;
+
+ case EMU_DCDCLPVCTRL_LPATT | EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS3:
+ vrefLow = DEVINFO->DCDCLPVCTRL3;
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_MASK)
+ >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_SHIFT;
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_MASK)
+ >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_SHIFT;
+ break;
+
+ case EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS0:
+ vrefLow = DEVINFO->DCDCLPVCTRL0;
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL0_1V8LPATT0LPCMPBIAS0_MASK)
+ >> _DEVINFO_DCDCLPVCTRL0_1V8LPATT0LPCMPBIAS0_SHIFT;
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL0_1V2LPATT0LPCMPBIAS0_MASK)
+ >> _DEVINFO_DCDCLPVCTRL0_1V2LPATT0LPCMPBIAS0_SHIFT;
+ break;
+
+ case EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS1:
+ vrefLow = DEVINFO->DCDCLPVCTRL0;
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL0_1V8LPATT0LPCMPBIAS1_MASK)
+ >> _DEVINFO_DCDCLPVCTRL0_1V8LPATT0LPCMPBIAS1_SHIFT;
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL0_1V2LPATT0LPCMPBIAS1_MASK)
+ >> _DEVINFO_DCDCLPVCTRL0_1V2LPATT0LPCMPBIAS1_SHIFT;
+ break;
+
+ case EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS2:
+ vrefLow = DEVINFO->DCDCLPVCTRL1;
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL1_1V8LPATT0LPCMPBIAS2_MASK)
+ >> _DEVINFO_DCDCLPVCTRL1_1V8LPATT0LPCMPBIAS2_SHIFT;
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL1_1V2LPATT0LPCMPBIAS2_MASK)
+ >> _DEVINFO_DCDCLPVCTRL1_1V2LPATT0LPCMPBIAS2_SHIFT;
+ break;
+
+ case EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS3:
+ vrefLow = DEVINFO->DCDCLPVCTRL1;
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL1_1V8LPATT0LPCMPBIAS3_MASK)
+ >> _DEVINFO_DCDCLPVCTRL1_1V8LPATT0LPCMPBIAS3_SHIFT;
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL1_1V2LPATT0LPCMPBIAS3_MASK)
+ >> _DEVINFO_DCDCLPVCTRL1_1V2LPATT0LPCMPBIAS3_SHIFT;
+ break;
+
+ default:
+ EFM_ASSERT(false);
+ break;
+ }
+
+ /* Load LP comparator hysteresis calibration */
+ if(!(LpCmpHystCalibrationLoad(attSet, lpcmpBias >> _EMU_DCDCMISCCTRL_LPCMPBIAS_SHIFT)))
+ {
+ EFM_ASSERT(false);
+ /* Return when assertions are disabled */
+ return false;
+ }
+ } /* Low-nise / low-power mode */
+
+
+ /* Check for valid 2-point trim values */
+ if ((vrefLow == 0xFF) && (vrefHigh == 0xFF))
+ {
+ EFM_ASSERT(false);
+ /* Return when assertions are disabled */
+ return false;
+ }
+
+ /* Calculate and set voltage trim */
+ vrefVal = ((mV - mVlow) * (vrefHigh - vrefLow)) / (mVhigh - mVlow);
+ vrefVal += vrefLow;
+
+ /* Range check */
+ if ((vrefVal > vrefHigh) || (vrefVal < vrefLow))
+ {
+ EFM_ASSERT(false);
+ /* Return when assertions are disabled */
+ return false;
+ }
+
+ /* Update DCDCLNVCTRL/DCDCLPVCTRL */
+ *ctrlReg = (vrefVal << vrefShift) | attMask;
+ }
+#endif
+ return true;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Optimize DCDC slice count based on the estimated average load current
+ * in EM0
+ *
+ * @param[in] mAEm0LoadCurrent
+ * Estimated average EM0 load current in mA.
+ ******************************************************************************/
+void EMU_DCDCOptimizeSlice(uint32_t mAEm0LoadCurrent)
+{
+ uint32_t sliceCount = 0;
+ uint32_t rcoBand = (EMU->DCDCLNFREQCTRL & _EMU_DCDCLNFREQCTRL_RCOBAND_MASK)
+ >> _EMU_DCDCLNFREQCTRL_RCOBAND_SHIFT;
+
+ /* Set recommended slice count */
+ if ((EMU->DCDCMISCCTRL & _EMU_DCDCMISCCTRL_LNFORCECCM_MASK) && (rcoBand >= EMU_DcdcLnRcoBand_5MHz))
+ {
+ if (mAEm0LoadCurrent < 20)
+ {
+ sliceCount = 4;
+ }
+ else if ((mAEm0LoadCurrent >= 20) && (mAEm0LoadCurrent < 40))
+ {
+ sliceCount = 8;
+ }
+ else
+ {
+ sliceCount = 16;
+ }
+ }
+ else if ((!(EMU->DCDCMISCCTRL & _EMU_DCDCMISCCTRL_LNFORCECCM_MASK)) && (rcoBand <= EMU_DcdcLnRcoBand_4MHz))
+ {
+ if (mAEm0LoadCurrent < 10)
+ {
+ sliceCount = 4;
+ }
+ else if ((mAEm0LoadCurrent >= 10) && (mAEm0LoadCurrent < 20))
+ {
+ sliceCount = 8;
+ }
+ else
+ {
+ sliceCount = 16;
+ }
+ }
+ else if ((EMU->DCDCMISCCTRL & _EMU_DCDCMISCCTRL_LNFORCECCM_MASK) && (rcoBand <= EMU_DcdcLnRcoBand_4MHz))
+ {
+ if (mAEm0LoadCurrent < 40)
+ {
+ sliceCount = 8;
+ }
+ else
+ {
+ sliceCount = 16;
+ }
+ }
+ else
+ {
+ /* This configuration is not recommended. EMU_DCDCInit() applies a recommended
+ configuration. */
+ EFM_ASSERT(false);
+ }
+
+ /* The selected silices are PSLICESEL + 1 */
+ sliceCount--;
+
+ /* Apply slice count to both N and P slice */
+ sliceCount = (sliceCount << _EMU_DCDCMISCCTRL_PFETCNT_SHIFT
+ | sliceCount << _EMU_DCDCMISCCTRL_NFETCNT_SHIFT);
+ EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~(_EMU_DCDCMISCCTRL_PFETCNT_MASK
+ | _EMU_DCDCMISCCTRL_NFETCNT_MASK))
+ | sliceCount;
+
+ /* Update current limit configuration as it depends on the slice configuration. */
+ maxCurrentUpdate();
+}
+
+/***************************************************************************//**
+ * @brief
+ * Set DCDC Low-noise RCO band.
+ *
+ * @param[in] band
+ * RCO band to set.
+ ******************************************************************************/
+void EMU_DCDCLnRcoBandSet(EMU_DcdcLnRcoBand_TypeDef band)
+{
+ EMU->DCDCLNFREQCTRL = (EMU->DCDCLNFREQCTRL & ~_EMU_DCDCLNFREQCTRL_RCOBAND_MASK)
+ | (band << _EMU_DCDCLNFREQCTRL_RCOBAND_SHIFT);
+}
+
+/***************************************************************************//**
+ * @brief
+ * Power off the DCDC regulator.
+ *
+ * @details
+ * This function powers off the DCDC controller. This function should only be
+ * used if the external power circuit is wired for no DCDC. If the external power
+ * circuit is wired for DCDC usage, then use EMU_DCDCInit() and set the
+ * DCDC in bypass mode to disable DCDC.
+ *
+ * @return
+ * Return false if the DCDC could not be disabled.
+ ******************************************************************************/
+bool EMU_DCDCPowerOff(void)
+{
+ /* Set power configuration to hard bypass */
+ EMU->PWRCFG = 0xF;
+ if ((EMU->PWRCFG & _EMU_PWRCFG_PWRCFG_MASK) != 0xF)
+ {
+ EFM_ASSERT(false);
+ /* Return when assertions are disabled */
+ return false;
+ }
+
+ /* Set DCDC to OFF and disable LP in EM2/3/4 */
+ EMU->DCDCCTRL = EMU_DCDCCTRL_DCDCMODE_OFF;
+ return true;
+}
+#endif
+
+
+#if defined( EMU_STATUS_VMONRDY )
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+__STATIC_INLINE uint32_t vmonMilliVoltToCoarseThreshold(int mV)
+{
+ return (mV - 1200) / 200;
+}
+
+__STATIC_INLINE uint32_t vmonMilliVoltToFineThreshold(int mV, uint32_t coarseThreshold)
+{
+ return (mV - 1200 - (coarseThreshold * 200)) / 20;
+}
+/** @endcond */
+
+/***************************************************************************//**
+ * @brief
+ * Initialize VMON channel.
+ *
+ * @details
+ * Initialize a VMON channel without hysteresis. If the channel supports
+ * separate rise and fall triggers, both thresholds will be set to the same
+ * value.
+ *
+ * @param[in] vmonInit
+ * VMON initialization struct
+ ******************************************************************************/
+void EMU_VmonInit(EMU_VmonInit_TypeDef *vmonInit)
+{
+ uint32_t thresholdCoarse, thresholdFine;
+ EFM_ASSERT((vmonInit->threshold >= 1200) && (vmonInit->threshold <= 3980));
+
+ thresholdCoarse = vmonMilliVoltToCoarseThreshold(vmonInit->threshold);
+ thresholdFine = vmonMilliVoltToFineThreshold(vmonInit->threshold, thresholdCoarse);
+
+ switch(vmonInit->channel)
+ {
+ case emuVmonChannel_AVDD:
+ EMU->VMONAVDDCTRL = (thresholdCoarse << _EMU_VMONAVDDCTRL_RISETHRESCOARSE_SHIFT)
+ | (thresholdFine << _EMU_VMONAVDDCTRL_RISETHRESFINE_SHIFT)
+ | (thresholdCoarse << _EMU_VMONAVDDCTRL_FALLTHRESCOARSE_SHIFT)
+ | (thresholdFine << _EMU_VMONAVDDCTRL_FALLTHRESFINE_SHIFT)
+ | (vmonInit->riseWakeup ? EMU_VMONAVDDCTRL_RISEWU : 0)
+ | (vmonInit->fallWakeup ? EMU_VMONAVDDCTRL_FALLWU : 0)
+ | (vmonInit->enable ? EMU_VMONAVDDCTRL_EN : 0);
+ break;
+ case emuVmonChannel_ALTAVDD:
+ EMU->VMONALTAVDDCTRL = (thresholdCoarse << _EMU_VMONALTAVDDCTRL_THRESCOARSE_SHIFT)
+ | (thresholdFine << _EMU_VMONALTAVDDCTRL_THRESFINE_SHIFT)
+ | (vmonInit->riseWakeup ? EMU_VMONALTAVDDCTRL_RISEWU : 0)
+ | (vmonInit->fallWakeup ? EMU_VMONALTAVDDCTRL_FALLWU : 0)
+ | (vmonInit->enable ? EMU_VMONALTAVDDCTRL_EN : 0);
+ break;
+ case emuVmonChannel_DVDD:
+ EMU->VMONDVDDCTRL = (thresholdCoarse << _EMU_VMONDVDDCTRL_THRESCOARSE_SHIFT)
+ | (thresholdFine << _EMU_VMONDVDDCTRL_THRESFINE_SHIFT)
+ | (vmonInit->riseWakeup ? EMU_VMONDVDDCTRL_RISEWU : 0)
+ | (vmonInit->fallWakeup ? EMU_VMONDVDDCTRL_FALLWU : 0)
+ | (vmonInit->enable ? EMU_VMONDVDDCTRL_EN : 0);
+ break;
+ case emuVmonChannel_IOVDD0:
+ EMU->VMONIO0CTRL = (thresholdCoarse << _EMU_VMONIO0CTRL_THRESCOARSE_SHIFT)
+ | (thresholdFine << _EMU_VMONIO0CTRL_THRESFINE_SHIFT)
+ | (vmonInit->retDisable ? EMU_VMONIO0CTRL_RETDIS : 0)
+ | (vmonInit->riseWakeup ? EMU_VMONIO0CTRL_RISEWU : 0)
+ | (vmonInit->fallWakeup ? EMU_VMONIO0CTRL_FALLWU : 0)
+ | (vmonInit->enable ? EMU_VMONIO0CTRL_EN : 0);
+ break;
+ default:
+ EFM_ASSERT(false);
+ return;
+ }
+}
+
+/***************************************************************************//**
+ * @brief
+ * Initialize VMON channel with hysteresis (separate rise and fall triggers).
+ *
+ * @details
+ * Initialize a VMON channel which supports hysteresis. The AVDD channel is
+ * the only channel to support separate rise and fall triggers.
+ *
+ * @param[in] vmonInit
+ * VMON Hysteresis initialization struct
+ ******************************************************************************/
+void EMU_VmonHystInit(EMU_VmonHystInit_TypeDef *vmonInit)
+{
+ uint32_t riseThresholdCoarse, riseThresholdFine, fallThresholdCoarse, fallThresholdFine;
+ /* VMON supports voltages between 1200 mV and 3980 mV (inclusive) in 20 mV increments */
+ EFM_ASSERT((vmonInit->riseThreshold >= 1200) && (vmonInit->riseThreshold < 4000));
+ EFM_ASSERT((vmonInit->fallThreshold >= 1200) && (vmonInit->fallThreshold < 4000));
+ /* Fall threshold has to be lower than rise threshold */
+ EFM_ASSERT(vmonInit->fallThreshold <= vmonInit->riseThreshold);
+
+ riseThresholdCoarse = vmonMilliVoltToCoarseThreshold(vmonInit->riseThreshold);
+ riseThresholdFine = vmonMilliVoltToFineThreshold(vmonInit->riseThreshold, riseThresholdCoarse);
+ fallThresholdCoarse = vmonMilliVoltToCoarseThreshold(vmonInit->fallThreshold);
+ fallThresholdFine = vmonMilliVoltToFineThreshold(vmonInit->fallThreshold, fallThresholdCoarse);
+
+ switch(vmonInit->channel)
+ {
+ case emuVmonChannel_AVDD:
+ EMU->VMONAVDDCTRL = (riseThresholdCoarse << _EMU_VMONAVDDCTRL_RISETHRESCOARSE_SHIFT)
+ | (riseThresholdFine << _EMU_VMONAVDDCTRL_RISETHRESFINE_SHIFT)
+ | (fallThresholdCoarse << _EMU_VMONAVDDCTRL_FALLTHRESCOARSE_SHIFT)
+ | (fallThresholdFine << _EMU_VMONAVDDCTRL_FALLTHRESFINE_SHIFT)
+ | (vmonInit->riseWakeup ? EMU_VMONAVDDCTRL_RISEWU : 0)
+ | (vmonInit->fallWakeup ? EMU_VMONAVDDCTRL_FALLWU : 0)
+ | (vmonInit->enable ? EMU_VMONAVDDCTRL_EN : 0);
+ break;
+ default:
+ EFM_ASSERT(false);
+ return;
+ }
+}
+
+/***************************************************************************//**
+ * @brief
+ * Enable or disable a VMON channel
+ *
+ * @param[in] channel
+ * VMON channel to enable/disable
+ *
+ * @param[in] enable
+ * Whether to enable or disable
+ ******************************************************************************/
+void EMU_VmonEnable(EMU_VmonChannel_TypeDef channel, bool enable)
+{
+ uint32_t volatile * reg;
+ uint32_t bit;
+
+ switch(channel)
+ {
+ case emuVmonChannel_AVDD:
+ reg = &(EMU->VMONAVDDCTRL);
+ bit = _EMU_VMONAVDDCTRL_EN_SHIFT;
+ break;
+ case emuVmonChannel_ALTAVDD:
+ reg = &(EMU->VMONALTAVDDCTRL);
+ bit = _EMU_VMONALTAVDDCTRL_EN_SHIFT;
+ break;
+ case emuVmonChannel_DVDD:
+ reg = &(EMU->VMONDVDDCTRL);
+ bit = _EMU_VMONDVDDCTRL_EN_SHIFT;
+ break;
+ case emuVmonChannel_IOVDD0:
+ reg = &(EMU->VMONIO0CTRL);
+ bit = _EMU_VMONIO0CTRL_EN_SHIFT;
+ break;
+ default:
+ EFM_ASSERT(false);
+ return;
+ }
+
+ BUS_RegBitWrite(reg, bit, enable);
+}
+
+/***************************************************************************//**
+ * @brief
+ * Get the status of a voltage monitor channel.
+ *
+ * @param[in] channel
+ * VMON channel to get status for
+ *
+ * @return
+ * Status of the selected VMON channel. True if channel is triggered.
+ ******************************************************************************/
+bool EMU_VmonChannelStatusGet(EMU_VmonChannel_TypeDef channel)
+{
+ uint32_t bit;
+ switch(channel)
+ {
+ case emuVmonChannel_AVDD:
+ bit = _EMU_STATUS_VMONAVDD_SHIFT;
+ break;
+ case emuVmonChannel_ALTAVDD:
+ bit = _EMU_STATUS_VMONALTAVDD_SHIFT;
+ break;
+ case emuVmonChannel_DVDD:
+ bit = _EMU_STATUS_VMONDVDD_SHIFT;
+ break;
+ case emuVmonChannel_IOVDD0:
+ bit = _EMU_STATUS_VMONIO0_SHIFT;
+ break;
+ default:
+ EFM_ASSERT(false);
+ bit = 0;
+ }
+
+ return BUS_RegBitRead(&EMU->STATUS, bit);
+}
+#endif /* EMU_STATUS_VMONRDY */
+
+/** @} (end addtogroup EMU) */
+/** @} (end addtogroup EM_Library) */
+#endif /* __EM_EMU_H */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_gpio.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_gpio.c new file mode 100644 index 000000000..46db33557 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_gpio.c @@ -0,0 +1,320 @@ +/***************************************************************************//**
+ * @file em_gpio.c
+ * @brief General Purpose IO (GPIO) peripheral API
+ * devices.
+ * @version 4.2.1
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+
+#include "em_gpio.h"
+
+#if defined(GPIO_COUNT) && (GPIO_COUNT > 0)
+
+/***************************************************************************//**
+ * @addtogroup EM_Library
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup GPIO
+ * @brief General Purpose Input/Output (GPIO) API
+ * @{
+ ******************************************************************************/
+
+/*******************************************************************************
+ ******************************* DEFINES ***********************************
+ ******************************************************************************/
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+/** Validation of pin typically usable in assert statements. */
+#define GPIO_DRIVEMODE_VALID(mode) ((mode) <= 3)
+#define GPIO_STRENGHT_VALID(strenght) (!((strenght) & \
+ ~(_GPIO_P_CTRL_DRIVESTRENGTH_MASK \
+ | _GPIO_P_CTRL_DRIVESTRENGTHALT_MASK)))
+/** @endcond */
+
+
+/*******************************************************************************
+ ************************** GLOBAL FUNCTIONS *******************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief
+ * Sets the pin location of the debug pins (Serial Wire interface).
+ *
+ * @note
+ * Changing the pins used for debugging uncontrolled, may result in a lockout.
+ *
+ * @param[in] location
+ * The debug pin location to use (0-3).
+ ******************************************************************************/
+void GPIO_DbgLocationSet(unsigned int location)
+{
+#if defined ( _GPIO_ROUTE_SWLOCATION_MASK )
+ EFM_ASSERT(location < AFCHANLOC_MAX);
+
+ GPIO->ROUTE = (GPIO->ROUTE & ~_GPIO_ROUTE_SWLOCATION_MASK) |
+ (location << _GPIO_ROUTE_SWLOCATION_SHIFT);
+#else
+ (void)location;
+#endif
+}
+
+#if defined (_GPIO_P_CTRL_DRIVEMODE_MASK)
+/***************************************************************************//**
+ * @brief
+ * Sets the drive mode for a GPIO port.
+ *
+ * @param[in] port
+ * The GPIO port to access.
+ *
+ * @param[in] mode
+ * Drive mode to use for port.
+ ******************************************************************************/
+void GPIO_DriveModeSet(GPIO_Port_TypeDef port, GPIO_DriveMode_TypeDef mode)
+{
+ EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_DRIVEMODE_VALID(mode));
+
+ GPIO->P[port].CTRL = (GPIO->P[port].CTRL & ~(_GPIO_P_CTRL_DRIVEMODE_MASK))
+ | (mode << _GPIO_P_CTRL_DRIVEMODE_SHIFT);
+}
+#endif
+
+
+#if defined (_GPIO_P_CTRL_DRIVESTRENGTH_MASK)
+/***************************************************************************//**
+ * @brief
+ * Sets the drive strength for a GPIO port.
+ *
+ * @param[in] port
+ * The GPIO port to access.
+ *
+ * @param[in] strength
+ * Drive strength to use for port.
+ ******************************************************************************/
+void GPIO_DriveStrengthSet(GPIO_Port_TypeDef port,
+ GPIO_DriveStrength_TypeDef strength)
+{
+ EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_STRENGHT_VALID(strength));
+ BUS_RegMaskedWrite(&GPIO->P[port].CTRL,
+ _GPIO_P_CTRL_DRIVESTRENGTH_MASK | _GPIO_P_CTRL_DRIVESTRENGTHALT_MASK,
+ strength);
+}
+#endif
+
+/***************************************************************************//**
+ * @brief
+ * Configure GPIO interrupt.
+ *
+ * @details
+ * If reconfiguring a GPIO interrupt that is already enabled, it is generally
+ * recommended to disable it first, see GPIO_Disable().
+ *
+ * The actual GPIO interrupt handler must be in place before enabling the
+ * interrupt.
+ *
+ * Notice that any pending interrupt for the selected pin is cleared by this
+ * function.
+ *
+ * @note
+ * A certain pin number can only be associated with one port. Ie, if GPIO
+ * interrupt 1 is assigned to port A/pin 1, then it is not possibly to use
+ * pin 1 from any other ports for interrupts. Please refer to the reference
+ * manual.
+ *
+ * @param[in] port
+ * The port to associate with @p pin.
+ *
+ * @param[in] pin
+ * The GPIO interrupt number (= port pin).
+ *
+ * @param[in] risingEdge
+ * Set to true if interrupts shall be enabled on rising edge, otherwise false.
+ *
+ * @param[in] fallingEdge
+ * Set to true if interrupts shall be enabled on falling edge, otherwise false.
+ *
+ * @param[in] enable
+ * Set to true if interrupt shall be enabled after configuration completed,
+ * false to leave disabled. See GPIO_IntDisable() and GPIO_IntEnable().
+ ******************************************************************************/
+void GPIO_IntConfig(GPIO_Port_TypeDef port,
+ unsigned int pin,
+ bool risingEdge,
+ bool fallingEdge,
+ bool enable)
+{
+ uint32_t tmp;
+
+ EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));
+
+ /* There are two registers controlling the interrupt configuration:
+ * The EXTIPSELL register controls pins 0-7 and EXTIPSELH controls
+ * pins 8-15. */
+ if (pin < 8)
+ {
+ BUS_RegMaskedWrite(&GPIO->EXTIPSELL,
+ 0xF << (4 * pin),
+ port << (4 * pin));
+ }
+ else
+ {
+ tmp = pin - 8;
+ BUS_RegMaskedWrite(&GPIO->EXTIPSELH,
+ 0xF << (4 * tmp),
+ port << (4 * tmp));
+ }
+
+ /* Enable/disable rising edge */
+ BUS_RegBitWrite(&(GPIO->EXTIRISE), pin, risingEdge);
+
+ /* Enable/disable falling edge */
+ BUS_RegBitWrite(&(GPIO->EXTIFALL), pin, fallingEdge);
+
+ /* Clear any pending interrupt */
+ GPIO->IFC = 1 << pin;
+
+ /* Finally enable/disable interrupt */
+ BUS_RegBitWrite(&(GPIO->IEN), pin, enable);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ * Set the mode for a GPIO pin.
+ *
+ * @param[in] port
+ * The GPIO port to access.
+ *
+ * @param[in] pin
+ * The pin number in the port.
+ *
+ * @param[in] mode
+ * The desired pin mode.
+ *
+ * @param[in] out
+ * Value to set for pin in DOUT register. The DOUT setting is important for
+ * even some input mode configurations, determining pull-up/down direction.
+ ******************************************************************************/
+void GPIO_PinModeSet(GPIO_Port_TypeDef port,
+ unsigned int pin,
+ GPIO_Mode_TypeDef mode,
+ unsigned int out)
+{
+ EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));
+
+ /* If disabling pin, do not modify DOUT in order to reduce chance for */
+ /* glitch/spike (may not be sufficient precaution in all use cases) */
+ if (mode != gpioModeDisabled)
+ {
+ if (out)
+ {
+ GPIO_PinOutSet(port, pin);
+ }
+ else
+ {
+ GPIO_PinOutClear(port, pin);
+ }
+ }
+
+ /* There are two registers controlling the pins for each port. The MODEL
+ * register controls pins 0-7 and MODEH controls pins 8-15. */
+ if (pin < 8)
+ {
+ BUS_RegMaskedWrite(&GPIO->P[port].MODEL,
+ 0xF << (pin * 4),
+ mode << (pin * 4));
+ }
+ else
+ {
+ BUS_RegMaskedWrite(&GPIO->P[port].MODEH,
+ 0xF << ((pin - 8) * 4),
+ mode << ((pin - 8) * 4));
+ }
+
+ if (mode == gpioModeDisabled)
+ {
+ if (out)
+ {
+ GPIO_PinOutSet(port, pin);
+ }
+ else
+ {
+ GPIO_PinOutClear(port, pin);
+ }
+ }
+}
+
+#if defined( _GPIO_EM4WUEN_MASK )
+/**************************************************************************//**
+ * @brief
+ * Enable GPIO pin wake-up from EM4. When the function exits,
+ * EM4 mode can be safely entered.
+ *
+ * @note
+ * It is assumed that the GPIO pin modes are set correctly.
+ * Valid modes are @ref gpioModeInput and @ref gpioModeInputPull.
+ *
+ * @param[in] pinmask
+ * Bitmask containing the bitwise logic OR of which GPIO pin(s) to enable.
+ * Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
+ * @param[in] polaritymask
+ * Bitmask containing the bitwise logic OR of GPIO pin(s) wake-up polarity.
+ * Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
+ *****************************************************************************/
+void GPIO_EM4EnablePinWakeup(uint32_t pinmask, uint32_t polaritymask)
+{
+ EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0);
+
+#if defined( _GPIO_EM4WUPOL_MASK )
+ EFM_ASSERT((polaritymask & ~_GPIO_EM4WUPOL_MASK) == 0);
+ GPIO->EM4WUPOL &= ~pinmask; /* Set wakeup polarity */
+ GPIO->EM4WUPOL |= pinmask & polaritymask;
+#elif defined( _GPIO_EXTILEVEL_MASK )
+ EFM_ASSERT((polaritymask & ~_GPIO_EXTILEVEL_MASK) == 0);
+ GPIO->EXTILEVEL &= ~pinmask;
+ GPIO->EXTILEVEL |= pinmask & polaritymask;
+#endif
+ GPIO->EM4WUEN |= pinmask; /* Enable wakeup */
+
+ GPIO_EM4SetPinRetention(true); /* Enable pin retention */
+
+#if defined( _GPIO_CMD_EM4WUCLR_MASK )
+ GPIO->CMD = GPIO_CMD_EM4WUCLR; /* Clear wake-up logic */
+#elif defined( _GPIO_IFC_EM4WU_MASK )
+ GPIO_IntClear(pinmask);
+#endif
+}
+#endif
+
+/** @} (end addtogroup GPIO) */
+/** @} (end addtogroup EM_Library) */
+
+#endif /* defined(GPIO_COUNT) && (GPIO_COUNT > 0) */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_int.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_int.c new file mode 100644 index 000000000..cab8c3416 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_int.c @@ -0,0 +1,73 @@ +/**************************************************************************//**
+ * @file em_int.c
+ * @brief Interrupt enable/disable unit API
+ * @version 4.2.1
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+#include <stdint.h>
+#include "em_int.h"
+
+/***************************************************************************//**
+ * @addtogroup EM_Library
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup INT
+ * @brief Safe nesting of interrupt disable/enable API
+ * @{
+ * @details
+ * This module contains functions to safely disable and enable interrupts
+ * at CPU level. INT_Disable() disables interrupts globally and increments a lock
+ * level counter (counting semaphore). INT_Enable() decrements the lock level
+ * counter and enable interrupts if the counter reaches zero.
+ *
+ * These functions would normally be used to secure critical regions, and
+ * to make sure that a critical section that calls into another critical
+ * section does not unintentionally terminate the callee critical section.
+ *
+ * These functions should also be used inside interrupt handlers:
+ * @verbatim
+ * void SysTick_Handler(void)
+ * {
+ * INT_Disable();
+ * .
+ * .
+ * .
+ * INT_Enable();
+ * }
+ * @endverbatim
+ ******************************************************************************/
+
+/** Interrupt lock level counter. Set to zero initially as we normally enter
+ * main with interrupts enabled */
+uint32_t INT_LockCnt = 0;
+
+/** @} (end addtogroup INT) */
+/** @} (end addtogroup EM_Library) */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_rtcc.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_rtcc.c new file mode 100644 index 000000000..c2b0fb57f --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_rtcc.c @@ -0,0 +1,180 @@ +/***************************************************************************//**
+ * @file
+ * @brief Real Time Counter with Calendar (RTCC) Peripheral API
+ * @version 4.2.1
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+#include "em_rtcc.h"
+#if defined( RTCC_COUNT ) && ( RTCC_COUNT == 1 )
+#include "em_bus.h"
+
+/***************************************************************************//**
+ * @addtogroup EM_Library
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup RTCC
+ * @brief Real Time Counter (RTCC) Peripheral API
+ * @{
+ ******************************************************************************/
+
+/*******************************************************************************
+ ******************************* DEFINES ***********************************
+ ******************************************************************************/
+
+/*******************************************************************************
+ ************************** LOCAL FUNCTIONS ********************************
+ ******************************************************************************/
+
+/*******************************************************************************
+ ************************** GLOBAL FUNCTIONS *******************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief
+ * Configure the selected capture/compare channel of the RTCC.
+ *
+ * @details
+ * Use this function to configure a RTCC channel.
+ * Select capture/compare mode, match output action, overflow output action
+ * and PRS input configuration.
+ * Refer to the configuration structure @ref RTCC_CCChConf_TypeDef for more
+ * details.
+ *
+ * @param[in] ch
+ * Channel selector.
+ *
+ * @param[in] confPtr
+ * Pointer to configuration structure.
+ ******************************************************************************/
+void RTCC_ChannelInit( int ch, RTCC_CCChConf_TypeDef const *confPtr )
+{
+ EFM_ASSERT( RTCC_CH_VALID( ch ) );
+ EFM_ASSERT( (uint32_t)confPtr->compMask
+ < ( _RTCC_CC_CTRL_COMPMASK_MASK >> _RTCC_CC_CTRL_COMPMASK_SHIFT )
+ + 1 );
+
+ /** Configure the selected capture/compare channel. */
+ RTCC->CC[ch].CTRL = ( (uint32_t)confPtr->chMode << _RTCC_CC_CTRL_MODE_SHIFT )
+ | ( (uint32_t)confPtr->compMatchOutAction << _RTCC_CC_CTRL_CMOA_SHIFT )
+ | ( (uint32_t)confPtr->prsSel << _RTCC_CC_CTRL_PRSSEL_SHIFT )
+ | ( (uint32_t)confPtr->inputEdgeSel << _RTCC_CC_CTRL_ICEDGE_SHIFT )
+ | ( (uint32_t)confPtr->compBase << _RTCC_CC_CTRL_COMPBASE_SHIFT )
+ | ( (uint32_t)confPtr->compMask << _RTCC_CC_CTRL_COMPMASK_SHIFT )
+ | ( (uint32_t)confPtr->dayCompMode << _RTCC_CC_CTRL_DAYCC_SHIFT );
+}
+
+/***************************************************************************//**
+ * @brief
+ * Enable/disable RTCC.
+ *
+ * @param[in] enable
+ * True to enable RTCC, false to disable.
+ ******************************************************************************/
+void RTCC_Enable( bool enable )
+{
+ /* Bitbanding the enable bit in the CTRL register (atomic). */
+ BUS_RegBitWrite((&RTCC->CTRL), _RTCC_CTRL_ENABLE_SHIFT, enable);
+}
+
+/***************************************************************************//**
+ * @brief
+ * Initialize RTCC.
+ *
+ * @details
+ * Note that the compare values must be set separately with RTCC_CompareSet().
+ * That should probably be done prior to the use of this function if
+ * configuring the RTCC to start when initialization is completed.
+ *
+ * @param[in] init
+ * Pointer to RTCC initialization structure.
+ ******************************************************************************/
+void RTCC_Init( const RTCC_Init_TypeDef *init )
+{
+ RTCC->CTRL = ( (uint32_t)init->enable << _RTCC_CTRL_ENABLE_SHIFT )
+ | ( (uint32_t)init->debugRun << _RTCC_CTRL_DEBUGRUN_SHIFT )
+ | ( (uint32_t)init->precntWrapOnCCV0 << _RTCC_CTRL_PRECCV0TOP_SHIFT )
+ | ( (uint32_t)init->cntWrapOnCCV1 << _RTCC_CTRL_CCV1TOP_SHIFT )
+ | ( (uint32_t)init->presc << _RTCC_CTRL_CNTPRESC_SHIFT )
+ | ( (uint32_t)init->prescMode << _RTCC_CTRL_CNTTICK_SHIFT )
+#if defined(_RTCC_CTRL_BUMODETSEN_MASK)
+ | ( (uint32_t)init->enaBackupModeSet << _RTCC_CTRL_BUMODETSEN_SHIFT )
+#endif
+ | ( (uint32_t)init->enaOSCFailDetect << _RTCC_CTRL_OSCFDETEN_SHIFT )
+ | ( (uint32_t)init->cntMode << _RTCC_CTRL_CNTMODE_SHIFT )
+ | ( (uint32_t)init->disLeapYearCorr << _RTCC_CTRL_LYEARCORRDIS_SHIFT );
+}
+
+/***************************************************************************//**
+ * @brief
+ * Restore RTCC to its reset state.
+ ******************************************************************************/
+void RTCC_Reset( void )
+{
+ int i;
+
+ /* Restore all RTCC registers to their default values. */
+ RTCC_Unlock();
+ RTCC->CTRL = _RTCC_CTRL_RESETVALUE;
+ RTCC->PRECNT = _RTCC_PRECNT_RESETVALUE;
+ RTCC->CNT = _RTCC_CNT_RESETVALUE;
+ RTCC->TIME = _RTCC_TIME_RESETVALUE;
+ RTCC->DATE = _RTCC_DATE_RESETVALUE;
+ RTCC->IEN = _RTCC_IEN_RESETVALUE;
+ RTCC->IFC = _RTCC_IFC_MASK;
+ RTCC_StatusClear();
+ RTCC->EM4WUEN = _RTCC_EM4WUEN_RESETVALUE;
+
+ for (i = 0; i < 3; i++)
+ {
+ RTCC->CC[i].CTRL = _RTCC_CC_CTRL_RESETVALUE;
+ RTCC->CC[i].CCV = _RTCC_CC_CCV_RESETVALUE;
+ RTCC->CC[i].TIME = _RTCC_CC_TIME_RESETVALUE;
+ RTCC->CC[i].DATE = _RTCC_CC_DATE_RESETVALUE;
+ }
+}
+
+/***************************************************************************//**
+ * @brief
+ * Clear STATUS register.
+ ******************************************************************************/
+void RTCC_StatusClear( void )
+{
+ while ( RTCC->SYNCBUSY & RTCC_SYNCBUSY_CMD )
+ {
+ // Wait for syncronization.
+ }
+ RTCC->CMD = RTCC_CMD_CLRSTATUS;
+}
+
+/** @} (end addtogroup RTCC) */
+/** @} (end addtogroup EM_Library) */
+
+#endif /* defined( RTCC_COUNT ) && ( RTCC_COUNT == 1 ) */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_system.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_system.c new file mode 100644 index 000000000..98e8a0ab6 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/SilLabs_Source/emlib/em_system.c @@ -0,0 +1,121 @@ +/***************************************************************************//**
+ * @file em_system.c
+ * @brief System Peripheral API
+ * @version 4.2.1
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+#include "em_system.h"
+#include "em_assert.h"
+
+/***************************************************************************//**
+ * @addtogroup EM_Library
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup SYSTEM
+ * @brief System Peripheral API
+ * @{
+ ******************************************************************************/
+
+/*******************************************************************************
+ ************************** GLOBAL FUNCTIONS *******************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief
+ * Get chip major/minor revision.
+ *
+ * @param[out] rev
+ * Location to place chip revision info.
+ ******************************************************************************/
+void SYSTEM_ChipRevisionGet(SYSTEM_ChipRevision_TypeDef *rev)
+{
+ uint8_t tmp;
+
+ EFM_ASSERT(rev);
+
+ /* CHIP FAMILY bit [5:2] */
+ tmp = (((ROMTABLE->PID1 & _ROMTABLE_PID1_FAMILYMSB_MASK) >> _ROMTABLE_PID1_FAMILYMSB_SHIFT) << 2);
+ /* CHIP FAMILY bit [1:0] */
+ tmp |= ((ROMTABLE->PID0 & _ROMTABLE_PID0_FAMILYLSB_MASK) >> _ROMTABLE_PID0_FAMILYLSB_SHIFT);
+ rev->family = tmp;
+
+ /* CHIP MAJOR bit [3:0] */
+ rev->major = (ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK) >> _ROMTABLE_PID0_REVMAJOR_SHIFT;
+
+ /* CHIP MINOR bit [7:4] */
+ tmp = (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK) >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);
+ /* CHIP MINOR bit [3:0] */
+ tmp |= ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK) >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);
+ rev->minor = tmp;
+}
+
+
+#if defined(CALIBRATE)
+/***************************************************************************//**
+ * @brief
+ * Get factory calibration value for a given peripheral register.
+ *
+ * @param[in] regAddress
+ * Address of register to get a calibration value for.
+ *
+ * @return
+ * Calibration value for the requested register.
+ ******************************************************************************/
+uint32_t SYSTEM_GetCalibrationValue(volatile uint32_t *regAddress)
+{
+ int regCount;
+ CALIBRATE_TypeDef *p;
+
+ regCount = 1;
+ p = CALIBRATE;
+
+ for (;; )
+ {
+ if ((regCount > CALIBRATE_MAX_REGISTERS) ||
+ (p->VALUE == 0xFFFFFFFF))
+ {
+ EFM_ASSERT(false);
+ return 0; /* End of device calibration table reached. */
+ }
+
+ if (p->ADDRESS == (uint32_t)regAddress)
+ {
+ return p->VALUE; /* Calibration value found ! */
+ }
+
+ p++;
+ regCount++;
+ }
+}
+#endif /* defined (CALIBRATE) */
+
+/** @} (end addtogroup SYSTEM) */
+/** @} (end addtogroup EM_Library) */
diff --git a/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/main.c b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/main.c new file mode 100644 index 000000000..de94bcb9f --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_EFM32_Pearl_Gecko_Simplicity_Studio/main.c @@ -0,0 +1,255 @@ +/*
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/******************************************************************************
+ * This project provides two demo applications. A simple blinky style project
+ * that demonstrates low power tickless functionality, and a more comprehensive
+ * test and demo application. The configCREATE_LOW_POWER_DEMO setting, which is
+ * defined in FreeRTOSConfig.h, is used to select between the two, and to select
+ * the clock used when demonstrating tickless functionality.
+ *
+ * The simply blinky low power demo is implemented and described in
+ * main_low_power.c. The more comprehensive test and demo application is
+ * implemented and described in main_full.c.
+ *
+ * This file implements the code that is not demo specific, including the
+ * hardware setup and standard FreeRTOS hook functions.
+ *
+ * ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON
+ * THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO
+ * APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT!
+ *
+ */
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* SiLabs includes. */
+#include "em_emu.h"
+#include "bsp.h"
+#include "bsp_trace.h"
+#include "sleep.h"
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Configure the hardware as necessary to run this demo.
+ */
+static void prvSetupHardware( void );
+
+/*
+ * main_low_power() is used when configCREATE_LOW_POWER_DEMO is set to 1.
+ * main_full() is used when configCREATE_LOW_POWER_DEMO is set to 0.
+ */
+#if( configCREATE_LOW_POWER_DEMO != 0 )
+ extern void main_low_power( void );
+#else
+ extern void main_full( void );
+#endif /* #if configCREATE_LOW_POWER_DEMO == 1 */
+
+/* Prototypes for the standard FreeRTOS callback/hook functions implemented
+within this file. */
+void vApplicationMallocFailedHook( void );
+void vApplicationIdleHook( void );
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );
+void vApplicationTickHook( void );
+
+/*-----------------------------------------------------------*/
+
+int main( void )
+{
+ /* Configure the hardware ready to run the demo. */
+ prvSetupHardware();
+
+ /* The mainCREATE_LOW_POWER_DEMO setting is described at the top
+ of this file. */
+ #if( configCREATE_LOW_POWER_DEMO != 0 )
+ {
+ main_low_power();
+ }
+ #else
+ {
+ main_full();
+ }
+ #endif
+
+ /* Should not get here. */
+ return 0;
+}
+/*-----------------------------------------------------------*/
+
+static void prvSetupHardware( void )
+{
+EMU_DCDCInit_TypeDef xDCDInit = EMU_DCDCINIT_STK_DEFAULT;
+CMU_HFXOInit_TypeDef xHFXOInit = CMU_HFXOINIT_STK_DEFAULT;
+
+ /* Chip errata */
+ CHIP_Init();
+
+ /* Init DCDC regulator and HFXO with kit specific parameters */
+ EMU_DCDCInit( &xDCDInit );
+ CMU_HFXOInit( &xHFXOInit );
+
+ /* Switch HFCLK to HFXO and disable HFRCO */
+ CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO );
+ CMU_OscillatorEnable( cmuOsc_HFRCO, false, false );
+
+ /* Initialize LED driver. */
+ BSP_LedsInit();
+ BSP_LedSet( 0 );
+ BSP_LedClear( 1 );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationMallocFailedHook( void )
+{
+ /* Called if a call to pvPortMalloc() fails because there is insufficient
+ free memory available in the FreeRTOS heap. pvPortMalloc() is called
+ internally by FreeRTOS API functions that create tasks, queues, software
+ timers, and semaphores. The size of the FreeRTOS heap is set by the
+ configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */
+
+ /* Force an assert. */
+ configASSERT( ( volatile void * ) NULL );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
+{
+ ( void ) pcTaskName;
+ ( void ) pxTask;
+
+ /* Run time stack overflow checking is performed if
+ configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
+ function is called if a stack overflow is detected. */
+
+ /* Force an assert. */
+ configASSERT( ( volatile void * ) NULL );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationIdleHook( void )
+{
+volatile size_t xFreeHeapSpace;
+
+ /* This is just a trivial example of an idle hook. It is called on each
+ cycle of the idle task. It must *NOT* attempt to block. In this case the
+ idle task just queries the amount of FreeRTOS heap that remains. See the
+ memory management section on the http://www.FreeRTOS.org web site for memory
+ management options. If there is a lot of heap memory free then the
+ configTOTAL_HEAP_SIZE value in FreeRTOSConfig.h can be reduced to free up
+ RAM. */
+ xFreeHeapSpace = xPortGetFreeHeapSize();
+
+ /* Remove compiler warning about xFreeHeapSpace being set but never used. */
+ ( void ) xFreeHeapSpace;
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationTickHook( void )
+{
+ /* The full demo includes tests that run from the tick hook. */
+ #if( configCREATE_LOW_POWER_DEMO == 0 )
+ {
+ extern void vFullDemoTickHook( void );
+
+ /* Some of the tests and demo tasks executed by the full demo include
+ interaction from an interrupt - for which the tick interrupt is used
+ via the tick hook function. */
+ vFullDemoTickHook();
+ }
+ #endif
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize )
+{
+ /* configUSE_STATIC_ALLOCATION is set to 1, so the application has the
+ opportunity to supply the buffers that will be used by the Idle task as its
+ stack and to hold its TCB. If these are set to NULL then the buffers will
+ be allocated dynamically, just as if xTaskCreate() had been called. */
+ *ppxIdleTaskTCBBuffer = NULL;
+ *ppxIdleTaskStackBuffer = NULL;
+ *pusIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* In words. NOT in bytes! */
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize )
+{
+ /* configUSE_STATIC_ALLOCATION is set to 1, so the application has the
+ opportunity to supply the buffers that will be used by the Timer/RTOS daemon
+ task as its stack and to hold its TCB. If these are set to NULL then the
+ buffers will be allocated dynamically, just as if xTaskCreate() had been
+ called. */
+ *ppxTimerTaskTCBBuffer = NULL;
+ *ppxTimerTaskStackBuffer = NULL;
+ *pusTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; /* In words. NOT in bytes! */
+}
+/*-----------------------------------------------------------*/
|