#include "em_burtc.h"\r
#include "em_rmu.h"\r
#include "em_int.h"\r
-#include "em_rtc.h"\r
#include "sleep.h"\r
\r
/* SEE THE COMMENTS ABOVE THE DEFINITION OF configCREATE_LOW_POWER_DEMO IN\r
{\r
ulTickFlag = pdTRUE;\r
\r
- if( RTC_CompareGet( 0 ) != ulReloadValueForOneTick )\r
+ if( BURTC_CompareGet( 0 ) != ulReloadValueForOneTick )\r
{\r
- /* Set RTC interrupt to one RTOS tick period. */\r
+ /* Set BURTC interrupt to one RTOS tick period. */\r
BURTC_Enable( false );\r
BURTC_CompareSet( 0, ulReloadValueForOneTick );\r
BURTC_Enable( true );\r
}\r
\r
- BURTC_IntClear( _RTC_IFC_MASK );\r
+ BURTC_IntClear( _BURTC_IFC_MASK );\r
\r
- /* Critical section which protect incrementing the tick*/\r
- ( void ) portSET_INTERRUPT_MASK_FROM_ISR();\r
+ /* Critical section which protect incrementing the tick. */\r
+ portDISABLE_INTERRUPTS();\r
{\r
if( xTaskIncrementTick() != pdFALSE )\r
{\r
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
}\r
}\r
- portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );\r
+ portENABLE_INTERRUPTS();\r
}\r
\r
#endif /* ( configCREATE_LOW_POWER_DEMO == 1 ) */\r
\r
RTC_IntClear( _RTC_IFC_MASK );\r
\r
- /* Critical section which protect incrementing the tick*/\r
- ( void ) portSET_INTERRUPT_MASK_FROM_ISR();\r
+ /* Critical section which protect incrementing the tick. */\r
+ portDISABLE_INTERRUPTS();\r
{\r
if( xTaskIncrementTick() != pdFALSE )\r
{\r
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
}\r
}\r
- portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );\r
+ portENABLE_INTERRUPTS();\r
}\r
/*-----------------------------------------------------------*/\r
\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<?fileVersion 4.0.0?>\r
+\r
+<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">\r
+ <storageModule moduleId="org.eclipse.cdt.core.settings">\r
+ <cconfiguration id="com.silabs.ide.si32.gcc.debug#com.silabs.ide.si32.gcc:4.8.3.20131129">\r
+ <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">\r
+ <macros>\r
+ <stringMacro name="StudioToolchainPath" type="VALUE_PATH_DIR" value="${StudioToolchainPathFromID:com.silabs.ide.si32.gcc:4.8.3.20131129}"/>\r
+ <stringMacro name="StudioSdkPath" type="VALUE_PATH_DIR" value="${StudioSdkPathFromID:com.silabs.sdk.si32.efm32.sls:2.0.10}"/>\r
+ </macros>\r
+ <externalSettings/>\r
+ <extensions>\r
+ <extension id="com.silabs.ide.debug.core.S37" point="org.eclipse.cdt.core.BinaryParser"/>\r
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>\r
+ <extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>\r
+ <extension id="com.silabs.ide.debug.core.BIN" point="org.eclipse.cdt.core.BinaryParser"/>\r
+ <extension id="com.silabs.ide.debug.core.HEX" point="org.eclipse.cdt.core.BinaryParser"/>\r
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>\r
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
+ </extensions>\r
+ </storageModule>\r
+ <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"/>\r
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">\r
+ <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">\r
+ <folderInfo id="com.silabs.ide.si32.gcc.debug#com.silabs.ide.si32.gcc:4.8.3.20131129." name="/" resourcePath="">\r
+ <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">\r
+ <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"/>\r
+ <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"/>\r
+ <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"/>\r
+ <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">\r
+ <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"/>\r
+ <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">\r
+ <listOptionValue builtIn="false" value="DEBUG_EFM=1"/>\r
+ <listOptionValue builtIn="false" value="SLEEP_LOWEST_ENERGY_MODE_DEFAULT=sleepEM2"/>\r
+ <listOptionValue builtIn="false" value="EFM32PG1B200F256GM48=1"/>\r
+ <listOptionValue builtIn="false" value="DEBUG=1"/>\r
+ </option>\r
+ <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"/>\r
+ <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"/>\r
+ <option id="gnu.c.compiler.option.include.paths.1242792235" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/SLSTK3401A_EFM32PG/config""/>\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/CMSIS/Include""/>\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/emlib/inc""/>\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/common/bsp""/>\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/common/drivers""/>\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/Device/SiliconLabs/EFM32PG1B/Include""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/FreeRTOS_Source/include}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/GCC/ARM_CM3}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/Full_Demo/Standard_Demo_Tasks/include}""/>\r
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/SilLabs_Source/emdrv/sleep/inc}""/>\r
+ </option>\r
+ <option id="gnu.c.compiler.option.warnings.extrawarn.257881085" name="Extra warnings (-Wextra)" superClass="gnu.c.compiler.option.warnings.extrawarn" value="true" valueType="boolean"/>\r
+ <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"/>\r
+ </tool>\r
+ <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">\r
+ <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"/>\r
+ <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"/>\r
+ <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"/>\r
+ </tool>\r
+ <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">\r
+ <option id="gnu.both.asm.option.include.paths.1966239528" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/SLSTK3401A_EFM32PG/examples/blink""/>\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/SLSTK3401A_EFM32PG/config""/>\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/CMSIS/Include""/>\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/emlib/inc""/>\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/common/bsp""/>\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/kits/common/drivers""/>\r
+ <listOptionValue builtIn="false" value=""${StudioSdkPath}/Device/SiliconLabs/EFM32PG1B/Include""/>\r
+ </option>\r
+ <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">\r
+ <listOptionValue builtIn="false" value="EFM32PG1B200F256GM48=1"/>\r
+ </option>\r
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.80652597" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>\r
+ </tool>\r
+ <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">\r
+ <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"/>\r
+ <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"/>\r
+ <inputType id="cdt.managedbuild.tool.gnu.c.linker.input.673598100" superClass="cdt.managedbuild.tool.gnu.c.linker.input">\r
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>\r
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>\r
+ </inputType>\r
+ </tool>\r
+ <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"/>\r
+ <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"/>\r
+ </toolChain>\r
+ </folderInfo>\r
+ </configuration>\r
+ </storageModule>\r
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>\r
+ </cconfiguration>\r
+ </storageModule>\r
+ <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"/>\r
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">\r
+ <project id="RTOSDemo.com.silabs.ide.project.core.cdt.cdtMbsProjectType.476959829" name="SLS CDT Project" projectType="com.silabs.ide.project.core.cdt.cdtMbsProjectType"/>\r
+ </storageModule>\r
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>\r
+ <storageModule moduleId="scannerConfiguration">\r
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>\r
+ <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">\r
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>\r
+ </scannerConfigBuildInfo>\r
+ </storageModule>\r
+ <storageModule moduleId="refreshScope"/>\r
+</cproject>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>RTOSDemo</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>\r
+ <triggers>clean,full,incremental,</triggers>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>\r
+ <triggers>full,incremental,</triggers>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.cdt.core.cnature</nature>\r
+ <nature>com.silabs.ide.project.core.SLSProjectNature</nature>\r
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>\r
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>\r
+ </natures>\r
+ <linkedResources>\r
+ <link>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>2</type>\r
+ <locationURI>FREERTOS_ROOT/FreeRTOS/Source</locationURI>\r
+ </link>\r
+ <link>\r
+ <name>Full_Demo/Standard_Demo_Tasks</name>\r
+ <type>2</type>\r
+ <locationURI>FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal</locationURI>\r
+ </link>\r
+ <link>\r
+ <name>Full_Demo/Standard_Demo_Tasks/include</name>\r
+ <type>2</type>\r
+ <locationURI>FREERTOS_ROOT/FreeRTOS/Demo/Common/include</locationURI>\r
+ </link>\r
+ </linkedResources>\r
+ <filteredResources>\r
+ <filter>\r
+ <id>1455990187566</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-event_groups.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1455990187573</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-queue.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1455990187577</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-tasks.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1455990187582</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-timers.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1455990187588</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>9</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-include</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1455990187592</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>9</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-portable</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1455990187597</id>\r
+ <name>FreeRTOS_Source</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-list.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>FreeRTOS_Source/portable</name>\r
+ <type>9</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-MemMang</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>FreeRTOS_Source/portable</name>\r
+ <type>9</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-GCC</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>Full_Demo/Standard_Demo_Tasks</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-flop.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>Full_Demo/Standard_Demo_Tasks</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-dynamic.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>Full_Demo/Standard_Demo_Tasks</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-blocktim.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>Full_Demo/Standard_Demo_Tasks</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-GenQTest.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>Full_Demo/Standard_Demo_Tasks</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-TimerDemo.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>Full_Demo/Standard_Demo_Tasks</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-EventGroupsDemo.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>Full_Demo/Standard_Demo_Tasks</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-TaskNotify.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>Full_Demo/Standard_Demo_Tasks</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-recmutex.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>Full_Demo/Standard_Demo_Tasks</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-semtest.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>0</id>\r
+ <name>Full_Demo/Standard_Demo_Tasks</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-StaticAllocation.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1455989277852</id>\r
+ <name>FreeRTOS_Source/portable/GCC</name>\r
+ <type>9</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-ARM_CM3</arguments>\r
+ </matcher>\r
+ </filter>\r
+ <filter>\r
+ <id>1455989313240</id>\r
+ <name>FreeRTOS_Source/portable/MemMang</name>\r
+ <type>5</type>\r
+ <matcher>\r
+ <id>org.eclipse.ui.ide.multiFilter</id>\r
+ <arguments>1.0-name-matches-false-false-heap_4.c</arguments>\r
+ </matcher>\r
+ </filter>\r
+ </filteredResources>\r
+ <variableList>\r
+ <variable>\r
+ <name>FREERTOS_ROOT</name>\r
+ <value>$%7BPARENT-3-PROJECT_LOC%7D</value>\r
+ </variable>\r
+ </variableList>\r
+</projectDescription>\r
--- /dev/null
+/*\r
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+ All rights reserved\r
+\r
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
+\r
+ ***************************************************************************\r
+ >>! NOTE: The modification to the GPL is included to allow you to !<<\r
+ >>! distribute a combined work that includes FreeRTOS without being !<<\r
+ >>! obliged to provide the source code for proprietary components !<<\r
+ >>! outside of the FreeRTOS kernel. !<<\r
+ ***************************************************************************\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following\r
+ link: http://www.freertos.org/a00114.html\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS provides completely free yet professionally developed, *\r
+ * robust, strictly quality controlled, supported, and cross *\r
+ * platform software that is more than just the market leader, it *\r
+ * is the industry's de facto standard. *\r
+ * *\r
+ * Help yourself get started quickly while simultaneously helping *\r
+ * to support the FreeRTOS project by purchasing a FreeRTOS *\r
+ * tutorial book, reference manual, or both: *\r
+ * http://www.FreeRTOS.org/Documentation *\r
+ * *\r
+ ***************************************************************************\r
+\r
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading\r
+ the FAQ page "My application does not run, what could be wrong?". Have you\r
+ defined configASSERT()?\r
+\r
+ http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+ embedded software for free we request you assist our global community by\r
+ participating in the support forum.\r
+\r
+ http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+ be as productive as possible as early as possible. Now you can receive\r
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+ Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS\r
+ licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+ engineered and independently SIL3 certified version for use in safety and\r
+ mission critical applications that require provable dependability.\r
+\r
+ 1 tab == 4 spaces!\r
+*/\r
+\r
+#ifndef FREERTOS_CONFIG_H\r
+#define FREERTOS_CONFIG_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#include "em_chip.h"\r
+#include "em_cmu.h"\r
+\r
+/*-----------------------------------------------------------\r
+ * Application specific definitions.\r
+ *\r
+ * These definitions should be adjusted for your particular hardware and\r
+ * application requirements.\r
+ *\r
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE\r
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.\r
+ *\r
+ * See http://www.freertos.org/a00110.html.\r
+ *----------------------------------------------------------*/\r
+\r
+\r
+/* Set configCREATE_LOW_POWER_DEMO as follows:\r
+ *\r
+ * 0: Build the full test and demo application.\r
+ * 1: Build the simple blinky tickless low power demo, generating the tick\r
+ * interrupt from the RTCC. EM2 will be entered. The LXFO clock is used.\r
+ * See the comments at the top of main.c, main_full.c and main_low_power.c for\r
+ * more information.\r
+ */\r
+#define configCREATE_LOW_POWER_DEMO 1\r
+\r
+/* Some configuration is dependent on the demo being built. */\r
+#if( configCREATE_LOW_POWER_DEMO == 0 )\r
+\r
+ /* Tickless mode is not used. */\r
+\r
+ /* Some of the standard demo test tasks assume a tick rate of 1KHz, even\r
+ though that is faster than would normally be warranted by a real\r
+ application. */\r
+ #define configTICK_RATE_HZ ( 1000 )\r
+\r
+ /* The full demo always has tasks to run so the tick will never be turned\r
+ off. The blinky demo will use the default tickless idle implementation to\r
+ turn the tick off. */\r
+ #define configUSE_TICKLESS_IDLE 0\r
+\r
+ /* Hook function related definitions. */\r
+ #define configUSE_TICK_HOOK ( 1 )\r
+ #define configCHECK_FOR_STACK_OVERFLOW ( 1 )\r
+ #define configUSE_MALLOC_FAILED_HOOK ( 1 )\r
+ #define configUSE_IDLE_HOOK ( 1 )\r
+\r
+ #define configENERGY_MODE ( sleepEM3 )\r
+\r
+#else\r
+\r
+ /* Tickless idle mode, generating RTOS tick interrupts from the RTC, fed\r
+ by the LXFO clock. */\r
+\r
+ /* The slow clock used to generate the tick interrupt in the low power demo\r
+ runs at 32768/8=4096Hz. Ensure the tick rate is a multiple of the clock. */\r
+ #define configTICK_RATE_HZ ( 128 )\r
+\r
+ /* The low power demo uses the tickless idle feature. */\r
+ #define configUSE_TICKLESS_IDLE 1\r
+\r
+ /* Hook function related definitions. */\r
+ #define configUSE_TICK_HOOK ( 0 )\r
+ #define configCHECK_FOR_STACK_OVERFLOW ( 0 )\r
+ #define configUSE_MALLOC_FAILED_HOOK ( 0 )\r
+ #define configUSE_IDLE_HOOK ( 0 )\r
+\r
+#endif\r
+\r
+/* Main functions*/\r
+#define configUSE_PREEMPTION ( 1 )\r
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION ( 1 )\r
+#define configSUPPORT_STATIC_ALLOCATION ( 1 )\r
+#define configCPU_CLOCK_HZ ( CMU_ClockFreqGet( cmuClock_CORE ) )\r
+#define configMAX_PRIORITIES ( 6 )\r
+#define configMINIMAL_STACK_SIZE (( unsigned short ) 130)\r
+#define configTOTAL_HEAP_SIZE (( size_t )(25000))\r
+#define configMAX_TASK_NAME_LEN ( 10 )\r
+#define configUSE_TRACE_FACILITY ( 0 )\r
+#define configUSE_16_BIT_TICKS ( 0 )\r
+#define configIDLE_SHOULD_YIELD ( 0 )\r
+#define configUSE_MUTEXES ( 1 )\r
+#define configUSE_RECURSIVE_MUTEXES ( 1 )\r
+#define configUSE_COUNTING_SEMAPHORES ( 1 )\r
+#define configUSE_ALTERNATIVE_API ( 0 )/* Deprecated! */\r
+#define configQUEUE_REGISTRY_SIZE ( 10 )\r
+#define configUSE_QUEUE_SETS ( 0 )\r
+\r
+/* Run time stats gathering related definitions. */\r
+#define configGENERATE_RUN_TIME_STATS ( 0 )\r
+\r
+/* Co-routine related definitions. */\r
+#define configUSE_CO_ROUTINES ( 0 )\r
+#define configMAX_CO_ROUTINE_PRIORITIES ( 1 )\r
+\r
+/* Software timer related definitions. */\r
+#define configUSE_TIMERS ( 1 )\r
+#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) /* Highest priority */\r
+#define configTIMER_QUEUE_LENGTH ( 10 )\r
+#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )\r
+\r
+/* Cortex-M specific definitions. */\r
+#ifdef __NVIC_PRIO_BITS\r
+ /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */\r
+ #define configPRIO_BITS __NVIC_PRIO_BITS\r
+#else\r
+ #define configPRIO_BITS 3 /* 7 priority levels */\r
+#endif\r
+\r
+/* The lowest interrupt priority that can be used in a call to a "set priority"\r
+function. */\r
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x07\r
+\r
+/* The highest interrupt priority that can be used by any interrupt service\r
+routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL\r
+INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER\r
+PRIORITY THAN THIS! (higher priorities are lower numeric values. */\r
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x05\r
+\r
+/* Interrupt priorities used by the kernel port layer itself. These are generic\r
+to all Cortex-M ports, and do not rely on any particular library functions. */\r
+#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )\r
+/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!\r
+See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */\r
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )\r
+\r
+\r
+/* Optional functions - most linkers will remove unused functions anyway. */\r
+#define INCLUDE_vTaskPrioritySet ( 1 )\r
+#define INCLUDE_uxTaskPriorityGet ( 1 )\r
+#define INCLUDE_vTaskDelete ( 1 )\r
+#define INCLUDE_vTaskSuspend ( 1 )\r
+#define INCLUDE_xResumeFromISR ( 1 )\r
+#define INCLUDE_vTaskDelayUntil ( 1 )\r
+#define INCLUDE_vTaskDelay ( 1 )\r
+#define INCLUDE_xTaskGetSchedulerState ( 1 )\r
+#define INCLUDE_xTaskGetCurrentTaskHandle ( 1 )\r
+#define INCLUDE_uxTaskGetStackHighWaterMark ( 0 )\r
+#define INCLUDE_xTaskGetIdleTaskHandle ( 0 )\r
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle ( 0 )\r
+#define INCLUDE_pcTaskGetTaskName ( 0 )\r
+#define INCLUDE_eTaskGetState ( 1 )\r
+#define INCLUDE_xTimerPendFunctionCall ( 1 )\r
+\r
+/* Stop if an assertion fails. */\r
+#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }\r
+\r
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS\r
+standard names. */\r
+#define vPortSVCHandler SVC_Handler\r
+#define xPortPendSVHandler PendSV_Handler\r
+#define xPortSysTickHandler SysTick_Handler\r
+\r
+/* For the linker. */\r
+#define fabs __builtin_fabs\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+#endif /* FREERTOS_CONFIG_H */\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+ All rights reserved\r
+\r
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
+\r
+ ***************************************************************************\r
+ >>! NOTE: The modification to the GPL is included to allow you to !<<\r
+ >>! distribute a combined work that includes FreeRTOS without being !<<\r
+ >>! obliged to provide the source code for proprietary components !<<\r
+ >>! outside of the FreeRTOS kernel. !<<\r
+ ***************************************************************************\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following\r
+ link: http://www.freertos.org/a00114.html\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS provides completely free yet professionally developed, *\r
+ * robust, strictly quality controlled, supported, and cross *\r
+ * platform software that is more than just the market leader, it *\r
+ * is the industry's de facto standard. *\r
+ * *\r
+ * Help yourself get started quickly while simultaneously helping *\r
+ * to support the FreeRTOS project by purchasing a FreeRTOS *\r
+ * tutorial book, reference manual, or both: *\r
+ * http://www.FreeRTOS.org/Documentation *\r
+ * *\r
+ ***************************************************************************\r
+\r
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading\r
+ the FAQ page "My application does not run, what could be wrong?". Have you\r
+ defined configASSERT()?\r
+\r
+ http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+ embedded software for free we request you assist our global community by\r
+ participating in the support forum.\r
+\r
+ http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+ be as productive as possible as early as possible. Now you can receive\r
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+ Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS\r
+ licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+ engineered and independently SIL3 certified version for use in safety and\r
+ mission critical applications that require provable dependability.\r
+\r
+ 1 tab == 4 spaces!\r
+*/\r
+\r
+/*\r
+ * "Reg test" tasks - These fill the registers with known values, then check\r
+ * that each register maintains its expected value for the lifetime of the\r
+ * task. Each task uses a different set of values. The reg test tasks execute\r
+ * with a very low priority, so get preempted very frequently. A register\r
+ * containing an unexpected value is indicative of an error in the context\r
+ * switching mechanism.\r
+ */\r
+\r
+void vRegTest1Implementation( void ) __attribute__ ((naked));\r
+void vRegTest2Implementation( void ) __attribute__ ((naked));\r
+\r
+void vRegTest1Implementation( void )\r
+{\r
+ __asm volatile\r
+ (\r
+ ".extern ulRegTest1LoopCounter \n"\r
+ "/* Fill the core registers with known values. */ \n"\r
+ "mov r0, #100 \n"\r
+ "mov r1, #101 \n"\r
+ "mov r2, #102 \n"\r
+ "mov r3, #103 \n"\r
+ "mov r4, #104 \n"\r
+ "mov r5, #105 \n"\r
+ "mov r6, #106 \n"\r
+ "mov r7, #107 \n"\r
+ "mov r8, #108 \n"\r
+ "mov r9, #109 \n"\r
+ "mov r10, #110 \n"\r
+ "mov r11, #111 \n"\r
+ "mov r12, #112 \n"\r
+\r
+ "reg1_loop: \n"\r
+\r
+ "/* Check each register has maintained its expected value. */ \n"\r
+ "cmp r0, #100 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r1, #101 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r2, #102 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r3, #103 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r4, #104 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r5, #105 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r6, #106 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r7, #107 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r8, #108 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r9, #109 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r10, #110 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r11, #111 \n"\r
+ "bne reg1_error_loop \n"\r
+ "cmp r12, #112 \n"\r
+ "bne reg1_error_loop \n"\r
+\r
+ "/* Everything passed, increment the loop counter. */ \n"\r
+ "push { r0-r1 } \n"\r
+ "ldr r0, =ulRegTest1LoopCounter \n"\r
+ "ldr r1, [r0] \n"\r
+ "adds r1, r1, #1 \n"\r
+ "str r1, [r0] \n"\r
+ "pop { r0-r1 } \n"\r
+\r
+ "/* Start again. */ \n"\r
+ "b reg1_loop \n"\r
+\r
+ "reg1_error_loop: \n"\r
+ "/* If this line is hit then there was an error in a core register value. \n"\r
+ "The loop ensures the loop counter stops incrementing. */ \n"\r
+ "b reg1_error_loop \n"\r
+ "nop "\r
+ ); /* __asm volatile. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vRegTest2Implementation( void )\r
+{\r
+ __asm volatile\r
+ (\r
+ ".extern ulRegTest2LoopCounter \n"\r
+ "/* Set all the core registers to known values. */ \n"\r
+ "mov r0, #-1 \n"\r
+ "mov r1, #1 \n"\r
+ "mov r2, #2 \n"\r
+ "mov r3, #3 \n"\r
+ "mov r4, #4 \n"\r
+ "mov r5, #5 \n"\r
+ "mov r6, #6 \n"\r
+ "mov r7, #7 \n"\r
+ "mov r8, #8 \n"\r
+ "mov r9, #9 \n"\r
+ "mov r10, #10 \n"\r
+ "mov r11, #11 \n"\r
+ "mov r12, #12 \n"\r
+\r
+ "reg2_loop: \n"\r
+\r
+ "cmp r0, #-1 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r1, #1 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r2, #2 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r3, #3 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r4, #4 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r5, #5 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r6, #6 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r7, #7 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r8, #8 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r9, #9 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r10, #10 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r11, #11 \n"\r
+ "bne reg2_error_loop \n"\r
+ "cmp r12, #12 \n"\r
+ "bne reg2_error_loop \n"\r
+\r
+ "/* Increment the loop counter to indicate this test is still functioning \n"\r
+ "correctly. */ \n"\r
+ "push { r0-r1 } \n"\r
+ "ldr r0, =ulRegTest2LoopCounter \n"\r
+ "ldr r1, [r0] \n"\r
+ "adds r1, r1, #1 \n"\r
+ "str r1, [r0] \n"\r
+\r
+ "/* Yield to increase test coverage. */ \n"\r
+ "movs r0, #0x01 \n"\r
+ "ldr r1, =0xe000ed04 /*NVIC_INT_CTRL */ \n"\r
+ "lsl r0, r0, #28 /* Shift to PendSV bit */ \n"\r
+ "str r0, [r1] \n"\r
+ "dsb \n"\r
+\r
+ "pop { r0-r1 } \n"\r
+\r
+ "/* Start again. */ \n"\r
+ "b reg2_loop \n"\r
+\r
+ "reg2_error_loop: \n"\r
+ "/* If this line is hit then there was an error in a core register value. \n"\r
+ "This loop ensures the loop counter variable stops incrementing. */ \n"\r
+ "b reg2_error_loop \n"\r
+ ); /* __asm volatile */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+ All rights reserved\r
+\r
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
+\r
+ ***************************************************************************\r
+ >>! NOTE: The modification to the GPL is included to allow you to !<<\r
+ >>! distribute a combined work that includes FreeRTOS without being !<<\r
+ >>! obliged to provide the source code for proprietary components !<<\r
+ >>! outside of the FreeRTOS kernel. !<<\r
+ ***************************************************************************\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following\r
+ link: http://www.freertos.org/a00114.html\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS provides completely free yet professionally developed, *\r
+ * robust, strictly quality controlled, supported, and cross *\r
+ * platform software that is more than just the market leader, it *\r
+ * is the industry's de facto standard. *\r
+ * *\r
+ * Help yourself get started quickly while simultaneously helping *\r
+ * to support the FreeRTOS project by purchasing a FreeRTOS *\r
+ * tutorial book, reference manual, or both: *\r
+ * http://www.FreeRTOS.org/Documentation *\r
+ * *\r
+ ***************************************************************************\r
+\r
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading\r
+ the FAQ page "My application does not run, what could be wrong?". Have you\r
+ defined configASSERT()?\r
+\r
+ http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+ embedded software for free we request you assist our global community by\r
+ participating in the support forum.\r
+\r
+ http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+ be as productive as possible as early as possible. Now you can receive\r
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+ Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS\r
+ licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+ engineered and independently SIL3 certified version for use in safety and\r
+ mission critical applications that require provable dependability.\r
+\r
+ 1 tab == 4 spaces!\r
+*/\r
+\r
+/******************************************************************************\r
+ * NOTE 1: This project provides two demo applications. A simple blinky style\r
+ * project that demonstrates the tickless low power features of FreeRTOS, and a\r
+ * more comprehensive test and demo application. The configCREATE_LOW_POWER_DEMO\r
+ * setting in FreeRTOSConifg.h is used to select between the two, and to select\r
+ * the clock used when tickless mode is used. See the notes on using\r
+ * conifgCREATE_LOW_POWER_DEMO in main.c. This file implements the\r
+ * comprehensive test and demo version.\r
+ *\r
+ * NOTE 2: This file only contains the source code that is specific to the\r
+ * full demo. Generic functions, such FreeRTOS hook functions, and functions\r
+ * required to configure the hardware, are defined in main.c.\r
+ *\r
+ ******************************************************************************\r
+ *\r
+ * main_full() creates all the demo application tasks and software timers, then\r
+ * starts the scheduler. The web documentation provides more details of the\r
+ * standard demo application tasks, which provide no particular functionality,\r
+ * but do provide a good example of how to use the FreeRTOS API.\r
+ *\r
+ * In addition to the standard demo tasks, the following tasks and tests are\r
+ * defined and/or created within this file:\r
+ *\r
+ * "Reg test" tasks - These fill both the core and floating point registers with\r
+ * known values, then check that each register maintains its expected value for\r
+ * the lifetime of the task. Each task uses a different set of values. The reg\r
+ * test tasks execute with a very low priority, so get preempted very\r
+ * frequently. A register containing an unexpected value is indicative of an\r
+ * error in the context switching mechanism.\r
+ *\r
+ * "Check" task - The check task period is initially set to three seconds. The\r
+ * task checks that all the standard demo tasks, and the register check tasks,\r
+ * are not only still executing, but are executing without reporting any errors.\r
+ * If the check task discovers that a task has either stalled, or reported an\r
+ * error, then it changes its own execution period from the initial three\r
+ * seconds, to just 200ms. The check task also toggles an LED each time it is\r
+ * called. This provides a visual indication of the system status: If the LED\r
+ * toggles every three seconds, then no issues have been discovered. If the LED\r
+ * toggles every 200ms, then an issue has been discovered with at least one\r
+ * task.\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdio.h>\r
+\r
+/* Kernel includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "timers.h"\r
+#include "semphr.h"\r
+\r
+/* SiLabs includes. */\r
+#include "bsp.h"\r
+\r
+/* Standard demo application includes. */\r
+#include "flop.h"\r
+#include "semtest.h"\r
+#include "dynamic.h"\r
+#include "blocktim.h"\r
+#include "GenQTest.h"\r
+#include "recmutex.h"\r
+#include "TimerDemo.h"\r
+#include "EventGroupsDemo.h"\r
+#include "TaskNotify.h"\r
+#include "StaticAllocation.h"\r
+\r
+/* Priorities for the demo application tasks. */\r
+#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1UL )\r
+#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3UL )\r
+#define mainFLOP_TASK_PRIORITY ( tskIDLE_PRIORITY )\r
+#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )\r
+\r
+/* A block time of zero simply means "don't block". */\r
+#define mainDONT_BLOCK ( 0UL )\r
+\r
+/* The period after which the check timer will expire, in ms, provided no errors\r
+have been reported by any of the standard demo tasks. ms are converted to the\r
+equivalent in ticks using the portTICK_PERIOD_MS constant. */\r
+#define mainNO_ERROR_CHECK_TASK_PERIOD ( 3000UL / portTICK_PERIOD_MS )\r
+\r
+/* The period at which the check timer will expire, in ms, if an error has been\r
+reported in one of the standard demo tasks. ms are converted to the equivalent\r
+in ticks using the portTICK_PERIOD_MS constant. */\r
+#define mainERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 200UL )\r
+\r
+/* Parameters that are passed into the register check tasks solely for the\r
+purpose of ensuring parameters are passed into tasks correctly. */\r
+#define mainREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x12345678 )\r
+#define mainREG_TEST_TASK_2_PARAMETER ( ( void * ) 0x87654321 )\r
+\r
+/* The base period used by the timer test tasks. */\r
+#define mainTIMER_TEST_PERIOD ( 50 )\r
+\r
+/* The LED toggled by the check task. */\r
+#define mainTASK_LED ( 0 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Called by main() to run the full demo (as opposed to the blinky demo) when\r
+ * mainCREATE_LOW_POWER_DEMO is set to 0.\r
+ */\r
+void main_full( void );\r
+\r
+/*\r
+ * The check task, as described at the top of this file.\r
+ */\r
+static void prvCheckTask( void *pvParameters );\r
+\r
+/*\r
+ * Some of the tests and demo tasks executed by the full demo include\r
+ * interaction from an interrupt - for which the tick interrupt is used via the\r
+ * tick hook function.\r
+ */\r
+void vFullDemoTickHook( void );\r
+\r
+/*\r
+ * Register check tasks, and the tasks used to write over and check the contents\r
+ * of the FPU registers, as described at the top of this file. The nature of\r
+ * these files necessitates that they are written in an assembly file, but the\r
+ * entry points are kept in the C file for the convenience of checking the task\r
+ * parameter.\r
+ */\r
+static void prvRegTestTaskEntry1( void *pvParameters );\r
+extern void vRegTest1Implementation( void );\r
+static void prvRegTestTaskEntry2( void *pvParameters );\r
+extern void vRegTest2Implementation( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The following two variables are used to communicate the status of the\r
+register check tasks to the check task. If the variables keep incrementing,\r
+then the register check tasks have not discovered any errors. If a variable\r
+stops incrementing, then an error has been found. */\r
+volatile unsigned long ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL;\r
+\r
+/* The variable incremented in lieu of having a proper LED outout. */\r
+extern volatile uint32_t ulLED;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void main_full( void )\r
+{\r
+ /* Start all the other standard demo/test tasks. They have no particular\r
+ functionality, but do demonstrate how to use the FreeRTOS API and test the\r
+ kernel port. */\r
+ vStartDynamicPriorityTasks();\r
+ vCreateBlockTimeTasks();\r
+ vStartGenericQueueTasks( tskIDLE_PRIORITY );\r
+ vStartRecursiveMutexTasks();\r
+ vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
+ vStartMathTasks( mainFLOP_TASK_PRIORITY );\r
+ vStartTimerDemoTask( mainTIMER_TEST_PERIOD );\r
+ vStartEventGroupTasks();\r
+ vStartTaskNotifyTask();\r
+ vStartStaticallyAllocatedTasks();\r
+\r
+ /* Create the register check tasks, as described at the top of this file */\r
+ xTaskCreate( prvRegTestTaskEntry1, "Reg1", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_1_PARAMETER, tskIDLE_PRIORITY, NULL );\r
+ xTaskCreate( prvRegTestTaskEntry2, "Reg2", configMINIMAL_STACK_SIZE, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL );\r
+\r
+ /* Create the task that performs the 'check' functionality, as described at\r
+ the top of this file. */\r
+ xTaskCreate( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
+\r
+ /* Start the scheduler. */\r
+ vTaskStartScheduler();\r
+\r
+ /* If all is well, the scheduler will now be running, and the following\r
+ line will never be reached. If the following line does execute, then\r
+ there was insufficient FreeRTOS heap memory available for the Idle and/or\r
+ timer tasks to be created. See the memory management section on the\r
+ FreeRTOS web site for more details on the FreeRTOS heap\r
+ http://www.freertos.org/a00111.html. */\r
+ for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCheckTask( void *pvParameters )\r
+{\r
+TickType_t xDelayPeriod = mainNO_ERROR_CHECK_TASK_PERIOD;\r
+TickType_t xLastExecutionTime;\r
+static unsigned long ulLastRegTest1Value = 0, ulLastRegTest2Value = 0;\r
+unsigned long ulErrorFound = pdFALSE;\r
+\r
+ /* Just to stop compiler warnings. */\r
+ ( void ) pvParameters;\r
+\r
+ /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()\r
+ works correctly. */\r
+ xLastExecutionTime = xTaskGetTickCount();\r
+\r
+ /* Cycle for ever, delaying then checking all the other tasks are still\r
+ operating without error. The onboard LED is toggled on each iteration.\r
+ If an error is detected then the delay period is decreased from\r
+ mainNO_ERROR_CHECK_TASK_PERIOD to mainERROR_CHECK_TASK_PERIOD. This has the\r
+ effect of increasing the rate at which the onboard LED toggles, and in so\r
+ doing gives visual feedback of the system status. */\r
+ for( ;; )\r
+ {\r
+ /* Delay until it is time to execute again. */\r
+ vTaskDelayUntil( &xLastExecutionTime, xDelayPeriod );\r
+\r
+ /* Check all the demo tasks (other than the flash tasks) to ensure\r
+ that they are all still running, and that none have detected an error. */\r
+ if( xAreMathsTaskStillRunning() != pdTRUE )\r
+ {\r
+ ulErrorFound = 1UL << 1UL;\r
+ }\r
+\r
+ if( xAreDynamicPriorityTasksStillRunning() != pdTRUE )\r
+ {\r
+ ulErrorFound = 1UL << 2UL;\r
+ }\r
+\r
+ if( xAreStaticAllocationTasksStillRunning() != pdPASS )\r
+ {\r
+ ulErrorFound = 1UL << 3UL;\r
+ }\r
+\r
+ if ( xAreBlockTimeTestTasksStillRunning() != pdTRUE )\r
+ {\r
+ ulErrorFound = 1UL << 4UL;\r
+ }\r
+\r
+ if ( xAreGenericQueueTasksStillRunning() != pdTRUE )\r
+ {\r
+ ulErrorFound = 1UL << 5UL;\r
+ }\r
+\r
+ if ( xAreRecursiveMutexTasksStillRunning() != pdTRUE )\r
+ {\r
+ ulErrorFound = 1UL << 6UL;\r
+ }\r
+\r
+ if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
+ {\r
+ ulErrorFound = 1UL << 8UL;\r
+ }\r
+\r
+ if( xAreTimerDemoTasksStillRunning( ( TickType_t ) xDelayPeriod ) != pdPASS )\r
+ {\r
+ ulErrorFound = 1UL << 9UL;\r
+ }\r
+\r
+ if( xAreEventGroupTasksStillRunning() != pdPASS )\r
+ {\r
+ ulErrorFound = 1UL << 12UL;\r
+ }\r
+\r
+ if( xAreTaskNotificationTasksStillRunning() != pdPASS )\r
+ {\r
+ ulErrorFound = 1UL << 14UL;\r
+ }\r
+\r
+ /* Check that the register test 1 task is still running. */\r
+ if( ulLastRegTest1Value == ulRegTest1LoopCounter )\r
+ {\r
+ ulErrorFound = 1UL << 15UL;\r
+ }\r
+ ulLastRegTest1Value = ulRegTest1LoopCounter;\r
+\r
+ /* Check that the register test 2 task is still running. */\r
+ if( ulLastRegTest2Value == ulRegTest2LoopCounter )\r
+ {\r
+ ulErrorFound = 1UL << 16UL;\r
+ }\r
+ ulLastRegTest2Value = ulRegTest2LoopCounter;\r
+\r
+ /* Toggle the check LED to give an indication of the system status. If\r
+ the LED toggles every mainNO_ERROR_CHECK_TASK_PERIOD milliseconds then\r
+ everything is ok. A faster toggle indicates an error. */\r
+ BSP_LedToggle( mainTASK_LED );\r
+\r
+ if( ulErrorFound != pdFALSE )\r
+ {\r
+ /* An error has been detected in one of the tasks - flash the LED\r
+ at a higher frequency to give visible feedback that something has\r
+ gone wrong. */\r
+ xDelayPeriod = mainERROR_CHECK_TASK_PERIOD;\r
+ }\r
+\r
+ configASSERT( ulErrorFound == pdFALSE );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRegTestTaskEntry1( void *pvParameters )\r
+{\r
+ /* Although the regtest task is written in assembler, its entry point is\r
+ written in C for convenience of checking the task parameter is being passed\r
+ in correctly. */\r
+ if( pvParameters == mainREG_TEST_TASK_1_PARAMETER )\r
+ {\r
+ /* Start the part of the test that is written in assembler. */\r
+ vRegTest1Implementation();\r
+ }\r
+\r
+ /* The following line will only execute if the task parameter is found to\r
+ be incorrect. The check timer will detect that the regtest loop counter is\r
+ not being incremented and flag an error. */\r
+ vTaskDelete( NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRegTestTaskEntry2( void *pvParameters )\r
+{\r
+ /* Although the regtest task is written in assembler, its entry point is\r
+ written in C for convenience of checking the task parameter is being passed\r
+ in correctly. */\r
+ if( pvParameters == mainREG_TEST_TASK_2_PARAMETER )\r
+ {\r
+ /* Start the part of the test that is written in assembler. */\r
+ vRegTest2Implementation();\r
+ }\r
+\r
+ /* The following line will only execute if the task parameter is found to\r
+ be incorrect. The check timer will detect that the regtest loop counter is\r
+ not being incremented and flag an error. */\r
+ vTaskDelete( NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vFullDemoTickHook( void )\r
+{\r
+ /* Some of the tests and demo tasks executed by the full demo include\r
+ interaction from an interrupt - for which the tick interrupt is used via\r
+ the tick hook function. */\r
+\r
+ /* The full demo includes a software timer demo/test that requires\r
+ prodding periodically from the tick interrupt. */\r
+ vTimerPeriodicISRTests();\r
+\r
+ /* Call the periodic event group from ISR demo. */\r
+ vPeriodicEventGroupsProcessing();\r
+\r
+ /* Call the code that 'gives' a task notification from an ISR. */\r
+ xNotifyTaskFromISR();\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+ All rights reserved\r
+\r
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
+\r
+ ***************************************************************************\r
+ >>! NOTE: The modification to the GPL is included to allow you to !<<\r
+ >>! distribute a combined work that includes FreeRTOS without being !<<\r
+ >>! obliged to provide the source code for proprietary components !<<\r
+ >>! outside of the FreeRTOS kernel. !<<\r
+ ***************************************************************************\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following\r
+ link: http://www.freertos.org/a00114.html\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS provides completely free yet professionally developed, *\r
+ * robust, strictly quality controlled, supported, and cross *\r
+ * platform software that is more than just the market leader, it *\r
+ * is the industry's de facto standard. *\r
+ * *\r
+ * Help yourself get started quickly while simultaneously helping *\r
+ * to support the FreeRTOS project by purchasing a FreeRTOS *\r
+ * tutorial book, reference manual, or both: *\r
+ * http://www.FreeRTOS.org/Documentation *\r
+ * *\r
+ ***************************************************************************\r
+\r
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading\r
+ the FAQ page "My application does not run, what could be wrong?". Have you\r
+ defined configASSERT()?\r
+\r
+ http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+ embedded software for free we request you assist our global community by\r
+ participating in the support forum.\r
+\r
+ http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+ be as productive as possible as early as possible. Now you can receive\r
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+ Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS\r
+ licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+ engineered and independently SIL3 certified version for use in safety and\r
+ mission critical applications that require provable dependability.\r
+\r
+ 1 tab == 4 spaces!\r
+*/\r
+\r
+/* Standard inlcludes. */\r
+#include <limits.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* SiLabs library includes. */\r
+#include "em_cmu.h"\r
+#include "em_rtcc.h"\r
+#include "em_rmu.h"\r
+#include "em_int.h"\r
+#include "sleep.h"\r
+\r
+/* SEE THE COMMENTS ABOVE THE DEFINITION OF configCREATE_LOW_POWER_DEMO IN\r
+FreeRTOSConfig.h\r
+This file contains functions that will override the default implementations\r
+in the RTOS port layer. Therefore only build this file if the low power demo\r
+is being built. */\r
+#if( configCREATE_LOW_POWER_DEMO == 1 )\r
+\r
+/* The RTCC channel used to generate the tick interrupt. */\r
+#define lpRTCC_CHANNEL ( 1 )\r
+\r
+/* 32768 clock divided by 1. Don't use a prescale if errata RTCC_E201\r
+applies. */\r
+#define mainTIMER_FREQUENCY_HZ ( 32768UL )\r
+\r
+/*\r
+ * The low power demo does not use the SysTick, so override the\r
+ * vPortSetupTickInterrupt() function with an implementation that configures\r
+ * a low power clock source. NOTE: This function name must not be changed as\r
+ * it is called from the RTOS portable layer.\r
+ */\r
+void vPortSetupTimerInterrupt( void );\r
+\r
+/*\r
+ * Override the default definition of vPortSuppressTicksAndSleep() that is\r
+ * weakly defined in the FreeRTOS Cortex-M port layer with a version that\r
+ * manages the RTC clock, as the tick is generated from the low power RTC\r
+ * and not the SysTick as would normally be the case on a Cortex-M.\r
+ */\r
+void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Calculate how many clock increments make up a single tick period. */\r
+static const uint32_t ulReloadValueForOneTick = ( mainTIMER_FREQUENCY_HZ / configTICK_RATE_HZ );\r
+\r
+/* Will hold the maximum number of ticks that can be suppressed. */\r
+static uint32_t xMaximumPossibleSuppressedTicks = 0;\r
+\r
+/* Flag set from the tick interrupt to allow the sleep processing to know if\r
+sleep mode was exited because of a timer interrupt or a different interrupt. */\r
+static volatile uint32_t ulTickFlag = pdFALSE;\r
+\r
+/* As the clock is only 32KHz, it is likely a value of 1 will be enough. */\r
+static const uint32_t ulStoppedTimerCompensation = 0UL;\r
+\r
+/* RTCC configuration structures. */\r
+static const RTCC_Init_TypeDef xRTCInitStruct =\r
+{\r
+ false, /* Don't start counting when init complete. */\r
+ false, /* Disable counter during debug halt. */\r
+ false, /* Don't care. */\r
+ true, /* Enable counter wrap on ch. 1 CCV value. */\r
+ rtccCntPresc_1, /* NOTE: Do not use a pre-scale if errata RTCC_E201 applies. */\r
+ rtccCntTickPresc, /* Count using the clock input directly. */\r
+#if defined(_RTCC_CTRL_BUMODETSEN_MASK)\r
+ false, /* Disable storing RTCC counter value in RTCC_CCV2 upon backup mode entry. */\r
+#endif\r
+ false, /* Oscillator fail detection disabled. */\r
+ rtccCntModeNormal, /* Use RTCC in normal mode (increment by 1 on each tick) and not in calendar mode. */\r
+ false /* Don't care. */\r
+};\r
+\r
+static const RTCC_CCChConf_TypeDef xRTCCChannel1InitStruct =\r
+{\r
+ rtccCapComChModeCompare, /* Use Compare mode. */\r
+ rtccCompMatchOutActionPulse,/* Don't care. */\r
+ rtccPRSCh0, /* PRS not used. */\r
+ rtccInEdgeNone, /* Capture Input not used. */\r
+ rtccCompBaseCnt, /* Compare with Base CNT register. */\r
+ 0, /* Compare mask. */\r
+ rtccDayCompareModeMonth /* Don't care. */\r
+};\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortSetupTimerInterrupt( void )\r
+{\r
+ /* Configure the RTCC to generate the RTOS tick interrupt. */\r
+\r
+ /* The maximum number of ticks that can be suppressed depends on the clock\r
+ frequency. */\r
+ xMaximumPossibleSuppressedTicks = ULONG_MAX / ulReloadValueForOneTick;\r
+\r
+ /* Ensure LE modules are accessible. */\r
+ CMU_ClockEnable( cmuClock_CORELE, true );\r
+\r
+ /* Use LFXO. */\r
+ CMU_ClockSelectSet( cmuClock_LFE, cmuSelect_LFXO );\r
+\r
+ /* Enable clock to the RTC module. */\r
+ CMU_ClockEnable( cmuClock_RTCC, true );\r
+\r
+ /* Use channel 1 to generate the RTOS tick interrupt. */\r
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValueForOneTick );\r
+\r
+ RTCC_Init( &xRTCInitStruct );\r
+ RTCC_ChannelInit( lpRTCC_CHANNEL, &xRTCCChannel1InitStruct );\r
+ RTCC_EM4WakeupEnable( true );\r
+\r
+ /* Disable RTCC interrupt. */\r
+ RTCC_IntDisable( _RTCC_IF_MASK );\r
+ RTCC_IntClear( _RTCC_IF_MASK );\r
+ RTCC->CNT = _RTCC_CNT_RESETVALUE;\r
+\r
+ /* The tick interrupt must be set to the lowest priority possible. */\r
+ NVIC_SetPriority( RTCC_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY );\r
+ NVIC_ClearPendingIRQ( RTCC_IRQn );\r
+ NVIC_EnableIRQ( RTCC_IRQn );\r
+ RTCC_IntEnable( RTCC_IEN_CC1 );\r
+ RTCC_Enable( true );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )\r
+{\r
+uint32_t ulReloadValue, ulCompleteTickPeriods, ulCountBeforeSleep, ulCountAfterSleep;\r
+eSleepModeStatus eSleepAction;\r
+TickType_t xModifiableIdleTime;\r
+\r
+ /* THIS FUNCTION IS CALLED WITH THE SCHEDULER SUSPENDED. */\r
+\r
+ /* Make sure the RTC reload value does not overflow the counter. */\r
+ if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )\r
+ {\r
+ xExpectedIdleTime = xMaximumPossibleSuppressedTicks;\r
+ }\r
+\r
+ /* Calculate the reload value required to wait xExpectedIdleTime tick\r
+ periods. */\r
+ ulReloadValue = ulReloadValueForOneTick * xExpectedIdleTime;\r
+ if( ulReloadValue > ulStoppedTimerCompensation )\r
+ {\r
+ /* Compensate for the fact that the RTC is going to be stopped\r
+ momentarily. */\r
+ ulReloadValue -= ulStoppedTimerCompensation;\r
+ }\r
+\r
+ /* Stop the RTC momentarily. The time the RTC is stopped for is accounted\r
+ for as best it can be, but using the tickless mode will inevitably result\r
+ in some tiny drift of the time maintained by the kernel with respect to\r
+ calendar time. The count is latched before stopping the timer as stopping\r
+ the timer appears to clear the count. */\r
+ ulCountBeforeSleep = RTCC_CounterGet();\r
+ RTCC_Enable( false );\r
+\r
+ /* If this function is re-entered before one complete tick period then the\r
+ reload value might be set to take into account a partial time slice, but\r
+ just reading the count assumes it is counting up to a full ticks worth - so\r
+ add in the difference if any. */\r
+ ulCountBeforeSleep += ( ulReloadValueForOneTick - RTCC_ChannelCCVGet( lpRTCC_CHANNEL ) );\r
+\r
+ /* Enter a critical section but don't use the taskENTER_CRITICAL() method as\r
+ that will mask interrupts that should exit sleep mode. */\r
+ INT_Disable();\r
+ __asm volatile( "dsb" );\r
+ __asm volatile( "isb" );\r
+\r
+ /* The tick flag is set to false before sleeping. If it is true when sleep\r
+ mode is exited then sleep mode was probably exited because the tick was\r
+ suppressed for the entire xExpectedIdleTime period. */\r
+ ulTickFlag = pdFALSE;\r
+\r
+ /* If a context switch is pending then abandon the low power entry as the\r
+ context switch might have been pended by an external interrupt that requires\r
+ processing. */\r
+ eSleepAction = eTaskConfirmSleepModeStatus();\r
+ if( eSleepAction == eAbortSleep )\r
+ {\r
+ /* Restart tick and count up to whatever was left of the current time\r
+ slice. */\r
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ( ulReloadValueForOneTick - ulCountBeforeSleep ) + ulStoppedTimerCompensation );\r
+ RTCC_Enable( true );\r
+\r
+ /* Re-enable interrupts - see comments above the cpsid instruction()\r
+ above. */\r
+ INT_Enable();\r
+ }\r
+ else\r
+ {\r
+ /* Adjust the reload value to take into account that the current time\r
+ slice is already partially complete. */\r
+ ulReloadValue -= ulCountBeforeSleep;\r
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValue );\r
+\r
+ /* Restart the RTC. */\r
+ RTCC_Enable( true );\r
+\r
+ /* Allow the application to define some pre-sleep processing. */\r
+ xModifiableIdleTime = xExpectedIdleTime;\r
+ configPRE_SLEEP_PROCESSING( xModifiableIdleTime );\r
+\r
+ /* xExpectedIdleTime being set to 0 by configPRE_SLEEP_PROCESSING()\r
+ means the application defined code has already executed the WAIT\r
+ instruction. */\r
+ if( xModifiableIdleTime > 0 )\r
+ {\r
+ __asm volatile( "dsb" );\r
+ SLEEP_Sleep();\r
+ __asm volatile( "isb" );\r
+ }\r
+\r
+ /* Allow the application to define some post sleep processing. */\r
+ configPOST_SLEEP_PROCESSING( xModifiableIdleTime );\r
+\r
+ /* Stop RTC. Again, the time the SysTick is stopped for is accounted\r
+ for as best it can be, but using the tickless mode will inevitably\r
+ result in some tiny drift of the time maintained by the kernel with\r
+ respect to calendar time. The count value is latched before stopping\r
+ the timer as stopping the timer appears to clear the count. */\r
+ ulCountAfterSleep = RTCC_CounterGet();\r
+ RTCC_Enable( false );\r
+\r
+ /* Re-enable interrupts - see comments above the cpsid instruction()\r
+ above. */\r
+ INT_Enable();\r
+ __asm volatile( "dsb" );\r
+ __asm volatile( "isb" );\r
+\r
+ if( ulTickFlag != pdFALSE )\r
+ {\r
+ /* The tick interrupt has already executed, although because this\r
+ function is called with the scheduler suspended the actual tick\r
+ processing will not occur until after this function has exited.\r
+ Reset the reload value with whatever remains of this tick period. */\r
+ ulReloadValue = ulReloadValueForOneTick - ulCountAfterSleep;\r
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValue );\r
+\r
+ /* The tick interrupt handler will already have pended the tick\r
+ processing in the kernel. As the pending tick will be processed as\r
+ soon as this function exits, the tick value maintained by the tick\r
+ is stepped forward by one less than the time spent sleeping. The\r
+ actual stepping of the tick appears later in this function. */\r
+ ulCompleteTickPeriods = xExpectedIdleTime - 1UL;\r
+ }\r
+ else\r
+ {\r
+ /* Something other than the tick interrupt ended the sleep. How\r
+ many complete tick periods passed while the processor was\r
+ sleeping? Add back in the adjustment that was made to the reload\r
+ value to account for the fact that a time slice was part way through\r
+ when this function was called. */\r
+ ulCountAfterSleep += ulCountBeforeSleep;\r
+ ulCompleteTickPeriods = ulCountAfterSleep / ulReloadValueForOneTick;\r
+\r
+ /* The reload value is set to whatever fraction of a single tick\r
+ period remains. */\r
+ ulCountAfterSleep -= ( ulCompleteTickPeriods * ulReloadValueForOneTick );\r
+ ulReloadValue = ulReloadValueForOneTick - ulCountAfterSleep;\r
+\r
+ if( ulReloadValue == 0 )\r
+ {\r
+ /* There is no fraction remaining. */\r
+ ulReloadValue = ulReloadValueForOneTick;\r
+ ulCompleteTickPeriods++;\r
+ }\r
+\r
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValue );\r
+ }\r
+\r
+ /* Restart the RTC so it runs up to the alarm value. The alarm value\r
+ will get set to the value required to generate exactly one tick period\r
+ the next time the RTC interrupt executes. */\r
+ RTCC_Enable( true );\r
+\r
+ /* Wind the tick forward by the number of tick periods that the CPU\r
+ remained in a low power state. */\r
+ vTaskStepTick( ulCompleteTickPeriods );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void RTCC_IRQHandler( void )\r
+{\r
+ ulTickFlag = pdTRUE;\r
+\r
+ if( RTCC_ChannelCCVGet( lpRTCC_CHANNEL ) != ulReloadValueForOneTick )\r
+ {\r
+ /* Set RTC interrupt to one RTOS tick period. */\r
+ RTCC_Enable( false );\r
+ RTCC_ChannelCCVSet( lpRTCC_CHANNEL, ulReloadValueForOneTick );\r
+ RTCC_Enable( true );\r
+ }\r
+\r
+ RTCC_IntClear( _RTCC_IF_MASK );\r
+\r
+ /* Critical section which protect incrementing the tick*/\r
+ portDISABLE_INTERRUPTS();\r
+ {\r
+ if( xTaskIncrementTick() != pdFALSE )\r
+ {\r
+ /* Pend a context switch. */\r
+ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
+ }\r
+ }\r
+ portENABLE_INTERRUPTS();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#endif /* ( configCREATE_LOW_POWER_DEMO == 1 ) */\r
--- /dev/null
+/*\r
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+ All rights reserved\r
+\r
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
+\r
+ ***************************************************************************\r
+ >>! NOTE: The modification to the GPL is included to allow you to !<<\r
+ >>! distribute a combined work that includes FreeRTOS without being !<<\r
+ >>! obliged to provide the source code for proprietary components !<<\r
+ >>! outside of the FreeRTOS kernel. !<<\r
+ ***************************************************************************\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following\r
+ link: http://www.freertos.org/a00114.html\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS provides completely free yet professionally developed, *\r
+ * robust, strictly quality controlled, supported, and cross *\r
+ * platform software that is more than just the market leader, it *\r
+ * is the industry's de facto standard. *\r
+ * *\r
+ * Help yourself get started quickly while simultaneously helping *\r
+ * to support the FreeRTOS project by purchasing a FreeRTOS *\r
+ * tutorial book, reference manual, or both: *\r
+ * http://www.FreeRTOS.org/Documentation *\r
+ * *\r
+ ***************************************************************************\r
+\r
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading\r
+ the FAQ page "My application does not run, what could be wrong?". Have you\r
+ defined configASSERT()?\r
+\r
+ http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+ embedded software for free we request you assist our global community by\r
+ participating in the support forum.\r
+\r
+ http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+ be as productive as possible as early as possible. Now you can receive\r
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+ Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS\r
+ licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+ engineered and independently SIL3 certified version for use in safety and\r
+ mission critical applications that require provable dependability.\r
+\r
+ 1 tab == 4 spaces!\r
+*/\r
+\r
+/******************************************************************************\r
+ * NOTE 1: This project provides two demo applications. A simple blinky demo\r
+ * that demonstrates tickless low power operation, and a more comprehensive\r
+ * test and demo application. The configCREATE_LOW_POWER_DEMO setting in\r
+ * FreeRTOSConfig.h is used to select between the two, and to select the clock\r
+ * used when tickless low power operation is demonstrated. See the notes on\r
+ * using configCREATE_LOW_POWER_DEMO in main.c. This file implements the low\r
+ * power version.\r
+ *\r
+ * NOTE 2: This file only contains the source code that is specific to the\r
+ * low power demo. Generic functions, such FreeRTOS hook functions, and\r
+ * functions required to configure the hardware are defined in main.c.\r
+ ******************************************************************************\r
+ *\r
+ * main_low_power() creates one queue, and two tasks. It then starts the\r
+ * scheduler.\r
+ *\r
+ * The Queue Send Task:\r
+ * The queue send task is implemented by the prvQueueSendTask() function in\r
+ * this file. It sends the value 100 to the queue every second.\r
+ *\r
+ * The Queue Receive Task:\r
+ * The queue receive task is implemented by the prvQueueReceiveTask() function\r
+ * in this file. prvQueueReceiveTask() blocks on the queue, blipping (quickly\r
+ * turn on then off again) the LED each time it received the value 100 from the\r
+ * queue send task. The queue send task writes to the queue every second, so\r
+ * the LED will blip once a second.\r
+ *\r
+ * The RTOS tick is turned off when the queue send task and queue receive task\r
+ * are both in the Blocked state.\r
+ *\r
+ */\r
+\r
+\r
+/* Kernel includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* SiLabs includes. */\r
+#include "bsp.h"\r
+\r
+/* Priorities at which the tasks are created. */\r
+#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )\r
+#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
+\r
+/* The rate at which data is sent to the queue. The 200ms value is converted\r
+to ticks using the portTICK_PERIOD_MS constant. */\r
+#define mainQUEUE_SEND_FREQUENCY_MS pdMS_TO_TICKS( 1000 )\r
+\r
+/* The number of items the queue can hold. This is 1 as the receive task\r
+will remove items as they are added, meaning the send task should always find\r
+the queue empty. */\r
+#define mainQUEUE_LENGTH ( 1 )\r
+\r
+/* The LED toggled by the Rx task. */\r
+#define mainTASK_LED ( 0 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Called by main when mainCREATE_LOW_POWER_DEMO is set to 1 in\r
+ * main.c.\r
+ */\r
+void main_low_power( void );\r
+\r
+/*\r
+ * The tasks as described in the comments at the top of this file.\r
+ */\r
+static void prvQueueReceiveTask( void *pvParameters );\r
+static void prvQueueSendTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The queue used by both tasks. */\r
+static QueueHandle_t xQueue = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void main_low_power( void )\r
+{\r
+ /* Create the queue. */\r
+ xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );\r
+\r
+ if( xQueue != NULL )\r
+ {\r
+ /* Start the two tasks as described in the comments at the top of this\r
+ file. */\r
+ xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */\r
+ "Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */\r
+ configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */\r
+ NULL, /* The parameter passed to the task - not used in this case. */\r
+ mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */\r
+ NULL ); /* The task handle is not required, so NULL is passed. */\r
+\r
+ xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );\r
+\r
+ /* Start the tasks and timer running. */\r
+ vTaskStartScheduler();\r
+ }\r
+\r
+ /* If all is well, the scheduler will now be running, and the following\r
+ line will never be reached. If the following line does execute, then\r
+ there was insufficient FreeRTOS heap memory available for the Idle and/or\r
+ timer tasks to be created. See the memory management section on the\r
+ FreeRTOS web site for more details on the FreeRTOS heap\r
+ http://www.freertos.org/a00111.html. */\r
+ for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvQueueSendTask( void *pvParameters )\r
+{\r
+TickType_t xNextWakeTime;\r
+const uint32_t ulValueToSend = 100UL;\r
+\r
+ /* Remove compiler warning about unused parameter. */\r
+ ( void ) pvParameters;\r
+\r
+ /* Initialise xNextWakeTime - this only needs to be done once. */\r
+ xNextWakeTime = xTaskGetTickCount();\r
+\r
+ for( ;; )\r
+ {\r
+ /* Place this task in the blocked state until it is time to run again. */\r
+ vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );\r
+\r
+ /* Send to the queue - causing the queue receive task to unblock and\r
+ toggle the LED. 0 is used as the block time so the sending operation\r
+ will not block - it shouldn't need to block as the queue should always\r
+ be empty at this point in the code. */\r
+ xQueueSend( xQueue, &ulValueToSend, 0U );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvQueueReceiveTask( void *pvParameters )\r
+{\r
+uint32_t ulReceivedValue;\r
+const uint32_t ulExpectedValue = 100UL;\r
+const TickType_t xShortDelay = pdMS_TO_TICKS( 10 );\r
+\r
+ /* Remove compiler warning about unused parameter. */\r
+ ( void ) pvParameters;\r
+\r
+ for( ;; )\r
+ {\r
+ /* Wait until something arrives in the queue - this task will block\r
+ indefinitely provided INCLUDE_vTaskSuspend is set to 1 in\r
+ FreeRTOSConfig.h. */\r
+ xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );\r
+\r
+ /* To get here something must have been received from the queue, but\r
+ is it the expected value? If it is, toggle the LED. */\r
+ if( ulReceivedValue == ulExpectedValue )\r
+ {\r
+ /* Turn the LED on for a brief time only so it doens't distort the\r
+ energy reading. */\r
+ BSP_LedSet( mainTASK_LED );\r
+ vTaskDelay( xShortDelay );\r
+ BSP_LedClear( mainTASK_LED );\r
+ ulReceivedValue = 0U;\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
--- /dev/null
+/***************************************************************************//**\r
+ * @file\r
+ * @brief Board support package API for GPIO leds on STK's.\r
+ * @version 4.2.1\r
+ *******************************************************************************\r
+ * @section License\r
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>\r
+ *******************************************************************************\r
+ *\r
+ * This file is licensed under the Silabs License Agreement. See the file\r
+ * "Silabs_License_Agreement.txt" for details. Before using this software for\r
+ * any purpose, you must agree to the terms of that agreement.\r
+ *\r
+ ******************************************************************************/\r
+\r
+\r
+\r
+#include "em_device.h"\r
+#include "em_cmu.h"\r
+#include "em_gpio.h"\r
+#include "bsp.h"\r
+\r
+#if defined( BSP_GPIO_LEDS )\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+\r
+typedef struct\r
+{\r
+ GPIO_Port_TypeDef port;\r
+ unsigned int pin;\r
+} tLedArray;\r
+\r
+static const tLedArray ledArray[ BSP_NO_OF_LEDS ] = BSP_GPIO_LEDARRAY_INIT;\r
+\r
+int BSP_LedsInit(void)\r
+{\r
+ int i;\r
+\r
+ CMU_ClockEnable(cmuClock_HFPER, true);\r
+ CMU_ClockEnable(cmuClock_GPIO, true);\r
+ for ( i=0; i<BSP_NO_OF_LEDS; i++ )\r
+ {\r
+ GPIO_PinModeSet(ledArray[i].port, ledArray[i].pin, gpioModePushPull, 0);\r
+ }\r
+ return BSP_STATUS_OK;\r
+}\r
+\r
+uint32_t BSP_LedsGet(void)\r
+{\r
+ int i;\r
+ uint32_t retVal, mask;\r
+\r
+ for ( i=0, retVal=0, mask=0x1; i<BSP_NO_OF_LEDS; i++, mask <<= 1 )\r
+ {\r
+ if (GPIO_PinOutGet(ledArray[i].port, ledArray[i].pin))\r
+ retVal |= mask;\r
+ }\r
+ return retVal;\r
+}\r
+\r
+int BSP_LedsSet(uint32_t leds)\r
+{\r
+ int i;\r
+ uint32_t mask;\r
+\r
+ for ( i=0, mask=0x1; i<BSP_NO_OF_LEDS; i++, mask <<= 1 )\r
+ {\r
+ if ( leds & mask )\r
+ GPIO_PinOutSet(ledArray[i].port, ledArray[i].pin);\r
+ else\r
+ GPIO_PinOutClear(ledArray[i].port, ledArray[i].pin);\r
+ }\r
+ return BSP_STATUS_OK;\r
+}\r
+\r
+int BSP_LedClear(int ledNo)\r
+{\r
+ if ((ledNo >= 0) && (ledNo < BSP_NO_OF_LEDS))\r
+ {\r
+ GPIO_PinOutClear(ledArray[ledNo].port, ledArray[ledNo].pin);\r
+ return BSP_STATUS_OK;\r
+ }\r
+ return BSP_STATUS_ILLEGAL_PARAM;\r
+}\r
+\r
+int BSP_LedGet(int ledNo)\r
+{\r
+ int retVal = BSP_STATUS_ILLEGAL_PARAM;\r
+\r
+ if ((ledNo >= 0) && (ledNo < BSP_NO_OF_LEDS))\r
+ {\r
+ retVal = (int)GPIO_PinOutGet(ledArray[ledNo].port, ledArray[ledNo].pin);\r
+ }\r
+ return retVal;\r
+}\r
+\r
+int BSP_LedSet(int ledNo)\r
+{\r
+ if ((ledNo >= 0) && (ledNo < BSP_NO_OF_LEDS))\r
+ {\r
+ GPIO_PinOutSet(ledArray[ledNo].port, ledArray[ledNo].pin);\r
+ return BSP_STATUS_OK;\r
+ }\r
+ return BSP_STATUS_ILLEGAL_PARAM;\r
+}\r
+\r
+int BSP_LedToggle(int ledNo)\r
+{\r
+ if ((ledNo >= 0) && (ledNo < BSP_NO_OF_LEDS))\r
+ {\r
+ GPIO_PinOutToggle(ledArray[ledNo].port, ledArray[ledNo].pin);\r
+ return BSP_STATUS_OK;\r
+ }\r
+ return BSP_STATUS_ILLEGAL_PARAM;\r
+}\r
+\r
+/** @endcond */\r
+#endif /* BSP_GPIO_LEDS */\r
--- /dev/null
+/* @file startup_efm32pg1b.S\r
+ * @brief startup file for Silicon Labs EFM32PG1B devices.\r
+ * For use with GCC for ARM Embedded Processors\r
+ * @version 4.2.1\r
+ * Date: 12 June 2014\r
+ *\r
+ */\r
+/* Copyright (c) 2011 - 2014 ARM LIMITED\r
+\r
+ All rights reserved.\r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions are met:\r
+ - Redistributions of source code must retain the above copyright\r
+ notice, this list of conditions and the following disclaimer.\r
+ - Redistributions in binary form must reproduce the above copyright\r
+ notice, this list of conditions and the following disclaimer in the\r
+ documentation and/or other materials provided with the distribution.\r
+ - Neither the name of ARM nor the names of its contributors may be used\r
+ to endorse or promote products derived from this software without\r
+ specific prior written permission.\r
+ *\r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE\r
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ POSSIBILITY OF SUCH DAMAGE.\r
+ ---------------------------------------------------------------------------*/\r
+\r
+ .syntax unified\r
+ .arch armv7-m\r
+ .section .stack\r
+ .align 3\r
+#ifdef __STACK_SIZE\r
+ .equ Stack_Size, __STACK_SIZE\r
+#else\r
+ .equ Stack_Size, 0x00000400\r
+#endif\r
+ .globl __StackTop\r
+ .globl __StackLimit\r
+__StackLimit:\r
+ .space Stack_Size\r
+ .size __StackLimit, . - __StackLimit\r
+__StackTop:\r
+ .size __StackTop, . - __StackTop\r
+\r
+ .section .heap\r
+ .align 3\r
+#ifdef __HEAP_SIZE\r
+ .equ Heap_Size, __HEAP_SIZE\r
+#else\r
+ .equ Heap_Size, 0x00000C00\r
+#endif\r
+ .globl __HeapBase\r
+ .globl __HeapLimit\r
+__HeapBase:\r
+ .if Heap_Size\r
+ .space Heap_Size\r
+ .endif\r
+ .size __HeapBase, . - __HeapBase\r
+__HeapLimit:\r
+ .size __HeapLimit, . - __HeapLimit\r
+\r
+ .section .vectors\r
+ .align 2\r
+ .globl __Vectors\r
+__Vectors:\r
+ .long __StackTop /* Top of Stack */\r
+ .long Reset_Handler /* Reset Handler */\r
+ .long NMI_Handler /* NMI Handler */\r
+ .long HardFault_Handler /* Hard Fault Handler */\r
+ .long MemManage_Handler /* MPU Fault Handler */\r
+ .long BusFault_Handler /* Bus Fault Handler */\r
+ .long UsageFault_Handler /* Usage Fault Handler */\r
+ .long Default_Handler /* Reserved */\r
+ .long Default_Handler /* Reserved */\r
+ .long Default_Handler /* Reserved */\r
+ .long Default_Handler /* Reserved */\r
+ .long SVC_Handler /* SVCall Handler */\r
+ .long DebugMon_Handler /* Debug Monitor Handler */\r
+ .long Default_Handler /* Reserved */\r
+ .long PendSV_Handler /* PendSV Handler */\r
+ .long SysTick_Handler /* SysTick Handler */\r
+\r
+ /* External interrupts */\r
+ .long EMU_IRQHandler /* 0 - EMU */\r
+ .long Default_Handler /* 1 - Reserved */\r
+ .long WDOG0_IRQHandler /* 2 - WDOG0 */\r
+ .long Default_Handler /* 3 - Reserved */\r
+ .long Default_Handler /* 4 - Reserved */\r
+ .long Default_Handler /* 5 - Reserved */\r
+ .long Default_Handler /* 6 - Reserved */\r
+ .long Default_Handler /* 7 - Reserved */\r
+ .long LDMA_IRQHandler /* 8 - LDMA */\r
+ .long GPIO_EVEN_IRQHandler /* 9 - GPIO_EVEN */\r
+ .long TIMER0_IRQHandler /* 10 - TIMER0 */\r
+ .long USART0_RX_IRQHandler /* 11 - USART0_RX */\r
+ .long USART0_TX_IRQHandler /* 12 - USART0_TX */\r
+ .long ACMP0_IRQHandler /* 13 - ACMP0 */\r
+ .long ADC0_IRQHandler /* 14 - ADC0 */\r
+ .long IDAC0_IRQHandler /* 15 - IDAC0 */\r
+ .long I2C0_IRQHandler /* 16 - I2C0 */\r
+ .long GPIO_ODD_IRQHandler /* 17 - GPIO_ODD */\r
+ .long TIMER1_IRQHandler /* 18 - TIMER1 */\r
+ .long USART1_RX_IRQHandler /* 19 - USART1_RX */\r
+ .long USART1_TX_IRQHandler /* 20 - USART1_TX */\r
+ .long LEUART0_IRQHandler /* 21 - LEUART0 */\r
+ .long PCNT0_IRQHandler /* 22 - PCNT0 */\r
+ .long CMU_IRQHandler /* 23 - CMU */\r
+ .long MSC_IRQHandler /* 24 - MSC */\r
+ .long CRYPTO_IRQHandler /* 25 - CRYPTO */\r
+ .long LETIMER0_IRQHandler /* 26 - LETIMER0 */\r
+ .long Default_Handler /* 27 - Reserved */\r
+ .long Default_Handler /* 28 - Reserved */\r
+ .long RTCC_IRQHandler /* 29 - RTCC */\r
+ .long Default_Handler /* 30 - Reserved */\r
+ .long CRYOTIMER_IRQHandler /* 31 - CRYOTIMER */\r
+ .long Default_Handler /* 32 - Reserved */\r
+ .long FPUEH_IRQHandler /* 33 - FPUEH */\r
+\r
+\r
+ .size __Vectors, . - __Vectors\r
+\r
+ .text\r
+ .thumb\r
+ .thumb_func\r
+ .align 2\r
+ .globl Reset_Handler\r
+ .type Reset_Handler, %function\r
+Reset_Handler:\r
+#ifndef __NO_SYSTEM_INIT\r
+ ldr r0, =SystemInit\r
+ blx r0\r
+#endif\r
+\r
+/* Firstly it copies data from read only memory to RAM. There are two schemes\r
+ * to copy. One can copy more than one sections. Another can only copy\r
+ * one section. The former scheme needs more instructions and read-only\r
+ * data to implement than the latter.\r
+ * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */\r
+\r
+#ifdef __STARTUP_COPY_MULTIPLE\r
+/* Multiple sections scheme.\r
+ *\r
+ * Between symbol address __copy_table_start__ and __copy_table_end__,\r
+ * there are array of triplets, each of which specify:\r
+ * offset 0: LMA of start of a section to copy from\r
+ * offset 4: VMA of start of a section to copy to\r
+ * offset 8: size of the section to copy. Must be multiply of 4\r
+ *\r
+ * All addresses must be aligned to 4 bytes boundary.\r
+ */\r
+ ldr r4, =__copy_table_start__\r
+ ldr r5, =__copy_table_end__\r
+\r
+.L_loop0:\r
+ cmp r4, r5\r
+ bge .L_loop0_done\r
+ ldr r1, [r4]\r
+ ldr r2, [r4, #4]\r
+ ldr r3, [r4, #8]\r
+\r
+.L_loop0_0:\r
+ subs r3, #4\r
+ ittt ge\r
+ ldrge r0, [r1, r3]\r
+ strge r0, [r2, r3]\r
+ bge .L_loop0_0\r
+\r
+ adds r4, #12\r
+ b .L_loop0\r
+\r
+.L_loop0_done:\r
+#else\r
+/* Single section scheme.\r
+ *\r
+ * The ranges of copy from/to are specified by following symbols\r
+ * __etext: LMA of start of the section to copy from. Usually end of text\r
+ * __data_start__: VMA of start of the section to copy to\r
+ * __data_end__: VMA of end of the section to copy to\r
+ *\r
+ * All addresses must be aligned to 4 bytes boundary.\r
+ */\r
+ ldr r1, =__etext\r
+ ldr r2, =__data_start__\r
+ ldr r3, =__data_end__\r
+\r
+.L_loop1:\r
+ cmp r2, r3\r
+ ittt lt\r
+ ldrlt r0, [r1], #4\r
+ strlt r0, [r2], #4\r
+ blt .L_loop1\r
+#endif /*__STARTUP_COPY_MULTIPLE */\r
+\r
+/* This part of work usually is done in C library startup code. Otherwise,\r
+ * define this macro to enable it in this startup.\r
+ *\r
+ * There are two schemes too. One can clear multiple BSS sections. Another\r
+ * can only clear one section. The former is more size expensive than the\r
+ * latter.\r
+ *\r
+ * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.\r
+ * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later.\r
+ */\r
+#ifdef __STARTUP_CLEAR_BSS_MULTIPLE\r
+/* Multiple sections scheme.\r
+ *\r
+ * Between symbol address __copy_table_start__ and __copy_table_end__,\r
+ * there are array of tuples specifying:\r
+ * offset 0: Start of a BSS section\r
+ * offset 4: Size of this BSS section. Must be multiply of 4\r
+ */\r
+ ldr r3, =__zero_table_start__\r
+ ldr r4, =__zero_table_end__\r
+\r
+.L_loop2:\r
+ cmp r3, r4\r
+ bge .L_loop2_done\r
+ ldr r1, [r3]\r
+ ldr r2, [r3, #4]\r
+ movs r0, 0\r
+\r
+.L_loop2_0:\r
+ subs r2, #4\r
+ itt ge\r
+ strge r0, [r1, r2]\r
+ bge .L_loop2_0\r
+ adds r3, #8\r
+ b .L_loop2\r
+.L_loop2_done:\r
+#elif defined (__STARTUP_CLEAR_BSS)\r
+/* Single BSS section scheme.\r
+ *\r
+ * The BSS section is specified by following symbols\r
+ * __bss_start__: start of the BSS section.\r
+ * __bss_end__: end of the BSS section.\r
+ *\r
+ * Both addresses must be aligned to 4 bytes boundary.\r
+ */\r
+ ldr r1, =__bss_start__\r
+ ldr r2, =__bss_end__\r
+\r
+ movs r0, 0\r
+.L_loop3:\r
+ cmp r1, r2\r
+ itt lt\r
+ strlt r0, [r1], #4\r
+ blt .L_loop3\r
+#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */\r
+\r
+#ifndef __START\r
+#define __START _start\r
+#endif\r
+ bl __START\r
+\r
+ .pool\r
+ .size Reset_Handler, . - Reset_Handler\r
+\r
+ .align 1\r
+ .thumb_func\r
+ .weak Default_Handler\r
+ .type Default_Handler, %function\r
+Default_Handler:\r
+ b .\r
+ .size Default_Handler, . - Default_Handler\r
+\r
+/* Macro to define default handlers. Default handler\r
+ * will be weak symbol and just dead loops. They can be\r
+ * overwritten by other handlers */\r
+ .macro def_irq_handler handler_name\r
+ .weak \handler_name\r
+ .set \handler_name, Default_Handler\r
+ .endm\r
+\r
+ def_irq_handler NMI_Handler\r
+ def_irq_handler HardFault_Handler\r
+ def_irq_handler MemManage_Handler\r
+ def_irq_handler BusFault_Handler\r
+ def_irq_handler UsageFault_Handler\r
+ def_irq_handler SVC_Handler\r
+ def_irq_handler DebugMon_Handler\r
+ def_irq_handler PendSV_Handler\r
+ def_irq_handler SysTick_Handler\r
+\r
+\r
+ def_irq_handler EMU_IRQHandler\r
+ def_irq_handler WDOG0_IRQHandler\r
+ def_irq_handler LDMA_IRQHandler\r
+ def_irq_handler GPIO_EVEN_IRQHandler\r
+ def_irq_handler TIMER0_IRQHandler\r
+ def_irq_handler USART0_RX_IRQHandler\r
+ def_irq_handler USART0_TX_IRQHandler\r
+ def_irq_handler ACMP0_IRQHandler\r
+ def_irq_handler ADC0_IRQHandler\r
+ def_irq_handler IDAC0_IRQHandler\r
+ def_irq_handler I2C0_IRQHandler\r
+ def_irq_handler GPIO_ODD_IRQHandler\r
+ def_irq_handler TIMER1_IRQHandler\r
+ def_irq_handler USART1_RX_IRQHandler\r
+ def_irq_handler USART1_TX_IRQHandler\r
+ def_irq_handler LEUART0_IRQHandler\r
+ def_irq_handler PCNT0_IRQHandler\r
+ def_irq_handler CMU_IRQHandler\r
+ def_irq_handler MSC_IRQHandler\r
+ def_irq_handler CRYPTO_IRQHandler\r
+ def_irq_handler LETIMER0_IRQHandler\r
+ def_irq_handler RTCC_IRQHandler\r
+ def_irq_handler CRYOTIMER_IRQHandler\r
+ def_irq_handler FPUEH_IRQHandler\r
+\r
+ .end\r
--- /dev/null
+/***************************************************************************//**\r
+ * @file system_efm32pg1b.c\r
+ * @brief CMSIS Cortex-M3/M4 System Layer for EFM32 devices.\r
+ * @version 4.2.1\r
+ ******************************************************************************\r
+ * @section License\r
+ * <b>Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com</b>\r
+ ******************************************************************************\r
+ *\r
+ * Permission is granted to anyone to use this software for any purpose,\r
+ * including commercial applications, and to alter it and redistribute it\r
+ * freely, subject to the following restrictions:\r
+ *\r
+ * 1. The origin of this software must not be misrepresented; you must not\r
+ * claim that you wrote the original software.@n\r
+ * 2. Altered source versions must be plainly marked as such, and must not be\r
+ * misrepresented as being the original software.@n\r
+ * 3. This notice may not be removed or altered from any source distribution.\r
+ *\r
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Laboratories, Inc.\r
+ * has no obligation to support this Software. Silicon Laboratories, Inc. is\r
+ * providing the Software "AS IS", with no express or implied warranties of any\r
+ * kind, including, but not limited to, any implied warranties of\r
+ * merchantability or fitness for any particular purpose or warranties against\r
+ * infringement of any proprietary rights of a third party.\r
+ *\r
+ * Silicon Laboratories, Inc. will not be liable for any consequential,\r
+ * incidental, or special damages, or any other relief, or for any claim by\r
+ * any third party, arising from your use of this Software.\r
+ *\r
+ *****************************************************************************/\r
+\r
+#include <stdint.h>\r
+#include "em_device.h"\r
+\r
+/*******************************************************************************\r
+ ****************************** DEFINES ************************************\r
+ ******************************************************************************/\r
+\r
+/** LFRCO frequency, tuned to below frequency during manufacturing. */\r
+#define EFM32_LFRCO_FREQ (32768UL)\r
+#define EFM32_ULFRCO_FREQ (1000UL)\r
+\r
+/*******************************************************************************\r
+ ************************** LOCAL VARIABLES ********************************\r
+ ******************************************************************************/\r
+\r
+/* System oscillator frequencies. These frequencies are normally constant */\r
+/* for a target, but they are made configurable in order to allow run-time */\r
+/* handling of different boards. The crystal oscillator clocks can be set */\r
+/* compile time to a non-default value by defining respective EFM_nFXO_FREQ */\r
+/* values according to board design. By defining the EFM_nFXO_FREQ to 0, */\r
+/* one indicates that the oscillator is not present, in order to save some */\r
+/* SW footprint. */\r
+\r
+#ifndef EFM32_HFRCO_MAX_FREQ\r
+#define EFM32_HFRCO_MAX_FREQ (38000000UL)\r
+#endif\r
+\r
+#ifndef EFM32_HFXO_FREQ\r
+#define EFM32_HFXO_FREQ (40000000UL)\r
+#endif\r
+\r
+#ifndef EFM32_HFRCO_STARTUP_FREQ\r
+#define EFM32_HFRCO_STARTUP_FREQ (19000000UL)\r
+#endif\r
+\r
+\r
+/* Do not define variable if HF crystal oscillator not present */\r
+#if (EFM32_HFXO_FREQ > 0UL)\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+/** System HFXO clock. */\r
+static uint32_t SystemHFXOClock = EFM32_HFXO_FREQ;\r
+/** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */\r
+#endif\r
+\r
+#ifndef EFM32_LFXO_FREQ\r
+#define EFM32_LFXO_FREQ (EFM32_LFRCO_FREQ)\r
+#endif\r
+/* Do not define variable if LF crystal oscillator not present */\r
+#if (EFM32_LFXO_FREQ > 0UL)\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+/** System LFXO clock. */\r
+static uint32_t SystemLFXOClock = 32768UL;\r
+/** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */\r
+#endif\r
+\r
+\r
+/*******************************************************************************\r
+ ************************** GLOBAL VARIABLES *******************************\r
+ ******************************************************************************/\r
+\r
+/**\r
+ * @brief\r
+ * System System Clock Frequency (Core Clock).\r
+ *\r
+ * @details\r
+ * Required CMSIS global variable that must be kept up-to-date.\r
+ */\r
+uint32_t SystemCoreClock;\r
+\r
+\r
+/**\r
+ * @brief\r
+ * System HFRCO frequency\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary variable, not part of the CMSIS definition.\r
+ *\r
+ * @details\r
+ * Frequency of the system HFRCO oscillator\r
+ */\r
+uint32_t SystemHfrcoFreq = EFM32_HFRCO_STARTUP_FREQ;\r
+\r
+\r
+/*******************************************************************************\r
+ ************************** GLOBAL FUNCTIONS *******************************\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the current core clock frequency.\r
+ *\r
+ * @details\r
+ * Calculate and get the current core clock frequency based on the current\r
+ * configuration. Assuming that the SystemCoreClock global variable is\r
+ * maintained, the core clock frequency is stored in that variable as well.\r
+ * This function will however calculate the core clock based on actual HW\r
+ * configuration. It will also update the SystemCoreClock global variable.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * The current core clock frequency in Hz.\r
+ ******************************************************************************/\r
+uint32_t SystemCoreClockGet(void)\r
+{\r
+ uint32_t ret;\r
+ uint32_t presc;\r
+\r
+ ret = SystemHFClockGet();\r
+ presc = (CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK) >>\r
+ _CMU_HFCOREPRESC_PRESC_SHIFT;\r
+ ret /= (presc + 1);\r
+\r
+ /* Keep CMSIS system clock variable up-to-date */\r
+ SystemCoreClock = ret;\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the maximum core clock frequency.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * The maximum core clock frequency in Hz.\r
+ ******************************************************************************/\r
+uint32_t SystemMaxCoreClockGet(void)\r
+{\r
+ return (EFM32_HFRCO_MAX_FREQ > EFM32_HFXO_FREQ ? \\r
+ EFM32_HFRCO_MAX_FREQ : EFM32_HFXO_FREQ);\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the current HFCLK frequency.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * The current HFCLK frequency in Hz.\r
+ ******************************************************************************/\r
+uint32_t SystemHFClockGet(void)\r
+{\r
+ uint32_t ret;\r
+\r
+ switch (CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK)\r
+ {\r
+ case CMU_HFCLKSTATUS_SELECTED_LFXO:\r
+#if (EFM32_LFXO_FREQ > 0)\r
+ ret = SystemLFXOClock;\r
+#else\r
+ /* We should not get here, since core should not be clocked. May */\r
+ /* be caused by a misconfiguration though. */\r
+ ret = 0;\r
+#endif\r
+ break;\r
+\r
+ case CMU_HFCLKSTATUS_SELECTED_LFRCO:\r
+ ret = EFM32_LFRCO_FREQ;\r
+ break;\r
+\r
+ case CMU_HFCLKSTATUS_SELECTED_HFXO:\r
+#if (EFM32_HFXO_FREQ > 0)\r
+ ret = SystemHFXOClock;\r
+#else\r
+ /* We should not get here, since core should not be clocked. May */\r
+ /* be caused by a misconfiguration though. */\r
+ ret = 0;\r
+#endif\r
+ break;\r
+\r
+ default: /* CMU_HFCLKSTATUS_SELECTED_HFRCO */\r
+ ret = SystemHfrcoFreq;\r
+ break;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Get high frequency crystal oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * HFXO frequency in Hz.\r
+ *****************************************************************************/\r
+uint32_t SystemHFXOClockGet(void)\r
+{\r
+ /* External crystal oscillator present? */\r
+#if (EFM32_HFXO_FREQ > 0)\r
+ return SystemHFXOClock;\r
+#else\r
+ return 0;\r
+#endif\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Set high frequency crystal oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This function is mainly provided for being able to handle target systems\r
+ * with different HF crystal oscillator frequencies run-time. If used, it\r
+ * should probably only be used once during system startup.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @param[in] freq\r
+ * HFXO frequency in Hz used for target.\r
+ *****************************************************************************/\r
+void SystemHFXOClockSet(uint32_t freq)\r
+{\r
+ /* External crystal oscillator present? */\r
+#if (EFM32_HFXO_FREQ > 0)\r
+ SystemHFXOClock = freq;\r
+\r
+ /* Update core clock frequency if HFXO is used to clock core */\r
+ if ((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) == CMU_HFCLKSTATUS_SELECTED_HFXO)\r
+ {\r
+ /* The function will update the global variable */\r
+ SystemCoreClockGet();\r
+ }\r
+#else\r
+ (void)freq; /* Unused parameter */\r
+#endif\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Initialize the system.\r
+ *\r
+ * @details\r
+ * Do required generic HW system init.\r
+ *\r
+ * @note\r
+ * This function is invoked during system init, before the main() routine\r
+ * and any data has been initialized. For this reason, it cannot do any\r
+ * initialization of variables etc.\r
+ *****************************************************************************/\r
+void SystemInit(void)\r
+{\r
+#if (__FPU_PRESENT == 1)\r
+ /* Set floating point coprosessor access mode. */\r
+ SCB->CPACR |= ((3UL << 10 * 2) | /* set CP10 Full Access */\r
+ (3UL << 11 * 2)); /* set CP11 Full Access */\r
+#endif\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Get low frequency RC oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * LFRCO frequency in Hz.\r
+ *****************************************************************************/\r
+uint32_t SystemLFRCOClockGet(void)\r
+{\r
+ /* Currently we assume that this frequency is properly tuned during */\r
+ /* manufacturing and is not changed after reset. If future requirements */\r
+ /* for re-tuning by user, we can add support for that. */\r
+ return EFM32_LFRCO_FREQ;\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Get ultra low frequency RC oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * ULFRCO frequency in Hz.\r
+ *****************************************************************************/\r
+uint32_t SystemULFRCOClockGet(void)\r
+{\r
+ /* The ULFRCO frequency is not tuned, and can be very inaccurate */\r
+ return EFM32_ULFRCO_FREQ;\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Get low frequency crystal oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * LFXO frequency in Hz.\r
+ *****************************************************************************/\r
+uint32_t SystemLFXOClockGet(void)\r
+{\r
+ /* External crystal oscillator present? */\r
+#if (EFM32_LFXO_FREQ > 0)\r
+ return SystemLFXOClock;\r
+#else\r
+ return 0;\r
+#endif\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Set low frequency crystal oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This function is mainly provided for being able to handle target systems\r
+ * with different HF crystal oscillator frequencies run-time. If used, it\r
+ * should probably only be used once during system startup.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @param[in] freq\r
+ * LFXO frequency in Hz used for target.\r
+ *****************************************************************************/\r
+void SystemLFXOClockSet(uint32_t freq)\r
+{\r
+ /* External crystal oscillator present? */\r
+#if (EFM32_LFXO_FREQ > 0)\r
+ SystemLFXOClock = freq;\r
+\r
+ /* Update core clock frequency if LFXO is used to clock core */\r
+ if ((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) == CMU_HFCLKSTATUS_SELECTED_LFXO)\r
+ {\r
+ /* The function will update the global variable */\r
+ SystemCoreClockGet();\r
+ }\r
+#else\r
+ (void)freq; /* Unused parameter */\r
+#endif\r
+}\r
--- /dev/null
+/***************************************************************************//**\r
+ * @file sleep.h\r
+ * @brief Energy Modes management driver\r
+ * @version 4.2.1\r
+ * @details\r
+ * This is a energy modes management module consisting of sleep.c and sleep.h\r
+ * source files. The main purpose of the module is to ease energy\r
+ * optimization with a simple API. The module allows the system to always sleep\r
+ * in the lowest possible energy mode. Users could set up callbacks that are\r
+ * being called before and after each and every sleep. A counting semaphore is\r
+ * available for each low energy mode (EM1/EM2/EM3) to protect certain system\r
+ * states from being corrupted. This semaphore has limit set to maximum 255 locks.\r
+ *\r
+ * The module provides the following public API to the users:\r
+ * SLEEP_Init()\r
+ * SLEEP_Sleep()\r
+ * SLEEP_SleepBlockBegin()\r
+ * SLEEP_SleepBlockEnd()\r
+ * SLEEP_ForceSleepInEM4()\r
+ *\r
+ *******************************************************************************\r
+ * @section License\r
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>\r
+ *******************************************************************************\r
+ *\r
+ * This file is licensed under the Silabs License Agreement. See the file\r
+ * "Silabs_License_Agreement.txt" for details. Before using this software for\r
+ * any purpose, you must agree to the terms of that agreement.\r
+ *\r
+ ******************************************************************************/\r
+\r
+#ifndef __SLEEP_H\r
+#define __SLEEP_H\r
+\r
+#include <stdint.h>\r
+#include <stdbool.h>\r
+\r
+/* Device specific header file(s). */\r
+#include "em_device.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup EM_Drivers\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup SLEEP\r
+ * @brief Energy Modes management driver.\r
+ * @details\r
+ * This is a energy modes management module consisting of sleep.c and sleep.h\r
+ * source files. The main purpose of the module is to ease energy\r
+ * optimization with a simple API. The module allows the system to always sleep\r
+ * in the lowest possible energy mode. Users could set up callbacks that are\r
+ * being called before and after each and every sleep. A counting semaphore is\r
+ * available for each low energy mode (EM1/EM2/EM3) to protect certain system\r
+ * states from being corrupted. This semaphore has limit set to maximum 255 locks.\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/*******************************************************************************\r
+ ******************************* MACROS ************************************\r
+ ******************************************************************************/\r
+\r
+\r
+/*******************************************************************************\r
+ **************************** CONFIGURATION ********************************\r
+ ******************************************************************************/\r
+\r
+/** Enable/disable the HW block for protecting accidental setting of low energy\r
+ * modes (recommended to be set to true). */\r
+#ifndef SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED\r
+#define SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED true\r
+#endif\r
+\r
+/** Enable/disable calling wakeup callback after EM4 reset. */\r
+#ifndef SLEEP_EM4_WAKEUP_CALLBACK_ENABLED\r
+#define SLEEP_EM4_WAKEUP_CALLBACK_ENABLED true\r
+#endif\r
+\r
+/** Configure default lowest energy mode that the system can be set to.\r
+ * Possible values:\r
+ * @li sleepEM1 - EM1, the CPU core is turned off.\r
+ * @li sleepEM2 - EM2, like EM1 + all HF clocks are turned off, LF clocks are on.\r
+ * @li sleepEM3 - EM3, like EM2 + LF clocks are off, RAM retention, GPIO and ACMP\r
+ * interrupt is on. */\r
+#ifndef SLEEP_LOWEST_ENERGY_MODE_DEFAULT\r
+#define SLEEP_LOWEST_ENERGY_MODE_DEFAULT sleepEM3\r
+#endif\r
+\r
+/*******************************************************************************\r
+ ****************************** TYPEDEFS ***********************************\r
+ ******************************************************************************/\r
+\r
+/** Status value used for showing the Energy Mode the device is currently in. */\r
+typedef enum\r
+{\r
+ /** Status value for EM0. */\r
+ sleepEM0 = 0,\r
+\r
+ /** Status value for EM1. */\r
+ sleepEM1 = 1,\r
+\r
+ /** Status value for EM2. */\r
+ sleepEM2 = 2,\r
+\r
+ /** Status value for EM3. */\r
+ sleepEM3 = 3,\r
+\r
+ /** Status value for EM4. */\r
+ sleepEM4 = 4\r
+} SLEEP_EnergyMode_t;\r
+\r
+/** Callback function pointer type. */\r
+typedef void (*SLEEP_CbFuncPtr_t)(SLEEP_EnergyMode_t);\r
+\r
+\r
+/*******************************************************************************\r
+ ****************************** PROTOTYPES *********************************\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Initialize the Sleep module.\r
+ *\r
+ * @details\r
+ * Use this function to initialize the Sleep module, should be called\r
+ * only once! Pointers to sleep and wake-up callback functions shall be\r
+ * provided when calling this function.\r
+ * If SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to true, this function checks\r
+ * for the cause of the reset that implicitly called it and calls the wakeup\r
+ * callback if the reset was a wakeup from EM4 (does not work on Gecko MCU).\r
+ *\r
+ * @param[in] pSleepCb\r
+ * Pointer to the callback function that is being called before the device is\r
+ * going to sleep.\r
+ *\r
+ * @param[in] pWakeUpCb\r
+ * Pointer to the callback function that is being called after wake up.\r
+ ******************************************************************************/\r
+void SLEEP_Init(SLEEP_CbFuncPtr_t pSleepCb, SLEEP_CbFuncPtr_t pWakeUpCb);\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Gets the lowest energy mode that the system is allowed to be set to.\r
+ *\r
+ * @details\r
+ * This function uses the low energy mode block counters to determine the\r
+ * lowest possible that the system is allowed to be set to.\r
+ *\r
+ * @return\r
+ * Lowest energy mode that the system can be set to. Possible values:\r
+ * @li sleepEM0\r
+ * @li sleepEM1\r
+ * @li sleepEM2\r
+ * @li sleepEM3\r
+ ******************************************************************************/\r
+SLEEP_EnergyMode_t SLEEP_LowestEnergyModeGet(void);\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Sets the system to sleep into the lowest possible energy mode.\r
+ *\r
+ * @details\r
+ * This function takes care of the system states protected by the sleep block\r
+ * provided by SLEEP_SleepBlockBegin() / SLEEP_SleepBlockEnd(). It allows\r
+ * the system to go into the lowest possible energy mode that the device can\r
+ * be set into at the time of the call of this function.\r
+ * This function will not go lower than EM3 because leaving EM4 requires\r
+ * resetting MCU. To enter into EM4 call SLEEP_ForceSleepInEM4().\r
+ *\r
+ * @return\r
+ * Energy Mode that was entered. Possible values:\r
+ * @li sleepEM0\r
+ * @li sleepEM1\r
+ * @li sleepEM2\r
+ * @li sleepEM3\r
+ ******************************************************************************/\r
+SLEEP_EnergyMode_t SLEEP_Sleep(void);\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Force the device to go to EM4 without doing any checks.\r
+ *\r
+ * @details\r
+ * This function unblocks the low energy sleep block then goes to EM4.\r
+ *\r
+ * @note\r
+ * Regular RAM is not retained in EM4 and the wake up causes a reset.\r
+ * If the configuration option SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to\r
+ * true, the SLEEP_Init() function checks for the reset cause and calls the\r
+ * EM4 wakeup callback.\r
+ ******************************************************************************/\r
+void SLEEP_ForceSleepInEM4(void);\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Begin sleep block in the requested energy mode.\r
+ *\r
+ * @details\r
+ * Blocking a critical system state from a certain energy mode makes sure that\r
+ * the system is not set to that energy mode while the block is not being\r
+ * released.\r
+ * Every SLEEP_SleepBlockBegin() increases the corresponding counter and\r
+ * every SLEEP_SleepBlockEnd() decreases it.\r
+ *\r
+ * Example:\code\r
+ * SLEEP_SleepBlockBegin(sleepEM2); // do not allow EM2 or higher\r
+ * // do some stuff that requires EM1 at least, like ADC sampling\r
+ * SLEEP_SleepBlockEnd(sleepEM2); // remove restriction for EM2\endcode\r
+ *\r
+ * @note\r
+ * Be aware that there is limit of maximum blocks nesting to 255.\r
+ *\r
+ * @param[in] eMode\r
+ * Energy mode to begin to block. Possible values:\r
+ * @li sleepEM1 - Begin to block the system from being set to EM1 (and EM2..4).\r
+ * @li sleepEM2 - Begin to block the system from being set to EM2 (and EM3/EM4).\r
+ * @li sleepEM3 - Begin to block the system from being set to EM3 (and EM4).\r
+ ******************************************************************************/\r
+void SLEEP_SleepBlockBegin(SLEEP_EnergyMode_t eMode);\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * End sleep block in the requested energy mode.\r
+ *\r
+ * @details\r
+ * Release restriction for entering certain energy mode. Every call of this\r
+ * function reduce blocking counter by 1. Once the counter for specific energy\r
+ * mode is 0 and all counters for lower energy modes are 0 as well, using\r
+ * particular energy mode is allowed.\r
+ * Every SLEEP_SleepBlockBegin() increases the corresponding counter and\r
+ * every SLEEP_SleepBlockEnd() decreases it.\r
+ *\r
+ * Example:\code\r
+ * // at start all energy modes are allowed\r
+ * SLEEP_SleepBlockBegin(sleepEM2); // EM2, EM3, EM4 are blocked\r
+ * SLEEP_SleepBlockBegin(sleepEM1); // EM1, EM2, EM3, EM4 are blocked\r
+ * SLEEP_SleepBlockBegin(sleepEM1); // EM1, EM2, EM3, EM4 are blocked\r
+ * SLEEP_SleepBlockEnd(sleepEM2); // still EM1, EM2, EM3, EM4 are blocked\r
+ * SLEEP_SleepBlockEnd(sleepEM1); // still EM1, EM2, EM3, EM4 are blocked\r
+ * SLEEP_SleepBlockEnd(sleepEM1); // all energy modes are allowed now\endcode\r
+ *\r
+ * @param[in] eMode\r
+ * Energy mode to end to block. Possible values:\r
+ * @li sleepEM1 - End to block the system from being set to EM1 (and EM2..4).\r
+ * @li sleepEM2 - End to block the system from being set to EM2 (and EM3/EM4).\r
+ * @li sleepEM3 - End to block the system from being set to EM3 (and EM4).\r
+ ******************************************************************************/\r
+void SLEEP_SleepBlockEnd(SLEEP_EnergyMode_t eMode);\r
+\r
+\r
+/** @} (end addtogroup SLEEP) */\r
+/** @} (end addtogroup EM_Drivers) */\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+#endif /* __SLEEP_H */\r
--- /dev/null
+/***************************************************************************//**\r
+ * @file sleep.c\r
+ * @brief Energy Modes management driver.\r
+ * @version 4.2.1\r
+ * @details\r
+ * This is a energy modes management module consisting of sleep.c and sleep.h\r
+ * source files. The main purpose of the module is to ease energy\r
+ * optimization with a simple API. The module allows the system to always sleep\r
+ * in the lowest possible energy mode. Users could set up callbacks that are\r
+ * being called before and after each and every sleep. A counting semaphore is\r
+ * available for each low energy mode (EM1/EM2/EM3) to protect certain system\r
+ * states from being corrupted. This semaphore has limit set to maximum 255 locks.\r
+ *\r
+ * The module provides the following public API to the users:\r
+ * SLEEP_Init()\r
+ * SLEEP_Sleep()\r
+ * SLEEP_SleepBlockBegin()\r
+ * SLEEP_SleepBlockEnd()\r
+ * SLEEP_ForceSleepInEM4()\r
+ *\r
+ *******************************************************************************\r
+ * @section License\r
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>\r
+ *******************************************************************************\r
+ *\r
+ * This file is licensed under the Silabs License Agreement. See the file\r
+ * "Silabs_License_Agreement.txt" for details. Before using this software for\r
+ * any purpose, you must agree to the terms of that agreement.\r
+ *\r
+ ******************************************************************************/\r
+\r
+\r
+/* Chip specific header file(s). */\r
+#include "em_device.h"\r
+#include "em_assert.h"\r
+#include "em_int.h"\r
+#include "em_rmu.h"\r
+#include "em_emu.h"\r
+\r
+/* Module header file(s). */\r
+#include "sleep.h"\r
+\r
+/* stdlib is needed for NULL definition */\r
+#include <stdlib.h>\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup EM_Drivers\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup SLEEP\r
+ * @brief Energy Modes management driver.\r
+ * @details\r
+ * This is a energy modes management module consisting of sleep.c and sleep.h\r
+ * source files. The main purpose of the module is to ease energy\r
+ * optimization with a simple API. The module allows the system to always sleep\r
+ * in the lowest possible energy mode. Users could set up callbacks that are\r
+ * being called before and after each and every sleep. A counting semaphore is\r
+ * available for each low energy mode (EM1/EM2/EM3) to protect certain system\r
+ * states from being corrupted. This semaphore has limit set to maximum 255 locks.\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/*******************************************************************************\r
+ ******************************* MACROS ************************************\r
+ ******************************************************************************/\r
+\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+\r
+/* Number of low energy modes (EM1, EM2, EM3). Note: EM4 sleep/wakeup is handled\r
+ * differently therefore it is not part of the list! */\r
+#define SLEEP_NUMOF_LOW_ENERGY_MODES 3U\r
+\r
+\r
+\r
+/*******************************************************************************\r
+ ****************************** TYPEDEFS ***********************************\r
+ ******************************************************************************/\r
+\r
+\r
+/*******************************************************************************\r
+ ****************************** CONSTANTS **********************************\r
+ ******************************************************************************/\r
+\r
+\r
+/*******************************************************************************\r
+ ******************************* STATICS ***********************************\r
+ ******************************************************************************/\r
+\r
+/* Callback functions to call before and after sleep. */\r
+static SLEEP_CbFuncPtr_t sleepCallback = NULL;\r
+static SLEEP_CbFuncPtr_t wakeUpCallback = NULL;\r
+\r
+/* Sleep block counter array representing the nested sleep blocks for the low\r
+ * energy modes (EM1/EM2/EM3). Array index 0 corresponds to EM1, 1 to EM2 and 2\r
+ * to EM3 accordingly.\r
+ *\r
+ * Note:\r
+ * - EM4 sleep/wakeup is handled differently therefore it is not part of the\r
+ * list!\r
+ * - Max. number of sleep block nesting is 255. */\r
+static uint8_t sleepBlockCnt[SLEEP_NUMOF_LOW_ENERGY_MODES];\r
+\r
+/*******************************************************************************\r
+ ****************************** PROTOTYPES *********************************\r
+ ******************************************************************************/\r
+\r
+static void SLEEP_EnterEMx(SLEEP_EnergyMode_t eMode);\r
+//static SLEEP_EnergyMode_t SLEEP_LowestEnergyModeGet(void);\r
+\r
+/** @endcond */\r
+\r
+/*******************************************************************************\r
+ *************************** GLOBAL FUNCTIONS ******************************\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Initialize the Sleep module.\r
+ *\r
+ * @details\r
+ * Use this function to initialize the Sleep module, should be called\r
+ * only once! Pointers to sleep and wake-up callback functions shall be\r
+ * provided when calling this function.\r
+ * If SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to true, this function checks\r
+ * for the cause of the reset that implicitly called it and calls the wakeup\r
+ * callback if the reset was a wakeup from EM4 (does not work on Gecko MCU).\r
+ *\r
+ * @param[in] pSleepCb\r
+ * Pointer to the callback function that is being called before the device is\r
+ * going to sleep.\r
+ *\r
+ * @param[in] pWakeUpCb\r
+ * Pointer to the callback function that is being called after wake up.\r
+ ******************************************************************************/\r
+void SLEEP_Init(SLEEP_CbFuncPtr_t pSleepCb, SLEEP_CbFuncPtr_t pWakeUpCb)\r
+{\r
+ /* Initialize callback functions. */\r
+ sleepCallback = pSleepCb;\r
+ wakeUpCallback = pWakeUpCb;\r
+\r
+ /* Reset sleep block counters. Note: not using for() saves code! */\r
+ sleepBlockCnt[0U] = 0U;\r
+ sleepBlockCnt[1U] = 0U;\r
+ sleepBlockCnt[2U] = 0U;\r
+\r
+#if (SLEEP_EM4_WAKEUP_CALLBACK_ENABLED == true) && defined(RMU_RSTCAUSE_EM4WURST)\r
+ /* Check if the Init() happened after an EM4 reset. */\r
+ if (RMU_ResetCauseGet() & RMU_RSTCAUSE_EM4WURST)\r
+ {\r
+ /* Clear the cause of the reset. */\r
+ RMU_ResetCauseClear();\r
+ /* Call wakeup callback with EM4 parameter. */\r
+ if (NULL != wakeUpCallback)\r
+ {\r
+ wakeUpCallback(sleepEM4);\r
+ }\r
+ }\r
+#endif\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Sets the system to sleep into the lowest possible energy mode.\r
+ *\r
+ * @details\r
+ * This function takes care of the system states protected by the sleep block\r
+ * provided by SLEEP_SleepBlockBegin() / SLEEP_SleepBlockEnd(). It allows\r
+ * the system to go into the lowest possible energy mode that the device can\r
+ * be set into at the time of the call of this function.\r
+ * This function will not go lower than EM3 because leaving EM4 requires\r
+ * resetting MCU. To enter into EM4 call SLEEP_ForceSleepInEM4().\r
+ *\r
+ * @return\r
+ * Energy Mode that was entered. Possible values:\r
+ * @li sleepEM0\r
+ * @li sleepEM1\r
+ * @li sleepEM2\r
+ * @li sleepEM3\r
+ ******************************************************************************/\r
+SLEEP_EnergyMode_t SLEEP_Sleep(void)\r
+{\r
+ SLEEP_EnergyMode_t allowedEM;\r
+\r
+ INT_Disable();\r
+\r
+ allowedEM = SLEEP_LowestEnergyModeGet();\r
+\r
+ if ((allowedEM >= sleepEM1) && (allowedEM <= sleepEM3))\r
+ {\r
+ SLEEP_EnterEMx(allowedEM);\r
+ }\r
+ else\r
+ {\r
+ allowedEM = sleepEM0;\r
+ }\r
+\r
+ INT_Enable();\r
+\r
+ return(allowedEM);\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Force the device to go to EM4 without doing any checks.\r
+ *\r
+ * @details\r
+ * This function unblocks the low energy sleep block then goes to EM4.\r
+ *\r
+ * @note\r
+ * Regular RAM is not retained in EM4 and the wake up causes a reset.\r
+ * If the configuration option SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to\r
+ * true, the SLEEP_Init() function checks for the reset cause and calls the\r
+ * EM4 wakeup callback.\r
+ ******************************************************************************/\r
+void SLEEP_ForceSleepInEM4(void)\r
+{\r
+#if (SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED == true)\r
+ /* Unblock the EM2/EM3/EM4 block in the EMU. */\r
+ EMU_EM2UnBlock();\r
+#endif\r
+\r
+ /* Request entering to EM4. */\r
+ SLEEP_EnterEMx(sleepEM4);\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Begin sleep block in the requested energy mode.\r
+ *\r
+ * @details\r
+ * Blocking a critical system state from a certain energy mode makes sure that\r
+ * the system is not set to that energy mode while the block is not being\r
+ * released.\r
+ * Every SLEEP_SleepBlockBegin() increases the corresponding counter and\r
+ * every SLEEP_SleepBlockEnd() decreases it.\r
+ *\r
+ * Example:\code\r
+ * SLEEP_SleepBlockBegin(sleepEM2); // do not allow EM2 or higher\r
+ * // do some stuff that requires EM1 at least, like ADC sampling\r
+ * SLEEP_SleepBlockEnd(sleepEM2); // remove restriction for EM2\endcode\r
+ *\r
+ * @note\r
+ * Be aware that there is limit of maximum blocks nesting to 255.\r
+ *\r
+ * @param[in] eMode\r
+ * Energy mode to begin to block. Possible values:\r
+ * @li sleepEM1 - Begin to block the system from being set to EM1 (and EM2..4).\r
+ * @li sleepEM2 - Begin to block the system from being set to EM2 (and EM3/EM4).\r
+ * @li sleepEM3 - Begin to block the system from being set to EM3 (and EM4).\r
+ ******************************************************************************/\r
+void SLEEP_SleepBlockBegin(SLEEP_EnergyMode_t eMode)\r
+{\r
+ EFM_ASSERT((eMode >= sleepEM1) && (eMode < sleepEM4));\r
+ EFM_ASSERT((sleepBlockCnt[(uint8_t) eMode - 1U]) < 255U);\r
+\r
+ /* Increase the sleep block counter of the selected energy mode. */\r
+ sleepBlockCnt[(uint8_t) eMode - 1U]++;\r
+\r
+#if (SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED == true)\r
+ /* Block EM2/EM3 sleep if the EM2 block begins. */\r
+ if (eMode == sleepEM2)\r
+ {\r
+ EMU_EM2Block();\r
+ }\r
+#endif\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * End sleep block in the requested energy mode.\r
+ *\r
+ * @details\r
+ * Release restriction for entering certain energy mode. Every call of this\r
+ * function reduce blocking counter by 1. Once the counter for specific energy\r
+ * mode is 0 and all counters for lower energy modes are 0 as well, using\r
+ * particular energy mode is allowed.\r
+ * Every SLEEP_SleepBlockBegin() increases the corresponding counter and\r
+ * every SLEEP_SleepBlockEnd() decreases it.\r
+ *\r
+ * Example:\code\r
+ * // at start all energy modes are allowed\r
+ * SLEEP_SleepBlockBegin(sleepEM2); // EM2, EM3, EM4 are blocked\r
+ * SLEEP_SleepBlockBegin(sleepEM1); // EM1, EM2, EM3, EM4 are blocked\r
+ * SLEEP_SleepBlockBegin(sleepEM1); // EM1, EM2, EM3, EM4 are blocked\r
+ * SLEEP_SleepBlockEnd(sleepEM2); // still EM1, EM2, EM3, EM4 are blocked\r
+ * SLEEP_SleepBlockEnd(sleepEM1); // still EM1, EM2, EM3, EM4 are blocked\r
+ * SLEEP_SleepBlockEnd(sleepEM1); // all energy modes are allowed now\endcode\r
+ *\r
+ * @param[in] eMode\r
+ * Energy mode to end to block. Possible values:\r
+ * @li sleepEM1 - End to block the system from being set to EM1 (and EM2..4).\r
+ * @li sleepEM2 - End to block the system from being set to EM2 (and EM3/EM4).\r
+ * @li sleepEM3 - End to block the system from being set to EM3 (and EM4).\r
+ ******************************************************************************/\r
+void SLEEP_SleepBlockEnd(SLEEP_EnergyMode_t eMode)\r
+{\r
+ EFM_ASSERT((eMode >= sleepEM1) && (eMode < sleepEM4));\r
+\r
+ /* Decrease the sleep block counter of the selected energy mode. */\r
+ if (sleepBlockCnt[(uint8_t) eMode - 1U] > 0U)\r
+ {\r
+ sleepBlockCnt[(uint8_t) eMode - 1U]--;\r
+ }\r
+\r
+#if (SLEEP_HW_LOW_ENERGY_BLOCK_ENABLED == true)\r
+ /* Check if the EM2/EM3 block should be unblocked in the EMU. */\r
+ if (0U == sleepBlockCnt[(uint8_t) sleepEM2 - 1U])\r
+ {\r
+ EMU_EM2UnBlock();\r
+ }\r
+#endif\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Gets the lowest energy mode that the system is allowed to be set to.\r
+ *\r
+ * @details\r
+ * This function uses the low energy mode block counters to determine the\r
+ * lowest possible that the system is allowed to be set to.\r
+ *\r
+ * @return\r
+ * Lowest energy mode that the system can be set to. Possible values:\r
+ * @li sleepEM0\r
+ * @li sleepEM1\r
+ * @li sleepEM2\r
+ * @li sleepEM3\r
+ ******************************************************************************/\r
+SLEEP_EnergyMode_t SLEEP_LowestEnergyModeGet(void)\r
+{\r
+ SLEEP_EnergyMode_t tmpLowestEM = sleepEM0;\r
+\r
+ /* Check which is the lowest energy mode that the system can be set to. */\r
+ if (0U == sleepBlockCnt[(uint8_t) sleepEM1 - 1U])\r
+ {\r
+ tmpLowestEM = sleepEM1;\r
+ if (0U == sleepBlockCnt[(uint8_t) sleepEM2 - 1U])\r
+ {\r
+ tmpLowestEM = sleepEM2;\r
+ if (0U == sleepBlockCnt[(uint8_t) sleepEM3 - 1U])\r
+ {\r
+ tmpLowestEM = sleepEM3;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Compare with the default lowest energy mode setting. */\r
+ if (SLEEP_LOWEST_ENERGY_MODE_DEFAULT < tmpLowestEM)\r
+ {\r
+ tmpLowestEM = SLEEP_LOWEST_ENERGY_MODE_DEFAULT;\r
+ }\r
+\r
+ return tmpLowestEM;\r
+}\r
+\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Call the callbacks and enter the requested energy mode.\r
+ *\r
+ * @details\r
+ * This function is not part of the API, therefore it shall not be called by\r
+ * the user directly as it doesn not have any checks if the system is ready\r
+ * for sleep!\r
+ *\r
+ * @note\r
+ * The EM4 wakeup callback is not being called from this function because\r
+ * waking up from EM4 causes a reset.\r
+ * If SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to true, SLEEP_Init() function\r
+ * checks for the cause of the reset and calls the wakeup callback if the\r
+ * reset was a wakeup from EM4.\r
+ ******************************************************************************/\r
+static void SLEEP_EnterEMx(SLEEP_EnergyMode_t eMode)\r
+{\r
+ EFM_ASSERT((eMode > sleepEM0) && (eMode <= sleepEM4));\r
+\r
+ /* Call sleepCallback() before going to sleep. */\r
+ if (NULL != sleepCallback)\r
+ {\r
+ /* Call the callback before going to sleep. */\r
+ sleepCallback(eMode);\r
+ }\r
+\r
+ /* Enter the requested energy mode. */\r
+ switch (eMode)\r
+ {\r
+ case sleepEM1:\r
+ {\r
+ EMU_EnterEM1();\r
+ } break;\r
+\r
+ case sleepEM2:\r
+ {\r
+ EMU_EnterEM2(true);\r
+ } break;\r
+\r
+ case sleepEM3:\r
+ {\r
+ EMU_EnterEM3(true);\r
+ } break;\r
+\r
+ case sleepEM4:\r
+ {\r
+ EMU_EnterEM4();\r
+ } break;\r
+\r
+ default:\r
+ {\r
+ /* Don't do anything, stay in EM0. */\r
+ } break;\r
+ }\r
+\r
+ /* Call the callback after waking up from sleep. */\r
+ if (NULL != wakeUpCallback)\r
+ {\r
+ wakeUpCallback(eMode);\r
+ }\r
+}\r
+/** @endcond */\r
+\r
+/** @} (end addtogroup SLEEP */\r
+/** @} (end addtogroup EM_Drivers) */\r
--- /dev/null
+/***************************************************************************//**\r
+ * @file em_assert.c\r
+ * @brief Assert API\r
+ * @version 4.2.1\r
+ *******************************************************************************\r
+ * @section License\r
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>\r
+ *******************************************************************************\r
+ *\r
+ * Permission is granted to anyone to use this software for any purpose,\r
+ * including commercial applications, and to alter it and redistribute it\r
+ * freely, subject to the following restrictions:\r
+ *\r
+ * 1. The origin of this software must not be misrepresented; you must not\r
+ * claim that you wrote the original software.\r
+ * 2. Altered source versions must be plainly marked as such, and must not be\r
+ * misrepresented as being the original software.\r
+ * 3. This notice may not be removed or altered from any source distribution.\r
+ *\r
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
+ * obligation to support this Software. Silicon Labs is providing the\r
+ * Software "AS IS", with no express or implied warranties of any kind,\r
+ * including, but not limited to, any implied warranties of merchantability\r
+ * or fitness for any particular purpose or warranties against infringement\r
+ * of any proprietary rights of a third party.\r
+ *\r
+ * Silicon Labs will not be liable for any consequential, incidental, or\r
+ * special damages, or any other relief, or for any claim by any third party,\r
+ * arising from your use of this Software.\r
+ *\r
+ ******************************************************************************/\r
+\r
+\r
+#include "em_assert.h"\r
+\r
+#if defined(DEBUG_EFM)\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * EFM internal assert handling.\r
+ *\r
+ * This function is invoked through EFM_ASSERT() macro usage only, it should\r
+ * not be used explicitly.\r
+ *\r
+ * Currently this implementation only enters an indefinite loop, allowing\r
+ * the use of a debugger to determine cause of failure. By defining\r
+ * DEBUG_EFM_USER to the preprocessor for all files, a user defined version\r
+ * of this function must be defined and will be invoked instead, possibly\r
+ * providing output of assertion location.\r
+ *\r
+ * Please notice that this function is not used unless DEBUG_EFM is defined\r
+ * during preprocessing of EFM_ASSERT() usage.\r
+ *\r
+ * @par file\r
+ * Name of source file where assertion failed.\r
+ *\r
+ * @par line\r
+ * Line number in source file where assertion failed.\r
+ ******************************************************************************/\r
+void assertEFM(const char *file, int line)\r
+{\r
+ (void)file; /* Unused parameter */\r
+ (void)line; /* Unused parameter */\r
+\r
+ while (1)\r
+ ;\r
+}\r
+\r
+#endif /* DEBUG_EFM */\r
--- /dev/null
+/***************************************************************************//**\r
+ * @file em_cmu.c\r
+ * @brief Clock management unit (CMU) Peripheral API\r
+ * @version 4.2.1\r
+ *******************************************************************************\r
+ * @section License\r
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>\r
+ *******************************************************************************\r
+ *\r
+ * Permission is granted to anyone to use this software for any purpose,\r
+ * including commercial applications, and to alter it and redistribute it\r
+ * freely, subject to the following restrictions:\r
+ *\r
+ * 1. The origin of this software must not be misrepresented; you must not\r
+ * claim that you wrote the original software.\r
+ * 2. Altered source versions must be plainly marked as such, and must not be\r
+ * misrepresented as being the original software.\r
+ * 3. This notice may not be removed or altered from any source distribution.\r
+ *\r
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
+ * obligation to support this Software. Silicon Labs is providing the\r
+ * Software "AS IS", with no express or implied warranties of any kind,\r
+ * including, but not limited to, any implied warranties of merchantability\r
+ * or fitness for any particular purpose or warranties against infringement\r
+ * of any proprietary rights of a third party.\r
+ *\r
+ * Silicon Labs will not be liable for any consequential, incidental, or\r
+ * special damages, or any other relief, or for any claim by any third party,\r
+ * arising from your use of this Software.\r
+ *\r
+ ******************************************************************************/\r
+#include "em_cmu.h"\r
+#if defined( CMU_PRESENT )\r
+\r
+#include <stddef.h>\r
+#include <limits.h>\r
+#include "em_assert.h"\r
+#include "em_bus.h"\r
+#include "em_emu.h"\r
+#include "em_system.h"\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup EM_Library\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup CMU\r
+ * @brief Clock management unit (CMU) Peripheral API\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/*******************************************************************************\r
+ ****************************** DEFINES ************************************\r
+ ******************************************************************************/\r
+\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+/** Maximum allowed core frequency when using 0 wait-states on flash access. */\r
+#define CMU_MAX_FREQ_0WS 26000000\r
+/** Maximum allowed core frequency when using 1 wait-states on flash access */\r
+#define CMU_MAX_FREQ_1WS 40000000\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+/** Maximum allowed core frequency when using 0 wait-states on flash access. */\r
+#define CMU_MAX_FREQ_0WS 16000000\r
+/** Maximum allowed core frequency when using 1 wait-states on flash access */\r
+#define CMU_MAX_FREQ_1WS 32000000\r
+#else\r
+#error "Unkown MCU platform."\r
+#endif\r
+\r
+#if defined( CMU_CTRL_HFLE )\r
+/** Maximum frequency for HFLE needs to be enabled on Giant, Leopard and\r
+ Wonder. */\r
+#if defined( _EFM32_WONDER_FAMILY ) \\r
+ || defined( _EZR32_LEOPARD_FAMILY ) \\r
+ || defined( _EZR32_WONDER_FAMILY )\r
+#define CMU_MAX_FREQ_HFLE() 24000000\r
+#elif defined ( _EFM32_GIANT_FAMILY )\r
+#define CMU_MAX_FREQ_HFLE() (maxFreqHfle())\r
+#else\r
+#error Invalid part/device.\r
+#endif\r
+#endif\r
+\r
+/*******************************************************************************\r
+ ************************** LOCAL VARIABLES ********************************\r
+ ******************************************************************************/\r
+\r
+#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )\r
+static CMU_AUXHFRCOFreq_TypeDef auxHfrcoFreq = cmuAUXHFRCOFreq_19M0Hz;\r
+#endif\r
+\r
+/** @endcond */\r
+\r
+/*******************************************************************************\r
+ ************************** LOCAL FUNCTIONS ********************************\r
+ ******************************************************************************/\r
+\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the AUX clock frequency. Used by MSC flash programming and LESENSE,\r
+ * by default also as debug clock.\r
+ *\r
+ * @return\r
+ * AUX Frequency in Hz\r
+ ******************************************************************************/\r
+static uint32_t auxClkGet(void)\r
+{\r
+ uint32_t ret;\r
+\r
+#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )\r
+ ret = auxHfrcoFreq;\r
+\r
+#elif defined( _CMU_AUXHFRCOCTRL_BAND_MASK )\r
+ /* All Geckos from TG and newer */\r
+ switch(CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_BAND_MASK)\r
+ {\r
+ case CMU_AUXHFRCOCTRL_BAND_1MHZ:\r
+ ret = 1000000;\r
+ break;\r
+\r
+ case CMU_AUXHFRCOCTRL_BAND_7MHZ:\r
+ ret = 7000000;\r
+ break;\r
+\r
+ case CMU_AUXHFRCOCTRL_BAND_11MHZ:\r
+ ret = 11000000;\r
+ break;\r
+\r
+ case CMU_AUXHFRCOCTRL_BAND_14MHZ:\r
+ ret = 14000000;\r
+ break;\r
+\r
+ case CMU_AUXHFRCOCTRL_BAND_21MHZ:\r
+ ret = 21000000;\r
+ break;\r
+\r
+#if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ )\r
+ case CMU_AUXHFRCOCTRL_BAND_28MHZ:\r
+ ret = 28000000;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = 0;\r
+ break;\r
+ }\r
+\r
+#else\r
+ /* Gecko has a fixed 14Mhz AUXHFRCO clock */\r
+ ret = 14000000;\r
+\r
+#endif\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the Debug Trace clock frequency\r
+ *\r
+ * @return\r
+ * Debug Trace frequency in Hz\r
+ ******************************************************************************/\r
+static uint32_t dbgClkGet(void)\r
+{\r
+ uint32_t ret;\r
+ CMU_Select_TypeDef clk;\r
+\r
+ /* Get selected clock source */\r
+ clk = CMU_ClockSelectGet(cmuClock_DBG);\r
+\r
+ switch(clk)\r
+ {\r
+ case cmuSelect_HFCLK:\r
+ ret = SystemHFClockGet();\r
+#if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
+ /* Family with an additional divider. */\r
+ ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)\r
+ >> _CMU_CTRL_HFCLKDIV_SHIFT));\r
+#endif\r
+ break;\r
+\r
+ case cmuSelect_AUXHFRCO:\r
+ ret = auxClkGet();\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = 0;\r
+ break;\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Configure flash access wait states in order to support given core clock\r
+ * frequency.\r
+ *\r
+ * @param[in] coreFreq\r
+ * Core clock frequency to configure flash wait-states for\r
+ ******************************************************************************/\r
+static void flashWaitStateControl(uint32_t coreFreq)\r
+{\r
+ uint32_t mode;\r
+ bool mscLocked;\r
+#if defined( MSC_READCTRL_MODE_WS0SCBTP )\r
+ bool scbtpEn; /* Suppressed Conditional Branch Target Prefetch setting. */\r
+#endif\r
+\r
+ /* Make sure the MSC is unlocked */\r
+ mscLocked = MSC->LOCK;\r
+ MSC->LOCK = MSC_UNLOCK_CODE;\r
+\r
+ /* Get mode and SCBTP enable */\r
+ mode = MSC->READCTRL & _MSC_READCTRL_MODE_MASK;\r
+#if defined( MSC_READCTRL_MODE_WS0SCBTP )\r
+ switch(mode)\r
+ {\r
+ case MSC_READCTRL_MODE_WS0:\r
+ case MSC_READCTRL_MODE_WS1:\r
+#if defined( MSC_READCTRL_MODE_WS2 )\r
+ case MSC_READCTRL_MODE_WS2:\r
+#endif\r
+ scbtpEn = false;\r
+ break;\r
+\r
+ default: /* WSxSCBTP */\r
+ scbtpEn = true;\r
+ break;\r
+ }\r
+#endif\r
+\r
+\r
+ /* Set mode based on the core clock frequency and SCBTP enable */\r
+#if defined( MSC_READCTRL_MODE_WS0SCBTP )\r
+ if (false)\r
+ {\r
+ }\r
+#if defined( MSC_READCTRL_MODE_WS2 )\r
+ else if (coreFreq > CMU_MAX_FREQ_1WS)\r
+ {\r
+ mode = (scbtpEn ? MSC_READCTRL_MODE_WS2SCBTP : MSC_READCTRL_MODE_WS2);\r
+ }\r
+#endif\r
+ else if ((coreFreq <= CMU_MAX_FREQ_1WS) && (coreFreq > CMU_MAX_FREQ_0WS))\r
+ {\r
+ mode = (scbtpEn ? MSC_READCTRL_MODE_WS1SCBTP : MSC_READCTRL_MODE_WS1);\r
+ }\r
+ else\r
+ {\r
+ mode = (scbtpEn ? MSC_READCTRL_MODE_WS0SCBTP : MSC_READCTRL_MODE_WS0);\r
+ }\r
+\r
+#else /* If MODE and SCBTP is in separate register fields */\r
+\r
+ if (false)\r
+ {\r
+ }\r
+#if defined( MSC_READCTRL_MODE_WS2 )\r
+ else if (coreFreq > CMU_MAX_FREQ_1WS)\r
+ {\r
+ mode = MSC_READCTRL_MODE_WS2;\r
+ }\r
+#endif\r
+ else if ((coreFreq <= CMU_MAX_FREQ_1WS) && (coreFreq > CMU_MAX_FREQ_0WS))\r
+ {\r
+ mode = MSC_READCTRL_MODE_WS1;\r
+ }\r
+ else\r
+ {\r
+ mode = MSC_READCTRL_MODE_WS0;\r
+ }\r
+#endif\r
+\r
+ /* BUS_RegMaskedWrite cannot be used here as it would temporarely set the\r
+ mode field to WS0 */\r
+ MSC->READCTRL = (MSC->READCTRL &~_MSC_READCTRL_MODE_MASK) | mode;\r
+\r
+ if (mscLocked)\r
+ {\r
+ MSC->LOCK = 0;\r
+ }\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Configure flash access wait states to most conservative setting for\r
+ * this target. Retain SCBTP (Suppressed Conditional Branch Target Prefetch)\r
+ * setting.\r
+ ******************************************************************************/\r
+static void flashWaitStateMax(void)\r
+{\r
+ flashWaitStateControl(SystemMaxCoreClockGet());\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the LFnCLK frequency based on current configuration.\r
+ *\r
+ * @param[in] lfClkBranch\r
+ * Selected LF branch\r
+ *\r
+ * @return\r
+ * The LFnCLK frequency in Hz. If no LFnCLK is selected (disabled), 0 is\r
+ * returned.\r
+ ******************************************************************************/\r
+static uint32_t lfClkGet(CMU_Clock_TypeDef lfClkBranch)\r
+{\r
+ uint32_t sel;\r
+ uint32_t ret = 0;\r
+\r
+ switch (lfClkBranch)\r
+ {\r
+ case cmuClock_LFA:\r
+ case cmuClock_LFB:\r
+#if defined( _CMU_LFCCLKEN0_MASK )\r
+ case cmuClock_LFC:\r
+#endif\r
+#if defined( _CMU_LFECLKSEL_MASK )\r
+ case cmuClock_LFE:\r
+#endif\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+\r
+ sel = CMU_ClockSelectGet(lfClkBranch);\r
+\r
+ /* Get clock select field */\r
+ switch (lfClkBranch)\r
+ {\r
+ case cmuClock_LFA:\r
+#if defined( _CMU_LFCLKSEL_MASK )\r
+ sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK) >> _CMU_LFCLKSEL_LFA_SHIFT;\r
+#elif defined( _CMU_LFACLKSEL_MASK )\r
+ sel = (CMU->LFACLKSEL & _CMU_LFACLKSEL_LFA_MASK) >> _CMU_LFACLKSEL_LFA_SHIFT;\r
+#else\r
+ EFM_ASSERT(0);\r
+#endif\r
+ break;\r
+\r
+ case cmuClock_LFB:\r
+#if defined( _CMU_LFCLKSEL_MASK )\r
+ sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK) >> _CMU_LFCLKSEL_LFB_SHIFT;\r
+#elif defined( _CMU_LFBCLKSEL_MASK )\r
+ sel = (CMU->LFBCLKSEL & _CMU_LFBCLKSEL_LFB_MASK) >> _CMU_LFBCLKSEL_LFB_SHIFT;\r
+#else\r
+ EFM_ASSERT(0);\r
+#endif\r
+ break;\r
+\r
+#if defined( _CMU_LFCCLKEN0_MASK )\r
+ case cmuClock_LFC:\r
+ sel = (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK) >> _CMU_LFCLKSEL_LFC_SHIFT;\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_LFECLKSEL_MASK )\r
+ case cmuClock_LFE:\r
+ sel = (CMU->LFECLKSEL & _CMU_LFECLKSEL_LFE_MASK) >> _CMU_LFECLKSEL_LFE_SHIFT;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+\r
+ /* Get clock frequency */\r
+#if defined( _CMU_LFCLKSEL_MASK )\r
+ switch (sel)\r
+ {\r
+ case _CMU_LFCLKSEL_LFA_LFRCO:\r
+ ret = SystemLFRCOClockGet();\r
+ break;\r
+\r
+ case _CMU_LFCLKSEL_LFA_LFXO:\r
+ ret = SystemLFXOClockGet();\r
+ break;\r
+\r
+#if defined( _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2 )\r
+ case _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:\r
+#if defined( CMU_CTRL_HFLE )\r
+ /* Family which can use an extra div 4 divider */\r
+ /* (and must if >32MHz) or HFLE is set. */\r
+ if(((CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKLEDIV_MASK)\r
+ == CMU_HFCORECLKDIV_HFCORECLKLEDIV_DIV4)\r
+ || (CMU->CTRL & CMU_CTRL_HFLE))\r
+ {\r
+ ret = SystemCoreClockGet() / 4U;\r
+ }\r
+ else\r
+ {\r
+ ret = SystemCoreClockGet() / 2U;\r
+ }\r
+#else\r
+ ret = SystemCoreClockGet() / 2U;\r
+#endif\r
+ break;\r
+#endif\r
+\r
+ case _CMU_LFCLKSEL_LFA_DISABLED:\r
+ ret = 0;\r
+#if defined( CMU_LFCLKSEL_LFAE )\r
+ /* Check LF Extended bit setting for LFA or LFB ULFRCO clock */\r
+ if ((lfClkBranch == cmuClock_LFA) || (lfClkBranch == cmuClock_LFB))\r
+ {\r
+ if (CMU->LFCLKSEL >> (lfClkBranch == cmuClock_LFA\r
+ ? _CMU_LFCLKSEL_LFAE_SHIFT\r
+ : _CMU_LFCLKSEL_LFBE_SHIFT))\r
+ {\r
+ ret = SystemULFRCOClockGet();\r
+ }\r
+ }\r
+#endif\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = 0U;\r
+ break;\r
+ }\r
+#endif /* _CMU_LFCLKSEL_MASK */\r
+\r
+#if defined( _CMU_LFACLKSEL_MASK )\r
+ switch (sel)\r
+ {\r
+ case _CMU_LFACLKSEL_LFA_LFRCO:\r
+ ret = SystemLFRCOClockGet();\r
+ break;\r
+\r
+ case _CMU_LFACLKSEL_LFA_LFXO:\r
+ ret = SystemLFXOClockGet();\r
+ break;\r
+\r
+ case _CMU_LFACLKSEL_LFA_ULFRCO:\r
+ ret = SystemULFRCOClockGet();\r
+ break;\r
+\r
+#if defined( _CMU_LFACLKSEL_LFA_HFCLKLE )\r
+ case _CMU_LFACLKSEL_LFA_HFCLKLE:\r
+ ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK)\r
+ == CMU_HFPRESC_HFCLKLEPRESC_DIV4)\r
+ ? SystemCoreClockGet() / 4U\r
+ : SystemCoreClockGet() / 2U;\r
+ break;\r
+#elif defined( _CMU_LFBCLKSEL_LFB_HFCLKLE )\r
+ case _CMU_LFBCLKSEL_LFB_HFCLKLE:\r
+ ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK)\r
+ == CMU_HFPRESC_HFCLKLEPRESC_DIV4)\r
+ ? SystemCoreClockGet() / 4U\r
+ : SystemCoreClockGet() / 2U;\r
+ break;\r
+#endif\r
+\r
+ case _CMU_LFACLKSEL_LFA_DISABLED:\r
+ ret = 0;\r
+ break;\r
+ }\r
+#endif\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+#if defined( CMU_CTRL_HFLE ) \\r
+ && !defined( _EFM32_WONDER_FAMILY ) \\r
+ && !defined( _EZR32_LEOPARD_FAMILY ) \\r
+ && !defined( _EZR32_WONDER_FAMILY )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Return max allowed frequency for low energy peripherals.\r
+ ******************************************************************************/\r
+static uint32_t maxFreqHfle(void)\r
+{\r
+ uint16_t majorMinorRev;\r
+\r
+ switch (SYSTEM_GetFamily())\r
+ {\r
+ case systemPartFamilyEfm32Leopard:\r
+ /* CHIP MAJOR bit [5:0] */\r
+ majorMinorRev = (((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK)\r
+ >> _ROMTABLE_PID0_REVMAJOR_SHIFT) << 8);\r
+ /* CHIP MINOR bit [7:4] */\r
+ majorMinorRev |= (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK)\r
+ >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);\r
+ /* CHIP MINOR bit [3:0] */\r
+ majorMinorRev |= ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK)\r
+ >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);\r
+\r
+ if (majorMinorRev >= 0x0204)\r
+ return 24000000;\r
+ else\r
+ return 32000000;\r
+\r
+ case systemPartFamilyEfm32Giant:\r
+ return 32000000;\r
+\r
+ default:\r
+ /* Invalid device family. */\r
+ EFM_ASSERT(false);\r
+ return 0;\r
+ }\r
+}\r
+#endif\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Wait for ongoing sync of register(s) to low frequency domain to complete.\r
+ *\r
+ * @param[in] mask\r
+ * Bitmask corresponding to SYNCBUSY register defined bits, indicating\r
+ * registers that must complete any ongoing synchronization.\r
+ ******************************************************************************/\r
+__STATIC_INLINE void syncReg(uint32_t mask)\r
+{\r
+ /* Avoid deadlock if modifying the same register twice when freeze mode is */\r
+ /* activated. */\r
+ if (CMU->FREEZE & CMU_FREEZE_REGFREEZE)\r
+ return;\r
+\r
+ /* Wait for any pending previous write operation to have been completed */\r
+ /* in low frequency domain */\r
+ while (CMU->SYNCBUSY & mask)\r
+ {\r
+ }\r
+}\r
+\r
+\r
+#if defined(USB_PRESENT)\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the USBC frequency\r
+ *\r
+ * @return\r
+ * USBC frequency in Hz\r
+ ******************************************************************************/\r
+static uint32_t usbCClkGet(void)\r
+{\r
+ uint32_t ret;\r
+ CMU_Select_TypeDef clk;\r
+\r
+ /* Get selected clock source */\r
+ clk = CMU_ClockSelectGet(cmuClock_USBC);\r
+\r
+ switch(clk)\r
+ {\r
+ case cmuSelect_LFXO:\r
+ ret = SystemLFXOClockGet();\r
+ break;\r
+ case cmuSelect_LFRCO:\r
+ ret = SystemLFRCOClockGet();\r
+ break;\r
+ case cmuSelect_HFCLK:\r
+ ret = SystemHFClockGet();\r
+ break;\r
+ default:\r
+ /* Clock is not enabled */\r
+ ret = 0;\r
+ break;\r
+ }\r
+ return ret;\r
+}\r
+#endif\r
+\r
+\r
+/** @endcond */\r
+\r
+/*******************************************************************************\r
+ ************************** GLOBAL FUNCTIONS *******************************\r
+ ******************************************************************************/\r
+\r
+#if defined( _CMU_AUXHFRCOCTRL_BAND_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get AUXHFRCO band in use.\r
+ *\r
+ * @return\r
+ * AUXHFRCO band in use.\r
+ ******************************************************************************/\r
+CMU_AUXHFRCOBand_TypeDef CMU_AUXHFRCOBandGet(void)\r
+{\r
+ return (CMU_AUXHFRCOBand_TypeDef)((CMU->AUXHFRCOCTRL\r
+ & _CMU_AUXHFRCOCTRL_BAND_MASK)\r
+ >> _CMU_AUXHFRCOCTRL_BAND_SHIFT);\r
+}\r
+#endif /* _CMU_AUXHFRCOCTRL_BAND_MASK */\r
+\r
+\r
+#if defined( _CMU_AUXHFRCOCTRL_BAND_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set AUXHFRCO band and the tuning value based on the value in the\r
+ * calibration table made during production.\r
+ *\r
+ * @param[in] band\r
+ * AUXHFRCO band to activate.\r
+ ******************************************************************************/\r
+void CMU_AUXHFRCOBandSet(CMU_AUXHFRCOBand_TypeDef band)\r
+{\r
+ uint32_t tuning;\r
+\r
+ /* Read tuning value from calibration table */\r
+ switch (band)\r
+ {\r
+ case cmuAUXHFRCOBand_1MHz:\r
+ tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND1_MASK)\r
+ >> _DEVINFO_AUXHFRCOCAL0_BAND1_SHIFT;\r
+ break;\r
+\r
+ case cmuAUXHFRCOBand_7MHz:\r
+ tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND7_MASK)\r
+ >> _DEVINFO_AUXHFRCOCAL0_BAND7_SHIFT;\r
+ break;\r
+\r
+ case cmuAUXHFRCOBand_11MHz:\r
+ tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND11_MASK)\r
+ >> _DEVINFO_AUXHFRCOCAL0_BAND11_SHIFT;\r
+ break;\r
+\r
+ case cmuAUXHFRCOBand_14MHz:\r
+ tuning = (DEVINFO->AUXHFRCOCAL0 & _DEVINFO_AUXHFRCOCAL0_BAND14_MASK)\r
+ >> _DEVINFO_AUXHFRCOCAL0_BAND14_SHIFT;\r
+ break;\r
+\r
+ case cmuAUXHFRCOBand_21MHz:\r
+ tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND21_MASK)\r
+ >> _DEVINFO_AUXHFRCOCAL1_BAND21_SHIFT;\r
+ break;\r
+\r
+#if defined( _CMU_AUXHFRCOCTRL_BAND_28MHZ )\r
+ case cmuAUXHFRCOBand_28MHz:\r
+ tuning = (DEVINFO->AUXHFRCOCAL1 & _DEVINFO_AUXHFRCOCAL1_BAND28_MASK)\r
+ >> _DEVINFO_AUXHFRCOCAL1_BAND28_SHIFT;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ return;\r
+ }\r
+\r
+ /* Set band/tuning */\r
+ CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL &\r
+ ~(_CMU_AUXHFRCOCTRL_BAND_MASK\r
+ | _CMU_AUXHFRCOCTRL_TUNING_MASK))\r
+ | (band << _CMU_AUXHFRCOCTRL_BAND_SHIFT)\r
+ | (tuning << _CMU_AUXHFRCOCTRL_TUNING_SHIFT);\r
+\r
+}\r
+#endif /* _CMU_AUXHFRCOCTRL_BAND_MASK */\r
+\r
+\r
+#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Get a pointer to the AUXHFRCO frequency calibration word in DEVINFO\r
+ *\r
+ * @param[in] freq\r
+ * Frequency in Hz\r
+ *\r
+ * @return\r
+ * AUXHFRCO calibration word for a given frequency\r
+ *****************************************************************************/\r
+static uint32_t CMU_AUXHFRCODevinfoGet(CMU_AUXHFRCOFreq_TypeDef freq)\r
+{\r
+ switch (freq)\r
+ {\r
+ /* 1, 2 and 4MHz share the same calibration word */\r
+ case cmuAUXHFRCOFreq_1M0Hz:\r
+ case cmuAUXHFRCOFreq_2M0Hz:\r
+ case cmuAUXHFRCOFreq_4M0Hz:\r
+ return DEVINFO->AUXHFRCOCAL0;\r
+\r
+ case cmuAUXHFRCOFreq_7M0Hz:\r
+ return DEVINFO->AUXHFRCOCAL3;\r
+\r
+ case cmuAUXHFRCOFreq_13M0Hz:\r
+ return DEVINFO->AUXHFRCOCAL6;\r
+\r
+ case cmuAUXHFRCOFreq_16M0Hz:\r
+ return DEVINFO->AUXHFRCOCAL7;\r
+\r
+ case cmuAUXHFRCOFreq_19M0Hz:\r
+ return DEVINFO->AUXHFRCOCAL8;\r
+\r
+ case cmuAUXHFRCOFreq_26M0Hz:\r
+ return DEVINFO->AUXHFRCOCAL10;\r
+\r
+ case cmuAUXHFRCOFreq_32M0Hz:\r
+ return DEVINFO->AUXHFRCOCAL11;\r
+\r
+ case cmuAUXHFRCOFreq_38M0Hz:\r
+ return DEVINFO->AUXHFRCOCAL12;\r
+\r
+ default: /* cmuAUXHFRCOFreq_UserDefined */\r
+ return 0;\r
+ }\r
+}\r
+#endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */\r
+\r
+\r
+#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get AUXHFRCO frequency enumeration in use\r
+ *\r
+ * @return\r
+ * AUXHFRCO frequency enumeration in use\r
+ ******************************************************************************/\r
+CMU_AUXHFRCOFreq_TypeDef CMU_AUXHFRCOFreqGet(void)\r
+{\r
+ return auxHfrcoFreq;\r
+}\r
+#endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */\r
+\r
+\r
+#if defined( _CMU_AUXHFRCOCTRL_FREQRANGE_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set AUXHFRCO calibration for the selected target frequency\r
+ *\r
+ * @param[in] frequency\r
+ * AUXHFRCO frequency to set\r
+ ******************************************************************************/\r
+void CMU_AUXHFRCOFreqSet(CMU_AUXHFRCOFreq_TypeDef freq)\r
+{\r
+ uint32_t freqCal;\r
+\r
+ /* Get DEVINFO index, set global auxHfrcoFreq */\r
+ freqCal = CMU_AUXHFRCODevinfoGet(freq);\r
+ EFM_ASSERT((freqCal != 0) && (freqCal != UINT_MAX));\r
+ auxHfrcoFreq = freq;\r
+\r
+ /* Wait for any previous sync to complete, and then set calibration data\r
+ for the selected frequency. */\r
+ while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_AUXHFRCOBSY_SHIFT));\r
+\r
+ /* Set divider in AUXHFRCOCTRL for 1, 2 and 4MHz */\r
+ switch(freq)\r
+ {\r
+ case cmuAUXHFRCOFreq_1M0Hz:\r
+ freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)\r
+ | CMU_AUXHFRCOCTRL_CLKDIV_DIV4;\r
+ break;\r
+\r
+ case cmuAUXHFRCOFreq_2M0Hz:\r
+ freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)\r
+ | CMU_AUXHFRCOCTRL_CLKDIV_DIV2;\r
+ break;\r
+\r
+ case cmuAUXHFRCOFreq_4M0Hz:\r
+ freqCal = (freqCal & ~_CMU_AUXHFRCOCTRL_CLKDIV_MASK)\r
+ | CMU_AUXHFRCOCTRL_CLKDIV_DIV1;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ CMU->AUXHFRCOCTRL = freqCal;\r
+}\r
+#endif /* _CMU_AUXHFRCOCTRL_FREQRANGE_MASK */\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Calibrate clock.\r
+ *\r
+ * @details\r
+ * Run a calibration for HFCLK against a selectable reference clock. Please\r
+ * refer to the reference manual, CMU chapter, for further details.\r
+ *\r
+ * @note\r
+ * This function will not return until calibration measurement is completed.\r
+ *\r
+ * @param[in] HFCycles\r
+ * The number of HFCLK cycles to run calibration. Increasing this number\r
+ * increases precision, but the calibration will take more time.\r
+ *\r
+ * @param[in] ref\r
+ * The reference clock used to compare HFCLK with.\r
+ *\r
+ * @return\r
+ * The number of ticks the reference clock after HFCycles ticks on the HF\r
+ * clock.\r
+ ******************************************************************************/\r
+uint32_t CMU_Calibrate(uint32_t HFCycles, CMU_Osc_TypeDef ref)\r
+{\r
+ EFM_ASSERT(HFCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));\r
+\r
+ /* Set reference clock source */\r
+ switch (ref)\r
+ {\r
+ case cmuOsc_LFXO:\r
+ CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFXO;\r
+ break;\r
+\r
+ case cmuOsc_LFRCO:\r
+ CMU->CALCTRL = CMU_CALCTRL_UPSEL_LFRCO;\r
+ break;\r
+\r
+ case cmuOsc_HFXO:\r
+ CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFXO;\r
+ break;\r
+\r
+ case cmuOsc_HFRCO:\r
+ CMU->CALCTRL = CMU_CALCTRL_UPSEL_HFRCO;\r
+ break;\r
+\r
+ case cmuOsc_AUXHFRCO:\r
+ CMU->CALCTRL = CMU_CALCTRL_UPSEL_AUXHFRCO;\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ return 0;\r
+ }\r
+\r
+ /* Set top value */\r
+ CMU->CALCNT = HFCycles;\r
+\r
+ /* Start calibration */\r
+ CMU->CMD = CMU_CMD_CALSTART;\r
+\r
+#if defined( CMU_STATUS_CALRDY )\r
+ /* Wait until calibration completes */\r
+ while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALRDY_SHIFT))\r
+ {\r
+ }\r
+#else\r
+ /* Wait until calibration completes */\r
+ while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT))\r
+ {\r
+ }\r
+#endif\r
+\r
+ return CMU->CALCNT;\r
+}\r
+\r
+\r
+#if defined( _CMU_CALCTRL_UPSEL_MASK ) && defined( _CMU_CALCTRL_DOWNSEL_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Configure clock calibration\r
+ *\r
+ * @details\r
+ * Configure a calibration for a selectable clock source against another\r
+ * selectable reference clock.\r
+ * Refer to the reference manual, CMU chapter, for further details.\r
+ *\r
+ * @note\r
+ * After configuration, a call to CMU_CalibrateStart() is required, and\r
+ * the resulting calibration value can be read out with the\r
+ * CMU_CalibrateCountGet() function call.\r
+ *\r
+ * @param[in] downCycles\r
+ * The number of downSel clock cycles to run calibration. Increasing this\r
+ * number increases precision, but the calibration will take more time.\r
+ *\r
+ * @param[in] downSel\r
+ * The clock which will be counted down downCycles\r
+ *\r
+ * @param[in] upSel\r
+ * The reference clock, the number of cycles generated by this clock will\r
+ * be counted and added up, the result can be given with the\r
+ * CMU_CalibrateCountGet() function call.\r
+ ******************************************************************************/\r
+void CMU_CalibrateConfig(uint32_t downCycles, CMU_Osc_TypeDef downSel,\r
+ CMU_Osc_TypeDef upSel)\r
+{\r
+ /* Keep untouched configuration settings */\r
+ uint32_t calCtrl = CMU->CALCTRL\r
+ & ~(_CMU_CALCTRL_UPSEL_MASK | _CMU_CALCTRL_DOWNSEL_MASK);\r
+\r
+ /* 20 bits of precision to calibration count register */\r
+ EFM_ASSERT(downCycles <= (_CMU_CALCNT_CALCNT_MASK >> _CMU_CALCNT_CALCNT_SHIFT));\r
+\r
+ /* Set down counting clock source - down counter */\r
+ switch (downSel)\r
+ {\r
+ case cmuOsc_LFXO:\r
+ calCtrl |= CMU_CALCTRL_DOWNSEL_LFXO;\r
+ break;\r
+\r
+ case cmuOsc_LFRCO:\r
+ calCtrl |= CMU_CALCTRL_DOWNSEL_LFRCO;\r
+ break;\r
+\r
+ case cmuOsc_HFXO:\r
+ calCtrl |= CMU_CALCTRL_DOWNSEL_HFXO;\r
+ break;\r
+\r
+ case cmuOsc_HFRCO:\r
+ calCtrl |= CMU_CALCTRL_DOWNSEL_HFRCO;\r
+ break;\r
+\r
+ case cmuOsc_AUXHFRCO:\r
+ calCtrl |= CMU_CALCTRL_DOWNSEL_AUXHFRCO;\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+\r
+ /* Set top value to be counted down by the downSel clock */\r
+ CMU->CALCNT = downCycles;\r
+\r
+ /* Set reference clock source - up counter */\r
+ switch (upSel)\r
+ {\r
+ case cmuOsc_LFXO:\r
+ calCtrl |= CMU_CALCTRL_UPSEL_LFXO;\r
+ break;\r
+\r
+ case cmuOsc_LFRCO:\r
+ calCtrl |= CMU_CALCTRL_UPSEL_LFRCO;\r
+ break;\r
+\r
+ case cmuOsc_HFXO:\r
+ calCtrl |= CMU_CALCTRL_UPSEL_HFXO;\r
+ break;\r
+\r
+ case cmuOsc_HFRCO:\r
+ calCtrl |= CMU_CALCTRL_UPSEL_HFRCO;\r
+ break;\r
+\r
+ case cmuOsc_AUXHFRCO:\r
+ calCtrl |= CMU_CALCTRL_UPSEL_AUXHFRCO;\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+\r
+ CMU->CALCTRL = calCtrl;\r
+}\r
+#endif\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get calibration count register\r
+ * @note\r
+ * If continuous calibrartion mode is active, calibration busy will almost\r
+ * always be off, and we just need to read the value, where the normal case\r
+ * would be that this function call has been triggered by the CALRDY\r
+ * interrupt flag.\r
+ * @return\r
+ * Calibration count, the number of UPSEL clocks (see CMU_CalibrateConfig)\r
+ * in the period of DOWNSEL oscillator clock cycles configured by a previous\r
+ * write operation to CMU->CALCNT\r
+ ******************************************************************************/\r
+uint32_t CMU_CalibrateCountGet(void)\r
+{\r
+ /* Wait until calibration completes, UNLESS continuous calibration mode is */\r
+ /* active */\r
+#if defined( CMU_CALCTRL_CONT )\r
+ if (!BUS_RegBitRead(&CMU->CALCTRL, _CMU_CALCTRL_CONT_SHIFT))\r
+ {\r
+#if defined( CMU_STATUS_CALRDY )\r
+ /* Wait until calibration completes */\r
+ while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALRDY_SHIFT))\r
+ {\r
+ }\r
+#else\r
+ /* Wait until calibration completes */\r
+ while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT))\r
+ {\r
+ }\r
+#endif\r
+ }\r
+#else\r
+ while (BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_CALBSY_SHIFT))\r
+ {\r
+ }\r
+#endif\r
+ return CMU->CALCNT;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get clock divisor/prescaler.\r
+ *\r
+ * @param[in] clock\r
+ * Clock point to get divisor/prescaler for. Notice that not all clock points\r
+ * have a divisor/prescaler. Please refer to CMU overview in reference manual.\r
+ *\r
+ * @return\r
+ * The current clock point divisor/prescaler. 1 is returned\r
+ * if @p clock specifies a clock point without a divisor/prescaler.\r
+ ******************************************************************************/\r
+CMU_ClkDiv_TypeDef CMU_ClockDivGet(CMU_Clock_TypeDef clock)\r
+{\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ return 1 + (uint32_t)CMU_ClockPrescGet(clock);\r
+\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ uint32_t divReg;\r
+ CMU_ClkDiv_TypeDef ret;\r
+\r
+ /* Get divisor reg id */\r
+ divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;\r
+\r
+ switch (divReg)\r
+ {\r
+#if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
+ case CMU_HFCLKDIV_REG:\r
+ ret = 1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)\r
+ >> _CMU_CTRL_HFCLKDIV_SHIFT);\r
+ break;\r
+#endif\r
+\r
+ case CMU_HFPERCLKDIV_REG:\r
+ ret = (CMU_ClkDiv_TypeDef)((CMU->HFPERCLKDIV\r
+ & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)\r
+ >> _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);\r
+ ret = CMU_Log2ToDiv(ret);\r
+ break;\r
+\r
+ case CMU_HFCORECLKDIV_REG:\r
+ ret = (CMU_ClkDiv_TypeDef)((CMU->HFCORECLKDIV\r
+ & _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK)\r
+ >> _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);\r
+ ret = CMU_Log2ToDiv(ret);\r
+ break;\r
+\r
+ case CMU_LFAPRESC0_REG:\r
+ switch (clock)\r
+ {\r
+ case cmuClock_RTC:\r
+ ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK)\r
+ >> _CMU_LFAPRESC0_RTC_SHIFT);\r
+ ret = CMU_Log2ToDiv(ret);\r
+ break;\r
+\r
+#if defined(_CMU_LFAPRESC0_LETIMER0_MASK)\r
+ case cmuClock_LETIMER0:\r
+ ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)\r
+ >> _CMU_LFAPRESC0_LETIMER0_SHIFT);\r
+ ret = CMU_Log2ToDiv(ret);\r
+ break;\r
+#endif\r
+\r
+#if defined(_CMU_LFAPRESC0_LCD_MASK)\r
+ case cmuClock_LCDpre:\r
+ ret = (CMU_ClkDiv_TypeDef)(((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)\r
+ >> _CMU_LFAPRESC0_LCD_SHIFT)\r
+ + CMU_DivToLog2(cmuClkDiv_16));\r
+ ret = CMU_Log2ToDiv(ret);\r
+ break;\r
+#endif\r
+\r
+#if defined(_CMU_LFAPRESC0_LESENSE_MASK)\r
+ case cmuClock_LESENSE:\r
+ ret = (CMU_ClkDiv_TypeDef)((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK)\r
+ >> _CMU_LFAPRESC0_LESENSE_SHIFT);\r
+ ret = CMU_Log2ToDiv(ret);\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = cmuClkDiv_1;\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case CMU_LFBPRESC0_REG:\r
+ switch (clock)\r
+ {\r
+#if defined(_CMU_LFBPRESC0_LEUART0_MASK)\r
+ case cmuClock_LEUART0:\r
+ ret = (CMU_ClkDiv_TypeDef)((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)\r
+ >> _CMU_LFBPRESC0_LEUART0_SHIFT);\r
+ ret = CMU_Log2ToDiv(ret);\r
+ break;\r
+#endif\r
+\r
+#if defined(_CMU_LFBPRESC0_LEUART1_MASK)\r
+ case cmuClock_LEUART1:\r
+ ret = (CMU_ClkDiv_TypeDef)((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)\r
+ >> _CMU_LFBPRESC0_LEUART1_SHIFT);\r
+ ret = CMU_Log2ToDiv(ret);\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = cmuClkDiv_1;\r
+ break;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = cmuClkDiv_1;\r
+ break;\r
+ }\r
+\r
+ return ret;\r
+#endif\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set clock divisor/prescaler.\r
+ *\r
+ * @note\r
+ * If setting a LF clock prescaler, synchronization into the low frequency\r
+ * domain is required. If the same register is modified before a previous\r
+ * update has completed, this function will stall until the previous\r
+ * synchronization has completed. Please refer to CMU_FreezeEnable() for\r
+ * a suggestion on how to reduce stalling time in some use cases.\r
+ *\r
+ * @param[in] clock\r
+ * Clock point to set divisor/prescaler for. Notice that not all clock points\r
+ * have a divisor/prescaler, please refer to CMU overview in the reference\r
+ * manual.\r
+ *\r
+ * @param[in] div\r
+ * The clock divisor to use (<= cmuClkDiv_512).\r
+ ******************************************************************************/\r
+void CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div)\r
+{\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ CMU_ClockPrescSet(clock, (CMU_ClkPresc_TypeDef)(div - 1));\r
+\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ uint32_t freq;\r
+ uint32_t divReg;\r
+\r
+ /* Get divisor reg id */\r
+ divReg = (clock >> CMU_DIV_REG_POS) & CMU_DIV_REG_MASK;\r
+\r
+ switch (divReg)\r
+ {\r
+#if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
+ case CMU_HFCLKDIV_REG:\r
+ EFM_ASSERT((div>=cmuClkDiv_1) && (div<=cmuClkDiv_8));\r
+\r
+ /* Configure worst case wait states for flash access before setting divisor */\r
+ flashWaitStateMax();\r
+\r
+ /* Set divider */\r
+ CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFCLKDIV_MASK)\r
+ | ((div-1) << _CMU_CTRL_HFCLKDIV_SHIFT);\r
+\r
+ /* Update CMSIS core clock variable */\r
+ /* (The function will update the global variable) */\r
+ freq = SystemCoreClockGet();\r
+\r
+ /* Optimize flash access wait state setting for current core clk */\r
+ flashWaitStateControl(freq);\r
+ break;\r
+#endif\r
+\r
+ case CMU_HFPERCLKDIV_REG:\r
+ EFM_ASSERT((div >= cmuClkDiv_1) && (div <= cmuClkDiv_512));\r
+ /* Convert to correct scale */\r
+ div = CMU_DivToLog2(div);\r
+ CMU->HFPERCLKDIV = (CMU->HFPERCLKDIV & ~_CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)\r
+ | (div << _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT);\r
+ break;\r
+\r
+ case CMU_HFCORECLKDIV_REG:\r
+ EFM_ASSERT(div <= cmuClkDiv_512);\r
+\r
+ /* Configure worst case wait states for flash access before setting divisor */\r
+ flashWaitStateMax();\r
+\r
+#if defined( CMU_CTRL_HFLE )\r
+ /* Clear HFLE and set DIV2 factor for peripheral clock\r
+ when running at frequencies lower than or equal to CMU_MAX_FREQ_HFLE. */\r
+ if ((CMU_ClockFreqGet(cmuClock_HF) / div) <= CMU_MAX_FREQ_HFLE())\r
+ {\r
+ /* Clear CMU HFLE */\r
+ BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 0);\r
+\r
+ /* Set DIV2 factor for peripheral clock */\r
+ BUS_RegBitWrite(&CMU->HFCORECLKDIV,\r
+ _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 0);\r
+ }\r
+ else\r
+ {\r
+ /* Set CMU HFLE */\r
+ BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1);\r
+\r
+ /* Set DIV4 factor for peripheral clock */\r
+ BUS_RegBitWrite(&CMU->HFCORECLKDIV,\r
+ _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
+ }\r
+#endif\r
+\r
+ /* Convert to correct scale */\r
+ div = CMU_DivToLog2(div);\r
+\r
+ CMU->HFCORECLKDIV = (CMU->HFCORECLKDIV\r
+ & ~_CMU_HFCORECLKDIV_HFCORECLKDIV_MASK)\r
+ | (div << _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT);\r
+\r
+ /* Update CMSIS core clock variable */\r
+ /* (The function will update the global variable) */\r
+ freq = SystemCoreClockGet();\r
+\r
+ /* Optimize flash access wait state setting for current core clk */\r
+ flashWaitStateControl(freq);\r
+ break;\r
+\r
+ case CMU_LFAPRESC0_REG:\r
+ switch (clock)\r
+ {\r
+ case cmuClock_RTC:\r
+ EFM_ASSERT(div <= cmuClkDiv_32768);\r
+\r
+ /* LF register about to be modified require sync. busy check */\r
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
+\r
+ /* Convert to correct scale */\r
+ div = CMU_DivToLog2(div);\r
+\r
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK)\r
+ | (div << _CMU_LFAPRESC0_RTC_SHIFT);\r
+ break;\r
+\r
+#if defined(_CMU_LFAPRESC0_LETIMER0_MASK)\r
+ case cmuClock_LETIMER0:\r
+ EFM_ASSERT(div <= cmuClkDiv_32768);\r
+\r
+ /* LF register about to be modified require sync. busy check */\r
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
+\r
+ /* Convert to correct scale */\r
+ div = CMU_DivToLog2(div);\r
+\r
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK)\r
+ | (div << _CMU_LFAPRESC0_LETIMER0_SHIFT);\r
+ break;\r
+#endif\r
+\r
+#if defined(LCD_PRESENT)\r
+ case cmuClock_LCDpre:\r
+ EFM_ASSERT((div >= cmuClkDiv_16) && (div <= cmuClkDiv_128));\r
+\r
+ /* LF register about to be modified require sync. busy check */\r
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
+\r
+ /* Convert to correct scale */\r
+ div = CMU_DivToLog2(div);\r
+\r
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LCD_MASK)\r
+ | ((div - CMU_DivToLog2(cmuClkDiv_16))\r
+ << _CMU_LFAPRESC0_LCD_SHIFT);\r
+ break;\r
+#endif /* defined(LCD_PRESENT) */\r
+\r
+#if defined(LESENSE_PRESENT)\r
+ case cmuClock_LESENSE:\r
+ EFM_ASSERT(div <= cmuClkDiv_8);\r
+\r
+ /* LF register about to be modified require sync. busy check */\r
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
+\r
+ /* Convert to correct scale */\r
+ div = CMU_DivToLog2(div);\r
+\r
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LESENSE_MASK)\r
+ | (div << _CMU_LFAPRESC0_LESENSE_SHIFT);\r
+ break;\r
+#endif /* defined(LESENSE_PRESENT) */\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case CMU_LFBPRESC0_REG:\r
+ switch (clock)\r
+ {\r
+#if defined(_CMU_LFBPRESC0_LEUART0_MASK)\r
+ case cmuClock_LEUART0:\r
+ EFM_ASSERT(div <= cmuClkDiv_8);\r
+\r
+ /* LF register about to be modified require sync. busy check */\r
+ syncReg(CMU_SYNCBUSY_LFBPRESC0);\r
+\r
+ /* Convert to correct scale */\r
+ div = CMU_DivToLog2(div);\r
+\r
+ CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK)\r
+ | (((uint32_t)div) << _CMU_LFBPRESC0_LEUART0_SHIFT);\r
+ break;\r
+#endif\r
+\r
+#if defined(_CMU_LFBPRESC0_LEUART1_MASK)\r
+ case cmuClock_LEUART1:\r
+ EFM_ASSERT(div <= cmuClkDiv_8);\r
+\r
+ /* LF register about to be modified require sync. busy check */\r
+ syncReg(CMU_SYNCBUSY_LFBPRESC0);\r
+\r
+ /* Convert to correct scale */\r
+ div = CMU_DivToLog2(div);\r
+\r
+ CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK)\r
+ | (((uint32_t)div) << _CMU_LFBPRESC0_LEUART1_SHIFT);\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+#endif\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Enable/disable a clock.\r
+ *\r
+ * @details\r
+ * In general, module clocking is disabled after a reset. If a module\r
+ * clock is disabled, the registers of that module are not accessible and\r
+ * reading from such registers may return undefined values. Writing to\r
+ * registers of clock disabled modules have no effect. One should normally\r
+ * avoid accessing module registers of a module with a disabled clock.\r
+ *\r
+ * @note\r
+ * If enabling/disabling a LF clock, synchronization into the low frequency\r
+ * domain is required. If the same register is modified before a previous\r
+ * update has completed, this function will stall until the previous\r
+ * synchronization has completed. Please refer to CMU_FreezeEnable() for\r
+ * a suggestion on how to reduce stalling time in some use cases.\r
+ *\r
+ * @param[in] clock\r
+ * The clock to enable/disable. Notice that not all defined clock\r
+ * points have separate enable/disable control, please refer to CMU overview\r
+ * in reference manual.\r
+ *\r
+ * @param[in] enable\r
+ * @li true - enable specified clock.\r
+ * @li false - disable specified clock.\r
+ ******************************************************************************/\r
+void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)\r
+{\r
+ volatile uint32_t *reg;\r
+ uint32_t bit;\r
+ uint32_t sync = 0;\r
+\r
+ /* Identify enable register */\r
+ switch ((clock >> CMU_EN_REG_POS) & CMU_EN_REG_MASK)\r
+ {\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ case CMU_CTRL_EN_REG:\r
+ reg = &CMU->CTRL;\r
+ break;\r
+#endif\r
+\r
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ case CMU_HFCORECLKEN0_EN_REG:\r
+ reg = &CMU->HFCORECLKEN0;\r
+#if defined( CMU_CTRL_HFLE )\r
+ /* Set HFLE and DIV4 factor for peripheral clock when\r
+ running at frequencies higher than or equal to CMU_MAX_FREQ_HFLE. */\r
+ if ( CMU_ClockFreqGet(cmuClock_CORE) > CMU_MAX_FREQ_HFLE())\r
+ {\r
+ /* Enable CMU HFLE */\r
+ BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1);\r
+\r
+ /* Set DIV4 factor for peripheral clock */\r
+ BUS_RegBitWrite(&CMU->HFCORECLKDIV,\r
+ _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
+ }\r
+#endif\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_HFBUSCLKEN0_MASK )\r
+ case CMU_HFBUSCLKEN0_EN_REG:\r
+ reg = &CMU->HFBUSCLKEN0;\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_HFRADIOCLKEN0_MASK )\r
+ case CMU_HFRADIOCLKEN0_EN_REG:\r
+ reg = &CMU->HFRADIOCLKEN0;\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_HFPERCLKDIV_MASK )\r
+ case CMU_HFPERCLKDIV_EN_REG:\r
+ reg = &CMU->HFPERCLKDIV;\r
+ break;\r
+#endif\r
+\r
+ case CMU_HFPERCLKEN0_EN_REG:\r
+ reg = &CMU->HFPERCLKEN0;\r
+ break;\r
+\r
+ case CMU_LFACLKEN0_EN_REG:\r
+ reg = &CMU->LFACLKEN0;\r
+ sync = CMU_SYNCBUSY_LFACLKEN0;\r
+ break;\r
+\r
+ case CMU_LFBCLKEN0_EN_REG:\r
+ reg = &CMU->LFBCLKEN0;\r
+ sync = CMU_SYNCBUSY_LFBCLKEN0;\r
+ break;\r
+\r
+#if defined( _CMU_LFCCLKEN0_MASK )\r
+ case CMU_LFCCLKEN0_EN_REG:\r
+ reg = &CMU->LFCCLKEN0;\r
+ sync = CMU_SYNCBUSY_LFCCLKEN0;\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_LFECLKEN0_MASK )\r
+ case CMU_LFECLKEN0_EN_REG:\r
+ reg = &CMU->LFECLKEN0;\r
+ sync = CMU_SYNCBUSY_LFECLKEN0;\r
+ break;\r
+#endif\r
+\r
+ case CMU_PCNT_EN_REG:\r
+ reg = &CMU->PCNTCTRL;\r
+ break;\r
+\r
+ default: /* Cannot enable/disable clock point */\r
+ EFM_ASSERT(0);\r
+ return;\r
+ }\r
+\r
+ /* Get bit position used to enable/disable */\r
+ bit = (clock >> CMU_EN_BIT_POS) & CMU_EN_BIT_MASK;\r
+\r
+ /* LF synchronization required? */\r
+ if (sync)\r
+ {\r
+ syncReg(sync);\r
+ }\r
+\r
+ /* Set/clear bit as requested */\r
+ BUS_RegBitWrite(reg, bit, enable);\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get clock frequency for a clock point.\r
+ *\r
+ * @param[in] clock\r
+ * Clock point to fetch frequency for.\r
+ *\r
+ * @return\r
+ * The current frequency in Hz.\r
+ ******************************************************************************/\r
+uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)\r
+{\r
+ uint32_t ret;\r
+\r
+ switch(clock & (CMU_CLK_BRANCH_MASK << CMU_CLK_BRANCH_POS))\r
+ {\r
+ case (CMU_HF_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = SystemHFClockGet();\r
+#if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
+ /* Family with an additional divider. */\r
+ ret = ret / (1U + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)\r
+ >> _CMU_CTRL_HFCLKDIV_SHIFT));\r
+#endif\r
+#if defined( _CMU_HFPRESC_MASK )\r
+ ret = ret / (1U + ((CMU->HFPRESC & _CMU_HFPRESC_PRESC_MASK)\r
+ >> _CMU_HFPRESC_PRESC_SHIFT));\r
+#endif\r
+ break;\r
+\r
+ case (CMU_HFPER_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = SystemHFClockGet();\r
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+#if defined( _CMU_CTRL_HFCLKDIV_MASK )\r
+ /* Family with an additional divider. */\r
+ ret = ret / (1U + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)\r
+ >> _CMU_CTRL_HFCLKDIV_SHIFT));\r
+#endif\r
+ ret >>= (CMU->HFPERCLKDIV & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK)\r
+ >> _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT;\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ ret /= 1U + ((CMU->HFPERPRESC & _CMU_HFPERPRESC_PRESC_MASK)\r
+ >> _CMU_HFPERPRESC_PRESC_SHIFT);\r
+#endif\r
+ break;\r
+\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+#if defined( _CMU_HFRADIOPRESC_PRESC_MASK )\r
+ case (CMU_HFRADIO_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = SystemHFClockGet();\r
+ ret /= 1U + ((CMU->HFRADIOPRESC & _CMU_HFRADIOPRESC_PRESC_MASK)\r
+ >> _CMU_HFRADIOPRESC_PRESC_SHIFT);\r
+ break;\r
+#endif\r
+\r
+#if defined( CRYPTO_PRESENT ) \\r
+ || defined( LDMA_PRESENT ) \\r
+ || defined( GPCRC_PRESENT ) \\r
+ || defined( PRS_PRESENT ) \\r
+ || defined( GPIO_PRESENT )\r
+ case (CMU_HFBUS_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = SystemHFClockGet();\r
+ break;\r
+#endif\r
+\r
+ case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = SystemHFClockGet();\r
+ ret /= 1U + ((CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK)\r
+ >> _CMU_HFCOREPRESC_PRESC_SHIFT);\r
+ break;\r
+\r
+ case (CMU_HFEXP_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = SystemHFClockGet();\r
+ ret /= 1U + ((CMU->HFEXPPRESC & _CMU_HFEXPPRESC_PRESC_MASK)\r
+ >> _CMU_HFEXPPRESC_PRESC_SHIFT);\r
+ break;\r
+#endif\r
+\r
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+#if defined(AES_PRESENT) \\r
+ || defined(DMA_PRESENT) \\r
+ || defined(EBI_PRESENT) \\r
+ || defined(USB_PRESENT)\r
+ case (CMU_HFCORE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ {\r
+ ret = SystemCoreClockGet();\r
+ } break;\r
+#endif\r
+#endif\r
+\r
+ case (CMU_LFA_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = lfClkGet(cmuClock_LFA);\r
+ break;\r
+\r
+#if defined( _CMU_LFACLKEN0_RTC_MASK )\r
+ case (CMU_RTC_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = lfClkGet(cmuClock_LFA);\r
+ ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_RTC_MASK)\r
+ >> _CMU_LFAPRESC0_RTC_SHIFT;\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_LFECLKEN0_RTCC_MASK )\r
+ case (CMU_RTCC_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = lfClkGet(cmuClock_LFE);\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_LFACLKEN0_LETIMER0_MASK )\r
+ case (CMU_LETIMER0_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = lfClkGet(cmuClock_LFA);\r
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)\r
+ >> _CMU_LFAPRESC0_LETIMER0_SHIFT;\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ ret /= CMU_Log2ToDiv((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)\r
+ >> _CMU_LFAPRESC0_LETIMER0_SHIFT);\r
+#endif\r
+ break;\r
+#endif\r
+\r
+#if defined(_CMU_LFACLKEN0_LCD_MASK)\r
+ case (CMU_LCDPRE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = lfClkGet(cmuClock_LFA);\r
+ ret >>= ((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)\r
+ >> _CMU_LFAPRESC0_LCD_SHIFT)\r
+ + CMU_DivToLog2(cmuClkDiv_16);\r
+ break;\r
+\r
+ case (CMU_LCD_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = lfClkGet(cmuClock_LFA);\r
+ ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LCD_MASK)\r
+ >> _CMU_LFAPRESC0_LCD_SHIFT;\r
+ ret /= 1U + ((CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK)\r
+ >> _CMU_LCDCTRL_FDIV_SHIFT);\r
+ break;\r
+#endif\r
+\r
+#if defined(_CMU_LFACLKEN0_LESENSE_MASK)\r
+ case (CMU_LESENSE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = lfClkGet(cmuClock_LFA);\r
+ ret >>= (CMU->LFAPRESC0 & _CMU_LFAPRESC0_LESENSE_MASK)\r
+ >> _CMU_LFAPRESC0_LESENSE_SHIFT;\r
+ break;\r
+#endif\r
+\r
+ case (CMU_LFB_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = lfClkGet(cmuClock_LFB);\r
+ break;\r
+\r
+#if defined( _CMU_LFBCLKEN0_LEUART0_MASK )\r
+ case (CMU_LEUART0_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = lfClkGet(cmuClock_LFB);\r
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)\r
+ >> _CMU_LFBPRESC0_LEUART0_SHIFT;\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ ret /= CMU_Log2ToDiv((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)\r
+ >> _CMU_LFBPRESC0_LEUART0_SHIFT);\r
+#endif\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_LFBCLKEN0_LEUART1_MASK )\r
+ case (CMU_LEUART1_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = lfClkGet(cmuClock_LFB);\r
+#if defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ ret >>= (CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)\r
+ >> _CMU_LFBPRESC0_LEUART1_SHIFT;\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ ret /= CMU_Log2ToDiv((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)\r
+ >> _CMU_LFBPRESC0_LEUART1_SHIFT);\r
+#endif\r
+ break;\r
+#endif\r
+\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ case (CMU_LFE_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = lfClkGet(cmuClock_LFE);\r
+ break;\r
+#endif\r
+\r
+ case (CMU_DBG_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = dbgClkGet();\r
+ break;\r
+\r
+ case (CMU_AUX_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = auxClkGet();\r
+ break;\r
+\r
+#if defined(USB_PRESENT)\r
+ case (CMU_USBC_CLK_BRANCH << CMU_CLK_BRANCH_POS):\r
+ ret = usbCClkGet();\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = 0;\r
+ break;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get clock prescaler.\r
+ *\r
+ * @param[in] clock\r
+ * Clock point to get the prescaler for. Notice that not all clock points\r
+ * have a prescaler. Please refer to CMU overview in reference manual.\r
+ *\r
+ * @return\r
+ * The prescaler value of the current clock point. 0 is returned\r
+ * if @p clock specifies a clock point without a prescaler.\r
+ ******************************************************************************/\r
+uint32_t CMU_ClockPrescGet(CMU_Clock_TypeDef clock)\r
+{\r
+ uint32_t prescReg;\r
+ uint32_t ret;\r
+\r
+ /* Get prescaler register id. */\r
+ prescReg = (clock >> CMU_PRESC_REG_POS) & CMU_PRESC_REG_MASK;\r
+\r
+ switch (prescReg)\r
+ {\r
+ case CMU_HFPRESC_REG:\r
+ ret = ((CMU->HFPRESC & _CMU_HFPRESC_PRESC_MASK)\r
+ >> _CMU_HFPRESC_PRESC_SHIFT);\r
+ break;\r
+\r
+ case CMU_HFEXPPRESC_REG:\r
+ ret = ((CMU->HFEXPPRESC & _CMU_HFEXPPRESC_PRESC_MASK)\r
+ >> _CMU_HFEXPPRESC_PRESC_SHIFT);\r
+ break;\r
+\r
+ case CMU_HFCLKLEPRESC_REG:\r
+ ret = ((CMU->HFPRESC & _CMU_HFPRESC_HFCLKLEPRESC_MASK)\r
+ >> _CMU_HFPRESC_HFCLKLEPRESC_SHIFT);\r
+ break;\r
+\r
+ case CMU_HFPERPRESC_REG:\r
+ ret = ((CMU->HFPERPRESC & _CMU_HFPERPRESC_PRESC_MASK)\r
+ >> _CMU_HFPERPRESC_PRESC_SHIFT);\r
+ break;\r
+\r
+#if defined( _CMU_HFRADIOPRESC_PRESC_MASK )\r
+ case CMU_HFRADIOPRESC_REG:\r
+ ret = ((CMU->HFRADIOPRESC & _CMU_HFRADIOPRESC_PRESC_MASK)\r
+ >> _CMU_HFRADIOPRESC_PRESC_SHIFT);\r
+ break;\r
+#endif\r
+\r
+ case CMU_HFCOREPRESC_REG:\r
+ ret = ((CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK)\r
+ >> _CMU_HFCOREPRESC_PRESC_SHIFT);\r
+ break;\r
+\r
+ case CMU_LFAPRESC0_REG:\r
+ switch (clock)\r
+ {\r
+#if defined( _CMU_LFAPRESC0_LETIMER0_MASK )\r
+ case cmuClock_LETIMER0:\r
+ ret = (((CMU->LFAPRESC0 & _CMU_LFAPRESC0_LETIMER0_MASK)\r
+ >> _CMU_LFAPRESC0_LETIMER0_SHIFT));\r
+ /* Convert the exponent to prescaler value. */\r
+ ret = CMU_Log2ToDiv(ret) - 1U;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = 0U;\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case CMU_LFBPRESC0_REG:\r
+ switch (clock)\r
+ {\r
+#if defined( _CMU_LFBPRESC0_LEUART0_MASK )\r
+ case cmuClock_LEUART0:\r
+ ret = (((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART0_MASK)\r
+ >> _CMU_LFBPRESC0_LEUART0_SHIFT));\r
+ /* Convert the exponent to prescaler value. */\r
+ ret = CMU_Log2ToDiv(ret) - 1U;\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_LFBPRESC0_LEUART1_MASK )\r
+ case cmuClock_LEUART1:\r
+ ret = (((CMU->LFBPRESC0 & _CMU_LFBPRESC0_LEUART1_MASK)\r
+ >> _CMU_LFBPRESC0_LEUART1_SHIFT));\r
+ /* Convert the exponent to prescaler value. */\r
+ ret = CMU_Log2ToDiv(ret) - 1U;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = 0U;\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case CMU_LFEPRESC0_REG:\r
+ switch (clock)\r
+ {\r
+#if defined( RTCC_PRESENT )\r
+ case cmuClock_RTCC:\r
+ /* No need to compute with LFEPRESC0_RTCC - DIV1 is the only */\r
+ /* allowed value. Convert the exponent to prescaler value. */\r
+ ret = _CMU_LFEPRESC0_RTCC_DIV1;\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = 0U;\r
+ break;\r
+#endif\r
+ }\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = 0U;\r
+ break;\r
+ }\r
+\r
+ return ret;\r
+}\r
+#endif\r
+\r
+\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set clock prescaler.\r
+ *\r
+ * @note\r
+ * If setting a LF clock prescaler, synchronization into the low frequency\r
+ * domain is required. If the same register is modified before a previous\r
+ * update has completed, this function will stall until the previous\r
+ * synchronization has completed. Please refer to CMU_FreezeEnable() for\r
+ * a suggestion on how to reduce stalling time in some use cases.\r
+ *\r
+ * @param[in] clock\r
+ * Clock point to set prescaler for. Notice that not all clock points\r
+ * have a prescaler, please refer to CMU overview in the reference manual.\r
+ *\r
+ * @param[in] presc\r
+ * The clock prescaler to use.\r
+ ******************************************************************************/\r
+void CMU_ClockPrescSet(CMU_Clock_TypeDef clock, CMU_ClkPresc_TypeDef presc)\r
+{\r
+ uint32_t freq;\r
+ uint32_t prescReg;\r
+\r
+ /* Get divisor reg id */\r
+ prescReg = (clock >> CMU_PRESC_REG_POS) & CMU_PRESC_REG_MASK;\r
+\r
+ switch (prescReg)\r
+ {\r
+ case CMU_HFPRESC_REG:\r
+ EFM_ASSERT(presc < 32U);\r
+\r
+ CMU->HFPRESC = (CMU->HFPRESC & ~_CMU_HFPRESC_PRESC_MASK)\r
+ | (presc << _CMU_HFPRESC_PRESC_SHIFT);\r
+ break;\r
+\r
+ case CMU_HFEXPPRESC_REG:\r
+ EFM_ASSERT(presc < 32U);\r
+\r
+ CMU->HFEXPPRESC = (CMU->HFEXPPRESC & ~_CMU_HFEXPPRESC_PRESC_MASK)\r
+ | (presc << _CMU_HFEXPPRESC_PRESC_SHIFT);\r
+ break;\r
+\r
+ case CMU_HFCLKLEPRESC_REG:\r
+ EFM_ASSERT(presc < 2U);\r
+\r
+ /* Specifies the clock divider for HFCLKLE. When running at frequencies\r
+ * higher than 32 MHz, this must be set to DIV4. */\r
+ CMU->HFPRESC = (CMU->HFPRESC & ~_CMU_HFPRESC_HFCLKLEPRESC_MASK)\r
+ | (presc << _CMU_HFPRESC_HFCLKLEPRESC_SHIFT);\r
+ break;\r
+\r
+ case CMU_HFPERPRESC_REG:\r
+ EFM_ASSERT(presc < 512U);\r
+\r
+ CMU->HFPERPRESC = (CMU->HFPERPRESC & ~_CMU_HFPERPRESC_PRESC_MASK)\r
+ | (presc << _CMU_HFPERPRESC_PRESC_SHIFT);\r
+ break;\r
+\r
+#if defined( _CMU_HFRADIOPRESC_PRESC_MASK )\r
+ case CMU_HFRADIOPRESC_REG:\r
+ EFM_ASSERT(presc < 512U);\r
+\r
+ CMU->HFRADIOPRESC = (CMU->HFRADIOPRESC & ~_CMU_HFRADIOPRESC_PRESC_MASK)\r
+ | (presc << _CMU_HFRADIOPRESC_PRESC_SHIFT);\r
+ break;\r
+#endif\r
+\r
+ case CMU_HFCOREPRESC_REG:\r
+ EFM_ASSERT(presc < 512U);\r
+\r
+ /* Configure worst case wait states for flash access before setting\r
+ * the prescaler. */\r
+ flashWaitStateControl(CMU_MAX_FREQ_0WS + 1);\r
+\r
+ CMU->HFCOREPRESC = (CMU->HFCOREPRESC & ~_CMU_HFCOREPRESC_PRESC_MASK)\r
+ | (presc << _CMU_HFCOREPRESC_PRESC_SHIFT);\r
+\r
+ /* Update CMSIS core clock variable */\r
+ /* (The function will update the global variable) */\r
+ freq = SystemCoreClockGet();\r
+\r
+ /* Optimize flash access wait state setting for current core clk */\r
+ flashWaitStateControl(freq);\r
+ break;\r
+\r
+ case CMU_LFAPRESC0_REG:\r
+ switch (clock)\r
+ {\r
+#if defined( RTC_PRESENT )\r
+ case cmuClock_RTC:\r
+ EFM_ASSERT(presc <= 32768U);\r
+\r
+ /* Convert prescaler value to DIV exponent scale. */\r
+ presc = CMU_PrescToLog2(presc);\r
+\r
+ /* LF register about to be modified require sync. Busy check. */\r
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
+\r
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTC_MASK)\r
+ | (presc << _CMU_LFAPRESC0_RTC_SHIFT);\r
+ break;\r
+#endif\r
+\r
+#if defined( RTCC_PRESENT )\r
+ case cmuClock_RTCC:\r
+#if defined( _CMU_LFEPRESC0_RTCC_MASK )\r
+ /* DIV1 is the only accepted value. */\r
+ EFM_ASSERT(presc <= 0U);\r
+\r
+ /* LF register about to be modified require sync. Busy check.. */\r
+ syncReg(CMU_SYNCBUSY_LFEPRESC0);\r
+\r
+ CMU->LFEPRESC0 = (CMU->LFEPRESC0 & ~_CMU_LFEPRESC0_RTCC_MASK)\r
+ | (presc << _CMU_LFEPRESC0_RTCC_SHIFT);\r
+#else\r
+ EFM_ASSERT(presc <= 32768U);\r
+\r
+ /* Convert prescaler value to DIV exponent scale. */\r
+ presc = CMU_PrescToLog2(presc);\r
+\r
+ /* LF register about to be modified require sync. Busy check. */\r
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
+\r
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_RTCC_MASK)\r
+ | (presc << _CMU_LFAPRESC0_RTCC_SHIFT);\r
+#endif\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_LFAPRESC0_LETIMER0_MASK )\r
+ case cmuClock_LETIMER0:\r
+ EFM_ASSERT(presc <= 32768U);\r
+\r
+ /* Convert prescaler value to DIV exponent scale. */\r
+ presc = CMU_PrescToLog2(presc);\r
+\r
+ /* LF register about to be modified require sync. Busy check. */\r
+ syncReg(CMU_SYNCBUSY_LFAPRESC0);\r
+\r
+ CMU->LFAPRESC0 = (CMU->LFAPRESC0 & ~_CMU_LFAPRESC0_LETIMER0_MASK)\r
+ | (presc << _CMU_LFAPRESC0_LETIMER0_SHIFT);\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case CMU_LFBPRESC0_REG:\r
+ switch (clock)\r
+ {\r
+#if defined( _CMU_LFBPRESC0_LEUART0_MASK )\r
+ case cmuClock_LEUART0:\r
+ EFM_ASSERT(presc <= 8U);\r
+\r
+ /* Convert prescaler value to DIV exponent scale. */\r
+ presc = CMU_PrescToLog2(presc);\r
+\r
+ /* LF register about to be modified require sync. Busy check. */\r
+ syncReg(CMU_SYNCBUSY_LFBPRESC0);\r
+\r
+ CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART0_MASK)\r
+ | (presc << _CMU_LFBPRESC0_LEUART0_SHIFT);\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_LFBPRESC0_LEUART1_MASK )\r
+ case cmuClock_LEUART1:\r
+ EFM_ASSERT(presc <= 8U);\r
+\r
+ /* Convert prescaler value to DIV exponent scale. */\r
+ presc = CMU_PrescToLog2(presc);\r
+\r
+ /* LF register about to be modified require sync. Busy check. */\r
+ syncReg(CMU_SYNCBUSY_LFBPRESC0);\r
+\r
+ CMU->LFBPRESC0 = (CMU->LFBPRESC0 & ~_CMU_LFBPRESC0_LEUART1_MASK)\r
+ | (presc << _CMU_LFBPRESC0_LEUART1_SHIFT);\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case CMU_LFEPRESC0_REG:\r
+ switch (clock)\r
+ {\r
+#if defined( _CMU_LFEPRESC0_RTCC_MASK )\r
+ case cmuClock_RTCC:\r
+ EFM_ASSERT(presc <= 0U);\r
+\r
+ /* LF register about to be modified require sync. Busy check. */\r
+ syncReg(CMU_SYNCBUSY_LFEPRESC0);\r
+\r
+ CMU->LFEPRESC0 = (CMU->LFEPRESC0 & ~_CMU_LFEPRESC0_RTCC_MASK)\r
+ | (presc << _CMU_LFEPRESC0_RTCC_SHIFT);\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+}\r
+#endif\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get currently selected reference clock used for a clock branch.\r
+ *\r
+ * @param[in] clock\r
+ * Clock branch to fetch selected ref. clock for. One of:\r
+ * @li #cmuClock_HF\r
+ * @li #cmuClock_LFA\r
+ * @li #cmuClock_LFB @if _CMU_LFCLKSEL_LFAE_ULFRCO\r
+ * @li #cmuClock_LFC\r
+ * @endif @if _SILICON_LABS_32B_PLATFORM_2\r
+ * @li #cmuClock_LFE\r
+ * @endif\r
+ * @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT\r
+ * @li #cmuClock_USBC\r
+ * @endif\r
+ *\r
+ * @return\r
+ * Reference clock used for clocking selected branch, #cmuSelect_Error if\r
+ * invalid @p clock provided.\r
+ ******************************************************************************/\r
+CMU_Select_TypeDef CMU_ClockSelectGet(CMU_Clock_TypeDef clock)\r
+{\r
+ CMU_Select_TypeDef ret = cmuSelect_Disabled;\r
+ uint32_t selReg;\r
+\r
+ selReg = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;\r
+\r
+ switch (selReg)\r
+ {\r
+ case CMU_HFCLKSEL_REG:\r
+#if defined( _CMU_HFCLKSEL_HF_MASK )\r
+ switch (CMU->HFCLKSEL & _CMU_HFCLKSEL_HF_MASK)\r
+ {\r
+ case CMU_HFCLKSEL_HF_LFXO:\r
+ ret = cmuSelect_LFXO;\r
+ break;\r
+\r
+ case CMU_HFCLKSEL_HF_LFRCO:\r
+ ret = cmuSelect_LFRCO;\r
+ break;\r
+\r
+ case CMU_HFCLKSEL_HF_HFXO:\r
+ ret = cmuSelect_HFXO;\r
+ break;\r
+\r
+ default:\r
+ ret = cmuSelect_HFRCO;\r
+ break;\r
+ }\r
+#else\r
+ switch (CMU->STATUS\r
+ & (CMU_STATUS_HFRCOSEL\r
+ | CMU_STATUS_HFXOSEL\r
+ | CMU_STATUS_LFRCOSEL\r
+#if defined( CMU_STATUS_USHFRCODIV2SEL )\r
+ | CMU_STATUS_USHFRCODIV2SEL\r
+#endif\r
+ | CMU_STATUS_LFXOSEL))\r
+ {\r
+ case CMU_STATUS_LFXOSEL:\r
+ ret = cmuSelect_LFXO;\r
+ break;\r
+\r
+ case CMU_STATUS_LFRCOSEL:\r
+ ret = cmuSelect_LFRCO;\r
+ break;\r
+\r
+ case CMU_STATUS_HFXOSEL:\r
+ ret = cmuSelect_HFXO;\r
+ break;\r
+\r
+#if defined( CMU_STATUS_USHFRCODIV2SEL )\r
+ case CMU_STATUS_USHFRCODIV2SEL:\r
+ ret = cmuSelect_USHFRCODIV2;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ ret = cmuSelect_HFRCO;\r
+ break;\r
+ }\r
+#endif\r
+ break;\r
+\r
+ case CMU_LFACLKSEL_REG:\r
+#if defined( _CMU_LFCLKSEL_MASK )\r
+ switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFA_MASK)\r
+ {\r
+ case CMU_LFCLKSEL_LFA_LFRCO:\r
+ ret = cmuSelect_LFRCO;\r
+ break;\r
+\r
+ case CMU_LFCLKSEL_LFA_LFXO:\r
+ ret = cmuSelect_LFXO;\r
+ break;\r
+\r
+#if defined( CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2 )\r
+ case CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2:\r
+ ret = cmuSelect_CORELEDIV2;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+#if defined( CMU_LFCLKSEL_LFAE )\r
+ if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFAE_MASK)\r
+ {\r
+ ret = cmuSelect_ULFRCO;\r
+ break;\r
+ }\r
+#else\r
+ ret = cmuSelect_Disabled;\r
+#endif\r
+ break;\r
+ }\r
+#endif /* _CMU_LFCLKSEL_MASK */\r
+\r
+#if defined( _CMU_LFACLKSEL_MASK )\r
+ switch (CMU->LFACLKSEL & _CMU_LFACLKSEL_LFA_MASK)\r
+ {\r
+ case CMU_LFACLKSEL_LFA_LFRCO:\r
+ ret = cmuSelect_LFRCO;\r
+ break;\r
+\r
+ case CMU_LFACLKSEL_LFA_LFXO:\r
+ ret = cmuSelect_LFXO;\r
+ break;\r
+\r
+ case CMU_LFACLKSEL_LFA_ULFRCO:\r
+ ret = cmuSelect_ULFRCO;\r
+ break;\r
+\r
+#if defined( _CMU_LFACLKSEL_LFA_HFCLKLE )\r
+ case CMU_LFACLKSEL_LFA_HFCLKLE:\r
+ ret = cmuSelect_HFCLKLE;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ ret = cmuSelect_Disabled;\r
+ break;\r
+ }\r
+#endif\r
+ break;\r
+\r
+ case CMU_LFBCLKSEL_REG:\r
+#if defined( _CMU_LFCLKSEL_MASK )\r
+ switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFB_MASK)\r
+ {\r
+ case CMU_LFCLKSEL_LFB_LFRCO:\r
+ ret = cmuSelect_LFRCO;\r
+ break;\r
+\r
+ case CMU_LFCLKSEL_LFB_LFXO:\r
+ ret = cmuSelect_LFXO;\r
+ break;\r
+\r
+#if defined( CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2 )\r
+ case CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2:\r
+ ret = cmuSelect_CORELEDIV2;\r
+ break;\r
+#endif\r
+\r
+#if defined( CMU_LFCLKSEL_LFB_HFCLKLE )\r
+ case CMU_LFCLKSEL_LFB_HFCLKLE:\r
+ ret = cmuSelect_HFCLKLE;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+#if defined( CMU_LFCLKSEL_LFBE )\r
+ if (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFBE_MASK)\r
+ {\r
+ ret = cmuSelect_ULFRCO;\r
+ break;\r
+ }\r
+#else\r
+ ret = cmuSelect_Disabled;\r
+#endif\r
+ break;\r
+ }\r
+#endif /* _CMU_LFCLKSEL_MASK */\r
+\r
+#if defined( _CMU_LFBCLKSEL_MASK )\r
+ switch (CMU->LFBCLKSEL & _CMU_LFBCLKSEL_LFB_MASK)\r
+ {\r
+ case CMU_LFBCLKSEL_LFB_LFRCO:\r
+ ret = cmuSelect_LFRCO;\r
+ break;\r
+\r
+ case CMU_LFBCLKSEL_LFB_LFXO:\r
+ ret = cmuSelect_LFXO;\r
+ break;\r
+\r
+ case CMU_LFBCLKSEL_LFB_ULFRCO:\r
+ ret = cmuSelect_ULFRCO;\r
+ break;\r
+\r
+ case CMU_LFBCLKSEL_LFB_HFCLKLE:\r
+ ret = cmuSelect_HFCLKLE;\r
+ break;\r
+\r
+ default:\r
+ ret = cmuSelect_Disabled;\r
+ break;\r
+ }\r
+#endif\r
+ break;\r
+\r
+#if defined( _CMU_LFCLKSEL_LFC_MASK )\r
+ case CMU_LFCCLKSEL_REG:\r
+ switch (CMU->LFCLKSEL & _CMU_LFCLKSEL_LFC_MASK)\r
+ {\r
+ case CMU_LFCLKSEL_LFC_LFRCO:\r
+ ret = cmuSelect_LFRCO;\r
+ break;\r
+\r
+ case CMU_LFCLKSEL_LFC_LFXO:\r
+ ret = cmuSelect_LFXO;\r
+ break;\r
+\r
+ default:\r
+ ret = cmuSelect_Disabled;\r
+ break;\r
+ }\r
+ break;\r
+#endif\r
+\r
+#if defined( _CMU_LFECLKSEL_LFE_MASK )\r
+ case CMU_LFECLKSEL_REG:\r
+ switch (CMU->LFECLKSEL & _CMU_LFECLKSEL_LFE_MASK)\r
+ {\r
+ case CMU_LFECLKSEL_LFE_LFRCO:\r
+ ret = cmuSelect_LFRCO;\r
+ break;\r
+\r
+ case CMU_LFECLKSEL_LFE_LFXO:\r
+ ret = cmuSelect_LFXO;\r
+ break;\r
+\r
+ case CMU_LFECLKSEL_LFE_ULFRCO:\r
+ ret = cmuSelect_ULFRCO;\r
+ break;\r
+\r
+#if defined ( _CMU_LFECLKSEL_LFE_HFCLKLE )\r
+ case CMU_LFECLKSEL_LFE_HFCLKLE:\r
+ ret = cmuSelect_HFCLKLE;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ ret = cmuSelect_Disabled;\r
+ break;\r
+ }\r
+ break;\r
+#endif /* CMU_LFECLKSEL_REG */\r
+\r
+ case CMU_DBGCLKSEL_REG:\r
+#if defined( _CMU_DBGCLKSEL_DBG_MASK )\r
+ switch (CMU->DBGCLKSEL & _CMU_DBGCLKSEL_DBG_MASK)\r
+ {\r
+ case CMU_DBGCLKSEL_DBG_HFCLK:\r
+ ret = cmuSelect_HFCLK;\r
+ break;\r
+\r
+ case CMU_DBGCLKSEL_DBG_AUXHFRCO:\r
+ ret = cmuSelect_AUXHFRCO;\r
+ break;\r
+ }\r
+#else\r
+ ret = cmuSelect_AUXHFRCO;\r
+#endif /* CMU_DBGCLKSEL_DBG */\r
+\r
+#if defined( _CMU_CTRL_DBGCLK_MASK )\r
+ switch(CMU->CTRL & _CMU_CTRL_DBGCLK_MASK)\r
+ {\r
+ case CMU_CTRL_DBGCLK_AUXHFRCO:\r
+ ret = cmuSelect_AUXHFRCO;\r
+ break;\r
+\r
+ case CMU_CTRL_DBGCLK_HFCLK:\r
+ ret = cmuSelect_HFCLK;\r
+ break;\r
+ }\r
+#else\r
+ ret = cmuSelect_AUXHFRCO;\r
+#endif\r
+ break;\r
+\r
+\r
+#if defined( USB_PRESENT )\r
+ case CMU_USBCCLKSEL_REG:\r
+ switch (CMU->STATUS\r
+ & (CMU_STATUS_USBCLFXOSEL\r
+#if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)\r
+ | CMU_STATUS_USBCHFCLKSEL\r
+#endif\r
+#if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)\r
+ | CMU_STATUS_USBCUSHFRCOSEL\r
+#endif\r
+ | CMU_STATUS_USBCLFRCOSEL))\r
+ {\r
+#if defined(_CMU_STATUS_USBCHFCLKSEL_MASK)\r
+ case CMU_STATUS_USBCHFCLKSEL:\r
+ ret = cmuSelect_HFCLK;\r
+ break;\r
+#endif\r
+\r
+#if defined(_CMU_STATUS_USBCUSHFRCOSEL_MASK)\r
+ case CMU_STATUS_USBCUSHFRCOSEL:\r
+ ret = cmuSelect_USHFRCO;\r
+ break;\r
+#endif\r
+\r
+ case CMU_STATUS_USBCLFXOSEL:\r
+ ret = cmuSelect_LFXO;\r
+ break;\r
+\r
+ case CMU_STATUS_USBCLFRCOSEL:\r
+ ret = cmuSelect_LFRCO;\r
+ break;\r
+\r
+ default:\r
+ ret = cmuSelect_Disabled;\r
+ break;\r
+ }\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = cmuSelect_Error;\r
+ break;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Select reference clock/oscillator used for a clock branch.\r
+ *\r
+ * @details\r
+ * Notice that if a selected reference is not enabled prior to selecting its\r
+ * use, it will be enabled, and this function will wait for the selected\r
+ * oscillator to be stable. It will however NOT be disabled if another\r
+ * reference clock is selected later.\r
+ *\r
+ * This feature is particularly important if selecting a new reference\r
+ * clock for the clock branch clocking the core, otherwise the system\r
+ * may halt.\r
+ *\r
+ * @param[in] clock\r
+ * Clock branch to select reference clock for. One of:\r
+ * @li #cmuClock_HF\r
+ * @li #cmuClock_LFA\r
+ * @li #cmuClock_LFB @if _CMU_LFCLKSEL_LFAE_ULFRCO\r
+ * @li #cmuClock_LFC\r
+ * @endif @if _SILICON_LABS_32B_PLATFORM_2\r
+ * @li #cmuClock_LFE\r
+ * @endif\r
+ * @li #cmuClock_DBG @if DOXYDOC_USB_PRESENT\r
+ * @li #cmuClock_USBC\r
+ * @endif\r
+ *\r
+ * @param[in] ref\r
+ * Reference selected for clocking, please refer to reference manual for\r
+ * for details on which reference is available for a specific clock branch.\r
+ * @li #cmuSelect_HFRCO\r
+ * @li #cmuSelect_LFRCO\r
+ * @li #cmuSelect_HFXO\r
+ * @li #cmuSelect_LFXO\r
+ * @li #cmuSelect_CORELEDIV2\r
+ * @li #cmuSelect_AUXHFRCO\r
+ * @li #cmuSelect_HFCLK @ifnot DOXYDOC_EFM32_GECKO_FAMILY\r
+ * @li #cmuSelect_ULFRCO\r
+ * @endif\r
+ ******************************************************************************/\r
+void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)\r
+{\r
+ uint32_t select = cmuOsc_HFRCO;\r
+ CMU_Osc_TypeDef osc = cmuOsc_HFRCO;\r
+ uint32_t freq;\r
+ uint32_t tmp;\r
+ uint32_t selRegId;\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ volatile uint32_t *selReg = NULL;\r
+#endif\r
+#if defined( CMU_LFCLKSEL_LFAE_ULFRCO )\r
+ uint32_t lfExtended = 0;\r
+#endif\r
+\r
+ selRegId = (clock >> CMU_SEL_REG_POS) & CMU_SEL_REG_MASK;\r
+\r
+ switch (selRegId)\r
+ {\r
+ case CMU_HFCLKSEL_REG:\r
+ switch (ref)\r
+ {\r
+ case cmuSelect_LFXO:\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ select = CMU_HFCLKSEL_HF_LFXO;\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ select = CMU_CMD_HFCLKSEL_LFXO;\r
+#endif\r
+ osc = cmuOsc_LFXO;\r
+ break;\r
+\r
+ case cmuSelect_LFRCO:\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ select = CMU_HFCLKSEL_HF_LFRCO;\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ select = CMU_CMD_HFCLKSEL_LFRCO;\r
+#endif\r
+ osc = cmuOsc_LFRCO;\r
+ break;\r
+\r
+ case cmuSelect_HFXO:\r
+ osc = cmuOsc_HFXO;\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ select = CMU_HFCLKSEL_HF_HFXO;\r
+ /* Adjust HFXO buffer current for high frequencies, */\r
+ /* enable WSHFLE for frequencies above 32MHz. */\r
+ if (SystemHFXOClockGet() > 32000000)\r
+ {\r
+ CMU->CTRL |= CMU_CTRL_WSHFLE;\r
+ }\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ select = CMU_CMD_HFCLKSEL_HFXO;\r
+#if defined( CMU_CTRL_HFLE )\r
+ /* Adjust HFXO buffer current for high frequencies, */\r
+ /* enable HFLE for frequencies above CMU_MAX_FREQ_HFLE. */\r
+ if(SystemHFXOClockGet() > CMU_MAX_FREQ_HFLE())\r
+ {\r
+ CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK)\r
+ | CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ\r
+ /* Must have HFLE enabled to access some LE peripherals >=32MHz */\r
+ | CMU_CTRL_HFLE;\r
+\r
+ /* Set HFLE and DIV4 factor for peripheral clock if HFCORE */\r
+ /* clock for LE is enabled. */\r
+ if (CMU->HFCORECLKEN0 & CMU_HFCORECLKEN0_LE)\r
+ {\r
+ BUS_RegBitWrite(&CMU->HFCORECLKDIV,\r
+ _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* This can happen if the user configures the EFM32_HFXO_FREQ to */\r
+ /* use another oscillator frequency */\r
+ CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBUFCUR_MASK)\r
+ | CMU_CTRL_HFXOBUFCUR_BOOSTUPTO32MHZ;\r
+ }\r
+#endif\r
+#endif\r
+ break;\r
+\r
+ case cmuSelect_HFRCO:\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ select = CMU_HFCLKSEL_HF_HFRCO;\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ select = CMU_CMD_HFCLKSEL_HFRCO;\r
+#endif\r
+ osc = cmuOsc_HFRCO;\r
+ break;\r
+\r
+#if defined( CMU_CMD_HFCLKSEL_USHFRCODIV2 )\r
+ case cmuSelect_USHFRCODIV2:\r
+ select = CMU_CMD_HFCLKSEL_USHFRCODIV2;\r
+ osc = cmuOsc_USHFRCO;\r
+ break;\r
+#endif\r
+\r
+#if defined( CMU_LFCLKSEL_LFAE_ULFRCO ) || defined( CMU_LFACLKSEL_LFA_ULFRCO )\r
+ case cmuSelect_ULFRCO:\r
+ /* ULFRCO cannot be used as HFCLK */\r
+ EFM_ASSERT(0);\r
+ return;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ return;\r
+ }\r
+\r
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
+ CMU_OscillatorEnable(osc, true, true);\r
+\r
+ /* Configure worst case wait states for flash access before selecting */\r
+ flashWaitStateMax();\r
+\r
+ /* Switch to selected oscillator */\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ CMU->HFCLKSEL = select;\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ CMU->CMD = select;\r
+#endif\r
+\r
+ /* Keep EMU module informed */\r
+ EMU_UpdateOscConfig();\r
+\r
+ /* Update CMSIS core clock variable */\r
+ /* (The function will update the global variable) */\r
+ freq = SystemCoreClockGet();\r
+\r
+ /* Optimize flash access wait state setting for currently selected core clk */\r
+ flashWaitStateControl(freq);\r
+ break;\r
+\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ case CMU_LFACLKSEL_REG:\r
+ selReg = (selReg == NULL) ? &CMU->LFACLKSEL : selReg;\r
+#if !defined( _CMU_LFACLKSEL_LFA_HFCLKLE )\r
+ /* HFCLKCLE can not be used as LFACLK */\r
+ EFM_ASSERT(ref != cmuSelect_HFCLKLE);\r
+#endif\r
+ case CMU_LFECLKSEL_REG:\r
+ selReg = (selReg == NULL) ? &CMU->LFECLKSEL : selReg;\r
+#if !defined( _CMU_LFECLKSEL_LFE_HFCLKLE )\r
+ /* HFCLKCLE can not be used as LFECLK */\r
+ EFM_ASSERT(ref != cmuSelect_HFCLKLE);\r
+#endif\r
+ case CMU_LFBCLKSEL_REG:\r
+ selReg = (selReg == NULL) ? &CMU->LFBCLKSEL : selReg;\r
+ switch (ref)\r
+ {\r
+ case cmuSelect_Disabled:\r
+ tmp = _CMU_LFACLKSEL_LFA_DISABLED;\r
+ break;\r
+\r
+ case cmuSelect_LFXO:\r
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
+ CMU_OscillatorEnable(cmuOsc_LFXO, true, true);\r
+ tmp = _CMU_LFACLKSEL_LFA_LFXO;\r
+ break;\r
+\r
+ case cmuSelect_LFRCO:\r
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
+ CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);\r
+ tmp = _CMU_LFACLKSEL_LFA_LFRCO;\r
+ break;\r
+\r
+ case cmuSelect_HFCLKLE:\r
+ /* Ensure HFCORE to LE clocking is enabled */\r
+ BUS_RegBitWrite(&CMU->HFBUSCLKEN0, _CMU_HFBUSCLKEN0_LE_SHIFT, 1);\r
+ tmp = _CMU_LFBCLKSEL_LFB_HFCLKLE;\r
+\r
+ /* If core frequency is > 32MHz enable WSHFLE */\r
+ freq = SystemCoreClockGet();\r
+ if (freq > 32000000U)\r
+ {\r
+ /* Enable CMU HFLE */\r
+ BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_WSHFLE_SHIFT, 1);\r
+\r
+ /* Enable DIV4 factor for peripheral clock */\r
+ BUS_RegBitWrite(&CMU->HFPRESC, _CMU_HFPRESC_HFCLKLEPRESC_SHIFT, 1);\r
+ }\r
+ break;\r
+\r
+ case cmuSelect_ULFRCO:\r
+ /* ULFRCO is always on, there is no need to enable it. */\r
+ tmp = _CMU_LFACLKSEL_LFA_ULFRCO;\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ return;\r
+ }\r
+ *selReg = tmp;\r
+ break;\r
+\r
+#elif defined( _SILICON_LABS_32B_PLATFORM_1 )\r
+ case CMU_LFACLKSEL_REG:\r
+ case CMU_LFBCLKSEL_REG:\r
+ switch (ref)\r
+ {\r
+ case cmuSelect_Disabled:\r
+ tmp = _CMU_LFCLKSEL_LFA_DISABLED;\r
+ break;\r
+\r
+ case cmuSelect_LFXO:\r
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
+ CMU_OscillatorEnable(cmuOsc_LFXO, true, true);\r
+ tmp = _CMU_LFCLKSEL_LFA_LFXO;\r
+ break;\r
+\r
+ case cmuSelect_LFRCO:\r
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
+ CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);\r
+ tmp = _CMU_LFCLKSEL_LFA_LFRCO;\r
+ break;\r
+\r
+ case cmuSelect_CORELEDIV2:\r
+ /* Ensure HFCORE to LE clocking is enabled */\r
+ BUS_RegBitWrite(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_LE_SHIFT, 1);\r
+ tmp = _CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2;\r
+#if defined( CMU_CTRL_HFLE )\r
+ /* If core frequency is higher than CMU_MAX_FREQ_HFLE on\r
+ Giant/Leopard/Wonder, enable HFLE and DIV4. */\r
+ freq = SystemCoreClockGet();\r
+ if(freq > CMU_MAX_FREQ_HFLE())\r
+ {\r
+ /* Enable CMU HFLE */\r
+ BUS_RegBitWrite(&CMU->CTRL, _CMU_CTRL_HFLE_SHIFT, 1);\r
+\r
+ /* Enable DIV4 factor for peripheral clock */\r
+ BUS_RegBitWrite(&CMU->HFCORECLKDIV,\r
+ _CMU_HFCORECLKDIV_HFCORECLKLEDIV_SHIFT, 1);\r
+ }\r
+#endif\r
+ break;\r
+\r
+#if defined( CMU_LFCLKSEL_LFAE_ULFRCO )\r
+ case cmuSelect_ULFRCO:\r
+ /* ULFRCO is always enabled */\r
+ tmp = _CMU_LFCLKSEL_LFA_DISABLED;\r
+ lfExtended = 1;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ /* Illegal clock source for LFA/LFB selected */\r
+ EFM_ASSERT(0);\r
+ return;\r
+ }\r
+\r
+ /* Apply select */\r
+ if (selRegId == CMU_LFACLKSEL_REG)\r
+ {\r
+#if defined( _CMU_LFCLKSEL_LFAE_MASK )\r
+ CMU->LFCLKSEL = (CMU->LFCLKSEL\r
+ & ~(_CMU_LFCLKSEL_LFA_MASK | _CMU_LFCLKSEL_LFAE_MASK))\r
+ | (tmp << _CMU_LFCLKSEL_LFA_SHIFT)\r
+ | (lfExtended << _CMU_LFCLKSEL_LFAE_SHIFT);\r
+#else\r
+ CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFA_MASK)\r
+ | (tmp << _CMU_LFCLKSEL_LFA_SHIFT);\r
+#endif\r
+ }\r
+ else\r
+ {\r
+#if defined( _CMU_LFCLKSEL_LFBE_MASK )\r
+ CMU->LFCLKSEL = (CMU->LFCLKSEL\r
+ & ~(_CMU_LFCLKSEL_LFB_MASK | _CMU_LFCLKSEL_LFBE_MASK))\r
+ | (tmp << _CMU_LFCLKSEL_LFB_SHIFT)\r
+ | (lfExtended << _CMU_LFCLKSEL_LFBE_SHIFT);\r
+#else\r
+ CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFB_MASK)\r
+ | (tmp << _CMU_LFCLKSEL_LFB_SHIFT);\r
+#endif\r
+ }\r
+ break;\r
+\r
+#if defined( _CMU_LFCLKSEL_LFC_MASK )\r
+ case CMU_LFCCLKSEL_REG:\r
+ switch(ref)\r
+ {\r
+ case cmuSelect_Disabled:\r
+ tmp = _CMU_LFCLKSEL_LFA_DISABLED;\r
+ break;\r
+\r
+ case cmuSelect_LFXO:\r
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
+ CMU_OscillatorEnable(cmuOsc_LFXO, true, true);\r
+ tmp = _CMU_LFCLKSEL_LFC_LFXO;\r
+ break;\r
+\r
+ case cmuSelect_LFRCO:\r
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
+ CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);\r
+ tmp = _CMU_LFCLKSEL_LFC_LFRCO;\r
+ break;\r
+\r
+ default:\r
+ /* Illegal clock source for LFC selected */\r
+ EFM_ASSERT(0);\r
+ return;\r
+ }\r
+\r
+ /* Apply select */\r
+ CMU->LFCLKSEL = (CMU->LFCLKSEL & ~_CMU_LFCLKSEL_LFC_MASK)\r
+ | (tmp << _CMU_LFCLKSEL_LFC_SHIFT);\r
+ break;\r
+#endif\r
+#endif\r
+\r
+#if defined( CMU_DBGCLKSEL_DBG ) || defined( CMU_CTRL_DBGCLK )\r
+ case CMU_DBGCLKSEL_REG:\r
+ switch(ref)\r
+ {\r
+#if defined( CMU_DBGCLKSEL_DBG )\r
+ case cmuSelect_AUXHFRCO:\r
+ /* Select AUXHFRCO as debug clock */\r
+ CMU->DBGCLKSEL = CMU_DBGCLKSEL_DBG_AUXHFRCO;\r
+ break;\r
+\r
+ case cmuSelect_HFCLK:\r
+ /* Select divided HFCLK as debug clock */\r
+ CMU->DBGCLKSEL = CMU_DBGCLKSEL_DBG_HFCLK;\r
+ break;\r
+#endif\r
+\r
+#if defined( CMU_CTRL_DBGCLK )\r
+ case cmuSelect_AUXHFRCO:\r
+ /* Select AUXHFRCO as debug clock */\r
+ CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))\r
+ | CMU_CTRL_DBGCLK_AUXHFRCO;\r
+ break;\r
+\r
+ case cmuSelect_HFCLK:\r
+ /* Select divided HFCLK as debug clock */\r
+ CMU->CTRL = (CMU->CTRL & ~(_CMU_CTRL_DBGCLK_MASK))\r
+ | CMU_CTRL_DBGCLK_HFCLK;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ /* Illegal clock source for debug selected */\r
+ EFM_ASSERT(0);\r
+ return;\r
+ }\r
+ break;\r
+#endif\r
+\r
+#if defined(USB_PRESENT)\r
+ case CMU_USBCCLKSEL_REG:\r
+ switch(ref)\r
+ {\r
+ case cmuSelect_LFXO:\r
+ /* Select LFXO as clock source for USB, can only be used in sleep mode */\r
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
+ CMU_OscillatorEnable(cmuOsc_LFXO, true, true);\r
+\r
+ /* Switch oscillator */\r
+ CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO;\r
+\r
+ /* Wait until clock is activated */\r
+ while((CMU->STATUS & CMU_STATUS_USBCLFXOSEL)==0)\r
+ {\r
+ }\r
+ break;\r
+\r
+ case cmuSelect_LFRCO:\r
+ /* Select LFRCO as clock source for USB, can only be used in sleep mode */\r
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
+ CMU_OscillatorEnable(cmuOsc_LFRCO, true, true);\r
+\r
+ /* Switch oscillator */\r
+ CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO;\r
+\r
+ /* Wait until clock is activated */\r
+ while((CMU->STATUS & CMU_STATUS_USBCLFRCOSEL)==0)\r
+ {\r
+ }\r
+ break;\r
+\r
+#if defined( CMU_STATUS_USBCHFCLKSEL )\r
+ case cmuSelect_HFCLK:\r
+ /* Select undivided HFCLK as clock source for USB */\r
+ /* Oscillator must already be enabled to avoid a core lockup */\r
+ CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;\r
+ /* Wait until clock is activated */\r
+ while((CMU->STATUS & CMU_STATUS_USBCHFCLKSEL)==0)\r
+ {\r
+ }\r
+ break;\r
+#endif\r
+\r
+#if defined( CMU_CMD_USBCCLKSEL_USHFRCO )\r
+ case cmuSelect_USHFRCO:\r
+ /* Select USHFRCO as clock source for USB */\r
+ /* Ensure selected oscillator is enabled, waiting for it to stabilize */\r
+ CMU_OscillatorEnable(cmuOsc_USHFRCO, true, true);\r
+\r
+ /* Switch oscillator */\r
+ CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO;\r
+\r
+ /* Wait until clock is activated */\r
+ while((CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL)==0)\r
+ {\r
+ }\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ /* Illegal clock source for USB */\r
+ EFM_ASSERT(0);\r
+ return;\r
+ }\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * CMU low frequency register synchronization freeze control.\r
+ *\r
+ * @details\r
+ * Some CMU registers requires synchronization into the low frequency (LF)\r
+ * domain. The freeze feature allows for several such registers to be\r
+ * modified before passing them to the LF domain simultaneously (which\r
+ * takes place when the freeze mode is disabled).\r
+ *\r
+ * Another usage scenario of this feature, is when using an API (such\r
+ * as the CMU API) for modifying several bit fields consecutively in the\r
+ * same register. If freeze mode is enabled during this sequence, stalling\r
+ * can be avoided.\r
+ *\r
+ * @note\r
+ * When enabling freeze mode, this function will wait for all current\r
+ * ongoing CMU synchronization to LF domain to complete (Normally\r
+ * synchronization will not be in progress.) However for this reason, when\r
+ * using freeze mode, modifications of registers requiring LF synchronization\r
+ * should be done within one freeze enable/disable block to avoid unecessary\r
+ * stalling.\r
+ *\r
+ * @param[in] enable\r
+ * @li true - enable freeze, modified registers are not propagated to the\r
+ * LF domain\r
+ * @li false - disable freeze, modified registers are propagated to LF\r
+ * domain\r
+ *****************************************************************************/\r
+void CMU_FreezeEnable(bool enable)\r
+{\r
+ if (enable)\r
+ {\r
+ /* Wait for any ongoing LF synchronization to complete. This is just to */\r
+ /* protect against the rare case when a user */\r
+ /* - modifies a register requiring LF sync */\r
+ /* - then enables freeze before LF sync completed */\r
+ /* - then modifies the same register again */\r
+ /* since modifying a register while it is in sync progress should be */\r
+ /* avoided. */\r
+ while (CMU->SYNCBUSY)\r
+ {\r
+ }\r
+\r
+ CMU->FREEZE = CMU_FREEZE_REGFREEZE;\r
+ }\r
+ else\r
+ {\r
+ CMU->FREEZE = 0;\r
+ }\r
+}\r
+\r
+\r
+#if defined( _CMU_HFRCOCTRL_BAND_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get HFRCO band in use.\r
+ *\r
+ * @return\r
+ * HFRCO band in use.\r
+ ******************************************************************************/\r
+CMU_HFRCOBand_TypeDef CMU_HFRCOBandGet(void)\r
+{\r
+ return (CMU_HFRCOBand_TypeDef)((CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK)\r
+ >> _CMU_HFRCOCTRL_BAND_SHIFT);\r
+}\r
+#endif /* _CMU_HFRCOCTRL_BAND_MASK */\r
+\r
+\r
+#if defined( _CMU_HFRCOCTRL_BAND_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set HFRCO band and the tuning value based on the value in the calibration\r
+ * table made during production.\r
+ *\r
+ * @param[in] band\r
+ * HFRCO band to activate.\r
+ ******************************************************************************/\r
+void CMU_HFRCOBandSet(CMU_HFRCOBand_TypeDef band)\r
+{\r
+ uint32_t tuning;\r
+ uint32_t freq;\r
+ CMU_Select_TypeDef osc;\r
+\r
+ /* Read tuning value from calibration table */\r
+ switch (band)\r
+ {\r
+ case cmuHFRCOBand_1MHz:\r
+ tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND1_MASK)\r
+ >> _DEVINFO_HFRCOCAL0_BAND1_SHIFT;\r
+ break;\r
+\r
+ case cmuHFRCOBand_7MHz:\r
+ tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND7_MASK)\r
+ >> _DEVINFO_HFRCOCAL0_BAND7_SHIFT;\r
+ break;\r
+\r
+ case cmuHFRCOBand_11MHz:\r
+ tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND11_MASK)\r
+ >> _DEVINFO_HFRCOCAL0_BAND11_SHIFT;\r
+ break;\r
+\r
+ case cmuHFRCOBand_14MHz:\r
+ tuning = (DEVINFO->HFRCOCAL0 & _DEVINFO_HFRCOCAL0_BAND14_MASK)\r
+ >> _DEVINFO_HFRCOCAL0_BAND14_SHIFT;\r
+ break;\r
+\r
+ case cmuHFRCOBand_21MHz:\r
+ tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND21_MASK)\r
+ >> _DEVINFO_HFRCOCAL1_BAND21_SHIFT;\r
+ break;\r
+\r
+#if defined( _CMU_HFRCOCTRL_BAND_28MHZ )\r
+ case cmuHFRCOBand_28MHz:\r
+ tuning = (DEVINFO->HFRCOCAL1 & _DEVINFO_HFRCOCAL1_BAND28_MASK)\r
+ >> _DEVINFO_HFRCOCAL1_BAND28_SHIFT;\r
+ break;\r
+#endif\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ return;\r
+ }\r
+\r
+ /* If HFRCO is used for core clock, we have to consider flash access WS. */\r
+ osc = CMU_ClockSelectGet(cmuClock_HF);\r
+ if (osc == cmuSelect_HFRCO)\r
+ {\r
+ /* Configure worst case wait states for flash access before setting divider */\r
+ flashWaitStateMax();\r
+ }\r
+\r
+ /* Set band/tuning */\r
+ CMU->HFRCOCTRL = (CMU->HFRCOCTRL &\r
+ ~(_CMU_HFRCOCTRL_BAND_MASK | _CMU_HFRCOCTRL_TUNING_MASK))\r
+ | (band << _CMU_HFRCOCTRL_BAND_SHIFT)\r
+ | (tuning << _CMU_HFRCOCTRL_TUNING_SHIFT);\r
+\r
+ /* If HFRCO is used for core clock, optimize flash WS */\r
+ if (osc == cmuSelect_HFRCO)\r
+ {\r
+ /* Update CMSIS core clock variable and get current core clock */\r
+ /* (The function will update the global variable) */\r
+ /* NOTE! We need at least 21 cycles before setting zero wait state to flash */\r
+ /* (i.e. WS0) when going from the 28MHz to 1MHz in the HFRCO band */\r
+ freq = SystemCoreClockGet();\r
+\r
+ /* Optimize flash access wait state setting for current core clk */\r
+ flashWaitStateControl(freq);\r
+ }\r
+}\r
+#endif /* _CMU_HFRCOCTRL_BAND_MASK */\r
+\r
+\r
+#if defined( _CMU_HFRCOCTRL_FREQRANGE_MASK )\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Get a pointer to the HFRCO frequency calibration word in DEVINFO\r
+ *\r
+ * @param[in] freq\r
+ * Frequency in Hz\r
+ *\r
+ * @return\r
+ * HFRCO calibration word for a given frequency\r
+ *****************************************************************************/\r
+static uint32_t CMU_HFRCODevinfoGet(CMU_HFRCOFreq_TypeDef freq)\r
+{\r
+ switch (freq)\r
+ {\r
+ /* 1, 2 and 4MHz share the same calibration word */\r
+ case cmuHFRCOFreq_1M0Hz:\r
+ case cmuHFRCOFreq_2M0Hz:\r
+ case cmuHFRCOFreq_4M0Hz:\r
+ return DEVINFO->HFRCOCAL0;\r
+\r
+ case cmuHFRCOFreq_7M0Hz:\r
+ return DEVINFO->HFRCOCAL3;\r
+\r
+ case cmuHFRCOFreq_13M0Hz:\r
+ return DEVINFO->HFRCOCAL6;\r
+\r
+ case cmuHFRCOFreq_16M0Hz:\r
+ return DEVINFO->HFRCOCAL7;\r
+\r
+ case cmuHFRCOFreq_19M0Hz:\r
+ return DEVINFO->HFRCOCAL8;\r
+\r
+ case cmuHFRCOFreq_26M0Hz:\r
+ return DEVINFO->HFRCOCAL10;\r
+\r
+ case cmuHFRCOFreq_32M0Hz:\r
+ return DEVINFO->HFRCOCAL11;\r
+\r
+ case cmuHFRCOFreq_38M0Hz:\r
+ return DEVINFO->HFRCOCAL12;\r
+\r
+ default: /* cmuHFRCOFreq_UserDefined */\r
+ return 0;\r
+ }\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get HFRCO frequency enumeration in use\r
+ *\r
+ * @return\r
+ * HFRCO frequency enumeration in use\r
+ ******************************************************************************/\r
+CMU_HFRCOFreq_TypeDef CMU_HFRCOFreqGet(void)\r
+{\r
+ return (CMU_HFRCOFreq_TypeDef)SystemHfrcoFreq;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set HFRCO calibration for the selected target frequency\r
+ *\r
+ * @param[in] freq\r
+ * HFRCO frequency band to set\r
+ ******************************************************************************/\r
+void CMU_HFRCOFreqSet(CMU_HFRCOFreq_TypeDef freq)\r
+{\r
+ uint32_t freqCal;\r
+\r
+ /* Get DEVINFO index, set CMSIS frequency SystemHfrcoFreq */\r
+ freqCal = CMU_HFRCODevinfoGet(freq);\r
+ EFM_ASSERT((freqCal != 0) && (freqCal != UINT_MAX));\r
+ SystemHfrcoFreq = (uint32_t)freq;\r
+\r
+ /* Set max wait-states while changing core clock */\r
+ if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO)\r
+ {\r
+ flashWaitStateMax();\r
+ }\r
+\r
+ /* Wait for any previous sync to complete, and then set calibration data\r
+ for the selected frequency. */\r
+ while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_HFRCOBSY_SHIFT));\r
+\r
+ /* Check for valid calibration data */\r
+ EFM_ASSERT(freqCal != UINT_MAX);\r
+\r
+ /* Set divider in HFRCOCTRL for 1, 2 and 4MHz */\r
+ switch(freq)\r
+ {\r
+ case cmuHFRCOFreq_1M0Hz:\r
+ freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)\r
+ | CMU_HFRCOCTRL_CLKDIV_DIV4;\r
+ break;\r
+\r
+ case cmuHFRCOFreq_2M0Hz:\r
+ freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)\r
+ | CMU_HFRCOCTRL_CLKDIV_DIV2;\r
+ break;\r
+\r
+ case cmuHFRCOFreq_4M0Hz:\r
+ freqCal = (freqCal & ~_CMU_HFRCOCTRL_CLKDIV_MASK)\r
+ | CMU_HFRCOCTRL_CLKDIV_DIV1;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ CMU->HFRCOCTRL = freqCal;\r
+\r
+ /* Optimize flash access wait-state configuration for this frequency, */\r
+ /* if HFRCO is reference for core clock. */\r
+ if (CMU_ClockSelectGet(cmuClock_HF) == cmuSelect_HFRCO)\r
+ {\r
+ flashWaitStateControl((uint32_t)freq);\r
+ }\r
+}\r
+#endif /* _CMU_HFRCOCTRL_FREQRANGE_MASK */\r
+\r
+#if defined( _CMU_HFRCOCTRL_SUDELAY_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the HFRCO startup delay.\r
+ *\r
+ * @details\r
+ * Please refer to the reference manual for further details.\r
+ *\r
+ * @return\r
+ * The startup delay in use.\r
+ ******************************************************************************/\r
+uint32_t CMU_HFRCOStartupDelayGet(void)\r
+{\r
+ return (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_SUDELAY_MASK)\r
+ >> _CMU_HFRCOCTRL_SUDELAY_SHIFT;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set the HFRCO startup delay.\r
+ *\r
+ * @details\r
+ * Please refer to the reference manual for further details.\r
+ *\r
+ * @param[in] delay\r
+ * The startup delay to set (<= 31).\r
+ ******************************************************************************/\r
+void CMU_HFRCOStartupDelaySet(uint32_t delay)\r
+{\r
+ EFM_ASSERT(delay <= 31);\r
+\r
+ delay &= _CMU_HFRCOCTRL_SUDELAY_MASK >> _CMU_HFRCOCTRL_SUDELAY_SHIFT;\r
+ CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_SUDELAY_MASK))\r
+ | (delay << _CMU_HFRCOCTRL_SUDELAY_SHIFT);\r
+}\r
+#endif\r
+\r
+\r
+#if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Enable or disable HFXO autostart\r
+ *\r
+ * @param[in] enRACStartSel\r
+ * If true, HFXO is automatically started and selected upon RAC wakeup.\r
+ * If false, HFXO is not started or selected automatically upon RAC wakeup.\r
+ *\r
+ * @param[in] enEM0EM1Start\r
+ * If true, HFXO is automatically started upon entering EM0/EM1 entry from\r
+ * EM2/EM3. HFXO selection has to be handled by the user.\r
+ * If false, HFXO is not started automatically when entering EM0/EM1.\r
+ *\r
+ * @param[in] enEM0EM1StartSel\r
+ * If true, HFXO is automatically started and immediately selected upon\r
+ * entering EM0/EM1 entry from EM2/EM3. Note that this option stalls the use of\r
+ * HFSRCCLK until HFXO becomes ready.\r
+ * If false, HFXO is not started or selected automatically when entering\r
+ * EM0/EM1.\r
+ ******************************************************************************/\r
+void CMU_HFXOAutostartEnable(bool enRACStartSel,\r
+ bool enEM0EM1Start,\r
+ bool enEM0EM1StartSel)\r
+{\r
+ uint32_t hfxoCtrl;\r
+ hfxoCtrl = CMU->HFXOCTRL & ~(_CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK\r
+ | _CMU_HFXOCTRL_AUTOSTARTEM0EM1_MASK\r
+ | _CMU_HFXOCTRL_AUTOSTARTSELEM0EM1_MASK);\r
+\r
+ hfxoCtrl |= (enRACStartSel ? CMU_HFXOCTRL_AUTOSTARTRDYSELRAC : 0)\r
+ | (enEM0EM1Start ? CMU_HFXOCTRL_AUTOSTARTEM0EM1 : 0)\r
+ | (enEM0EM1StartSel ? CMU_HFXOCTRL_AUTOSTARTSELEM0EM1 : 0);\r
+\r
+ CMU->HFXOCTRL = hfxoCtrl;\r
+}\r
+#endif /* _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK */\r
+\r
+\r
+#if defined( _CMU_HFXOCTRL_MASK )\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Set HFXO control registers\r
+ *\r
+ * @note\r
+ * HFXO configuration should be obtained from a configuration tool,\r
+ * app note or xtal datasheet. This function disables the HFXO to ensure\r
+ * a valid state before update.\r
+ *\r
+ * @param[in] hfxoInit\r
+ * HFXO setup parameters\r
+ *****************************************************************************/\r
+void CMU_HFXOInit(CMU_HFXOInit_TypeDef *hfxoInit)\r
+{\r
+ uint32_t ishReg;\r
+ uint32_t ishMax;\r
+\r
+ /* Do not disable HFXO if it is currently selected as HF/Core clock */\r
+ EFM_ASSERT(CMU_ClockSelectGet(cmuClock_HF) != cmuSelect_HFXO);\r
+\r
+ /* HFXO must be disabled before reconfiguration */\r
+ CMU_OscillatorEnable(cmuOsc_HFXO, false, false);\r
+\r
+ /* Apply control settings */\r
+ BUS_RegMaskedWrite(&CMU->HFXOCTRL,\r
+ _CMU_HFXOCTRL_LOWPOWER_MASK\r
+#if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK )\r
+ | _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK\r
+#endif\r
+ | _CMU_HFXOCTRL_AUTOSTARTEM0EM1_MASK\r
+ | _CMU_HFXOCTRL_AUTOSTARTSELEM0EM1_MASK,\r
+ (hfxoInit->lowPowerMode\r
+ ? CMU_HFXOCTRL_LOWPOWER : 0)\r
+#if defined( _CMU_HFXOCTRL_AUTOSTARTRDYSELRAC_MASK )\r
+ | (hfxoInit->autoStartSelOnRacWakeup\r
+ ? CMU_HFXOCTRL_AUTOSTARTRDYSELRAC : 0)\r
+#endif\r
+ | (hfxoInit->autoStartEm01\r
+ ? CMU_HFXOCTRL_AUTOSTARTEM0EM1 : 0)\r
+ | (hfxoInit->autoSelEm01\r
+ ? CMU_HFXOCTRL_AUTOSTARTSELEM0EM1 : 0));\r
+\r
+ /* Set XTAL tuning parameters */\r
+\r
+ /* Set peak detection threshold in CMU_HFXOCTRL1_PEAKDETTHR[2:0] (hidden). */\r
+ BUS_RegMaskedWrite((volatile uint32_t *)0x400E4028, 0x7, hfxoInit->thresholdPeakDetect);\r
+\r
+ /* Set tuning for startup and steady state */\r
+ BUS_RegMaskedWrite(&CMU->HFXOSTARTUPCTRL,\r
+ _CMU_HFXOSTARTUPCTRL_CTUNE_MASK\r
+ | _CMU_HFXOSTARTUPCTRL_REGISHWARM_MASK\r
+ | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK\r
+ | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCOREWARM_MASK,\r
+ (hfxoInit->ctuneStartup\r
+ << _CMU_HFXOSTARTUPCTRL_CTUNE_SHIFT)\r
+ | (hfxoInit->regIshStartup\r
+ << _CMU_HFXOSTARTUPCTRL_REGISHWARM_SHIFT)\r
+ | (hfxoInit->xoCoreBiasTrimStartup\r
+ << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT)\r
+ | 0x4 /* Recommended tuning */\r
+ << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCOREWARM_SHIFT);\r
+\r
+ /* Adjust CMU_HFXOSTEADYSTATECTRL_REGISHUPPER according to regIshSteadyState.\r
+ Saturate at max value. Please see the reference manual page 433 and Section\r
+ 12.5.10 CMU_HFXOSTEADYSTATECTRL for more details. */\r
+ ishReg = hfxoInit->regIshSteadyState + 3;\r
+ ishMax = _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK\r
+ >> _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_SHIFT;\r
+ ishReg = ishReg > ishMax ? ishMax : ishReg;\r
+ ishReg <<= _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_SHIFT;\r
+\r
+ BUS_RegMaskedWrite(&CMU->HFXOSTEADYSTATECTRL,\r
+ _CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK\r
+ | _CMU_HFXOSTEADYSTATECTRL_REGISH_MASK\r
+ | _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK\r
+ | _CMU_HFXOSTEADYSTATECTRL_REGISHUPPER_MASK,\r
+ (hfxoInit->ctuneSteadyState\r
+ << _CMU_HFXOSTEADYSTATECTRL_CTUNE_SHIFT)\r
+ | (hfxoInit->regIshSteadyState\r
+ << _CMU_HFXOSTEADYSTATECTRL_REGISH_SHIFT)\r
+ | (hfxoInit->xoCoreBiasTrimSteadyState\r
+ << _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_SHIFT)\r
+ | ishReg);\r
+\r
+ /* Set timeouts */\r
+ BUS_RegMaskedWrite(&CMU->HFXOTIMEOUTCTRL,\r
+ _CMU_HFXOTIMEOUTCTRL_SHUNTOPTTIMEOUT_MASK\r
+ | _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_MASK\r
+ | _CMU_HFXOTIMEOUTCTRL_WARMSTEADYTIMEOUT_MASK\r
+ | _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_MASK\r
+ | _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_MASK,\r
+ (hfxoInit->timeoutShuntOptimization\r
+ << _CMU_HFXOTIMEOUTCTRL_SHUNTOPTTIMEOUT_SHIFT)\r
+ | (hfxoInit->timeoutPeakDetect\r
+ << _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_SHIFT)\r
+ | (hfxoInit->timeoutWarmSteady\r
+ << _CMU_HFXOTIMEOUTCTRL_WARMSTEADYTIMEOUT_SHIFT)\r
+ | (hfxoInit->timeoutSteady\r
+ << _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_SHIFT)\r
+ | (hfxoInit->timeoutStartup\r
+ << _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_SHIFT));\r
+}\r
+#endif\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the LCD framerate divisor (FDIV) setting.\r
+ *\r
+ * @return\r
+ * The LCD framerate divisor.\r
+ ******************************************************************************/\r
+uint32_t CMU_LCDClkFDIVGet(void)\r
+{\r
+#if defined( LCD_PRESENT )\r
+ return (CMU->LCDCTRL & _CMU_LCDCTRL_FDIV_MASK) >> _CMU_LCDCTRL_FDIV_SHIFT;\r
+#else\r
+ return 0;\r
+#endif /* defined(LCD_PRESENT) */\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set the LCD framerate divisor (FDIV) setting.\r
+ *\r
+ * @note\r
+ * The FDIV field (CMU LCDCTRL register) should only be modified while the\r
+ * LCD module is clock disabled (CMU LFACLKEN0.LCD bit is 0). This function\r
+ * will NOT modify FDIV if the LCD module clock is enabled. Please refer to\r
+ * CMU_ClockEnable() for disabling/enabling LCD clock.\r
+ *\r
+ * @param[in] div\r
+ * The FDIV setting to use.\r
+ ******************************************************************************/\r
+void CMU_LCDClkFDIVSet(uint32_t div)\r
+{\r
+#if defined( LCD_PRESENT )\r
+ EFM_ASSERT(div <= cmuClkDiv_128);\r
+\r
+ /* Do not allow modification if LCD clock enabled */\r
+ if (CMU->LFACLKEN0 & CMU_LFACLKEN0_LCD)\r
+ {\r
+ return;\r
+ }\r
+\r
+ div <<= _CMU_LCDCTRL_FDIV_SHIFT;\r
+ div &= _CMU_LCDCTRL_FDIV_MASK;\r
+ CMU->LCDCTRL = (CMU->LCDCTRL & ~_CMU_LCDCTRL_FDIV_MASK) | div;\r
+#else\r
+ (void)div; /* Unused parameter */\r
+#endif /* defined(LCD_PRESENT) */\r
+}\r
+\r
+\r
+#if defined( _CMU_LFXOCTRL_MASK )\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Set LFXO control registers\r
+ *\r
+ * @note\r
+ * LFXO configuration should be obtained from a configuration tool,\r
+ * app note or xtal datasheet. This function disables the LFXO to ensure\r
+ * a valid state before update.\r
+ *\r
+ * @param[in] lfxoInit\r
+ * LFXO setup parameters\r
+ *****************************************************************************/\r
+void CMU_LFXOInit(CMU_LFXOInit_TypeDef *lfxoInit)\r
+{\r
+ /* Do not disable LFXO if it is currently selected as HF/Core clock */\r
+ EFM_ASSERT(CMU_ClockSelectGet(cmuClock_HF) != cmuSelect_LFXO);\r
+\r
+ /* LFXO must be disabled before reconfiguration */\r
+ CMU_OscillatorEnable(cmuOsc_LFXO, false, false);\r
+\r
+ BUS_RegMaskedWrite(&CMU->LFXOCTRL,\r
+ _CMU_LFXOCTRL_TUNING_MASK\r
+ | _CMU_LFXOCTRL_GAIN_MASK\r
+ | _CMU_LFXOCTRL_TIMEOUT_MASK,\r
+ (lfxoInit->ctune << _CMU_LFXOCTRL_TUNING_SHIFT)\r
+ | (lfxoInit->gain << _CMU_LFXOCTRL_GAIN_SHIFT)\r
+ | (lfxoInit->timeout << _CMU_LFXOCTRL_TIMEOUT_SHIFT));\r
+}\r
+#endif\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Enable/disable oscillator.\r
+ *\r
+ * @note\r
+ * WARNING: When this function is called to disable either cmuOsc_LFXO or\r
+ * cmuOsc_HFXO the LFXOMODE or HFXOMODE fields of the CMU_CTRL register\r
+ * are reset to the reset value. I.e. if external clock sources are selected\r
+ * in either LFXOMODE or HFXOMODE fields, the configuration will be cleared\r
+ * and needs to be reconfigured if needed later.\r
+ *\r
+ * @param[in] osc\r
+ * The oscillator to enable/disable.\r
+ *\r
+ * @param[in] enable\r
+ * @li true - enable specified oscillator.\r
+ * @li false - disable specified oscillator.\r
+ *\r
+ * @param[in] wait\r
+ * Only used if @p enable is true.\r
+ * @li true - wait for oscillator start-up time to timeout before returning.\r
+ * @li false - do not wait for oscillator start-up time to timeout before\r
+ * returning.\r
+ ******************************************************************************/\r
+void CMU_OscillatorEnable(CMU_Osc_TypeDef osc, bool enable, bool wait)\r
+{\r
+ uint32_t rdyBitPos;\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ uint32_t ensBitPos;\r
+#endif\r
+ uint32_t enBit;\r
+ uint32_t disBit;\r
+\r
+ switch (osc)\r
+ {\r
+ case cmuOsc_HFRCO:\r
+ enBit = CMU_OSCENCMD_HFRCOEN;\r
+ disBit = CMU_OSCENCMD_HFRCODIS;\r
+ rdyBitPos = _CMU_STATUS_HFRCORDY_SHIFT;\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ ensBitPos = _CMU_STATUS_HFRCOENS_SHIFT;\r
+#endif\r
+ break;\r
+\r
+ case cmuOsc_HFXO:\r
+ enBit = CMU_OSCENCMD_HFXOEN;\r
+ disBit = CMU_OSCENCMD_HFXODIS;\r
+ rdyBitPos = _CMU_STATUS_HFXORDY_SHIFT;\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ ensBitPos = _CMU_STATUS_HFXOENS_SHIFT;\r
+#endif\r
+ break;\r
+\r
+ case cmuOsc_AUXHFRCO:\r
+ enBit = CMU_OSCENCMD_AUXHFRCOEN;\r
+ disBit = CMU_OSCENCMD_AUXHFRCODIS;\r
+ rdyBitPos = _CMU_STATUS_AUXHFRCORDY_SHIFT;\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ ensBitPos = _CMU_STATUS_AUXHFRCOENS_SHIFT;\r
+#endif\r
+ break;\r
+\r
+ case cmuOsc_LFRCO:\r
+ enBit = CMU_OSCENCMD_LFRCOEN;\r
+ disBit = CMU_OSCENCMD_LFRCODIS;\r
+ rdyBitPos = _CMU_STATUS_LFRCORDY_SHIFT;\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ ensBitPos = _CMU_STATUS_LFRCOENS_SHIFT;\r
+#endif\r
+ break;\r
+\r
+ case cmuOsc_LFXO:\r
+ enBit = CMU_OSCENCMD_LFXOEN;\r
+ disBit = CMU_OSCENCMD_LFXODIS;\r
+ rdyBitPos = _CMU_STATUS_LFXORDY_SHIFT;\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ ensBitPos = _CMU_STATUS_LFXOENS_SHIFT;\r
+#endif\r
+ break;\r
+\r
+#if defined( _CMU_STATUS_USHFRCOENS_MASK )\r
+ case cmuOsc_USHFRCO:\r
+ enBit = CMU_OSCENCMD_USHFRCOEN;\r
+ disBit = CMU_OSCENCMD_USHFRCODIS;\r
+ rdyBitPos = _CMU_STATUS_USHFRCORDY_SHIFT;\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ ensBitPos = _CMU_STATUS_USHFRCOENS_SHIFT;\r
+#endif\r
+ break;\r
+#endif\r
+\r
+#if defined( CMU_LFCLKSEL_LFAE_ULFRCO )\r
+ case cmuOsc_ULFRCO:\r
+ /* ULFRCO is always enabled, and cannot be turned off */\r
+ return;\r
+#endif\r
+\r
+ default:\r
+ /* Undefined clock source */\r
+ EFM_ASSERT(0);\r
+ return;\r
+ }\r
+\r
+ if (enable)\r
+ {\r
+ CMU->OSCENCMD = enBit;\r
+\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ /* Always wait for ENS to go high */\r
+ while (!BUS_RegBitRead(&CMU->STATUS, ensBitPos))\r
+ {\r
+ }\r
+#endif\r
+\r
+ /* Wait for clock to become ready after enable */\r
+ if (wait)\r
+ {\r
+ while (!BUS_RegBitRead(&CMU->STATUS, rdyBitPos));\r
+#if defined( _CMU_STATUS_HFXOSHUNTOPTRDY_MASK )\r
+ /* Wait for shunt current optimization to complete */\r
+ if ((osc == cmuOsc_HFXO)\r
+ && (BUS_RegMaskedRead(&CMU->HFXOCTRL,\r
+ _CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_MASK)\r
+ == CMU_HFXOCTRL_PEAKDETSHUNTOPTMODE_AUTOCMD))\r
+ {\r
+ while (!BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_HFXOSHUNTOPTRDY_SHIFT))\r
+ {\r
+ }\r
+ /* Assert on failed peak detection. Incorrect HFXO initialization parameters\r
+ caused startup to fail. Please review parameters. */\r
+ EFM_ASSERT(BUS_RegBitRead(&CMU->STATUS, _CMU_STATUS_HFXOPEAKDETRDY_SHIFT));\r
+ }\r
+#endif\r
+ }\r
+ }\r
+ else\r
+ {\r
+ CMU->OSCENCMD = disBit;\r
+\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ /* Always wait for ENS to go low */\r
+ while (BUS_RegBitRead(&CMU->STATUS, ensBitPos))\r
+ {\r
+ }\r
+#endif\r
+ }\r
+\r
+ /* Keep EMU module informed */\r
+ EMU_UpdateOscConfig();\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get oscillator frequency tuning setting.\r
+ *\r
+ * @param[in] osc\r
+ * Oscillator to get tuning value for, one of:\r
+ * @li #cmuOsc_LFRCO\r
+ * @li #cmuOsc_HFRCO\r
+ * @li #cmuOsc_AUXHFRCO\r
+ *\r
+ * @return\r
+ * The oscillator frequency tuning setting in use.\r
+ ******************************************************************************/\r
+uint32_t CMU_OscillatorTuningGet(CMU_Osc_TypeDef osc)\r
+{\r
+ uint32_t ret;\r
+\r
+ switch (osc)\r
+ {\r
+ case cmuOsc_LFRCO:\r
+ ret = (CMU->LFRCOCTRL & _CMU_LFRCOCTRL_TUNING_MASK)\r
+ >> _CMU_LFRCOCTRL_TUNING_SHIFT;\r
+ break;\r
+\r
+ case cmuOsc_HFRCO:\r
+ ret = (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_TUNING_MASK)\r
+ >> _CMU_HFRCOCTRL_TUNING_SHIFT;\r
+ break;\r
+\r
+ case cmuOsc_AUXHFRCO:\r
+ ret = (CMU->AUXHFRCOCTRL & _CMU_AUXHFRCOCTRL_TUNING_MASK)\r
+ >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT;\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ ret = 0;\r
+ break;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set the oscillator frequency tuning control.\r
+ *\r
+ * @note\r
+ * Oscillator tuning is done during production, and the tuning value is\r
+ * automatically loaded after a reset. Changing the tuning value from the\r
+ * calibrated value is for more advanced use.\r
+ *\r
+ * @param[in] osc\r
+ * Oscillator to set tuning value for, one of:\r
+ * @li #cmuOsc_LFRCO\r
+ * @li #cmuOsc_HFRCO\r
+ * @li #cmuOsc_AUXHFRCO\r
+ *\r
+ * @param[in] val\r
+ * The oscillator frequency tuning setting to use.\r
+ ******************************************************************************/\r
+void CMU_OscillatorTuningSet(CMU_Osc_TypeDef osc, uint32_t val)\r
+{\r
+ switch (osc)\r
+ {\r
+ case cmuOsc_LFRCO:\r
+ EFM_ASSERT(val <= (_CMU_LFRCOCTRL_TUNING_MASK\r
+ >> _CMU_LFRCOCTRL_TUNING_SHIFT));\r
+ val &= (_CMU_LFRCOCTRL_TUNING_MASK >> _CMU_LFRCOCTRL_TUNING_SHIFT);\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_LFRCOBSY_SHIFT));\r
+#endif\r
+ CMU->LFRCOCTRL = (CMU->LFRCOCTRL & ~(_CMU_LFRCOCTRL_TUNING_MASK))\r
+ | (val << _CMU_LFRCOCTRL_TUNING_SHIFT);\r
+ break;\r
+\r
+ case cmuOsc_HFRCO:\r
+ EFM_ASSERT(val <= (_CMU_HFRCOCTRL_TUNING_MASK\r
+ >> _CMU_HFRCOCTRL_TUNING_SHIFT));\r
+ val &= (_CMU_HFRCOCTRL_TUNING_MASK >> _CMU_HFRCOCTRL_TUNING_SHIFT);\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_HFRCOBSY_SHIFT))\r
+ {\r
+ }\r
+#endif\r
+ CMU->HFRCOCTRL = (CMU->HFRCOCTRL & ~(_CMU_HFRCOCTRL_TUNING_MASK))\r
+ | (val << _CMU_HFRCOCTRL_TUNING_SHIFT);\r
+ break;\r
+\r
+ case cmuOsc_AUXHFRCO:\r
+ EFM_ASSERT(val <= (_CMU_AUXHFRCOCTRL_TUNING_MASK\r
+ >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT));\r
+ val &= (_CMU_AUXHFRCOCTRL_TUNING_MASK >> _CMU_AUXHFRCOCTRL_TUNING_SHIFT);\r
+#if defined( _SILICON_LABS_32B_PLATFORM_2 )\r
+ while(BUS_RegBitRead(&CMU->SYNCBUSY, _CMU_SYNCBUSY_AUXHFRCOBSY_SHIFT))\r
+ {\r
+ }\r
+#endif\r
+ CMU->AUXHFRCOCTRL = (CMU->AUXHFRCOCTRL & ~(_CMU_AUXHFRCOCTRL_TUNING_MASK))\r
+ | (val << _CMU_AUXHFRCOCTRL_TUNING_SHIFT);\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ break;\r
+ }\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Determine if currently selected PCNTn clock used is external or LFBCLK.\r
+ *\r
+ * @param[in] instance\r
+ * PCNT instance number to get currently selected clock source for.\r
+ *\r
+ * @return\r
+ * @li true - selected clock is external clock.\r
+ * @li false - selected clock is LFBCLK.\r
+ *****************************************************************************/\r
+bool CMU_PCNTClockExternalGet(unsigned int instance)\r
+{\r
+ uint32_t setting;\r
+\r
+ switch (instance)\r
+ {\r
+#if defined( _CMU_PCNTCTRL_PCNT0CLKEN_MASK )\r
+ case 0:\r
+ setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT0CLKSEL_PCNT0S0;\r
+ break;\r
+\r
+#if defined( _CMU_PCNTCTRL_PCNT1CLKEN_MASK )\r
+ case 1:\r
+ setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT1CLKSEL_PCNT1S0;\r
+ break;\r
+\r
+#if defined( _CMU_PCNTCTRL_PCNT2CLKEN_MASK )\r
+ case 2:\r
+ setting = CMU->PCNTCTRL & CMU_PCNTCTRL_PCNT2CLKSEL_PCNT2S0;\r
+ break;\r
+#endif\r
+#endif\r
+#endif\r
+\r
+ default:\r
+ setting = 0;\r
+ break;\r
+ }\r
+ return (setting ? true : false);\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Select PCNTn clock.\r
+ *\r
+ * @param[in] instance\r
+ * PCNT instance number to set selected clock source for.\r
+ *\r
+ * @param[in] external\r
+ * Set to true to select external clock, false to select LFBCLK.\r
+ *****************************************************************************/\r
+void CMU_PCNTClockExternalSet(unsigned int instance, bool external)\r
+{\r
+#if defined( PCNT_PRESENT )\r
+ uint32_t setting = 0;\r
+\r
+ EFM_ASSERT(instance < PCNT_COUNT);\r
+\r
+ if (external)\r
+ {\r
+ setting = 1;\r
+ }\r
+\r
+ BUS_RegBitWrite(&(CMU->PCNTCTRL), (instance * 2) + 1, setting);\r
+\r
+#else\r
+ (void)instance; /* Unused parameter */\r
+ (void)external; /* Unused parameter */\r
+#endif\r
+}\r
+\r
+\r
+#if defined( _CMU_USHFRCOCONF_BAND_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get USHFRCO band in use.\r
+ *\r
+ * @return\r
+ * USHFRCO band in use.\r
+ ******************************************************************************/\r
+CMU_USHFRCOBand_TypeDef CMU_USHFRCOBandGet(void)\r
+{\r
+ return (CMU_USHFRCOBand_TypeDef)((CMU->USHFRCOCONF\r
+ & _CMU_USHFRCOCONF_BAND_MASK)\r
+ >> _CMU_USHFRCOCONF_BAND_SHIFT);\r
+}\r
+#endif\r
+\r
+#if defined( _CMU_USHFRCOCONF_BAND_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set USHFRCO band to use.\r
+ *\r
+ * @param[in] band\r
+ * USHFRCO band to activate.\r
+ ******************************************************************************/\r
+void CMU_USHFRCOBandSet(CMU_USHFRCOBand_TypeDef band)\r
+{\r
+ uint32_t tuning;\r
+ uint32_t fineTuning;\r
+ CMU_Select_TypeDef osc;\r
+\r
+ /* Cannot switch band if USHFRCO is already selected as HF clock. */\r
+ osc = CMU_ClockSelectGet(cmuClock_HF);\r
+ EFM_ASSERT((CMU_USHFRCOBandGet() != band) && (osc != cmuSelect_USHFRCO));\r
+\r
+ /* Read tuning value from calibration table */\r
+ switch (band)\r
+ {\r
+ case cmuUSHFRCOBand_24MHz:\r
+ tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND24_TUNING_MASK)\r
+ >> _DEVINFO_USHFRCOCAL0_BAND24_TUNING_SHIFT;\r
+ fineTuning = (DEVINFO->USHFRCOCAL0\r
+ & _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_MASK)\r
+ >> _DEVINFO_USHFRCOCAL0_BAND24_FINETUNING_SHIFT;\r
+ break;\r
+\r
+ case cmuUSHFRCOBand_48MHz:\r
+ tuning = (DEVINFO->USHFRCOCAL0 & _DEVINFO_USHFRCOCAL0_BAND48_TUNING_MASK)\r
+ >> _DEVINFO_USHFRCOCAL0_BAND48_TUNING_SHIFT;\r
+ fineTuning = (DEVINFO->USHFRCOCAL0\r
+ & _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_MASK)\r
+ >> _DEVINFO_USHFRCOCAL0_BAND48_FINETUNING_SHIFT;\r
+ /* Enable the clock divider before switching the band from 24 to 48MHz */\r
+ BUS_RegBitWrite(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 0);\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(0);\r
+ return;\r
+ }\r
+\r
+ /* Set band and tuning */\r
+ CMU->USHFRCOCONF = (CMU->USHFRCOCONF & ~_CMU_USHFRCOCONF_BAND_MASK)\r
+ | (band << _CMU_USHFRCOCONF_BAND_SHIFT);\r
+ CMU->USHFRCOCTRL = (CMU->USHFRCOCTRL & ~_CMU_USHFRCOCTRL_TUNING_MASK)\r
+ | (tuning << _CMU_USHFRCOCTRL_TUNING_SHIFT);\r
+ CMU->USHFRCOTUNE = (CMU->USHFRCOTUNE & ~_CMU_USHFRCOTUNE_FINETUNING_MASK)\r
+ | (fineTuning << _CMU_USHFRCOTUNE_FINETUNING_SHIFT);\r
+\r
+ /* Disable the clock divider after switching the band from 48 to 24MHz */\r
+ if (band == cmuUSHFRCOBand_24MHz)\r
+ {\r
+ BUS_RegBitWrite(&CMU->USHFRCOCONF, _CMU_USHFRCOCONF_USHFRCODIV2DIS_SHIFT, 1);\r
+ }\r
+}\r
+#endif\r
+\r
+\r
+\r
+/** @} (end addtogroup CMU) */\r
+/** @} (end addtogroup EM_Library) */\r
+#endif /* __EM_CMU_H */\r
--- /dev/null
+/***************************************************************************//**\r
+ * @file em_emu.c\r
+ * @brief Energy Management Unit (EMU) Peripheral API\r
+ * @version 4.2.1\r
+ *******************************************************************************\r
+ * @section License\r
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>\r
+ *******************************************************************************\r
+ *\r
+ * Permission is granted to anyone to use this software for any purpose,\r
+ * including commercial applications, and to alter it and redistribute it\r
+ * freely, subject to the following restrictions:\r
+ *\r
+ * 1. The origin of this software must not be misrepresented; you must not\r
+ * claim that you wrote the original software.\r
+ * 2. Altered source versions must be plainly marked as such, and must not be\r
+ * misrepresented as being the original software.\r
+ * 3. This notice may not be removed or altered from any source distribution.\r
+ *\r
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
+ * obligation to support this Software. Silicon Labs is providing the\r
+ * Software "AS IS", with no express or implied warranties of any kind,\r
+ * including, but not limited to, any implied warranties of merchantability\r
+ * or fitness for any particular purpose or warranties against infringement\r
+ * of any proprietary rights of a third party.\r
+ *\r
+ * Silicon Labs will not be liable for any consequential, incidental, or\r
+ * special damages, or any other relief, or for any claim by any third party,\r
+ * arising from your use of this Software.\r
+ *\r
+ ******************************************************************************/\r
+\r
+#include <limits.h>\r
+\r
+#include "em_emu.h"\r
+#if defined( EMU_PRESENT ) && ( EMU_COUNT > 0 )\r
+\r
+#include "em_cmu.h"\r
+#include "em_system.h"\r
+#include "em_assert.h"\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup EM_Library\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup EMU\r
+ * @brief Energy Management Unit (EMU) Peripheral API\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/* Consistency check, since restoring assumes similar bitpositions in */\r
+/* CMU OSCENCMD and STATUS regs */\r
+#if (CMU_STATUS_AUXHFRCOENS != CMU_OSCENCMD_AUXHFRCOEN)\r
+#error Conflict in AUXHFRCOENS and AUXHFRCOEN bitpositions\r
+#endif\r
+#if (CMU_STATUS_HFXOENS != CMU_OSCENCMD_HFXOEN)\r
+#error Conflict in HFXOENS and HFXOEN bitpositions\r
+#endif\r
+#if (CMU_STATUS_LFRCOENS != CMU_OSCENCMD_LFRCOEN)\r
+#error Conflict in LFRCOENS and LFRCOEN bitpositions\r
+#endif\r
+#if (CMU_STATUS_LFXOENS != CMU_OSCENCMD_LFXOEN)\r
+#error Conflict in LFXOENS and LFXOEN bitpositions\r
+#endif\r
+\r
+\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+/* Fix for errata EMU_E107 - non-WIC interrupt masks. */\r
+#if defined( _EFM32_GECKO_FAMILY )\r
+#define ERRATA_FIX_EMU_E107_EN\r
+#define NON_WIC_INT_MASK_0 (~(0x0dfc0323U))\r
+#define NON_WIC_INT_MASK_1 (~(0x0U))\r
+\r
+#elif defined( _EFM32_TINY_FAMILY )\r
+#define ERRATA_FIX_EMU_E107_EN\r
+#define NON_WIC_INT_MASK_0 (~(0x001be323U))\r
+#define NON_WIC_INT_MASK_1 (~(0x0U))\r
+\r
+#elif defined( _EFM32_GIANT_FAMILY )\r
+#define ERRATA_FIX_EMU_E107_EN\r
+#define NON_WIC_INT_MASK_0 (~(0xff020e63U))\r
+#define NON_WIC_INT_MASK_1 (~(0x00000046U))\r
+\r
+#elif defined( _EFM32_WONDER_FAMILY )\r
+#define ERRATA_FIX_EMU_E107_EN\r
+#define NON_WIC_INT_MASK_0 (~(0xff020e63U))\r
+#define NON_WIC_INT_MASK_1 (~(0x00000046U))\r
+\r
+#else\r
+/* Zero Gecko and future families are not affected by errata EMU_E107 */\r
+#endif\r
+\r
+/* Fix for errata EMU_E108 - High Current Consumption on EM4 Entry. */\r
+#if defined( _EFM32_HAPPY_FAMILY )\r
+#define ERRATA_FIX_EMU_E108_EN\r
+#endif\r
+/** @endcond */\r
+\r
+\r
+#if defined( _EMU_DCDCCTRL_MASK )\r
+/* DCDCTODVDD output range min/max */\r
+#define PWRCFG_DCDCTODVDD_VMIN 1200\r
+#define PWRCFG_DCDCTODVDD_VMAX 3000\r
+typedef enum\r
+{\r
+ errataFixDcdcHsInit,\r
+ errataFixDcdcHsTrimSet,\r
+ errataFixDcdcHsLnWaitDone\r
+} errataFixDcdcHs_TypeDef;\r
+errataFixDcdcHs_TypeDef errataFixDcdcHsState = errataFixDcdcHsInit;\r
+#endif\r
+\r
+/*******************************************************************************\r
+ ************************** LOCAL VARIABLES ********************************\r
+ ******************************************************************************/\r
+\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+/**\r
+ * CMU configured oscillator selection and oscillator enable status. When a\r
+ * user configures oscillators, this varaiable shall shadow the configuration.\r
+ * It is used by the EMU module in order to be able to restore the oscillator\r
+ * config after having been in certain energy modes (since HW may automatically\r
+ * alter config when going into an energy mode). It is the responsibility of\r
+ * the CMU module to keep it up-to-date (or a user if not using the CMU API\r
+ * for oscillator control).\r
+ */\r
+static uint32_t cmuStatus;\r
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )\r
+static uint16_t cmuHfclkStatus;\r
+#endif\r
+#if defined( _EMU_DCDCCTRL_MASK )\r
+static uint16_t dcdcMaxCurrent_mA;\r
+static uint16_t dcdcOutput_mVout;\r
+#endif\r
+\r
+/** @endcond */\r
+\r
+\r
+/*******************************************************************************\r
+ ************************** LOCAL FUNCTIONS ********************************\r
+ ******************************************************************************/\r
+\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Restore oscillators and core clock after having been in EM2 or EM3.\r
+ ******************************************************************************/\r
+static void emuRestore(void)\r
+{\r
+ uint32_t oscEnCmd;\r
+ uint32_t cmuLocked;\r
+\r
+ /* Although we could use the CMU API for most of the below handling, we */\r
+ /* would like this function to be as efficient as possible. */\r
+\r
+ /* CMU registers may be locked */\r
+ cmuLocked = CMU->LOCK & CMU_LOCK_LOCKKEY_LOCKED;\r
+ CMU_Unlock();\r
+\r
+ /* AUXHFRCO are automatically disabled (except if using debugger). */\r
+ /* HFRCO, USHFRCO and HFXO are automatically disabled. */\r
+ /* LFRCO/LFXO may be disabled by SW in EM3. */\r
+ /* Restore according to status prior to entering energy mode. */\r
+ oscEnCmd = 0;\r
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_HFRCOENS) ? CMU_OSCENCMD_HFRCOEN : 0);\r
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_AUXHFRCOENS) ? CMU_OSCENCMD_AUXHFRCOEN : 0);\r
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_LFRCOENS) ? CMU_OSCENCMD_LFRCOEN : 0);\r
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_HFXOENS) ? CMU_OSCENCMD_HFXOEN : 0);\r
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_LFXOENS) ? CMU_OSCENCMD_LFXOEN : 0);\r
+#if defined( _CMU_STATUS_USHFRCOENS_MASK )\r
+ oscEnCmd |= ((cmuStatus & CMU_STATUS_USHFRCOENS) ? CMU_OSCENCMD_USHFRCOEN : 0);\r
+#endif\r
+ CMU->OSCENCMD = oscEnCmd;\r
+\r
+\r
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )\r
+ /* Restore oscillator used for clocking core */\r
+ switch (cmuHfclkStatus & _CMU_HFCLKSTATUS_SELECTED_MASK)\r
+ {\r
+ case CMU_HFCLKSTATUS_SELECTED_LFRCO:\r
+ /* HFRCO could only be selected if the autostart HFXO feature is not\r
+ * enabled, otherwise the HFXO would be started and selected automatically.\r
+ * Note: this error hook helps catching erroneous oscillator configurations,\r
+ * when the AUTOSTARTSELEM0EM1 is set in CMU_HFXOCTRL. */\r
+ if (!(CMU->HFXOCTRL & CMU_HFXOCTRL_AUTOSTARTSELEM0EM1))\r
+ {\r
+ /* Wait for LFRCO to stabilize */\r
+ while (!(CMU->STATUS & CMU_STATUS_LFRCORDY))\r
+ ;\r
+ CMU->HFCLKSEL = CMU_HFCLKSEL_HF_LFRCO;\r
+ }\r
+ else\r
+ {\r
+ EFM_ASSERT(0);\r
+ }\r
+ break;\r
+\r
+ case CMU_HFCLKSTATUS_SELECTED_LFXO:\r
+ /* Wait for LFXO to stabilize */\r
+ while (!(CMU->STATUS & CMU_STATUS_LFXORDY))\r
+ ;\r
+ CMU->HFCLKSEL = CMU_HFCLKSEL_HF_LFXO;\r
+ break;\r
+\r
+ case CMU_HFCLKSTATUS_SELECTED_HFXO:\r
+ /* Wait for HFXO to stabilize */\r
+ while (!(CMU->STATUS & CMU_STATUS_HFXORDY))\r
+ ;\r
+ CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFXO;\r
+ break;\r
+\r
+ default: /* CMU_HFCLKSTATUS_SELECTED_HFRCO */\r
+ /* If core clock was HFRCO core clock, it is automatically restored to */\r
+ /* state prior to entering energy mode. No need for further action. */\r
+ break;\r
+ }\r
+#else\r
+ switch (cmuStatus & (CMU_STATUS_HFRCOSEL\r
+ | CMU_STATUS_HFXOSEL\r
+ | CMU_STATUS_LFRCOSEL\r
+#if defined( CMU_STATUS_USHFRCODIV2SEL )\r
+ | CMU_STATUS_USHFRCODIV2SEL\r
+#endif\r
+ | CMU_STATUS_LFXOSEL))\r
+ {\r
+ case CMU_STATUS_LFRCOSEL:\r
+ /* Wait for LFRCO to stabilize */\r
+ while (!(CMU->STATUS & CMU_STATUS_LFRCORDY))\r
+ ;\r
+ CMU->CMD = CMU_CMD_HFCLKSEL_LFRCO;\r
+ break;\r
+\r
+ case CMU_STATUS_LFXOSEL:\r
+ /* Wait for LFXO to stabilize */\r
+ while (!(CMU->STATUS & CMU_STATUS_LFXORDY))\r
+ ;\r
+ CMU->CMD = CMU_CMD_HFCLKSEL_LFXO;\r
+ break;\r
+\r
+ case CMU_STATUS_HFXOSEL:\r
+ /* Wait for HFXO to stabilize */\r
+ while (!(CMU->STATUS & CMU_STATUS_HFXORDY))\r
+ ;\r
+ CMU->CMD = CMU_CMD_HFCLKSEL_HFXO;\r
+ break;\r
+\r
+#if defined( CMU_STATUS_USHFRCODIV2SEL )\r
+ case CMU_STATUS_USHFRCODIV2SEL:\r
+ /* Wait for USHFRCO to stabilize */\r
+ while (!(CMU->STATUS & CMU_STATUS_USHFRCORDY))\r
+ ;\r
+ CMU->CMD = _CMU_CMD_HFCLKSEL_USHFRCODIV2;\r
+ break;\r
+#endif\r
+\r
+ default: /* CMU_STATUS_HFRCOSEL */\r
+ /* If core clock was HFRCO core clock, it is automatically restored to */\r
+ /* state prior to entering energy mode. No need for further action. */\r
+ break;\r
+ }\r
+\r
+ /* If HFRCO was disabled before entering Energy Mode, turn it off again */\r
+ /* as it is automatically enabled by wake up */\r
+ if ( ! (cmuStatus & CMU_STATUS_HFRCOENS) )\r
+ {\r
+ CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS;\r
+ }\r
+#endif\r
+ /* Restore CMU register locking */\r
+ if (cmuLocked)\r
+ {\r
+ CMU_Lock();\r
+ }\r
+}\r
+\r
+\r
+#if defined( ERRATA_FIX_EMU_E107_EN )\r
+/* Get enable conditions for errata EMU_E107 fix. */\r
+static __INLINE bool getErrataFixEmuE107En(void)\r
+{\r
+ /* SYSTEM_ChipRevisionGet could have been used here, but we would like a\r
+ * faster implementation in this case.\r
+ */\r
+ uint16_t majorMinorRev;\r
+\r
+ /* CHIP MAJOR bit [3:0] */\r
+ majorMinorRev = ((ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK)\r
+ >> _ROMTABLE_PID0_REVMAJOR_SHIFT)\r
+ << 8;\r
+ /* CHIP MINOR bit [7:4] */\r
+ majorMinorRev |= ((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK)\r
+ >> _ROMTABLE_PID2_REVMINORMSB_SHIFT)\r
+ << 4;\r
+ /* CHIP MINOR bit [3:0] */\r
+ majorMinorRev |= (ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK)\r
+ >> _ROMTABLE_PID3_REVMINORLSB_SHIFT;\r
+\r
+#if defined( _EFM32_GECKO_FAMILY )\r
+ return (majorMinorRev <= 0x0103);\r
+#elif defined( _EFM32_TINY_FAMILY )\r
+ return (majorMinorRev <= 0x0102);\r
+#elif defined( _EFM32_GIANT_FAMILY )\r
+ return (majorMinorRev <= 0x0103) || (majorMinorRev == 0x0204);\r
+#elif defined( _EFM32_WONDER_FAMILY )\r
+ return (majorMinorRev == 0x0100);\r
+#else\r
+ /* Zero Gecko and future families are not affected by errata EMU_E107 */\r
+ return false;\r
+#endif\r
+}\r
+#endif\r
+\r
+\r
+#if defined( _EMU_DCDCCTRL_MASK )\r
+/* LP prepare / LN restore P/NFET count */\r
+static void maxCurrentUpdate(void);\r
+#define DCDC_LP_PFET_CNT 7\r
+#define DCDC_LP_NFET_CNT 15\r
+void dcdcFetCntSet(bool lpModeSet)\r
+{\r
+ uint32_t tmp;\r
+ static uint32_t emuDcdcMiscCtrlReg;\r
+\r
+ if (lpModeSet)\r
+ {\r
+ emuDcdcMiscCtrlReg = EMU->DCDCMISCCTRL;\r
+ tmp = EMU->DCDCMISCCTRL\r
+ & ~(_EMU_DCDCMISCCTRL_PFETCNT_MASK | _EMU_DCDCMISCCTRL_NFETCNT_MASK);\r
+ tmp |= (DCDC_LP_PFET_CNT << _EMU_DCDCMISCCTRL_PFETCNT_SHIFT)\r
+ | (DCDC_LP_NFET_CNT << _EMU_DCDCMISCCTRL_NFETCNT_SHIFT);\r
+ EMU->DCDCMISCCTRL = tmp;\r
+ maxCurrentUpdate();\r
+ }\r
+ else\r
+ {\r
+ EMU->DCDCMISCCTRL = emuDcdcMiscCtrlReg;\r
+ maxCurrentUpdate();\r
+ }\r
+}\r
+\r
+void dcdcHsFixLnBlock(void)\r
+{\r
+#define EMU_DCDCSTATUS (* (volatile uint32_t *)(EMU_BASE + 0x7C))\r
+ if (errataFixDcdcHsState == errataFixDcdcHsTrimSet)\r
+ {\r
+ /* Wait for LNRUNNING */\r
+ if ((EMU->DCDCCTRL & ~_EMU_DCDCCTRL_DCDCMODE_MASK) == EMU_DCDCCTRL_DCDCMODE_LOWNOISE)\r
+ {\r
+ while (!(EMU_DCDCSTATUS & (0x1 << 16)));\r
+ }\r
+ errataFixDcdcHsState = errataFixDcdcHsLnWaitDone;\r
+ }\r
+}\r
+#endif\r
+\r
+\r
+/** @endcond */\r
+\r
+\r
+/*******************************************************************************\r
+ ************************** GLOBAL FUNCTIONS *******************************\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Enter energy mode 2 (EM2).\r
+ *\r
+ * @details\r
+ * When entering EM2, the high frequency clocks are disabled, ie HFXO, HFRCO\r
+ * and AUXHFRCO (for AUXHFRCO, see exception note below). When re-entering\r
+ * EM0, HFRCO is re-enabled and the core will be clocked by the configured\r
+ * HFRCO band. This ensures a quick wakeup from EM2.\r
+ *\r
+ * However, prior to entering EM2, the core may have been using another\r
+ * oscillator than HFRCO. The @p restore parameter gives the user the option\r
+ * to restore all HF oscillators according to state prior to entering EM2,\r
+ * as well as the clock used to clock the core. This restore procedure is\r
+ * handled by SW. However, since handled by SW, it will not be restored\r
+ * before completing the interrupt function(s) waking up the core!\r
+ *\r
+ * @note\r
+ * If restoring core clock to use the HFXO oscillator, which has been\r
+ * disabled during EM2 mode, this function will stall until the oscillator\r
+ * has stabilized. Stalling time can be reduced by adding interrupt\r
+ * support detecting stable oscillator, and an asynchronous switch to the\r
+ * original oscillator. See CMU documentation. Such a feature is however\r
+ * outside the scope of the implementation in this function.\r
+ * @par\r
+ * If HFXO is re-enabled by this function, and NOT used to clock the core,\r
+ * this function will not wait for HFXO to stabilize. This must be considered\r
+ * by the application if trying to use features relying on that oscillator\r
+ * upon return.\r
+ * @par\r
+ * If a debugger is attached, the AUXHFRCO will not be disabled if enabled\r
+ * upon entering EM2. It will thus remain enabled when returning to EM0\r
+ * regardless of the @p restore parameter.\r
+ * @par\r
+ * If HFXO autostart and select is enabled by using CMU_HFXOAutostartEnable(),\r
+ * the starting and selecting of the core clocks will be identical to the user\r
+ * independently of the value of the @p restore parameter when waking up on\r
+ * the wakeup sources corresponding to the autostart and select setting.\r
+ *\r
+ * @param[in] restore\r
+ * @li true - restore oscillators and clocks, see function details.\r
+ * @li false - do not restore oscillators and clocks, see function details.\r
+ * @par\r
+ * The @p restore option should only be used if all clock control is done\r
+ * via the CMU API.\r
+ ******************************************************************************/\r
+void EMU_EnterEM2(bool restore)\r
+{\r
+#if defined( ERRATA_FIX_EMU_E107_EN )\r
+ bool errataFixEmuE107En;\r
+ uint32_t nonWicIntEn[2];\r
+#endif\r
+\r
+ /* Auto-update CMU status just in case before entering energy mode. */\r
+ /* This variable is normally kept up-to-date by the CMU API. */\r
+ cmuStatus = CMU->STATUS;\r
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )\r
+ cmuHfclkStatus = (uint16_t)(CMU->HFCLKSTATUS);\r
+#endif\r
+\r
+ /* Enter Cortex deep sleep mode */\r
+ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;\r
+\r
+ /* Fix for errata EMU_E107 - store non-WIC interrupt enable flags.\r
+ Disable the enabled non-WIC interrupts. */\r
+#if defined( ERRATA_FIX_EMU_E107_EN )\r
+ errataFixEmuE107En = getErrataFixEmuE107En();\r
+ if (errataFixEmuE107En)\r
+ {\r
+ nonWicIntEn[0] = NVIC->ISER[0] & NON_WIC_INT_MASK_0;\r
+ NVIC->ICER[0] = nonWicIntEn[0];\r
+#if (NON_WIC_INT_MASK_1 != (~(0x0U)))\r
+ nonWicIntEn[1] = NVIC->ISER[1] & NON_WIC_INT_MASK_1;\r
+ NVIC->ICER[1] = nonWicIntEn[1];\r
+#endif\r
+ }\r
+#endif\r
+\r
+#if defined( _EMU_DCDCCTRL_MASK )\r
+ dcdcFetCntSet(true);\r
+ dcdcHsFixLnBlock();\r
+#endif\r
+\r
+ __WFI();\r
+\r
+#if defined( _EMU_DCDCCTRL_MASK )\r
+ dcdcFetCntSet(false);\r
+#endif\r
+\r
+ /* Fix for errata EMU_E107 - restore state of non-WIC interrupt enable flags. */\r
+#if defined( ERRATA_FIX_EMU_E107_EN )\r
+ if (errataFixEmuE107En)\r
+ {\r
+ NVIC->ISER[0] = nonWicIntEn[0];\r
+#if (NON_WIC_INT_MASK_1 != (~(0x0U)))\r
+ NVIC->ISER[1] = nonWicIntEn[1];\r
+#endif\r
+ }\r
+#endif\r
+\r
+ /* Restore oscillators/clocks if specified */\r
+ if (restore)\r
+ {\r
+ emuRestore();\r
+ }\r
+ /* If not restoring, and original clock was not HFRCO, we have to */\r
+ /* update CMSIS core clock variable since core clock has changed */\r
+ /* to using HFRCO. */\r
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )\r
+ else if ((cmuHfclkStatus & _CMU_HFCLKSTATUS_SELECTED_MASK)\r
+ != CMU_HFCLKSTATUS_SELECTED_HFRCO)\r
+#else\r
+ else if (!(cmuStatus & CMU_STATUS_HFRCOSEL))\r
+#endif\r
+ {\r
+ SystemCoreClockUpdate();\r
+ }\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Enter energy mode 3 (EM3).\r
+ *\r
+ * @details\r
+ * When entering EM3, the high frequency clocks are disabled by HW, ie HFXO,\r
+ * HFRCO and AUXHFRCO (for AUXHFRCO, see exception note below). In addition,\r
+ * the low frequency clocks, ie LFXO and LFRCO are disabled by SW. When\r
+ * re-entering EM0, HFRCO is re-enabled and the core will be clocked by the\r
+ * configured HFRCO band. This ensures a quick wakeup from EM3.\r
+ *\r
+ * However, prior to entering EM3, the core may have been using another\r
+ * oscillator than HFRCO. The @p restore parameter gives the user the option\r
+ * to restore all HF/LF oscillators according to state prior to entering EM3,\r
+ * as well as the clock used to clock the core. This restore procedure is\r
+ * handled by SW. However, since handled by SW, it will not be restored\r
+ * before completing the interrupt function(s) waking up the core!\r
+ *\r
+ * @note\r
+ * If restoring core clock to use an oscillator other than HFRCO, this\r
+ * function will stall until the oscillator has stabilized. Stalling time\r
+ * can be reduced by adding interrupt support detecting stable oscillator,\r
+ * and an asynchronous switch to the original oscillator. See CMU\r
+ * documentation. Such a feature is however outside the scope of the\r
+ * implementation in this function.\r
+ * @par\r
+ * If HFXO/LFXO/LFRCO are re-enabled by this function, and NOT used to clock\r
+ * the core, this function will not wait for those oscillators to stabilize.\r
+ * This must be considered by the application if trying to use features\r
+ * relying on those oscillators upon return.\r
+ * @par\r
+ * If a debugger is attached, the AUXHFRCO will not be disabled if enabled\r
+ * upon entering EM3. It will thus remain enabled when returning to EM0\r
+ * regardless of the @p restore parameter.\r
+ *\r
+ * @param[in] restore\r
+ * @li true - restore oscillators and clocks, see function details.\r
+ * @li false - do not restore oscillators and clocks, see function details.\r
+ * @par\r
+ * The @p restore option should only be used if all clock control is done\r
+ * via the CMU API.\r
+ ******************************************************************************/\r
+void EMU_EnterEM3(bool restore)\r
+{\r
+ uint32_t cmuLocked;\r
+\r
+#if defined( ERRATA_FIX_EMU_E107_EN )\r
+ bool errataFixEmuE107En;\r
+ uint32_t nonWicIntEn[2];\r
+#endif\r
+\r
+ /* Auto-update CMU status just in case before entering energy mode. */\r
+ /* This variable is normally kept up-to-date by the CMU API. */\r
+ cmuStatus = CMU->STATUS;\r
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )\r
+ cmuHfclkStatus = (uint16_t)(CMU->HFCLKSTATUS);\r
+#endif\r
+\r
+ /* CMU registers may be locked */\r
+ cmuLocked = CMU->LOCK & CMU_LOCK_LOCKKEY_LOCKED;\r
+ CMU_Unlock();\r
+\r
+ /* Disable LF oscillators */\r
+ CMU->OSCENCMD = CMU_OSCENCMD_LFXODIS | CMU_OSCENCMD_LFRCODIS;\r
+\r
+ /* Restore CMU register locking */\r
+ if (cmuLocked)\r
+ {\r
+ CMU_Lock();\r
+ }\r
+\r
+ /* Enter Cortex deep sleep mode */\r
+ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;\r
+\r
+ /* Fix for errata EMU_E107 - store non-WIC interrupt enable flags.\r
+ Disable the enabled non-WIC interrupts. */\r
+#if defined( ERRATA_FIX_EMU_E107_EN )\r
+ errataFixEmuE107En = getErrataFixEmuE107En();\r
+ if (errataFixEmuE107En)\r
+ {\r
+ nonWicIntEn[0] = NVIC->ISER[0] & NON_WIC_INT_MASK_0;\r
+ NVIC->ICER[0] = nonWicIntEn[0];\r
+#if (NON_WIC_INT_MASK_1 != (~(0x0U)))\r
+ nonWicIntEn[1] = NVIC->ISER[1] & NON_WIC_INT_MASK_1;\r
+ NVIC->ICER[1] = nonWicIntEn[1];\r
+#endif\r
+\r
+ }\r
+#endif\r
+\r
+#if defined( _EMU_DCDCCTRL_MASK )\r
+ dcdcFetCntSet(true);\r
+ dcdcHsFixLnBlock();\r
+#endif\r
+\r
+ __WFI();\r
+\r
+#if defined( _EMU_DCDCCTRL_MASK )\r
+ dcdcFetCntSet(false);\r
+#endif\r
+\r
+ /* Fix for errata EMU_E107 - restore state of non-WIC interrupt enable flags. */\r
+#if defined( ERRATA_FIX_EMU_E107_EN )\r
+ if (errataFixEmuE107En)\r
+ {\r
+ NVIC->ISER[0] = nonWicIntEn[0];\r
+#if (NON_WIC_INT_MASK_1 != (~(0x0U)))\r
+ NVIC->ISER[1] = nonWicIntEn[1];\r
+#endif\r
+ }\r
+#endif\r
+\r
+ /* Restore oscillators/clocks if specified */\r
+ if (restore)\r
+ {\r
+ emuRestore();\r
+ }\r
+ /* If not restoring, and original clock was not HFRCO, we have to */\r
+ /* update CMSIS core clock variable since core clock has changed */\r
+ /* to using HFRCO. */\r
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )\r
+ else if ((cmuHfclkStatus & _CMU_HFCLKSTATUS_SELECTED_MASK)\r
+ != CMU_HFCLKSTATUS_SELECTED_HFRCO)\r
+#else\r
+ else if (!(cmuStatus & CMU_STATUS_HFRCOSEL))\r
+#endif\r
+ {\r
+ SystemCoreClockUpdate();\r
+ }\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Enter energy mode 4 (EM4).\r
+ *\r
+ * @note\r
+ * Only a power on reset or external reset pin can wake the device from EM4.\r
+ ******************************************************************************/\r
+void EMU_EnterEM4(void)\r
+{\r
+ int i;\r
+\r
+#if defined( _EMU_EM4CTRL_EM4ENTRY_SHIFT )\r
+ uint32_t em4seq2 = (EMU->EM4CTRL & ~_EMU_EM4CTRL_EM4ENTRY_MASK)\r
+ | (2 << _EMU_EM4CTRL_EM4ENTRY_SHIFT);\r
+ uint32_t em4seq3 = (EMU->EM4CTRL & ~_EMU_EM4CTRL_EM4ENTRY_MASK)\r
+ | (3 << _EMU_EM4CTRL_EM4ENTRY_SHIFT);\r
+#else\r
+ uint32_t em4seq2 = (EMU->CTRL & ~_EMU_CTRL_EM4CTRL_MASK)\r
+ | (2 << _EMU_CTRL_EM4CTRL_SHIFT);\r
+ uint32_t em4seq3 = (EMU->CTRL & ~_EMU_CTRL_EM4CTRL_MASK)\r
+ | (3 << _EMU_CTRL_EM4CTRL_SHIFT);\r
+#endif\r
+\r
+ /* Make sure register write lock is disabled */\r
+ EMU_Unlock();\r
+\r
+#if defined( ERRATA_FIX_EMU_E108_EN )\r
+ /* Fix for errata EMU_E108 - High Current Consumption on EM4 Entry. */\r
+ __disable_irq();\r
+ *(volatile uint32_t *)0x400C80E4 = 0;\r
+#endif\r
+\r
+#if defined( _EMU_DCDCCTRL_MASK )\r
+ dcdcFetCntSet(true);\r
+ dcdcHsFixLnBlock();\r
+#endif\r
+\r
+ for (i = 0; i < 4; i++)\r
+ {\r
+#if defined( _EMU_EM4CTRL_EM4ENTRY_SHIFT )\r
+ EMU->EM4CTRL = em4seq2;\r
+ EMU->EM4CTRL = em4seq3;\r
+ }\r
+ EMU->EM4CTRL = em4seq2;\r
+#else\r
+ EMU->CTRL = em4seq2;\r
+ EMU->CTRL = em4seq3;\r
+ }\r
+ EMU->CTRL = em4seq2;\r
+#endif\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Power down memory block.\r
+ *\r
+ * @param[in] blocks\r
+ * Specifies a logical OR of bits indicating memory blocks to power down.\r
+ * Bit 0 selects block 1, bit 1 selects block 2, etc. Memory block 0 cannot\r
+ * be disabled. Please refer to the reference manual for available\r
+ * memory blocks for a device.\r
+ *\r
+ * @note\r
+ * Only a reset can make the specified memory block(s) available for use\r
+ * after having been powered down. Function will be void for devices not\r
+ * supporting this feature.\r
+ ******************************************************************************/\r
+void EMU_MemPwrDown(uint32_t blocks)\r
+{\r
+#if defined( _EMU_MEMCTRL_POWERDOWN_MASK )\r
+ EFM_ASSERT(blocks <= (_EMU_MEMCTRL_POWERDOWN_MASK\r
+ >> _EMU_MEMCTRL_POWERDOWN_SHIFT));\r
+ EMU->MEMCTRL = blocks;\r
+\r
+#elif defined( _EMU_MEMCTRL_RAMPOWERDOWN_MASK ) \\r
+ && defined( _EMU_MEMCTRL_RAMHPOWERDOWN_MASK ) \\r
+ && defined( _EMU_MEMCTRL_SEQRAMPOWERDOWN_MASK )\r
+ EFM_ASSERT((blocks & (_EMU_MEMCTRL_RAMPOWERDOWN_MASK\r
+ | _EMU_MEMCTRL_RAMHPOWERDOWN_MASK\r
+ | _EMU_MEMCTRL_SEQRAMPOWERDOWN_MASK))\r
+ == blocks);\r
+ EMU->MEMCTRL = blocks;\r
+\r
+#elif defined( _EMU_MEMCTRL_RAMPOWERDOWN_MASK )\r
+ EFM_ASSERT((blocks & _EMU_MEMCTRL_RAMPOWERDOWN_MASK) == blocks);\r
+ EMU->MEMCTRL = blocks;\r
+\r
+#elif defined( _EMU_RAM0CTRL_RAMPOWERDOWN_MASK )\r
+ EFM_ASSERT((blocks & _EMU_RAM0CTRL_RAMPOWERDOWN_MASK) == blocks);\r
+ EMU->RAM0CTRL = blocks;\r
+\r
+#else\r
+ (void)blocks;\r
+#endif\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Update EMU module with CMU oscillator selection/enable status.\r
+ *\r
+ * @details\r
+ * When entering EM2 and EM3, the HW may change the core clock oscillator\r
+ * used, as well as disabling some oscillators. The user may optionally select\r
+ * to restore the oscillators after waking up from EM2 and EM3 through the\r
+ * SW API.\r
+ *\r
+ * However, in order to support this in a safe way, the EMU module must\r
+ * be kept up-to-date on the actual selected configuration. The CMU\r
+ * module must keep the EMU module up-to-date.\r
+ *\r
+ * This function is mainly intended for internal use by the CMU module,\r
+ * but if the applications changes oscillator configurations without\r
+ * using the CMU API, this function can be used to keep the EMU module\r
+ * up-to-date.\r
+ ******************************************************************************/\r
+void EMU_UpdateOscConfig(void)\r
+{\r
+ /* Fetch current configuration */\r
+ cmuStatus = CMU->STATUS;\r
+#if defined( _CMU_HFCLKSTATUS_RESETVALUE )\r
+ cmuHfclkStatus = (uint16_t)(CMU->HFCLKSTATUS);\r
+#endif\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Update EMU module with Energy Mode 2 and 3 configuration\r
+ *\r
+ * @param[in] em23Init\r
+ * Energy Mode 2 and 3 configuration structure\r
+ ******************************************************************************/\r
+void EMU_EM23Init(EMU_EM23Init_TypeDef *em23Init)\r
+{\r
+#if defined( _EMU_CTRL_EMVREG_MASK )\r
+ EMU->CTRL = em23Init->em23VregFullEn ? (EMU->CTRL | EMU_CTRL_EMVREG)\r
+ : (EMU->CTRL & ~EMU_CTRL_EMVREG);\r
+#elif defined( _EMU_CTRL_EM23VREG_MASK )\r
+ EMU->CTRL = em23Init->em23VregFullEn ? (EMU->CTRL | EMU_CTRL_EM23VREG)\r
+ : (EMU->CTRL & ~EMU_CTRL_EM23VREG);\r
+#else\r
+ (void)em23Init;\r
+#endif\r
+}\r
+\r
+\r
+#if defined( _EMU_EM4CONF_MASK ) || defined( _EMU_EM4CTRL_MASK )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Update EMU module with Energy Mode 4 configuration\r
+ *\r
+ * @param[in] em4Init\r
+ * Energy Mode 4 configuration structure\r
+ ******************************************************************************/\r
+void EMU_EM4Init(EMU_EM4Init_TypeDef *em4Init)\r
+{\r
+#if defined( _EMU_EM4CONF_MASK )\r
+ /* Init for platforms with EMU->EM4CONF register */\r
+ uint32_t em4conf = EMU->EM4CONF;\r
+\r
+ /* Clear fields that will be reconfigured */\r
+ em4conf &= ~(_EMU_EM4CONF_LOCKCONF_MASK\r
+ | _EMU_EM4CONF_OSC_MASK\r
+ | _EMU_EM4CONF_BURTCWU_MASK\r
+ | _EMU_EM4CONF_VREGEN_MASK);\r
+\r
+ /* Configure new settings */\r
+ em4conf |= (em4Init->lockConfig << _EMU_EM4CONF_LOCKCONF_SHIFT)\r
+ | (em4Init->osc)\r
+ | (em4Init->buRtcWakeup << _EMU_EM4CONF_BURTCWU_SHIFT)\r
+ | (em4Init->vreg << _EMU_EM4CONF_VREGEN_SHIFT);\r
+\r
+ /* Apply configuration. Note that lock can be set after this stage. */\r
+ EMU->EM4CONF = em4conf;\r
+\r
+#elif defined( _EMU_EM4CTRL_MASK )\r
+ /* Init for platforms with EMU->EM4CTRL register */\r
+\r
+ uint32_t em4ctrl = EMU->EM4CTRL;\r
+\r
+ em4ctrl &= ~(_EMU_EM4CTRL_RETAINLFXO_MASK\r
+ | _EMU_EM4CTRL_RETAINLFRCO_MASK\r
+ | _EMU_EM4CTRL_RETAINULFRCO_MASK\r
+ | _EMU_EM4CTRL_EM4STATE_MASK\r
+ | _EMU_EM4CTRL_EM4IORETMODE_MASK);\r
+\r
+ em4ctrl |= (em4Init->retainLfxo ? EMU_EM4CTRL_RETAINLFXO : 0)\r
+ | (em4Init->retainLfrco ? EMU_EM4CTRL_RETAINLFRCO : 0)\r
+ | (em4Init->retainUlfrco ? EMU_EM4CTRL_RETAINULFRCO : 0)\r
+ | (em4Init->em4State ? EMU_EM4CTRL_EM4STATE_EM4H : 0)\r
+ | (em4Init->pinRetentionMode);\r
+\r
+ EMU->EM4CTRL = em4ctrl;\r
+#endif\r
+}\r
+#endif\r
+\r
+\r
+#if defined( BU_PRESENT )\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Configure Backup Power Domain settings\r
+ *\r
+ * @param[in] bupdInit\r
+ * Backup power domain initialization structure\r
+ ******************************************************************************/\r
+void EMU_BUPDInit(EMU_BUPDInit_TypeDef *bupdInit)\r
+{\r
+ uint32_t reg;\r
+\r
+ /* Set power connection configuration */\r
+ reg = EMU->PWRCONF & ~(_EMU_PWRCONF_PWRRES_MASK\r
+ | _EMU_PWRCONF_VOUTSTRONG_MASK\r
+ | _EMU_PWRCONF_VOUTMED_MASK\r
+ | _EMU_PWRCONF_VOUTWEAK_MASK);\r
+\r
+ reg |= bupdInit->resistor\r
+ | (bupdInit->voutStrong << _EMU_PWRCONF_VOUTSTRONG_SHIFT)\r
+ | (bupdInit->voutMed << _EMU_PWRCONF_VOUTMED_SHIFT)\r
+ | (bupdInit->voutWeak << _EMU_PWRCONF_VOUTWEAK_SHIFT);\r
+\r
+ EMU->PWRCONF = reg;\r
+\r
+ /* Set backup domain inactive mode configuration */\r
+ reg = EMU->BUINACT & ~(_EMU_BUINACT_PWRCON_MASK);\r
+ reg |= (bupdInit->inactivePower);\r
+ EMU->BUINACT = reg;\r
+\r
+ /* Set backup domain active mode configuration */\r
+ reg = EMU->BUACT & ~(_EMU_BUACT_PWRCON_MASK);\r
+ reg |= (bupdInit->activePower);\r
+ EMU->BUACT = reg;\r
+\r
+ /* Set power control configuration */\r
+ reg = EMU->BUCTRL & ~(_EMU_BUCTRL_PROBE_MASK\r
+ | _EMU_BUCTRL_BODCAL_MASK\r
+ | _EMU_BUCTRL_STATEN_MASK\r
+ | _EMU_BUCTRL_EN_MASK);\r
+\r
+ /* Note use of ->enable to both enable BUPD, use BU_VIN pin input and\r
+ release reset */\r
+ reg |= bupdInit->probe\r
+ | (bupdInit->bodCal << _EMU_BUCTRL_BODCAL_SHIFT)\r
+ | (bupdInit->statusPinEnable << _EMU_BUCTRL_STATEN_SHIFT)\r
+ | (bupdInit->enable << _EMU_BUCTRL_EN_SHIFT);\r
+\r
+ /* Enable configuration */\r
+ EMU->BUCTRL = reg;\r
+\r
+ /* If enable is true, enable BU_VIN input power pin, if not disable it */\r
+ EMU_BUPinEnable(bupdInit->enable);\r
+\r
+ /* If enable is true, release BU reset, if not keep reset asserted */\r
+ BUS_RegBitWrite(&(RMU->CTRL), _RMU_CTRL_BURSTEN_SHIFT, !bupdInit->enable);\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Configure Backup Power Domain BOD Threshold value\r
+ * @note\r
+ * These values are precalibrated\r
+ * @param[in] mode Active or Inactive mode\r
+ * @param[in] value\r
+ ******************************************************************************/\r
+void EMU_BUThresholdSet(EMU_BODMode_TypeDef mode, uint32_t value)\r
+{\r
+ EFM_ASSERT(value<8);\r
+ EFM_ASSERT(value<=(_EMU_BUACT_BUEXTHRES_MASK>>_EMU_BUACT_BUEXTHRES_SHIFT));\r
+\r
+ switch(mode)\r
+ {\r
+ case emuBODMode_Active:\r
+ EMU->BUACT = (EMU->BUACT & ~_EMU_BUACT_BUEXTHRES_MASK)\r
+ | (value<<_EMU_BUACT_BUEXTHRES_SHIFT);\r
+ break;\r
+ case emuBODMode_Inactive:\r
+ EMU->BUINACT = (EMU->BUINACT & ~_EMU_BUINACT_BUENTHRES_MASK)\r
+ | (value<<_EMU_BUINACT_BUENTHRES_SHIFT);\r
+ break;\r
+ }\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Configure Backup Power Domain BOD Threshold Range\r
+ * @note\r
+ * These values are precalibrated\r
+ * @param[in] mode Active or Inactive mode\r
+ * @param[in] value\r
+ ******************************************************************************/\r
+void EMU_BUThresRangeSet(EMU_BODMode_TypeDef mode, uint32_t value)\r
+{\r
+ EFM_ASSERT(value < 4);\r
+ EFM_ASSERT(value<=(_EMU_BUACT_BUEXRANGE_MASK>>_EMU_BUACT_BUEXRANGE_SHIFT));\r
+\r
+ switch(mode)\r
+ {\r
+ case emuBODMode_Active:\r
+ EMU->BUACT = (EMU->BUACT & ~_EMU_BUACT_BUEXRANGE_MASK)\r
+ | (value<<_EMU_BUACT_BUEXRANGE_SHIFT);\r
+ break;\r
+ case emuBODMode_Inactive:\r
+ EMU->BUINACT = (EMU->BUINACT & ~_EMU_BUINACT_BUENRANGE_MASK)\r
+ | (value<<_EMU_BUINACT_BUENRANGE_SHIFT);\r
+ break;\r
+ }\r
+}\r
+#endif\r
+\r
+\r
+#if defined( _EMU_DCDCCTRL_MASK )\r
+\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Load DCDC calibration constants from DI page. Const means calibration\r
+ * data that does not change depending on other configuration parameters.\r
+ *\r
+ * @return\r
+ * False if calibration registers are locked\r
+ ******************************************************************************/\r
+static bool ConstCalibrationLoad(void)\r
+{\r
+ uint32_t val;\r
+ volatile uint32_t *reg;\r
+\r
+ /* DI calib data in flash */\r
+ volatile uint32_t* const diCal_EMU_DCDCLNFREQCTRL = (volatile uint32_t *)(0x0FE08038);\r
+ volatile uint32_t* const diCal_EMU_DCDCLNVCTRL = (volatile uint32_t *)(0x0FE08040);\r
+ volatile uint32_t* const diCal_EMU_DCDCLPCTRL = (volatile uint32_t *)(0x0FE08048);\r
+ volatile uint32_t* const diCal_EMU_DCDCLPVCTRL = (volatile uint32_t *)(0x0FE08050);\r
+ volatile uint32_t* const diCal_EMU_DCDCTRIM0 = (volatile uint32_t *)(0x0FE08058);\r
+ volatile uint32_t* const diCal_EMU_DCDCTRIM1 = (volatile uint32_t *)(0x0FE08060);\r
+\r
+ if (DEVINFO->DCDCLPVCTRL0 != UINT_MAX)\r
+ {\r
+ val = *(diCal_EMU_DCDCLNFREQCTRL + 1);\r
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCLNFREQCTRL;\r
+ *reg = val;\r
+\r
+ val = *(diCal_EMU_DCDCLNVCTRL + 1);\r
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCLNVCTRL;\r
+ *reg = val;\r
+\r
+ val = *(diCal_EMU_DCDCLPCTRL + 1);\r
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCLPCTRL;\r
+ *reg = val;\r
+\r
+ val = *(diCal_EMU_DCDCLPVCTRL + 1);\r
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCLPVCTRL;\r
+ *reg = val;\r
+\r
+ val = *(diCal_EMU_DCDCTRIM0 + 1);\r
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCTRIM0;\r
+ *reg = val;\r
+\r
+ val = *(diCal_EMU_DCDCTRIM1 + 1);\r
+ reg = (volatile uint32_t *)*diCal_EMU_DCDCTRIM1;\r
+ *reg = val;\r
+\r
+ return true;\r
+ }\r
+ EFM_ASSERT(false);\r
+ /* Return when assertions are disabled */\r
+ return false;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set recommended and validated current optimization settings\r
+ *\r
+ ******************************************************************************/\r
+void ValidatedConfigSet(void)\r
+{\r
+#define EMU_DCDCSMCTRL (* (volatile uint32_t *)(EMU_BASE + 0x44))\r
+\r
+ uint32_t dcdcTiming;\r
+ SYSTEM_PartFamily_TypeDef family;\r
+ SYSTEM_ChipRevision_TypeDef rev;\r
+\r
+ /* Enable duty cycling of the bias */\r
+ EMU->DCDCLPCTRL |= EMU_DCDCLPCTRL_LPVREFDUTYEN;\r
+\r
+ /* Set low-noise RCO for EFM32 and EFR32 */\r
+#if defined( _EFR_DEVICE )\r
+ /* 7MHz is recommended for all EFR32 parts with DCDC */\r
+ EMU->DCDCLNFREQCTRL = (EMU->DCDCLNFREQCTRL & ~_EMU_DCDCLNFREQCTRL_RCOBAND_MASK)\r
+ | (EMU_DcdcLnRcoBand_7MHz << _EMU_DCDCLNFREQCTRL_RCOBAND_SHIFT);\r
+#else\r
+ /* 3MHz is recommended for all EFM32 parts with DCDC */\r
+ EMU->DCDCLNFREQCTRL = (EMU->DCDCLNFREQCTRL & ~_EMU_DCDCLNFREQCTRL_RCOBAND_MASK)\r
+ | (EMU_DcdcLnRcoBand_3MHz << _EMU_DCDCLNFREQCTRL_RCOBAND_SHIFT);\r
+#endif\r
+\r
+ EMU->DCDCTIMING &= ~_EMU_DCDCTIMING_DUTYSCALE_MASK;\r
+\r
+ family = SYSTEM_GetFamily();\r
+ SYSTEM_ChipRevisionGet(&rev);\r
+ if ((((family >= systemPartFamilyMighty1P)\r
+ && (family <= systemPartFamilyFlex1V))\r
+ || (family == systemPartFamilyEfm32Pearl1B)\r
+ || (family == systemPartFamilyEfm32Jade1B))\r
+ && ((rev.major == 1) && (rev.minor < 3))\r
+ && (errataFixDcdcHsState == errataFixDcdcHsInit))\r
+ {\r
+ /* LPCMPWAITDIS = 1 */\r
+ EMU_DCDCSMCTRL |= 1;\r
+\r
+ dcdcTiming = EMU->DCDCTIMING;\r
+ dcdcTiming &= ~(_EMU_DCDCTIMING_LPINITWAIT_MASK\r
+ |_EMU_DCDCTIMING_LNWAIT_MASK\r
+ |_EMU_DCDCTIMING_BYPWAIT_MASK);\r
+\r
+ dcdcTiming |= ((180 << _EMU_DCDCTIMING_LPINITWAIT_SHIFT)\r
+ | (12 << _EMU_DCDCTIMING_LNWAIT_SHIFT)\r
+ | (180 << _EMU_DCDCTIMING_BYPWAIT_SHIFT));\r
+ EMU->DCDCTIMING = dcdcTiming;\r
+\r
+ errataFixDcdcHsState = errataFixDcdcHsTrimSet;\r
+ }\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Calculate and update EMU->DCDCMISCCTRL for maximum DCDC current based\r
+ * on the slice configuration and user set maximum.\r
+ ******************************************************************************/\r
+static void maxCurrentUpdate(void)\r
+{\r
+ uint32_t lncLimImSel;\r
+ uint32_t lpcLimImSel;\r
+ uint32_t pFetCnt;\r
+\r
+ pFetCnt = (EMU->DCDCMISCCTRL & _EMU_DCDCMISCCTRL_PFETCNT_MASK)\r
+ >> _EMU_DCDCMISCCTRL_PFETCNT_SHIFT;\r
+\r
+ /* Equation from Reference Manual section 11.5.20, in the register\r
+ field description for LNCLIMILIMSEL and LPCLIMILIMSEL. */\r
+ lncLimImSel = (dcdcMaxCurrent_mA / (5 * (pFetCnt + 1))) - 1;\r
+ /* 80mA as recommended in Application Note AN0948 */\r
+ lpcLimImSel = (80 / (5 * (pFetCnt + 1))) - 1;\r
+\r
+ lncLimImSel <<= _EMU_DCDCMISCCTRL_LNCLIMILIMSEL_SHIFT;\r
+ lpcLimImSel <<= _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_SHIFT;\r
+ EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~(_EMU_DCDCMISCCTRL_LNCLIMILIMSEL_MASK\r
+ | _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_MASK))\r
+ | (lncLimImSel | lpcLimImSel);\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set static variable that holds the user set maximum current. Update\r
+ * DCDC configuration.\r
+ *\r
+ * @param[in] mAmaxCurrent\r
+ * Maximum allowed current drawn by the DCDC from VREGVDD in mA.\r
+ ******************************************************************************/\r
+static void maxCurrentSet(uint32_t mAmaxCurrent)\r
+{\r
+ dcdcMaxCurrent_mA = mAmaxCurrent;\r
+ maxCurrentUpdate();\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Load EMU_DCDCLPCTRL_LPCMPHYSSEL depending on LP bias, LP feedback\r
+ * attenuation and DEVINFOREV.\r
+ *\r
+ * @param[in] attSet\r
+ * LP feedback attenuation.\r
+ * @param[in] lpCmpBias\r
+ * lpCmpBias selection\r
+ ******************************************************************************/\r
+static bool LpCmpHystCalibrationLoad(bool lpAttenuation, uint32_t lpCmpBias)\r
+{\r
+ uint8_t devinfoRev;\r
+ uint32_t lpcmpHystSel;\r
+\r
+ /* Get calib data revision */\r
+ devinfoRev = SYSTEM_GetDevinfoRev();\r
+\r
+ /* Load LPATT indexed calibration data */\r
+ if (devinfoRev < 4)\r
+ {\r
+ lpcmpHystSel = DEVINFO->DCDCLPCMPHYSSEL0;\r
+\r
+ if (lpAttenuation)\r
+ {\r
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL0_LPCMPHYSSELLPATT1_MASK)\r
+ >> _DEVINFO_DCDCLPCMPHYSSEL0_LPCMPHYSSELLPATT1_SHIFT;\r
+ }\r
+ else\r
+ {\r
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL0_LPCMPHYSSELLPATT0_MASK)\r
+ >> _DEVINFO_DCDCLPCMPHYSSEL0_LPCMPHYSSELLPATT0_SHIFT;\r
+ }\r
+ }\r
+ /* devinfoRev >= 4\r
+ Load LPCMPBIAS indexed calibration data */\r
+ else\r
+ {\r
+ lpcmpHystSel = DEVINFO->DCDCLPCMPHYSSEL1;\r
+ switch (lpCmpBias)\r
+ {\r
+ case _EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS0:\r
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS0_MASK)\r
+ >> _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS0_SHIFT;\r
+ break;\r
+\r
+ case _EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS1:\r
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS1_MASK)\r
+ >> _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS1_SHIFT;\r
+ break;\r
+\r
+ case _EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS2:\r
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS2_MASK)\r
+ >> _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS2_SHIFT;\r
+ break;\r
+\r
+ case _EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS3:\r
+ lpcmpHystSel = (lpcmpHystSel & _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS3_MASK)\r
+ >> _DEVINFO_DCDCLPCMPHYSSEL1_LPCMPHYSSELLPCMPBIAS3_SHIFT;\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(false);\r
+ /* Return when assertions are disabled */\r
+ return false;\r
+ }\r
+ }\r
+\r
+ /* Make sure the sel value is within the field range. */\r
+ lpcmpHystSel <<= _EMU_DCDCLPCTRL_LPCMPHYSSEL_SHIFT;\r
+ if (lpcmpHystSel & ~_EMU_DCDCLPCTRL_LPCMPHYSSEL_MASK)\r
+ {\r
+ EFM_ASSERT(false);\r
+ /* Return when assertions are disabled */\r
+ return false;\r
+ }\r
+ EMU->DCDCLPCTRL = (EMU->DCDCLPCTRL & ~_EMU_DCDCLPCTRL_LPCMPHYSSEL_MASK) | lpcmpHystSel;\r
+\r
+ return true;\r
+}\r
+\r
+\r
+/** @endcond */\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set DCDC regulator operating mode\r
+ *\r
+ * @param[in] dcdcMode\r
+ * DCDC mode\r
+ ******************************************************************************/\r
+void EMU_DCDCModeSet(EMU_DcdcMode_TypeDef dcdcMode)\r
+{\r
+ while(EMU->DCDCSYNC & EMU_DCDCSYNC_DCDCCTRLBUSY);\r
+ BUS_RegBitWrite(&EMU->DCDCCLIMCTRL, _EMU_DCDCCLIMCTRL_BYPLIMEN_SHIFT, dcdcMode == emuDcdcMode_Bypass ? 0 : 1);\r
+ EMU->DCDCCTRL = (EMU->DCDCCTRL & ~_EMU_DCDCCTRL_DCDCMODE_MASK) | dcdcMode;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Configure DCDC regulator\r
+ *\r
+ * @note\r
+ * Use the function EMU_DCDCPowerDown() to if the power circuit is configured\r
+ * for NODCDC as decribed in Section 11.3.4.3 in the Reference Manual.\r
+ *\r
+ * @param[in] dcdcInit\r
+ * DCDC initialization structure\r
+ *\r
+ * @return\r
+ * True if initialization parameters are valid\r
+ ******************************************************************************/\r
+bool EMU_DCDCInit(EMU_DCDCInit_TypeDef *dcdcInit)\r
+{\r
+ uint32_t lpCmpBiasSel;\r
+\r
+ /* Set external power configuration. This enables writing to the other\r
+ DCDC registers. */\r
+ EMU->PWRCFG = dcdcInit->powerConfig;\r
+\r
+ /* EMU->PWRCFG is write-once and POR reset only. Check that\r
+ we could set the desired power configuration. */\r
+ if ((EMU->PWRCFG & _EMU_PWRCFG_PWRCFG_MASK) != dcdcInit->powerConfig)\r
+ {\r
+ /* If this assert triggers unexpectedly, please power cycle the\r
+ kit to reset the power configuration. */\r
+ EFM_ASSERT(false);\r
+ /* Return when assertions are disabled */\r
+ return false;\r
+ }\r
+\r
+ /* Load DCDC calibration data from the DI page */\r
+ ConstCalibrationLoad();\r
+\r
+ /* Check current parameters */\r
+ EFM_ASSERT(dcdcInit->maxCurrent_mA <= 200);\r
+ EFM_ASSERT(dcdcInit->em01LoadCurrent_mA <= dcdcInit->maxCurrent_mA);\r
+\r
+ /* DCDC low-noise supports max 200mA */\r
+ if (dcdcInit->dcdcMode == emuDcdcMode_LowNoise)\r
+ {\r
+ EFM_ASSERT(dcdcInit->em01LoadCurrent_mA <= 200);\r
+ }\r
+\r
+ /* EM2, 3 and 4 current above 100uA is not supported */\r
+ EFM_ASSERT(dcdcInit->em234LoadCurrent_uA <= 100);\r
+\r
+ /* Decode LP comparator bias for EM0/1 and EM2/3 */\r
+ lpCmpBiasSel = EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS1;\r
+ if (dcdcInit->em234LoadCurrent_uA <= 10)\r
+ {\r
+ lpCmpBiasSel = EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS0;\r
+ }\r
+\r
+ /* Set DCDC low-power mode comparator bias selection */\r
+ EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~(_EMU_DCDCMISCCTRL_LPCMPBIAS_MASK\r
+ | _EMU_DCDCMISCCTRL_LNFORCECCM_MASK))\r
+ | ((uint32_t)lpCmpBiasSel\r
+ | (uint32_t)dcdcInit->lnTransientMode);\r
+\r
+ /* Set recommended and validated current optimization settings */\r
+ ValidatedConfigSet();\r
+\r
+ /* Set the maximum current that the DCDC can draw from the power source */\r
+ maxCurrentSet(dcdcInit->maxCurrent_mA);\r
+\r
+ /* Optimize LN slice based on given load current estimate */\r
+ EMU_DCDCOptimizeSlice(dcdcInit->em01LoadCurrent_mA);\r
+\r
+ /* Set DCDC output voltage */\r
+ dcdcOutput_mVout = dcdcInit->mVout;\r
+ if (!EMU_DCDCOutputVoltageSet(dcdcOutput_mVout, true, true))\r
+ {\r
+ EFM_ASSERT(false);\r
+ /* Return when assertions are disabled */\r
+ return false;\r
+ }\r
+\r
+ /* Set EM0 DCDC operating mode. Output voltage set in EMU_DCDCOutputVoltageSet()\r
+ above takes effect if mode is changed from bypass here. */\r
+ EMU_DCDCModeSet(dcdcInit->dcdcMode);\r
+\r
+ /* Select analog peripheral power supply */\r
+ BUS_RegBitWrite(&EMU->PWRCTRL, _EMU_PWRCTRL_ANASW_SHIFT, dcdcInit->anaPeripheralPower ? 1 : 0);\r
+\r
+ return true;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set DCDC output voltage\r
+ *\r
+ * @param[in] mV\r
+ * Target DCDC output voltage in mV\r
+ *\r
+ * @return\r
+ * True if the mV parameter is valid\r
+ ******************************************************************************/\r
+bool EMU_DCDCOutputVoltageSet(uint32_t mV,\r
+ bool setLpVoltage,\r
+ bool setLnVoltage)\r
+{\r
+#if defined( _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_MASK )\r
+\r
+ bool validOutVoltage;\r
+ uint8_t lnMode;\r
+ bool attSet;\r
+ uint32_t attMask;\r
+ uint32_t vrefLow = 0;\r
+ uint32_t vrefHigh = 0;\r
+ uint32_t vrefVal = 0;\r
+ uint32_t mVlow = 0;\r
+ uint32_t mVhigh = 0;\r
+ uint32_t vrefShift;\r
+ uint32_t lpcmpBias;\r
+ volatile uint32_t* ctrlReg;\r
+\r
+ /* Check that the set voltage is within valid range.\r
+ Voltages are obtained from the datasheet. */\r
+ validOutVoltage = false;\r
+ if ((EMU->PWRCFG & _EMU_PWRCFG_PWRCFG_MASK) == EMU_PWRCFG_PWRCFG_DCDCTODVDD)\r
+ {\r
+ validOutVoltage = ((mV >= PWRCFG_DCDCTODVDD_VMIN)\r
+ && (mV <= PWRCFG_DCDCTODVDD_VMAX));\r
+ }\r
+\r
+ if (!validOutVoltage)\r
+ {\r
+ EFM_ASSERT(false);\r
+ /* Return when assertions are disabled */\r
+ return false;\r
+ }\r
+\r
+ /* Populate both LP and LN registers, set control reg pointer and VREF shift. */\r
+ for (lnMode = 0; lnMode <= 1; lnMode++)\r
+ {\r
+ if (((lnMode == 0) && !setLpVoltage)\r
+ || ((lnMode == 1) && !setLnVoltage))\r
+ {\r
+ continue;\r
+ }\r
+\r
+ ctrlReg = (lnMode ? &EMU->DCDCLNVCTRL : &EMU->DCDCLPVCTRL);\r
+ vrefShift = (lnMode ? _EMU_DCDCLNVCTRL_LNVREF_SHIFT\r
+ : _EMU_DCDCLPVCTRL_LPVREF_SHIFT);\r
+\r
+ /* Set attenuation to use */\r
+ attSet = (mV > 1800);\r
+ if (attSet)\r
+ {\r
+ mVlow = 1800;\r
+ mVhigh = 3000;\r
+ attMask = (lnMode ? EMU_DCDCLNVCTRL_LNATT : EMU_DCDCLPVCTRL_LPATT);\r
+ }\r
+ else\r
+ {\r
+ mVlow = 1200;\r
+ mVhigh = 1800;\r
+ attMask = 0;\r
+ }\r
+\r
+ /* Get 2-point calib data from DEVINFO, calculate trimming and set voltege */\r
+ if (lnMode)\r
+ {\r
+ /* Set low-noise DCDC output voltage tuning */\r
+ if (attSet)\r
+ {\r
+ vrefLow = DEVINFO->DCDCLNVCTRL0;\r
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_MASK)\r
+ >> _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_SHIFT;\r
+ vrefLow = (vrefLow & _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_MASK)\r
+ >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_SHIFT;\r
+ }\r
+ else\r
+ {\r
+ vrefLow = DEVINFO->DCDCLNVCTRL0;\r
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_MASK)\r
+ >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_SHIFT;\r
+ vrefLow = (vrefLow & _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_MASK)\r
+ >> _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_SHIFT;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* Set low-power DCDC output voltage tuning */\r
+\r
+ /* Get LPCMPBIAS and make sure masks are not overlayed */\r
+ lpcmpBias = EMU->DCDCMISCCTRL & _EMU_DCDCMISCCTRL_LPCMPBIAS_MASK;\r
+ EFM_ASSERT(!(_EMU_DCDCMISCCTRL_LPCMPBIAS_MASK & attMask));\r
+ switch (attMask | lpcmpBias)\r
+ {\r
+ case EMU_DCDCLPVCTRL_LPATT | EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS0:\r
+ vrefLow = DEVINFO->DCDCLPVCTRL2;\r
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_SHIFT;\r
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_SHIFT;\r
+ break;\r
+\r
+ case EMU_DCDCLPVCTRL_LPATT | EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS1:\r
+ vrefLow = DEVINFO->DCDCLPVCTRL2;\r
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_SHIFT;\r
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_SHIFT;\r
+ break;\r
+\r
+ case EMU_DCDCLPVCTRL_LPATT | EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS2:\r
+ vrefLow = DEVINFO->DCDCLPVCTRL3;\r
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_SHIFT;\r
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_SHIFT;\r
+ break;\r
+\r
+ case EMU_DCDCLPVCTRL_LPATT | EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS3:\r
+ vrefLow = DEVINFO->DCDCLPVCTRL3;\r
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_SHIFT;\r
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_SHIFT;\r
+ break;\r
+\r
+ case EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS0:\r
+ vrefLow = DEVINFO->DCDCLPVCTRL0;\r
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL0_1V8LPATT0LPCMPBIAS0_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL0_1V8LPATT0LPCMPBIAS0_SHIFT;\r
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL0_1V2LPATT0LPCMPBIAS0_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL0_1V2LPATT0LPCMPBIAS0_SHIFT;\r
+ break;\r
+\r
+ case EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS1:\r
+ vrefLow = DEVINFO->DCDCLPVCTRL0;\r
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL0_1V8LPATT0LPCMPBIAS1_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL0_1V8LPATT0LPCMPBIAS1_SHIFT;\r
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL0_1V2LPATT0LPCMPBIAS1_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL0_1V2LPATT0LPCMPBIAS1_SHIFT;\r
+ break;\r
+\r
+ case EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS2:\r
+ vrefLow = DEVINFO->DCDCLPVCTRL1;\r
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL1_1V8LPATT0LPCMPBIAS2_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL1_1V8LPATT0LPCMPBIAS2_SHIFT;\r
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL1_1V2LPATT0LPCMPBIAS2_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL1_1V2LPATT0LPCMPBIAS2_SHIFT;\r
+ break;\r
+\r
+ case EMU_DCDCMISCCTRL_LPCMPBIAS_BIAS3:\r
+ vrefLow = DEVINFO->DCDCLPVCTRL1;\r
+ vrefHigh = (vrefLow & _DEVINFO_DCDCLPVCTRL1_1V8LPATT0LPCMPBIAS3_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL1_1V8LPATT0LPCMPBIAS3_SHIFT;\r
+ vrefLow = (vrefLow & _DEVINFO_DCDCLPVCTRL1_1V2LPATT0LPCMPBIAS3_MASK)\r
+ >> _DEVINFO_DCDCLPVCTRL1_1V2LPATT0LPCMPBIAS3_SHIFT;\r
+ break;\r
+\r
+ default:\r
+ EFM_ASSERT(false);\r
+ break;\r
+ }\r
+\r
+ /* Load LP comparator hysteresis calibration */\r
+ if(!(LpCmpHystCalibrationLoad(attSet, lpcmpBias >> _EMU_DCDCMISCCTRL_LPCMPBIAS_SHIFT)))\r
+ {\r
+ EFM_ASSERT(false);\r
+ /* Return when assertions are disabled */\r
+ return false;\r
+ }\r
+ } /* Low-nise / low-power mode */\r
+\r
+\r
+ /* Check for valid 2-point trim values */\r
+ if ((vrefLow == 0xFF) && (vrefHigh == 0xFF))\r
+ {\r
+ EFM_ASSERT(false);\r
+ /* Return when assertions are disabled */\r
+ return false;\r
+ }\r
+\r
+ /* Calculate and set voltage trim */\r
+ vrefVal = ((mV - mVlow) * (vrefHigh - vrefLow)) / (mVhigh - mVlow);\r
+ vrefVal += vrefLow;\r
+\r
+ /* Range check */\r
+ if ((vrefVal > vrefHigh) || (vrefVal < vrefLow))\r
+ {\r
+ EFM_ASSERT(false);\r
+ /* Return when assertions are disabled */\r
+ return false;\r
+ }\r
+\r
+ /* Update DCDCLNVCTRL/DCDCLPVCTRL */\r
+ *ctrlReg = (vrefVal << vrefShift) | attMask;\r
+ }\r
+#endif\r
+ return true;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Optimize DCDC slice count based on the estimated average load current\r
+ * in EM0\r
+ *\r
+ * @param[in] mAEm0LoadCurrent\r
+ * Estimated average EM0 load current in mA.\r
+ ******************************************************************************/\r
+void EMU_DCDCOptimizeSlice(uint32_t mAEm0LoadCurrent)\r
+{\r
+ uint32_t sliceCount = 0;\r
+ uint32_t rcoBand = (EMU->DCDCLNFREQCTRL & _EMU_DCDCLNFREQCTRL_RCOBAND_MASK)\r
+ >> _EMU_DCDCLNFREQCTRL_RCOBAND_SHIFT;\r
+\r
+ /* Set recommended slice count */\r
+ if ((EMU->DCDCMISCCTRL & _EMU_DCDCMISCCTRL_LNFORCECCM_MASK) && (rcoBand >= EMU_DcdcLnRcoBand_5MHz))\r
+ {\r
+ if (mAEm0LoadCurrent < 20)\r
+ {\r
+ sliceCount = 4;\r
+ }\r
+ else if ((mAEm0LoadCurrent >= 20) && (mAEm0LoadCurrent < 40))\r
+ {\r
+ sliceCount = 8;\r
+ }\r
+ else\r
+ {\r
+ sliceCount = 16;\r
+ }\r
+ }\r
+ else if ((!(EMU->DCDCMISCCTRL & _EMU_DCDCMISCCTRL_LNFORCECCM_MASK)) && (rcoBand <= EMU_DcdcLnRcoBand_4MHz))\r
+ {\r
+ if (mAEm0LoadCurrent < 10)\r
+ {\r
+ sliceCount = 4;\r
+ }\r
+ else if ((mAEm0LoadCurrent >= 10) && (mAEm0LoadCurrent < 20))\r
+ {\r
+ sliceCount = 8;\r
+ }\r
+ else\r
+ {\r
+ sliceCount = 16;\r
+ }\r
+ }\r
+ else if ((EMU->DCDCMISCCTRL & _EMU_DCDCMISCCTRL_LNFORCECCM_MASK) && (rcoBand <= EMU_DcdcLnRcoBand_4MHz))\r
+ {\r
+ if (mAEm0LoadCurrent < 40)\r
+ {\r
+ sliceCount = 8;\r
+ }\r
+ else\r
+ {\r
+ sliceCount = 16;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* This configuration is not recommended. EMU_DCDCInit() applies a recommended\r
+ configuration. */\r
+ EFM_ASSERT(false);\r
+ }\r
+\r
+ /* The selected silices are PSLICESEL + 1 */\r
+ sliceCount--;\r
+\r
+ /* Apply slice count to both N and P slice */\r
+ sliceCount = (sliceCount << _EMU_DCDCMISCCTRL_PFETCNT_SHIFT\r
+ | sliceCount << _EMU_DCDCMISCCTRL_NFETCNT_SHIFT);\r
+ EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~(_EMU_DCDCMISCCTRL_PFETCNT_MASK\r
+ | _EMU_DCDCMISCCTRL_NFETCNT_MASK))\r
+ | sliceCount;\r
+\r
+ /* Update current limit configuration as it depends on the slice configuration. */\r
+ maxCurrentUpdate();\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set DCDC Low-noise RCO band.\r
+ *\r
+ * @param[in] band\r
+ * RCO band to set.\r
+ ******************************************************************************/\r
+void EMU_DCDCLnRcoBandSet(EMU_DcdcLnRcoBand_TypeDef band)\r
+{\r
+ EMU->DCDCLNFREQCTRL = (EMU->DCDCLNFREQCTRL & ~_EMU_DCDCLNFREQCTRL_RCOBAND_MASK)\r
+ | (band << _EMU_DCDCLNFREQCTRL_RCOBAND_SHIFT);\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Power off the DCDC regulator.\r
+ *\r
+ * @details\r
+ * This function powers off the DCDC controller. This function should only be\r
+ * used if the external power circuit is wired for no DCDC. If the external power\r
+ * circuit is wired for DCDC usage, then use EMU_DCDCInit() and set the\r
+ * DCDC in bypass mode to disable DCDC.\r
+ *\r
+ * @return\r
+ * Return false if the DCDC could not be disabled.\r
+ ******************************************************************************/\r
+bool EMU_DCDCPowerOff(void)\r
+{\r
+ /* Set power configuration to hard bypass */\r
+ EMU->PWRCFG = 0xF;\r
+ if ((EMU->PWRCFG & _EMU_PWRCFG_PWRCFG_MASK) != 0xF)\r
+ {\r
+ EFM_ASSERT(false);\r
+ /* Return when assertions are disabled */\r
+ return false;\r
+ }\r
+\r
+ /* Set DCDC to OFF and disable LP in EM2/3/4 */\r
+ EMU->DCDCCTRL = EMU_DCDCCTRL_DCDCMODE_OFF;\r
+ return true;\r
+}\r
+#endif\r
+\r
+\r
+#if defined( EMU_STATUS_VMONRDY )\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+__STATIC_INLINE uint32_t vmonMilliVoltToCoarseThreshold(int mV)\r
+{\r
+ return (mV - 1200) / 200;\r
+}\r
+\r
+__STATIC_INLINE uint32_t vmonMilliVoltToFineThreshold(int mV, uint32_t coarseThreshold)\r
+{\r
+ return (mV - 1200 - (coarseThreshold * 200)) / 20;\r
+}\r
+/** @endcond */\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Initialize VMON channel.\r
+ *\r
+ * @details\r
+ * Initialize a VMON channel without hysteresis. If the channel supports\r
+ * separate rise and fall triggers, both thresholds will be set to the same\r
+ * value.\r
+ *\r
+ * @param[in] vmonInit\r
+ * VMON initialization struct\r
+ ******************************************************************************/\r
+void EMU_VmonInit(EMU_VmonInit_TypeDef *vmonInit)\r
+{\r
+ uint32_t thresholdCoarse, thresholdFine;\r
+ EFM_ASSERT((vmonInit->threshold >= 1200) && (vmonInit->threshold <= 3980));\r
+\r
+ thresholdCoarse = vmonMilliVoltToCoarseThreshold(vmonInit->threshold);\r
+ thresholdFine = vmonMilliVoltToFineThreshold(vmonInit->threshold, thresholdCoarse);\r
+\r
+ switch(vmonInit->channel)\r
+ {\r
+ case emuVmonChannel_AVDD:\r
+ EMU->VMONAVDDCTRL = (thresholdCoarse << _EMU_VMONAVDDCTRL_RISETHRESCOARSE_SHIFT)\r
+ | (thresholdFine << _EMU_VMONAVDDCTRL_RISETHRESFINE_SHIFT)\r
+ | (thresholdCoarse << _EMU_VMONAVDDCTRL_FALLTHRESCOARSE_SHIFT)\r
+ | (thresholdFine << _EMU_VMONAVDDCTRL_FALLTHRESFINE_SHIFT)\r
+ | (vmonInit->riseWakeup ? EMU_VMONAVDDCTRL_RISEWU : 0)\r
+ | (vmonInit->fallWakeup ? EMU_VMONAVDDCTRL_FALLWU : 0)\r
+ | (vmonInit->enable ? EMU_VMONAVDDCTRL_EN : 0);\r
+ break;\r
+ case emuVmonChannel_ALTAVDD:\r
+ EMU->VMONALTAVDDCTRL = (thresholdCoarse << _EMU_VMONALTAVDDCTRL_THRESCOARSE_SHIFT)\r
+ | (thresholdFine << _EMU_VMONALTAVDDCTRL_THRESFINE_SHIFT)\r
+ | (vmonInit->riseWakeup ? EMU_VMONALTAVDDCTRL_RISEWU : 0)\r
+ | (vmonInit->fallWakeup ? EMU_VMONALTAVDDCTRL_FALLWU : 0)\r
+ | (vmonInit->enable ? EMU_VMONALTAVDDCTRL_EN : 0);\r
+ break;\r
+ case emuVmonChannel_DVDD:\r
+ EMU->VMONDVDDCTRL = (thresholdCoarse << _EMU_VMONDVDDCTRL_THRESCOARSE_SHIFT)\r
+ | (thresholdFine << _EMU_VMONDVDDCTRL_THRESFINE_SHIFT)\r
+ | (vmonInit->riseWakeup ? EMU_VMONDVDDCTRL_RISEWU : 0)\r
+ | (vmonInit->fallWakeup ? EMU_VMONDVDDCTRL_FALLWU : 0)\r
+ | (vmonInit->enable ? EMU_VMONDVDDCTRL_EN : 0);\r
+ break;\r
+ case emuVmonChannel_IOVDD0:\r
+ EMU->VMONIO0CTRL = (thresholdCoarse << _EMU_VMONIO0CTRL_THRESCOARSE_SHIFT)\r
+ | (thresholdFine << _EMU_VMONIO0CTRL_THRESFINE_SHIFT)\r
+ | (vmonInit->retDisable ? EMU_VMONIO0CTRL_RETDIS : 0)\r
+ | (vmonInit->riseWakeup ? EMU_VMONIO0CTRL_RISEWU : 0)\r
+ | (vmonInit->fallWakeup ? EMU_VMONIO0CTRL_FALLWU : 0)\r
+ | (vmonInit->enable ? EMU_VMONIO0CTRL_EN : 0);\r
+ break;\r
+ default:\r
+ EFM_ASSERT(false);\r
+ return;\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Initialize VMON channel with hysteresis (separate rise and fall triggers).\r
+ *\r
+ * @details\r
+ * Initialize a VMON channel which supports hysteresis. The AVDD channel is\r
+ * the only channel to support separate rise and fall triggers.\r
+ *\r
+ * @param[in] vmonInit\r
+ * VMON Hysteresis initialization struct\r
+ ******************************************************************************/\r
+void EMU_VmonHystInit(EMU_VmonHystInit_TypeDef *vmonInit)\r
+{\r
+ uint32_t riseThresholdCoarse, riseThresholdFine, fallThresholdCoarse, fallThresholdFine;\r
+ /* VMON supports voltages between 1200 mV and 3980 mV (inclusive) in 20 mV increments */\r
+ EFM_ASSERT((vmonInit->riseThreshold >= 1200) && (vmonInit->riseThreshold < 4000));\r
+ EFM_ASSERT((vmonInit->fallThreshold >= 1200) && (vmonInit->fallThreshold < 4000));\r
+ /* Fall threshold has to be lower than rise threshold */\r
+ EFM_ASSERT(vmonInit->fallThreshold <= vmonInit->riseThreshold);\r
+\r
+ riseThresholdCoarse = vmonMilliVoltToCoarseThreshold(vmonInit->riseThreshold);\r
+ riseThresholdFine = vmonMilliVoltToFineThreshold(vmonInit->riseThreshold, riseThresholdCoarse);\r
+ fallThresholdCoarse = vmonMilliVoltToCoarseThreshold(vmonInit->fallThreshold);\r
+ fallThresholdFine = vmonMilliVoltToFineThreshold(vmonInit->fallThreshold, fallThresholdCoarse);\r
+\r
+ switch(vmonInit->channel)\r
+ {\r
+ case emuVmonChannel_AVDD:\r
+ EMU->VMONAVDDCTRL = (riseThresholdCoarse << _EMU_VMONAVDDCTRL_RISETHRESCOARSE_SHIFT)\r
+ | (riseThresholdFine << _EMU_VMONAVDDCTRL_RISETHRESFINE_SHIFT)\r
+ | (fallThresholdCoarse << _EMU_VMONAVDDCTRL_FALLTHRESCOARSE_SHIFT)\r
+ | (fallThresholdFine << _EMU_VMONAVDDCTRL_FALLTHRESFINE_SHIFT)\r
+ | (vmonInit->riseWakeup ? EMU_VMONAVDDCTRL_RISEWU : 0)\r
+ | (vmonInit->fallWakeup ? EMU_VMONAVDDCTRL_FALLWU : 0)\r
+ | (vmonInit->enable ? EMU_VMONAVDDCTRL_EN : 0);\r
+ break;\r
+ default:\r
+ EFM_ASSERT(false);\r
+ return;\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Enable or disable a VMON channel\r
+ *\r
+ * @param[in] channel\r
+ * VMON channel to enable/disable\r
+ *\r
+ * @param[in] enable\r
+ * Whether to enable or disable\r
+ ******************************************************************************/\r
+void EMU_VmonEnable(EMU_VmonChannel_TypeDef channel, bool enable)\r
+{\r
+ uint32_t volatile * reg;\r
+ uint32_t bit;\r
+\r
+ switch(channel)\r
+ {\r
+ case emuVmonChannel_AVDD:\r
+ reg = &(EMU->VMONAVDDCTRL);\r
+ bit = _EMU_VMONAVDDCTRL_EN_SHIFT;\r
+ break;\r
+ case emuVmonChannel_ALTAVDD:\r
+ reg = &(EMU->VMONALTAVDDCTRL);\r
+ bit = _EMU_VMONALTAVDDCTRL_EN_SHIFT;\r
+ break;\r
+ case emuVmonChannel_DVDD:\r
+ reg = &(EMU->VMONDVDDCTRL);\r
+ bit = _EMU_VMONDVDDCTRL_EN_SHIFT;\r
+ break;\r
+ case emuVmonChannel_IOVDD0:\r
+ reg = &(EMU->VMONIO0CTRL);\r
+ bit = _EMU_VMONIO0CTRL_EN_SHIFT;\r
+ break;\r
+ default:\r
+ EFM_ASSERT(false);\r
+ return;\r
+ }\r
+\r
+ BUS_RegBitWrite(reg, bit, enable);\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the status of a voltage monitor channel.\r
+ *\r
+ * @param[in] channel\r
+ * VMON channel to get status for\r
+ *\r
+ * @return\r
+ * Status of the selected VMON channel. True if channel is triggered.\r
+ ******************************************************************************/\r
+bool EMU_VmonChannelStatusGet(EMU_VmonChannel_TypeDef channel)\r
+{\r
+ uint32_t bit;\r
+ switch(channel)\r
+ {\r
+ case emuVmonChannel_AVDD:\r
+ bit = _EMU_STATUS_VMONAVDD_SHIFT;\r
+ break;\r
+ case emuVmonChannel_ALTAVDD:\r
+ bit = _EMU_STATUS_VMONALTAVDD_SHIFT;\r
+ break;\r
+ case emuVmonChannel_DVDD:\r
+ bit = _EMU_STATUS_VMONDVDD_SHIFT;\r
+ break;\r
+ case emuVmonChannel_IOVDD0:\r
+ bit = _EMU_STATUS_VMONIO0_SHIFT;\r
+ break;\r
+ default:\r
+ EFM_ASSERT(false);\r
+ bit = 0;\r
+ }\r
+\r
+ return BUS_RegBitRead(&EMU->STATUS, bit);\r
+}\r
+#endif /* EMU_STATUS_VMONRDY */\r
+\r
+/** @} (end addtogroup EMU) */\r
+/** @} (end addtogroup EM_Library) */\r
+#endif /* __EM_EMU_H */\r
--- /dev/null
+/***************************************************************************//**\r
+ * @file em_gpio.c\r
+ * @brief General Purpose IO (GPIO) peripheral API\r
+ * devices.\r
+ * @version 4.2.1\r
+ *******************************************************************************\r
+ * @section License\r
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>\r
+ *******************************************************************************\r
+ *\r
+ * Permission is granted to anyone to use this software for any purpose,\r
+ * including commercial applications, and to alter it and redistribute it\r
+ * freely, subject to the following restrictions:\r
+ *\r
+ * 1. The origin of this software must not be misrepresented; you must not\r
+ * claim that you wrote the original software.\r
+ * 2. Altered source versions must be plainly marked as such, and must not be\r
+ * misrepresented as being the original software.\r
+ * 3. This notice may not be removed or altered from any source distribution.\r
+ *\r
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
+ * obligation to support this Software. Silicon Labs is providing the\r
+ * Software "AS IS", with no express or implied warranties of any kind,\r
+ * including, but not limited to, any implied warranties of merchantability\r
+ * or fitness for any particular purpose or warranties against infringement\r
+ * of any proprietary rights of a third party.\r
+ *\r
+ * Silicon Labs will not be liable for any consequential, incidental, or\r
+ * special damages, or any other relief, or for any claim by any third party,\r
+ * arising from your use of this Software.\r
+ *\r
+ ******************************************************************************/\r
+\r
+\r
+#include "em_gpio.h"\r
+\r
+#if defined(GPIO_COUNT) && (GPIO_COUNT > 0)\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup EM_Library\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup GPIO\r
+ * @brief General Purpose Input/Output (GPIO) API\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/*******************************************************************************\r
+ ******************************* DEFINES ***********************************\r
+ ******************************************************************************/\r
+\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+\r
+/** Validation of pin typically usable in assert statements. */\r
+#define GPIO_DRIVEMODE_VALID(mode) ((mode) <= 3)\r
+#define GPIO_STRENGHT_VALID(strenght) (!((strenght) & \\r
+ ~(_GPIO_P_CTRL_DRIVESTRENGTH_MASK \\r
+ | _GPIO_P_CTRL_DRIVESTRENGTHALT_MASK)))\r
+/** @endcond */\r
+\r
+\r
+/*******************************************************************************\r
+ ************************** GLOBAL FUNCTIONS *******************************\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Sets the pin location of the debug pins (Serial Wire interface).\r
+ *\r
+ * @note\r
+ * Changing the pins used for debugging uncontrolled, may result in a lockout.\r
+ *\r
+ * @param[in] location\r
+ * The debug pin location to use (0-3).\r
+ ******************************************************************************/\r
+void GPIO_DbgLocationSet(unsigned int location)\r
+{\r
+#if defined ( _GPIO_ROUTE_SWLOCATION_MASK )\r
+ EFM_ASSERT(location < AFCHANLOC_MAX);\r
+\r
+ GPIO->ROUTE = (GPIO->ROUTE & ~_GPIO_ROUTE_SWLOCATION_MASK) |\r
+ (location << _GPIO_ROUTE_SWLOCATION_SHIFT);\r
+#else\r
+ (void)location;\r
+#endif\r
+}\r
+\r
+#if defined (_GPIO_P_CTRL_DRIVEMODE_MASK)\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Sets the drive mode for a GPIO port.\r
+ *\r
+ * @param[in] port\r
+ * The GPIO port to access.\r
+ *\r
+ * @param[in] mode\r
+ * Drive mode to use for port.\r
+ ******************************************************************************/\r
+void GPIO_DriveModeSet(GPIO_Port_TypeDef port, GPIO_DriveMode_TypeDef mode)\r
+{\r
+ EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_DRIVEMODE_VALID(mode));\r
+\r
+ GPIO->P[port].CTRL = (GPIO->P[port].CTRL & ~(_GPIO_P_CTRL_DRIVEMODE_MASK))\r
+ | (mode << _GPIO_P_CTRL_DRIVEMODE_SHIFT);\r
+}\r
+#endif\r
+\r
+\r
+#if defined (_GPIO_P_CTRL_DRIVESTRENGTH_MASK)\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Sets the drive strength for a GPIO port.\r
+ *\r
+ * @param[in] port\r
+ * The GPIO port to access.\r
+ *\r
+ * @param[in] strength\r
+ * Drive strength to use for port.\r
+ ******************************************************************************/\r
+void GPIO_DriveStrengthSet(GPIO_Port_TypeDef port,\r
+ GPIO_DriveStrength_TypeDef strength)\r
+{\r
+ EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_STRENGHT_VALID(strength));\r
+ BUS_RegMaskedWrite(&GPIO->P[port].CTRL,\r
+ _GPIO_P_CTRL_DRIVESTRENGTH_MASK | _GPIO_P_CTRL_DRIVESTRENGTHALT_MASK,\r
+ strength);\r
+}\r
+#endif\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Configure GPIO interrupt.\r
+ *\r
+ * @details\r
+ * If reconfiguring a GPIO interrupt that is already enabled, it is generally\r
+ * recommended to disable it first, see GPIO_Disable().\r
+ *\r
+ * The actual GPIO interrupt handler must be in place before enabling the\r
+ * interrupt.\r
+ *\r
+ * Notice that any pending interrupt for the selected pin is cleared by this\r
+ * function.\r
+ *\r
+ * @note\r
+ * A certain pin number can only be associated with one port. Ie, if GPIO\r
+ * interrupt 1 is assigned to port A/pin 1, then it is not possibly to use\r
+ * pin 1 from any other ports for interrupts. Please refer to the reference\r
+ * manual.\r
+ *\r
+ * @param[in] port\r
+ * The port to associate with @p pin.\r
+ *\r
+ * @param[in] pin\r
+ * The GPIO interrupt number (= port pin).\r
+ *\r
+ * @param[in] risingEdge\r
+ * Set to true if interrupts shall be enabled on rising edge, otherwise false.\r
+ *\r
+ * @param[in] fallingEdge\r
+ * Set to true if interrupts shall be enabled on falling edge, otherwise false.\r
+ *\r
+ * @param[in] enable\r
+ * Set to true if interrupt shall be enabled after configuration completed,\r
+ * false to leave disabled. See GPIO_IntDisable() and GPIO_IntEnable().\r
+ ******************************************************************************/\r
+void GPIO_IntConfig(GPIO_Port_TypeDef port,\r
+ unsigned int pin,\r
+ bool risingEdge,\r
+ bool fallingEdge,\r
+ bool enable)\r
+{\r
+ uint32_t tmp;\r
+\r
+ EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));\r
+\r
+ /* There are two registers controlling the interrupt configuration:\r
+ * The EXTIPSELL register controls pins 0-7 and EXTIPSELH controls\r
+ * pins 8-15. */\r
+ if (pin < 8)\r
+ {\r
+ BUS_RegMaskedWrite(&GPIO->EXTIPSELL,\r
+ 0xF << (4 * pin),\r
+ port << (4 * pin));\r
+ }\r
+ else\r
+ {\r
+ tmp = pin - 8;\r
+ BUS_RegMaskedWrite(&GPIO->EXTIPSELH,\r
+ 0xF << (4 * tmp),\r
+ port << (4 * tmp));\r
+ }\r
+\r
+ /* Enable/disable rising edge */\r
+ BUS_RegBitWrite(&(GPIO->EXTIRISE), pin, risingEdge);\r
+\r
+ /* Enable/disable falling edge */\r
+ BUS_RegBitWrite(&(GPIO->EXTIFALL), pin, fallingEdge);\r
+\r
+ /* Clear any pending interrupt */\r
+ GPIO->IFC = 1 << pin;\r
+\r
+ /* Finally enable/disable interrupt */\r
+ BUS_RegBitWrite(&(GPIO->IEN), pin, enable);\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Set the mode for a GPIO pin.\r
+ *\r
+ * @param[in] port\r
+ * The GPIO port to access.\r
+ *\r
+ * @param[in] pin\r
+ * The pin number in the port.\r
+ *\r
+ * @param[in] mode\r
+ * The desired pin mode.\r
+ *\r
+ * @param[in] out\r
+ * Value to set for pin in DOUT register. The DOUT setting is important for\r
+ * even some input mode configurations, determining pull-up/down direction.\r
+ ******************************************************************************/\r
+void GPIO_PinModeSet(GPIO_Port_TypeDef port,\r
+ unsigned int pin,\r
+ GPIO_Mode_TypeDef mode,\r
+ unsigned int out)\r
+{\r
+ EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));\r
+\r
+ /* If disabling pin, do not modify DOUT in order to reduce chance for */\r
+ /* glitch/spike (may not be sufficient precaution in all use cases) */\r
+ if (mode != gpioModeDisabled)\r
+ {\r
+ if (out)\r
+ {\r
+ GPIO_PinOutSet(port, pin);\r
+ }\r
+ else\r
+ {\r
+ GPIO_PinOutClear(port, pin);\r
+ }\r
+ }\r
+\r
+ /* There are two registers controlling the pins for each port. The MODEL\r
+ * register controls pins 0-7 and MODEH controls pins 8-15. */\r
+ if (pin < 8)\r
+ {\r
+ BUS_RegMaskedWrite(&GPIO->P[port].MODEL,\r
+ 0xF << (pin * 4),\r
+ mode << (pin * 4));\r
+ }\r
+ else\r
+ {\r
+ BUS_RegMaskedWrite(&GPIO->P[port].MODEH,\r
+ 0xF << ((pin - 8) * 4),\r
+ mode << ((pin - 8) * 4));\r
+ }\r
+\r
+ if (mode == gpioModeDisabled)\r
+ {\r
+ if (out)\r
+ {\r
+ GPIO_PinOutSet(port, pin);\r
+ }\r
+ else\r
+ {\r
+ GPIO_PinOutClear(port, pin);\r
+ }\r
+ }\r
+}\r
+\r
+#if defined( _GPIO_EM4WUEN_MASK )\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Enable GPIO pin wake-up from EM4. When the function exits,\r
+ * EM4 mode can be safely entered.\r
+ *\r
+ * @note\r
+ * It is assumed that the GPIO pin modes are set correctly.\r
+ * Valid modes are @ref gpioModeInput and @ref gpioModeInputPull.\r
+ *\r
+ * @param[in] pinmask\r
+ * Bitmask containing the bitwise logic OR of which GPIO pin(s) to enable.\r
+ * Refer to Reference Manuals for pinmask to GPIO port/pin mapping.\r
+ * @param[in] polaritymask\r
+ * Bitmask containing the bitwise logic OR of GPIO pin(s) wake-up polarity.\r
+ * Refer to Reference Manuals for pinmask to GPIO port/pin mapping.\r
+ *****************************************************************************/\r
+void GPIO_EM4EnablePinWakeup(uint32_t pinmask, uint32_t polaritymask)\r
+{\r
+ EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0);\r
+\r
+#if defined( _GPIO_EM4WUPOL_MASK )\r
+ EFM_ASSERT((polaritymask & ~_GPIO_EM4WUPOL_MASK) == 0);\r
+ GPIO->EM4WUPOL &= ~pinmask; /* Set wakeup polarity */\r
+ GPIO->EM4WUPOL |= pinmask & polaritymask;\r
+#elif defined( _GPIO_EXTILEVEL_MASK )\r
+ EFM_ASSERT((polaritymask & ~_GPIO_EXTILEVEL_MASK) == 0);\r
+ GPIO->EXTILEVEL &= ~pinmask;\r
+ GPIO->EXTILEVEL |= pinmask & polaritymask;\r
+#endif\r
+ GPIO->EM4WUEN |= pinmask; /* Enable wakeup */\r
+\r
+ GPIO_EM4SetPinRetention(true); /* Enable pin retention */\r
+\r
+#if defined( _GPIO_CMD_EM4WUCLR_MASK )\r
+ GPIO->CMD = GPIO_CMD_EM4WUCLR; /* Clear wake-up logic */\r
+#elif defined( _GPIO_IFC_EM4WU_MASK )\r
+ GPIO_IntClear(pinmask);\r
+#endif\r
+}\r
+#endif\r
+\r
+/** @} (end addtogroup GPIO) */\r
+/** @} (end addtogroup EM_Library) */\r
+\r
+#endif /* defined(GPIO_COUNT) && (GPIO_COUNT > 0) */\r
--- /dev/null
+/**************************************************************************//**\r
+ * @file em_int.c\r
+ * @brief Interrupt enable/disable unit API\r
+ * @version 4.2.1\r
+ ******************************************************************************\r
+ * @section License\r
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>\r
+ *******************************************************************************\r
+ *\r
+ * Permission is granted to anyone to use this software for any purpose,\r
+ * including commercial applications, and to alter it and redistribute it\r
+ * freely, subject to the following restrictions:\r
+ *\r
+ * 1. The origin of this software must not be misrepresented; you must not\r
+ * claim that you wrote the original software.\r
+ * 2. Altered source versions must be plainly marked as such, and must not be\r
+ * misrepresented as being the original software.\r
+ * 3. This notice may not be removed or altered from any source distribution.\r
+ *\r
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
+ * obligation to support this Software. Silicon Labs is providing the\r
+ * Software "AS IS", with no express or implied warranties of any kind,\r
+ * including, but not limited to, any implied warranties of merchantability\r
+ * or fitness for any particular purpose or warranties against infringement\r
+ * of any proprietary rights of a third party.\r
+ *\r
+ * Silicon Labs will not be liable for any consequential, incidental, or\r
+ * special damages, or any other relief, or for any claim by any third party,\r
+ * arising from your use of this Software.\r
+ *\r
+ ******************************************************************************/\r
+\r
+#include <stdint.h>\r
+#include "em_int.h"\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup EM_Library\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup INT\r
+ * @brief Safe nesting of interrupt disable/enable API\r
+ * @{\r
+ * @details\r
+ * This module contains functions to safely disable and enable interrupts\r
+ * at CPU level. INT_Disable() disables interrupts globally and increments a lock\r
+ * level counter (counting semaphore). INT_Enable() decrements the lock level \r
+ * counter and enable interrupts if the counter reaches zero.\r
+ *\r
+ * These functions would normally be used to secure critical regions, and \r
+ * to make sure that a critical section that calls into another critical \r
+ * section does not unintentionally terminate the callee critical section.\r
+ *\r
+ * These functions should also be used inside interrupt handlers:\r
+ * @verbatim\r
+ * void SysTick_Handler(void)\r
+ * {\r
+ * INT_Disable();\r
+ * .\r
+ * .\r
+ * .\r
+ * INT_Enable();\r
+ * }\r
+ * @endverbatim\r
+ ******************************************************************************/\r
+\r
+/** Interrupt lock level counter. Set to zero initially as we normally enter\r
+ * main with interrupts enabled */\r
+uint32_t INT_LockCnt = 0;\r
+\r
+/** @} (end addtogroup INT) */\r
+/** @} (end addtogroup EM_Library) */\r
--- /dev/null
+/***************************************************************************//**\r
+ * @file\r
+ * @brief Real Time Counter with Calendar (RTCC) Peripheral API\r
+ * @version 4.2.1\r
+ *******************************************************************************\r
+ * @section License\r
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>\r
+ *******************************************************************************\r
+ *\r
+ * Permission is granted to anyone to use this software for any purpose,\r
+ * including commercial applications, and to alter it and redistribute it\r
+ * freely, subject to the following restrictions:\r
+ *\r
+ * 1. The origin of this software must not be misrepresented; you must not\r
+ * claim that you wrote the original software.\r
+ * 2. Altered source versions must be plainly marked as such, and must not be\r
+ * misrepresented as being the original software.\r
+ * 3. This notice may not be removed or altered from any source distribution.\r
+ *\r
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
+ * obligation to support this Software. Silicon Labs is providing the\r
+ * Software "AS IS", with no express or implied warranties of any kind,\r
+ * including, but not limited to, any implied warranties of merchantability\r
+ * or fitness for any particular purpose or warranties against infringement\r
+ * of any proprietary rights of a third party.\r
+ *\r
+ * Silicon Labs will not be liable for any consequential, incidental, or\r
+ * special damages, or any other relief, or for any claim by any third party,\r
+ * arising from your use of this Software.\r
+ *\r
+ ******************************************************************************/\r
+\r
+#include "em_rtcc.h"\r
+#if defined( RTCC_COUNT ) && ( RTCC_COUNT == 1 )\r
+#include "em_bus.h"\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup EM_Library\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup RTCC\r
+ * @brief Real Time Counter (RTCC) Peripheral API\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/*******************************************************************************\r
+ ******************************* DEFINES ***********************************\r
+ ******************************************************************************/\r
+\r
+/*******************************************************************************\r
+ ************************** LOCAL FUNCTIONS ********************************\r
+ ******************************************************************************/\r
+\r
+/*******************************************************************************\r
+ ************************** GLOBAL FUNCTIONS *******************************\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Configure the selected capture/compare channel of the RTCC.\r
+ *\r
+ * @details\r
+ * Use this function to configure a RTCC channel.\r
+ * Select capture/compare mode, match output action, overflow output action\r
+ * and PRS input configuration.\r
+ * Refer to the configuration structure @ref RTCC_CCChConf_TypeDef for more\r
+ * details.\r
+ *\r
+ * @param[in] ch\r
+ * Channel selector.\r
+ *\r
+ * @param[in] confPtr\r
+ * Pointer to configuration structure.\r
+ ******************************************************************************/\r
+void RTCC_ChannelInit( int ch, RTCC_CCChConf_TypeDef const *confPtr )\r
+{\r
+ EFM_ASSERT( RTCC_CH_VALID( ch ) );\r
+ EFM_ASSERT( (uint32_t)confPtr->compMask\r
+ < ( _RTCC_CC_CTRL_COMPMASK_MASK >> _RTCC_CC_CTRL_COMPMASK_SHIFT )\r
+ + 1 );\r
+\r
+ /** Configure the selected capture/compare channel. */\r
+ RTCC->CC[ch].CTRL = ( (uint32_t)confPtr->chMode << _RTCC_CC_CTRL_MODE_SHIFT )\r
+ | ( (uint32_t)confPtr->compMatchOutAction << _RTCC_CC_CTRL_CMOA_SHIFT )\r
+ | ( (uint32_t)confPtr->prsSel << _RTCC_CC_CTRL_PRSSEL_SHIFT )\r
+ | ( (uint32_t)confPtr->inputEdgeSel << _RTCC_CC_CTRL_ICEDGE_SHIFT )\r
+ | ( (uint32_t)confPtr->compBase << _RTCC_CC_CTRL_COMPBASE_SHIFT )\r
+ | ( (uint32_t)confPtr->compMask << _RTCC_CC_CTRL_COMPMASK_SHIFT )\r
+ | ( (uint32_t)confPtr->dayCompMode << _RTCC_CC_CTRL_DAYCC_SHIFT );\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Enable/disable RTCC.\r
+ *\r
+ * @param[in] enable\r
+ * True to enable RTCC, false to disable.\r
+ ******************************************************************************/\r
+void RTCC_Enable( bool enable )\r
+{\r
+ /* Bitbanding the enable bit in the CTRL register (atomic). */\r
+ BUS_RegBitWrite((&RTCC->CTRL), _RTCC_CTRL_ENABLE_SHIFT, enable);\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Initialize RTCC.\r
+ *\r
+ * @details\r
+ * Note that the compare values must be set separately with RTCC_CompareSet().\r
+ * That should probably be done prior to the use of this function if\r
+ * configuring the RTCC to start when initialization is completed.\r
+ *\r
+ * @param[in] init\r
+ * Pointer to RTCC initialization structure.\r
+ ******************************************************************************/\r
+void RTCC_Init( const RTCC_Init_TypeDef *init )\r
+{\r
+ RTCC->CTRL = ( (uint32_t)init->enable << _RTCC_CTRL_ENABLE_SHIFT )\r
+ | ( (uint32_t)init->debugRun << _RTCC_CTRL_DEBUGRUN_SHIFT )\r
+ | ( (uint32_t)init->precntWrapOnCCV0 << _RTCC_CTRL_PRECCV0TOP_SHIFT )\r
+ | ( (uint32_t)init->cntWrapOnCCV1 << _RTCC_CTRL_CCV1TOP_SHIFT )\r
+ | ( (uint32_t)init->presc << _RTCC_CTRL_CNTPRESC_SHIFT )\r
+ | ( (uint32_t)init->prescMode << _RTCC_CTRL_CNTTICK_SHIFT )\r
+#if defined(_RTCC_CTRL_BUMODETSEN_MASK)\r
+ | ( (uint32_t)init->enaBackupModeSet << _RTCC_CTRL_BUMODETSEN_SHIFT )\r
+#endif\r
+ | ( (uint32_t)init->enaOSCFailDetect << _RTCC_CTRL_OSCFDETEN_SHIFT )\r
+ | ( (uint32_t)init->cntMode << _RTCC_CTRL_CNTMODE_SHIFT )\r
+ | ( (uint32_t)init->disLeapYearCorr << _RTCC_CTRL_LYEARCORRDIS_SHIFT );\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Restore RTCC to its reset state.\r
+ ******************************************************************************/\r
+void RTCC_Reset( void )\r
+{\r
+ int i;\r
+\r
+ /* Restore all RTCC registers to their default values. */\r
+ RTCC_Unlock();\r
+ RTCC->CTRL = _RTCC_CTRL_RESETVALUE;\r
+ RTCC->PRECNT = _RTCC_PRECNT_RESETVALUE;\r
+ RTCC->CNT = _RTCC_CNT_RESETVALUE;\r
+ RTCC->TIME = _RTCC_TIME_RESETVALUE;\r
+ RTCC->DATE = _RTCC_DATE_RESETVALUE;\r
+ RTCC->IEN = _RTCC_IEN_RESETVALUE;\r
+ RTCC->IFC = _RTCC_IFC_MASK;\r
+ RTCC_StatusClear();\r
+ RTCC->EM4WUEN = _RTCC_EM4WUEN_RESETVALUE;\r
+\r
+ for (i = 0; i < 3; i++)\r
+ {\r
+ RTCC->CC[i].CTRL = _RTCC_CC_CTRL_RESETVALUE;\r
+ RTCC->CC[i].CCV = _RTCC_CC_CCV_RESETVALUE;\r
+ RTCC->CC[i].TIME = _RTCC_CC_TIME_RESETVALUE;\r
+ RTCC->CC[i].DATE = _RTCC_CC_DATE_RESETVALUE;\r
+ }\r
+}\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Clear STATUS register.\r
+ ******************************************************************************/\r
+void RTCC_StatusClear( void )\r
+{\r
+ while ( RTCC->SYNCBUSY & RTCC_SYNCBUSY_CMD )\r
+ {\r
+ // Wait for syncronization.\r
+ }\r
+ RTCC->CMD = RTCC_CMD_CLRSTATUS;\r
+}\r
+\r
+/** @} (end addtogroup RTCC) */\r
+/** @} (end addtogroup EM_Library) */\r
+\r
+#endif /* defined( RTCC_COUNT ) && ( RTCC_COUNT == 1 ) */\r
--- /dev/null
+/***************************************************************************//**\r
+ * @file em_system.c\r
+ * @brief System Peripheral API\r
+ * @version 4.2.1\r
+ *******************************************************************************\r
+ * @section License\r
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>\r
+ *******************************************************************************\r
+ *\r
+ * Permission is granted to anyone to use this software for any purpose,\r
+ * including commercial applications, and to alter it and redistribute it\r
+ * freely, subject to the following restrictions:\r
+ *\r
+ * 1. The origin of this software must not be misrepresented; you must not\r
+ * claim that you wrote the original software.\r
+ * 2. Altered source versions must be plainly marked as such, and must not be\r
+ * misrepresented as being the original software.\r
+ * 3. This notice may not be removed or altered from any source distribution.\r
+ *\r
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
+ * obligation to support this Software. Silicon Labs is providing the\r
+ * Software "AS IS", with no express or implied warranties of any kind,\r
+ * including, but not limited to, any implied warranties of merchantability\r
+ * or fitness for any particular purpose or warranties against infringement\r
+ * of any proprietary rights of a third party.\r
+ *\r
+ * Silicon Labs will not be liable for any consequential, incidental, or\r
+ * special damages, or any other relief, or for any claim by any third party,\r
+ * arising from your use of this Software.\r
+ *\r
+ ******************************************************************************/\r
+\r
+#include "em_system.h"\r
+#include "em_assert.h"\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup EM_Library\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @addtogroup SYSTEM\r
+ * @brief System Peripheral API\r
+ * @{\r
+ ******************************************************************************/\r
+\r
+/*******************************************************************************\r
+ ************************** GLOBAL FUNCTIONS *******************************\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get chip major/minor revision.\r
+ *\r
+ * @param[out] rev\r
+ * Location to place chip revision info.\r
+ ******************************************************************************/\r
+void SYSTEM_ChipRevisionGet(SYSTEM_ChipRevision_TypeDef *rev)\r
+{\r
+ uint8_t tmp;\r
+\r
+ EFM_ASSERT(rev);\r
+\r
+ /* CHIP FAMILY bit [5:2] */\r
+ tmp = (((ROMTABLE->PID1 & _ROMTABLE_PID1_FAMILYMSB_MASK) >> _ROMTABLE_PID1_FAMILYMSB_SHIFT) << 2);\r
+ /* CHIP FAMILY bit [1:0] */\r
+ tmp |= ((ROMTABLE->PID0 & _ROMTABLE_PID0_FAMILYLSB_MASK) >> _ROMTABLE_PID0_FAMILYLSB_SHIFT);\r
+ rev->family = tmp;\r
+\r
+ /* CHIP MAJOR bit [3:0] */\r
+ rev->major = (ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK) >> _ROMTABLE_PID0_REVMAJOR_SHIFT;\r
+\r
+ /* CHIP MINOR bit [7:4] */\r
+ tmp = (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK) >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);\r
+ /* CHIP MINOR bit [3:0] */\r
+ tmp |= ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK) >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);\r
+ rev->minor = tmp;\r
+}\r
+\r
+\r
+#if defined(CALIBRATE)\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get factory calibration value for a given peripheral register.\r
+ *\r
+ * @param[in] regAddress\r
+ * Address of register to get a calibration value for.\r
+ *\r
+ * @return\r
+ * Calibration value for the requested register.\r
+ ******************************************************************************/\r
+uint32_t SYSTEM_GetCalibrationValue(volatile uint32_t *regAddress)\r
+{\r
+ int regCount;\r
+ CALIBRATE_TypeDef *p;\r
+\r
+ regCount = 1;\r
+ p = CALIBRATE;\r
+\r
+ for (;; )\r
+ {\r
+ if ((regCount > CALIBRATE_MAX_REGISTERS) ||\r
+ (p->VALUE == 0xFFFFFFFF))\r
+ {\r
+ EFM_ASSERT(false);\r
+ return 0; /* End of device calibration table reached. */\r
+ }\r
+\r
+ if (p->ADDRESS == (uint32_t)regAddress)\r
+ {\r
+ return p->VALUE; /* Calibration value found ! */\r
+ }\r
+\r
+ p++;\r
+ regCount++;\r
+ }\r
+}\r
+#endif /* defined (CALIBRATE) */\r
+\r
+/** @} (end addtogroup SYSTEM) */\r
+/** @} (end addtogroup EM_Library) */\r
--- /dev/null
+/*\r
+ FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+ All rights reserved\r
+\r
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
+\r
+ ***************************************************************************\r
+ >>! NOTE: The modification to the GPL is included to allow you to !<<\r
+ >>! distribute a combined work that includes FreeRTOS without being !<<\r
+ >>! obliged to provide the source code for proprietary components !<<\r
+ >>! outside of the FreeRTOS kernel. !<<\r
+ ***************************************************************************\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following\r
+ link: http://www.freertos.org/a00114.html\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS provides completely free yet professionally developed, *\r
+ * robust, strictly quality controlled, supported, and cross *\r
+ * platform software that is more than just the market leader, it *\r
+ * is the industry's de facto standard. *\r
+ * *\r
+ * Help yourself get started quickly while simultaneously helping *\r
+ * to support the FreeRTOS project by purchasing a FreeRTOS *\r
+ * tutorial book, reference manual, or both: *\r
+ * http://www.FreeRTOS.org/Documentation *\r
+ * *\r
+ ***************************************************************************\r
+\r
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading\r
+ the FAQ page "My application does not run, what could be wrong?". Have you\r
+ defined configASSERT()?\r
+\r
+ http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+ embedded software for free we request you assist our global community by\r
+ participating in the support forum.\r
+\r
+ http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+ be as productive as possible as early as possible. Now you can receive\r
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+ Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS\r
+ licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+ engineered and independently SIL3 certified version for use in safety and\r
+ mission critical applications that require provable dependability.\r
+\r
+ 1 tab == 4 spaces!\r
+*/\r
+\r
+/******************************************************************************\r
+ * This project provides two demo applications. A simple blinky style project\r
+ * that demonstrates low power tickless functionality, and a more comprehensive\r
+ * test and demo application. The configCREATE_LOW_POWER_DEMO setting, which is\r
+ * defined in FreeRTOSConfig.h, is used to select between the two, and to select\r
+ * the clock used when demonstrating tickless functionality.\r
+ *\r
+ * The simply blinky low power demo is implemented and described in\r
+ * main_low_power.c. The more comprehensive test and demo application is\r
+ * implemented and described in main_full.c.\r
+ *\r
+ * This file implements the code that is not demo specific, including the\r
+ * hardware setup and standard FreeRTOS hook functions.\r
+ *\r
+ * ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON\r
+ * THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO\r
+ * APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT!\r
+ *\r
+ */\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* SiLabs includes. */\r
+#include "em_emu.h"\r
+#include "bsp.h"\r
+#include "bsp_trace.h"\r
+#include "sleep.h"\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Configure the hardware as necessary to run this demo.\r
+ */\r
+static void prvSetupHardware( void );\r
+\r
+/*\r
+ * main_low_power() is used when configCREATE_LOW_POWER_DEMO is set to 1.\r
+ * main_full() is used when configCREATE_LOW_POWER_DEMO is set to 0.\r
+ */\r
+#if( configCREATE_LOW_POWER_DEMO != 0 )\r
+ extern void main_low_power( void );\r
+#else\r
+ extern void main_full( void );\r
+#endif /* #if configCREATE_LOW_POWER_DEMO == 1 */\r
+\r
+/* Prototypes for the standard FreeRTOS callback/hook functions implemented\r
+within this file. */\r
+void vApplicationMallocFailedHook( void );\r
+void vApplicationIdleHook( void );\r
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );\r
+void vApplicationTickHook( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+int main( void )\r
+{\r
+ /* Configure the hardware ready to run the demo. */\r
+ prvSetupHardware();\r
+\r
+ /* The mainCREATE_LOW_POWER_DEMO setting is described at the top\r
+ of this file. */\r
+ #if( configCREATE_LOW_POWER_DEMO != 0 )\r
+ {\r
+ main_low_power();\r
+ }\r
+ #else\r
+ {\r
+ main_full();\r
+ }\r
+ #endif\r
+\r
+ /* Should not get here. */\r
+ return 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupHardware( void )\r
+{\r
+EMU_DCDCInit_TypeDef xDCDInit = EMU_DCDCINIT_STK_DEFAULT;\r
+CMU_HFXOInit_TypeDef xHFXOInit = CMU_HFXOINIT_STK_DEFAULT;\r
+\r
+ /* Chip errata */\r
+ CHIP_Init();\r
+\r
+ /* Init DCDC regulator and HFXO with kit specific parameters */\r
+ EMU_DCDCInit( &xDCDInit );\r
+ CMU_HFXOInit( &xHFXOInit );\r
+\r
+ /* Switch HFCLK to HFXO and disable HFRCO */\r
+ CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO );\r
+ CMU_OscillatorEnable( cmuOsc_HFRCO, false, false );\r
+\r
+ /* Initialize LED driver. */\r
+ BSP_LedsInit();\r
+ BSP_LedSet( 0 );\r
+ BSP_LedClear( 1 );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationMallocFailedHook( void )\r
+{\r
+ /* Called if a call to pvPortMalloc() fails because there is insufficient\r
+ free memory available in the FreeRTOS heap. pvPortMalloc() is called\r
+ internally by FreeRTOS API functions that create tasks, queues, software\r
+ timers, and semaphores. The size of the FreeRTOS heap is set by the\r
+ configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */\r
+\r
+ /* Force an assert. */\r
+ configASSERT( ( volatile void * ) NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )\r
+{\r
+ ( void ) pcTaskName;\r
+ ( void ) pxTask;\r
+\r
+ /* Run time stack overflow checking is performed if\r
+ configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook\r
+ function is called if a stack overflow is detected. */\r
+\r
+ /* Force an assert. */\r
+ configASSERT( ( volatile void * ) NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationIdleHook( void )\r
+{\r
+volatile size_t xFreeHeapSpace;\r
+\r
+ /* This is just a trivial example of an idle hook. It is called on each\r
+ cycle of the idle task. It must *NOT* attempt to block. In this case the\r
+ idle task just queries the amount of FreeRTOS heap that remains. See the\r
+ memory management section on the http://www.FreeRTOS.org web site for memory\r
+ management options. If there is a lot of heap memory free then the\r
+ configTOTAL_HEAP_SIZE value in FreeRTOSConfig.h can be reduced to free up\r
+ RAM. */\r
+ xFreeHeapSpace = xPortGetFreeHeapSize();\r
+\r
+ /* Remove compiler warning about xFreeHeapSpace being set but never used. */\r
+ ( void ) xFreeHeapSpace;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationTickHook( void )\r
+{\r
+ /* The full demo includes tests that run from the tick hook. */\r
+ #if( configCREATE_LOW_POWER_DEMO == 0 )\r
+ {\r
+ extern void vFullDemoTickHook( void );\r
+\r
+ /* Some of the tests and demo tasks executed by the full demo include\r
+ interaction from an interrupt - for which the tick interrupt is used\r
+ via the tick hook function. */\r
+ vFullDemoTickHook();\r
+ }\r
+ #endif\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize )\r
+{\r
+ /* configUSE_STATIC_ALLOCATION is set to 1, so the application has the\r
+ opportunity to supply the buffers that will be used by the Idle task as its\r
+ stack and to hold its TCB. If these are set to NULL then the buffers will\r
+ be allocated dynamically, just as if xTaskCreate() had been called. */\r
+ *ppxIdleTaskTCBBuffer = NULL;\r
+ *ppxIdleTaskStackBuffer = NULL;\r
+ *pusIdleTaskStackSize = configMINIMAL_STACK_SIZE; /* In words. NOT in bytes! */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint16_t *pusTimerTaskStackSize )\r
+{\r
+ /* configUSE_STATIC_ALLOCATION is set to 1, so the application has the\r
+ opportunity to supply the buffers that will be used by the Timer/RTOS daemon\r
+ task as its stack and to hold its TCB. If these are set to NULL then the\r
+ buffers will be allocated dynamically, just as if xTaskCreate() had been\r
+ called. */\r
+ *ppxTimerTaskTCBBuffer = NULL;\r
+ *ppxTimerTaskStackBuffer = NULL;\r
+ *pusTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; /* In words. NOT in bytes! */\r
+}\r
+/*-----------------------------------------------------------*/\r
void *pxDummy14;\r
#endif\r
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )\r
- void pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];\r
+ void *pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];\r
#endif\r
#if ( configGENERATE_RUN_TIME_STATS == 1 )\r
uint32_t ulDummy16;\r
*/\r
typedef void (*TaskFunction_t)( void * );\r
\r
-/* Converts a time in milliseconds to a time in ticks. */\r
-#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) )\r
+/* Converts a time in milliseconds to a time in ticks. This macro can be\r
+overridden by a macro of the same name defined in FreeRTOSConfig.h in case the\r
+definition here is not suitable for your application. */\r
+#ifndef pdMS_TO_TICKS\r
+ #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) )\r
+#endif\r
\r
#define pdFALSE ( ( BaseType_t ) 0 )\r
#define pdTRUE ( ( BaseType_t ) 1 )\r
#endif\r
\r
bx r14\r
- nop\r
}\r
/*-----------------------------------------------------------*/\r
\r
--- /dev/null
+[{000214A0-0000-0000-C000-000000000046}]\r
+Prop3=19,2\r
+[InternetShortcut]\r
+URL=http://www.freertos.org/FreeRTOS-V9.html\r
+IDList=\r