feat: add pec930_sdk-v1.0.1

This commit is contained in:
charles
2026-04-03 00:03:29 +08:00
parent c90b6cbc22
commit 74f221cb75
483 changed files with 97873 additions and 0 deletions
BIN
View File
Binary file not shown.
+110
View File
@@ -0,0 +1,110 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
*.depend
*.layout
obj/*
bin/*
*.tar
*.bit
*.ltx
*.rpt
*.7z
*.gz
*cscope*
GPATH
GRTAGS
GTAGS
ID
tags
*.axf
*.iex
*.uvguix.*
*.uvoptx
*.crf
*.htm
*.lnp
*.dep
*.bin
*.lst
*.list
*.swp
*.swo
*.txt
*.depend
*.elay
*.Bak
*.scvd
**/Project.sct
**/JLinkLog.txt
*.log
*.orig
**/~$*
*.sct
*.target_clock
**/JLinkSettings.ini
**/Dbg_RAM.ini
**/SVD/*.h
*.SFR
*.sfd
*.pack
**/pack/*
**/out/*
**/output/*
*_org*
*~
**/.cache/
**/Debug/
**/Release/
**/.metadata/
**/.settings/
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,309 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.926872659">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.926872659" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.RV_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="${cross_rm} -rf" description="" id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.926872659" name="Debug" parent="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug" postbuildStep="${cross_prefix}${cross_objcopy}${cross_suffix} -O binary ${ProjName}.elf ${ProjName}.bin">
<folderInfo id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.926872659." name="/" resourcePath="">
<toolChain id="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.debug.1243233573" name="RISC-V Cross GCC" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.debug">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash.249191345" name="Create flash image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting.243120876" name="Create extended listing" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize.1566043258" name="Print size" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.1801001334" name="Optimization Level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.none" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength.651682061" name="Message length (-fmessage-length=0)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar.1219903449" name="'char' is signed (-fsigned-char)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections.168524687" name="Function sections (-ffunction-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections.2098519515" name="Data sections (-fdata-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level.1093129020" name="Debug level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level.max" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format.449325272" name="Debug format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.id.758656032" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.id" value="2262347901" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name.932361954" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name" value="RISC-V GCC/Newlib" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix.1942787399" name="Prefix" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix" value="riscv64-unknown-elf-" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c.684525315" name="C compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c" value="gcc" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp.1638988330" name="C++ compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp" value="g++" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar.1234563299" name="Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar" value="ar" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy.1492404953" name="Hex/Bin converter" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy" value="objcopy" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump.1394253527" name="Listing generator" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump" value="objdump" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size.1332389637" name="Size command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size" value="size" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make.2031126337" name="Build command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make" value="make" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm.1285759101" name="Remove command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm" value="rm" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.base.1410576671" name="Architecture" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.base" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.arch.rv32e" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.compressed.353152664" name="Compressed extension (RVC)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.compressed" value="false" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.abi.integer.1735833830" name="Integer ABI" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.abi.integer" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.abi.integer.ilp32e" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.codemodel.796386542" name="Code model" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.codemodel" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.codemodel.low" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.tune.90660292" name="Tuning" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.tune" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.tune.n200series" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.preferxpacksbin.159763604" name="Prefer xpacks/.bin" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.preferxpacksbin" value="false" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.multiply.1863445619" name="Multiply extension (RVM)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.multiply" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.atomic.1533438913" name="Atomic extension (RVA)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.atomic" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.extensions.447179843" name="Other extensions" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.extensions" value="_zba_zbb_zbs_zca_zcb_zcmp_zcmt_zicond" valueType="string"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.RV_ELF;org.eclipse.cdt.core.ELF" id="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform.624485565" isAbstract="false" osList="all" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform"/>
<builder buildPath="${workspace_loc:/Project}/Debug" id="ilg.gnumcueclipse.managedbuild.cross.riscv.builder.1494546460" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.builder"/>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.1909166920" name="GNU RISC-V Cross Assembler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor.1982625252" name="Use preprocessor" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor" value="true" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.defs.1756055012" name="Defined symbols (-D)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.defs" valueType="definedSymbols">
<listOptionValue builtIn="false" value="__IDE_RV_CORE=N203E"/>
<listOptionValue builtIn="false" value="CONFIG_USE_PEC930"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.include.paths.1624800055" name="Include paths (-I)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/NMSIS/Core/Include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/Device/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/HAL_Lib/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/BSP/StarterKit}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Common}&quot;"/>
</option>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input.724532243" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.991594434" name="GNU RISC-V Cross C Compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler">
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs.1630974101" name="Defined symbols (-D)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols">
<listOptionValue builtIn="false" value="__IDE_RV_CORE=N203E"/>
<listOptionValue builtIn="false" value="CONFIG_USE_PEC930"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.include.paths.1504538192" name="Include paths (-I)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.include.paths" useByScannerDiscovery="true" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/NMSIS/Core/Include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/Device/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/HAL_Lib/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/BSP/StarterKit}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Common}&quot;"/>
</option>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.std.345216805" name="Language standard" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.std" useByScannerDiscovery="true" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.std.c99" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.asmlisting.1125613692" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.asmlisting" value="true" valueType="boolean"/>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.1843576227" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler.958908384" name="GNU RISC-V Cross C++ Compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler">
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.compiler.defs.665145577" name="Defined symbols (-D)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols">
<listOptionValue builtIn="false" value="__IDE_RV_CORE=N203E"/>
</option>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.1832379824" name="GNU RISC-V Cross C Linker" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.gcsections.1847575804" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.gcsections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.other.962260539" name="Other linker flags" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.other" value="" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nostart.1331613792" name="Do not use standard start files (-nostartfiles)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nostart" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nodeflibs.1405041078" name="Do not use default libraries (-nodefaultlibs)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nodeflibs" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.printmap.663083040" name="Print link map (-Xlinker --print-map)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.printmap" value="false" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.cref.986670320" name="Cross reference (-Xlinker --cref)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.cref" value="true" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.scriptfile.1007616047" name="Script files (-T)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.scriptfile" valueType="stringList">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/gcc_flashxip.ld}&quot;"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.libs.2005823803" name="Libraries (-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.libs" valueType="libs">
<listOptionValue builtIn="false" value="c_nano"/>
<listOptionValue builtIn="false" value="m"/>
<listOptionValue builtIn="false" value="gcc"/>
<listOptionValue builtIn="false" value="SysDev_PEC930"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.flags.1425978507" name="Linker flags (-Xlinker [option])" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.flags" valueType="stringList"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.grouplibs.1661588098" name="Group libraries (-Wl,--start-group, ... ,--end-group)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.grouplibs" value="true" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.paths.1811936326" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.paths" valueType="libPaths">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930}&quot;"/>
</option>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.input.393723091" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.linker.1387419752" name="GNU RISC-V Cross C++ Linker" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.linker">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.gcsections.297993148" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.gcsections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.other.720519285" name="Other linker flags" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.other" value="-u _isatty -u _write -u _sbrk -u _read -u _close -u _fstat -u _lseek " valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.libs.2127007227" name="Libraries (-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.libs"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver.2145124977" name="GNU RISC-V Cross Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver"/>
<tool command="${cross_prefix}${cross_objcopy}${cross_suffix}" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT}" id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash.586549949" name="GNU RISC-V Cross Create Flash Image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice.283218197" name="Output file format (-O)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice.ihex" valueType="enumerated"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createlisting.1070118556" name="GNU RISC-V Cross Create Listing" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createlisting">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.source.1733954628" name="Display source (--source|-S)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.source" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders.1626209232" name="Display all headers (--all-headers|-x)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle.280684598" name="Demangle names (--demangle|-C)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle" value="false" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers.1695987115" name="Display line numbers (--line-numbers|-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide.1148871387" name="Wide lines (--wide|-w)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.disassemble.1301534980" name="Disassemble (--disassemble|-d)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.disassemble" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.printsize.315205585" name="GNU RISC-V Cross Print Size" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.printsize">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.printsize.format.1467048234" name="Size format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.printsize.format"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="ilg.gnumcueclipse.managedbuild.packs"/>
</cconfiguration>
<cconfiguration id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.16434552">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.16434552" moduleId="org.eclipse.cdt.core.settings" name="Release">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.RV_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="${cross_rm} -rf" description="" id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.16434552" name="Release" parent="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release">
<folderInfo id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.16434552." name="/" resourcePath="">
<toolChain id="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.release.837856819" name="RISC-V Cross GCC" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.release">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash.1208613512" name="Create flash image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting.1016401583" name="Create extended listing" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize.1246797237" name="Print size" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.2012455781" name="Optimization Level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.size" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength.1493955924" name="Message length (-fmessage-length=0)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar.651822097" name="'char' is signed (-fsigned-char)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections.1717953891" name="Function sections (-ffunction-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections.541048735" name="Data sections (-fdata-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level.360621726" name="Debug level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format.1281181250" name="Debug format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.id.723143813" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.id" value="2262347901" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name.399597377" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name" value="RISC-V GCC/Newlib" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix.568227293" name="Prefix" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix" value="riscv64-unknown-elf-" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c.639974320" name="C compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c" value="gcc" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp.1733841476" name="C++ compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp" value="g++" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar.789308737" name="Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar" value="ar" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy.1273467405" name="Hex/Bin converter" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy" value="objcopy" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump.1863146323" name="Listing generator" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump" value="objdump" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size.350346878" name="Size command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size" value="size" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make.1982710953" name="Build command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make" value="make" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm.1369963916" name="Remove command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm" value="rm" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.base.371627411" name="Architecture" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.base" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.arch.rv32e" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.compressed.325570710" name="Compressed extension (RVC)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.compressed" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.abi.integer.268981471" name="Integer ABI" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.abi.integer" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.abi.integer.ilp32e" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.codemodel.1135863126" name="Code model" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.codemodel" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.codemodel.low" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.tune.1264121613" name="Tuning" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.tune" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.tune.n200series" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.multiply.2138851355" name="Multiply extension (RVM)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.multiply" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.atomic.1576924112" name="Atomic extension (RVA)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.atomic" value="true" valueType="boolean"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.RV_ELF;org.eclipse.cdt.core.ELF" id="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform.930977981" isAbstract="false" osList="all" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform"/>
<builder buildPath="${workspace_loc:/Project}/Release" id="ilg.gnumcueclipse.managedbuild.cross.riscv.builder.1235026887" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.builder"/>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.1274001025" name="GNU RISC-V Cross Assembler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor.1238271906" name="Use preprocessor" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor" value="true" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.defs.1967727594" name="Defined symbols (-D)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.defs" valueType="definedSymbols">
<listOptionValue builtIn="false" value="__IDE_RV_CORE=N203E"/>
<listOptionValue builtIn="false" value="CONFIG_USE_PEC930"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.include.paths.284910497" name="Include paths (-I)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/NMSIS/Core/Include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/Device/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/HAL_Lib/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/BSP/StarterKit}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Common}&quot;"/>
</option>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input.1276065282" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.1901433257" name="GNU RISC-V Cross C Compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler">
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs.687116111" name="Defined symbols (-D)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols">
<listOptionValue builtIn="false" value="__IDE_RV_CORE=N203E"/>
<listOptionValue builtIn="false" value="NDEBUG"/>
<listOptionValue builtIn="false" value="CONFIG_USE_PEC930"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.include.paths.140100445" name="Include paths (-I)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.include.paths" useByScannerDiscovery="true" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/NMSIS/Core/Include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/Device/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/HAL_Lib/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/BSP/StarterKit}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Common}&quot;"/>
</option>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.std.651499832" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.std" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.std.c99" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.asmlisting.1089299915" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.asmlisting" value="true" valueType="boolean"/>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.868354821" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler.1780721496" name="GNU RISC-V Cross C++ Compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler">
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.compiler.defs.1060583602" name="Defined symbols (-D)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols">
<listOptionValue builtIn="false" value="__IDE_RV_CORE=N203E"/>
</option>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.1023024678" name="GNU RISC-V Cross C Linker" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.gcsections.589554014" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.gcsections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.other.170075676" name="Other linker flags" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.other" value="--specs=nosys.specs" valueType="string"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.scriptfile.123103120" name="Script files (-T)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.scriptfile" valueType="stringList">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930/gcc_flashxip.ld}&quot;"/>
</option>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nodeflibs.122457886" name="Do not use default libraries (-nodefaultlibs)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nodeflibs" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nostart.507700170" name="Do not use standard start files (-nostartfiles)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nostart" value="true" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.libs.1049690196" name="Libraries (-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.libs" valueType="libs">
<listOptionValue builtIn="false" value="c_nano"/>
<listOptionValue builtIn="false" value="m"/>
<listOptionValue builtIn="false" value="gcc"/>
<listOptionValue builtIn="false" value="SysDev_PEC930"/>
</option>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.grouplibs.700421258" name="Group libraries (-Wl,--start-group, ... ,--end-group)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.grouplibs" value="true" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.paths.1485402190" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.paths" valueType="libPaths">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Drivers/PEC930}&quot;"/>
</option>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.input.1639406854" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.linker.554290345" name="GNU RISC-V Cross C++ Linker" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.linker">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.gcsections.1904431755" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.gcsections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.other.450429501" name="Other linker flags" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.other" value="-u _isatty -u _write -u _sbrk -u _read -u _close -u _fstat -u _lseek " valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.libs.1125125661" name="Libraries (-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.libs"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver.1507570544" name="GNU RISC-V Cross Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver"/>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash.841899246" name="GNU RISC-V Cross Create Flash Image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice.413941719" name="Output file format (-O)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createflash.choice.ihex" valueType="enumerated"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createlisting.39250443" name="GNU RISC-V Cross Create Listing" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createlisting">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.source.778908801" name="Display source (--source|-S)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.source" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders.1081260692" name="Display all headers (--all-headers|-x)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle.212671820" name="Demangle names (--demangle|-C)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers.1206119075" name="Display line numbers (--line-numbers|-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide.625905344" name="Wide lines (--wide|-w)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.printsize.1552514466" name="GNU RISC-V Cross Print Size" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.printsize">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.printsize.format.1158424346" name="Size format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.printsize.format"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="ilg.gnumcueclipse.managedbuild.packs"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="Project.ilg.gnumcueclipse.managedbuild.cross.riscv.target.rvelf.1157615279" name="Executable" projectType="ilg.gnumcueclipse.managedbuild.cross.riscv.target.rvelf"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.926872659;ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.926872659.;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.991594434;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.1843576227">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.16434552;ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.16434552.;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.1901433257;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.868354821">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/Project"/>
</configuration>
<configuration configurationName="Release">
<resource resourceType="PROJECT" workspacePath="/Project"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cproject>
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Project</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<linkedResources>
<link>
<name>Common</name>
<type>2</type>
<locationURI>PARENT-2-PROJECT_LOC/Common</locationURI>
</link>
<link>
<name>Drivers</name>
<type>2</type>
<locationURI>PARENT-2-PROJECT_LOC/Drivers</locationURI>
</link>
<link>
<name>Profiles</name>
<type>2</type>
<locationURI>PARENT-2-PROJECT_LOC/Tools/scripts/Profiles</locationURI>
</link>
</linkedResources>
<filteredResources>
<filter>
<id>1762843010815</id>
<name></name>
<type>6</type>
<matcher>
<id>org.eclipse.ui.ide.multiFilter</id>
<arguments>1.0-name-matches-false-false-*.nuproject</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
@@ -0,0 +1,25 @@
SDK_CONFIG:
Debug:
core: N203E
extra_asmflags:
archext:
extra_cxxflags:
cmodel: medlow
extra_commonflags:
abi: ilp32e
arch: rv32ema_zba_zbb_zbs_zca_zcb_zcmp_zcmt_zicond
toolchain: gnu
extra_cflags:
extra_ldflags:
Release:
core: N203E
extra_asmflags:
archext:
extra_cxxflags:
cmodel: medlow
extra_commonflags:
abi: ilp32e
arch: rv32emac_zba_zbb_zbs
toolchain: gnu
extra_cflags:
extra_ldflags:
@@ -0,0 +1,16 @@
#
# component Makefile
#
C_SOURCES += \
$(srctree)/$(PROJ)/src/isr.c \
$(srctree)/$(PROJ)/src/main.c
C_INCLUDES += -I$(srctree)/$(PROJ)/inc
LIBS +=
CFLAGS +=
LDFLAGS +=
LIBDIR +=
@@ -0,0 +1,50 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file isr.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/16
* @license
* @description
*/
#ifndef __isr_H_wuraIpBA_lTJm_HvJw_sNDo_uEd5JnucTReY__
#define __isr_H_wuraIpBA_lTJm_HvJw_sNDo_uEd5JnucTReY__
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,51 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file main.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/08/29
* @license
* @description
*/
#ifndef __main_H_wxBnwdPw_lq7D_H4I5_sHPp_uXof15pFLp4V__
#define __main_H_wxBnwdPw_lq7D_H4I5_sHPp_uXof15pFLp4V__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_device.h"
#include "syslog.h"
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,8 @@
demo_project
---
This example is a demo project to descript `how to log message`
## Log
Use serial port with baudrate 115200, 8bit, no parity check.
@@ -0,0 +1,39 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file isr.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/16
* @license
* @description
*/
#include "isr.h"
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
@@ -0,0 +1,67 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file main.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/08/29
* @license
* @description
*/
#include "main.h"
#include "isr.h"
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
uint32_t __FASTCODE fastcode_proc(void)
{
log_color(SLOG_CYAN, "run at fast area: $pc= x%08X\n", (uint32_t)&fastcode_proc);
return 0;
}
//=============================================================================
// Public Function Definition
//=============================================================================
int main(void)
{
SYSCFG_ClkInitTypeDef SysClkInit = {0};
SysClkInit.ClkSource = SYSCFG_ClkSrc_HSI;
SYSCFG_SysClkConfig(&SysClkInit);
sys_config_systick(SYS_TICK_1_MS);
syslog_init();
info("This is a app demo project\n");
msg("log debug message: $pc= x%08X\n", __get_pc());
log_color(SLOG_GREEN, "color green\n");
log_color(SLOG_YELLOW, "color yellow\n");
fastcode_proc();
while(1)
{
__NOP();
}
return 0;
}
+36
View File
@@ -0,0 +1,36 @@
# CHANGELOG
---
## v1.0.1
### Bug Fixes
+ [PWR] Support to focus a wake-up type
+ [PWR] Review the configuration flow of wake-up with interrupt signal
+ [LPTIM] Fix reset flow when init and deinit
### Features
+ [ALL] Modify project files to involve libSysDev_PEC930.a
+ [ICE] Add an example of Unlock-ICE mechanism
## v1.0.0
### Bug Fixes
+ [LVD] Fix function name to call lvd driver
+ [GPIO] Fix the configuration of interrupt
+ [I2C] Add disable interrupt when deinit function
+ [WDG] Refactor hal-driver and examples for friendly usage
+ [AMISC] Review the configuration of voltage source of HSI
+ [UART] Delete dummy register field of UART
+ [GPIO] Fix configuration when disable interrupt
+ [AMISC] Fix the configuration of V15 output of hal-driver
+ [ADC] delete clock divider option to fit hardware limitation
### Features
+ [SPI] Add examples of interrupt of SPI master and slave
+ [COMP] Add example and hal-driver of COMP
## v1.0.0-RC1
+16
View File
@@ -0,0 +1,16 @@
#
# common Makefile
#
C_SOURCES += \
$(srctree)/Common/printf.c \
$(srctree)/Common/syslog.c
C_INCLUDES += -I$(srctree)/Common
CFLAGS +=
CXXFLAGS +=
LDFLAGS +=
+192
View File
@@ -0,0 +1,192 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_conf.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#ifndef __hal_conf_H_wV9UWaWV_lh0O_HTIV_ssSG_umphyc0TVXKd__
#define __hal_conf_H_wV9UWaWV_lh0O_HTIV_ssSG_umphyc0TVXKd__
#ifdef __cplusplus
extern "C" {
#endif
//=============================================================================
// Constant Definition
//=============================================================================
/**
* Uncomment 'USE_FULL_ASSERT' to expanse the "assert_param" macro
* in the HAL drivers code
* ps. User should implement the funciton
* 'void assert_failed(char *func, uint32_t line)' at applicaion layer
*/
// #define USE_FULL_ASSERT 1
/**
* The list of modules to be used in the HAL drivers
*/
#define CONFIG_ENABLE_HAL_SYSCFG
#define CONFIG_ENABLE_HAL_PWR
#define CONFIG_ENABLE_HAL_FLASH
#define CONFIG_ENABLE_HAL_GPIO
#define CONFIG_ENABLE_HAL_UART
#define CONFIG_ENABLE_HAL_I2C
#define CONFIG_ENABLE_HAL_SPI
#define CONFIG_ENABLE_HAL_LPTIM
#define CONFIG_ENABLE_HAL_TIM0
#define CONFIG_ENABLE_HAL_TIM1
#define CONFIG_ENABLE_HAL_TIM2
#define CONFIG_ENABLE_HAL_WDG
#define CONFIG_ENABLE_HAL_ADC
#define CONFIG_ENABLE_HAL_AMISC
#define CONFIG_ENABLE_HAL_COMP
#define CONFIG_ENABLE_HAL_OPAMP
#define CONFIG_ENABLE_HAL_CRC
#define CONFIG_ENABLE_HAL_DSP
#define CONFIG_ENABLE_HAL_EPWM
/**
* System-clock Definition
*/
#if !defined(SYS_HIRC_VALUE)
#define SYS_HIRC_MHZ (60ul)
#define SYS_HIRC_VALUE (SYS_HIRC_MHZ * 1000ul * 1000ul)
#endif
#if !defined(SYS_OSC_VALUE)
#define SYS_OSC_VALUE (8 * 1000ul * 1000ul)
#endif
#if !defined(SYS_LIRC_VALUE)
#define SYS_LIRC_VALUE 32768ul
#endif
#define SYS_TIMER_FREQ SYS_LIRC_VALUE
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
#ifdef CONFIG_ENABLE_HAL_SYSCFG
/* Reset and Clock Control module */
#include "hal_syscfg.h"
#endif /* CONFIG_ENABLE_HAL_SYSCFG */
#ifdef CONFIG_ENABLE_HAL_PWR
/* Power Management Unit module */
#include "hal_pwr.h"
#endif /* CONFIG_ENABLE_HAL_PWR */
#ifdef CONFIG_ENABLE_HAL_FLASH
/* Embedded Flash module */
#include "hal_flash.h"
#endif /* CONFIG_ENABLE_HAL_FLASH */
#ifdef CONFIG_ENABLE_HAL_GPIO
/* General-purpose I/O module */
#include "hal_gpio.h"
#endif /* CONFIG_ENABLE_HAL_GPIO */
#ifdef CONFIG_ENABLE_HAL_UART
/* Universal Asynchronous Rx/Tx module */
#include "hal_uart.h"
#endif /* CONFIG_ENABLE_HAL_UART */
#ifdef CONFIG_ENABLE_HAL_I2C
/* Inter-Integrated Circuit module */
#include "hal_i2c.h"
#endif /* CONFIG_ENABLE_HAL_I2C */
#ifdef CONFIG_ENABLE_HAL_SPI
/* Serial Peripheral Interface-Bus module */
#include "hal_spi.h"
#endif /* CONFIG_ENABLE_HAL_SPI */
#ifdef CONFIG_ENABLE_HAL_LPTIM
/* Low-Power Timer module */
#include "hal_lptim.h"
#endif /* CONFIG_ENABLE_HAL_LPTIM */
#ifdef CONFIG_ENABLE_HAL_TIM0
/* Tim0 module */
#include "hal_lptim.h"
#endif /* CONFIG_ENABLE_HAL_TIM0 */
#ifdef CONFIG_ENABLE_HAL_TIM1
/* Tim1 module */
#include "hal_lptim.h"
#endif /* CONFIG_ENABLE_HAL_TIM1 */
#ifdef CONFIG_ENABLE_HAL_TIM2
/* Timer module */
#include "hal_tim.h"
#endif /* CONFIG_ENABLE_HAL_TIM2 */
#ifdef CONFIG_ENABLE_HAL_WDG
/* Watch Dog module */
#include "hal_wdg.h"
#endif /* CONFIG_ENABLE_HAL_WDG */
#ifdef CONFIG_ENABLE_HAL_ADC
/* Analog-to-Digital Converter module */
#include "hal_adc.h"
#endif /* CONFIG_ENABLE_HAL_ADC */
#ifdef CONFIG_ENABLE_HAL_AMISC
/* Analog MISC controller module */
#include "hal_amisc.h"
#endif /* CONFIG_ENABLE_HAL_AMISC */
#ifdef CONFIG_ENABLE_HAL_COMP
/* Voltage Compare module */
#include "hal_comp.h"
#endif /* CONFIG_ENABLE_HAL_COMP */
#ifdef CONFIG_ENABLE_HAL_OPAMP
/* OP-Amplifiers with Programmable Gain Amplifier mode */
#include "hal_opamp.h"
#endif /* CONFIG_ENABLE_HAL_OPAMP */
#ifdef CONFIG_ENABLE_HAL_CRC
/* Cyclic Redundancy Check module */
#include "hal_crc.h"
#endif /* CONFIG_ENABLE_HAL_CRC */
#ifdef CONFIG_ENABLE_HAL_DSP
/* Peripheral DSP module */
#include "hal_dsp.h"
#endif /* CONFIG_ENABLE_HAL_DSP */
#ifdef CONFIG_ENABLE_HAL_EPWM
/* Enhance PWM module */
#include "hal_tim.h"
#endif /* CONFIG_ENABLE_HAL_EPWM */
#ifdef __cplusplus
}
#endif
#endif
File diff suppressed because it is too large Load Diff
+116
View File
@@ -0,0 +1,116 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
// embedded systems with a very limited resources.
// Use this instead of bloated standard/newlib printf.
// These routines are thread safe and reentrant.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _PRINTF_H_
#define _PRINTF_H_
#include <stdarg.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Output a character to a custom device like UART, used by the printf() function
* This function is declared here only. You have to write your custom implementation somewhere
* \param character Character to output
*/
void _putchar(char character);
/**
* Tiny printf implementation
* You have to implement _putchar if you use printf()
* To avoid conflicts with the regular printf() API it is overridden by macro defines
* and internal underscore-appended functions like printf_() are used
* \param format A string that specifies the format of the output
* \return The number of characters that are written into the array, not counting the terminating null character
*/
#define printf sys_printf
int sys_printf(const char* format, ...);
/**
* Tiny sprintf implementation
* Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD!
* \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output!
* \param format A string that specifies the format of the output
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
*/
#define sprintf sys_sprintf
int sys_sprintf(char* buffer, const char* format, ...);
/**
* Tiny snprintf/vsnprintf implementation
* \param buffer A pointer to the buffer where to store the formatted string
* \param count The maximum number of characters to store in the buffer, including a terminating null character
* \param format A string that specifies the format of the output
* \param va A value identifying a variable arguments list
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
* If the formatted string is truncated the buffer size (count) is returned
*/
#define snprintf sys_snprintf
#define vsnprintf sys_vsnprintf
int sys_snprintf(char* buffer, size_t count, const char* format, ...);
int sys_vsnprintf(char* buffer, size_t count, const char* format, va_list va);
/**
* Tiny vprintf implementation
* \param format A string that specifies the format of the output
* \param va A value identifying a variable arguments list
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
*/
#define vprintf sys_vprintf
int sys_vprintf(const char* format, va_list va);
/**
* printf with output function
* You may use this as dynamic alternative to printf() with its fixed _putchar() output
* \param out An output function which takes one character and an argument pointer
* \param arg An argument pointer for user data passed to output function
* \param format A string that specifies the format of the output
* \return The number of characters that are sent to the output function, not counting the terminating null character
*/
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...);
#ifdef __cplusplus
}
#endif
#endif // _PRINTF_H_
+126
View File
@@ -0,0 +1,126 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file syslog.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/08/29
* @license
* @description
*/
#include "hal_device.h"
#include "syslog.h"
//=============================================================================
// Constant Definition
//=============================================================================
#define CONFIG_LOG_MSG_DEVICE UART0
#define CONFIG_LOG_DEVICE_TX_IO_PORTx GPIOA
#define CONFIG_LOG_DEVICE_TX_IO_PINx GPIO_Pin_15
#define CONFIG_LOG_DEVICE_TX_IO_AF GPIO_AF_1
#define CONFIG_LOG_DEVICE_RESET() __HAL_SYSCFG_RESET_UART0()
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
void _putchar(char character)
{
UART_SendData(CONFIG_LOG_MSG_DEVICE, character);
UART_WaitTxFifoEmpty(CONFIG_LOG_MSG_DEVICE);
return;
}
//=============================================================================
// Public Function Definition
//=============================================================================
void syslog_init(void)
{
GPIO_InitTypeDef gpio_init = {0};
UART_InitTypeDef uart_init = {0};
/* configure GPIO Pin mux of UART Tx */
gpio_init.GPIO_Pin = CONFIG_LOG_DEVICE_TX_IO_PINx;
gpio_init.GPIO_AF_Mode = CONFIG_LOG_DEVICE_TX_IO_AF;
gpio_init.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(CONFIG_LOG_DEVICE_TX_IO_PORTx, &gpio_init);
uart_init.BaudRate = SLOG_SERIAL_BPS;
uart_init.WordLength = UART_WordLength_8b;
uart_init.StopBits = UART_StopBits_1;
uart_init.Parity = UART_Parity_No;
uart_init.Mode = UART_Mode_TxRx;
UART_Init(CONFIG_LOG_MSG_DEVICE, &uart_init);
UART_Start(CONFIG_LOG_MSG_DEVICE);
return;
}
void syslog_deinit(void)
{
GPIO_DeInit(CONFIG_LOG_DEVICE_TX_IO_PORTx, CONFIG_LOG_DEVICE_TX_IO_PINx);
CONFIG_LOG_DEVICE_RESET();
return;
}
void
syslog_dump_mem(
char *prefix,
uint32_t *pAddr,
int bytes,
int has_out_u32le)
{
if( has_out_u32le )
{
uintptr_t addr = (uintptr_t)pAddr;
uint32_t cnt = (bytes + 0x3) >> 2;
uint32_t *pCur = (uint32_t*)pAddr;
for(int i = 0; i < cnt; i++)
{
if( (i & 0x3) == 2 )
printf(" -");
else if( !(i & 0x3) )
{
printf("\n%s%08X |", prefix, addr);
addr += 16;
}
printf(" %08X", pCur[i]);
}
printf("\n\n");
}
else
{
uintptr_t addr = (uintptr_t)pAddr;
uint8_t *pCur = (uint8_t*)pAddr;
for(int i = 0; i < bytes; i++)
{
if( (i & 0xF) == 8 )
printf(" -");
else if( !(i & 0xF) )
{
printf("\n%s%08X |", prefix, addr);
addr += 16;
}
printf(" %02X", pCur[i]);
}
printf("\n\n");
}
return;
}
+108
View File
@@ -0,0 +1,108 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file syslog.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/08/29
* @license
* @description
*/
#ifndef __syslog_H_wWjHKLEN_l9U5_H1mZ_sZEW_uX5M5YmrWbVp__
#define __syslog_H_wWjHKLEN_l9U5_H1mZ_sZEW_uX5M5YmrWbVp__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include "printf.h"
//=============================================================================
// Constant Definition
//=============================================================================
/**
* System Log message through uart with baudrate 'SLOG_SERIAL_BPS'
*/
#define SLOG_SERIAL_BPS 115200
#define SLOG_BLACK "\033[30m"
#define SLOG_RED "\033[31m"
#define SLOG_GREEN "\033[32m"
#define SLOG_YELLOW "\033[33m"
#define SLOG_BLUE "\033[34m"
#define SLOG_MAGENTA "\033[35m"
#define SLOG_CYAN "\033[36m"
#define SLOG_WHITE "\033[97m"
#define SLOG_DEFAULT "\033[39m"
#define SLOG_RESET "\033[m"
#define SLOG_RED2 "\33[91m"
#define SLOG_GREEN2 "\33[92m"
#define SLOG_YELLOW2 "\33[93m"
#define SLOG_BLUE2 "\33[94m"
#define SLOG_VIOLET2 "\33[95m"
#define SLOG_BEIGE2 "\33[96m"
//=============================================================================
// Macro Definition
//=============================================================================
#define stringize(s) #s
#define _toStr(a) stringize(a)
#define err(str, ...) printf(SLOG_RED "[error] " str SLOG_RESET, ##__VA_ARGS__)
#if defined(NDEBUG)
/* release */
#define info(str, ...)
#define msg(str, ...)
#define dbg(str, ...)
#define log_color(COLOR, str, ...)
#else
#define info(str, ...) printf(SLOG_YELLOW str SLOG_RESET, ##__VA_ARGS__)
#define msg(str, ...) printf(str, ##__VA_ARGS__)
#define dbg(str, ...) printf(str, ##__VA_ARGS__)
#define log_color(COLOR, str, ...) printf(COLOR str SLOG_RESET, ##__VA_ARGS__)
#endif /* NDEBUG */
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
void syslog_init(void);
void syslog_deinit(void);
/**
* \brief Dump memory data through system log
*
* \param [in] prefix the prefix text
* \param [in] pAddr the target memory address
* \param [in] bytes the dumped length
* \param [in] has_out_u32le layout with 32-bits little-endian or not
* \return
* None
*/
void
syslog_dump_mem(
char *prefix,
uint32_t *pAddr,
int bytes,
int has_out_u32le);
#ifdef __cplusplus
}
#endif
#endif
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,38 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file starterkit.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/08/29
* @license
* @description
*/
#include "starterkit.h"
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
@@ -0,0 +1,49 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file starterkit.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/08/29
* @license
* @description
*/
#ifndef __starterkit_H_wdeYMM70_lNLW_HSdS_sZLf_uhvq7CKQjo90__
#define __starterkit_H_wdeYMM70_lNLW_HSdS_sZLf_uhvq7CKQjo90__
#ifdef __cplusplus
extern "C" {
#endif
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
#ifdef __cplusplus
}
#endif
#endif
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,56 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file device.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/08/29
* @license
* @description
*/
#ifndef __device_H_wqIH3HdS_l3C8_Hgh6_syur_ubmEVDiPX8aR__
#define __device_H_wqIH3HdS_l3C8_Hgh6_syur_ubmEVDiPX8aR__
#ifdef __cplusplus
extern "C" {
#endif
#if defined(CONFIG_USE_PEC930)
#include "pec930.h"
#else
#error "Please select first the target device !"
#endif
//=============================================================================
// Constant Definition
//=============================================================================
typedef void (*isr_t)(void);
typedef void (*cb_trap_t)(void);
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
#ifdef __cplusplus
}
#endif
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,383 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file system_dev.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/08/29
* @license
* @description
*/
#ifndef __system_dev_H_wjaCXWfu_lqsX_H0XR_svyC_uj3MxJR5UZzV__
#define __system_dev_H_wjaCXWfu_lqsX_H0XR_svyC_uj3MxJR5UZzV__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
//=============================================================================
// Constant Definition
//=============================================================================
#ifndef SYS_TIMER_FREQ
#define SYS_TIMER_FREQ 32768ul
#endif
#ifndef SYS_MAX_DELAY
#define SYS_MAX_DELAY 0x7FFFFFFFul
#endif
#define SYS_IGNORE_TAG (~0)
/**
* Exception Code
*/
typedef enum EXCPn
{
/* =============== Nuclei N/NX Specific Exception Code =============== */
EXCPn_InsUnalign = 0, /*!< Instruction address misaligned */
EXCPn_InsAccFault = 1, /*!< Instruction access fault */
EXCPn_IlleIns = 2, /*!< Illegal instruction */
EXCPn_Break = 3, /*!< Beakpoint */
EXCPn_LdAddrUnalign = 4, /*!< Load address misaligned */
EXCPn_LdFault = 5, /*!< Load access fault */
EXCPn_StAddrUnalign = 6, /*!< Store or AMO address misaligned */
EXCPn_StAccessFault = 7, /*!< Store or AMO access fault */
EXCPn_UmodeEcall = 8, /*!< Environment call from User mode */
EXCPn_SmodeEcall = 9, /*!< Environment call from S-mode */
EXCPn_MmodeEcall = 11, /*!< Environment call from Machine mode */
#if 1
EXCPn_Total,
#else
EXCPn_InsPageFault = 12, /*!< Instruction page fault */
EXCPn_LdPageFault = 13, /*!< Load page fault */
EXCPn_StPageFault = 15, /*!< Store or AMO page fault */
EXCPn_StackOverflow = 24, /*!< Stack overflow fault */
EXCPn_StackUnderflow = 25, /*!< Stack underflow fault */
EXCPn_Total,
#endif
EXCPn_NMI = 0xfff, /*!< NMI interrupt */
} EXCPn_Type;
/**
* SYS_TIMER_PERIOD with 1ms, 10ms, 100ms
*/
typedef enum sys_tick
{
SYS_TICK_1_MS = 0,
SYS_TICK_10_MS,
SYS_TICK_100_MS,
SYS_TICK_1_SEC,
} sys_tick_t;
#if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
typedef enum sys_irq_trigger
{
SYS_IRQ_TRIGGER_LEVEL = ECLIC_LEVEL_TRIGGER, /*!< Level Triggerred */
SYS_IRQ_TRIGGER_POSTIVE_EDGE = ECLIC_POSTIVE_EDGE_TRIGGER, /*!< Postive/Rising Edge Triggered */
SYS_IRQ_TRIGGER_NEGTIVE_EDGE = ECLIC_NEGTIVE_EDGE_TRIGGER, /*!< Negtive/Falling Edge Triggered */
SYS_IRQ_TRIGGER_MAX = ECLIC_MAX_TRIGGER, /*!< MAX Supported Trigger Mode */
} sys_irq_trigger_t;
typedef enum sys_irq_level
{
SYS_IRQ_LEVEL_LL = 0, /*!< Interrupt Level lowest */
SYS_IRQ_LEVEL_L = 1, /*!< Interrupt Level low */
SYS_IRQ_LEVEL_M = 2, /*!< Interrupt Level midden */
SYS_IRQ_LEVEL_H = 3, /*!< Interrupt Level high */
SYS_IRQ_LEVEL_HH = 4, /*!< Interrupt Level highest */
} sys_irq_level_t;
typedef enum sys_irq_priority
{
SYS_IRQ_PRIORITY_LOW = 0, /*!< Interrupt Priority Low */
SYS_IRQ_PRIORITY_MIDDEN = 1, /*!< Interrupt Priority Midden */
SYS_IRQ_PRIORITY_HIGH = 2, /*!< Interrupt Priority High */
} sys_irq_priority_t;
#endif /* __ECLIC_PRESENT */
typedef void (*fp_isr_t)(void);
/**
* Exception Handler Function Typedef
*/
typedef void (*cb_excp_handler_t)(uint32_t cause, uint32_t sp);
//=============================================================================
// Macro Definition
//=============================================================================
/**
* Locate function to specific section
* e.g.
* uint32_t __FASTCODE foo(void) { return 123; }
*/
#define __FASTCODE __attribute__((__section__(".fastcode")))
__STATIC_FORCEINLINE uint32_t* __get_pc(void)
{
uint32_t *pc;
__asm__("auipc %0, 0" : "=r"(pc));
return pc;
}
__STATIC_FORCEINLINE uint32_t* __get_sp(void)
{
uint32_t *sp;
__asm__("move %0, sp" : "=r"(sp));
return sp;
}
//=============================================================================
// Structure Definition
//=============================================================================
typedef struct excp_frame
{
uint32_t ra; /* ra: x1, return address for jump */
uint32_t tp; /* tp: x4, thread pointer */
uint32_t t0; /* t0: x5, temporary register 0 */
uint32_t t1; /* t1: x6, temporary register 1 */
uint32_t t2; /* t2: x7, temporary register 2 */
uint32_t a0; /* a0: x10, return value or function argument 0 */
uint32_t a1; /* a1: x11, return value or function argument 1 */
uint32_t a2; /* a2: x12, function argument 2 */
uint32_t a3; /* a3: x13, function argument 3 */
uint32_t a4; /* a4: x14, function argument 4 */
uint32_t a5; /* a5: x15, function argument 5 */
uint32_t cause; /* cause: machine cause csr register */
uint32_t epc; /* epc: machine exception program counter csr register */
uint32_t msubm; /* msubm: machine sub-mode csr register, nuclei customized */
} excp_frame_t;
typedef struct sys_irq_attr
{
uint8_t trig_mode; /*!< the interrupt trigger mode, @ref sys_irq_trigger_t */
uint8_t disable_vector; /*!< use vector table or not */
uint8_t level; /*!< interupt nested level,
high-level (bigger value) will interrupt low-level, @ref sys_irq_level_t */
uint8_t priority; /*!< interrupt priority,
the priority of the pended interrupts (when the same IRQ level), @ref sys_irq_priority_t
ps. This priority has NOTHING about nested interrup */
} sys_irq_attr_t;
//=============================================================================
// Global Data Definition
//=============================================================================
extern volatile uint32_t g_SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
extern volatile uint32_t g_SysTicks;
extern volatile uint32_t g_SysTickPeriod;
extern volatile uint32_t g_SysTickUnit_MS;
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Enable system tick
*/
__STATIC_FORCEINLINE void sys_enable_systick(void)
{
SysTick_Reload(g_SysTickPeriod);
ECLIC_EnableIRQ(SysTimer_IRQn);
SysTimer_Start();
return;
}
/**
* \brief Disable system tick
*/
__STATIC_FORCEINLINE void sys_disable_systick(void)
{
ECLIC_DisableIRQ(SysTimer_IRQn);
SysTimer_Stop();
return;
}
/**
* \brief Trigger software interrupt through system timer
*
* \return None
*/
__STATIC_FORCEINLINE void sys_launch_swi(void)
{
SysTimer_SetSWIRQ();
return;
}
/**
* \brief Clear software interrupt
*
* \return None
*/
__STATIC_FORCEINLINE void sys_clear_swi(void)
{
SysTimer_ClearSWIRQ();
return;
}
/**
* \brief Clear interrupt flags of interrupt controller
*
* \param [in] irq_id the target IRQ Id, @ref IRQn_Type
* \return None
*/
__STATIC_FORCEINLINE void sys_clear_IRQFlag(IRQn_Type irq_id)
{
ECLIC_ClearPendingIRQ(irq_id);
return;
}
/**
* \brief Get the pending specific interrupt of interrupt controller
*
* \param [in] irq_id the target IRQ Id, @ref IRQn_Type
* \return
* IRQ is pending or not
*
*/
__STATIC_FORCEINLINE int sys_get_IRQPending(IRQn_Type irq_id)
{
return ECLIC_GetPendingIRQ(irq_id);
}
/**
* \brief Get system ticks
*
* \return
* System Ticks
*/
__STATIC_FORCEINLINE uint32_t sys_get_tick(void)
{
return g_SysTicks;
}
/**
* \brief Open interrupt source of interrupt controller
*
* \param [in] irq_id the target IRQ Id, @ref IRQn_Type
* \return None
*/
__STATIC_FORCEINLINE void sys_open_IRQ(IRQn_Type irq_id)
{
ECLIC_EnableIRQ(irq_id);
ECLIC_ClearPendingIRQ(irq_id);
return;
}
/**
* \brief Close interrupt source of interrupt controller
*
* \param [in] irq_id the target IRQ Id, @ref IRQn_Type
* \return None
*/
__STATIC_FORCEINLINE void sys_close_IRQ(IRQn_Type irq_id)
{
ECLIC_DisableIRQ(irq_id);
return;
}
/**
* \brief Enable global interrupt
*
* \return None
*/
__STATIC_FORCEINLINE void sys_enable_girq(void)
{
__enable_irq();
return;
}
/**
* \brief Disable global interrupt
*
* \return None
*/
__STATIC_FORCEINLINE void sys_disable_girq(void)
{
__disable_irq();
return;
}
/**
* \brief system high accuracy delay with systick
*
* \param [in] msec milli-seconds
* \return None
*/
void sys_delay(uint32_t msec);
/**
* \brief system low accuracy delay with the CPU tick
*
* \param [in] ticks the CPU ticks
* \return None
*/
void sys_busy_wait(uint32_t ticks);
/**
* \brief get system frequency
*
* \return the cpu frequency value
*/
uint32_t sys_get_cpu_freq(void);
#if defined(__EXCP_PRESENT) && (__EXCP_PRESENT == 1)
/**
* \brief Register handler to Exception table
*
* \param [in] excp_id exception ID, @ref EXCPn_Type
* \param [in] excp_handler the handler function
* \return
* 0 : ok
* others: fail
*/
int sys_excp_register_handler(EXCPn_Type excp_id, uint32_t excp_handler);
#endif
#if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
/**
* \brief Set the attribute of the target interrupt
*
* \param [in] irq_id the terget IRQ ID, @ref IRQn_Type
* \param [in] pAttr pointer to a attribute of interrupt if necessary, @ref sys_irq_attr_t
* \return
* 0 : ok
* others: fail
*/
int sys_set_IRQAttr(IRQn_Type irq_id, sys_irq_attr_t *pAttr);
/**
* \brief Register ISR to Interrupt
*
* \param [in] irq_id the terget IRQ ID, @ref IRQn_Type
* \param [in] cb_handler the ISR funciotn
* \param [in] pAttr pointer to a attribute of interrupt if necessary, @ref sys_irq_attr_t
* \return
* 0 : ok
* others: fail
*/
int sys_register_IRQ(IRQn_Type irq_id, void *cb_handler, sys_irq_attr_t *pAttr);
#endif /* __ECLIC_PRESENT == 1 */
/**
* \brief Configure system tick
*
* \param [in] ticks period of ticks
* SYS_TICK_1_MS/ SYS_TICK_10_MS/ SYS_TICK_100_MS
*/
void sys_config_systick(uint32_t ticks);
#ifdef __cplusplus
}
#endif
#endif
Binary file not shown.
@@ -0,0 +1,154 @@
/*
* Copyright (c) 2024 Padauk Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* \file startup.S
* \brief Modified NMSIS RISC-V Core based Core Device Startup File for
* RISC-V evaluation SoC which support RISC-V cores
* \version V1.00
* \date 10/24/2024
*
******************************************************************************/
#include "riscv_encoding.h"
.section .init
.globl _start
.type _start,@function
_start:
nop
/* ===== Startup Stage 1 ===== */
csrc CSR_MSTATUS, MSTATUS_MIE
csrw CSR_MIE, 0x0
.option push
.option norelax
la gp, __global_pointer$
la tp, __tls_base
#if defined(__riscv_zcmt)
la t0, __jvt_base$
csrw CSR_JVT, t0
#endif
.option pop
la sp, _sp
#if 0
/* Disable/Enable ICE I/O */
li a0, 0x00001C28
li a1, 0x4000F804
li a2, 0x80000000
lw t0, (a1)
and t1, t0, a2
beq t1, a2, 1f
li a0, 0x00201C28
1:
li a1, 0xFFFFFFFF
li a2, 0x31454349
lw t0, (a0)
beq t0, a1, 2f
beq t0, a2, 2f
li a0, 0x4001F02C
li a1, 0xE6530000
sw a1, (a0)
2:
#endif
li t0, MMISC_CTL_NMI_CAUSE_FFF
csrs CSR_MMISC_CTL, t0
li t0, MMISC_CTL_ZC
#if defined(__riscv_zcmp) || defined(__riscv_zcmt)
csrs CSR_MMISC_CTL, t0
#else
csrc CSR_MMISC_CTL, t0
#endif
la t0, early_excp_entry
csrw CSR_MTVEC, t0
li t0, 0x3f
csrc CSR_MTVEC, t0
csrs CSR_MTVEC, 0x3
csrci CSR_MCOUNTINHIBIT, 0x5
la a0, __fastcode_lma_start
la a1, __fastcode_vma_start
beq a0, a1, 2f
la a2, __fastcode_vma_end
bgeu a1, a2, 2f
1:
lw t0, (a0)
sw t0, (a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, 1b
2:
la a0, _data_lma
la a1, _data
beq a0, a1, 2f
la a2, _edata
bgeu a1, a2, 2f
1:
lw t0, (a0)
sw t0, (a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, 1b
2:
la a0, __bss_start
la a1, _end
bgeu a0, a1, 2f
1:
sw zero, (a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
call sys_init
call sys_premain_init
#if defined(CONFIG_HAS_BPU)
li t0, MMISC_CTL_BPU
csrs CSR_MMISC_CTL, t0
#endif
/* ===== Call Main Function ===== */
li a0, 0
li a1, 0
call main
call sys_postmain_fini
1:
j 1b
.align 6
.global early_excp_entry
.type early_excp_entry, @function
early_excp_entry:
wfi
j early_excp_entry
@@ -0,0 +1,222 @@
/*
* Copyright (c) 2024 Padauk Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
* \file trap.S
* \brief Modified NMSIS Interrupt and Exception Handling Template File
* for RISC-V evaluation SoC which support RISC-V cores
* \version V1.00
* \date 10/24/2024
*
******************************************************************************/
#include "riscv_encoding.h"
/******************************************************************************
* \brief Global interrupt disabled
* \details
* This function disable global interrupt.
* \remarks
* - All the interrupt requests will be ignored by CPU.
*/
.macro DISABLE_MIE
csrc CSR_MSTATUS, MSTATUS_MIE
.endm
/******************************************************************************
* \brief Macro for context save
* \details
* This macro save ABI defined caller saved registers in the stack.
* \remarks
* - This Macro could use to save context when you enter to interrupt
* or exception
*/
/* Save caller registers */
.macro SAVE_CONTEXT
#ifndef __riscv_32e
/* rv32i */
addi sp, sp, -20*REGBYTES
#else
/* rv32e */
addi sp, sp, -14*REGBYTES
#endif /* __riscv_32e */
STORE x1, 0*REGBYTES(sp)
STORE x4, 1*REGBYTES(sp)
STORE x5, 2*REGBYTES(sp)
STORE x6, 3*REGBYTES(sp)
STORE x7, 4*REGBYTES(sp)
STORE x10, 5*REGBYTES(sp)
STORE x11, 6*REGBYTES(sp)
STORE x12, 7*REGBYTES(sp)
STORE x13, 8*REGBYTES(sp)
STORE x14, 9*REGBYTES(sp)
STORE x15, 10*REGBYTES(sp)
#ifndef __riscv_32e
/* rv32i */
STORE x16, 14*REGBYTES(sp)
STORE x17, 15*REGBYTES(sp)
STORE x28, 16*REGBYTES(sp)
STORE x29, 17*REGBYTES(sp)
STORE x30, 18*REGBYTES(sp)
STORE x31, 19*REGBYTES(sp)
#endif /* __riscv_32e */
.endm
/******************************************************************************
* \brief Macro for restore caller registers
* \details
* This macro restore ABI defined caller saved registers from stack.
* \remarks
* - You could use this macro to restore context before you want return
* from interrupt or exeception
*/
/* Restore caller registers */
.macro RESTORE_CONTEXT
LOAD x1, 0*REGBYTES(sp)
LOAD x4, 1*REGBYTES(sp)
LOAD x5, 2*REGBYTES(sp)
LOAD x6, 3*REGBYTES(sp)
LOAD x7, 4*REGBYTES(sp)
LOAD x10, 5*REGBYTES(sp)
LOAD x11, 6*REGBYTES(sp)
LOAD x12, 7*REGBYTES(sp)
LOAD x13, 8*REGBYTES(sp)
LOAD x14, 9*REGBYTES(sp)
LOAD x15, 10*REGBYTES(sp)
#ifndef __riscv_32e
/* rv32i */
LOAD x16, 14*REGBYTES(sp)
LOAD x17, 15*REGBYTES(sp)
LOAD x28, 16*REGBYTES(sp)
LOAD x29, 17*REGBYTES(sp)
LOAD x30, 18*REGBYTES(sp)
LOAD x31, 19*REGBYTES(sp)
addi sp, sp, 20*REGBYTES
#else
/* rv32e */
addi sp, sp, 14*REGBYTES
#endif /* __riscv_32e */
.endm
/******************************************************************************
* \brief Macro for save necessary CSRs to stack
* \details
* This macro store MCAUSE, MEPC, MSUBM to stack.
*/
.macro SAVE_CSR_CONTEXT
csrrwi x0, CSR_PUSHMCAUSE, 11
csrrwi x0, CSR_PUSHMEPC, 12
csrrwi x0, CSR_PUSHMSUBM, 13
.endm
/******************************************************************************
* \brief Macro for restore necessary CSRs from stack
* \details
* This macro restore MSUBM, MEPC, MCAUSE from stack.
*/
.macro RESTORE_CSR_CONTEXT
LOAD x5, 13*REGBYTES(sp)
csrw CSR_MSUBM, x5
LOAD x5, 12*REGBYTES(sp)
csrw CSR_MEPC, x5
LOAD x5, 11*REGBYTES(sp)
csrw CSR_MCAUSE, x5
.endm
/******************************************************************************
* \brief Exception/NMI Entry
* \details
* This function provide common entry functions for exception/nmi.
* \remarks
* This function provide a default exception/nmi entry.
* ABI defined caller save register and some CSR registers
* to be saved before enter interrupt handler and be restored before return.
*/
.section .text.trap
.align 6
.global excp_entry
.type excp_entry, @function
excp_entry:
SAVE_CONTEXT
SAVE_CSR_CONTEXT
csrr a0, mcause
mv a1, sp
/**
* Call the exception handler function
* By default, the function template is provided in
* system_Device.c, you can adjust it as you want
*/
call sys_core_excp_handler
RESTORE_CSR_CONTEXT
RESTORE_CONTEXT
mret
.size excp_entry, . - excp_entry
/**
* \brief Non-Vector Interrupt Entry
* \details
* This function provide common entry functions for handling
* non-vector interrupts
* \remarks
* This function provide a default non-vector interrupt entry.
* ABI defined caller save register and some CSR registers need
* to be saved before enter interrupt handler and be restored before return.
*/
.section .text.irq
.align 2
.weak irq_entry
.type irq_entry, @function
irq_entry:
SAVE_CONTEXT
SAVE_CSR_CONTEXT
csrrw ra, CSR_JALMNXTI, ra
DISABLE_MIE
RESTORE_CSR_CONTEXT
RESTORE_CONTEXT
mret
.size irq_entry, . - irq_entry
.section .text
.align 7
.weak default_handler
.type default_handler, @function
Undef_Handler:
default_handler:
1:
j 1b
.size default_handler, . - default_handler
@@ -0,0 +1,119 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file interrupt.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/08/29
* @license
* @description
*/
#include "device.h"
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
extern void default_handler(void);
//=============================================================================
// Private Function Definition
//=============================================================================
/**
* \brief System Timer ISR
*
* \return None
*/
void eclic_mtim_handler(void)
{
g_SysTicks++;
// Reload Timer Interrupt
SysTick_Reload(g_SysTickPeriod);
return;
}
/**
* \brief System Software ISR
*
* \return None
*/
__INTERRUPT void eclic_mswi_handler(void)
{
SAVE_IRQ_CSR_CONTEXT();
sys_clear_swi();
sys_clear_IRQFlag(SysSW_IRQn);
RESTORE_IRQ_CSR_CONTEXT();
return;
}
__INTERRUPT void eclic_bwei_handler(void)
{
return;
}
__INTERRUPT void eclic_pmovi_handler(void)
{
return;
}
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* irq vector table
*/
const fp_isr_t __Vectors[__ECLIC_INTNUM] __USED __attribute__((section (".mintvec"))) =
{
(fp_isr_t)0, /* 0: Reserved */
default_handler, /* 1: Reserved */
default_handler, /* 2: Reserved */
eclic_mswi_handler, /* 3: Machine software interrupt */
default_handler, /* 4: Reserved */
default_handler, /* 5: Reserved */
default_handler, /* 6: Reserved */
eclic_mtim_handler, /* 7: Machine timer interrupt */
default_handler, /* 8: Reserved */
default_handler, /* 9: Reserved */
default_handler, /* 10: Reserved */
default_handler, /* 11: Reserved */
default_handler, /* 12: Reserved */
default_handler, /* 13: Reserved */
default_handler, /* 14: Reserved */
default_handler, /* 15: Reserved */
default_handler, /* 16: Reserved */
eclic_bwei_handler, /* 17: Bus Error interrupt */
eclic_pmovi_handler, /* 18: Performance Monitor */
/*========= external interrupt ================*/
default_handler, /* 19: ext_irq Reserved */
default_handler, /* 20: ext_irq Reserved */
default_handler, /* 21: ext_irq Reserved */
default_handler, /* 22: ext_irq Reserved */
default_handler, /* 23: ext_irq Reserved */
default_handler, /* 24: ext_irq Reserved */
default_handler, /* 25: ext_irq Reserved */
default_handler, /* 26: ext_irq Reserved */
default_handler, /* 27: ext_irq Reserved */
default_handler, /* 28: ext_irq Reserved */
default_handler, /* 29: ext_irq Reserved */
default_handler, /* 30: ext_irq Reserved */
default_handler, /* 31: ext_irq Reserved */
default_handler, /* 32: ext_irq Reserved */
default_handler, /* 33: ext_irq Reserved */
};
@@ -0,0 +1,201 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file syscalls.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/02
* @license
* @description
*/
#include <stddef.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/time.h>
#include <time.h>
#include "nmsis_core.h"
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
#ifndef TIMEVAL_TO_TIMESPEC
#define TIMEVAL_TO_TIMESPEC(tv, ts) \
do { \
(ts)->tv_sec = (tv)->tv_sec; \
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
} while (0)
#endif
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
__WEAK int _open(const char *name, int flags, int mode)
{
return -1;
}
__WEAK int _close(int fd)
{
return -1;
}
__WEAK ssize_t _read(int fd, void *ptr, size_t len)
{
return 0;
}
__WEAK ssize_t _write(int fd, const void *ptr, size_t len)
{
return 0;
}
__WEAK int _lseek(int file, int offset, int whence)
{
return 0;
}
__WEAK int _isatty(int fd)
{
return 1;
}
__WEAK int _stat(char *file, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
__WEAK int _fstat(int file, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
__WEAK void _exit(int fd)
{
while(1)
{
__WFI();
}
}
__WEAK int _wait(int *status)
{
return -1;
}
int _link(char *old, char *new)
{
return -1;
}
__WEAK int _unlink(const char *name)
{
return -1;
}
__WEAK int _fork(void)
{
return -1;
}
__WEAK int _getpid(void)
{
return 1;
}
__WEAK int _kill(int pid, int sig)
{
return -1;
}
__WEAK int _execve(char *name, char **argv, char **env)
{
return -1;
}
__WEAK int _gettimeofday(struct timeval *tp, void *tzp)
{
extern uint32_t SystemCoreClock;
uint64_t cycles;
cycles = __get_rv_cycle();
tp->tv_sec = cycles / SystemCoreClock;
tp->tv_usec = (cycles % SystemCoreClock) * 1000000 / SystemCoreClock;
return 0;
}
__WEAK int clock_gettime(clockid_t clock_id, struct timespec *tp)
{
struct timeval tv;
int retval = -1;
retval = _gettimeofday(&tv, NULL);
if (retval == 0)
{
TIMEVAL_TO_TIMESPEC(&tv, tp);
}
return retval;
}
__WEAK int clock_settime(clockid_t clock_id, const struct timespec *tp)
{
return -1;
}
__WEAK int clock_getres(clockid_t clock_id, struct timespec *res)
{
extern uint32_t SystemCoreClock;
res->tv_sec = 0;
res->tv_nsec = 1000000000l / SystemCoreClock;
return 0;
}
__WEAK clock_t _times(struct tms *buf)
{
static struct timeval t0;
struct timeval t;
long long utime;
/* When called for the first time, initialize t0. */
if( t0.tv_sec == 0 && t0.tv_usec == 0 )
{
_gettimeofday(&t0, 0);
}
_gettimeofday(&t, 0);
utime = (t.tv_sec - t0.tv_sec) * 1000000 + (t.tv_usec - t0.tv_usec);
buf->tms_utime = utime * CLOCKS_PER_SEC / 1000000;
buf->tms_stime = buf->tms_cstime = buf->tms_cutime = 0;
return buf->tms_utime;
}
__WEAK void *_sbrk(ptrdiff_t incr)
{
return 0;
}
@@ -0,0 +1,424 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file system_dev.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/08/29
* @license
* @description
*/
#include "device.h"
//=============================================================================
// Constant Definition
//=============================================================================
#define CONFIG_ENABLE_STACK_DEBUG 0
#if (CONFIG_ENABLE_STACK_DEBUG)
extern int sys_printf(const char* format, ...);
#define DEBUG(str, ...) sys_printf(str, ##__VA_ARGS__)
#else
#define DEBUG(str, ...)
#endif
#if !defined(SYS_HIRC_VALUE)
#define SYS_HIRC_MHZ (60ul)
#define SYS_HIRC_VALUE (SYS_HIRC_MHZ * 1000ul * 1000ul)
#endif
#if !defined(SYS_OSC_VALUE)
#define SYS_OSC_VALUE (8 * 1000ul * 1000ul)
#endif
#if !defined(SYS_LIRC_VALUE)
#define SYS_LIRC_VALUE 32768ul
#endif
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
volatile uint32_t g_SystemCoreClock = SYS_HIRC_VALUE;
volatile uint32_t g_SysTicks = 0;
volatile uint32_t g_SysTickPeriod = 0;
volatile uint32_t g_SysTickUnit_MS = 0;
//=============================================================================
// Private Function Definition
//=============================================================================
#if defined(__EXCP_PRESENT) && (__EXCP_PRESENT == 1)
/**
* Max exception handler number
*/
#define CONFIG_SYS_EXCP_MAX_NUM ((int)EXCPn_Total)
/**
* \brief Store the exception handlers for each exception ID
* \note
* - This g_SysExcpHandlers are used to store all the handlers for all
* the exception codes Nuclei N100 core provided.
* - Exception code 0 - 11, totally 12 exceptions are mapped to g_SysExcpHandlers[0:11]
*/
static uint32_t g_SysExcpHandlers[CONFIG_SYS_EXCP_MAX_NUM] = {0};
static uint32_t g_cb_nmi_handler = 0;
/**
* @brief System Default Exception Handler
* This function provides a default exception handler for all exception IDs.
* By default, It will just print some information for debug,
* Vendor can customize it according to its requirements.
*
* @param [in] mcause code indicating the reason that caused the trap in machine mode
* @param [in] sp stack pointer
* @return
* None
*/
static void _sys_def_excp_handler(uint32_t mcause, uint32_t sp)
{
DEBUG("MCAUSE : 0x%08X\n", mcause);
DEBUG("MEPC : 0x%08X\n", __RV_CSR_READ(CSR_MEPC));
DEBUG("MTVAL : 0x%08X\n", __RV_CSR_READ(CSR_MTVAL));
DEBUG("HARTID : %u\n", (unsigned int)__get_hart_id());
do{ /* Dump the frame of stack */
DEBUG("ra: 0x%08X, tp: 0x%08X,\n"
"t0: 0x%08X, t1: 0x%08X, t2: 0x%08X,\n"
"a0: 0x%08X, a1: 0x%08X, a2: 0x%08X, a3: 0x%08X,\n"
"a4: 0x%08X, a5: 0x%08X,\n"
"cause: 0x%08X, epc: 0x%08X\n",
((excp_frame_t*)sp)->ra, ((excp_frame_t*)sp)->tp,
((excp_frame_t*)sp)->t0, ((excp_frame_t*)sp)->t1, ((excp_frame_t*)sp)->t2,
((excp_frame_t*)sp)->a0, ((excp_frame_t*)sp)->a1, ((excp_frame_t*)sp)->a2, ((excp_frame_t*)sp)->a3,
((excp_frame_t*)sp)->a4, ((excp_frame_t*)sp)->a5,
((excp_frame_t*)sp)->cause, ((excp_frame_t*)sp)->epc);
DEBUG("sp: 0x%08X\n", (int)__get_sp());
#ifndef __riscv_32e
/* rv32i */
DEBUG("t3: 0x%08X, t4: 0x%08X, t5: 0x%08X, t6: 0x%08X,\n"
"a6: 0x%08X, a7: 0x%08X\n",
((excp_frame_t*)sp)->t3, ((excp_frame_t*)sp)->t4, ((excp_frame_t*)sp)->t5, ((excp_frame_t*)sp)->t6,
((excp_frame_t*)sp)->a6, ((excp_frame_t*)sp)->a7);
#endif /* __riscv_32e */
}while(0);
while (1)
{
__WFI();
}
}
/**
* @brief Common Exception handler entry
* This function provided a command entry for exception.
* Silicon Vendor could modify this template implementation according to requirement.
* @param [in] mcause code indicating the reason that caused the trap in machine mode
* @param [in] sp stack pointer
* @return
* 0
* \remarks
* - RISCV provided common entry for all types of exception. This is proposed code template
* for exception entry function, Silicon Vendor could modify the implementation.
* - For the sys_core_excp_handler template, we provided exception register function \ref Exception_Register_EXC
* which can help developer to register your exception handler for specific exception number.
*/
__WEAK uint32_t sys_core_excp_handler(uint32_t mcause, uint32_t sp)
{
uint32_t excp_code = (uint32_t)(mcause & 0x00000FFF);
cb_excp_handler_t cb_excp_handler = 0;
cb_excp_handler = (excp_code == EXCPn_NMI) ? (cb_excp_handler_t)g_cb_nmi_handler
: (excp_code < CONFIG_SYS_EXCP_MAX_NUM) ? (cb_excp_handler_t)g_SysExcpHandlers[excp_code]
: (cb_excp_handler_t)_sys_def_excp_handler;
if( cb_excp_handler )
{
cb_excp_handler(mcause, sp);
}
return 0;
}
/**
* @brief Initialize all the default exception handlers
* The core exception handler for each exception ID
* will be initialized to @ref _sys_def_excp_handler.
* ps. Called in @ref sys_premain_init function,
* used to initialize default exception handlers for all exception IDs
* @return
* None
*/
__WEAK void sys_excp_init(void)
{
extern void excp_entry(void);
g_cb_nmi_handler = (uint32_t)_sys_def_excp_handler;
for(int i = 0; i < CONFIG_SYS_EXCP_MAX_NUM; i++)
{
g_SysExcpHandlers[i] = (uint32_t)_sys_def_excp_handler;
}
__RV_CSR_WRITE(CSR_MTVEC, (uint32_t)excp_entry | 0x3ul);
return;
}
__WEAK int sys_excp_register_handler(EXCPn_Type excp_id, uint32_t excp_handler)
{
if( (int)excp_id == EXCPn_NMI )
{
g_cb_nmi_handler = excp_handler;
}
else if( (int)excp_id < CONFIG_SYS_EXCP_MAX_NUM )
{
g_SysExcpHandlers[excp_id] = (uint32_t)excp_handler;
}
else
return -1;
return 0;
}
#else /* __EXCP_PRESENT == 1 */
#define sys_excp_init()
#define sys_excp_register_handler()
#endif /* __EXCP_PRESENT == 1 */
#if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
/**
* @brief Initialize interrupt config
* Interrupt needs be initialized after boot up
*
* @return None
*/
static void sys_interrupt_init(void)
{
extern const fp_isr_t __Vectors[__ECLIC_INTNUM];
extern void irq_entry(void);
__RV_CSR_WRITE(CSR_MTVT, (uint32_t)__Vectors);
__RV_CSR_WRITE(CSR_MTVT2, (uint32_t)irq_entry | 0x1ul);
ECLIC_SetMth(0);
ECLIC_SetCfgNlbits(__ECLIC_INTCTLBITS);
return;
}
int sys_set_IRQAttr(IRQn_Type irq_id, sys_irq_attr_t *pAttr)
{
if( irq_id >= __ECLIC_INTNUM || !pAttr )
return -1;
/* set interrupt vector mode */
ECLIC_SetShvIRQ(irq_id,
(pAttr->disable_vector) ? ECLIC_NON_VECTOR_INTERRUPT : ECLIC_VECTOR_INTERRUPT);
ECLIC_SetTrigIRQ(irq_id, pAttr->trig_mode); /* set interrupt vector mode */
ECLIC_SetLevelIRQ(irq_id, pAttr->level); /* set interrupt level */
ECLIC_SetPriorityIRQ(irq_id, pAttr->priority); /* set interrupt priority */
/* enable interrupt */
ECLIC_EnableIRQ(irq_id);
return 0;
}
int sys_register_IRQ(IRQn_Type irq_id, void *cb_handler, sys_irq_attr_t *pAttr)
{
if( irq_id >= __ECLIC_INTNUM || !cb_handler || !pAttr )
return -1;
ECLIC_DisableIRQ(irq_id);
if( cb_handler )
{
/* set interrupt handler entry to vector table */
ECLIC_SetVector(irq_id, (rv_csr_t)cb_handler);
}
sys_set_IRQAttr(irq_id, pAttr);
return 0;
}
#else /* __ECLIC_PRESENT == 1 */
#define sys_interrupt_init()
#endif /* __ECLIC_PRESENT == 1 */
/**
* \brief early init function before main
*
* \return
* none
* \details
* This function is executed right before main function.
* For RISC-V gnu toolchain, _init function might not be called
* by __libc_init_array function, so we defined a new function
* to do initialization
*/
void sys_premain_init(void)
{
SysTimer_Stop();
g_SysTickPeriod = SYS_TICK_1_MS;
g_SysTicks = 0;
g_SystemCoreClock = sys_get_cpu_freq();
sys_excp_init();
sys_interrupt_init();
return;
}
/**
* \brief finish function after main
*
* \param [in] status
* \return
*
* \details
* This function is executed right after main function.
* For RISC-V gnu toolchain, _fini function might not be called
* by __libc_fini_array function, so we defined a new function
* to do initialization
*/
void sys_postmain_fini(int status)
{
return;
}
//=============================================================================
// Public Function Definition
//=============================================================================
void sys_init(void)
{
/**
* Configure eFlash
* + Set eFlash latency
* + Disable and clear interrup
*/
FLASH->CMD = 0xA5A50020ul;
FLASH->SR = 0xFFFFFFFFul;
FLASH->DIV = (FLASH->DIV & ~FLASH_DIV_DIV_Msk) | \
(SYS_HIRC_MHZ << FLASH_DIV_DIV_Pos) | \
(0x1ul << 8);
#if 1
SYSCFG->PCLKEN |= SYSCFG_PCLKEN_AMISC_Msk;
AMISC->HSI_CR = (AMISC->HSI_CR & ~AMISC_HSI_CR_LDO_SEL_Msk) | \
(AMISC_HSI_CR_LDO_SEL_LDO << AMISC_HSI_CR_LDO_SEL_Pos);
#endif
return;
}
/**
* \brief delay a time in milliseconds
*
* \param [in] msec count in milliseconds
* \return
* none
*/
void sys_delay(uint32_t msec)
{
#if defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1)
/**
* Only for 1ms system tick
*/
uint32_t tick_start = 0;
tick_start = g_SysTicks;
while( (g_SysTicks - tick_start) < msec )
{
}
#else
#warning "sys_delay_1ms function require system timer present, if you are using this, it will not work"
#endif
}
void sys_busy_wait(uint32_t ticks)
{
while( ticks-- );
return;
}
uint32_t sys_get_cpu_freq(void)
{
if( (SYSCFG->SYSCLKCR & SYSCFG_SYSCLKCR_CLKSW_Msk)
== (SYSCFG_SYSCLKCR_CLKSW_HSI << SYSCFG_SYSCLKCR_CLKSW_Pos) )
{
g_SystemCoreClock = SYS_HIRC_VALUE;
}
else if( (SYSCFG->SYSCLKCR & SYSCFG_SYSCLKCR_CLKSW_Msk)
== SYSCFG_SYSCLKCR_CLKSW_LSI << SYSCFG_SYSCLKCR_CLKSW_Pos )
{
g_SystemCoreClock = SYS_LIRC_VALUE;
}
else if( (SYSCFG->SYSCLKCR & SYSCFG_SYSCLKCR_CLKSW_Msk)
== (SYSCFG_SYSCLKCR_CLKSW_HSE << SYSCFG_SYSCLKCR_CLKSW_Pos) )
{
g_SystemCoreClock = SYS_OSC_VALUE;
}
else
{
uint32_t div = (SYSCFG->SYSCLKCR & SYSCFG_SYSCLKCR_CLKDIV_Msk) >> SYSCFG_SYSCLKCR_CLKDIV_Pos;
div = (div) ? (div + 1) : 2;
g_SystemCoreClock = SYS_HIRC_VALUE / div;
}
return g_SystemCoreClock;
}
void sys_config_systick(uint32_t ticks)
{
volatile register uint32_t value = 0;
uint32_t sys_clock = SYS_HIRC_VALUE;
if( (SYSCFG->SYSCLKCR & SYSCFG_SYSCLKCR_CLKSW_Msk)
== (SYSCFG_SYSCLKCR_CLKSW_CLKDIV << SYSCFG_SYSCLKCR_CLKSW_Pos) )
{
uint32_t div = (SYSCFG->SYSCLKCR & SYSCFG_SYSCLKCR_CLKDIV_Msk) >> SYSCFG_SYSCLKCR_CLKDIV_Pos;
div = (div) ? (div + 1) : 2;
sys_clock = SYS_HIRC_VALUE / div;
}
value = (SYSCFG->SYSCLKCR & SYSCFG_SYSCLKCR_SYSTICKCR_Msk) >> SYSCFG_SYSCLKCR_SYSTICKCR_Pos;
g_SysTickUnit_MS = (value == SYSCFG_SYSCLKCR_SYSTICKCR_HSI_DIV2) ? (sys_clock / 2000ul) :
(value == SYSCFG_SYSCLKCR_SYSTICKCR_HSI_DIV4) ? (sys_clock / 4000ul) :
(value == SYSCFG_SYSCLKCR_SYSTICKCR_HSI_DIV8) ? (sys_clock / 8000ul) :
(SYS_TIMER_FREQ / 1000ul);
g_SysTickPeriod = (ticks == SYS_TICK_10_MS) ? (10ul * g_SysTickUnit_MS) :
(ticks == SYS_TICK_100_MS) ? (100ul * g_SysTickUnit_MS) :
(ticks == SYS_TICK_1_SEC) ? (1000ul * g_SysTickUnit_MS) :
g_SysTickUnit_MS;
__disable_irq();
SysTimer_Stop();
SysTick_Config(g_SysTickPeriod);
SysTimer_Start();
__enable_irq();
return;
}
Binary file not shown.
@@ -0,0 +1,527 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_adc.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#ifndef __hal_adc_H_wiD001de_llts_HbDE_s9jK_uDX2acTbwqSx__
#define __hal_adc_H_wiD001de_llts_HbDE_s9jK_uDX2acTbwqSx__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
#define ADC_AIN_CHANNEL_NUM 16
/**
* ADC AIN channels
* ps. Channel-0 conversion priority is the highest and
* Channel-15 conversion priority is the lowest
*/
typedef enum ADC_Channels
{
ADC_Channel_00 = (0x1ul << 0 ),
ADC_Channel_01 = (0x1ul << 1 ),
ADC_Channel_02 = (0x1ul << 2 ),
ADC_Channel_03 = (0x1ul << 3 ),
ADC_Channel_04 = (0x1ul << 4 ),
ADC_Channel_05 = (0x1ul << 5 ),
ADC_Channel_06 = (0x1ul << 6 ),
ADC_Channel_07 = (0x1ul << 7 ),
ADC_Channel_08 = (0x1ul << 8 ),
ADC_Channel_09 = (0x1ul << 9 ),
ADC_Channel_10 = (0x1ul << 10),
ADC_Channel_11 = (0x1ul << 11),
ADC_Channel_12 = (0x1ul << 12),
ADC_Channel_13 = (0x1ul << 13),
ADC_Channel_14 = (0x1ul << 14),
ADC_Channel_15 = (0x1ul << 15),
ADC_Channel_OPA0_O = ADC_Channel_00,
ADC_Channel_OPA1_O = ADC_Channel_01,
ADC_Channel_AVSS = ADC_Channel_14,
ADC_Channel_AMISC = ADC_Channel_15, // It should configure AMISC->VBUF_CR_b.ANA_SEL
} ADC_ChannelsTypeDef;
/**
* Sub-Channels of Channel-AMISC (channel-15) of ADC
* ref. AMISC->VBUF_CR_b.ANA_SEL
*/
typedef enum ADC_SubChannel
{
ADC_SubChannel_NONE = (AMISC_VBUF_CR_ANA_SEL_NONE << AMISC_VBUF_CR_ANA_SEL_Pos),
ADC_SubChannel_TEMP = (AMISC_VBUF_CR_ANA_SEL_TEMP << AMISC_VBUF_CR_ANA_SEL_Pos),
ADC_SubChannel_DAC0 = (AMISC_VBUF_CR_ANA_SEL_DAC0 << AMISC_VBUF_CR_ANA_SEL_Pos),
ADC_SubChannel_DAC1 = (AMISC_VBUF_CR_ANA_SEL_DAC1 << AMISC_VBUF_CR_ANA_SEL_Pos),
ADC_SubChannel_VBuf_1_5 = (AMISC_VBUF_CR_ANA_SEL_VBuf_1p5v << AMISC_VBUF_CR_ANA_SEL_Pos),
ADC_SubChannel_VDDL = (AMISC_VBUF_CR_ANA_SEL_VDDL << AMISC_VBUF_CR_ANA_SEL_Pos),
ADC_SubChannel_VSS = (AMISC_VBUF_CR_ANA_SEL_VSS << AMISC_VBUF_CR_ANA_SEL_Pos),
ADC_SubChannel_VDD = (AMISC_VBUF_CR_ANA_SEL_VDD << AMISC_VBUF_CR_ANA_SEL_Pos),
} ADC_SubChannelTypeDef;
/**
* ADC working clock divides
* Note 1: The Working-Clock of ADC MUST be 800KHz ~ 16MHz
* Note 2: It MUST wait 20-cycles after change ADC working-clock
*/
typedef enum ADC_ClkDiv
{
ADC_ClkDiv_Auto = 0,
ADC_ClkDiv_2 = (ADC_CON0_CLK_Div2 << ADC_CON0_CLK_Pos),
ADC_ClkDiv_4 = (ADC_CON0_CLK_Div4 << ADC_CON0_CLK_Pos),
ADC_ClkDiv_8 = (ADC_CON0_CLK_Div8 << ADC_CON0_CLK_Pos),
ADC_ClkDiv_16 = (ADC_CON0_CLK_Div16 << ADC_CON0_CLK_Pos),
ADC_ClkDiv_32 = (ADC_CON0_CLK_Div32 << ADC_CON0_CLK_Pos),
ADC_ClkDiv_3_75 = (ADC_CON0_CLK_Div3_75 << ADC_CON0_CLK_Pos),
ADC_ClkDiv_3_5 = (ADC_CON0_CLK_Div3_5 << ADC_CON0_CLK_Pos),
} ADC_ClkDivTypeDef;
/**
* ADC mode
*/
typedef enum ADC_Mode
{
ADC_Mode_SingleConv = 0,
ADC_Mode_Continuous, /*!< ADC Continuous mode will be Never-Stop-Conversion.
This mode NOT support interrupt. */
ADC_Mode_Scan,
ADC_Mode_Discontinuous,
} ADC_ModeTypeDef;
/**
* ADC external trigger source for conversion
*/
typedef enum ADC_ExtTrigSource
{
ADC_ExtTrigSource_00 = 0x0,
ADC_ExtTrigSource_01 = 0x1,
ADC_ExtTrigSource_02 = 0x2,
ADC_ExtTrigSource_03 = 0x3,
ADC_ExtTrigSource_04 = 0x4,
ADC_ExtTrigSource_05 = 0x5,
ADC_ExtTrigSource_06 = 0x6,
ADC_ExtTrigSource_07 = 0x7,
ADC_ExtTrigSource_08 = 0x8,
ADC_ExtTrigSource_09 = 0x9,
ADC_ExtTrigSource_10 = 0xA,
ADC_ExtTrigSource_11 = 0xB,
ADC_ExtTrigSource_12 = 0xC,
ADC_ExtTrigSource_13 = 0xD,
ADC_ExtTrigSource_14 = 0xE,
ADC_ExtTrigSource_15 = 0xF,
ADC_ExtTrigSource_16 = 0x1D,
ADC_ExtTrigSource_17 = 0x1E,
ADC_ExtTrigSource_Soft = 0xFF, /*!< ADC Software trigger */
ADC_ExtTrigSource_EPWM_CH1R = ADC_ExtTrigSource_00, /*!< ADC external source trigger from EPWM CH1 Rising */
ADC_ExtTrigSource_EPWM_CH2R = ADC_ExtTrigSource_01, /*!< ADC external source trigger from EPWM CH2 Rising */
ADC_ExtTrigSource_EPWM_CH3R = ADC_ExtTrigSource_02, /*!< ADC external source trigger from EPWM CH3 Rising */
ADC_ExtTrigSource_EPWM_CH1F = ADC_ExtTrigSource_03, /*!< ADC external source trigger from EPWM CH1 Falling */
ADC_ExtTrigSource_EPWM_CH2F = ADC_ExtTrigSource_04, /*!< ADC external source trigger from EPWM CH2 Falling */
ADC_ExtTrigSource_EPWM_CH3F = ADC_ExtTrigSource_05, /*!< ADC external source trigger from EPWM CH3 Falling */
ADC_ExtTrigSource_COMP0_Rise = ADC_ExtTrigSource_06, /*!< ADC external source trigger from COMP0 Rising */
ADC_ExtTrigSource_COMP1_Rise = ADC_ExtTrigSource_08, /*!< ADC external source trigger from COMP1 Rising */
ADC_ExtTrigSource_COMP0_Fall = ADC_ExtTrigSource_07, /*!< ADC external source trigger from COMP0 Falling */
ADC_ExtTrigSource_COMP1_Fall = ADC_ExtTrigSource_09, /*!< ADC external source trigger from COMP1 Falling */
ADC_ExtTrigSource_EPWM_UDF = ADC_ExtTrigSource_10, /*!< ADC external source trigger from EPWM Counter UDF */
ADC_ExtTrigSource_EPWM_OVF = ADC_ExtTrigSource_11, /*!< ADC external source trigger from EPWM Counter OVF */
ADC_ExtTrigSource_EPWM_CCR4_UP = ADC_ExtTrigSource_12, /*!< ADC external source trigger from EPWM_CNTUP == CCR4 */
ADC_ExtTrigSource_EPWM_CCDR4_UP = ADC_ExtTrigSource_13, /*!< ADC external source trigger from EPWM_CNTUP == CCDR4 */
ADC_ExtTrigSource_EPWM_CCR4_DN = ADC_ExtTrigSource_14, /*!< ADC external source trigger from EPWM_CNTDN == CCR4 */
ADC_ExtTrigSource_EPWM_CCDR4_DN = ADC_ExtTrigSource_15, /*!< ADC external source trigger from EPWM_CNTDN == CCDR4 */
ADC_ExtTrigSource_TIM0 = ADC_ExtTrigSource_16, /*!< ADC external source trigger from Tim0 */
ADC_ExtTrigSource_PB1 = (ADC_ExtTrigSource_17), /*!< ADC external source trigger from Pin (PB1) */
ADC_ExtTrigSource_PB2 = (ADC_ExtTrigSource_17 | 0x20ul), /*!< ADC external source trigger from Pin (PB2) */
} ADC_ExtTrigSourceTypeDef;
typedef enum ADC_ExtTrigMode
{
ADC_ExtTrigMode_Disable = 0ul,
ADC_ExtTrigMode_Enable = 0x1ul,
ADC_ExtTrigMode_PinRising = ADC_ExtTrigMode_Enable, // Be used when external source is ADC_ExtTrigSource_17
ADC_ExtTrigMode_PinFaling = (ADC_ExtTrigMode_Enable | 0x2ul), // Be used when external source is ADC_ExtTrigSource_17
} ADC_ExtTrigModeTypeDef;
/**
* ADC Data Align
*/
typedef enum ADC_DataAlign
{
ADC_DataAlign_Right = (ADC_CON0_ALIGN_RIGHT << ADC_CON0_ALIGN_Pos),
ADC_DataAlign_Left = (ADC_CON0_ALIGN_LEFT << ADC_CON0_ALIGN_Pos),
} ADC_DataAlignTypeDef;
/**
* The ADC interrupt type
*/
typedef enum ADC_IT
{
ADC_IT_DISABLE = (ADC_CON0_INT_EN_DISABLE << ADC_CON0_INT_EN_Pos),
ADC_IT_CONV_DONE = (ADC_CON0_INT_EN_DONE << ADC_CON0_INT_EN_Pos), /*!< ADC conversion is done */
ADC_IT_LOWER_THRESHOLD = (ADC_CON0_INT_EN_LT_THR << ADC_CON0_INT_EN_Pos), /*!< ADC conversion value is below threshold */
ADC_IT_HIGHER_THRESHOLD = (ADC_CON0_INT_EN_GT_THR << ADC_CON0_INT_EN_Pos), /*!< ADC conversion value is above threshold */
ADC_IT_EQUAL_THRESHOLD = (ADC_CON0_INT_EN_EQ_THR << ADC_CON0_INT_EN_Pos), /*!< ADC conversion value is equal to threshold */
ADC_IT_CONV_GROUP_SUBSET = (0x80000000ul | ADC_CHSEL_DISC_INTSEL_Msk),
ADC_IT_CONV_GROUP_DONE = 0x80000000ul,
} ADC_ITTypeDef;
/**
* The ADC interrupt status
*/
typedef enum ADC_ITStatus
{
ADC_ITStatus_None = (ADC_STAT_COMP_RESULT_NONE << ADC_STAT_COMP_RESULT_Pos),
ADC_ITStatus_LowerThreshold = (ADC_STAT_COMP_RESULT_LT_THR << ADC_STAT_COMP_RESULT_Pos),
ADC_ITStatus_HigherThreshold = (ADC_STAT_COMP_RESULT_GT_THR << ADC_STAT_COMP_RESULT_Pos),
ADC_ITStatus_EqualThreshold = (ADC_STAT_COMP_RESULT_EQ_THR << ADC_STAT_COMP_RESULT_Pos),
} ADC_ITStatusTypeDef;
/**
* The brake source type from an ADC channel
*/
typedef enum ADC_BKSrc
{
ADC_BKSrc_Src1 = 0,
ADC_BKSrc_Src2 = 8,
} ADC_BKSrcTypeDef;
/**
* The ADC brake filter type
*/
typedef enum ADC_BKFilter
{
ADC_BKFilter_MATCH_1 = (ADC_BKSEL_BK1_FLT_OFF << ADC_BKSEL_BK1_FLT_Pos),
ADC_BKFilter_MATCH_2 = (ADC_BKSEL_BK1_FLT_MATCH_2 << ADC_BKSEL_BK1_FLT_Pos),
ADC_BKFilter_MATCH_4 = (ADC_BKSEL_BK1_FLT_MATCH_4 << ADC_BKSEL_BK1_FLT_Pos),
ADC_BKFilter_MATCH_7 = (ADC_BKSEL_BK1_FLT_MATCH_7 << ADC_BKSEL_BK1_FLT_Pos),
} ADC_BKFilterTypeDef;
/**
* The Brake condition with the ADC brake source
*/
typedef enum ADC_BKCond
{
ADC_BKCond_Disabe = (ADC_BKSEL_BK1_EN_OFF << ADC_BKSEL_BK1_EN_Pos),
ADC_BKCond_LOWER_THRESHOLD = (ADC_BKSEL_BK1_EN_GT_THR << ADC_BKSEL_BK1_EN_Pos),
ADC_BKCond_HIGHER_THRESHOLD = (ADC_BKSEL_BK1_EN_LT_THR << ADC_BKSEL_BK1_EN_Pos),
ADC_BKCond_EQUAL_THRESHOLD = (ADC_BKSEL_BK1_EN_EQ_THR << ADC_BKSEL_BK1_EN_Pos),
} ADC_BKCondTypeDef;
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief ADC Start
* ps. This API MUST be called after ADC_Init()
*
* \param [in] pHADC Pointer to an ADC handler
* \return
* None
*/
__STATIC_FORCEINLINE void ADC_Start(ADC_Type *pHADC)
{
REG_SET_BITS(pHADC->STAT, ADC_STAT_INT_CLR_Msk); // clear flag
REG_SET_BITS(pHADC->CON0, ADC_CON0_START_Msk);
sys_busy_wait(32);
return;
}
/**
* \brief ADC conversion is idle or not
*
* \param [in] pHADC Pointer to an ADC handler
* \return
* 0: busy, others: idle
*/
__STATIC_FORCEINLINE uint32_t ADC_IsIdle(ADC_Type *pHADC)
{
return REG_READ_MASK(pHADC->STAT, ADC_STAT_DONE_Msk);
}
/**
* \brief Get the status of interrupt of ADC
*
* \param [in] pHADC Pointer to an ADC handler
* \return
* Interrupt flags, @ref ADC_ITStatusTypeDef
*/
__STATIC_FORCEINLINE ADC_ITStatusTypeDef ADC_GetITStatus(ADC_Type *pHADC)
{
return REG_READ_MASK(pHADC->STAT, ADC_STAT_COMP_RESULT_Msk);
}
/**
* \brief ADC Clear interrupt flag
*
* \param [in] pHADC
* \return
* None
*/
__STATIC_FORCEINLINE void ADC_ClearITFlag(ADC_Type *pHADC)
{
REG_SET_BITS(pHADC->STAT, ADC_STAT_INT_CLR_Msk);
return;
}
/**
* \brief Set the subset number of grouped-channels in ADC Discontinuous mode
*
* \param [in] pHADC Pointer to an ADC handler
* \param [in] subset_ch_num the subset channel number of a group
* ps. the group_ch_num ONLY be 1 ~ 8
* \return
* None
*/
__STATIC_FORCEINLINE void ADC_DiscMode_SetGroupSubsetNum(ADC_Type *pHADC, uint8_t subset_ch_num)
{
REG_WRITE_MASK(pHADC->CHSEL, ADC_CHSEL_DISCNUM_Msk, (subset_ch_num - 1) << ADC_CHSEL_DISCNUM_Pos);
return;
}
/**
* \brief Get the EOC count of ADC
*
* \param [in] pHADC Pointer to an ADC handler
* \return
* The EOC count of ADC
*/
__STATIC_FORCEINLINE uint8_t ADC_GetEOCCnt(ADC_Type *pHADC)
{
return (uint8_t)pHADC->STAT_b.EOC_CNT;
}
/**
* \brief Enable/Disable backup ADC conversion value
*
* \param [in] pHADC Pointer to an ADC handler
* \return
* None
*/
__STATIC_FORCEINLINE void ADC_EnableBackup(ADC_Type *pHADC)
{
REG_SET_BITS(pHADC->CON0, ADC_CON0_BAKEN_Msk);
return;
}
__STATIC_FORCEINLINE void ADC_DisableBackup(ADC_Type *pHADC)
{
REG_CLR_BITS(pHADC->CON0, ADC_CON0_BAKEN_Msk);
return;
}
/**
* \brief Get the backup of ADC conversion value
*
* \param [in] pHADC Pointer to an ADC handler
* \return
* The backup value
*/
__STATIC_FORCEINLINE uint16_t ADC_GetBakcupValue(ADC_Type *pHADC)
{
return (uint16_t)pHADC->BAKDAT_b.BAKDAT;
}
/**
* \brief Set the sample-period of an ADC
*
* \param [in] pHADC Pointer to an ADC handler
* \param [in] cycles extern cycles (range: 0 ~ 31, default: 3)
* \return
* None
*/
__STATIC_FORCEINLINE void ADC_SetSampleCycles(ADC_Type *pHADC, uint8_t cycles)
{
pHADC->STAT_b.TS_SET = cycles;
return;
}
/**
* \brief Get the conversion value of the ADC in ISR
*
* \param [in] pHADC Pointer to an ADC handler
* \param [in] channel The target channel, @ref ADC_ChannelsTypeDef
* \return
* The ADC conversion value
*/
__STATIC_FORCEINLINE uint16_t ADC_ITGetConvValue(ADC_Type *pHADC, ADC_ChannelsTypeDef channel)
{
#define __ADC_CLZ(x) __builtin_clz(x)
volatile uint32_t *pData = (volatile uint32_t*)&pHADC->DAT0;
uint32_t chnnl_id = (31ul - __ADC_CLZ(channel));
pData += (chnnl_id & 0xFul);
return (uint16_t)((*pData) & 0xFFFFul);
}
/**
* \brief Disable interrupt of ADC
*
* \param [in] pHADC Pointer to an ADC handler
* \return
* None
*/
__STATIC_FORCEINLINE void ADC_ITDisable(ADC_Type *pHADC)
{
REG_WRITE_MASK(pHADC->CON0, ADC_CON0_INT_EN_Msk, ADC_IT_DISABLE);
return;
}
//=============================================================================
// Structure Definition
//=============================================================================
/**
* ADC initialization info
*/
typedef struct ADC_Init
{
ADC_ChannelsTypeDef SelChannels;
ADC_ClkDivTypeDef ClkPrescaler; /*!< ADC the max working clock is 16-MHz */
ADC_DataAlignTypeDef DataAlign;
ADC_ModeTypeDef Mode;
bool IsSoftTrig;
} ADC_InitTypeDef;
/**
* The initialization info of brake source from the ADC Channel
*/
typedef struct ADC_BKSrcInit
{
uint8_t SelBKChannel; // The target channel ID (0~15) as brake source
ADC_BKFilterTypeDef BkFilter;
ADC_BKCondTypeDef BKCond;
} ADC_BKSrcInitTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Deinitializes ADC module
*
* \param [in] pHADC Pointer to an ADC handler
* \return
* None
*/
void ADC_DeInit(ADC_Type *pHADC);
/**
* \brief Initializes ADC module
*
* \param [in] pHADC Pointer to an ADC handler
* \param [in] pInit Pointer to an ADC_InitTypeDef structure, @ref ADC_InitTypeDef
* \return
* None
*/
void ADC_Init(ADC_Type *pHADC, ADC_InitTypeDef *pInit);
/**
* \brief Fills each ADC_InitStruct member with its default value.
*
* \param [in] pInit Pointer to an ADC_InitTypeDef structure, @ref ADC_InitTypeDef
* \return
* None
*/
void ADC_StructInit(ADC_InitTypeDef *pInit);
/**
* \brief ADC external trigger configuration
* Note. It should one by one to configure external sources
*
* \param [in] pHADC Pointer to an ADC handler
* \param [in] ext_src The target external source, @ref ADC_ExtTrigSourceTypeDef
* Note. if ext_src == ADC_ExtTrigSource_Soft,
* it will ignore trig_mode and DISABLE external trigger function
* \param [in] trig_mode The target ADC trigger mode, @ref ADC_ExtTrigModeTypeDef
* \return
* None
*/
void ADC_ExtTrigConfig(ADC_Type *pHADC, ADC_ExtTrigSourceTypeDef ext_src, ADC_ExtTrigModeTypeDef trig_mode);
/**
* \brief Select the sub-channel of the ADC Channel-15
*
* \param [in] subchannel The selected sub-channel of ADC channel-15, @ref ADC_SubChannelTypeDef
* \return
* None
*/
void ADC_SelSubChannel(ADC_SubChannelTypeDef subchannel);
/**
* \brief Get the conversion value of an ADC channel
*
* \param [in] pHADC Pointer to an ADC handler
* \param [in] channel The target channel, @ref ADC_ChannelsTypeDef
* \return
* The ADC conversion value
*/
uint16_t ADC_GetChannelConvValue(ADC_Type *pHADC, ADC_ChannelsTypeDef channel);
/**
* \brief Configures the comparison thresholds of an ADC channel
*
* \param [in] pHADC Pointer to an ADC handler
* \param [in] channel The target channel, @ref ADC_ChannelsTypeDef
* \param [in] threshold The target thershold value
* \return
* None
*/
void ADC_ChannelThresholdConfig(ADC_Type *pHADC, ADC_ChannelsTypeDef channel, uint16_t threshold);
/**
* \brief Enables or disables the specified ADC interrupts
*
* \param [in] pHADC Pointer to an ADC handler
* \param [in] it_types The target interrupt types
* ps. It supports multi-interrupts selection,
* but 'ADC_IT_DISABLE' is standalone
* \return
* None
*/
void ADC_ITConfig(ADC_Type *pHADC, ADC_ITTypeDef it_types);
/**
* \brief Configures the brake source from an ADC channel
*
* \param [in] pHADC Pointer to an ADC handler
* \param [in] bk_src the brake source type, @ref ADC_BKSrcTypeDef
* \param [in] pBKInit Pointer to an instance of the ADC brake initialization info, @ref ADC_BKSrcInitTypeDef
* \return
* None
*/
__STATIC_FORCEINLINE void ADC_BrakeSrcConfig(ADC_Type *pHADC, ADC_BKSrcTypeDef bk_src, ADC_BKSrcInitTypeDef *pBKInit)
{
REG_WRITE_MASK(pHADC->BKSEL,
(ADC_BKSEL_BK1_CH_Msk | ADC_BKSEL_BK1_FLT_Msk | ADC_BKSEL_BK1_EN_Msk) << bk_src,
((pBKInit->SelBKChannel & 0xFul) | pBKInit->BkFilter | pBKInit->BKCond) << bk_src);
return;
}
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,402 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_amisc.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#ifndef __hal_amisc_H_wiD001de_alts_HbDE_s9jK_uDb2acTbwQSx__
#define __hal_amisc_H_wiD001de_alts_HbDE_s9jK_uDb2acTbwQSx__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
typedef enum
{
AMISC_Status_OK = 0,
AMISC_Status_Error,
AMISC_Status_Bypass,
} AMISC_StatusTypeDef;
/**
* The threshold of LVD voltage
*/
typedef enum
{
AMISC_LVDVoltage_2V = (AMISC_LVD_LVR_CR_LVD_SEL_2V << AMISC_LVD_LVR_CR_LVD_SEL_Pos),
AMISC_LVDVoltage_2_2V = (AMISC_LVD_LVR_CR_LVD_SEL_2_2V << AMISC_LVD_LVR_CR_LVD_SEL_Pos),
AMISC_LVDVoltage_2_4V = (AMISC_LVD_LVR_CR_LVD_SEL_2_4V << AMISC_LVD_LVR_CR_LVD_SEL_Pos),
AMISC_LVDVoltage_2_7V = (AMISC_LVD_LVR_CR_LVD_SEL_2_7V << AMISC_LVD_LVR_CR_LVD_SEL_Pos),
AMISC_LVDVoltage_3V = (AMISC_LVD_LVR_CR_LVD_SEL_3V << AMISC_LVD_LVR_CR_LVD_SEL_Pos),
AMISC_LVDVoltage_3_7V = (AMISC_LVD_LVR_CR_LVD_SEL_3_7V << AMISC_LVD_LVR_CR_LVD_SEL_Pos),
AMISC_LVDVoltage_4V = (AMISC_LVD_LVR_CR_LVD_SEL_4V << AMISC_LVD_LVR_CR_LVD_SEL_Pos),
AMISC_LVDVoltage_4_3V = (AMISC_LVD_LVR_CR_LVD_SEL_4_3V << AMISC_LVD_LVR_CR_LVD_SEL_Pos),
} AMISC_LVDVoltageTypeDef;
/**
* The threshold of LVR voltage
*/
typedef enum
{
AMISC_LVRVoltage_2V = (AMISC_LVD_LVR_CR_LVR_SEL_2V << AMISC_LVD_LVR_CR_LVR_SEL_Pos),
AMISC_LVRVoltage_2_4V = (AMISC_LVD_LVR_CR_LVR_SEL_2_4V << AMISC_LVD_LVR_CR_LVR_SEL_Pos),
AMISC_LVRVoltage_2_7V = (AMISC_LVD_LVR_CR_LVR_SEL_2_7V << AMISC_LVD_LVR_CR_LVR_SEL_Pos),
AMISC_LVRVoltage_3V = (AMISC_LVD_LVR_CR_LVR_SEL_3V << AMISC_LVD_LVR_CR_LVR_SEL_Pos),
AMISC_LVRVoltage_3_7V = (AMISC_LVD_LVR_CR_LVR_SEL_3_7V << AMISC_LVD_LVR_CR_LVR_SEL_Pos),
} AMISC_LVRVoltageTypeDef;
typedef enum
{
AMISC_LVDFunc_LP = AMISC_LVD_LVR_CR_LDO_LP_EN_Msk, // LDO low power mode
AMISC_LVDFunc_TEMP = AMISC_LVD_LVR_CR_TEMP_EN_Msk, // Temperature detection
} AMISC_LVDFuncTypeDef;
typedef enum
{
AMISC_InternalSrc_NONE = (AMISC_VBUF_CR_ANA_SEL_NONE << AMISC_VBUF_CR_ANA_SEL_Pos),
AMISC_InternalSrc_TEMP = (AMISC_VBUF_CR_ANA_SEL_TEMP << AMISC_VBUF_CR_ANA_SEL_Pos),
AMISC_InternalSrc_DAC0 = (AMISC_VBUF_CR_ANA_SEL_DAC0 << AMISC_VBUF_CR_ANA_SEL_Pos),
AMISC_InternalSrc_DAC1 = (AMISC_VBUF_CR_ANA_SEL_DAC1 << AMISC_VBUF_CR_ANA_SEL_Pos),
AMISC_InternalSrc_VBuf_1P5V = (AMISC_VBUF_CR_ANA_SEL_VBuf_1p5v << AMISC_VBUF_CR_ANA_SEL_Pos),
AMISC_InternalSrc_VDDL = (AMISC_VBUF_CR_ANA_SEL_VDDL << AMISC_VBUF_CR_ANA_SEL_Pos),
AMISC_InternalSrc_VSS = (AMISC_VBUF_CR_ANA_SEL_VSS << AMISC_VBUF_CR_ANA_SEL_Pos),
AMISC_InternalSrc_VDD = (AMISC_VBUF_CR_ANA_SEL_VDD << AMISC_VBUF_CR_ANA_SEL_Pos),
} AMISC_InternalSrcTypeDef;
typedef enum
{
AMISC_HSIPwrSrc_Normal = (AMISC_HSI_CR_LDO_SEL_Normal << AMISC_HSI_CR_LDO_SEL_Pos),
AMISC_HSIPwrSrc_LowPower = (AMISC_HSI_CR_LDO_SEL_LDO << AMISC_HSI_CR_LDO_SEL_Pos),
} AMISC_HSIPwrSrcTypeDef;
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief Configure DAC0 of Analog Misc.
*
* \param [in] step the voltage step (10-bits) of DAC
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_DAC0_Config(uint16_t step)
{
REG_WRITE_MASK(AMISC->DAC_CR,
AMISC_DAC_CR_DAC0Step_Msk,
((uint32_t)step << AMISC_DAC_CR_DAC0Step_Pos));
return;
}
/**
* \brief Configure DAC1 of Analog Misc.
*
* \param [in] step the voltage step (10-bits) of DAC
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_DAC1_Config(uint16_t step)
{
REG_WRITE_MASK(AMISC->DAC_CR,
AMISC_DAC_CR_DAC1Step_Msk,
((uint32_t)step << AMISC_DAC_CR_DAC1Step_Pos));
return;
}
/**
* \brief Enable DAC0 of Analog Misc.
*
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_DAC0_Enable(void)
{
REG_SET_BITS(AMISC->DAC_CR, AMISC_DAC_CR_DAC0_EN_Msk);
return;
}
/**
* \brief Enable DAC1 of Analog Misc.
*
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_DAC1_Enable(void)
{
REG_SET_BITS(AMISC->DAC_CR, AMISC_DAC_CR_DAC1_EN_Msk);
return;
}
/**
* \brief Disable DAC0 of Analog Misc.
*
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_DAC0_Disable(void)
{
REG_CLR_BITS(AMISC->DAC_CR, AMISC_DAC_CR_DAC0_EN_Msk);
return;
}
/**
* \brief Disable DAC1 of Analog Misc.
*
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_DAC1_Disable(void)
{
REG_CLR_BITS(AMISC->DAC_CR, AMISC_DAC_CR_DAC1_EN_Msk);
return;
}
/**
* \brief Enable LVD module
*
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_LVD_Enable(void)
{
REG_SET_BITS(AMISC->LVD_LVR_CR, AMISC_LVD_LVR_CR_LVD_EN_Msk);
return;
}
/**
* \brief Disable LVD module
*
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_LVD_Disable(void)
{
REG_CLR_BITS(AMISC->LVD_LVR_CR, AMISC_LVD_LVR_CR_LVD_EN_Msk);
return;
}
/**
* \brief Enable LVR interrupt
*
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_LVR_Enable(void)
{
REG_SET_BITS(AMISC->LVD_LVR_CR, AMISC_LVD_LVR_CR_LVR_EN_Msk);
return;
}
/**
* \brief Disable LVR interrupt
*
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_LVR_Disable(void)
{
REG_CLR_BITS(AMISC->LVD_LVR_CR, AMISC_LVD_LVR_CR_LVR_EN_Msk);
return;
}
/**
* \brief Enable LVD interrupt
*
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_LVD_ITEnable(void)
{
REG_SET_BITS(AMISC->LVD_LVR_CR, AMISC_LVD_LVR_CR_LVD_INT_EN_Msk);
return;
}
/**
* \brief Disable LVD interrupt
*
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_LVD_ITDisable(void)
{
REG_CLR_BITS(AMISC->LVD_LVR_CR, AMISC_LVD_LVR_CR_LVD_INT_EN_Msk);
return;
}
/**
* \brief Get the status of LVD
*
* \return
* The new state of flags (SET or RESET)
*/
__STATIC_FORCEINLINE FlagStatus AMISC_LVD_GetFlagStatus(void)
{
return REG_READ_MASK(AMISC->LVD_LVR_CR, AMISC_LVD_LVR_CR_LVD_STATE_Msk) ? SET : RESET;
}
/**
* \brief Enable VBUF
*
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_Vbuf_Enable(void)
{
REG_SET_BITS(AMISC->VBUF_CR, AMISC_VBUF_CR_VBUF_EN_Msk);
return;
}
/**
* \brief Disable VBUF
*
* \param [in] pHAMisc Pointer to a Analog Misc. handler
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_Vbuf_Disable(void)
{
REG_CLR_BITS(AMISC->VBUF_CR, AMISC_VBUF_CR_VBUF_EN_Msk);
return;
}
/**
* \brief Set the power source of HSI
*
* \param [in] pwr_src The target power source, @ref AMISC_HSIPwrSrcTypeDef
* \return
* None
*/
__STATIC_FORCEINLINE void AMISC_SetHSIPwrSrc(AMISC_HSIPwrSrcTypeDef pwr_src)
{
REG_WRITE_MASK(AMISC->HSI_CR, AMISC_HSI_CR_LDO_SEL_Msk, pwr_src);
return;
}
//=============================================================================
// Structure Definition
//=============================================================================
typedef struct
{
AMISC_LVDVoltageTypeDef LVD_Voltage;
AMISC_LVRVoltageTypeDef LVR_Voltage;
AMISC_LVDFuncTypeDef LVD_FuncModes;
} AMISC_LVDRInitTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Initialize Analog misc. module
*
* \return
* result status, @ref AMISC_StatusTypeDef
*/
AMISC_StatusTypeDef AMISC_Init(void);
/**
* \brief De-Initialize Analog misc. module
*
* \param [in] is_force Force to de-initialize or not
* 0: Conditionally de-initialize
* others: Force to de-initialize
* \return
* result status, @ref AMISC_StatusTypeDef
*/
AMISC_StatusTypeDef AMISC_DeInit(uint32_t is_force);
/**
* \brief Reset Analog misc. module
* NOTE: It will reset OPAMP, DAC, LDO functions at the same time
*
* \return
* result status, @ref AMISC_StatusTypeDef
*/
AMISC_StatusTypeDef AMISC_Reset(void);
/**
* \brief Configure LVD/LVR module
*
* \param [in] pInit Pointer to a AMISC_LVDRInitTypeDef structure, @ref AMISC_LVDRInitTypeDef
* \return
* result status, @ref AMISC_StatusTypeDef
*/
AMISC_StatusTypeDef AMISC_LVD_LVR_Config(AMISC_LVDRInitTypeDef *pInit);
/**
* \brief Disable HSI clock source
*
* \return
* None
*/
void AMISC_HSI_Disable(void);
/**
* \brief Enable HSI clock source
*
* \return
* None
*/
void AMISC_HSI_Enable(void);
/**
* \brief Disable LSI clock source
*
* \return
* None
*/
void AMISC_LSI_Disable(void);
/**
* \brief Enable LSI clock source
*
* \return
* None
*/
void AMISC_LSI_Enable(void);
/**
* \brief Select the VinP internal source of PGA
*
* \param [in] src_type the target VinP internal source
* \return
* None
*/
void AMISC_Sel_PGA_VinP_Src(AMISC_InternalSrcTypeDef src_type);
/**
* \brief Output the internal signals to I/O Pin
*
* \param [in] src_type The target internal signal, @ref AMISC_InternalSrcTypeDef
* \param [in] has_output Enable output or not
* \return
* None
*/
void AMISC_OutInternalSignalToIO(AMISC_InternalSrcTypeDef src_type, int has_output);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,261 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_comp.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#ifndef __hal_comp_H_wqqzibVO_lvKI_HWdK_sROD_uhjcZz7SHMtL__
#define __hal_comp_H_wqqzibVO_lvKI_HWdK_sROD_uhjcZz7SHMtL__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
/**
* Input-minus type of the Comparator
*/
typedef enum COMP_VinM
{
COMP_VinM_IO = (COMP_CTRL_VIN_SEL_IO << COMP_CTRL_VIN_SEL_Pos),
COMP_VinM_DAC = (COMP_CTRL_VIN_SEL_DAC << COMP_CTRL_VIN_SEL_Pos),
} COMP_VinMTypeDef;
/**
* Input-plus type of the Comparator
*/
typedef enum COMP_VinP
{
COMP_VinP_PGA = (COMP_VIPSEL_VIP_SEL_PGA << COMP_VIPSEL_VIP_SEL_Pos),
COMP_VinP_IO0 = (COMP_VIPSEL_VIP_SEL_IO0 << COMP_VIPSEL_VIP_SEL_Pos),
COMP_VinP_IO1 = (COMP_VIPSEL_VIP_SEL_IO1 << COMP_VIPSEL_VIP_SEL_Pos),
COMP_VinP_IO2 = (COMP_VIPSEL_VIP_SEL_IO2 << COMP_VIPSEL_VIP_SEL_Pos),
COMP_VinP_IO3 = (COMP_VIPSEL_VIP_SEL_IO3 << COMP_VIPSEL_VIP_SEL_Pos),
} COMP_VinPTypeDef;
/**
* Filter frequency of the Comparator
*/
typedef enum COMP_Filter
{
COMP_Filter_Bypass = (COMP_CTRL_FIL_CTRL_BYPASS << COMP_CTRL_FIL_CTRL_Pos),
COMP_Filter_Sample_2 = (COMP_CTRL_FIL_CTRL_SAMPLE_2 << COMP_CTRL_FIL_CTRL_Pos),
COMP_Filter_Sample_4 = (COMP_CTRL_FIL_CTRL_SAMPLE_4 << COMP_CTRL_FIL_CTRL_Pos),
COMP_Filter_Sample_8 = (COMP_CTRL_FIL_CTRL_SAMPLE_8 << COMP_CTRL_FIL_CTRL_Pos),
COMP_Filter_Sample_16 = (COMP_CTRL_FIL_CTRL_SAMPLE_16 << COMP_CTRL_FIL_CTRL_Pos),
COMP_Filter_Sample_32 = (COMP_CTRL_FIL_CTRL_SAMPLE_32 << COMP_CTRL_FIL_CTRL_Pos),
COMP_Filter_Sample_64 = (COMP_CTRL_FIL_CTRL_SAMPLE_64 << COMP_CTRL_FIL_CTRL_Pos),
COMP_Filter_Sample_128 = (COMP_CTRL_FIL_CTRL_SAMPLE_128 << COMP_CTRL_FIL_CTRL_Pos),
COMP_Filter_Sample_256 = (COMP_CTRL_FIL_CTRL_SAMPLE_256 << COMP_CTRL_FIL_CTRL_Pos),
} COMP_FilterTypeDef;
/**
* Output polarity of the Comparator
*/
typedef enum COMP_OutPolarity
{
COMP_OutPolarity_Normal = (COMP_CTRL_POL_SEL_NORMAL << COMP_CTRL_POL_SEL_Pos),
COMP_OutPolarity_Invert = (COMP_CTRL_POL_SEL_INVERT << COMP_CTRL_POL_SEL_Pos),
} COMP_OutPolarityTypeDef;
/**
* Interrupt type of the Comparator
*/
typedef enum COMP_IE
{
COMP_IE_None = 0x0ul,
COMP_IE_Rising = COMP_IR_RIE_Msk,
COMP_IE_Falling = COMP_IR_FIE_Msk,
COMP_IE_ALL = (COMP_IR_RIE_Msk | COMP_IR_FIE_Msk),
} COMP_IETypeDef;
/**
* Output type of the Comparator
*/
typedef enum COMP_Vout
{
COMP_Vout_None = 0x0,
COMP_Vout_IO = COMP_CTRL_OUT_EN_Msk,
} COMP_VoutTypeDef;
/**
* Input hysteresis type of the Comparator
*/
typedef enum COMP_Hysteresis
{
COMP_Hysteresis_Disable = 0x0,
COMP_Hysteresis_Enable = COMP_CTRL_HYS_EN_Msk,
} COMP_HysteresisTypeDef;
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief COMP enable/disable
*
* \param [in] pHComp pointer to a COMP instance
* \return
* None
*/
__STATIC_INLINE void COMP_Enable(COMP_Type *pHComp)
{
REG_SET_BITS(pHComp->CTRL, COMP_CTRL_EN_Msk);
return;
}
__STATIC_INLINE void COMP_Disable(COMP_Type *pHComp)
{
REG_CLR_BITS(pHComp->CTRL, COMP_CTRL_EN_Msk);
return;
}
/**
* \brief COMP get output level
*
* \param [in] pHComp pointer to a COMP instance
* \return
* 0 : COMP OUT Low
* others: COMP OUT High
*/
__STATIC_INLINE uint32_t COMP_GetOutputLevel(COMP_Type *pHComp)
{
return REG_READ_MASK(pHComp->CTRL, COMP_CTRL_COUT_Msk);
}
/**
* \brief COMP configure interrupt
*
* \param [in] pHComp pointer to a COMP instance
* \param [in] it_types the target interrupt type, @ref COMP_IETypeDef
* \return
* None
*/
__STATIC_INLINE void COMP_ITConfig(COMP_Type *pHComp, COMP_IETypeDef it_types)
{
REG_WRITE_MASK(pHComp->IR, COMP_IR_RIE_Msk | COMP_IR_FIE_Msk, it_types);
return;
}
/**
* \brief Get the status flags of the COMP
*
* \param [in] pHComp pointer to a COMP instance
* \param [in] flags the target flag type, @ref COMP_IETypeDef
* \return
* 0 : No target status
* other: Get the target status
*/
__STATIC_INLINE uint32_t COMP_GetFlagStatus(COMP_Type *pHComp, COMP_IETypeDef flags)
{
return REG_READ_MASK(pHComp->IF, flags);
}
/**
* \brief Clear the status flags of the COMP
*
* \param [in] pHComp pointer to a COMP instance
* \param [in] it_types the target interrupt type, @ref COMP_IETypeDef
* \return
* None
*/
__STATIC_INLINE void COMP_ClearFlag(COMP_Type *pHComp, COMP_IETypeDef it_types)
{
REG_WRITE_MASK(pHComp->IF, COMP_IR_RIE_Msk | COMP_IR_FIE_Msk, it_types);
return;
}
/**
* \brief Get the interrupt setting flags of the COMP
*
* \param [in] pHComp pointer to a COMP instance
* \return
* it_types, @ref COMP_IETypeDef
*/
__STATIC_INLINE COMP_IETypeDef COMP_GetITFlags(COMP_Type *pHComp)
{
return REG_READ_MASK(pHComp->IR, COMP_IR_RIE_Msk | COMP_IR_FIE_Msk);
}
//=============================================================================
// Structure Definition
//=============================================================================
typedef struct
{
COMP_VinPTypeDef InputPlus; /*!< Set comparator Vin+. @ref COMP_VinPTypeDef */
COMP_VinMTypeDef InputMinus; /*!< Set comparator Vin-. @ref COMP_VinMTypeDef */
COMP_HysteresisTypeDef InputHysteresis; /*!< Set comparator hysteresis mode of the input minus. @ref COMP_HysteresisTypeDef */
COMP_FilterTypeDef FilterFreq; /*!< Set comparator filter frequency. @ref COMP_FilterTypeDef */
COMP_OutPolarityTypeDef OutputPolarity; /*!< Set comparator output polarity. @ref COMP_OutPolarityTypeDef */
COMP_VoutTypeDef OutputSel; /*!< Set comparator output selection. @ref COMP_VoutTypeDef */
uint16_t InitDelay; /*!< Set comparator initial delay ticks */
} COMP_InitTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* @brief Initializes the COMP module according to
* the specified parameters in the init_struct.
*
* @param pHComp: pointer to a COMP instance
* @param pInit: pointer to a COMP_InitTypeDef structure
* that contains the configuration information for the specified COMP module.
* @retval None.
*/
void COMP_Init(COMP_Type *pHComp, COMP_InitTypeDef *pInit);
/**
* \brief De-initializes the COMP module
*
* \param [in] pHComp pointer to a COMP instance
* \return
* None
*/
void COMP_DeInit(COMP_Type *pHComp);
/**
* \brief Set each initial field to default value.
*
* \param [in] pInit pointer to a COMP_InitTypeDef structure. @ref COMP_InitTypeDef
* \return
* None
*/
void COMP_StructInit(COMP_InitTypeDef *pInit);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,110 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_crc.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#ifndef __hal_crc_H_w0Q7P8ed_lHTg_HFk4_sJpZ_ukncYhoixtqA__
#define __hal_crc_H_w0Q7P8ed_lHTg_HFk4_sJpZ_ukncYhoixtqA__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
#define CRC_START_CODE (~0u)
typedef enum
{
CRC_Status_OK,
CRC_Status_Error,
} CRC_Status;
typedef enum
{
CRC_Width_CRC32 = (CRC_CR_POLYSEL_CRC32 << CRC_CR_POLYSEL_Pos),
CRC_Width_CRC16 = (CRC_CR_POLYSEL_CRC16 << CRC_CR_POLYSEL_Pos),
} CRC_WidthTypeDef;
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Initialize CRC module
*
* \return
* None
*/
void CRC_Init(void);
/**
* \brief Calculate the crc value with singal value
*
* \param [in] pValue pointer to an instance of value
* \param [in] crc_width the type of crc width, @ref CRC_WidthTypeDef
* \return
* CRC value
*/
uint32_t CRC_CalcCRC(uint8_t *pValue, CRC_WidthTypeDef crc_width);
/**
* \brief Calculate the CRC value of data stream
*
* \param [in] pData Pointer to the buffer containing the data to be computed
* \param [in] length Length of the buffer to be computed
* \param [in] crc_width the type of crc width, @ref CRC_WidthTypeDef
* \return
* CRC value
*/
uint32_t CRC_CalcBlockCRC(uint8_t *pData, int length, CRC_WidthTypeDef crc_width);
/**
* \brief Get the current CRC value
*
* \return
* CRC value
*/
uint32_t CRC_GetCRC(void);
/**
* \brief Verify the completeness of data
*
* \param [in] Valid_CRC The expected CRC value
* \return
* 0: data does not match
* others: verify success
*/
uint32_t CRC_VerifyFlag(uint32_t Valid_CRC);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,193 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_def.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#ifndef __hal_def_H_wrmPni7q_lbcH_Hmna_sBkY_uUTtDspcvhdh__
#define __hal_def_H_wrmPni7q_lbcH_Hmna_sBkY_uUTtDspcvhdh__
#ifdef __cplusplus
extern "C" {
#endif
#include "device.h"
//=============================================================================
// Constant Definition
//=============================================================================
#if defined(__GNUC__)
#else
#warning Not supported compiler type
#endif
typedef enum
{
DISABLE = 0,
ENABLE = !DISABLE
} FuncStatus, FunctionalState;
typedef enum
{
RESET = 0,
SET = !RESET
} FlagStatus, ITStatus;
typedef enum
{
ERROR = 0,
SUCCESS = !ERROR
} ErrorStatus;
//=============================================================================
// Macro Definition
//=============================================================================
#define REG_SET_BITS(__reg32__, __bit_msk__) ((__reg32__) |= (__bit_msk__))
#define REG_CLR_BITS(__reg32__, __bit_msk__) ((__reg32__) &= ~(__bit_msk__))
#define REG_READ(__reg32__) (__reg32__)
#define REG_READ_MASK(__reg32__, __msk__) ((__reg32__) & (__msk__))
#define REG_WRITE(__reg32__, __val__) ((__reg32__) = (__val__))
#define REG_WRITE_MASK(__reg32__, __msk__, __val__) ((__reg32__) = ((__reg32__) & ~(__msk__)) | ((__val__) & (__msk__)))
#define ALIGN_4(x) (((x) + 0x3ul) & ~0x3ul)
#define UNUSED(X) (void)(X)
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
/**
* register 32-bits operators
*/
__STATIC_INLINE void reg32_set_bits(uint32_t *addr, uint32_t bit_msk)
{
*((uint32_t*)addr) |= bit_msk;
return;
}
__STATIC_INLINE void reg32_clr_bits(uint32_t *addr, uint32_t bit_msk)
{
*((uint32_t*)addr) &= ~bit_msk;
return;
}
__STATIC_INLINE uint32_t reg32_read(uint32_t *addr)
{
return *((uint32_t*)addr);
}
__STATIC_INLINE uint32_t reg32_read_mask(uint32_t *addr, uint32_t mask)
{
return (*((uint32_t*)addr) & mask);
}
__STATIC_INLINE void reg32_write(uint32_t *addr, uint32_t value)
{
*(uint32_t*)addr = value;
return;
}
__STATIC_INLINE void reg32_write_mask(uint32_t *addr, uint32_t mask, uint32_t value)
{
*(uint32_t*)addr = ((*(uint32_t*)addr) & ~mask) | (value & mask);
return;
}
/**
* register 16-bits operators
*/
__STATIC_INLINE void reg16_set_bits(uint16_t *addr, uint16_t bit_msk)
{
*((uint16_t*)addr) |= bit_msk;
return;
}
__STATIC_INLINE void reg16_clr_bits(uint16_t *addr, uint16_t bit_msk)
{
*((uint16_t*)addr) &= ~bit_msk;
return;
}
__STATIC_INLINE uint16_t reg16_read(uint16_t *addr)
{
return *((uint16_t*)addr);
}
__STATIC_INLINE uint16_t reg16_read_mask(uint16_t *addr, uint16_t mask)
{
return (*((uint16_t*)addr) & mask);
}
__STATIC_INLINE void reg16_write(uint16_t *addr, uint16_t value)
{
*(uint16_t*)addr = value;
return;
}
__STATIC_INLINE void reg16_write_mask(uint16_t *addr, uint16_t mask, uint16_t value)
{
*(uint16_t*)addr = ((*(uint16_t*)addr) & ~mask) | (value & mask);
return;
}
/**
* register 8-bits operators
*/
__STATIC_INLINE void reg8_set_bits(uint8_t *addr, uint8_t bit_msk)
{
*((uint8_t*)addr) |= bit_msk;
return;
}
__STATIC_INLINE void reg8_clr_bits(uint8_t *addr, uint8_t bit_msk)
{
*((uint8_t*)addr) &= ~bit_msk;
return;
}
__STATIC_INLINE uint8_t reg8_read(uint8_t *addr)
{
return *((uint8_t*)addr);
}
__STATIC_INLINE uint8_t reg8_read_mask(uint8_t *addr, uint8_t mask)
{
return (*((uint8_t*)addr) & mask);
}
__STATIC_INLINE void reg8_write(uint8_t *addr, uint8_t value)
{
*(uint8_t*)addr = value;
return;
}
__STATIC_INLINE void reg8_write_mask(uint8_t *addr, uint8_t mask, uint8_t value)
{
*(uint8_t*)addr = ((*(uint8_t*)addr) & ~mask) | (value & mask);
return;
}
//=============================================================================
// Public Function Definition
//=============================================================================
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,138 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_device.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#ifndef __hal_device_H_wh21It4q_lc5o_HN4v_sYN9_uMvM6ZVOvOoN__
#define __hal_device_H_wh21It4q_lc5o_HN4v_sYN9_uMvM6ZVOvOoN__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_conf.h"
//=============================================================================
// Constant Definition
//=============================================================================
#if defined(USE_FULL_ASSERT)
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((char*)__func__, __LINE__))
void assert_failed(char *func, uint32_t line);
#else
#define assert_param(expr)
#endif
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief Count leading zeros
*
* \param [in] x Value to count the leading zeros
* \return
* Number of leading zeros in value
*/
__STATIC_FORCEINLINE int HAL_CLZ(uint32_t x)
{
return __builtin_clz(x);
}
/**
* \brief Count the amount of bit-1
*
* \param [in] x Value to count the amount of bit-1
* \return
* The amount of bit-1
*/
__STATIC_FORCEINLINE int HAL_PopCount(uint32_t x)
{
return __builtin_popcount(x);
}
/**
* \brief Get UID-1 value
* \return UID-1
*/
__STATIC_FORCEINLINE uint32_t HAL_GetUID1(void)
{
return REG_READ(UID->UID1);
}
/**
* \brief Get UID-2 value
* \return UID-2
*/
__STATIC_FORCEINLINE uint32_t HAL_GetUID2(void)
{
return REG_READ(UID->UID2);
}
/**
* \brief Get UID-3 value
* \return UID-3
*/
__STATIC_FORCEINLINE uint32_t HAL_GetUID3(void)
{
return REG_READ(UID->UID3);
}
/**
* \brief Initialize the peripherals of this device
*
* \return
* None
*/
__STATIC_FORCEINLINE void HAL_DeviceInit(void)
{
REG_WRITE(SYSCFG->PRSTEN1, 0xFFFFFFFFul);
REG_WRITE(SYSCFG->PRSTEN, 0xFFFFFFFFul);
REG_WRITE(SYSCFG->PRSTEN1, 0x0ul);
REG_WRITE(SYSCFG->PRSTEN, 0x0ul);
return;
}
#define HAL_SetBits(_val_, _bit_mak_) REG_SET_BITS(_val_, _bit_mak_)
#define HAL_ClearBits(_val_, _bit_mak_) REG_CLR_BITS(_val_, _bit_mak_)
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Set the seed to initialize pseudo-random number generator
*
* \param [in] seed The seed value
* \return
* None
*/
void HAL_SRand(uint32_t seed);
/**
* \brief Generate pseudo-random number
*
* \return
* The pseudo-random value
*/
uint32_t HAL_Rand(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,107 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_dsp.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#ifndef __hal_dsp_H_we15xl18_lz2k_Hix7_sTLr_uIRwmlwU5wH6__
#define __hal_dsp_H_we15xl18_lz2k_Hix7_sTLr_uIRwmlwU5wH6__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief H/W DSP Divide operation
*
* \param [in] numerator The numerator of Fraction
* \param [in] denominator The denominator of Fraction
* \param [in] pQuotient Pointer to a 32-bits signed value (Quotient)
* \param [in] pRemainder Pointer to a 32-bits signed value (Remainder)
* \return
* 0: ok
* others: fail
*/
__STATIC_FORCEINLINE int DSP_Div32(int numerator, int denominator, int *pQuotient, int *pRemainder)
{
DSP->CR_b.MODE = DSP_CR_MODE_DIV;
REG_WRITE(DSP->SDAT1, numerator);
REG_WRITE(DSP->SDAT2, denominator);
while( !REG_READ(DSP->SR) ) {}
if( pQuotient ) *pQuotient = REG_READ(DSP->RSLT1);
if( pRemainder ) *pRemainder = REG_READ(DSP->RSLT2);
return 0;
}
//=============================================================================
// Structure Definition
//=============================================================================
/**
* the paraments of dsp square root calculate
*/
typedef struct
{
union {
uint64_t value64;
uint32_t value32[2];
};
} DSP_SqrtParamTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
#if 0
/**
* \brief H/W DSP Divide operation
*
* \param [in] numerator The numerator of Fraction
* \param [in] denominator The denominator of Fraction
* \param [in] pQuotient Pointer to a 32-bits signed value (Quotient)
* \param [in] pRemainder Pointer to a 32-bits signed value (Remainder)
* \return
* 0: ok
* others: fail
*/
int DSP_Div32(int numerator, int denominator, int *pQuotient, int *pRemainder);
#endif
/**
* \brief H/w DSP Square root operation (unsigned 64-bits)
*
* \param [in] pParam The input paraments of Square root operation
* \return
* the calculated value
*/
uint32_t DSP_Sqrt32(DSP_SqrtParamTypeDef *pParam);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,203 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_flash.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#ifndef __hal_flash_H_wm4SBnn4_laN2_HBZw_sxWM_uBboLm9QaVsk__
#define __hal_flash_H_wm4SBnn4_laN2_HBZw_sxWM_uBboLm9QaVsk__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
#define FLASH_1_SECTOR_SIZE 512
#define FLASH_1_PAGE_SIZE FLASH_1_SECTOR_SIZE
#define FLASH_AUTH_KEY 0xA5A50000ul
/**
* eFlash status
*/
typedef enum flash_state
{
FLASH_STATE_OK = 0,
FLASH_STATE_BUSY,
FLASH_STATE_FAIL_PROG,
FLASH_STATE_FAIL_ERASE,
FLASH_STATE_FAIL_ADDR,
FLASH_STATE_NOT_4_ALIGN,
FLASH_STATE_FAIL_PARAM,
FLASH_STATE_TIMEOUT
} flash_state_t;
/**
* eFlash latency type
*/
typedef enum flash_latency
{
FLASH_LATENCY_1 = (0x1ul << FLASH_CMD_NWS_Pos),
FLASH_LATENCY_2 = (0x2ul << FLASH_CMD_NWS_Pos),
FLASH_LATENCY_3 = (0x3ul << FLASH_CMD_NWS_Pos),
} flash_latency_t;
/**
* eFlash H/w error type
*/
typedef enum flash_err_type
{
FLASH_ERR_TYPE_OK = 0,
FLASH_ERR_TYPE_KEY = FLASH_SR_KEY_ERR_Msk,
FLASH_ERR_TYPE_ACCESS = FLASH_SR_ACC_ERR_Msk,
FLASH_ERR_TYPE_ADDRESS = FLASH_SR_ADDR_ERR_Msk,
FLASH_ERR_TYPE_SYSINFO_FAIL = (FLASH_SR_HSI_TC_ERR_Msk | FLASH_SR_RSTIO_AF_ERR_Msk | \
FLASH_SR_LDO_TRIM_ERR_Msk | FLASH_SR_VBUF_TRIM_ERR_Msk | \
FLASH_SR_LSI_TRIM_ERR_Msk | FLASH_SR_HSI_TRIM_ERR_Msk),
FLASH_ERR_TYPE_INVALID_TRIM_HSI = FLASH_SR_HSI_TRIM_ERR_Msk,
FLASH_ERR_TYPE_INVALID_TRIM_HSI_TC = FLASH_SR_HSI_TC_ERR_Msk,
FLASH_ERR_TYPE_INVALID_TRIM_LSI = FLASH_SR_LSI_TRIM_ERR_Msk,
FLASH_ERR_TYPE_INVALID_TRIM_VBUF = FLASH_SR_VBUF_TRIM_ERR_Msk,
FLASH_ERR_TYPE_INVALID_TRIM_LDO = FLASH_SR_LDO_TRIM_ERR_Msk,
FLASH_ERR_TYPE_INVALID_RSTIO_CFG = FLASH_SR_RSTIO_AF_ERR_Msk,
} flash_err_type_t;
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief Check eFlash is idle or not.
*
* \return
* 0 : busy
* others: idle
*/
__STATIC_FORCEINLINE uint32_t FLASH_IsIdle(void)
{
return !REG_READ_MASK(FLASH->CMD, FLASH_CMD_START_Msk);
}
/**
* \brief Get the latency type of eFlash
*
* \return
* Latency value, @ref flash_latency_t
*/
__STATIC_FORCEINLINE uint32_t FLASH_GetLatency(void)
{
return REG_READ_MASK(FLASH->CMD, FLASH_CMD_NWS_Msk);
}
/**
* \brief Get eFlash H/w error type
*
* \return
* eFlash H/w error type, @ref flash_err_type_t
*/
__STATIC_FORCEINLINE flash_err_type_t FLASH_GetHwErr(void)
{
return (flash_err_type_t)REG_READ(FLASH->SR);
}
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Set Flash latency
* When CPU frequency is over eFlash,
* CPU MUST wait eFlash response
*
* \param [in] latency CPU wait latency (cycles) for eFlash, @ref flash_latency_t
* \return
* state, @ref flash_state_t
*/
flash_state_t
FLASH_SetLatency(flash_latency_t latency);
/**
* \brief Erase a page of eFlash
*
* \param [in] page_addr the target address (FLASH_1_PAGE_SIZE align) of the eFlash
* \return
* state, @ref flash_state_t
*/
flash_state_t
FLASH_ErasePage(uint32_t page_addr);
/**
* \brief Program a word (32-bits) value to eFlash
*
* \param [in] addr the target address of the eFlash
* \param [in] value the target value (32-bits)
* \return
* state, @ref flash_state_t
*/
flash_state_t
FLASH_ProgWord(uint32_t addr, uint32_t value);
/**
* \brief Program a half-word (16-bits) value to eFlash
*
* \param [in] addr the target address of the eFlash
* \param [in] value the target value (16-bits)
* \return
* state, @ref flash_state_t
*/
flash_state_t
FLASH_ProgHWord(uint32_t addr, uint16_t value);
/**
* \brief Program a byte (8-bits) value to eFlash
*
* \param [in] addr the target address of the eFlash
* \param [in] value the target value (8-bits)
* \return
* state, @ref flash_state_t
*/
flash_state_t
FLASH_ProgByte(uint32_t addr, uint8_t value);
/**
* \brief Program data set to eFlash
*
* \param [in] addr the target address of the eFlash
* \param [in] pData pointer to a 32-bits buffer of data set
* \param [in] length the 4-align length of data
* \return
* state, @ref flash_state_t
*/
flash_state_t
FLASH_ProgData(uint32_t addr, uint32_t *pData, int length);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,420 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_gpio.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#ifndef __hal_gpio_H_wPOJofWz_lXUp_H0cZ_sE46_uv8ZKHIsTlMH__
#define __hal_gpio_H_wPOJofWz_lXUp_H0cZ_sE46_uv8ZKHIsTlMH__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
typedef enum
{
GPIO_PIN_RESET = 0u,
GPIO_PIN_SET,
GPIO_PIN_LOW = GPIO_PIN_RESET,
GPIO_PIN_HIGH = GPIO_PIN_SET,
} GPIO_PinStateTypeDef;
typedef enum
{
GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */
GPIO_Mode_OUT, /*!< GPIO Output Mode */
GPIO_Mode_ANAL, /*!< GPIO Analog In/Out Mode */
GPIO_Mode_AF, /*!< GPIO Alternate function Mode */
GPIO_Mode_PWR_Saving, /*!< GPIO Power-Saving Mode */
} GPIO_ModeTypeDef;
typedef enum
{
GPIO_PuPd_NOPULL = 0x00,
GPIO_PuPd_UP = 0x01,
GPIO_PuPd_DOWN = 0x02
}GPIO_PuPdTypeDef;
typedef enum
{
GPIO_OType_PP = 0x0,
GPIO_OType_OD
}GPIO_OTypeTypeDef;
typedef enum
{
GPIO_Pin_00 = (0x1ul << 0),
GPIO_Pin_01 = (0x1ul << 1),
GPIO_Pin_02 = (0x1ul << 2),
GPIO_Pin_03 = (0x1ul << 3),
GPIO_Pin_04 = (0x1ul << 4),
GPIO_Pin_05 = (0x1ul << 5),
GPIO_Pin_06 = (0x1ul << 6),
GPIO_Pin_07 = (0x1ul << 7),
GPIO_Pin_08 = (0x1ul << 8),
GPIO_Pin_09 = (0x1ul << 9),
GPIO_Pin_10 = (0x1ul << 10),
GPIO_Pin_11 = (0x1ul << 11),
GPIO_Pin_12 = (0x1ul << 12),
GPIO_Pin_13 = (0x1ul << 13),
GPIO_Pin_14 = (0x1ul << 14),
GPIO_Pin_15 = (0x1ul << 15),
GPIO_PIN_All = 0xFFFFul
} GPIO_PinTypeDef;
/**
* GPIO Pin Alternate Function
*/
typedef enum
{
GPIO_AF_0 = 0,
GPIO_AF_1,
GPIO_AF_2,
GPIO_AF_3,
GPIO_AF_4,
GPIO_AF_5,
GPIO_AF_6,
GPIO_AF_7,
} GPIO_AFTypeDef;
typedef enum
{
GPIO_Peri_Fn1,
GPIO_Peri_BKIN,
GPIO_Peri_ECAP0,
GPIO_Peri_ECAP1,
GPIO_Peri_ECAP2,
GPIO_Peri_EPETR,
GPIO_Peri_Fn2,
GPIO_Peri_TCAP0,
GPIO_Peri_TCAP1,
GPIO_Peri_TCAP2,
GPIO_Peri_T2ETR,
GPIO_Peri_I2C_PULL0,
GPIO_Peri_I2C_PULL1,
GPIO_Peri_I2C_PULL2,
GPIO_Peri_I2C_PULL3,
GPIO_Peri_I2C_PULL4,
GPIO_Peri_I2C_PULL5,
GPIO_Peri_I2C_PULL6,
GPIO_Peri_I2C_PULL7,
} GPIO_PeriTypeDef;
/**
* Peripheral Alternate Function
* ps. GPIO FNx_AFR
*/
typedef enum
{
GPIO_PeriAF_0 = 0,
GPIO_PeriAF_1,
GPIO_PeriAF_2,
GPIO_PeriAF_3,
GPIO_PeriAF_4,
GPIO_PeriAF_5,
GPIO_PeriAF_6,
GPIO_PeriAF_7,
GPIO_PeriAF_8,
GPIO_PeriAF_9,
GPIO_PeriAF_10,
GPIO_PeriAF_11,
} GPIO_PeriAFTypeDef;
typedef enum
{
GPIO_Polarity_Low_Fall = 0, // Low level or falling edge
GPIO_Polarity_High_Rise = 1, // High level or rising edge
} GPIO_PolarityTypeDef;
typedef enum
{
GPIO_Trigger_Level = 0, // Level trigger
GPIO_Trigger_Edge = 1, // Edge trigger
GPIO_Trigger_Any_Edge = 2,
} GPIO_TriggerTypeDef;
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief Reads the input data of specified GPIO port pin.
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pin the target pin, @ref GPIO_PinTypeDef
* \return
* 0 : pin low state
* others: pin high state
*/
__STATIC_FORCEINLINE uint8_t GPIO_ReadInputDataBit(GPIO_Type *pHGpio, GPIO_PinTypeDef pin)
{
return REG_READ_MASK(pHGpio->DAT, pin) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
}
/**
* \brief Read all input data of a GPIO port.
*
* \param [in] pHGpio Pointer to a GPIO handler
* \return
* the gpio pins data
*/
__STATIC_FORCEINLINE uint16_t GPIO_ReadInputData(GPIO_Type *pHGpio)
{
return REG_READ(pHGpio->DAT);
}
/**
* \brief Reads the output data of specified GPIO port pin.
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pin the target pin, @ref GPIO_PinTypeDef
* \return
* 0 : pin low state
* others: pin high state
*/
__STATIC_FORCEINLINE uint8_t GPIO_ReadOutputDataBit(GPIO_Type *pHGpio, uint16_t pin)
{
return REG_READ_MASK(pHGpio->DAT, pin) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
}
/**
* \brief Reads all GPIO port pins output data.
*
* \param [in] pHGpio Pointer to a GPIO handler
* \return
* the gpio pins data
*/
__STATIC_FORCEINLINE uint16_t GPIO_ReadOutputData(GPIO_Type *pHGpio)
{
return REG_READ(pHGpio->DAT);
}
/**
* \brief Sets the selected data port bits.
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pins the target pin, @ref GPIO_PinTypeDef
* \return
* none
*/
__STATIC_FORCEINLINE void GPIO_SetBits(GPIO_Type *pHGpio, uint16_t pins)
{
REG_SET_BITS(pHGpio->LAT, pins);
return;
}
/**
* \brief Clears the selected data port bits.
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pins the target pin, @ref GPIO_PinTypeDef
* \return
* none
*/
__STATIC_FORCEINLINE void GPIO_ResetBits(GPIO_Type *pHGpio, uint16_t pins)
{
REG_CLR_BITS(pHGpio->LAT, pins);
return;
}
/**
* \brief Sets or clears the selected data port bit.
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pins the target pin, @ref GPIO_PinTypeDef
* \param [in] state the target pin state, @ref GPIO_PinStateTypeDef
* \return
* None
*/
__STATIC_FORCEINLINE void GPIO_WriteBit(GPIO_Type *pHGpio, uint16_t pins, GPIO_PinStateTypeDef state)
{
(state == GPIO_PIN_HIGH) ?
REG_SET_BITS(pHGpio->LAT, pins) :
REG_CLR_BITS(pHGpio->LAT, pins);
return;
}
/**
* \brief Writes data to the specified GPIO data port.
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] value Specifies the value to be written to the port output data register
* \return
* None
*/
__STATIC_FORCEINLINE void GPIO_Write(GPIO_Type *pHGpio, uint16_t value)
{
REG_WRITE(pHGpio->LAT, value);
return;
}
/**
* \brief Toggle the specified pin of GPIO port.
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pin The target pin, @ref GPIO_PinTypeDef
* \return
* None
*/
__STATIC_FORCEINLINE void GPIO_TogglePin(GPIO_Type *pHGpio, GPIO_PinTypeDef pin)
{
pHGpio->LAT ^= pin;
return;
}
/**
* \brief Enable/Disable the pin interrupt of GPIO
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pin The target pin, @ref GPIO_PinTypeDef
* \return
* None
*/
__STATIC_FORCEINLINE void GPIO_ITEnable(GPIO_Type *pHGpio, GPIO_PinTypeDef pin)
{
REG_SET_BITS(pHGpio->IES, pin);
return;
}
__STATIC_FORCEINLINE void GPIO_ITDisable(GPIO_Type *pHGpio, GPIO_PinTypeDef pin)
{
REG_SET_BITS(pHGpio->IEC, pin);
return;
}
/**
* \brief Get the interrupt flag of a GPIO pin
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pin The target pin, @ref GPIO_PinTypeDef
* \return
* the flag of status
*/
__STATIC_FORCEINLINE uint32_t GPIO_GetITFlag(GPIO_Type *pHGpio, GPIO_PinTypeDef pin)
{
return REG_READ_MASK(pHGpio->IST, pin);
}
/**
* \brief Clear GPIO interrupt flag
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pin The target pin, @ref GPIO_PinTypeDef
* \return
* None
*/
__STATIC_FORCEINLINE void GPIO_ClearITFlag(GPIO_Type *pHGpio, GPIO_PinTypeDef pin)
{
REG_SET_BITS(pHGpio->IST, pin);
return;
}
//=============================================================================
// Structure Definition
//=============================================================================
typedef struct GPIO_ITInit
{
GPIO_PolarityTypeDef GPIO_Polarity; /*!< Interrupt polarity.
This parameter can be a value of @ref GPIO_PolarityTypeDef */
GPIO_TriggerTypeDef GPIO_Trigger; /*!< Interrupt trigger type.
This parameter can be a value of @ref GPIO_TriggerTypeDef */
} GPIO_ITInitTypeDef;
typedef struct GPIO_Init
{
uint16_t GPIO_Pin; /*!< GPIO_Pin */
GPIO_ModeTypeDef GPIO_Mode; /*!< GPIO_Mode */
GPIO_PuPdTypeDef GPIO_PuPd; /*!< Specifies the operating Pull-up/Pull down for the selected pins.
This parameter can be a value of @ref GPIO_PuPdTypeDef */
GPIO_OTypeTypeDef GPIO_OType; /*!< Specifies the operating output type for the selected pins.
This parameter can be a value of @ref GPIO_OTypeTypeDef */
GPIO_AFTypeDef GPIO_AF_Mode; /*!< Peripheral to be connected to the selected pins.
This parameter can be a value of @ref GPIO_AFTypeDef */
GPIO_ITInitTypeDef GPIO_ITInit; /*!< Specifies the interrupt initial parameters, @ref GPIO_ITInitTypeDef */
} GPIO_InitTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Initializes the gpio peripheral according to the specified parameters.
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pInit Pointer to a instance of GPIO_InitTypeDef
* \return
* 0 : success
* other: fail
*/
int GPIO_Init(GPIO_Type *pHGpio, GPIO_InitTypeDef *pInit);
/**
* \brief De-initializes the gpio peripheral according to the specified parameters.
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pins The target pin, @ref GPIO_PinTypeDef
* \return
* None
*/
void GPIO_DeInit(GPIO_Type *pHGpio, uint32_t pins);
/**
* \brief Set Pin configuration of Peripheral IP with the specific Alternate Function
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] peri_type the specific peripheral IP, @ref GPIO_PeriTypeDef
* \param [in] af_mode the af mode, @ref GPIO_PeriAFTypeDef
* \return
* None
*/
void GPIO_PeriAFConfig(GPIO_Type *pHGpio, GPIO_PeriTypeDef peri_type, GPIO_PeriAFTypeDef af_mode);
/**
* \brief Configure GPIO interrrupt
*
* \param [in] pHGpio Pointer to a GPIO handler
* \param [in] pins The target pin, @ref GPIO_PinTypeDef
* \param [in] pInit Pointer to an instance of GPIO_ITInitTypeDef, @ref GPIO_ITInitTypeDef
* \return
* Nore
*/
void GPIO_ITConfig(GPIO_Type *pHGpio, GPIO_PinTypeDef pins, GPIO_ITInitTypeDef *pInit);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,325 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_i2c.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#ifndef __hal_i2c_H_wiTQLukR_lyWI_H9X1_s634_uL7YYZQ9qyOX__
#define __hal_i2c_H_wiTQLukR_lyWI_H9X1_s634_uL7YYZQ9qyOX__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
#define I2C_BLOCKING 0xFFFF
typedef enum
{
I2C_Err_OK = 0,
I2C_Err_Fail,
I2C_Err_WrongParams,
I2C_Err_TimeOut,
} I2C_ErrTypeDef;
typedef enum
{
/* Misc */
I2C_State_ERROR = 0x00u,
I2C_State_BUS_IDLE = 0xF8u,
I2C_State_SLAVE_STOP_RESTART = 0xA0u,
/* Master Transmit */
I2C_State_MASTER_TX_START = 0x08u,
I2C_State_MASTER_TX_RESTART = 0x10u,
I2C_State_MASTER_TX_SLAW_ACK = 0x18u, // Master sent (SlaveAddress + W-bit) and received ACK
I2C_State_MASTER_TX_SLAW_NOACK = 0x20u,
I2C_State_MASTER_TX_DATA_ACK = 0x28u, // Master sent data and received ACK
I2C_State_MASTER_TX_DATA_NOACK = 0x30u,
I2C_State_MASTER_TX_LOST_BUS = 0x38u,
/* Master Receive */
I2C_State_MASTER_RX_START = I2C_State_MASTER_TX_START,
I2C_State_MASTER_RX_RESTART = I2C_State_MASTER_TX_RESTART,
I2C_State_MASTER_RX_SLAR_ACK = 0x40u, // Master sent (SlaveAddress + R-bit) and received ACK
I2C_State_MASTER_RX_SLAR_NOACK = 0x48u,
I2C_State_MASTER_RX_DATA_ACK = 0x50u, // Master received data and received ACK
I2C_State_MASTER_RX_DATA_NOACK = 0x58u,
I2C_State_MASTER_RX_LOST_BUS = I2C_State_MASTER_TX_LOST_BUS,
/* Slave Receive */
I2C_State_SLAVE_RX_SLAW_ACK = 0x60u,
I2C_State_SLAVE_RX_SLAW_LOST_BUS = 0x68u,
I2C_State_SLAVE_RX_BROAD_ACK = 0x70u, // received broad address and sent ACK
I2C_State_SLAVE_RX_BADDR_LOST_BUS = 0x78u,
I2C_State_SLAVE_RX_DATA_ACK = 0x80u, // received data and sent ACK
I2C_State_SLAVE_RX_DATA_NOACK = 0x88u,
I2C_State_SLAVE_RX_BDATA_ACK = 0x90u, // received data (with broad address) and sent ACK
I2C_State_SLAVE_RX_BDATA_NOACK = 0x98u,
/* Slave Transmit */
I2C_State_SLAVE_RX_SLAR_ACK = 0xA8u,
I2C_State_SLAVE_TX_LOST_BUS = 0xB0u,
I2C_State_SLAVE_TX_DATA_ACK = 0xB8u,
I2C_State_SLAVE_TX_DATA_NOACK = 0xC0u,
I2C_State_SLAVE_TX_LAST_DATA = 0xC8u,
} I2C_StateTypeDef;
/**
* I2C role mode
*/
typedef enum
{
I2C_Mode_NONE = 0x00U, /*!< No I2C communication on going */
I2C_Mode_MASTER = 0x10U, /*!< I2C communication is in Master Mode */
I2C_Mode_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */
} I2C_ModeTypeDef;
/**
* The divide of I2C Clock
*/
typedef enum
{
I2C_CLK_Div60 = 60,
I2C_CLK_Div120 = 120,
I2C_CLK_Div160 = 160,
I2C_CLK_Div192 = 192,
I2C_CLK_Div244 = 244,
I2C_CLK_Div256 = 256,
I2C_CLK_Div960 = 960,
} I2C_Clk_DivTypeDef;
typedef enum
{
I2C_BroadAck_Disable = 0x0ul,
I2C_BroadAck_Enable = I2C_ADDR_GC_Msk,
} I2C_BroadAckTypeDef;
typedef enum
{
I2C_XferMode_Idle = 0,
I2C_XferMode_Transmite,
I2C_XferMode_Recevie,
} I2C_XferModeTypeDef;
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief Get the Hardware state of an I2C
*
* \param [in] pHI2C The handle of I2C
* \return
* Hardware state
*/
__STATIC_FORCEINLINE uint32_t I2C_GetHwState(I2C_Type *pHI2C)
{
return pHI2C->STAT_b.STAT;
}
//=============================================================================
// Structure Definition
//=============================================================================
/**
* I2C Initial Configuration
*/
typedef struct I2C_Init
{
I2C_Clk_DivTypeDef ClockDiv;
I2C_ModeTypeDef Mode; /*!< Specifies the I2C mode. This parameter can be a value of I2C_mode. */
uint8_t OwnAddress; /*!< Specifies the first device own address. This parameter can be a 7-bit address. */
I2C_BroadAckTypeDef BroadAck; /*!< ACK enable or disable when as slave.
This parameter can be a value of @ref I2C_BroadAckTypeDef */
} I2C_InitTypeDef;
typedef struct I2C_IT_Handle
{
I2C_Type *pHI2C;
uint8_t *pTxBuffPtr; /*!< Pointer to I2C Tx transfer Buffer */
__IO uint16_t TxXferCount; /*!< I2C Tx Transfer Counter */
uint8_t *pRxBuffPtr; /*!< Pointer to I2C Rx transfer Buffer */
__IO uint16_t RxXferCount; /*!< I2C Rx Transfer Counter */
I2C_XferModeTypeDef XferMode;
__IO uint16_t DevAddress; /*!< I2C Target device address */
} I2C_IT_HandleTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Fills each init_struct member with its default value.
*
* \param [in] pInit Pointer to an I2C_InitTypeDef structure
* which will be initialized.
* \return
* None
*/
void I2C_StructInit(I2C_InitTypeDef *pInit);
/**
* \brief Initializes the I2C module
*
* \param [in] pHI2C Pointer to an I2C handler
* \param [in] pInit Pointer to an I2C_InitTypeDef structure that
* contains the configuration information for the specified
* I2C peripheral
* \return
* error code, @ref I2C_ErrTypeDef
*/
I2C_ErrTypeDef I2C_Init(I2C_Type *pHI2C, I2C_InitTypeDef *pInit);
/**
* \brief De-Initializes the I2C peripheral registers to their default values.
*
* \param [in] pHI2C Pointer to an I2C handler
* \return
* None
*/
void I2C_DeInit(I2C_Type *pHI2C);
/**
* \brief I2C-Master transmits an amount of data in blocking mode.
*
* \param [in] pHI2C Pointer to an I2C handler
* \param [in] DevAddr Target device address: The device 7 bits address value
* in datasheet must be shift at right before call interface
* \param [in] pData Pointer to data buffer
* \param [in] Size Amount of data to be sent
* \return
* error code, @ref I2C_ErrTypeDef
*/
I2C_ErrTypeDef I2C_Master_Transmit(I2C_Type *pHI2C, uint16_t DevAddr, uint8_t *pData, uint16_t Size);
/**
* \brief I2C-Master receives an amount of data in blocking mode.
*
* \param [in] pHI2C Pointer to an I2C handler
* \param [in] DevAddr Target device address: The device 7 bits address value
* in datasheet must be shift at right before call interface
* \param [in] pData Pointer to data buffer
* \param [in] pSize Amount of data to be received
* \param [in] Timeout_ms Timeout with mseconds. If Timeout_ms == I2C_BLOCKING, slave transmit with blocking mode
* \return
* error code, @ref I2C_ErrTypeDef
*/
I2C_ErrTypeDef I2C_Master_Receive(I2C_Type *pHI2C, uint8_t DevAddr, uint8_t *pData, uint16_t *pSize, uint16_t Timeout_ms);
/**
* \brief I2C-Slave Transmit data in blocking mode
*
* \param [in] pHI2C Pointer to an I2C handler
* \param [in] pData Pointer to data buffer
* \param [in] Size Amount of data to be sent
* \param [in] Timeout_ms Timeout with mseconds. If Timeout_ms == I2C_BLOCKING, slave transmit with blocking mode
* \return
* error code, @ref I2C_ErrTypeDef
*/
I2C_ErrTypeDef I2C_Slave_Transmit(I2C_Type *pHI2C, uint8_t *pData, uint16_t Size, uint16_t Timeout_ms);
/**
* \brief I2C-Slave Receive data in blocking mode
*
* \param [in] pHI2C Pointer to an I2C handler
* \param [in] pData Pointer to data buffer
* \param [in] pSize Amount of data to be received
* \param [in] Timeout_ms Timeout with mseconds. If Timeout_ms == I2C_BLOCKING, slave transmit with blocking mode
* \return
* error code, @ref I2C_ErrTypeDef
*/
I2C_ErrTypeDef I2C_Slave_Receive(I2C_Type *pHI2C, uint8_t *pData, uint16_t *pSize, uint16_t Timeout_ms);
/**
* \brief I2C-Master transmits an amount of data in interrupt mode.
*
* \param [in] pHITI2C Pointer to an I2C IT handler, @ref I2C_IT_HandleTypeDef
* \param [in] DevAddr Target device address: The device 7 bits address value
* in datasheet must be shift at right before call interface
* \param [in] pData Pointer to data buffer
* \param [in] Size Amount of data to be sent
* \return
* error code, @ref I2C_ErrTypeDef
*/
I2C_ErrTypeDef I2C_Master_Transmit_IT(I2C_IT_HandleTypeDef *pHITI2C, uint16_t DevAddr, uint8_t *pData, uint16_t Size);
/**
* \brief I2C-Master receives an amount of data in interrupt mode.
*
* \param [in] pHITI2C Pointer to an I2C IT handler, @ref I2C_IT_HandleTypeDef
* \param [in] DevAddr Target device address: The device 7 bits address value
* in datasheet must be shift at right before call interface
* \param [in] pData Pointer to data buffer
* \param [in] Size Amount of data to be received
* \return
* error code, @ref I2C_ErrTypeDef
*/
I2C_ErrTypeDef I2C_Master_Receive_IT(I2C_IT_HandleTypeDef *pHITI2C, uint8_t DevAddr, uint8_t *pData, uint16_t Size);
/**
* \brief I2C-Slave Transmit data in interrupt mode
*
* \param [in] pHITI2C Pointer to an I2C IT handler, @ref I2C_IT_HandleTypeDef
* \param [in] pData Pointer to data buffer
* \param [in] Size Amount of data to be sent
* \return
* error code, @ref I2C_ErrTypeDef
*/
I2C_ErrTypeDef I2C_Slave_Transmit_IT(I2C_IT_HandleTypeDef *pHITI2C, uint8_t *pData, uint16_t Size);
/**
* \brief I2C-Slave Receive data in interrupt mode
*
* \param [in] pHITI2C Pointer to an I2C IT handler, @ref I2C_IT_HandleTypeDef
* \param [in] pData Pointer to data buffer
* \param [in] Size Amount of data to be received
* \return
* error code, @ref I2C_ErrTypeDef
*/
I2C_ErrTypeDef I2C_Slave_Receive_IT(I2C_IT_HandleTypeDef *pHITI2C, uint8_t *pData, uint16_t Size);
/**
* \brief This function handles I2C-Master interrupt request.
*
* \param [in] pHITI2C Pointer to an I2C IT Handler, @ref I2C_IT_HandleTypeDef
* \return
* None
*/
void I2C_Master_IRQHandler(I2C_IT_HandleTypeDef *pHITI2C);
/**
* \brief This function handles I2C-Slave interrupt request.
*
* \param [in] pHITI2C Pointer to an I2C IT Handler, @ref I2C_IT_HandleTypeDef
* \return
* None
*/
void I2C_Slave_IRQHandler(I2C_IT_HandleTypeDef *pHITI2C);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,244 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file lptim.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#ifndef __hal_lptim_H_wP2Tfucu_lfcA_HOTx_s6ox_udtG8lP5WVqK__
#define __hal_lptim_H_wP2Tfucu_lfcA_HOTx_s6ox_udtG8lP5WVqK__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
typedef enum
{
LPTIM_CLK_Src_SysClk = (LPTIM_TCR_CLKS_SysClk << LPTIM_TCR_CLKS_Pos),
LPTIM_CLK_Src_LSI = (LPTIM_TCR_CLKS_LSI << LPTIM_TCR_CLKS_Pos),
} LPTIM_CLK_SrcTypeDef;
typedef enum
{
LPTIM_MatchMode_Normal = 0,
LPTIM_MatchMode_IRQ = LPTIM_MCR_MR0INT_Msk,
LPTIM_MatchMode_Reset = LPTIM_MCR_MR0RST_Msk,
LPTIM_MatchMode_Stop = LPTIM_MCR_MR0STOP_Msk,
} LPTIM_MatchModeTypeDef;
typedef enum
{
LPTIM_Flag_Match0 = LPTIM_IR_MR0_Msk,
} LPTIM_FlagTypeDef;
typedef enum
{
LPTIM_TrigSrc_Normal = (LPTIM_TCR_TRIGSEL_Normal << LPTIM_TCR_TRIGSEL_Pos),
LPTIM_TrigSrc_PWMCh0_Rising = (LPTIM_TCR_TRIGSEL_EPWMCh0P << LPTIM_TCR_TRIGSEL_Pos),
LPTIM_TrigSrc_PWMCh1_Rising = (LPTIM_TCR_TRIGSEL_EPWMCh1P << LPTIM_TCR_TRIGSEL_Pos),
LPTIM_TrigSrc_PWMCh2_Rising = (LPTIM_TCR_TRIGSEL_EPWMCh2P << LPTIM_TCR_TRIGSEL_Pos),
LPTIM_TrigSrc_PWMCh0_Falling = (LPTIM_TCR_TRIGSEL_EPWMCh0N << LPTIM_TCR_TRIGSEL_Pos),
LPTIM_TrigSrc_PWMCh1_Falling = (LPTIM_TCR_TRIGSEL_EPWMCh1N << LPTIM_TCR_TRIGSEL_Pos),
LPTIM_TrigSrc_PWMCh2_Falling = (LPTIM_TCR_TRIGSEL_EPWMCh2N << LPTIM_TCR_TRIGSEL_Pos),
} LPTIM_TrigSrcTypeDef;
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief LpTim enable/disable
*
* \param [in] pHLpTim the LpTim/TIm0/TIM1 instance
* \return
* None
*/
__STATIC_INLINE void LPTIM_Enable(LPTIM_Type *pHLpTim)
{
REG_SET_BITS(pHLpTim->TCR, LPTIM_TCR_CEN_Msk);
return;
}
__STATIC_INLINE void LPTIM_Disable(LPTIM_Type *pHLpTim)
{
REG_CLR_BITS(pHLpTim->TCR, LPTIM_TCR_CEN_Msk);
return;
}
/**
* \brief Check whether the specified LpTIM flag is set or not.
*
* \param [in] pHLpTim the LpTim/TIm0/TIM1 instance
* \param [in] flag specifies the flag to check, @ref LPTIM_FlagTypeDef.
* \return
* 0: no status
* others: get the status
*/
__STATIC_INLINE uint32_t LPTIM_GetFlagStatus(LPTIM_Type *pHLpTim, LPTIM_FlagTypeDef flag)
{
return REG_READ_MASK(pHLpTim->IR, flag);
}
/**
* \brief Clear the LpTim's pending flags.
*
* \param [in] pHLpTim the LpTim/TIm0/TIM1 instance
* \param [in] flag specifies the flag to clear, @ref LPTIM_FlagTypeDef.
* \return
* None
*/
__STATIC_INLINE void LPTIM_ClearFlag(LPTIM_Type *pHLpTim, LPTIM_FlagTypeDef flag)
{
REG_SET_BITS(pHLpTim->IR, flag);
return;
}
/**
* \brief Reset LpTim
*
* \param [in] pHLpTim the LpTim/TIm0/TIM1 instance
* \return
* None
*/
__STATIC_INLINE void LPTIM_Reset(LPTIM_Type *pHLpTim)
{
REG_SET_BITS(pHLpTim->TCR, LPTIM_TCR_CRST_Msk);
return;
}
/**
* \brief Set the compare mode
*
* \param [in] pHLpTim the LpTim/TIm0/TIM1 instance
* \param [in] mode the specific match mode, @ref LPTIM_MatchModeTypeDef
* \param [in] MatchValue the target match value
* \return
* None
*/
__STATIC_INLINE void LPTIM_SetMatch(LPTIM_Type *pHLpTim, LPTIM_MatchModeTypeDef mode, uint16_t MatchValue)
{
REG_SET_BITS(pHLpTim->MCR, mode);
REG_WRITE_MASK(pHLpTim->MR0, LPTIM_MR0_MR0_Msk, (MatchValue << LPTIM_MR0_MR0_Pos));
return;
}
/**
* \brief Set LpTim prescaler
*
* \param [in] pHLpTim the LpTim/TIm0/TIM1 instance
* \param [in] pr_value prescaler value
* \return
* None
*/
__STATIC_INLINE void LPTIM_SetPrescaler(LPTIM_Type *pHLpTim, uint8_t pr_value)
{
REG_WRITE_MASK(pHLpTim->PR, LPTIM_PR_PR_Msk, (pr_value << LPTIM_PR_PR_Pos));
return;
}
/**
* \brief Get actual counter value
*
* \param [in] pHLpTim the LpTim/TIm0/TIM1 instance
* \return
* Counter value
*/
__STATIC_INLINE uint16_t LPTIM_GetCounter(LPTIM_Type *pHLpTim)
{
return REG_READ_MASK(pHLpTim->TC, LPTIM_TC_TC_Msk);
}
/**
* \brief Configure the external trigger used as a trigger event for the LPTIM.
*
* \param [in] pHLpTim the LpTim/TIm0/TIM1 instance
* \param [in] trig_src specific the tirgger source of LpTim, @ref LPTIM_TrigSrcTypeDef
* \return
* None
*/
__STATIC_INLINE void LPTIM_ConfigTrigger(LPTIM_Type *pHLpTim, LPTIM_TrigSrcTypeDef trig_src)
{
REG_WRITE_MASK(pHLpTim->TCR, LPTIM_TCR_TRIGSEL_Msk, trig_src);
return;
}
//=============================================================================
// Structure Definition
//=============================================================================
/**
* LpTIM Init structure definition
*/
typedef struct
{
LPTIM_CLK_SrcTypeDef LPTIM_ClockSource; /*!< Specifies the source of the clock. */
LPTIM_MatchModeTypeDef LPTIM_MatchMode; /*!< Specifies the mode when LPTIM matches the target counter value. */
uint16_t LPTIM_MatchValue; /*!< Specifies the repetition counter value. */
uint8_t LPTIM_Prescaler; /*!< Specifies the prescaler value used to divide the LPTIM clock. */
} LPTIM_InitTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* @brief Fills each LPTIM_InitTypeDef member with its default value.
* @param pInit: pointer to a LPTIM_TimeBaseInitTypeDef
* structure which will be initialized.
* @retval None.
*/
void LPTIM_StructInit(LPTIM_InitTypeDef *pInit);
/**
* @brief Initializes the lptim module according to
* the specified parameters in the init_struct.
*
* @param pHLpTim: the LpTim/TIm0/TIM1 instance
* @param pInit: pointer to a LPTIM_InitTypeDef structure
that contains the configuration information for the
* specified LpTIM module.
* @retval None.
*/
void LPTIM_Init(LPTIM_Type *pHLpTim, LPTIM_InitTypeDef *pInit);
/**
* \brief De-initialize LpTim
*
* \param [in] pHLpTim the LpTim/TIm0/TIM1 instance
* \return
* None
*/
void LPTIM_DeInit(LPTIM_Type *pHLpTim);
/**
* \brief Enables or disables the specified LpTim interrupts
*
* \param [in] pHLpTim the LpTim/TIm0/TIM1 instance
* \param [in] has_enable enable or not
* \return
* None
*/
void LPTIM_ITConfig(LPTIM_Type *pHLpTim, int has_enable);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,185 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_opamp.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/12/05
* @license
* @description
*/
#ifndef __hal_opamp_H_wWPO7hlc_lEYx_HN8q_ssua_u8WscF53B3q1__
#define __hal_opamp_H_wWPO7hlc_lEYx_HN8q_ssua_u8WscF53B3q1__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
/**
* The gain type of PGA of OPAMP
*/
typedef enum
{
OPAMP_PGAGain_Ext = (0x00 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_1 = (OPAMP_PGA_CR_PGA_GAIN_x1 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_2 = (OPAMP_PGA_CR_PGA_GAIN_x2 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_3 = (OPAMP_PGA_CR_PGA_GAIN_x3 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_4 = (OPAMP_PGA_CR_PGA_GAIN_x4 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_5 = (OPAMP_PGA_CR_PGA_GAIN_x5 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_6 = (OPAMP_PGA_CR_PGA_GAIN_x6 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_7 = (OPAMP_PGA_CR_PGA_GAIN_x7 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_8 = (OPAMP_PGA_CR_PGA_GAIN_x8 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_9 = (OPAMP_PGA_CR_PGA_GAIN_x9 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_10 = (OPAMP_PGA_CR_PGA_GAIN_x10 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_11 = (OPAMP_PGA_CR_PGA_GAIN_x11 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_12 = (OPAMP_PGA_CR_PGA_GAIN_x12 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_13 = (OPAMP_PGA_CR_PGA_GAIN_x13 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_14 = (OPAMP_PGA_CR_PGA_GAIN_x14 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_15 = (OPAMP_PGA_CR_PGA_GAIN_x15 << OPAMP_PGA_CR_PGA_GAIN_Pos),
OPAMP_PGAGain_16 = (OPAMP_PGA_CR_PGA_GAIN_x16 << OPAMP_PGA_CR_PGA_GAIN_Pos),
} OPAMP_PGAGainTypeDef;
/**
* The Vinput Plus signal source
*/
typedef enum
{
OPAMP_VinP_Internal = (0x0ul << OPAMP_PGA_CR_PGA_VIP_SEL_Pos),
OPAMP_VinP_IO = (0x1ul << OPAMP_PGA_CR_PGA_VIP_SEL_Pos),
} OPAMP_VinPTypeDef;
/**
* The Vinput Minus signal source
*/
typedef enum
{
OPAMP_VinM_GND = (0x0ul << OPAMP_PGA_CR_PGA_VIN_SEL_Pos),
OPAMP_VinM_IO = (0x1ul << OPAMP_PGA_CR_PGA_VIN_SEL_Pos),
} OPAMP_VinMTypeDef;
/**
* The Voutput destination
*/
typedef enum
{
OPAMP_Vout_None = (0x0ul << OPAMP_PGA_CR_PGA_IO_EN_Pos),
OPAMP_Vout_IO = (0x1ul << OPAMP_PGA_CR_PGA_IO_EN_Pos),
} OPAMP_VoutTypeDef;
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief Enable OPAMP
*
* \param [in] pHOPAmp The OPAMP instance
* \return
* None
*/
__STATIC_FORCEINLINE void OPAMP_Enable(OPAMP_Type *pHOPAmp)
{
REG_SET_BITS(pHOPAmp->PGA_CR, OPAMP_PGA_CR_PGA_EN_Msk);
return;
}
/**
* \brief Disable OPAMP
*
* \param [in] pHOPAmp The OPAMP instance
* \return
* None
*/
__STATIC_FORCEINLINE void OPAMP_Disable(OPAMP_Type *pHOPAmp)
{
REG_CLR_BITS(pHOPAmp->PGA_CR, OPAMP_PGA_CR_PGA_EN_Msk);
return;
}
/**
* \brief Set OPAMP PGA gain
*
* \param [in] pHOPAmp The OPAMP instance
* \param [in] gain The PGA gain, @ref OPAMP_PGAGainTypeDef
* \return
* None
*/
__STATIC_FORCEINLINE void OPAMP_SetPGAGain(OPAMP_Type *pHOPAmp, OPAMP_PGAGainTypeDef gain)
{
REG_WRITE_MASK(pHOPAmp->PGA_CR, OPAMP_PGA_CR_PGA_GAIN_Msk, gain);
return;
}
/**
* \brief Get OPAMP PGA gain
*
* \param [in] pHOPAmp The OPAMP instance
* \return
* the gain value, @ref OPAMP_PGAGainTypeDef
*/
__STATIC_FORCEINLINE OPAMP_PGAGainTypeDef OPAMP_GetPGAGain(OPAMP_Type *pHOPAmp)
{
return REG_READ_MASK(pHOPAmp->PGA_CR, OPAMP_PGA_CR_PGA_GAIN_Msk);
}
//=============================================================================
// Structure Definition
//=============================================================================
typedef struct
{
OPAMP_VinPTypeDef OPAMP_VinP;
OPAMP_VinMTypeDef OPAMP_VinM;
OPAMP_VoutTypeDef OPAMP_Vout;
OPAMP_PGAGainTypeDef OPAMP_Gain; /*!< Specifies the PGA Gain of OPAMP, @ref OPAMP_PGAGainTypeDef */
} OPAMP_InitTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Initialize OPAMP
*
* \param [in] pHOPAmp The OPAMP instance
* \param [in] pInit pointer to a OPAMP_InitTypeDef structure
* \return
* 0: ok, others: fail
*/
int OPAMP_Init(OPAMP_Type *pHOPAmp, OPAMP_InitTypeDef *pInit);
/**
* \brief De-Initialize OPAMP
*
* \param [in] pHOPAmp The OPAMP instance
* \return
* None
*/
void OPAMP_DeInit(OPAMP_Type *pHOPAmp);
/**
* \brief Set each field to default value
*
* \param [in] pInit pointer to a OPAMP_InitTypeDef structure
* \return
* None
*/
void OPAMP_StructInit(OPAMP_InitTypeDef *pInit);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,112 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_pwr.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#ifndef __hal_pmu_H_w8beFgJ5_lJKl_Ha3F_skkM_ujsx8CpdddI2__
#define __hal_pmu_H_w8beFgJ5_lJKl_Ha3F_skkM_ujsx8CpdddI2__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
/**
* Power mode type
*/
typedef enum PWR_Mode
{
PWR_Mode_Sleep = 0,
PWR_Mode_DeepSleep,
} PWR_ModeTypeDef;
/**
* The wake-up type of power mode
*/
typedef enum PWR_Wakeup
{
PWR_Wakeup_IO_PORT_A = (0x1ul << 0),
PWR_Wakeup_IO_PORT_B = (0x1ul << 1),
PWR_Wakeup_LpTIM = (0x1ul << 2),
PWR_Wakeup_WDG = (0x1ul << 3),
} PWR_WakeupTypeDef;
/**
* \brief Set the peripheral before entering power mode
*
* \param [in] pwr_mode the target power mode, @ref PWR_ModeTypeDef
* \param [in] pWakeup_type provide the target wake-up module from App level
* \return
* None
*/
typedef void (*CallbaskPreSleepTypeDef)(PWR_ModeTypeDef pwr_mode, PWR_WakeupTypeDef *pWakeup_type);
/**
* \brief Set the peripheral after power mode wake-up
*
* \param [in] pwr_mode the target power mode, @ref PWR_ModeTypeDef
* \return
* None
*/
typedef void (*CallbaskPostSleepTypeDef)(PWR_ModeTypeDef pwr_mode);
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Enters Sleep mode
*
* @param [in] cb_pre_set_clk Set peripheral BEFORE entering sleep
* @param [in] cb_post_set_clk Set peripheral AFTER wake-up from sleep
* \return
* None
*/
void PWR_EnterSleepMode(CallbaskPreSleepTypeDef cb_pre_set,
CallbaskPostSleepTypeDef cb_post_set);
/**
* @brief Enters Deep Sleep mode.
*
* @param [in] cb_pre_set_clk Set peripheral BEFORE entering deepsleep
* @param [in] cb_post_set_clk Set peripheral AFTER wake-up from deepsleep
* @return
* None
*/
void PWR_EnterDeepSleepMode(CallbaskPreSleepTypeDef cb_pre_set,
CallbaskPostSleepTypeDef cb_post_set);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,145 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_spi.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#ifndef __hal_spi_H_wPLkKnnQ_le5I_Hr02_sscR_uSVsVXDq15tf__
#define __hal_spi_H_wPLkKnnQ_le5I_Hr02_sscR_uSVsVXDq15tf__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
#define SPI_Mode_Slave (0x00U) /*!< SPI slave mode */
#define SPI_Mode_Master (0x01U) /*!< SPI master mode */
#define SPI_CPOL_Low (0x00U) /*!< The clock is low in idle state. */
#define SPI_CPOL_High (0x01U) /*!< The clock is high in idle state. */
#define SPI_CPHA_Effective (0x00U) /*!< Data sampling starts from the second clock edge. */
#define SPI_CPHA_Ineffective (0x01U) /*!< Data sampling starts from the first clock edge. */
#define SPI_FirstBit_MSB (0x00U) /*!< Data transfers start from MSB */
#define SPI_FirstBit_LSB (0x01U) /*!< Data transfers start from LSB */
#define SPI_SSOUT_Selected (0x00U)
#define SPI_SSOUT_NoSelected (0x01U)
#define SPI_ManualMode_Disable (0x00U)
#define SPI_ManualMode_Enable (0x01U)
#define SPI_RECVOV_Flag (0x01 << SPI_STA_RECVOV_Pos)
#define SPI_MDF_Flag (0x01 << SPI_STA_MDF_Pos)
#define SPI_TXNFUL_Flag (0x01 << SPI_STA_TXNFUL_Pos)
#define SPI_TXFUL_Flag (0x01 << SPI_STA_TXFUL_Pos)
#define SPI_RXNEP_Flag (0x01 << SPI_STA_RXNEP_Pos)
#define SPI_RXFUL_Flag (0x01 << SPI_STA_RXFUL_Pos)
#define SPI_TXUFL_Flag (0x01 << SPI_STA_TXUFL_Pos)
#define SPI_BUSY_Flag (0x01 << SPI_STA_BUSY_Pos)
typedef enum
{
SPI_TxDataSize_8b = 0, /*!< 8 bits valid data */
SPI_TxDataSize_16b , /*!< 16 bits valid data */
SPI_TxDataSize_24b , /*!< 24 bits valid data */
SPI_TxDataSize_32b , /*!< 32 bits valid data */
} SPI_TXDataSizeTypedef;
typedef enum
{
SPI_BaudratePrescaler_2 = 0, /*!< SCK clock devide by 2 */
SPI_BaudratePrescaler_4 , /*!< SCK clock devide by 4 */
SPI_BaudratePrescaler_8 , /*!< SCK clock devide by 7 */
SPI_BaudratePrescaler_16 , /*!< SCK clock devide by 16 */
SPI_BaudratePrescaler_32 , /*!< SCK clock devide by 32 */
SPI_BaudratePrescaler_64 , /*!< SCK clock devide by 64 */
SPI_BaudratePrescaler_128 , /*!< SCK clock devide by 128 */
SPI_BaudratePrescaler_256 , /*!< SCK clock devide by 256 */
} SPI_DBTypedef;
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
/**
* @brief SPI Init structure definition
*/
typedef struct
{
uint32_t SPI_Mode; /*!< Specifies the SPI operating mode */
uint32_t SPI_CPOL; /*!< Specifies the serial clock steady state */
uint32_t SPI_CPHA; /*!< Specifies the clock active edge for the bit capture */
uint32_t SPI_TxDataSize; /*!< Specifies the SPI available data size */
uint32_t SPI_BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be */
uint32_t SPI_FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit */
} SPI_InitTypeDef;
typedef struct
{
uint8_t d_int; /*!< Specifies the SPI operating mode */
uint8_t d_after; /*!< Specifies the serial clock steady state */
uint8_t d_btwn; /*!< Specifies the clock active edge for the bit capture */
uint8_t d_nss; /*!< Specifies the SPI available data size */
} SPI_DelayTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
void SPI_DeInit(SPI_Type *spi);
void SPI_StructInit(SPI_InitTypeDef *init_struct);
void SPI_Init(SPI_Type *spi, SPI_InitTypeDef *init_struct);
void SPI_Enable(SPI_Type *spi);
void SPI_Disable(SPI_Type *spi);
void SPI_MasterEnable(SPI_Type *spi);
void SPI_SlaveEnable(SPI_Type *spi);
void SPI_SendData(SPI_Type *spi, uint32_t data);
uint32_t SPI_ReceiveData(SPI_Type *spi);
void SPI_SetBaudRatePrescaler(SPI_Type *spi, SPI_DBTypedef spi_baudrateprescaler);
void SPI_SetSSOUT(SPI_Type *spi, uint32_t ss_out_value);
void SPI_SetManualChipSelect(SPI_Type *spi, uint32_t mcs_value);
void SPI_SetManualMode(SPI_Type *spi, uint32_t mce_en);
void SPI_ManualModeStart(SPI_Type *spi);
void SPI_SetTxDataSize(SPI_Type *spi, SPI_TXDataSizeTypedef datasize_value);
uint32_t SPI_GetInterruptStatus(SPI_Type *spi, uint32_t flag);
uint32_t SPI_GetFlagStatus(SPI_Type *spi, uint32_t flag);
void SPI_ClearFlagStatus(SPI_Type *spi, uint32_t flag);
void SPI_SetInterrupt(SPI_Type *spi, uint32_t flag);
void SPI_SetInterruptDisable(SPI_Type *spi, uint32_t flag);
void SPI_SetDelay(SPI_Type *spi, SPI_DelayTypeDef * delay_set);
void SPI_SetIdleCnt(SPI_Type *spi, uint32_t idle_cnt);
void SPI_SetTXTH(SPI_Type *spi, uint32_t txth);
void SPI_SetRXTH(SPI_Type *spi, uint32_t rxth);
void SPI_ManualSendData(SPI_Type *spi, uint32_t data);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,522 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_rcc.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#ifndef __hal_rcc_H_wdMtMHdK_l9Vy_HKdj_sp8x_uwqQm6IIBDo5__
#define __hal_rcc_H_wdMtMHdK_l9Vy_HKdj_sp8x_uwqQm6IIBDo5__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
#define SYSCFG_SIGN_RST_PIN_EN 0xA563
/**
* Clock source
*/
typedef enum
{
SYSCFG_ClkSrc_HSI = SYSCFG_SYSCLKCR_CLKSW_HSI << SYSCFG_SYSCLKCR_CLKSW_Pos, /*!< Internal High Speed Clock. */
SYSCFG_ClkSrc_HSE = SYSCFG_SYSCLKCR_CLKSW_HSE << SYSCFG_SYSCLKCR_CLKSW_Pos, /*!< External High Speed Clock. */
SYSCFG_ClkSrc_LSI = SYSCFG_SYSCLKCR_CLKSW_LSI << SYSCFG_SYSCLKCR_CLKSW_Pos, /*!< Internal Low Speed Clock. */
SYSCFG_ClkSrc_FreqDiv = SYSCFG_SYSCLKCR_CLKSW_CLKDIV << SYSCFG_SYSCLKCR_CLKSW_Pos, /*!< Prescaler Clock. */
} SYSCFG_ClkSrcTypeDef;
typedef enum
{
SYSCFG_SysClkDiv2 = (1ul << SYSCFG_SYSCLKCR_CLKDIV_Pos),
SYSCFG_SysClkDiv4 = (3ul << SYSCFG_SYSCLKCR_CLKDIV_Pos),
SYSCFG_SysClkDiv8 = (7ul << SYSCFG_SYSCLKCR_CLKDIV_Pos),
} SYSCFG_SysClkDivTypeDef;
typedef enum
{
SYSCFG_SysTickSrc_LSI = (SYSCFG_SYSCLKCR_SYSTICKCR_LSI << SYSCFG_SYSCLKCR_SYSTICKCR_Pos),
SYSCFG_SysTickSrc_HSI_Div2 = (SYSCFG_SYSCLKCR_SYSTICKCR_HSI_DIV2 << SYSCFG_SYSCLKCR_SYSTICKCR_Pos),
SYSCFG_SysTickSrc_HSI_Div4 = (SYSCFG_SYSCLKCR_SYSTICKCR_HSI_DIV4 << SYSCFG_SYSCLKCR_SYSTICKCR_Pos),
SYSCFG_SysTickSrc_HSI_Div8 = (SYSCFG_SYSCLKCR_SYSTICKCR_HSI_DIV8 << SYSCFG_SYSCLKCR_SYSTICKCR_Pos),
} SYSCFG_SysTickSrcTypeDef;
typedef enum
{
#define SYSCFG_FLAGS_TYPE_Msk 0x3F
SYSCFG_FLAG_PINRST = (uint8_t)((1 << 6U) | SYSCFG_SYSRSTSR_PADRST_Pos), /*!< PIN reset flag */
SYSCFG_FLAG_PORRST = (uint8_t)((1 << 6U) | SYSCFG_SYSRSTSR_PORRST_Pos), /*!< POR/PDR reset flag */
SYSCFG_FLAG_SFTRST = (uint8_t)((1 << 6U) | SYSCFG_SYSRSTSR_SWRST_Pos), /*!< Software Reset flag */
SYSCFG_FLAG_WDGRST = (uint8_t)((1 << 6U) | SYSCFG_SYSRSTSR_WDGRST_Pos), /*!< Watchdog reset flag */
SYSCFG_FLAG_LOCKUPRST = (uint8_t)((1 << 6U) | SYSCFG_SYSRSTSR_LOCKUPRST_Pos), /*!< LOCKUP reset flag */
SYSCFG_FLAG_LVDRST = (uint8_t)((1 << 6U) | SYSCFG_SYSRSTSR_LVDRST_Pos), /*!< LVD reset flag */
SYSCFG_FLAG_REBOOTRST = (uint8_t)((1 << 6U) | SYSCFG_SYSRSTSR_REBOOTRST_Pos), /*!< Re-boot latch reset flag */
SYSCFG_FLAG_ALL = (uint8_t)((1 << 6U) | SYSCFG_FLAGS_TYPE_Msk) /*!< Only for clearing flags */
} SYSCFG_FlagTypeDef;
//=============================================================================
// Macro Definition
//=============================================================================
/*** PCLK Module Enable ***/
/* UART0 */
#define __HAL_SYSCFG_UART0_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_UART0_Msk)
#define __HAL_SYSCFG_UART0_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_UART0_Msk))
#define __HAL_SYSCFG_UART0_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_UART0_Msk)
/* TIM0 */
#define __HAL_SYSCFG_TIM0_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_TIM0_Msk)
#define __HAL_SYSCFG_TIM0_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_TIM0_Msk))
#define __HAL_SYSCFG_TIM0_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_TIM0_Msk)
/* TIM1 */
#define __HAL_SYSCFG_TIM1_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_TIM1_Msk)
#define __HAL_SYSCFG_TIM1_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_TIM1_Msk))
#define __HAL_SYSCFG_TIM1_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_TIM1_Msk)
/* LPTIM */
#define __HAL_SYSCFG_LPTIM_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_LPTIM_Msk)
#define __HAL_SYSCFG_LPTIM_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_LPTIM_Msk))
#define __HAL_SYSCFG_LPTIM_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_LPTIM_Msk)
/* ADC */
#define __HAL_SYSCFG_ADC_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_ADC_Msk)
#define __HAL_SYSCFG_ADC_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_ADC_Msk))
#define __HAL_SYSCFG_ADC_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_ADC_Msk)
/* EPWM */
#define __HAL_SYSCFG_EPWM_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_EPWM_Msk)
#define __HAL_SYSCFG_EPWM_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_EPWM_Msk))
#define __HAL_SYSCFG_EPWM_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_EPWM_Msk)
/* DSP */
#define __HAL_SYSCFG_DSP_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_DSP_Msk)
#define __HAL_SYSCFG_DSP_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_DSP_Msk))
#define __HAL_SYSCFG_DSP_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_DSP_Msk)
/* COMP0 */
#define __HAL_SYSCFG_COMP0_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_COMP0_Msk)
#define __HAL_SYSCFG_COMP0_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_COMP0_Msk))
#define __HAL_SYSCFG_COMP0_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_COMP0_Msk)
/* SPI */
#define __HAL_SYSCFG_SPI_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_SPI_Msk)
#define __HAL_SYSCFG_SPI_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_SPI_Msk))
#define __HAL_SYSCFG_SPI_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_SPI_Msk)
/* TIM2 */
#define __HAL_SYSCFG_TIM2_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_TIM2_Msk)
#define __HAL_SYSCFG_TIM2_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_TIM2_Msk))
#define __HAL_SYSCFG_TIM2_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_TIM2_Msk)
/* I2C */
#define __HAL_SYSCFG_I2C_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_I2C_Msk)
#define __HAL_SYSCFG_I2C_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_I2C_Msk))
#define __HAL_SYSCFG_I2C_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_I2C_Msk)
/* COMP1 */
#define __HAL_SYSCFG_COMP1_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_COMP1_Msk)
#define __HAL_SYSCFG_COMP1_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_COMP1_Msk))
#define __HAL_SYSCFG_COMP1_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_COMP1_Msk)
/* WDG */
#define __HAL_SYSCFG_WDG_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_WDG_Msk)
#define __HAL_SYSCFG_WDG_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_WDG_Msk))
#define __HAL_SYSCFG_WDG_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_WDG_Msk)
/* AMISC */
#define __HAL_SYSCFG_AMISC_CLK_ENABLE() REG_SET_BITS(SYSCFG->PCLKEN, SYSCFG_PCLKEN_AMISC_Msk)
#define __HAL_SYSCFG_AMISC_CLK_DISABLE() REG_CLR_BITS(SYSCFG->PCLKEN, (SYSCFG_PCLKEN_AMISC_Msk))
#define __HAL_SYSCFG_AMISC_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->PCLKEN, SYSCFG_PCLKEN_AMISC_Msk)
/*** HCLK Module Enable ***/
/* GPIOA */
#define __HAL_SYSCFG_GPIOA_CLK_ENABLE() REG_SET_BITS(SYSCFG->HCLKEN, SYSCFG_HCLKEN_GPIOA_Msk)
#define __HAL_SYSCFG_GPIOA_CLK_DISABLE() REG_CLR_BITS(SYSCFG->HCLKEN, (SYSCFG_HCLKEN_GPIOA_Msk))
#define __HAL_SYSCFG_GPIOA_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->HCLKEN, SYSCFG_HCLKEN_GPIOA_Msk)
/* GPIOB */
#define __HAL_SYSCFG_GPIOB_CLK_ENABLE() REG_SET_BITS(SYSCFG->HCLKEN, SYSCFG_HCLKEN_GPIOB_Msk)
#define __HAL_SYSCFG_GPIOB_CLK_DISABLE() REG_CLR_BITS(SYSCFG->HCLKEN, (SYSCFG_HCLKEN_GPIOB_Msk))
#define __HAL_SYSCFG_GPIOB_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->HCLKEN, SYSCFG_HCLKEN_GPIOB_Msk)
/* CRC */
#define __HAL_SYSCFG_CRC_CLK_ENABLE() REG_SET_BITS(SYSCFG->HCLKEN, SYSCFG_HCLKEN_CRC_Msk)
#define __HAL_SYSCFG_CRC_CLK_DISABLE() REG_CLR_BITS(SYSCFG->HCLKEN, (SYSCFG_HCLKEN_CRC_Msk))
#define __HAL_SYSCFG_CRC_IS_CLK_ENABLED() REG_READ_MASK(SYSCFG->HCLKEN, SYSCFG_HCLKEN_CRC_Msk)
/*** peripherals reset ***/
/* UART0 */
#define __HAL_SYSCFG_UART0_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_UART0_Msk)
#define __HAL_SYSCFG_UART0_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_UART0_Msk)
#define __HAL_SYSCFG_RESET_UART0() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_UART0_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_UART0_Msk); \
}while(0)
/* TIM0 */
#define __HAL_SYSCFG_TIM0_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM0_Msk)
#define __HAL_SYSCFG_TIM0_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM0_Msk)
#define __HAL_SYSCFG_RESET_TIM0() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM0_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM0_Msk); \
}while(0)
/* TIM1 */
#define __HAL_SYSCFG_TIM1_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM1_Msk)
#define __HAL_SYSCFG_TIM1_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM1_Msk)
#define __HAL_SYSCFG_RESET_TIM1() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM1_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM1_Msk); \
}while(0)
/* LPTIM */
#define __HAL_SYSCFG_LPTIM_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_LPTIM_Msk)
#define __HAL_SYSCFG_LPTIM_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_LPTIM_Msk)
#define __HAL_SYSCFG_RESET_LPTIM() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_LPTIM_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_LPTIM_Msk); \
}while(0)
/* ADC */
#define __HAL_SYSCFG_ADC_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_ADC_Msk)
#define __HAL_SYSCFG_ADC_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_ADC_Msk)
#define __HAL_SYSCFG_RESET_ADC() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_ADC_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_ADC_Msk); \
}while(0)
/* EPWM */
#define __HAL_SYSCFG_EPWM_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_EPWM_Msk)
#define __HAL_SYSCFG_EPWM_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_EPWM_Msk)
#define __HAL_SYSCFG_RESET_EPWM() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_EPWM_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_EPWM_Msk); \
}while(0)
/* DSP */
#define __HAL_SYSCFG_DSP_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_DSP_Msk)
#define __HAL_SYSCFG_DSP_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_DSP_Msk)
#define __HAL_SYSCFG_RESET_DSP() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_DSP_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_DSP_Msk); \
}while(0)
/* COMP0 */
#define __HAL_SYSCFG_COMP0_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_COMP0_Msk)
#define __HAL_SYSCFG_COMP0_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_COMP0_Msk)
#define __HAL_SYSCFG_RESET_COMP0() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_COMP0_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_COMP0_Msk); \
}while(0)
/* SPI */
#define __HAL_SYSCFG_SPI_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_SPI_Msk)
#define __HAL_SYSCFG_SPI_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_SPI_Msk)
#define __HAL_SYSCFG_RESET_SPI() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_SPI_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_SPI_Msk); \
}while(0)
/* TIM2 */
#define __HAL_SYSCFG_TIM2_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM2_Msk)
#define __HAL_SYSCFG_TIM2_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM2_Msk)
#define __HAL_SYSCFG_RESET_TIM2() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM2_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_TIM2_Msk); \
}while(0)
/* I2C */
#define __HAL_SYSCFG_I2C_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_I2C_Msk)
#define __HAL_SYSCFG_I2C_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_I2C_Msk)
#define __HAL_SYSCFG_RESET_I2C() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_I2C_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_I2C_Msk); \
}while(0)
/* COMP1 */
#define __HAL_SYSCFG_COMP1_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_COMP1_Msk)
#define __HAL_SYSCFG_COMP1_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_COMP1_Msk)
#define __HAL_SYSCFG_RESET_COMP1() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_COMP1_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_COMP1_Msk); \
}while(0)
/* WDG */
#define __HAL_SYSCFG_WDG_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_WDG_Msk)
#define __HAL_SYSCFG_WDG_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_WDG_Msk)
#define __HAL_SYSCFG_RESET_WDG() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_WDG_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_WDG_Msk); \
}while(0)
/* AMISC */
#define __HAL_SYSCFG_AMISC_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_AMISC_Msk)
#define __HAL_SYSCFG_AMISC_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_AMISC_Msk)
#define __HAL_SYSCFG_RESET_AMISC() \
do{ REG_SET_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_AMISC_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN, SYSCFG_PRSTEN_AMISC_Msk); \
}while(0)
/*** peripherals reset ***/
/* GPIOA */
#define __HAL_SYSCFG_GPIOA_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_GPIOA_Msk)
#define __HAL_SYSCFG_GPIOA_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_GPIOA_Msk)
#define __HAL_SYSCFG_RESET_GPIOA() \
do{ REG_SET_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_GPIOA_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_GPIOA_Msk); \
}while(0)
/* GPIOB */
#define __HAL_SYSCFG_GPIOB_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_GPIOB_Msk)
#define __HAL_SYSCFG_GPIOB_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_GPIOB_Msk)
#define __HAL_SYSCFG_RESET_GPIOB() \
do{ REG_SET_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_GPIOB_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_GPIOB_Msk); \
}while(0)
/* CRC */
#define __HAL_SYSCFG_CRC_CLK_FORCE_RESET() REG_SET_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_CRC_Msk)
#define __HAL_SYSCFG_CRC_RELEASE_RESET() REG_CLR_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_CRC_Msk)
#define __HAL_SYSCFG_RESET_CRC() \
do{ REG_SET_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_CRC_Msk); \
REG_CLR_BITS(SYSCFG->PRSTEN1, SYSCFG_PRSTEN1_CRC_Msk); \
}while(0)
/**
* \brief Get chip ID of DUT
*
* \return
* Chip ID
*/
__STATIC_FORCEINLINE uint32_t SYSCFG_GetChipID(void)
{
return REG_READ(SYSCFG->CHIPID);
}
/**
* \brief Configure Reset-Pin to normal I/O or not
*
* \param [in] is_enable Set Reset-Pin to normal I/O or not
* \return
* None
*/
__STATIC_FORCEINLINE void SYSCFG_SetRstPin2NormalIO(int is_enable)
{
(is_enable)
? REG_WRITE_MASK(SYSCFG->RSTPINCR, SYSCFG_RSTPINCR_RSTPINAF_Msk, SYSCFG_RSTPINCR_RSTPINAF_OFF << SYSCFG_RSTPINCR_RSTPINAF_Pos)
: REG_WRITE_MASK(SYSCFG->RSTPINCR, SYSCFG_RSTPINCR_RSTPINAF_Msk, SYSCFG_RSTPINCR_RSTPINAF_ON << SYSCFG_RSTPINCR_RSTPINAF_Pos);
return;
}
/**
* \brief Enable low-power feature or not
*
* \param [in] is_enable 0: disable, others: enable
* \return
* None
*/
__STATIC_FORCEINLINE void SYSCFG_SetLowPower(int is_enable)
{
(is_enable)
? REG_SET_BITS(SYSCFG->PMUCR, SYSCFG_PMUCR_PMUEN_Msk)
: REG_CLR_BITS(SYSCFG->PMUCR, SYSCFG_PMUCR_PMUEN_Msk);
return;
}
/**
* \brief Get the system clock source type
*
* \return
* The system clock source type, @ref SYSCFG_ClkSrcTypeDef
*/
__STATIC_FORCEINLINE SYSCFG_ClkSrcTypeDef SYSCFG_GetSysClkType(void)
{
return REG_READ_MASK(SYSCFG->SYSCLKCR, SYSCFG_SYSCLKCR_CLKSW_Msk);
}
/**
* \brief Set System-Tick source
*
* \param [in] ClkSrc the target clock source of System-Tick, @ref SYSCFG_SysTickSrcTypeDef
* \return
* None
*/
__STATIC_FORCEINLINE void SYSCFG_SetSysTickSrc(SYSCFG_SysTickSrcTypeDef ClkSrc)
{
REG_WRITE_MASK(SYSCFG->SYSCLKCR, SYSCFG_SYSCLKCR_SYSTICKCR_Msk, ClkSrc);
return;
}
/**
* \brief Get System-Tick source
*
* \return
* the current clock source of System-Tick, @ref SYSCFG_SysTickSrcTypeDef
*/
__STATIC_FORCEINLINE SYSCFG_SysTickSrcTypeDef SYSCFG_GetSysTickSrc(void)
{
return REG_READ_MASK(SYSCFG->SYSCLKCR, SYSCFG_SYSCLKCR_SYSTICKCR_Msk);
}
/**
* \brief Set LSI Always On
*
* \param [in] is_enable 0: disable, others: enable
* \return
* None
*/
__STATIC_FORCEINLINE void SYSCFG_SetLSIAlwaysOn(int is_enable)
{
(is_enable)
? REG_SET_BITS(SYSCFG->SYSCLKCR, SYSCFG_SYSCLKCR_LSIAON_Msk)
: REG_CLR_BITS(SYSCFG->SYSCLKCR, SYSCFG_SYSCLKCR_LSIAON_Msk);
return;
}
//=============================================================================
// Structure Definition
//=============================================================================
typedef struct
{
SYSCFG_ClkSrcTypeDef ClkSource; /*!< The target clock source, @ref SYSCFG_ClkSrcTypeDef.
If ClkSource == SYSCFG_ClkSrc_FreqDiv,
SysClk_Div will be effective. */
SYSCFG_SysClkDivTypeDef SysClk_Div; /*!< SYSCLK clock prescaler, @ref SYSCFG_SysClkDivTypeDef (default: Div2). */
SYSCFG_SysTickSrcTypeDef SysTickSrc; /*!< Select the clock source of system-tick, @ref SYSCFG_SysTickSrcTypeDef (default: LSI) */
} SYSCFG_ClkInitTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Configure system clock
*
* \param [in] pInit Pointer to a SYSCFG_ClkInitTypeDef structure, @ref SYSCFG_ClkInitTypeDef
* \return
* None
*/
void SYSCFG_SysClkConfig(SYSCFG_ClkInitTypeDef *pInit);
/**
* \brief Checks whether the specified SYSCFG flag is set or not.
*
* \param [in] flag Specifies the flag to check, @ref SYSCFG_FlagTypeDef
* \return
* 0 : Nothing
* others: Get the specific status
*/
int SYSCFG_GetFlagStatus(SYSCFG_FlagTypeDef flag);
/**
* \brief Clear the SYSCFG flags.
*
* \param [in] flag Specifies the flag to check, @ref SYSCFG_FlagTypeDef
* \return
* None
*/
void SYSCFG_ClearFlags(SYSCFG_FlagTypeDef flag);
/**
* \brief Trigger DUT to reboot and letch system parameters
* ps. This API will block program and force to reboot DUT
*
* \return
* No return
*/
void SYSCFG_RebootLetch(void);
/**
* \brief Configure Alternate Function mode of I/O Pins of ICE (jTag)
*
* \param [in] is_enable Enable ICE I/O pins or not
* \return
* None
*/
void SYSCFG_SetICEPin2NormalIO(int is_enable);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,564 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_timer.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#ifndef __hal_timer_H_wP2TyFFu_lfcA_HOTx_s6ox_udtPYlP5WVqK__
#define __hal_timer_H_wP2TyFFu_lfcA_HOTx_s6ox_udtPYlP5WVqK__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
/**
* @brief TIM Time Base Init structure definition
*/
typedef struct
{
uint16_t TIM_Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock. */
uint32_t TIM_CounterMode; /*!< Specifies the counter mode. */
uint32_t TIM_Period; /*!< Specifies the period value to be loaded into the active */
uint32_t TIM_ClockDivision; /*!< Specifies the clock division. */
uint8_t TIM_RepetitionCounter; /*!< Specifies the repetition counter value. Each time the RCR downcounter */
} TIM_TimeBaseInitTypeDef;
/**
* @brief TIM Output Compare Init structure definition
*/
typedef struct
{
uint32_t TIM_OCMode; /*!< Specifies the TIM mode. */
uint32_t TIM_OutputState; /*!< Specifies the TIM Output Compare state. */
uint32_t TIM_OutputNState; /*!< Specifies the TIM complementary Output Compare state. */
uint32_t TIM_Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register. */
uint32_t TIM_OCPolarity; /*!< Specifies the output polarity. */
uint32_t TIM_OCNPolarity; /*!< Specifies the complementary output polarity. */
uint32_t TIM_OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. */
uint32_t TIM_OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. */
} TIM_OCInitTypeDef;
/**
* @brief TIM Input Capture Init structure definition
*/
typedef struct
{
uint16_t TIM_Channel; /*!< Specifies the TIM channel. */
uint16_t TIM_ICPolarity; /*!< Specifies the active edge of the input signal. */
uint16_t TIM_ICSelection; /*!< Specifies the input. */
uint16_t TIM_ICPrescaler; /*!< Specifies the Input Capture Prescaler. */
uint16_t TIM_ICFilter; /*!< Specifies the input capture filter. */
} TIM_ICInitTypeDef;
/**
* @brief BDTR structure definition
*/
typedef struct
{
uint16_t TIM_OSSRState; /*!< Specifies the Off-State selection used in Run mode. */
uint16_t TIM_OSSIState; /*!< Specifies the Off-State used in Idle state. */
uint16_t TIM_LOCKLevel; /*!< Specifies the LOCK level parameters. */
uint16_t TIM_DeadTime; /*!< Specifies the delay time between the switching-off and */
uint16_t TIM_Break; /*!< Specifies whether the TIM Break input is enabled or not. */
uint16_t TIM_BreakPolarity; /*!< Specifies the TIM Break Input pin polarity. */
uint16_t TIM_AutomaticOutput; /*!< Specifies whether the TIM Automatic Output feature is enabled or not. */
uint16_t TIM_DTGFTime; /*!< Specifies the delay time between the switching-off and */
uint32_t TIM_DTAEState; /*!< Specifies the delay time between the switching-off and */
} TIM_BDTRInitTypeDef;
/**
* @}
*/
/** @defgroup TIM_Exported_Constants
* @{
*/
/**
* @brief TIM_Clock_Division_CKD
*/
#define TIM_CKD_Div1 (0x00U << TIM_CR1_CKD_Pos) /*!< TDTS = Tck_tim */
#define TIM_CKD_Div2 (0x01U << TIM_CR1_CKD_Pos) /*!< TDTS = 2 * Tck_tim */
#define TIM_CKD_Div4 (0x02U << TIM_CR1_CKD_Pos) /*!< TDTS = 4 * Tck_tim */
/**
* @brief TIM_Counter_Mode
*/
#define TIM_CounterMode_Up (0x00U << TIM_CR1_DIR_Pos) /*!< TIM Up Counting Mode */
#define TIM_CounterMode_Down (0x01U << TIM_CR1_DIR_Pos) /*!< TIM Down Counting Mode */
#define TIM_CounterMode_CenterAligned1 (0x01U << TIM_CR1_CMS_Pos) /*!< TIM Center Aligned Mode1 */
#define TIM_CounterMode_CenterAligned2 (0x02U << TIM_CR1_CMS_Pos) /*!< TIM Center Aligned Mode2 */
#define TIM_CounterMode_CenterAligned3 (0x03U << TIM_CR1_CMS_Pos) /*!< TIM Center Aligned Mode3 */
/**
* @brief TIM_Prescaler_Reload_Mode
*/
#define TIM_PSCReloadMode_Update (0x00U << TIM_EGR_UG_Pos) /*!< The Prescaler is loaded at the update event */
#define TIM_PSCReloadMode_Immediate (0x01U << TIM_EGR_UG_Pos) /*!< The Prescaler is loaded immediately */
/**
* @brief TIM_Output_Compare_and_PWM_modes_and_Forced_Action
*/
#define TIM_OCMode_Timing 0x00U /*!< Output compare mode: Timing */
#define TIM_OCMode_Active 0x01U /*!< Output compare mode: Active */
#define TIM_OCMode_Inactive 0x02U /*!< Output compare mode: Inactive */
#define TIM_OCMode_Toggle 0x03U /*!< Output compare mode: Toggle */
#define TIM_ForcedAction_Inactive 0x04U /*!< Force inactive level on OCnREF */
#define TIM_ForcedAction_Active 0x05U /*!< Force active level on OCnREF */
#define TIM_OCMode_PWM1 0x06U /*!< Output compare mode: PWM1 */
#define TIM_OCMode_PWM2 0x07U /*!< Output compare mode: PWM2 */
/**
* @brief TIM_Output_Compare_Polarity
*/
#define TIM_OCPolarity_High 0x00U /*!< Output Compare active high */
#define TIM_OCPolarity_Low 0x01U /*!< Output Compare active low */
/**
* @brief TIM_Output_Compare_N_Polarity
*/
#define TIM_OCNPolarity_High 0x00U /*!< Output Compare active high */
#define TIM_OCNPolarity_Low 0x01U /*!< Output Compare active low */
/**
* @brief TIM_Output_Compare_state
*/
#define TIM_OutputState_Disable 0x00U /*!< Output Compare Disable */
#define TIM_OutputState_Enable 0x01U /*!< Output Compare Enable */
/**
* @brief TIM_Output_Compare_N_state
*/
#define TIM_OutputNState_Disable 0x00U /*!< Output Compare N Disable */
#define TIM_OutputNState_Enable 0x01U /*!< Output Compare N Enable */
/**
* @brief TIM_Output_Compare_Idle_State
*/
#define TIM_OCIdleState_Reset 0x00U /*!< OCn=0 (after a dead-time if OCnN is implemented) when MOE=0.(n= 0 : 4) */
#define TIM_OCIdleState_Set 0x01U /*!< OCn=1 (after a dead-time if OCnN is implemented) when MOE=0.(n= 0 : 4) */
/**
* @brief TIM_Output_Compare_N_Idle_State
*/
#define TIM_OCNIdleState_Reset 0x00U /*!< OCnN=0 after a dead-time when MOE=0.(n= 0 : 4) */
#define TIM_OCNIdleState_Set 0x01U /*!< OCnN=1 after a dead-time when MOE=0.(n= 0 : 4) */
/**
* @brief TIM_Channel
*/
#define TIM_Channel_1 0x0000 /*!< TIM Channel 1 */
#define TIM_Channel_2 0x0004 /*!< TIM Channel 2 */
#define TIM_Channel_3 0x0008 /*!< TIM Channel 3 */
#define TIM_Channel_4 0x000C /*!< TIM Channel 4 */
/**
* @brief TIM_Input_Capture_Polarity
*/
#define TIM_ICPolarity_Rising (0x00 << TIM_CCER_CC1P_Pos) /*!< IC Rising edge */
#define TIM_ICPolarity_Falling (0x01 << TIM_CCER_CC1P_Pos) /*!< IC Falling edge */
//#define TIM_ICPolarity_BothEdge ((0x01 << TIM_CCER_CC1P_Pos) | (0x01 << TIM_CCER_CC1NP_Pos))
/**
* @brief TIM_Input_Capture_Selection
*/
#define TIM_ICSelection_DirectTI 0x01U
#define TIM_ICSelection_IndirectTI 0x02U
#define TIM_ICSelection_TRC 0x03U
/**
* @brief TIM_Input_Capture_Prescaler
*/
#define TIM_ICPSC_Div1 0x0000 /*!< no prescaler */
#define TIM_ICPSC_Div2 0x0004 /*!< capture is done once every 2 events */
#define TIM_ICPSC_Div4 0x0008 /*!< capture is done once every 4 events */
#define TIM_ICPSC_Div8 0x000C /*!< capture is done once every 8 events */
/**
* @brief OSSR_Off_State_Selection_for_Run_mode_state
*/
#define TIM_OSSRState_Disable (0x00U << TIM_BDTR_OSSR_Pos)
#define TIM_OSSRState_Enable (0x01U << TIM_BDTR_OSSR_Pos)
/**
* @brief OSSI_Off_State_Selection_for_Idle_mode_state
*/
#define TIM_OSSIState_Disable (0x00U << TIM_BDTR_OSSI_Pos)
#define TIM_OSSIState_Enable (0x01U << TIM_BDTR_OSSI_Pos)
/**
* @brief Lock_level
*/
#define TIM_LockLevel_OFF (0x00U << TIM_BDTR_LOCK_Pos)//svd should LOOK -> LOCK
#define TIM_LockLevel_1 (0x01U << TIM_BDTR_LOCK_Pos)
#define TIM_LockLevel_2 (0x02U << TIM_BDTR_LOCK_Pos)
#define TIM_LockLevel_3 (0x03U << TIM_BDTR_LOCK_Pos)
/**
* @brief Break_Input_enable_disable
*/
#define TIM_Break_Disable (0x00U << TIM_BDTR_BKE_Pos) /*!< Break inputs (BRK and CSS clock failure event) disabled */
#define TIM_Break_Enable (0x01U << TIM_BDTR_BKE_Pos) /*!< Break inputs (BRK and CSS clock failure event) enabled */
/**
* @brief Break_Polarity
*/
#define TIM_BreakPolarity_Low (0x00U << TIM_BDTR_BKP_Pos) /*!< Break input BRK is active low */
#define TIM_BreakPolarity_High (0x01U << TIM_BDTR_BKP_Pos) /*!< Break input BRK is active high */
/**
* @brief TIM_AOE_Bit_Set_Reset
*/
#define TIM_AutomaticOutput_Disable (0x00U << TIM_BDTR_AOE_Pos) /*!< MOE can be set only by software. */
#define TIM_AutomaticOutput_Enable (0x01U << TIM_BDTR_AOE_Pos) /*!< MOE can be set by software or automatically at the next
update event (if the break input is not be active). */
/**
* @brief TIM_DOE_Bit_Set_Reset
*/
#define TIM_DirectOutput_Disable (0x00U << TIM_BDTR_DOE_Pos) /*!< Direct output disable, output waiting for dead time */
#define TIM_DirectOutput_Enable (0x01U << TIM_BDTR_DOE_Pos) /*!< Direct output enable, no longer waiting for output after dead time */
/**
* @brief DATE_State_Selection_for_Idle_mode_state
*/
#define TIM_DTAEState_Disable (0x00U << TIM_BDTR_DTAE_Pos)
#define TIM_DTAEState_Enable (0x01U << TIM_BDTR_DTAE_Pos)
/**
* @brief TIM_interrupt_sources
*/
#define TIM_IT_Update (0x01U << TIM_DIER_UIE_Pos) /*!< TIM update Interrupt source */
#define TIM_IT_CC1 (0x01U << TIM_DIER_CC1IE_Pos) /*!< TIM Capture Compare 1 Interrupt source */
#define TIM_IT_CC2 (0x01U << TIM_DIER_CC2IE_Pos) /*!< TIM Capture Compare 2 Interrupt source */
#define TIM_IT_CC3 (0x01U << TIM_DIER_CC3IE_Pos) /*!< TIM Capture Compare 3 Interrupt source */
#define TIM_IT_CC4 (0x01U << TIM_DIER_CC4IE_Pos) /*!< TIM Capture Compare 4 Interrupt source */
#define TIM_IT_COM (0x01U << TIM_DIER_COMIE_Pos) /*!< TIM Commutation Interrupt source */
#define TIM_IT_Trigger (0x01U << TIM_DIER_TIE_Pos) /*!< TIM Trigger Interrupt source */
#define TIM_IT_Break (0x01U << TIM_DIER_BIE_Pos) /*!< TIM Break Interrupt source */
#define TIM_IT_CCD1 (0x01U << TIM_DIER_CCD1IE_Pos) /*!< TIM Capture Compare 1 Interrupt source */
#define TIM_IT_CCD2 (0x01U << TIM_DIER_CCD2IE_Pos) /*!< TIM Capture Compare 2 Interrupt source */
#define TIM_IT_CCD3 (0x01U << TIM_DIER_CCD3IE_Pos) /*!< TIM Capture Compare 3 Interrupt source */
#define TIM_IT_OV (0x01U << TIM_DIER_OVIE_Pos) /*!< TIM Trigger Interrupt source */
#define TIM_IT_UD (0x01U << TIM_DIER_UDIE_Pos) /*!< TIM Break Interrupt source */
#define TIM_IT_CCD4 (0x01U << TIM_DIER_CCD4IE_Pos) /*!< TIM Capture Compare 4 Interrupt source */
/**
* @brief TIM_Event_Source
*/
#define TIM_EventSource_Update (0x01U << TIM_EGR_UG_Pos) /*!< Timer update Event source */
#define TIM_EventSource_CC1 (0x01U << TIM_EGR_CC1G_Pos) /*!< Timer Capture Compare 1 Event source */
#define TIM_EventSource_CC2 (0x01U << TIM_EGR_CC2G_Pos) /*!< Timer Capture Compare 2 Event source */
#define TIM_EventSource_CC3 (0x01U << TIM_EGR_CC3G_Pos) /*!< Timer Capture Compare 3 Event source */
#define TIM_EventSource_CC4 (0x01U << TIM_EGR_CC4G_Pos) /*!< Timer Capture Compare 4 Event source */
#define TIM_EventSource_COM (0x01U << TIM_EGR_COMG_Pos) /*!< Timer COM event source */
#define TIM_EventSource_Trigger (0x01U << TIM_EGR_TG_Pos) /*!< Timer Trigger Event source */
#define TIM_EventSource_Break (0x01U << TIM_EGR_BG_Pos) /*!< Timer Break event source */
/**
* @brief TIM_Internal_Trigger_Selection
*/
#define TIM_TS_ITR0 (0x00U << TIM_SMCR_TS_Pos) /*!< Internal Trigger 0 */
#define TIM_TS_ITR1 (0x01U << TIM_SMCR_TS_Pos) /*!< Internal Trigger 1 */
#define TIM_TS_ITR2 (0x02U << TIM_SMCR_TS_Pos) /*!< Internal Trigger 2 */
#define TIM_TS_ITR3 (0x03U << TIM_SMCR_TS_Pos) /*!< Internal Trigger 3 */
#define TIM_TS_TI1F_ED (0x04U << TIM_SMCR_TS_Pos) /*!< TI1 Edge Detector */
#define TIM_TS_TI1FP1 (0x05U << TIM_SMCR_TS_Pos) /*!< Filtered Timer Input 1 */
#define TIM_TS_TI2FP2 (0x06U << TIM_SMCR_TS_Pos) /*!< Filtered Timer Input 2 */
#define TIM_TS_ETRF (0x07U << TIM_SMCR_TS_Pos) /*!< TI1 Edge Detector */
/**
* @brief TIM_Encoder_Mode
*/
#define TIM_EncoderMode_TI1 (0x01U << TIM_SMCR_SMS_Pos) /*!< Counter counts on TI1FP1 edge depending on TI2FP2 level. */
#define TIM_EncoderMode_TI2 (0x02U << TIM_SMCR_SMS_Pos) /*!< Counter counts on TI2FP2 edge depending on TI1FP1 level. */
#define TIM_EncoderMode_TI12 (0x03U << TIM_SMCR_SMS_Pos) /*!< Counter counts on both TI1FP1 and TI2FP2 edges depending on the level of the other input. */
#define TIM_CCMR1_CC1S_OC (0x00U << TIM_CCMR1_OUTPUT_CC1S_Pos)
#define TIM_CCMR1_CC1S_DirectTI (0x01U << TIM_CCMR1_OUTPUT_CC1S_Pos)
#define TIM_CCMR1_CC1S_IndirectTI (0x02U << TIM_CCMR1_OUTPUT_CC1S_Pos)
#define TIM_CCMR1_CC1S_TRC (0x03U << TIM_CCMR1_OUTPUT_CC1S_Pos)
#define TIM_CCMR1_CC2S_OC (0x00U << TIM_CCMR1_OUTPUT_CC2S_Pos)
#define TIM_CCMR1_CC2S_DirectTI (0x01U << TIM_CCMR1_OUTPUT_CC2S_Pos)
#define TIM_CCMR1_CC2S_IndirectTI (0x02U << TIM_CCMR1_OUTPUT_CC2S_Pos)
#define TIM_CCMR1_CC2S_TRC (0x03U << TIM_CCMR1_OUTPUT_CC2S_Pos)
/**
* @brief TIM_Output_Compare_Preload_State
*/
#define TIM_OCPreload_Disable (0x00U << TIM_CCMR1_OUTPUT_OC1PE_Pos) /*!< TIM output compare preload disable */
#define TIM_OCPreload_Enable (0x01U << TIM_CCMR1_OUTPUT_OC1PE_Pos) /*!< TIM output compare preload enable */
/**
* @brief TIM_Output_Compare_Clear_State
*/
#define TIM_OCClear_Disable (0x00U << TIM_CCMR1_OUTPUT_OC1CE_Pos) /*!< TIM Output clear disable */
#define TIM_OCClear_Enable (0x01U << TIM_CCMR1_OUTPUT_OC1CE_Pos) /*!< TIM Output clear enable */
/**
* @brief TIM_Output_Compare_Fast_State
*/
#define TIM_OCFast_Disable (0x00U << TIM_CCMR1_OUTPUT_OC1FE_Pos) /*!< TIM output compare fast disable */
#define TIM_OCFast_Enable (0x01U << TIM_CCMR1_OUTPUT_OC1FE_Pos) /*!< TIM output compare fast enable */
/**
* @brief TIM_Capture_Compare_state
*/
#define TIM_CCx_Disable (0x00U << TIM_CCER_CC1E_Pos) /*!< Capture/Compare Enable */
#define TIM_CCx_Enable (0x01U << TIM_CCER_CC1E_Pos) /*!< Capture/Compare Enable */
/**
* @brief TIM_Capture_Compare_N_state
*/
#define TIM_CCxN_Disable (0x00U << TIM_CCER_CC1NE_Pos) /*!< Capture/Compare N Enable */
#define TIM_CCxN_Enable (0x01U << TIM_CCER_CC1NE_Pos) /*!< Capture/Compare N Enable */
/**
* @brief TIM_Update_Source
*/
#define TIM_UpdateSource_Global (0x00U << TIM_CR1_URS_Pos) /*!< Source of update is counter overflow/underflow. */
#define TIM_UpdateSource_Regular (0x01U << TIM_CR1_URS_Pos) /*!< Source of update is the counter overflow/underflow
or the setting of UG bit, or an update generation
through the slave mode controller. */
/**
* @brief TIM_One_Pulse_Mode
*/
#define TIM_OPMode_Repetitive (0x00U << TIM_CR1_OPM_Pos) /*!< Counter is not stopped at update event */
#define TIM_OPMode_Single (0x01U << TIM_CR1_OPM_Pos) /*!< Counter stops counting at the next update event (clearing the bit CEN) */
/**
* @brief TIM_Trigger_Output_Source
*/
#define TIM_TRIGSource_Reset (0x00U << TIM_CR2_MMS_Pos) /*!< The UG bit in the TIM_EGR register is used as the trigger output (TRIG). */
#define TIM_TRIGSource_Enable (0x01U << TIM_CR2_MMS_Pos) /*!< The Counter Enable CEN is used as the trigger output (TRIG). */
#define TIM_TRIGSource_Update (0x02U << TIM_CR2_MMS_Pos) /*!< The update event is used as the trigger output (TRIG). */
#define TIM_TRIGSource_OC1 (0x03U << TIM_CR2_MMS_Pos) /*!< The trigger output sends a positive pulse when the CC1IF flag */
#define TIM_TRIGSource_OC1REF (0x04U << TIM_CR2_MMS_Pos) /*!< OC1REF signal is used as the trigger output (TRIG). */
#define TIM_TRIGSource_OC2REF (0x05U << TIM_CR2_MMS_Pos) /*!< OC2REF signal is used as the trigger output (TRIG). */
#define TIM_TRIGSource_OC3REF (0x06U << TIM_CR2_MMS_Pos) /*!< OC3REF signal is used as the trigger output (TRIG). */
#define TIM_TRIGSource_OC4REF (0x07U << TIM_CR2_MMS_Pos) /*!< OC4REF signal is used as the trigger output (TRIG). */
/**
* @brief TIM_Slave_Mode
*/
#define TIM_SlaveMode_Reset (0x04U << TIM_SMCR_SMS_Pos) /*!< Rising edge of the selected trigger signal (TRGI) re-initializes */
#define TIM_SlaveMode_Gated (0x05U << TIM_SMCR_SMS_Pos) /*!< The counter clock is enabled when the trigger signal (TRGI) is high. */
#define TIM_SlaveMode_Trigger (0x06U << TIM_SMCR_SMS_Pos) /*!< The counter starts at a rising edge of the trigger TRGI. */
#define TIM_SlaveMode_External1 (0x07U << TIM_SMCR_SMS_Pos) /*!< Rising edges of the selected trigger (TRGI) clock the counter. */
/**
* @brief TIM_Master_Slave_Mode
*/
#define TIM_MasterSlaveMode_Disable (0x00U << TIM_SMCR_MSM_Pos) /*!< No action */
#define TIM_MasterSlaveMode_Enable (0x01U << TIM_SMCR_MSM_Pos) /*!< synchronization between the current timer and its slaves (through TRIG) */
/**
* @brief TIM_Flags
*/
#define TIM_FLAG_Update (0x01U << TIM_SR_UIF_Pos) /*!< TIM update Flag */
#define TIM_FLAG_CC1 (0x01U << TIM_SR_CC1IF_Pos) /*!< TIM Capture Compare 1 Flag */
#define TIM_FLAG_CC2 (0x01U << TIM_SR_CC2IF_Pos) /*!< TIM Capture Compare 2 Flag */
#define TIM_FLAG_CC3 (0x01U << TIM_SR_CC3IF_Pos) /*!< TIM Capture Compare 3 Flag */
#define TIM_FLAG_CC4 (0x01U << TIM_SR_CC4IF_Pos) /*!< TIM Capture Compare 4 Flag */
#define TIM_FLAG_COM (0x01U << TIM_SR_COMIF_Pos) /*!< TIM Commutation Flag */
#define TIM_FLAG_Trigger (0x01U << TIM_SR_TIF_Pos) /*!< TIM Trigger Flag */
#define TIM_FLAG_Break (0x01U << TIM_SR_BIF_Pos) /*!< TIM Break Flag */
#define TIM_FLAG_CC1OF (0x01U << TIM_SR_CC1OF_Pos) /*!< TIM Capture Compare 1 overcapture Flag */
#define TIM_FLAG_CC2OF (0x01U << TIM_SR_CC2OF_Pos) /*!< TIM Capture Compare 2 overcapture Flag */
#define TIM_FLAG_CC3OF (0x01U << TIM_SR_CC3OF_Pos) /*!< TIM Capture Compare 3 overcapture Flag */
#define TIM_FLAG_CC4OF (0x01U << TIM_SR_CC4OF_Pos) /*!< TIM Capture Compare 4 overcapture Flag */
/**
* @brief PWM phase shift and DMA repeat update
*/
#define TIM_PDER_CCR1SHIFTEN (0x01U << TIM_PDER_CCR1_SHIFT_EN_Pos) /*!< TIM Channel 1 output PWM phase shift enable bit */
#define TIM_PDER_CCR2SHIFTEN (0x01U << TIM_PDER_CCR2_SHIFT_EN_Pos) /*!< TIM Channel 2 output PWM phase shift enable bit */
#define TIM_PDER_CCR3SHIFTEN (0x01U << TIM_PDER_CCR3_SHIFT_EN_Pos) /*!< TIM Channel 3 output PWM phase shift enable bit */
#define TIM_PDER_CCR4SHIFTEN (0x01U << TIM_PDER_CCR4_SHIFT_EN_Pos) /*!< TIM Channel 4 output PWM phase shift enable bit */
#define TIM_PDER_CCR5SHIFTEN (0x01U << TIM_PDER_CCR5_SHIFT_EN_Pos) /*!< TIM Channel 5 output PWM phase shift enable bit */
/** @defgroup TIM_TIx_External_Clock_Source
* @{
*/
#define TIM_TIxExternalCLK1Source_TI1 ((uint16_t)0x0050)
#define TIM_TIxExternalCLK1Source_TI2 ((uint16_t)0x0060)
#define TIM_TIxExternalCLK1Source_TI1ED ((uint16_t)0x0040)
/** @defgroup TIM_External_Trigger_Prescaler
* @{
*/
#define TIM_ExtTRGPSC_OFF (0x00U << TIM_SMCR_ETPS_Pos)
#define TIM_ExtTRGPSC_DIV2 (0x01U << TIM_SMCR_ETPS_Pos)
#define TIM_ExtTRGPSC_DIV4 (0x02U << TIM_SMCR_ETPS_Pos)
#define TIM_ExtTRGPSC_DIV8 (0x03U << TIM_SMCR_ETPS_Pos)
/** @defgroup TIM_External_Trigger_Polarity
* @{
*/
#define TIM_ExtTRGPolarity_Inverted (0x01U << TIM_SMCR_ETP_Pos)
#define TIM_ExtTRGPolarity_NonInverted (0x00U << TIM_SMCR_ETP_Pos)
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
void TIM_DeInit(TIM_Type *tim);
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef *init_struct);
void TIM_TimeBaseInit(TIM_Type *tim, TIM_TimeBaseInitTypeDef *init_struct);
void TIM_OCStructInit(TIM_OCInitTypeDef *init_struct);
void TIM_OC1Init(TIM_Type *tim, TIM_OCInitTypeDef *init_struct);
void TIM_OC2Init(TIM_Type *tim, TIM_OCInitTypeDef *init_struct);
void TIM_OC3Init(TIM_Type *tim, TIM_OCInitTypeDef *init_struct);
void TIM_OC4Init(TIM_Type *tim, TIM_OCInitTypeDef *init_struct);
void TIM_SetIC1Prescaler(TIM_Type *tim, uint32_t psc);
void TIM_SetIC2Prescaler(TIM_Type *tim, uint32_t psc);
void TIM_SetIC3Prescaler(TIM_Type *tim, uint32_t psc);
void TIM_SetIC4Prescaler(TIM_Type *tim, uint32_t psc);
void TIM_ICStructInit(TIM_ICInitTypeDef *init_struct);
void TIM_ICInit(TIM_Type *tim, TIM_ICInitTypeDef *init_struct);
void TIM_PWMIConfig(TIM_Type *tim, TIM_ICInitTypeDef *init_struct);
void TIM_BDTRStructInit(TIM_BDTRInitTypeDef *init_struct);
void TIM_BDTRConfig(TIM_Type *tim, TIM_BDTRInitTypeDef *init_struct);
void TIM_CtrlPWMOutputs(TIM_Type *tim, FunctionalState state);
void TIM_Cmd(TIM_Type *tim, FunctionalState state);
void TIM_ITConfig(TIM_Type *tim, uint32_t it, FunctionalState state);
void TIM_GenerateEvent(TIM_Type *tim, uint32_t source);
void TIM_InternalClockConfig(TIM_Type *tim);
void TIM_ITRxExternalClockConfig(TIM_Type *tim, uint32_t source);
void TIM_SelectInputTrigger(TIM_Type *tim, uint16_t source);
void TIM_PrescalerConfig(TIM_Type *tim, uint16_t prescaler, uint16_t reloadMode);
void TIM_CounterModeConfig(TIM_Type *tim, uint32_t counter_mode);
void TIM_EncoderInterfaceConfig(TIM_Type *tim, uint32_t encoder_mode, uint32_t ic1_polarity, uint32_t ic2_polarity);
void TIM_ForcedOC1Config(TIM_Type *tim, uint32_t forced_action);
void TIM_ForcedOC2Config(TIM_Type *tim, uint32_t forced_action);
void TIM_ForcedOC3Config(TIM_Type *tim, uint32_t forced_action);
void TIM_ForcedOC4Config(TIM_Type *tim, uint32_t forced_action);
void TIM_ClearOC1Ref(TIM_Type *tim, uint16_t TIM_OCClear);
void TIM_ClearOC2Ref(TIM_Type *tim, uint16_t TIM_OCClear);
void TIM_ClearOC3Ref(TIM_Type *tim, uint16_t TIM_OCClear);
void TIM_ClearOC4Ref(TIM_Type *tim, uint16_t TIM_OCClear);
void TIM_ARRPreloadConfig(TIM_Type *tim, FunctionalState state);
void TIM_SelectCOM(TIM_Type *tim, FunctionalState state);
void TIM_SelectCCDMA(TIM_Type *tim, FunctionalState state);
void TIM_CCPreloadControl(TIM_Type *tim, FunctionalState state);
void TIM_OC1PreloadConfig(TIM_Type *tim, uint32_t preload);
void TIM_OC2PreloadConfig(TIM_Type *tim, uint32_t preload);
void TIM_OC3PreloadConfig(TIM_Type *tim, uint32_t preload);
void TIM_OC4PreloadConfig(TIM_Type *tim, uint32_t preload);
void TIM_OC1FastConfig(TIM_Type *tim, uint32_t fast);
void TIM_OC2FastConfig(TIM_Type *tim, uint32_t fast);
void TIM_OC3FastConfig(TIM_Type *tim, uint32_t fast);
void TIM_OC4FastConfig(TIM_Type *tim, uint32_t fast);
void TIM_OC1PolarityConfig(TIM_Type *tim, uint32_t polarity);
void TIM_OC1NPolarityConfig(TIM_Type *tim, uint32_t polarity);
void TIM_OC2PolarityConfig(TIM_Type *tim, uint32_t polarity);
void TIM_OC2NPolarityConfig(TIM_Type *tim, uint32_t polarity);
void TIM_OC3PolarityConfig(TIM_Type *tim, uint32_t polarity);
void TIM_OC3NPolarityConfig(TIM_Type *tim, uint32_t polarity);
void TIM_OC4PolarityConfig(TIM_Type *tim, uint32_t polarity);
void TIM_OC4NPolarityConfig(TIM_Type *tim, uint32_t polarity);
void TIM_CCxCmd(TIM_Type *tim, uint16_t channel, uint32_t ccx_en);
void TIM_CCxNCmd(TIM_Type *tim, uint16_t channel, uint32_t ccxn_en);
void TIM_SelectOCxM(TIM_Type *tim, uint16_t channel, uint32_t mode);
void TIM_SetCompare1(TIM_Type *tim, uint32_t compare);
void TIM_SetCompare2(TIM_Type *tim, uint32_t compare);
void TIM_SetCompare3(TIM_Type *tim, uint32_t compare);
void TIM_SetCompare4(TIM_Type *tim, uint32_t compare);
void TIM_ASYMEN_Cmd(TIM_Type *tim, FunctionalState state);
void TIM_SetDownCompare1(TIM_Type *tim, uint32_t compare);
void TIM_SetDownCompare2(TIM_Type *tim, uint32_t compare);
void TIM_SetDownCompare3(TIM_Type *tim, uint32_t compare);
void TIM_SetDownCompare4(TIM_Type *tim, uint32_t compare);
void TIM_UpdateDisableConfig(TIM_Type *tim, FunctionalState state);
void TIM_UpdateRequestConfig(TIM_Type *tim, uint32_t source);
void TIM_SelectHallSensor(TIM_Type *tim, FunctionalState state);
void TIM_SelectOnePulseMode(TIM_Type *tim, uint32_t mode);
void TIM_SelectOutputTrigger(TIM_Type *tim, uint32_t source);
void TIM_SelectSlaveMode(TIM_Type *tim, uint32_t mode);
void TIM_SelectMasterSlaveMode(TIM_Type *tim, uint32_t mode);
void TIM_SetAutoreload(TIM_Type *tim, uint16_t auto_reload);
void TIM_SetCounter(TIM_Type *tim, uint32_t counter);
void TIM_SetClockDivision(TIM_Type *tim, uint32_t clock_div);
uint32_t TIM_GetCapture1(TIM_Type *tim);
uint32_t TIM_GetCapture2(TIM_Type *tim);
uint32_t TIM_GetCapture3(TIM_Type *tim);
uint32_t TIM_GetCapture4(TIM_Type *tim);
uint32_t TIM_GetCounter(TIM_Type *tim);
uint16_t TIM_GetPrescaler(TIM_Type *tim);
FlagStatus TIM_GetFlagStatus(TIM_Type *tim, uint32_t flag);
void TIM_ClearFlag(TIM_Type *tim, uint32_t flag);
ITStatus TIM_GetITStatus(TIM_Type *tim, uint32_t it);
void TIM_ClearITPendingBit(TIM_Type *tim, uint32_t it);
void TIM_PWMShiftConfig(TIM_Type *tim, uint32_t it, FunctionalState state);
void TIM_SetCCR1FALL(TIM_Type *tim, uint32_t shift);
void TIM_SetCCR2FALL(TIM_Type *tim, uint32_t shift);
void TIM_SetCCR3FALL(TIM_Type *tim, uint32_t shift);
void TIM_SetCCR4FALL(TIM_Type *tim, uint32_t shift);
FlagStatus TIM_GetCountDirection(TIM_Type *tim);
uint32_t TIM_GetTIMxClock(TIM_Type *tim);
void TIM_ETRClockMode1Config(TIM_Type *tim, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
void TIM_ETRClockMode2Config(TIM_Type* TIMx, uint16_t TIM_ExtTRGPrescaler,uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
void TIM_TIxExternalClockConfig(TIM_Type *TIMx, uint16_t TIM_TIxExternalCLKSource, uint16_t TIM_ICPolarity, uint16_t ICFilter);
void TIM_ETRConfig(TIM_Type *tim, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,286 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_uart.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#ifndef __hal_uart_H_wrM7moXg_lQUd_HTJv_sOBv_uu2tvbtzutNR__
#define __hal_uart_H_wrM7moXg_lQUd_HTJv_sOBv_uu2tvbtzutNR__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
typedef enum
{
UART_ERR_OK = 0,
UART_ERR_NULL_POINTER,
} UART_ErrTypeDef;
/**
* UART Word Length
*/
typedef enum
{
UART_WordLength_8b = (UART_CR_MODE_8D << UART_CR_MODE_Pos),
UART_WordLength_8b1P = (UART_CR_MODE_8D1P << UART_CR_MODE_Pos),
UART_WordLength_9b = (UART_CR_MODE_9D << UART_CR_MODE_Pos),
} UART_WordLengthTypeDef;
/**
* UART Stop Bits
*/
typedef enum
{
UART_StopBits_1 = (UART_CR_STOPB_1B << UART_CR_STOPB_Pos),
UART_StopBits_2 = (UART_CR_STOPB_2B << UART_CR_STOPB_Pos),
} UART_StopBitsTypeDef;
/**
* UART Parity
*/
typedef enum
{
UART_Parity_No = (UART_CR_PAR_EVEN << UART_CR_PAR_Pos),
UART_Parity_Even = (UART_CR_PAR_EVEN << UART_CR_PAR_Pos),
UART_Parity_Odd = (UART_CR_PAR_ODD << UART_CR_PAR_Pos),
} UART_ParityTypeDef;
/**
* UART Mode
*/
typedef enum
{
UART_Mode_Tx = 0,
UART_Mode_TxRx = UART_CR_RXEN_Msk,
} UART_ModeTypeDef;
typedef enum
{
/* tx type */
UART_IT_TX_FIFO_EMPTY = UART_IE_TXEE_Msk,
UART_IT_TX_FIFO_FULL = UART_IE_TXFE_Msk,
UART_IT_TX_FIFO_HEMPTY = UART_IE_TXHEE_Msk, // Half-Empty
UART_IT_TX_DONE = UART_IE_TXENDE_Msk,
/* rx type */
UART_IT_RX_FIFO_NO_EMPTY = UART_IE_RXNEE_Msk,
UART_IT_RX_FIFO_FULL = UART_IE_RXFE_Msk,
UART_IT_RX_FIFO_HFULL = UART_IE_RXHFE_Msk, // Half-Full
/* error type */
#if 1
UART_IT_ERR = (UART_IE_PERRE_Msk | UART_IE_FERRE_Msk | UART_IE_OVERRE_Msk | \
UART_IE_TONEE_Msk | UART_IE_TOIDLEE_Msk)
#else
UART_IT_ERR_PARITY = UART_IE_PERRE_Msk,
UART_IT_ERR_FRAME = UART_IE_FERRE_Msk,
UART_IT_ERR_OVERFLOW = UART_IE_OVERRE_Msk,
UART_IT_ERR_CLR_FIFO_TIMEOUT = UART_IE_TONEE_Msk,
UART_IT_ERR_IDLE_TIMEOUT = UART_IE_TOIDLEE_Msk,
#endif
} UART_ITTypeDef;
/**
* UART_Flags
*/
typedef enum
{
UART_FLAG_RXNE = UART_SR_RXNE_Msk, /*!< Read data register not empty */
UART_FLAG_TXE = UART_SR_TXE_Msk, /*!< Transmit data register Empty */
UART_FLAG_TXHE = UART_SR_TXHE_Msk, /*!< Transmit data register half Empty */
UART_FLAG_PERR = UART_SR_PERR_Msk, /*!< Parity error */
UART_FLAG_FERR = UART_SR_FERR_Msk, /*!< Framing error */
UART_FLAG_OVERR = UART_SR_OVERR_Msk, /*!< Overrun error */
UART_FLAG_TONE = UART_SR_TONE_Msk, /*!< TONE Interrupt enable */
UART_FLAG_TOIDLE = UART_SR_TOIDLE_Msk, /*!< TOIDLE interrupt enable */
UART_FLAG_RXHF = UART_SR_RXHF_Msk, /*!< Read data register half empty */
UART_FLAG_RXF = UART_SR_RXF_Msk, /*!< Read data register empty */
UART_FLAG_TXEND = UART_SR_TXEND_Msk, /*!< TXEND interrupt enable */
UART_FLAG_TXF = UART_SR_TXF_Msk, /*!< TXF interrupt enable */
} UART_FlagTypeDef;
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief Uart reset/clear reception FIFO
*
* \param [in] pHUart Pointer to a UART handle
* \return
* None
*/
__STATIC_FORCEINLINE void UART_ResetRxFIFO(UART_Type *pHUart)
{
REG_WRITE(pHUart->RXFR, 0xe930);
return;
}
/**
* \brief Uart reset/clear transmission FIFO
*
* \param [in] pHUart Pointer to a UART handle
* \return
* None
*/
__STATIC_FORCEINLINE void UART_ResetTxFIFO(UART_Type *pHUart)
{
REG_WRITE(pHUart->TXFR, 0xe930);
return;
}
/**
* \brief Start UART module
*
* \param [in] pHUart Pointer to a UART handle
* \return
* None
*/
__STATIC_FORCEINLINE void UART_Start(UART_Type *pHUart)
{
REG_SET_BITS(pHUart->CR, UART_CR_RUN_Msk);
return;
}
/**
* \brief Stop UART module
*
* \param [in] pHUart Pointer to a UART handle
* \return
*
*/
__STATIC_FORCEINLINE void UART_Stop(UART_Type *pHUart)
{
REG_CLR_BITS(pHUart->CR, UART_CR_RUN_Msk);
return;
}
/**
* \brief Wait UART module Tx FIFO empty
*
* \param [in] pHUart Pointer to a UART handle
* \return
* None
*/
__STATIC_FORCEINLINE void UART_WaitTxFifoEmpty(UART_Type *pHUart)
{
while( !REG_READ_MASK(pHUart->SR, UART_SR_TXE_Msk) );
return;
}
/**
* \brief Get the interrupt status
*
* \param [in] pHUart Pointer to a UART handle
* \param [in] flags The target interrupt types, @ref UART_ITTypeDef
* \return
* status, @ref UART_ITTypeDef
*/
__STATIC_FORCEINLINE uint32_t UART_GetITStatus(UART_Type *pHUart, uint32_t flags)
{
return REG_READ_MASK(pHUart->SR, flags);
}
/**
* \brief Get the status of UART
*
* \param [in] pHUart Pointer to a UART handle
* \param [in] flags The specifies flags to check, @ref UART_FlagTypeDef
* \return
* The new state of flags (SET or RESET)
*/
__STATIC_FORCEINLINE FlagStatus UART_GetFlagStatus(UART_Type *pHUart, UART_FlagTypeDef flags)
{
return (pHUart->SR & flags) ? SET : RESET;
}
//=============================================================================
// Structure Definition
//=============================================================================
typedef struct
{
uint32_t BaudRate;
UART_WordLengthTypeDef WordLength;
UART_StopBitsTypeDef StopBits;
UART_ParityTypeDef Parity;
UART_ModeTypeDef Mode;
} UART_InitTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Initialize UART module
*
* \param [in] pHUart Pointer to a UART handle
* \param [in] pInit Pointer to a init structure, @ref UART_InitTypeDef
* \return
* Error number, @ref UART_ErrTypeDef
*/
UART_ErrTypeDef UART_Init(UART_Type *pHUart, UART_InitTypeDef *pInit);
/**
* \brief Send data througn UART module
*
* \param [in] pHUart Pointer to a UART handle
* \param [in] value the sent data
* \return
* None
*/
void UART_SendData(UART_Type *pHUart, uint16_t value);
/**
* \brief Receive data through UART module
*
* \param [in] pHUart Pointer to a UART handle
* \return
* received data
*/
uint16_t UART_ReceiveData(UART_Type *pHUart);
/**
* \brief Configure the interrupts of UART module
*
* \param [in] pHUart Pointer to a UART handle
* \param [in] flags The target interrupt types, @ref UART_ITTypeDef
* \param [in] is_enable enable or disable interrupts (0: disable, others: enable)
* \return
* Error number, @ref UART_ErrTypeDef
*/
UART_ErrTypeDef UART_ITConfig(UART_Type *pHUart, uint32_t flags, uint32_t is_enable);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,249 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_wdg.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#ifndef __hal_wdg_H_wI4mp2FJ_l3m6_H3ua_sohm_ufSbFzwpuIAH__
#define __hal_wdg_H_wI4mp2FJ_l3m6_H3ua_sohm_ufSbFzwpuIAH__
#ifdef __cplusplus
extern "C" {
#endif
#include "hal_def.h"
//=============================================================================
// Constant Definition
//=============================================================================
/**
* The reset mode of the WatchDog
*/
typedef enum WDG_Reset
{
WDG_Reset_Disable = 0x0ul,
WDG_Reset_Enable = WDG_CR_RSTE_Msk, /*!< WatchDog trigger system reset if timeout */
} WDG_ResetTypeDef;
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief Lock/Unlonk the WatchDog accessing
*
* \return
* None
*/
__STATIC_FORCEINLINE void WDG_Lock(void)
{
REG_WRITE(WDG->LOCK, 0x930ul);
return;
}
__STATIC_FORCEINLINE void WDG_Unlock(void)
{
REG_WRITE(WDG->LOCK, 0x1ACCE551ul);
return;
}
/**
* \brief Enable/Disable the WatchDog
*
* \return
* None
*/
__STATIC_FORCEINLINE void WDG_Enable(void)
{
WDG_Unlock();
REG_SET_BITS(WDG->CR, WDG_CR_INTE_Msk);
WDG_Lock();
return;
}
__STATIC_FORCEINLINE void WDG_Disable(void)
{
WDG_Unlock();
REG_CLR_BITS(WDG->CR, WDG_CR_INTE_Msk);
WDG_Lock();
return;
}
/**
* \brief Set the counter value of the WatchDog
*
* \param [in] Counter the specific counter value (32-bits) of the WDG
* \return
* None
*/
__STATIC_FORCEINLINE void WDG_SetCounter(uint32_t Counter)
{
REG_WRITE(WDG->LOAD, Counter);
REG_WRITE(WDG->INTCLR, 0x1ul);
return;
}
/**
* \brief Get the counter value of the WatchDog
*
* \return
* the counter value of the WatchDog
*/
__STATIC_FORCEINLINE uint32_t WDG_GetCounter(void)
{
return REG_READ(WDG->VALUE);
}
/**
* \brief Enable interrupt function of the WatchDog
*
* \return
* None
*/
__STATIC_FORCEINLINE void WDG_ITEnable(void)
{
sys_open_IRQ(WDG_IRQn);
sys_enable_girq();
return;
}
/**
* \brief Disable interrupt function of the WatchDog
*
* \return
* None
*/
__STATIC_FORCEINLINE void WDG_ITDisable(void)
{
sys_close_IRQ(WDG_IRQn);
return;
}
/**
* \brief Get the timeout status of the WatchDog
*
* \return
* 0: No timeout
* other: timeout happened
*/
__STATIC_FORCEINLINE uint32_t WDG_GetStatusFlag(void)
{
return REG_READ_MASK(WDG->RIS, WDG_RIS_RIF_Msk);
}
/**
* \brief Clear the flag of interrupt of the WatchDog
*
* \return
* None
*/
__STATIC_FORCEINLINE void WDG_ClearITFlag(void)
{
if( !REG_READ_MASK(WDG->CR, WDG_CR_RSTE_Msk) )
{
WDG_Unlock();
REG_WRITE(WDG->INTCLR, 0x1ul);
WDG_Lock();
}
return;
}
/**
* \brief Extend timeout of the WatchDog
*
* \return
* None
*/
__STATIC_FORCEINLINE void WDG_Kick(void)
{
WDG_Unlock();
REG_WRITE(WDG->INTCLR, 0x1ul);
WDG_Lock();
return;
}
/**
* \brief Enable/Disable debug mode of the WatchDog
* ps. WatchDog stop to conunt when enable debug mode
*
* \param [in] is_debug_mode enable debug mode or not
* \return
* None
*/
__STATIC_FORCEINLINE void WDG_DebugMode(int is_debug_mode)
{
(is_debug_mode)
? REG_SET_BITS(WDG->CR, WDG_CR_DBGE_Msk)
: REG_CLR_BITS(WDG->CR, WDG_CR_DBGE_Msk);
return;
}
/**
* \brief Convert the mille-seconds to counter value
*
* \param [in] msec Mille-second (max: 134217727)
* \return
* the counter value
*/
__STATIC_INLINE uint32_t WDG_MSec2Counter(uint32_t msec)
{
return (((uint32_t)msec * 32ul) - 1ul);
}
//=============================================================================
// Structure Definition
//=============================================================================
typedef struct WDG_Init
{
uint32_t Counter; /*!< Specifies the WatchDog counter value */
WDG_ResetTypeDef ResetMode; /*!< Reset system or not when timeout, @ref WDG_ResetTypeDef */
} WDG_InitTypeDef;
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Fills each WDG_InitTypeDef member with its default value.
*
* \param [in] pInit Pointer to a WatchDog initial structure, @ref WDG_InitTypeDef
* \return
* None
*/
void WDG_StructInit(WDG_InitTypeDef *pInit);
/**
* \brief Initialize the WatchDog
* ps. Register-ISR MUST be after WDG_Init()
*
* \param [in] pInit Pointer to a WatchDog initial structure, @ref WDG_InitTypeDef
* \return
* None
*/
void WDG_Init(WDG_InitTypeDef *pInit);
/**
* \brief De-initialize the WatchDog
*
* \return
* None
*/
void WDG_DeInit(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,302 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_adc.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_ADC)
//=============================================================================
// Constant Definition
//=============================================================================
#define ADC_TIMEOUT_CNT (60*1000*10)
#define ADC_ALL_CHANNELS_Msk (0xFFFF)
#define ADC_MAX_WORK_CLK (16*1000*1000)
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
void ADC_DeInit(ADC_Type *pHADC)
{
__HAL_SYSCFG_RESET_ADC();
__HAL_SYSCFG_ADC_CLK_DISABLE();
return;
}
void ADC_Init(ADC_Type *pHADC, ADC_InitTypeDef *pInit)
{
/* Enable ADC Controller */
__HAL_SYSCFG_ADC_CLK_ENABLE();
__HAL_SYSCFG_RESET_ADC();
if( pInit->ClkPrescaler == ADC_ClkDiv_Auto )
{
/**
* The max working clock of ADC is 16-MHz (min 800KHz).
* Auto-Calculate the fastest ADC working clock at the current system clock
*/
uint32_t divider = 0;
divider = (g_SystemCoreClock + (ADC_MAX_WORK_CLK - 1)) / ADC_MAX_WORK_CLK;
pInit->ClkPrescaler = (divider <= 2) ? ADC_ClkDiv_2 :
(divider <= 4) ? ADC_ClkDiv_4 :
ADC_ClkDiv_8;
}
/**
* + When change ADC working clock, it should wait 20-cycles
* + Enable Analog Physical Module
* Clear_Bits(ADC_CON0_PWD_Msk | ADC_CON0_RST_Msk)
* + Enable ADC (ADC_START MUST wait 32-cycles after enable)
*/
REG_WRITE_MASK(pHADC->CON0,
ADC_CON0_CLK_Msk | ADC_CON0_PWD_Msk | ADC_CON0_RST_Msk | ADC_CON0_EN_Msk,
pInit->ClkPrescaler | ADC_CON0_EN_Msk);
sys_busy_wait(100);
REG_CLR_BITS(pHADC->CHSEL, ADC_CHSEL_DISCEN_Msk);
REG_CLR_BITS(pHADC->STAT, ADC_STAT_EOC_CHECK_DIS_Msk);
if( pInit->Mode == ADC_Mode_SingleConv )
{
/**
* CONTINUE | ENCONT | DISCEN
* 0 | 0 | 0
*/
uint32_t channel_id = (31ul - HAL_CLZ(pInit->SelChannels));
REG_WRITE_MASK(pHADC->CON0,
ADC_CON0_M_Msk | \
(ADC_CON0_CONTINUE_Msk | ADC_CON0_ENCONT_Msk) | \
ADC_CON0_ALIGN_Msk,
(channel_id << ADC_CON0_M_Pos) |
0x0ul | 0x0ul |
pInit->DataAlign);
}
else
{
int chnnl_cnt = 0;
uint32_t target_chnnls = (uint32_t)pInit->SelChannels;
while( target_chnnls )
{
int index = 31ul - HAL_CLZ(target_chnnls);
target_chnnls &= ~(0x1ul << index);
chnnl_cnt++;
}
switch( pInit->Mode )
{
default:
return;
break;
case ADC_Mode_Continuous:
/**
* Never Stop Conversion and
* NOT support interrupt (Done-Flag will always be 0)
*
* CONTINUE | ENCONT | DISCEN
* 1 | 1 | 0
*/
REG_WRITE_MASK(pHADC->CON0,
(ADC_CON0_CONTINUE_Msk | ADC_CON0_ENCONT_Msk) | \
ADC_CON0_ALIGN_Msk,
ADC_CON0_CONTINUE_Msk | ADC_CON0_ENCONT_Msk |
pInit->DataAlign);
REG_SET_BITS(pHADC->STAT, ADC_STAT_EOC_CHECK_DIS_Msk);
REG_WRITE_MASK(pHADC->CHSEL, ADC_CHSEL_CH_SEL_Msk, pInit->SelChannels);
break;
case ADC_Mode_Scan:
/**
* CONTINUE | ENCONT | DISCEN
* 1 | 0 | 0
*/
REG_WRITE_MASK(pHADC->CON0,
(ADC_CON0_CONTINUE_Msk | ADC_CON0_ENCONT_Msk) | \
ADC_CON0_ALIGN_Msk,
ADC_CON0_CONTINUE_Msk | 0x0ul |
pInit->DataAlign);
REG_WRITE_MASK(pHADC->CHSEL,
ADC_CHSEL_CH_SEL_Msk | ADC_CHSEL_DISCEN_Msk | ADC_CHSEL_CH_CNT_Msk,
pInit->SelChannels | 0x0ul | (chnnl_cnt - 1) << ADC_CHSEL_CH_CNT_Pos);
break;
case ADC_Mode_Discontinuous:
/**
* CONTINUE | ENCONT | DISCEN
* 1 | 0 | 1
*/
REG_WRITE_MASK(pHADC->CON0,
(ADC_CON0_CONTINUE_Msk | ADC_CON0_ENCONT_Msk) | \
ADC_CON0_ALIGN_Msk,
ADC_CON0_CONTINUE_Msk | 0x0ul |
pInit->DataAlign);
REG_WRITE_MASK(pHADC->CHSEL,
ADC_CHSEL_CH_SEL_Msk | ADC_CHSEL_DISCEN_Msk | \
ADC_CHSEL_CH_CNT_Msk | ADC_CHSEL_DISCNUM_Msk,
pInit->SelChannels | ADC_CHSEL_DISCEN_Msk |
(chnnl_cnt - 1) << ADC_CHSEL_CH_CNT_Pos);
break;
}
}
(pInit->IsSoftTrig == true) ?
REG_CLR_BITS(pHADC->CON0, ADC_CON0_TRIG_EN_Msk) :
REG_SET_BITS(pHADC->CON0, ADC_CON0_TRIG_EN_Msk);
return;
}
void ADC_StructInit(ADC_InitTypeDef *pInit)
{
pInit->SelChannels = ADC_Channel_AVSS;
pInit->ClkPrescaler = ADC_ClkDiv_Auto;
pInit->DataAlign = ADC_DataAlign_Right;
pInit->Mode = ADC_Mode_SingleConv;
pInit->IsSoftTrig = true;
return;
}
void ADC_ExtTrigConfig(ADC_Type *pHADC, ADC_ExtTrigSourceTypeDef ext_src, ADC_ExtTrigModeTypeDef trig_mode)
{
if( ext_src == ADC_ExtTrigSource_Soft )
{
REG_CLR_BITS(pHADC->CON0, ADC_CON0_TRIG_EN_Msk);
}
else
{
int shift = (ext_src & 0xF) << 1;
REG_SET_BITS(pHADC->CON0, ADC_CON0_TRIG_EN_Msk);
if( ext_src & 0x10 )
{
uint32_t pin_sel = 0;
/* TRIG_SEL17 rising/falling configuraion */
pin_sel = (((ext_src & 0x20ul) >> 4) | ((trig_mode >> 1) & 0x1ul)) << ADC_CHSEL_EXTRIG_SEL_Pos;
REG_WRITE_MASK(pHADC->CHSEL,
(0x3ul << shift) | ADC_CHSEL_EXTRIG_SEL_Msk,
((trig_mode & 0x1ul) << shift) | pin_sel);
}
else
{
REG_WRITE_MASK(pHADC->TRGSEL, ADC_TRGSEL_TRIG_SEL0_Msk << shift, (trig_mode & 0x1ul) << shift);
}
}
return;
}
/**
* \brief Select the sub-channel of the ADC Channel-15
*
* \param [in] subchannel The selected sub-channel of ADC channel-15, @ref ADC_SubChannelTypeDef
* \return
* None
*/
void ADC_SelSubChannel(ADC_SubChannelTypeDef subchannel)
{
AMISC_InternalSrcTypeDef src_type = AMISC_InternalSrc_NONE;
src_type = (subchannel == ADC_SubChannel_TEMP) ? AMISC_InternalSrc_TEMP :
(subchannel == ADC_SubChannel_DAC0) ? AMISC_InternalSrc_DAC0 :
(subchannel == ADC_SubChannel_DAC1) ? AMISC_InternalSrc_DAC1 :
(subchannel == ADC_SubChannel_VBuf_1_5) ? AMISC_InternalSrc_VBuf_1P5V :
(subchannel == ADC_SubChannel_VDDL) ? AMISC_InternalSrc_VDDL :
(subchannel == ADC_SubChannel_VSS) ? AMISC_InternalSrc_VSS :
(subchannel == ADC_SubChannel_VDD) ? AMISC_InternalSrc_VDD :
AMISC_InternalSrc_NONE;
AMISC_OutInternalSignalToIO(src_type, false);
REG_SET_BITS(AMISC->ADC_AIN_CR, AMISC_ADC_AIN_CR_ANA2ADC_EN_Msk);
return;
}
uint16_t ADC_GetChannelConvValue(ADC_Type *pHADC, ADC_ChannelsTypeDef channel)
{
volatile uint32_t *pData = (volatile uint32_t*)&pHADC->DAT0;
int timeout = 0;
uint32_t chnnl_id = (31ul - HAL_CLZ(channel));
while( REG_READ_MASK(pHADC->CON0, ADC_CON0_ENCONT_Msk) == 0 &&
REG_READ_MASK(pHADC->STAT, ADC_STAT_DONE_Msk) == 0 )
{
if( timeout++ > ADC_TIMEOUT_CNT )
return 0;
}
pData += (chnnl_id & 0xFul);
return (uint16_t)((*pData) & 0xFFFFul);
}
void ADC_ChannelThresholdConfig(ADC_Type *pHADC, ADC_ChannelsTypeDef channel, uint16_t threshold)
{
volatile uint32_t *pReg = (volatile uint32_t*)&pHADC->DAT0;
uint32_t chnnl_id = (31ul - HAL_CLZ(channel));
pReg += (chnnl_id & 0xFul);
REG_WRITE_MASK(*pReg, ADC_DAT0_CMPTH_Msk, (threshold << ADC_DAT0_CMPTH_Pos));
return;
}
void ADC_ITConfig(ADC_Type *pHADC, ADC_ITTypeDef it_types)
{
REG_CLR_BITS(pHADC->CHSEL, ADC_CHSEL_DISC_INTSEL_Msk);
if( it_types == ADC_IT_DISABLE )
{
sys_close_IRQ(ADC0_IRQn);
REG_CLR_BITS(pHADC->CON0, ADC_CON0_INT_EN_Msk);
}
else
{
if( it_types == ADC_IT_CONV_GROUP_SUBSET )
REG_SET_BITS(pHADC->CHSEL, ADC_CHSEL_DISC_INTSEL_Msk);
REG_WRITE_MASK(pHADC->CON0, ADC_CON0_INT_EN_Msk, it_types);
sys_open_IRQ(ADC0_IRQn);
}
return;
}
#endif /* CONFIG_ENABLE_HAL_ADC */
@@ -0,0 +1,201 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_amisc.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_AMISC)
//=============================================================================
// Constant Definition
//=============================================================================
#define AMISC_LVD_LVR_ENABLE_FLAGS (AMISC_LVD_LVR_CR_LVD_EN_Msk | AMISC_LVD_LVR_CR_LVR_EN_Msk | \
AMISC_LVD_LVR_CR_LDO_LP_EN_Msk | AMISC_LVD_LVR_CR_TEMP_EN_Msk)
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
AMISC_StatusTypeDef AMISC_Init(void)
{
/* AMISC clock enable */
__HAL_SYSCFG_AMISC_CLK_ENABLE();
AMISC_SetHSIPwrSrc(AMISC_HSIPwrSrc_LowPower);
return AMISC_Status_OK;
}
AMISC_StatusTypeDef AMISC_DeInit(uint32_t is_force)
{
if( is_force ||
(REG_READ_MASK(AMISC->DAC_CR, AMISC_DAC_CR_DAC0_EN_Msk | AMISC_DAC_CR_DAC1_EN_Msk) == 0 &&
REG_READ_MASK(AMISC->LVD_LVR_CR, AMISC_LVD_LVR_ENABLE_FLAGS) == 0 &&
REG_READ_MASK(OPAMP0->PGA_CR, OPAMP_PGA_CR_PGA_EN_Msk) == 0 &&
REG_READ_MASK(OPAMP1->PGA_CR, OPAMP_PGA_CR_PGA_EN_Msk) == 0) )
{
/* AMISC clock disable */
__HAL_SYSCFG_AMISC_CLK_DISABLE();
return AMISC_Status_OK;
}
return AMISC_Status_Bypass;
}
AMISC_StatusTypeDef AMISC_Reset(void)
{
if( REG_READ_MASK(AMISC->DAC_CR, AMISC_DAC_CR_DAC0_EN_Msk | AMISC_DAC_CR_DAC1_EN_Msk) == 0 &&
REG_READ_MASK(AMISC->LVD_LVR_CR, AMISC_LVD_LVR_ENABLE_FLAGS) == 0 &&
REG_READ_MASK(OPAMP0->PGA_CR, OPAMP_PGA_CR_PGA_EN_Msk) == 0 &&
REG_READ_MASK(OPAMP1->PGA_CR, OPAMP_PGA_CR_PGA_EN_Msk) == 0 )
{
/* AMISC reset */
__HAL_SYSCFG_RESET_AMISC();
AMISC_SetHSIPwrSrc(AMISC_HSIPwrSrc_LowPower);
return AMISC_Status_OK;
}
return AMISC_Status_Error;
}
AMISC_StatusTypeDef AMISC_LVD_LVR_Config(AMISC_LVDRInitTypeDef *pInit)
{
REG_WRITE_MASK(AMISC->LVD_LVR_CR,
AMISC_LVD_LVR_CR_LVD_SEL_Msk | AMISC_LVD_LVR_CR_LVR_SEL_Msk | \
AMISC_LVD_LVR_CR_LDO_LP_EN_Msk | AMISC_LVD_LVR_CR_TEMP_EN_Msk,
pInit->LVD_Voltage | pInit->LVR_Voltage | pInit->LVD_FuncModes);
return AMISC_Status_OK;
}
void AMISC_HSI_Disable(void)
{
if( SYSCFG_GetSysClkType() == SYSCFG_ClkSrc_LSI )
{
REG_WRITE(AMISC->HSI_CR, 0x80000000);
}
return;
}
void AMISC_HSI_Enable(void)
{
REG_WRITE(AMISC->HSI_CR, 0x01000000);
return;
}
void AMISC_LSI_Disable(void)
{
if( SYSCFG_GetSysClkType() != SYSCFG_ClkSrc_LSI )
{
REG_WRITE(AMISC->LSI_CR, 0x80000000);
}
return;
}
void AMISC_LSI_Enable(void)
{
REG_WRITE(AMISC->LSI_CR, 0x01000000);
return;
}
void AMISC_Sel_PGA_VinP_Src(AMISC_InternalSrcTypeDef src_type)
{
AMISC_InternalSrcTypeDef VinP_Src = AMISC_InternalSrc_NONE;
/* AMISC clock enable */
__HAL_SYSCFG_AMISC_CLK_ENABLE();
VinP_Src = (src_type == AMISC_InternalSrc_NONE)
? src_type : (AMISC_VBUF_CR_ANA2PGA_EN_Msk | src_type);
switch( src_type )
{
default:
break;
case AMISC_InternalSrc_NONE:
break;
case AMISC_InternalSrc_TEMP:
REG_SET_BITS(AMISC->LVD_LVR_CR, AMISC_LVD_LVR_CR_TEMP_EN_Msk);
break;
case AMISC_InternalSrc_DAC0:
AMISC_DAC0_Enable();
break;
case AMISC_InternalSrc_DAC1:
AMISC_DAC1_Enable();
break;
case AMISC_InternalSrc_VBuf_1P5V:
REG_SET_BITS(AMISC->VBUF_CR, AMISC_VBUF_CR_VBUF_EN_Msk);
break;
}
REG_WRITE_MASK(AMISC->VBUF_CR,
AMISC_VBUF_CR_ANA_SEL_Msk | AMISC_VBUF_CR_ANA2PGA_EN_Msk,
VinP_Src);
sys_busy_wait(60*1000);
return;
}
void AMISC_OutInternalSignalToIO(AMISC_InternalSrcTypeDef src_type, int has_output)
{
uint32_t value = (has_output)
? (src_type | AMISC_VBUF_CR_ANA2IO_EN_Msk) : src_type;
/* AMISC clock enable */
__HAL_SYSCFG_AMISC_CLK_ENABLE();
switch( src_type )
{
default:
break;
case AMISC_InternalSrc_NONE:
break;
case AMISC_InternalSrc_TEMP:
REG_SET_BITS(AMISC->LVD_LVR_CR, AMISC_LVD_LVR_CR_TEMP_EN_Msk);
break;
case AMISC_InternalSrc_DAC0:
AMISC_DAC0_Enable();
break;
case AMISC_InternalSrc_DAC1:
AMISC_DAC1_Enable();
break;
case AMISC_InternalSrc_VBuf_1P5V:
REG_SET_BITS(value, AMISC_VBUF_CR_VBUF_EN_Msk);
break;
}
REG_WRITE_MASK(AMISC->VBUF_CR,
AMISC_VBUF_CR_ANA_SEL_Msk | AMISC_VBUF_CR_ANA2IO_EN_Msk | AMISC_VBUF_CR_VBUF_EN_Msk,
value);
sys_busy_wait(60*1000);
return;
}
#endif /* CONFIG_ENABLE_HAL_AMISC */
@@ -0,0 +1,94 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_vcmp.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_COMP)
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
void COMP_StructInit(COMP_InitTypeDef *pInit)
{
pInit->InputPlus = COMP_VinP_IO3;
pInit->InputMinus = 0x0;
pInit->InputHysteresis = COMP_Hysteresis_Disable;
pInit->FilterFreq = COMP_Filter_Bypass;
pInit->OutputPolarity = COMP_OutPolarity_Normal;
pInit->OutputSel = COMP_Vout_None;
pInit->InitDelay = 0x3C;
return;
}
void COMP_Init(COMP_Type *pHComp, COMP_InitTypeDef *pInit)
{
if( pHComp == COMP0 )
{
__HAL_SYSCFG_RESET_COMP0();
__HAL_SYSCFG_COMP0_CLK_ENABLE();
}
else if( pHComp == COMP1 )
{
__HAL_SYSCFG_RESET_COMP1();
__HAL_SYSCFG_COMP1_CLK_ENABLE();
}
REG_WRITE_MASK(pHComp->CTRL,
COMP_CTRL_VIN_SEL_Msk | COMP_CTRL_FIL_CTRL_Msk | COMP_CTRL_POL_SEL_Msk |
COMP_CTRL_OUT_EN_Msk | COMP_CTRL_HYS_EN_Msk ,
pInit->InputMinus | pInit->FilterFreq | pInit->OutputPolarity |
pInit->OutputSel | pInit->InputHysteresis);
REG_WRITE_MASK(pHComp->VIPSEL, COMP_VIPSEL_VIP_SEL_Msk, pInit->InputPlus);
REG_WRITE_MASK(pHComp->INITCNT, COMP_INITCNT_INIT_DELAY_Msk, pInit->InitDelay);
return;
}
void COMP_DeInit(COMP_Type *pHComp)
{
if( pHComp == COMP0 )
{
__HAL_SYSCFG_RESET_COMP0();
__HAL_SYSCFG_COMP0_CLK_DISABLE();
}
else if( pHComp == COMP1 )
{
__HAL_SYSCFG_RESET_COMP1();
__HAL_SYSCFG_COMP1_CLK_DISABLE();
}
return;
}
#endif /* CONFIG_ENABLE_HAL_VCMP */
@@ -0,0 +1,123 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_crc.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_CRC)
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
void CRC_Init(void)
{
/* reset CRC module */
__HAL_SYSCFG_RESET_CRC();
/* enable clock */
__HAL_SYSCFG_CRC_CLK_ENABLE();
return;
}
uint32_t CRC_CalcCRC(uint8_t *pData, CRC_WidthTypeDef crc_width)
{
REG_WRITE(CRC->CR, crc_width);
*((uint8_t*)&CRC->DIN) = *pData;
return REG_READ_MASK(CRC->DOUT, REG_READ_MASK(CRC->CR, CRC_CR_POLYSEL_Msk) ? 0xFFFFul : 0xFFFFFFFFul);
}
uint32_t CRC_CalcBlockCRC(uint8_t *pData, int length, CRC_WidthTypeDef crc_width)
{
REG_WRITE(CRC->CR, crc_width);
if( ((uint32_t)pData & 0x3) == 0 && (length & 0x3) == 0 )
{
uint32_t *pWord = (uint32_t*)pData;
length = length >> 2;
while( length-- )
{
// Write each word to the CRC_DATA register
*((uint32_t*)&CRC->DIN) = *pWord++;
}
}
else if( ((uint32_t)pData & 0x1) == 0 && (length & 0x1) == 0 )
{
uint16_t *pHWord = (uint16_t*)pData;
volatile uint16_t *pDatIn = (volatile uint16_t*)&CRC->DIN;
length = length >> 1;
while( length-- )
{
// Write each half-word to the CRC_DATA register
*pDatIn = *pHWord++;
}
}
else
{
volatile uint8_t *pDatIn = (volatile uint8_t*)&CRC->DIN;
while( length-- )
{
// Write each byte to the CRC_DATA register
*pDatIn = *pData++;
}
}
return REG_READ_MASK(CRC->DOUT, REG_READ_MASK(CRC->CR, CRC_CR_POLYSEL_Msk) ? 0xFFFFul : 0xFFFFFFFFul);
}
uint32_t CRC_GetCRC(void)
{
return REG_READ_MASK(CRC->DOUT, REG_READ_MASK(CRC->CR, CRC_CR_POLYSEL_Msk) ? 0xFFFFul : 0xFFFFFFFFul);
}
uint32_t CRC_VerifyFlag(uint32_t Valid_CRC)
{
if( Valid_CRC & 0xFFFF0000 )
{
*((uint32_t*)&CRC->DIN) = (uint32_t)(Valid_CRC & CRC_DIN_DIN_Msk);
}
else
{
volatile uint16_t *pDatIn = (volatile uint16_t*)&CRC->DIN;
*pDatIn = (uint16_t)(Valid_CRC & CRC_DIN_DIN_Msk);
}
return REG_READ_MASK(CRC->CR, CRC_CR_VERF_Msk);
}
#endif /* CONFIG_ENABLE_HAL_CRC */
@@ -0,0 +1,73 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_device.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#include "hal_device.h"
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
static uint32_t g_seed1 = 0, g_seed2 = 0, g_seed3 = 0, g_seed4 = 0;
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
__WEAK void assert_failed(char *func, uint32_t line)
{
while (1);
}
void HAL_SRand(uint32_t seed)
{
g_seed1 = seed;
g_seed2 = seed << 2;
g_seed3 = seed << 3;
g_seed4 = seed << 4;
return;
}
uint32_t HAL_Rand(void)
{
if( g_seed1 == 0 && g_seed2 == 0 )
{
g_seed1 = ((uint16_t*)&__TIME__)[0];
g_seed2 = ((uint16_t*)&__TIME__)[1];
g_seed3 = ((uint16_t*)&__TIME__)[2];
g_seed4 = ((uint16_t*)&__TIME__)[3];
}
uint32_t b;
b = ((g_seed1 << 6) ^ g_seed1) >> 13;
g_seed1 = ((g_seed1 & 0xFFFFFFFEU) << 18) ^ b;
b = ((g_seed2 << 2) ^ g_seed2) >> 27;
g_seed2 = ((g_seed2 & 0xFFFFFFF8U) << 2) ^ b;
b = ((g_seed3 << 13) ^ g_seed3) >> 21;
g_seed3 = ((g_seed3 & 0xFFFFFFF0U) << 7) ^ b;
b = ((g_seed4 << 3) ^ g_seed4) >> 12;
g_seed4 = ((g_seed4 & 0xFFFFFF80U) << 13) ^ b;
return (g_seed1 ^ g_seed2 ^ g_seed3 ^ g_seed4);
}
@@ -0,0 +1,83 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_dsp.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_DSP)
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
#if 0
int DSP_Div32(int numerator, int denominator, int *pQuotient, int *pRemainder)
{
#if 0
/* ToDo: It need to check RSLT1/RSLT2 should be clear with CPU or not */
REG_WRITE(DSP->RSLT1, 0x0ul);
REG_WRITE(DSP->RSLT2, 0x0ul);
#endif
DSP->CR_b.MODE = DSP_CR_MODE_DIV;
REG_WRITE(DSP->SDAT1, numerator);
REG_WRITE(DSP->SDAT2, denominator);
while( !REG_READ(DSP->SR) ) {}
if( pQuotient ) *pQuotient = REG_READ(DSP->RSLT1);
if( pRemainder ) *pRemainder = REG_READ(DSP->RSLT2);
return 0;
}
#endif
uint32_t DSP_Sqrt32(DSP_SqrtParamTypeDef *pParam)
{
#if 0
/* ToDo: It need to check RSLT1/RSLT2 should be clear with CPU or not */
REG_WRITE(DSP->RSLT1, 0x0ul);
REG_WRITE(DSP->RSLT2, 0x0ul);
#endif
DSP->CR_b.MODE = DSP_CR_MODE_SQRT;
REG_WRITE(DSP->SDAT1, pParam->value32[0]);
REG_WRITE(DSP->SDAT2, pParam->value32[1]);
while( !REG_READ(DSP->SR) ) {}
return REG_READ(DSP->RSLT1);
}
#endif /* CONFIG_ENABLE_HAL_DSP */
@@ -0,0 +1,280 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_flash.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_FLASH)
//=============================================================================
// Constant Definition
//=============================================================================
#define CONFIG_FLASH_TIMEOUT 0xFFFFFFFFul
#define FLASH_PE_CLK_MAX (1ul*1000*1000)
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
static void
_FLASH_SetDivider(void)
{
uint32_t div = 0;
div = sys_get_cpu_freq() / FLASH_PE_CLK_MAX;
REG_WRITE(FLASH->DIV, div | (0x1ul << 8));
return;
}
//=============================================================================
// Public Function Definition
//=============================================================================
flash_state_t FLASH_SetLatency(flash_latency_t latency)
{
uint32_t pclk = 0;
/* ToDo: verify system clock and latency relation */
pclk = sys_get_cpu_freq();
if( pclk > 80*1000*1000 &&
latency == FLASH_LATENCY_1 )
{
return FLASH_STATE_FAIL_PARAM;
}
REG_WRITE_MASK(FLASH->CMD,
(FLASH_CMD_KEY_Msk | FLASH_CMD_NWS_Msk),
(FLASH_AUTH_KEY | latency));
return FLASH_STATE_OK;
}
flash_state_t
FLASH_ErasePage(uint32_t page_addr)
{
flash_state_t rval = FLASH_STATE_OK;
_FLASH_SetDivider();
do {
REG_WRITE(FLASH->SR, 0xFFFFFFFFul); // clean interrutp flags
// FLASH->FLIER = FLASH_FLIER_CMD_ENDE_Msk | FLASH_FLIER_CMD_ERRE_Msk;
// FLASH->FLIER = FLASH_FLIER_ADDR_ERRE_Msk;
FLASH->AR = page_addr & ~(FLASH_1_PAGE_SIZE - 1);
REG_WRITE_MASK(FLASH->CMD,
(FLASH_CMD_KEY_Msk | FLASH_CMD_START_Msk |
FLASH_CMD_UNLOCK_Msk |
FLASH_CMD_CMD_Msk),
(FLASH_AUTH_KEY | FLASH_CMD_START_Msk | \
(0x1ul << FLASH_CMD_UNLOCK_Pos) | \
(FLASH_CMD_CMD_ERASE_SECTOR << FLASH_CMD_CMD_Pos)));
while( !FLASH_IsIdle() );
} while(0);
/* lock P/E operations */
REG_WRITE_MASK(FLASH->CMD,
(FLASH_CMD_KEY_Msk | FLASH_CMD_UNLOCK_Msk),
FLASH_AUTH_KEY);
return rval;
}
flash_state_t
FLASH_ProgWord(uint32_t addr, uint32_t value)
{
flash_state_t rval = FLASH_STATE_OK;
do {
if( addr & 0x3 )
{
rval = FLASH_STATE_FAIL_ADDR;
break;
}
_FLASH_SetDivider();
REG_WRITE(FLASH->SR, 0xFFFFFFFFul); // clean interrutp flags
FLASH->AR = addr;
FLASH->DR = value;
REG_WRITE_MASK(FLASH->CMD,
(FLASH_CMD_KEY_Msk | FLASH_CMD_START_Msk |
FLASH_CMD_UNLOCK_Msk |
FLASH_CMD_CMD_Msk),
(FLASH_AUTH_KEY | FLASH_CMD_START_Msk | \
(0x1ul << FLASH_CMD_UNLOCK_Pos) | \
(FLASH_CMD_CMD_PROG << FLASH_CMD_CMD_Pos)));
while( !FLASH_IsIdle() );
} while(0);
/* lock P/E operations */
REG_WRITE_MASK(FLASH->CMD,
(FLASH_CMD_KEY_Msk | FLASH_CMD_UNLOCK_Msk),
FLASH_AUTH_KEY);
return rval;
}
flash_state_t
FLASH_ProgHWord(uint32_t addr, uint16_t value)
{
flash_state_t rval = FLASH_STATE_OK;
do {
union {
uint16_t hword[2];
uint32_t word;
} u;
if( addr & 0x1 )
{
rval = FLASH_STATE_FAIL_ADDR;
break;
}
_FLASH_SetDivider();
REG_WRITE(FLASH->SR, 0xFFFFFFFFul); // clean interrutp flags
#if 0
u.word = 0xFFFFFFFFul;
#else
u.word = *(uint32_t*)(addr & ~0x3);
#endif
u.hword[(addr & 0x2) ? 1 : 0] = value;
FLASH->AR = (addr & ~0x3);
FLASH->DR = u.word;
REG_WRITE_MASK(FLASH->CMD,
(FLASH_CMD_KEY_Msk | FLASH_CMD_START_Msk |
FLASH_CMD_UNLOCK_Msk |
FLASH_CMD_CMD_Msk),
(FLASH_AUTH_KEY | FLASH_CMD_START_Msk | \
(0x1ul << FLASH_CMD_UNLOCK_Pos) | \
(FLASH_CMD_CMD_PROG << FLASH_CMD_CMD_Pos)));
while( !FLASH_IsIdle() );
} while(0);
/* lock P/E operations */
REG_WRITE_MASK(FLASH->CMD,
(FLASH_CMD_KEY_Msk | FLASH_CMD_UNLOCK_Msk),
FLASH_AUTH_KEY);
return rval;
}
flash_state_t
FLASH_ProgByte(uint32_t addr, uint8_t value)
{
flash_state_t rval = FLASH_STATE_OK;
do {
union {
uint8_t byte[4];
uint32_t word;
} u;
_FLASH_SetDivider();
REG_WRITE(FLASH->SR, 0xFFFFFFFFul); // clean interrutp flags
#if 0
u.word = 0xFFFFFFFFul;
#else
u.word = *(uint32_t*)(addr & ~0x3);
#endif
u.byte[(addr & 0x3)] = value;
FLASH->AR = (addr & ~0x3);
FLASH->DR = u.word;
REG_WRITE_MASK(FLASH->CMD,
(FLASH_CMD_KEY_Msk | FLASH_CMD_START_Msk |
FLASH_CMD_UNLOCK_Msk |
FLASH_CMD_CMD_Msk),
(FLASH_AUTH_KEY | FLASH_CMD_START_Msk | \
(0x1ul << FLASH_CMD_UNLOCK_Pos) | \
(FLASH_CMD_CMD_PROG << FLASH_CMD_CMD_Pos)));
while( !FLASH_IsIdle() );
} while(0);
/* lock P/E operations */
REG_WRITE_MASK(FLASH->CMD,
(FLASH_CMD_KEY_Msk | FLASH_CMD_UNLOCK_Msk),
FLASH_AUTH_KEY);
return rval;
}
flash_state_t
FLASH_ProgData(uint32_t addr, uint32_t *pData, int length)
{
flash_state_t rval = FLASH_STATE_OK;
do {
if( addr & 0x3 || length & 0x3 )
{
rval = FLASH_STATE_NOT_4_ALIGN;
break;
}
_FLASH_SetDivider();
REG_WRITE(FLASH->SR, 0xFFFFFFFFul); // clean interrutp flags
FLASH->AR = addr;
do {
FLASH->DR = *pData++;
FLASH->AR = addr;
REG_WRITE_MASK(FLASH->CMD,
(FLASH_CMD_KEY_Msk |
FLASH_CMD_UNLOCK_Msk |
FLASH_CMD_CMD_Msk | FLASH_CMD_START_Msk),
(FLASH_AUTH_KEY | \
(0x1ul << FLASH_CMD_UNLOCK_Pos) | \
(FLASH_CMD_CMD_PROG << FLASH_CMD_CMD_Pos) | FLASH_CMD_START_Msk));
while( !FLASH_IsIdle() );
length -= 4;
addr += 4;
} while( length > 0 );
/* lock P/E operations */
REG_WRITE_MASK(FLASH->CMD,
(FLASH_CMD_KEY_Msk | FLASH_CMD_UNLOCK_Msk),
FLASH_AUTH_KEY);
} while(0);
return rval;
}
#endif /* CONFIG_ENABLE_HAL_FLASH */
@@ -0,0 +1,249 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_gpio.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_GPIO)
//=============================================================================
// Constant Definition
//=============================================================================
#define GPIO_PORTA_AF_PINS (GPIO_Pin_00 | GPIO_Pin_01 | GPIO_Pin_02 | GPIO_Pin_03 | \
GPIO_Pin_04 | GPIO_Pin_05 | GPIO_Pin_14 | GPIO_Pin_15)
#define GPIO_PORTB_AF_PINS (GPIO_Pin_00 | GPIO_Pin_01 | GPIO_Pin_02 | GPIO_Pin_03 | \
GPIO_Pin_04 | GPIO_Pin_05)
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
int GPIO_Init(GPIO_Type *pHGpio, GPIO_InitTypeDef *pInit)
{
int rval = 0;
if( pHGpio == GPIOA )
{
__HAL_SYSCFG_GPIOA_CLK_ENABLE();
}
else if( pHGpio == GPIOB )
{
__HAL_SYSCFG_GPIOB_CLK_ENABLE();
}
for(int i = 0; i < 16; i++)
{
uint32_t pin_cur = (0x1ul << i);
if( REG_READ_MASK(pInit->GPIO_Pin, pin_cur) == 0 )
continue;
// enable Schmitt-Trigger
REG_SET_BITS(pHGpio->CTS, pin_cur);
(pInit->GPIO_OType == GPIO_OType_OD)
? REG_SET_BITS(pHGpio->ODS, pin_cur)
: REG_SET_BITS(pHGpio->ODC, pin_cur);
switch( pInit->GPIO_Mode )
{
default:
case GPIO_Mode_IN: /* Input mode */
REG_SET_BITS(pHGpio->OEC, pin_cur);
REG_SET_BITS(pHGpio->INES, pin_cur);
if( pInit->GPIO_PuPd == GPIO_PuPd_UP )
{
REG_SET_BITS(pHGpio->PUS, pin_cur);
REG_SET_BITS(pHGpio->PDC, pin_cur);
}
else if( pInit->GPIO_PuPd == GPIO_PuPd_DOWN )
{
REG_SET_BITS(pHGpio->PDS, pin_cur);
REG_SET_BITS(pHGpio->PUC, pin_cur);
}
else
{ /* NOPULL */
REG_SET_BITS(pHGpio->PDC, pin_cur);
REG_SET_BITS(pHGpio->PUC, pin_cur);
}
GPIO_ITConfig(pHGpio, (GPIO_PinTypeDef)pin_cur, &pInit->GPIO_ITInit);
break;
case GPIO_Mode_OUT: /* Output mode */
REG_SET_BITS(pHGpio->INEC, pin_cur);
REG_SET_BITS(pHGpio->OES, pin_cur);
if( pInit->GPIO_PuPd == GPIO_PuPd_UP )
{
REG_SET_BITS(pHGpio->LAT, pin_cur);
}
else if( pInit->GPIO_PuPd == GPIO_PuPd_DOWN )
{
REG_CLR_BITS(pHGpio->LAT, pin_cur);
}
else
{
/* NOPULL, H/w not support */
}
break;
case GPIO_Mode_ANAL: /* Analog mode */
REG_SET_BITS(pHGpio->INEC, pin_cur);
// disable Schmitt-Trigger
REG_SET_BITS(pHGpio->CTC, pin_cur);
break;
case GPIO_Mode_PWR_Saving:
REG_SET_BITS(pHGpio->INEC, pin_cur);
REG_SET_BITS(pHGpio->OEC, pin_cur);
break;
case GPIO_Mode_AF: /* Alternate mode */
if( pHGpio == GPIOA && (pin_cur & GPIO_PORTA_AF_PINS) )
{
int shift = 31 - HAL_CLZ(pin_cur);
shift = (shift > 5) ? (shift - 8) : shift;
REG_WRITE_MASK(AFIO->PAAFR, (AFIO_PAAFR_PA0_Msk << 3*shift), pInit->GPIO_AF_Mode << 3*shift);
}
else if( pHGpio == GPIOB && (pin_cur & GPIO_PORTB_AF_PINS) )
{
int shift = 31 - HAL_CLZ(pin_cur);
REG_WRITE_MASK(AFIO->PBAFR, (AFIO_PBAFR_PB0_Msk << 3*shift), pInit->GPIO_AF_Mode << 3*shift);
}
else
{
// The target pin is not supported AF mode
return -1;
}
break;
}
}
return rval;
}
void GPIO_DeInit(GPIO_Type *pHGpio, uint32_t pins)
{
while( pins )
{
int shift = 31 - HAL_CLZ(pins);
uint32_t pin_cur = 0x0;
pin_cur = 0x1ul << shift;
REG_CLR_BITS(pins, pin_cur);
REG_SET_BITS(pHGpio->IEC, pin_cur); // disable interrupt
REG_SET_BITS(pHGpio->INEC, pin_cur);
REG_SET_BITS(pHGpio->OEC, pin_cur);
REG_SET_BITS(pHGpio->ODC, pin_cur);
REG_SET_BITS(pHGpio->ITC0, pin_cur);
REG_SET_BITS(pHGpio->ITC1, pin_cur);
REG_SET_BITS(pHGpio->PLC, pin_cur);
REG_SET_BITS(pHGpio->IST, pin_cur);
REG_SET_BITS(pHGpio->CTS, pin_cur);
if( pHGpio == GPIOA && (pin_cur & GPIO_PORTA_AF_PINS) )
{
shift = (shift > 5) ? (shift - 8) : shift;
REG_WRITE_MASK(AFIO->PAAFR, (AFIO_PAAFR_PA0_Msk << 3*shift), GPIO_AF_0 << 3*shift);
}
else if( pHGpio == GPIOB && (pin_cur & GPIO_PORTB_AF_PINS) )
{
REG_WRITE_MASK(AFIO->PBAFR, (AFIO_PBAFR_PB0_Msk << 3*shift), GPIO_AF_0 << 3*shift);
}
}
return;
}
void GPIO_PeriAFConfig(GPIO_Type *pHGpio, GPIO_PeriTypeDef peri_type, GPIO_PeriAFTypeDef af_mode)
{
if( peri_type < GPIO_Peri_Fn2 )
{
// Fn1_AFR case
(peri_type == GPIO_Peri_BKIN) ? REG_WRITE_MASK(AFIO->FN1_AFR, AFIO_FN1_AFR_BKIN_Msk, af_mode << AFIO_FN1_AFR_BKIN_Pos) :
(peri_type == GPIO_Peri_ECAP0) ? REG_WRITE_MASK(AFIO->FN1_AFR, AFIO_FN1_AFR_ECAP0_Msk, af_mode << AFIO_FN1_AFR_ECAP0_Pos) :
(peri_type == GPIO_Peri_ECAP1) ? REG_WRITE_MASK(AFIO->FN1_AFR, AFIO_FN1_AFR_ECAP1_Msk, af_mode << AFIO_FN1_AFR_ECAP1_Pos) :
(peri_type == GPIO_Peri_ECAP2) ? REG_WRITE_MASK(AFIO->FN1_AFR, AFIO_FN1_AFR_ECAP2_Msk, af_mode << AFIO_FN1_AFR_ECAP2_Pos) :
REG_WRITE_MASK(AFIO->FN1_AFR, AFIO_FN1_AFR_EPETR_Msk, af_mode << AFIO_FN1_AFR_EPETR_Pos);
}
else
{
// Fn2_AFR case
(peri_type == GPIO_Peri_TCAP0) ? REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_TCAP0_Msk, af_mode << AFIO_FN2_AFR_TCAP0_Pos) :
(peri_type == GPIO_Peri_TCAP1) ? REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_TCAP1_Msk, af_mode << AFIO_FN2_AFR_TCAP1_Pos) :
(peri_type == GPIO_Peri_TCAP2) ? REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_TCAP2_Msk, af_mode << AFIO_FN2_AFR_TCAP2_Pos) :
(peri_type == GPIO_Peri_I2C_PULL0) ? REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_I2C_PULL0_Msk, af_mode << AFIO_FN2_AFR_I2C_PULL0_Pos) :
(peri_type == GPIO_Peri_I2C_PULL1) ? REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_I2C_PULL1_Msk, af_mode << AFIO_FN2_AFR_I2C_PULL1_Pos) :
(peri_type == GPIO_Peri_I2C_PULL2) ? REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_I2C_PULL2_Msk, af_mode << AFIO_FN2_AFR_I2C_PULL2_Pos) :
(peri_type == GPIO_Peri_I2C_PULL3) ? REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_I2C_PULL3_Msk, af_mode << AFIO_FN2_AFR_I2C_PULL3_Pos) :
(peri_type == GPIO_Peri_I2C_PULL4) ? REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_I2C_PULL4_Msk, af_mode << AFIO_FN2_AFR_I2C_PULL4_Pos) :
(peri_type == GPIO_Peri_I2C_PULL5) ? REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_I2C_PULL5_Msk, af_mode << AFIO_FN2_AFR_I2C_PULL5_Pos) :
(peri_type == GPIO_Peri_I2C_PULL6) ? REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_I2C_PULL6_Msk, af_mode << AFIO_FN2_AFR_I2C_PULL6_Pos) :
(peri_type == GPIO_Peri_I2C_PULL7) ? REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_I2C_PULL7_Msk, af_mode << AFIO_FN2_AFR_I2C_PULL7_Pos) :
REG_WRITE_MASK(AFIO->FN2_AFR, AFIO_FN2_AFR_T2ETR_Msk, af_mode << AFIO_FN2_AFR_T2ETR_Pos);
}
return;
}
void GPIO_ITConfig(GPIO_Type *pHGpio, GPIO_PinTypeDef pins, GPIO_ITInitTypeDef *pInit)
{
// set Interrupt trigger type & polarity
if( pInit->GPIO_Trigger == GPIO_Trigger_Any_Edge )
{
REG_SET_BITS(pHGpio->ITS1, pins); // both edge
}
else if( pInit->GPIO_Trigger == GPIO_Trigger_Edge )
{
REG_SET_BITS(pHGpio->ITC1, pins);
REG_SET_BITS(pHGpio->ITS0, pins); // Edge trigger
}
else
{
REG_SET_BITS(pHGpio->ITC1, pins);
REG_SET_BITS(pHGpio->ITC0, pins); // Level trigger
}
(pInit->GPIO_Polarity == GPIO_Polarity_High_Rise) ?
REG_SET_BITS(pHGpio->PLS, pins) : // High level or rising edge
REG_SET_BITS(pHGpio->PLC, pins); // Low level or falling edge
return;
}
#endif /* CONFIG_ENABLE_HAL_GPIO */
@@ -0,0 +1,868 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_i2c.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_I2C)
//=============================================================================
// Constant Definition
//=============================================================================
#define CONFIG_I2C_TIMEOUT 20U /*!< Timeout 20 ms */
#define I2C_CLOCK_FREQ_MAX (400ul*1000)
typedef enum
{
I2C_SwState_SUCCESS = 0, /*!< Waited i2c status flag */
I2C_SwState_ERROR = 1, /*!< No i2c status flag */
I2C_SwState_WAITING = 2, /*!< Waiting i2c status flag */
I2C_SwState_HOLD_DATA = 3, /*!< I2C hold data flag */
I2C_SwState_FORCE_STOP = 4, /*!< I2C force stop flag */
I2C_SwState_RESTART = 5, /*!< I2C restart flag */
} I2C_SwState;
typedef enum
{
I2C_TxStage_START_BIT = 0,
I2C_TxStage_ADDRESS,
I2C_TxStage_DATA,
} I2C_TxStage;
#define I2C_START_BIT_H I2C_CTLSET_STA_Msk
#define I2C_START_BIT_L 0x0u
#define I2C_STOP_BIT_H I2C_CTLSET_STO_Msk
#define I2C_STOP_BIT_L 0x0u
#define I2C_ACK_BIT_H I2C_CTLSET_AA_Msk
#define I2C_ACK_BIT_L 0x0u
#define I2C_CLK_DIVIDER_60 (I2C_CTLSET_CR1_Msk | I2C_CTLSET_CR2_Msk)
#define I2C_CLK_DIVIDER_120 (I2C_CTLSET_CR0_Msk | I2C_CTLSET_CR2_Msk)
#define I2C_CLK_DIVIDER_160 (I2C_CTLSET_CR0_Msk | I2C_CTLSET_CR1_Msk)
#define I2C_CLK_DIVIDER_192 I2C_CTLSET_CR1_Msk
#define I2C_CLK_DIVIDER_244 I2C_CTLSET_CR0_Msk
#define I2C_CLK_DIVIDER_256 0x0ul
#define I2C_CLK_DIVIDER_960 I2C_CTLSET_CR2_Msk
#define I2C_CLK_DIVIDER_Msk (I2C_CTLSET_CR0_Msk | I2C_CTLSET_CR1_Msk | I2C_CTLSET_CR2_Msk)
//=============================================================================
// Macro Definition
//=============================================================================
/**
* \brief Set/Clear Ack bit
*
* \param [in] pHI2C The handle of I2C
* \return None
*/
__STATIC_FORCEINLINE void _I2C_SET_ACK_FLAG(I2C_Type *pHI2C)
{
REG_SET_BITS(pHI2C->CTLSET, I2C_CTLSET_AA_Msk);
return;
}
__STATIC_FORCEINLINE void _I2C_CLR_ACK_FLAG(I2C_Type *pHI2C)
{
REG_SET_BITS(pHI2C->CTLCLR, I2C_CTLCLR_AA_Msk);
return;
}
/**
* \brief Set/Clear Start bit
*
* \param [in] pHI2C The handle of I2C
* \return None
*/
__STATIC_FORCEINLINE void _I2C_SET_START_FLAG(I2C_Type *pHI2C)
{
REG_SET_BITS(pHI2C->CTLSET, I2C_CTLSET_STA_Msk);
return;
}
__STATIC_FORCEINLINE void _I2C_CLR_START_FLAG(I2C_Type *pHI2C)
{
REG_SET_BITS(pHI2C->CTLCLR, I2C_CTLCLR_STA_Msk);
return;
}
/**
* \brief Check Interrupt flag of an I2C
*
* \param [in] __HANDLE__ The handle of I2C
* \return
* 0 : no interrupt
* others: get interrupt
*/
#define __I2C_GET_SI_FLAG(__HANDLE__) REG_READ_MASK((__HANDLE__)->CTLSET, I2C_CTLSET_SI_Msk)
/**
* \brief Set/Clear the I2C interrupt set-flag
*
* \param [in] pHI2C The handle of I2C
* \return
* None
*/
__STATIC_FORCEINLINE void _I2C_SET_SI_FLAG(I2C_Type *pHI2C)
{
REG_SET_BITS(pHI2C->CTLSET, I2C_CTLSET_SI_Msk);
return;
}
__STATIC_FORCEINLINE void _I2C_CLR_SI_FLAG(I2C_Type *pHI2C)
{
REG_SET_BITS(pHI2C->CTLCLR, I2C_CTLCLR_SI_Msk);
return;
}
/**
* \brief Enable/Disable General Call
*
* \param [in] pHI2C The handle of I2C
* \return None
*/
__STATIC_FORCEINLINE void _I2C_GC_ENABLE(I2C_Type *pHI2C)
{
REG_SET_BITS(pHI2C->ADDR, I2C_ADDR_GC_Msk);
return;
}
__STATIC_FORCEINLINE void _I2C_GC_DISABLE(I2C_Type *pHI2C)
{
REG_CLR_BITS(pHI2C->ADDR, I2C_ADDR_GC_Msk);
return;
}
/**
* \brief Enable/Disable I2C module
*
* \param [in] pHI2C The handle of I2C
* \return
* None
*/
__STATIC_FORCEINLINE void _I2C_ENABLE(I2C_Type *pHI2C)
{
REG_SET_BITS(pHI2C->CTLSET, I2C_CTLSET_EN_Msk);
return;
}
__STATIC_FORCEINLINE void _I2C_DISABLE(I2C_Type *pHI2C)
{
REG_SET_BITS(pHI2C->CTLCLR, I2C_CTLSET_EN_Msk);
return;
}
/**
* \brief Configure the Start/Stop/ACK flag
*
* \param [in] pHI2C The handle of I2C
* \param [in] start_bit The target state of start_bit
* \param [in] stop_bit The target state of stop_bit
* \param [in] ack_bit The target state of ack_bit
* \return
* None
*/
__STATIC_FORCEINLINE void _I2C_Config(I2C_Type *pHI2C, uint32_t start_bit, uint32_t stop_bit, uint32_t ack_bit)
{
REG_WRITE_MASK(pHI2C->CTLCLR,
I2C_CTLCLR_STA_Msk | I2C_CTLCLR_STO_Msk | I2C_CTLCLR_AA_Msk,
I2C_CTLCLR_STA_Msk | I2C_CTLCLR_STO_Msk | I2C_CTLCLR_AA_Msk);
REG_WRITE_MASK(pHI2C->CTLSET,
I2C_CTLSET_STA_Msk | I2C_CTLSET_STO_Msk | I2C_CTLSET_AA_Msk,
(start_bit) | (stop_bit) | (ack_bit));
return;
}
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
static I2C_ErrTypeDef
_I2C_Wait_SI_Flag(I2C_Type *pHI2C, uint32_t timeout_ms)
{
uint32_t start_ticks = 0;
start_ticks = sys_get_tick();
while( !REG_READ_MASK(pHI2C->CTLSET, I2C_CTLSET_SI_Msk) )
{
if( (sys_get_tick() - start_ticks) > timeout_ms )
{
return I2C_Err_TimeOut;
}
}
return I2C_Err_OK;
}
static I2C_SwState
_I2C_Master_Send_Byte(I2C_Type *pHI2C, uint8_t **ppData, bool is_end)
{
__IO uint32_t *pData_reg = &pHI2C->DATA;
I2C_SwState rval = I2C_SwState_SUCCESS;
switch( REG_READ(pHI2C->STAT) )
{
default:
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_H, I2C_ACK_BIT_L);
rval = I2C_SwState_ERROR;
break;
case I2C_State_MASTER_TX_START:
case I2C_State_MASTER_TX_RESTART:
case I2C_State_MASTER_TX_SLAW_ACK:
*((__IO uint8_t*)pData_reg) = *((__IO uint8_t*)(*ppData));
*ppData = *ppData + 1;
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_L, I2C_ACK_BIT_L);
break;
case I2C_State_MASTER_TX_SLAW_NOACK:
case I2C_State_MASTER_TX_DATA_NOACK:
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_H, I2C_ACK_BIT_L);
break;
case I2C_State_MASTER_TX_DATA_ACK:
if( is_end )
{
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_H, I2C_ACK_BIT_L);
break;
}
*((__IO uint8_t*)pData_reg) = *((__IO uint8_t*)(*ppData));
*ppData = *ppData + 1;
break;
case I2C_State_MASTER_TX_LOST_BUS:
_I2C_Config(pHI2C, I2C_START_BIT_H, I2C_STOP_BIT_L, I2C_ACK_BIT_L);
break;
}
_I2C_CLR_SI_FLAG(pHI2C);
return rval;
}
static I2C_SwState
_I2C_Master_Recv_Byte(I2C_Type *pHI2C, uint8_t **ppData, uint32_t is_end)
{
__IO uint32_t *pData_reg = &pHI2C->DATA;
I2C_SwState rval = I2C_SwState_SUCCESS;
switch( REG_READ(pHI2C->STAT) )
{
default:
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_H, I2C_ACK_BIT_L);
rval = I2C_SwState_ERROR;
break;
case I2C_State_MASTER_TX_DATA_ACK:
_I2C_Config(pHI2C, I2C_START_BIT_H, I2C_STOP_BIT_L, I2C_ACK_BIT_L);
break;
case I2C_State_MASTER_RX_START:
case I2C_State_MASTER_RX_RESTART:
*((__IO uint8_t*)pData_reg) = *((__IO uint8_t*)(*ppData));
*ppData = *ppData + 1;
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_L, I2C_ACK_BIT_L);
break;
case I2C_State_MASTER_RX_SLAR_ACK:
_I2C_Config(pHI2C, I2C_START_BIT_L,
I2C_STOP_BIT_L,
(is_end)? I2C_ACK_BIT_L : I2C_ACK_BIT_H);
break;
case I2C_State_MASTER_RX_DATA_ACK:
_I2C_Config(pHI2C, I2C_START_BIT_L,
I2C_STOP_BIT_L,
(is_end) ? I2C_ACK_BIT_L : I2C_ACK_BIT_H);
*(__IO uint8_t*)(*ppData) = *((__IO uint8_t*)pData_reg);
*ppData = *ppData + 1;
break;
case I2C_State_MASTER_RX_DATA_NOACK:
*(__IO uint8_t*)(*ppData) = *((__IO uint8_t*)pData_reg);
*ppData = *ppData + 1;
case I2C_State_MASTER_RX_SLAR_NOACK:
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_H, I2C_ACK_BIT_H);
break;
case I2C_State_MASTER_RX_LOST_BUS:
_I2C_Config(pHI2C, I2C_START_BIT_H, I2C_STOP_BIT_L, I2C_ACK_BIT_H);
break;
}
_I2C_CLR_SI_FLAG(pHI2C);
return rval;
}
static I2C_SwState
_I2C_Slave_Send_Byte(I2C_Type *pHI2C, uint8_t **ppData, bool *pHasRxAddr, bool is_end)
{
__IO uint32_t *pData_reg = &pHI2C->DATA;
I2C_SwState rval = I2C_SwState_SUCCESS;
switch( REG_READ(pHI2C->STAT) )
{
default:
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_H, I2C_ACK_BIT_H);
rval = I2C_SwState_ERROR;
break;
case I2C_State_SLAVE_RX_SLAR_ACK:
*pHasRxAddr = true;
case I2C_State_SLAVE_TX_DATA_ACK:
if( is_end )
{
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_H, I2C_ACK_BIT_H);
break;
}
*((__IO uint8_t*)pData_reg) = *((__IO uint8_t*)(*ppData));
*ppData = *ppData + 1;
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_L, I2C_ACK_BIT_H);
break;
case I2C_State_SLAVE_TX_LOST_BUS:
*((__IO uint8_t*)pData_reg) = *((__IO uint8_t*)(*ppData));
*ppData = *ppData + 1;
_I2C_Config(pHI2C, I2C_START_BIT_H, I2C_STOP_BIT_L, I2C_ACK_BIT_H);
break;
case I2C_State_SLAVE_TX_DATA_NOACK:
case I2C_State_SLAVE_TX_LAST_DATA:
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_L, I2C_ACK_BIT_H);
rval = I2C_SwState_SUCCESS;
break;
case I2C_State_SLAVE_STOP_RESTART: // master force stop
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_L, I2C_ACK_BIT_H);
rval = (*pHasRxAddr) ? I2C_SwState_FORCE_STOP : I2C_SwState_RESTART;
break;
}
_I2C_CLR_SI_FLAG(pHI2C);
return rval;
}
static I2C_SwState
_I2C_Slave_Recv_Byte(I2C_Type *pHI2C, uint8_t **ppData, uint32_t is_end)
{
__IO uint32_t *pData_reg = &pHI2C->DATA;
I2C_SwState rval = I2C_SwState_SUCCESS;
switch( REG_READ(pHI2C->STAT) )
{
default:
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_H, I2C_ACK_BIT_H);
rval = I2C_SwState_ERROR;
break;
case I2C_State_SLAVE_RX_SLAW_LOST_BUS:
case I2C_State_SLAVE_RX_BADDR_LOST_BUS:
_I2C_Config(pHI2C, I2C_START_BIT_H, I2C_STOP_BIT_L, I2C_ACK_BIT_H);
break;
case I2C_State_SLAVE_RX_SLAW_ACK:
case I2C_State_SLAVE_RX_BDATA_NOACK:
case I2C_State_SLAVE_RX_BROAD_ACK:
_I2C_Config(pHI2C, I2C_START_BIT_L,
I2C_STOP_BIT_L,
(is_end) ? I2C_ACK_BIT_L : I2C_ACK_BIT_H);
rval = I2C_SwState_HOLD_DATA;
break;
case I2C_State_SLAVE_RX_DATA_ACK:
*(__IO uint8_t*)(*ppData) = *((__IO uint8_t*)pData_reg);
*ppData = *ppData + 1;
_I2C_Config(pHI2C, I2C_START_BIT_L,
I2C_STOP_BIT_L,
(is_end) ? I2C_ACK_BIT_L : I2C_ACK_BIT_H);
break;
case I2C_State_SLAVE_RX_DATA_NOACK:
*(__IO uint8_t*)(*ppData) = *((__IO uint8_t*)pData_reg);
*ppData = *ppData + 1;
_I2C_Config(pHI2C, I2C_START_BIT_L,
(is_end) ? I2C_STOP_BIT_H : I2C_STOP_BIT_L,
I2C_ACK_BIT_H);
break;
case I2C_State_SLAVE_RX_BDATA_ACK:
*(__IO uint8_t*)(*ppData) = *((__IO uint8_t*)pData_reg);
*ppData = *ppData + 1;
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_L, I2C_ACK_BIT_H);
break;
case I2C_State_SLAVE_STOP_RESTART: // master force stop
_I2C_Config(pHI2C, I2C_START_BIT_L, I2C_STOP_BIT_L, I2C_ACK_BIT_H);
rval = I2C_SwState_FORCE_STOP;
break;
}
_I2C_CLR_SI_FLAG(pHI2C);
return rval;
}
//=============================================================================
// Public Function Definition
//=============================================================================
void I2C_StructInit(I2C_InitTypeDef *pInit)
{
int divider = 0;
pInit->Mode = I2C_Mode_MASTER;
pInit->OwnAddress = 0x0;
pInit->BroadAck = I2C_BroadAck_Disable;
divider = (g_SystemCoreClock / I2C_CLOCK_FREQ_MAX);
pInit->ClockDiv = (divider <= I2C_CLK_Div60) ? I2C_CLK_Div60 :
(divider <= I2C_CLK_Div120) ? I2C_CLK_Div120 :
(divider <= I2C_CLK_Div160) ? I2C_CLK_Div160 :
(divider <= I2C_CLK_Div192) ? I2C_CLK_Div192 :
(divider <= I2C_CLK_Div244) ? I2C_CLK_Div244 :
(divider <= I2C_CLK_Div256) ? I2C_CLK_Div256 :
I2C_CLK_Div960;
return;
}
void I2C_DeInit(I2C_Type *pHI2C)
{
if( (int)pHI2C == (int)I2C0 )
sys_close_IRQ(I2C0_IRQn);
_I2C_DISABLE(pHI2C);
__HAL_SYSCFG_RESET_I2C();
__HAL_SYSCFG_I2C_CLK_DISABLE();
return;
}
I2C_ErrTypeDef I2C_Init(I2C_Type *pHI2C, I2C_InitTypeDef *pInit)
{
__HAL_SYSCFG_I2C_CLK_ENABLE();
__HAL_SYSCFG_RESET_I2C();
if( pInit->Mode == I2C_Mode_MASTER )
{
uint32_t divider = 0ul;
#if 0
/**
* I2C clock freq should less than I2C_CLOCK_FREQ_MAX
*/
if( (g_SystemCoreClock / pInit->ClockDiv) > I2C_CLOCK_FREQ_MAX )
return I2C_Err_WrongParams;
#endif
divider = (pInit->ClockDiv == I2C_CLK_Div960) ? I2C_CLK_DIVIDER_960 :
(pInit->ClockDiv == I2C_CLK_Div256) ? I2C_CLK_DIVIDER_256 :
(pInit->ClockDiv == I2C_CLK_Div244) ? I2C_CLK_DIVIDER_244 :
(pInit->ClockDiv == I2C_CLK_Div192) ? I2C_CLK_DIVIDER_192 :
(pInit->ClockDiv == I2C_CLK_Div160) ? I2C_CLK_DIVIDER_160 :
(pInit->ClockDiv == I2C_CLK_Div120) ? I2C_CLK_DIVIDER_120 :
I2C_CLK_DIVIDER_60;
/* Set divider */
REG_WRITE_MASK(pHI2C->CTLSET, I2C_CLK_DIVIDER_Msk, divider);
/* clear ack flag */
_I2C_CLR_ACK_FLAG(pHI2C);
}
else if( pInit->Mode == I2C_Mode_SLAVE )
{
/* Configure Slave Address */
REG_WRITE_MASK(pHI2C->ADDR,
I2C_ADDR_ADDR_Msk | I2C_ADDR_GC_Msk,
(pInit->OwnAddress << I2C_ADDR_ADDR_Pos) | pInit->BroadAck);
REG_WRITE_MASK(pHI2C->CTLSET, I2C_CLK_DIVIDER_Msk, pInit->ClockDiv);
_I2C_SET_ACK_FLAG(pHI2C);
}
else
return I2C_Err_WrongParams;
_I2C_ENABLE(pHI2C);
_I2C_CLR_SI_FLAG(pHI2C);
return I2C_Err_OK;
}
I2C_ErrTypeDef I2C_Master_Transmit(I2C_Type *pHI2C, uint16_t DevAddr, uint8_t *pData, uint16_t Size)
{
I2C_SwState rval = I2C_SwState_SUCCESS;
I2C_TxStage stage = I2C_TxStage_START_BIT;
uint16_t tx_nbytes = 0;
if( (int)pHI2C == (int)I2C0 )
sys_close_IRQ(I2C0_IRQn);
_I2C_SET_START_FLAG(pHI2C);
stage = I2C_TxStage_ADDRESS;
while( tx_nbytes < Size )
{
if( _I2C_Wait_SI_Flag(pHI2C, CONFIG_I2C_TIMEOUT) != I2C_Err_OK )
break;
if( stage == I2C_TxStage_ADDRESS )
{
uint8_t addr = (uint8_t)DevAddr & ~0x1u; // write mode
uint8_t *pAddr = 0;
pAddr = &addr;
rval = _I2C_Master_Send_Byte(pHI2C, &pAddr, false);
if( rval == I2C_SwState_ERROR )
break;
stage = I2C_TxStage_DATA;
continue;
}
else
{
rval = _I2C_Master_Send_Byte(pHI2C, &pData, false);
if( rval == I2C_SwState_ERROR )
break;
}
tx_nbytes = (rval == I2C_SwState_SUCCESS) ? tx_nbytes + 1 : tx_nbytes;
}
if( rval == I2C_SwState_SUCCESS )
{
// send STOP-bit
_I2C_Wait_SI_Flag(pHI2C, CONFIG_I2C_TIMEOUT);
_I2C_Master_Send_Byte(pHI2C, &pData, true);
}
return (rval == I2C_SwState_SUCCESS) ? I2C_Err_OK : I2C_Err_Fail;
}
I2C_ErrTypeDef I2C_Master_Receive(I2C_Type *pHI2C, uint8_t DevAddr, uint8_t *pData, uint16_t *pSize, uint16_t Timeout_ms)
{
I2C_SwState rval = I2C_SwState_SUCCESS;
I2C_TxStage stage = I2C_TxStage_START_BIT;
uint16_t buf_size = *pSize;
int rx_nbytes = 0;
if( (int)pHI2C == (int)I2C0 )
sys_close_IRQ(I2C0_IRQn);
_I2C_SET_START_FLAG(pHI2C);
stage = I2C_TxStage_ADDRESS;
if( pSize ) *pSize = 0;
while( rx_nbytes < buf_size )
{
if( _I2C_Wait_SI_Flag(pHI2C, Timeout_ms) != I2C_Err_OK )
{
if( Timeout_ms == I2C_BLOCKING )
continue;
return I2C_Err_TimeOut;
}
if( stage == I2C_TxStage_ADDRESS )
{
uint8_t addr = (uint8_t)DevAddr | 0x1u; // read mode
uint8_t *pAddr = 0;
pAddr = &addr;
rval = _I2C_Master_Recv_Byte(pHI2C, &pAddr, (buf_size == 1));
if( rval == I2C_SwState_ERROR )
break;
/**
* send DevAddr+R and then receive data
* ps. Decrease the DevAddr+R byte
*/
rx_nbytes = -1;
stage = I2C_TxStage_DATA;
continue;
}
else
{
rval = _I2C_Master_Recv_Byte(pHI2C, &pData, ((rx_nbytes + 1) == (buf_size-1)));
if( rval == I2C_SwState_ERROR )
break;
}
rx_nbytes = (rval == I2C_SwState_SUCCESS) ? rx_nbytes + 1 : rx_nbytes;
}
if( pSize ) *pSize = rx_nbytes;
return (rval == I2C_SwState_SUCCESS) ? I2C_Err_OK : I2C_Err_Fail;
}
I2C_ErrTypeDef I2C_Slave_Transmit(I2C_Type *pHI2C, uint8_t *pData, uint16_t Size, uint16_t Timeout_ms)
{
__IO uint16_t tx_nbytes = 0;
I2C_SwState rval = I2C_SwState_SUCCESS;
bool HasRecvAddr = false;
if( (int)pHI2C == (int)I2C0 )
sys_close_IRQ(I2C0_IRQn);
while( tx_nbytes < Size )
{
if( _I2C_Wait_SI_Flag(pHI2C, Timeout_ms) != I2C_Err_OK )
{
if( Timeout_ms == I2C_BLOCKING )
continue;
return I2C_Err_TimeOut;
}
rval = _I2C_Slave_Send_Byte(pHI2C, &pData, &HasRecvAddr, false);
if( rval == I2C_SwState_ERROR || rval == I2C_SwState_FORCE_STOP )
{
break;
}
tx_nbytes = (rval == I2C_SwState_SUCCESS) ? tx_nbytes + 1 : tx_nbytes;
}
if( rval == I2C_SwState_SUCCESS )
{
// send STOP-bit
_I2C_Wait_SI_Flag(pHI2C, CONFIG_I2C_TIMEOUT);
_I2C_Slave_Send_Byte(pHI2C, &pData, &HasRecvAddr, true);
}
return (rval == I2C_SwState_SUCCESS) ? I2C_Err_OK : I2C_Err_Fail;
}
I2C_ErrTypeDef I2C_Slave_Receive(I2C_Type *pHI2C, uint8_t *pData, uint16_t *pSize, uint16_t Timeout_ms)
{
uint16_t rx_nbytes = 0;
uint16_t buf_size = *pSize;
I2C_SwState rval = I2C_SwState_SUCCESS;
if( (int)pHI2C == (int)I2C0 )
sys_close_IRQ(I2C0_IRQn);
if( pSize ) *pSize = 0;
while( rx_nbytes < buf_size )
{
if( _I2C_Wait_SI_Flag(pHI2C, Timeout_ms) != I2C_Err_OK )
{
if( Timeout_ms == I2C_BLOCKING )
continue;
return I2C_Err_TimeOut;
}
rval = _I2C_Slave_Recv_Byte(pHI2C, &pData, ((rx_nbytes + 1) == buf_size));
if( rval == I2C_SwState_ERROR || rval == I2C_SwState_FORCE_STOP )
{
break;
}
rx_nbytes = (rval == I2C_SwState_SUCCESS) ? rx_nbytes + 1 : rx_nbytes;
}
if( pSize ) *pSize = rx_nbytes;
return (rval == I2C_SwState_SUCCESS) ? I2C_Err_OK : I2C_Err_Fail;
}
I2C_ErrTypeDef I2C_Master_Transmit_IT(I2C_IT_HandleTypeDef *pHITI2C, uint16_t DevAddr, uint8_t *pData, uint16_t Size)
{
pHITI2C->XferMode = I2C_XferMode_Transmite;
pHITI2C->DevAddress = (uint8_t)DevAddr;
pHITI2C->pTxBuffPtr = pData;
pHITI2C->TxXferCount = Size;
if( (int)pHITI2C->pHI2C == (int)I2C0 )
sys_open_IRQ(I2C0_IRQn);
REG_WRITE_MASK(pHITI2C->pHI2C->CTLSET,
I2C_CTLSET_STA_Msk | I2C_CTLSET_SI_Msk,
I2C_CTLSET_STA_Msk | I2C_CTLSET_SI_Msk);
return I2C_Err_OK;
}
I2C_ErrTypeDef I2C_Master_Receive_IT(I2C_IT_HandleTypeDef *pHITI2C, uint8_t DevAddr, uint8_t *pData, uint16_t Size)
{
pHITI2C->XferMode = I2C_XferMode_Recevie;
pHITI2C->DevAddress = (uint8_t)DevAddr;
pHITI2C->pRxBuffPtr = pData;
pHITI2C->RxXferCount = Size;
if( (int)pHITI2C->pHI2C == (int)I2C0 )
sys_open_IRQ(I2C0_IRQn);
REG_WRITE_MASK(pHITI2C->pHI2C->CTLSET,
I2C_CTLSET_STA_Msk | I2C_CTLSET_SI_Msk,
I2C_CTLSET_STA_Msk | I2C_CTLSET_SI_Msk);
return I2C_Err_OK;
}
I2C_ErrTypeDef I2C_Slave_Transmit_IT(I2C_IT_HandleTypeDef *pHITI2C, uint8_t *pData, uint16_t Size)
{
pHITI2C->XferMode = I2C_XferMode_Transmite;
pHITI2C->pTxBuffPtr = pData;
pHITI2C->TxXferCount = Size;
_I2C_SET_SI_FLAG(pHITI2C->pHI2C);
if( (int)pHITI2C->pHI2C == (int)I2C0 )
sys_open_IRQ(I2C0_IRQn);
return I2C_Err_OK;
}
I2C_ErrTypeDef I2C_Slave_Receive_IT(I2C_IT_HandleTypeDef *pHITI2C, uint8_t *pData, uint16_t Size)
{
pHITI2C->XferMode = I2C_XferMode_Recevie;
pHITI2C->pRxBuffPtr = pData;
pHITI2C->RxXferCount = Size;
_I2C_SET_SI_FLAG(pHITI2C->pHI2C);
if( (int)pHITI2C->pHI2C == (int)I2C0 )
sys_open_IRQ(I2C0_IRQn);
return I2C_Err_OK;
}
void I2C_Master_IRQHandler(I2C_IT_HandleTypeDef *pHITI2C)
{
I2C_SwState rval = I2C_SwState_SUCCESS;
if( pHITI2C->XferMode == I2C_XferMode_Transmite )
{
if( pHITI2C->DevAddress & 0x8000 )
{
// xfer data stage, if pHITI2C->TxXferCount == 0, I2C should send STOP-bit
rval = _I2C_Master_Send_Byte(pHITI2C->pHI2C, &pHITI2C->pTxBuffPtr, (pHITI2C->TxXferCount) ? false : true);
if( rval == I2C_SwState_SUCCESS )
pHITI2C->TxXferCount--;
if( pHITI2C->TxXferCount == 0xFFFF )
{
pHITI2C->XferMode = I2C_XferMode_Idle;
}
}
else
{
uint8_t *pAddr = 0;
pHITI2C->DevAddress &= ~0x1u; // write mode
pAddr = (uint8_t*)&pHITI2C->DevAddress;
rval = _I2C_Master_Send_Byte(pHITI2C->pHI2C, &pAddr, false);
if( rval == I2C_SwState_SUCCESS )
pHITI2C->DevAddress |= 0x8000;
}
}
else if( pHITI2C->XferMode == I2C_XferMode_Recevie )
{
if( pHITI2C->DevAddress & 0x8000 )
{
rval = _I2C_Master_Recv_Byte(pHITI2C->pHI2C, &pHITI2C->pRxBuffPtr, (pHITI2C->RxXferCount - 2) ? false : true);
if( rval == I2C_SwState_SUCCESS )
pHITI2C->RxXferCount--;
if( pHITI2C->RxXferCount == 0 )
{
pHITI2C->XferMode = I2C_XferMode_Idle;
}
}
else
{
uint8_t *pAddr = 0;
pHITI2C->DevAddress |= 0x1u; // read mode
pAddr = (uint8_t*)&pHITI2C->DevAddress;
rval = _I2C_Master_Recv_Byte(pHITI2C->pHI2C, &pAddr, false);
if( rval == I2C_SwState_SUCCESS )
{
pHITI2C->DevAddress |= 0x8000;
/**
* send DevAddr+R and then receive data
* ps. Decrease the DevAddr+R byte
*/
pHITI2C->RxXferCount++;
}
}
}
return;
}
void I2C_Slave_IRQHandler(I2C_IT_HandleTypeDef *pHITI2C)
{
I2C_SwState rval = I2C_SwState_SUCCESS;
if( pHITI2C->XferMode == I2C_XferMode_Transmite )
{
bool HasRecvAddr = false;
// xfer data stage, if pHITI2C->TxXferCount == 0, I2C should send STOP-bit
rval = _I2C_Slave_Send_Byte(pHITI2C->pHI2C, &pHITI2C->pTxBuffPtr, &HasRecvAddr, (pHITI2C->TxXferCount) ? false : true);
pHITI2C->TxXferCount = (rval == I2C_SwState_SUCCESS) ? pHITI2C->TxXferCount - 1 :
(rval == I2C_SwState_FORCE_STOP) ? 0xFFFF :
pHITI2C->TxXferCount;
if( pHITI2C->TxXferCount == 0xFFFF )
{
pHITI2C->XferMode = I2C_XferMode_Idle;
}
}
else if( pHITI2C->XferMode == I2C_XferMode_Recevie )
{
rval = _I2C_Slave_Recv_Byte(pHITI2C->pHI2C, &pHITI2C->pRxBuffPtr, (pHITI2C->RxXferCount == 2));
pHITI2C->RxXferCount = (rval == I2C_SwState_SUCCESS) ? pHITI2C->RxXferCount - 1 :
(rval == I2C_SwState_FORCE_STOP) ? 0 :
pHITI2C->RxXferCount;
if( pHITI2C->RxXferCount == 0 )
{
pHITI2C->XferMode = I2C_XferMode_Idle;
}
}
return;
}
#endif /* CONFIG_ENABLE_HAL_I2C */
@@ -0,0 +1,145 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_lptim.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_LPTIM) || defined(CONFIG_ENABLE_HAL_TIM0) || defined(CONFIG_ENABLE_HAL_TIM1)
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
void LPTIM_StructInit(LPTIM_InitTypeDef *pInit)
{
pInit->LPTIM_Prescaler = 0;
pInit->LPTIM_ClockSource = LPTIM_CLK_Src_SysClk;
pInit->LPTIM_MatchMode = LPTIM_MatchMode_Normal;
pInit->LPTIM_MatchValue = 0;
return;
}
void LPTIM_Init(LPTIM_Type *pHLpTim, LPTIM_InitTypeDef *pInit)
{
if( pHLpTim == LPTIM )
{
sys_close_IRQ(LPTIM_IRQn);
__HAL_SYSCFG_RESET_LPTIM();
__HAL_SYSCFG_LPTIM_CLK_ENABLE();
REG_WRITE_MASK(pHLpTim->TCR, LPTIM_TCR_CLKS_Msk, pInit->LPTIM_ClockSource);
}
else if( pHLpTim == TIM0 )
{
sys_close_IRQ(TIM0_IRQn);
__HAL_SYSCFG_RESET_TIM0();
__HAL_SYSCFG_TIM0_CLK_ENABLE();
}
else if( pHLpTim == TIM1 )
{
sys_close_IRQ(TIM1_IRQn);
__HAL_SYSCFG_RESET_TIM1();
__HAL_SYSCFG_TIM1_CLK_ENABLE();
}
REG_SET_BITS(pHLpTim->IR, LPTIM_IR_MR0_Msk);
REG_SET_BITS(pHLpTim->TCR, LPTIM_TCR_CRST_Msk);
pHLpTim->PR = pInit->LPTIM_Prescaler;
pHLpTim->MCR = pInit->LPTIM_MatchMode;
pHLpTim->MR0 = pInit->LPTIM_MatchValue;
return;
}
void LPTIM_DeInit(LPTIM_Type *pHLpTim)
{
REG_SET_BITS(pHLpTim->TCR, LPTIM_TCR_CRST_Msk);
if( pHLpTim == LPTIM )
{
__HAL_SYSCFG_LPTIM_CLK_DISABLE();
__HAL_SYSCFG_RESET_LPTIM();
sys_close_IRQ(LPTIM_IRQn);
}
else if( pHLpTim == TIM0 )
{
__HAL_SYSCFG_TIM1_CLK_DISABLE();
__HAL_SYSCFG_RESET_TIM0();
sys_close_IRQ(TIM0_IRQn);
}
else if( pHLpTim == TIM1 )
{
__HAL_SYSCFG_TIM1_CLK_DISABLE();
__HAL_SYSCFG_RESET_TIM1();
sys_close_IRQ(TIM1_IRQn);
}
return;
}
void LPTIM_ITConfig(LPTIM_Type *pHLpTim, int has_enable)
{
if( pHLpTim == LPTIM )
{
(has_enable)
? sys_open_IRQ(LPTIM_IRQn)
: sys_close_IRQ(LPTIM_IRQn);
}
else if( pHLpTim == TIM0 )
{
(has_enable)
? sys_open_IRQ(TIM0_IRQn)
: sys_close_IRQ(TIM0_IRQn);
}
else if( pHLpTim == TIM1 )
{
(has_enable)
? sys_open_IRQ(TIM1_IRQn)
: sys_close_IRQ(TIM1_IRQn);
}
return;
}
#endif /* CONFIG_ENABLE_HAL_LPTIM || CONFIG_ENABLE_HAL_TIM0 || CONFIG_ENABLE_HAL_TIM1 */
@@ -0,0 +1,74 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_opamp.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/12/05
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_OPAMP)
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
int OPAMP_Init(OPAMP_Type *pHOPAmp, OPAMP_InitTypeDef *pInit)
{
AMISC_Init();
REG_WRITE_MASK(pHOPAmp->PGA_CR,
OPAMP_PGA_CR_PGA_VIP_SEL_Msk | OPAMP_PGA_CR_PGA_VIN_SEL_Msk | \
OPAMP_PGA_CR_PGA_IO_EN_Msk | OPAMP_PGA_CR_PGA_GAIN_Msk,
pInit->OPAMP_VinP | pInit->OPAMP_VinM | pInit->OPAMP_Vout | pInit->OPAMP_Gain);
return 0;
}
void OPAMP_DeInit(OPAMP_Type *pHOPAmp)
{
OPAMP_Disable(pHOPAmp);
REG_WRITE_MASK(pHOPAmp->PGA_CR,
OPAMP_PGA_CR_PGA_VIP_SEL_Msk | OPAMP_PGA_CR_PGA_VIN_SEL_Msk | \
OPAMP_PGA_CR_PGA_IO_EN_Msk | OPAMP_PGA_CR_PGA_GAIN_Msk,
OPAMP_VinP_Internal | OPAMP_VinM_GND | OPAMP_Vout_None | OPAMP_PGAGain_1);
AMISC_DeInit(false);
return;
}
void OPAMP_StructInit(OPAMP_InitTypeDef *pInit)
{
pInit->OPAMP_VinP = OPAMP_VinP_Internal;
pInit->OPAMP_VinM = OPAMP_VinM_GND;
pInit->OPAMP_Vout = OPAMP_Vout_None;
pInit->OPAMP_Gain = OPAMP_PGAGain_1;
return;
}
#endif /* CONFIG_ENABLE_HAL_OPAMP */
@@ -0,0 +1,115 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_pwr.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_PWR)
//=============================================================================
// Constant Definition
//=============================================================================
#if 1
#define __PWR_WAIT_RECHARGE() do{ __NOP(); __NOP(); __NOP(); __NOP(); \
}while(0)
#else
#define __PWR_WAIT_RECHARGE()
#endif
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
void PWR_EnterSleepMode(CallbaskPreSleepTypeDef cb_pre_set,
CallbaskPostSleepTypeDef cb_post_set)
{
int wakeup_type = 0;
sys_disable_girq();
if( cb_pre_set )
cb_pre_set(PWR_Mode_Sleep, (PWR_WakeupTypeDef*)&wakeup_type);
__HAL_SYSCFG_AMISC_CLK_ENABLE();
AMISC_SetHSIPwrSrc(AMISC_HSIPwrSrc_LowPower);
REG_WRITE(AMISC->DAC_CR, 0x0ul); // Off DAC leakage
__set_wfi_sleepmode(WFI_SHALLOW_SLEEP);
__WFI();
/* __PWR_WAIT_RECHARGE(); */
if( cb_post_set )
cb_post_set(PWR_Mode_Sleep);
sys_enable_girq();
return;
}
void PWR_EnterDeepSleepMode(CallbaskPreSleepTypeDef cb_pre_set,
CallbaskPostSleepTypeDef cb_post_set)
{
int wakeup_type = 0;
sys_disable_girq();
if( cb_pre_set )
cb_pre_set(PWR_Mode_DeepSleep, (PWR_WakeupTypeDef*)&wakeup_type);
__HAL_SYSCFG_AMISC_CLK_ENABLE();
AMISC_SetHSIPwrSrc(AMISC_HSIPwrSrc_LowPower);
REG_WRITE(AMISC->DAC_CR, 0x0ul); // Off DAC leakage
SYSCFG_SetLowPower(true);
/* Judge wakeup trigger */
(wakeup_type & PWR_Wakeup_LpTIM) ? sys_open_IRQ(LPTIM_IRQn) : sys_close_IRQ(LPTIM_IRQn);
(wakeup_type & PWR_Wakeup_WDG) ? sys_open_IRQ(WDG_IRQn) : sys_close_IRQ(WDG_IRQn);
(wakeup_type & PWR_Wakeup_IO_PORT_A) ? sys_open_IRQ(GPIOA_IRQn) : sys_close_IRQ(GPIOA_IRQn);
(wakeup_type & PWR_Wakeup_IO_PORT_B) ? sys_open_IRQ(GPIOB_IRQn) : sys_close_IRQ(GPIOB_IRQn);
__set_wfi_sleepmode(WFI_DEEP_SLEEP);
__WFI();
__PWR_WAIT_RECHARGE();
SYSCFG_SetLowPower(false);
if( cb_post_set )
cb_post_set(PWR_Mode_DeepSleep);
sys_enable_girq();
return;
}
#endif /* CONFIG_ENABLE_HAL_PMU */
@@ -0,0 +1,381 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_spi.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_SPI)
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* @brief Deinitializes the spi peripheral registers to their
* default reset values.
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @retval None.
*/
void SPI_DeInit(SPI_Type *spi)
{
if (spi == SPI0)
{
__HAL_SYSCFG_RESET_SPI();
}
}
/**
* @brief Fills each init_struct member with its default value.
* @param init_struct: pointer to a SPI_InitTypeDef structure
* which will be initialized.
* @retval None.
*/
void SPI_StructInit(SPI_InitTypeDef *init_struct)
{
init_struct->SPI_Mode = SPI_Mode_Master;
init_struct->SPI_CPOL = SPI_CPOL_Low;
init_struct->SPI_CPHA = SPI_CPHA_Effective;
init_struct->SPI_TxDataSize = SPI_TxDataSize_8b;
init_struct->SPI_BaudRatePrescaler = SPI_BaudratePrescaler_256;
init_struct->SPI_FirstBit = SPI_FirstBit_MSB;
}
/**
* @brief Initializes the spi peripheral according to the specified
* parameters in the init_struct .
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param init_struct: pointer to a SPI_InitTypeDef structure
* that contains the configuration information for the
* specified SPI peripheral.
* @retval None.
*/
void SPI_Init(SPI_Type *spi, SPI_InitTypeDef *init_struct)
{
__HAL_SYSCFG_SPI_CLK_ENABLE();
REG_WRITE_MASK(spi->CFG, SPI_CFG_MODE_Msk, (init_struct->SPI_Mode << SPI_CFG_MODE_Pos));
REG_WRITE_MASK(spi->CFG, SPI_CFG_CPOL_Msk, (init_struct->SPI_CPOL << SPI_CFG_CPOL_Pos));
REG_WRITE_MASK(spi->CFG, SPI_CFG_CPHA_Msk, (init_struct->SPI_CPHA << SPI_CFG_CPHA_Pos));
REG_WRITE_MASK(spi->CFG, SPI_CFG_TXWDSZ_Msk, (init_struct->SPI_TxDataSize << SPI_CFG_TXWDSZ_Pos));
REG_WRITE_MASK(spi->CFG, SPI_CFG_DB_Msk, (init_struct->SPI_BaudRatePrescaler << SPI_CFG_DB_Pos));
REG_WRITE_MASK(spi->CFG, SPI_CFG_LSB_Msk, (init_struct->SPI_FirstBit << SPI_CFG_LSB_Pos));
}
/**
* @brief Enables or disables the specified SPI peripheral.
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param state: new state of the spi peripheral.
* This parameter can be: ENABLE or DISABLE.
* @retval None.
*/
void SPI_Enable(SPI_Type *spi)
{
REG_SET_BITS(spi->EN, SPI_EN_EN_Msk);
}
void SPI_Disable(SPI_Type *spi)
{
REG_CLR_BITS(spi->EN, SPI_EN_EN_Msk);
}
void SPI_MasterEnable(SPI_Type *spi)
{
REG_SET_BITS(spi->CFG, SPI_CFG_MODE_Msk);
}
void SPI_SlaveEnable(SPI_Type *spi)
{
REG_CLR_BITS(spi->CFG, SPI_CFG_MODE_Msk);
}
/**
* @brief Transmits a Data through the spi peripheral.
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param data : Data to be transmitted.
* @retval None.
*/
void SPI_SendData(SPI_Type *spi, uint32_t data)
{
spi->TX = data;
}
/**
* @brief Returns the most recent received data by the spi peripheral.
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @retval The value of the received data.
*/
uint32_t SPI_ReceiveData(SPI_Type *spi)
{
return (spi->RX);
}
/**
* @brief Set the clock divide
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param baudrate: the clcok divide value
* @retval None.
*/
void SPI_SetBaudRatePrescaler(SPI_Type *spi, SPI_DBTypedef spi_baudrateprescaler)
{
REG_WRITE_MASK(spi->CFG, SPI_CFG_DB_Msk, (spi_baudrateprescaler << SPI_CFG_DB_Pos));
}
/**
* @brief Configures the CS pin control select for the selected SPI.
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param nss: specifies the SPI NSS internal state.
* This parameter can be one of the following values:
* @arg SPI_SSOUT_Selected: CS pin is low
* @arg SPI_SSOUT_NoSelected: CS pin is high
* @retval None.
*/
void SPI_SetSSOUT(SPI_Type *spi, uint32_t ss_out_value)
{
REG_WRITE_MASK(spi->CFG, SPI_CFG_SS_OUT_Msk, (ss_out_value << SPI_CFG_SS_OUT_Pos));
}
/**
* @brief Configures the CS pin manual select enable for the selected SPI.
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param mcs_value: CS manual select enable
* @retval None.
*/
void SPI_SetManualChipSelect(SPI_Type *spi, uint32_t mcs_value)
{
REG_WRITE_MASK(spi->CFG, SPI_CFG_MCS_Msk, (mcs_value << SPI_CFG_MCS_Pos));
}
/**
* @brief Configures the manual mode for the selected SPI.
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param mce_en: Manual mode enable or disable
* @retval None.
*/
void SPI_SetManualMode(SPI_Type *spi, uint32_t mce_en)
{
REG_WRITE_MASK(spi->CFG, SPI_CFG_MSE_Msk, (mce_en << SPI_CFG_MSE_Pos));
}
/**
* @brief Configures the manual send data for the selected SPI.
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @retval None.
*/
void SPI_ManualModeStart(SPI_Type *spi)
{
REG_SET_BITS(spi->CFG, SPI_CFG_MSTC_Msk);
}
/**
* @brief Configures the data size for the selected SPI.
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param datasize_value: specifies the SPI data size.
* @retval None.
* @retval None.
*/
void SPI_SetTxDataSize(SPI_Type *spi, SPI_TXDataSizeTypedef datasize_value)
{
REG_WRITE_MASK(spi->CFG, SPI_CFG_TXWDSZ_Msk, (datasize_value << SPI_CFG_TXWDSZ_Pos));
}
/**
* @brief Get interrupt status
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param flag: selects the position of the interrupt flag
* @arg SPI_RECVOV_Flag
* @arg SPI_MDF_Flag
* @arg SPI_TXNFUL_Flag
* @arg SPI_TXFUL_Flag
* @arg SPI_RXNEP_Flag
* @arg SPI_RXFUL_Flag
* @arg SPI_TXUFL_Flag
* @arg SPI_BUSY_Flag
* @retval indicate the interrupt flag is set or reset
*/
uint32_t SPI_GetInterruptStatus(SPI_Type *spi, uint32_t flag)
{
return ((spi->STA & flag) ? 1 : 0);
}
/**
* @brief Get interrupt flag status
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param flag: selects the position of the interrupt flag
* @retval indicate the interrupt flag is set or reset
*/
uint32_t SPI_GetFlagStatus(SPI_Type *spi, uint32_t flag)
{
return ((spi->STA & flag) ? 1 : 0);
}
/**
* @brief Clear interrupt flag
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param flag: selects the position of the interrupt flag
* only for RECVOV,MDF,TXUFL
* @retval write 1 to clear the interrupt flag
*/
void SPI_ClearFlagStatus(SPI_Type *spi, uint32_t flag)
{
REG_SET_BITS(spi->STA, flag);
}
/**
* @brief Set interrupt bit enable
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param interrupt: specifies the SPI interrupt source to enable.
* @retval None
*/
void SPI_SetInterrupt(SPI_Type *spi, uint32_t flag)
{
REG_SET_BITS(spi->INTEN, flag);
}
/**
* @brief Set interrupt bit disable
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param interrupt: specifies the SPI interrupt source to disable.
* @retval None
*/
void SPI_SetInterruptDisable(SPI_Type *spi, uint32_t flag)
{
REG_SET_BITS(spi->INTDIS, flag);
}
/**
* @brief Config the delay of spi transmit.
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param delay_set: the delay value to set
* @retval None.
*/
void SPI_SetDelay(SPI_Type *spi, SPI_DelayTypeDef * delay_set)
{
REG_WRITE_MASK(spi->DELAY, SPI_DELAY_d_int_Msk, (delay_set->d_int << SPI_DELAY_d_int_Pos));
REG_WRITE_MASK(spi->DELAY, SPI_DELAY_d_affter_Msk, (delay_set->d_after << SPI_DELAY_d_affter_Pos));
REG_WRITE_MASK(spi->DELAY, SPI_DELAY_d_btwn_Msk, (delay_set->d_btwn << SPI_DELAY_d_btwn_Pos));
REG_WRITE_MASK(spi->DELAY, SPI_DELAY_d_nss_Msk, (delay_set->d_nss << SPI_DELAY_d_nss_Pos));
}
/**
* @brief Set the idle time of the slaver device
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param idle_cnt: the idle time in slave mode
* @retval None.
*/
void SPI_SetIdleCnt(SPI_Type *spi, uint32_t idle_cnt)
{
spi->IDLECNT = idle_cnt;
}
/**
* @brief Transmits a Data through the spi peripheral.
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param data : Data to be transmitted by manual mode.
* @retval None.
*/
void SPI_ManualSendData(SPI_Type *spi, uint32_t data)
{
spi->TX = data;
SPI_ManualModeStart(spi);
}
/**
* @brief Set the send fifo threshold
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param txth: the value of send fifo threshold
* @retval None.
*/
void SPI_SetTXTH(SPI_Type *spi, uint32_t txth)
{
spi->TXTH = txth;
}
/**
* @brief Set the receive fifo threshold
* @param spi: Select the SPI peripheral.
* This parameter can be one of the following values:
* SPI0.
* @param txth: the value of receive fifo threshold
* @retval None.
*/
void SPI_SetRXTH(SPI_Type *spi, uint32_t rxth)
{
spi->RXTH = rxth;
}
#endif /* CONFIG_ENABLE_HAL_SPI */
@@ -0,0 +1,103 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_rcc.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_SYSCFG)
//=============================================================================
// Constant Definition
//=============================================================================
#define SYSCFG_RST_FLAGS_ALL (SYSCFG_SYSRSTSR_SWRST_Msk | SYSCFG_SYSRSTSR_WDGRST_Msk | \
SYSCFG_SYSRSTSR_LOCKUPRST_Msk | SYSCFG_SYSRSTSR_PORRST_Msk | \
SYSCFG_SYSRSTSR_PADRST_Msk | SYSCFG_SYSRSTSR_LVDRST_Msk | \
SYSCFG_SYSRSTSR_REBOOTRST_Msk)
#define SYSCFG_AUTHKEY_REBOOT_UNLOCK 0xAB56
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
void SYSCFG_SysClkConfig(SYSCFG_ClkInitTypeDef *pInit)
{
REG_WRITE_MASK(SYSCFG->SYSCLKCR,
(SYSCFG_SYSCLKCR_CLKSW_Msk | SYSCFG_SYSCLKCR_CLKDIV_Msk),
(pInit->ClkSource | pInit->SysClk_Div));
SYSCFG_SetSysTickSrc(pInit->SysTickSrc);
g_SystemCoreClock = sys_get_cpu_freq();
return;
}
int SYSCFG_GetFlagStatus(SYSCFG_FlagTypeDef flag)
{
uint32_t status = 0;
uint32_t mask = (flag == SYSCFG_FLAG_ALL)
? SYSCFG_FLAGS_TYPE_Msk
: (uint32_t)1ul << (flag & SYSCFG_FLAGS_TYPE_Msk);
status = REG_READ(SYSCFG->SYSRSTSR);
return (status & mask);
}
void SYSCFG_ClearFlags(SYSCFG_FlagTypeDef flag)
{
uint32_t shift = flag & SYSCFG_FLAGS_TYPE_Msk;
(shift == SYSCFG_FLAGS_TYPE_Msk)
? REG_SET_BITS(SYSCFG->SYSRSTSR, SYSCFG_RST_FLAGS_ALL)
: REG_SET_BITS(SYSCFG->SYSRSTSR, ((uint32_t)1ul << shift));
return;
}
void SYSCFG_RebootLetch(void)
{
REG_WRITE(SYSCFG->REBOOT_UNLOCK, SYSCFG_AUTHKEY_REBOOT_UNLOCK);
REG_SET_BITS(SYSCFG->SYSRSTCR, SYSCFG_SYSRSTCR_REBOOTEN_Msk);
while(1);
return;
}
void SYSCFG_SetICEPin2NormalIO(int is_enable)
{
(is_enable)
? REG_WRITE(SYSCFG->ICEIOCR, 0xE653ul << SYSCFG_ICEIOCR_AUTHKEY_Pos)
: REG_WRITE(SYSCFG->ICEIOCR,
(0xE653ul << SYSCFG_ICEIOCR_AUTHKEY_Pos) | \
SYSCFG_ICEIOCR_JTAGIOEN_Msk | SYSCFG_ICEIOCR_DBG_CTRL_EN_Msk | SYSCFG_ICEIOCR_DBG_EN_Msk);
return;
}
#endif /* CONFIG_ENABLE_HAL_RCC */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,100 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_uart.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/09/10
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_UART)
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
UART_ErrTypeDef UART_Init(UART_Type *pHUart, UART_InitTypeDef *pInit)
{
uint32_t pclk = g_SystemCoreClock;
uint32_t baudrate = 0;
if( pHUart == 0 || pInit == 0 )
{
return UART_ERR_NULL_POINTER;
}
if( pHUart == UART0 )
{
__HAL_SYSCFG_UART0_CLK_ENABLE();
__HAL_SYSCFG_RESET_UART0();
}
REG_WRITE(pHUart->CR, 0x0);
REG_WRITE(pHUart->IE, 0x0);
UART_ResetRxFIFO(pHUart);
UART_ResetTxFIFO(pHUart);
/**
* Uart->BR_b.BR should use algorithm to approach target baudrate
*/
baudrate = (pclk + (pInit->BaudRate * 8)) / (pInit->BaudRate * 16);
pHUart->BR = baudrate;
REG_WRITE_MASK(pHUart->CR,
(UART_CR_MODE_Msk | UART_CR_STOPB_Msk | UART_CR_PAR_Msk | UART_CR_RXEN_Msk),
(pInit->WordLength | pInit->StopBits | pInit->Parity | pInit->Mode));
return UART_ERR_OK;
}
void UART_SendData(UART_Type *pHUart, uint16_t value)
{
pHUart->DAT_b.DAT = value;
return;
}
uint16_t UART_ReceiveData(UART_Type *pHUart)
{
return pHUart->DAT_b.DAT;
}
UART_ErrTypeDef UART_ITConfig(UART_Type *pHUart, uint32_t flags, uint32_t is_enable)
{
if( pHUart == 0 )
return UART_ERR_NULL_POINTER;
(is_enable) ?
REG_SET_BITS(pHUart->IE, flags) :
REG_CLR_BITS(pHUart->IE, flags);
return UART_ERR_OK;
}
#endif /* CONFIG_ENABLE_HAL_UART */
@@ -0,0 +1,76 @@
/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file hal_wdg.c
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/10/17
* @license
* @description
*/
#include "hal_device.h"
#if defined(CONFIG_ENABLE_HAL_WDG)
//=============================================================================
// Constant Definition
//=============================================================================
//=============================================================================
// Macro Definition
//=============================================================================
//=============================================================================
// Structure Definition
//=============================================================================
//=============================================================================
// Global Data Definition
//=============================================================================
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
void WDG_StructInit(WDG_InitTypeDef *pInit)
{
pInit->Counter = 0xFFFFFFFFul;
pInit->ResetMode = WDG_Reset_Disable;
return;
}
void WDG_Init(WDG_InitTypeDef *pInit)
{
__HAL_SYSCFG_RESET_WDG();
__HAL_SYSCFG_WDG_CLK_ENABLE();
sys_close_IRQ(WDG_IRQn);
WDG_Unlock();
REG_WRITE(WDG->LOAD, pInit->Counter);
REG_WRITE_MASK(WDG->CR, WDG_CR_RSTE_Msk, pInit->ResetMode);
REG_WRITE(WDG->INTCLR, 0x1ul);
WDG_Lock();
return;
}
void WDG_DeInit(void)
{
__HAL_SYSCFG_WDG_CLK_DISABLE();
__HAL_SYSCFG_RESET_WDG();
sys_close_IRQ(WDG_IRQn);
return;
}
#endif /* CONFIG_ENABLE_HAL_WDG */
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,294 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_COMPATIABLE_H__
#define __CORE_COMPATIABLE_H__
/*!
* @file core_compatiable.h
* @brief ARM compatiable function definitions header file
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "core_feature_base.h"
/* ===== ARM Compatiable Functions ===== */
/**
* \defgroup NMSIS_Core_ARMCompatiable_Functions ARM Compatiable Functions
* \ingroup NMSIS_Core
* \brief A few functions that compatiable with ARM CMSIS-Core.
* \details
*
* Here we provided a few functions that compatiable with ARM CMSIS-Core,
* mostly used in the DSP and NN library.
* @{
*/
/** \brief Instruction Synchronization Barrier, compatiable with ARM */
#define __ISB() __RWMB()
/** \brief Data Synchronization Barrier, compatiable with ARM */
#define __DSB() __RWMB()
/** \brief Data Memory Barrier, compatiable with ARM */
#define __DMB() __RWMB()
/** \brief LDRT Unprivileged (8 bit), ARM Compatiable */
#define __LDRBT(ptr) __LB((ptr))
/** \brief LDRT Unprivileged (16 bit), ARM Compatiable */
#define __LDRHT(ptr) __LH((ptr))
/** \brief LDRT Unprivileged (32 bit), ARM Compatiable */
#define __LDRT(ptr) __LW((ptr))
/** \brief STRT Unprivileged (8 bit), ARM Compatiable */
#define __STRBT(val, ptr) __SB((ptr), (val))
/** \brief STRT Unprivileged (16 bit), ARM Compatiable */
#define __STRHT(val, ptr) __SH((ptr), (val))
/** \brief STRT Unprivileged (32 bit), ARM Compatiable */
#define __STRT(val, ptr) __SW((ptr), (val))
/* ===== Saturation Operations ===== */
/**
* \brief Signed Saturate
* \details Saturates a signed value.
* \param [in] value Value to be saturated
* \param [in] sat Bit position to saturate to (1..32)
* \return Saturated value
*/
#if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
#define __SSAT(val, sat) __RV_SCLIP32((val), (sat-1))
#else
__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat)
{
if ((sat >= 1U) && (sat <= 32U)) {
const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
const int32_t min = -1 - max ;
if (val > max) {
return max;
} else if (val < min) {
return min;
}
}
return val;
}
#endif
/**
* \brief Unsigned Saturate
* \details Saturates an unsigned value.
* \param [in] value Value to be saturated
* \param [in] sat Bit position to saturate to (0..31)
* \return Saturated value
*/
#if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
#define __USAT(val, sat) __RV_UCLIP32((val), (sat))
#else
__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat)
{
if (sat <= 31U) {
const uint32_t max = ((1U << sat) - 1U);
if (val > (int32_t)max) {
return max;
} else if (val < 0) {
return 0U;
}
}
return (uint32_t)val;
}
#endif
/* ===== Data Processing Operations ===== */
/**
* \brief Reverse byte order (32 bit)
* \details Reverses the byte order in unsigned integer value.
* For example, 0x12345678 becomes 0x78563412.
* \param [in] value Value to reverse
* \return Reversed value
*/
__STATIC_FORCEINLINE uint32_t __REV(uint32_t value)
{
uint32_t result;
result = ((value & 0xff000000) >> 24)
| ((value & 0x00ff0000) >> 8 )
| ((value & 0x0000ff00) << 8 )
| ((value & 0x000000ff) << 24);
return result;
}
/**
* \brief Reverse byte order (16 bit)
* \details Reverses the byte order within each halfword of a word.
* For example, 0x12345678 becomes 0x34127856.
* \param [in] value Value to reverse
* \return Reversed value
*/
__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value)
{
uint32_t result;
result = ((value & 0xff000000) >> 8)
| ((value & 0x00ff0000) << 8 )
| ((value & 0x0000ff00) >> 8 )
| ((value & 0x000000ff) << 8) ;
return result;
}
/**
* \brief Reverse byte order (16 bit)
* \details Reverses the byte order in a 16-bit value
* and returns the signed 16-bit result.
* For example, 0x0080 becomes 0x8000.
* \param [in] value Value to reverse
* \return Reversed value
*/
__STATIC_FORCEINLINE int16_t __REVSH(int16_t value)
{
int16_t result;
result = ((value & 0xff00) >> 8) | ((value & 0x00ff) << 8);
return result;
}
/**
* \brief Rotate Right in unsigned value (32 bit)
* \details Rotate Right (immediate) provides the value of
* the contents of a register rotated by a variable number of bits.
* \param [in] op1 Value to rotate
* \param [in] op2 Number of Bits to rotate(0-31)
* \return Rotated value
*/
__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
{
op2 = op2 & 0x1F;
if (op2 == 0U) {
return op1;
}
return (op1 >> op2) | (op1 << (32U - op2));
}
/**
* \brief Rotate Right in uint32x2 value (64 bit)
* \details Rotate Right (immediate) provides the value of
* the contents of a register rotated by a variable number of bits.
* \param [in] op1 Value to rotate([63:32] and [31:0] rotate separately)
* \param [in] op2 Number of Bits to rotate
* \return Rotated value([63:32] | [31:0])
*/
__STATIC_FORCEINLINE uint64_t __ROR64(uint64_t op1, uint32_t op2)
{
op2 = op2 & 0x1F;
if (op2 == 0U) {
return op1;
}
uint32_t tmp1 = (uint32_t)op1;
uint32_t tmp2 = (uint32_t)(op1 >> 32);
return (uint64_t)((tmp1 >> op2) | (tmp1 << (32U - op2)))
| ((uint64_t)((tmp2 >> op2) | (tmp2 << (32U - op2))) << 32);
}
/**
* \brief Reverse bit order of value
* \details Reverses the bit order of the given value.
* \param [in] value Value to reverse
* \return Reversed value
*/
#if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
#define __RBIT(value) __RV_BITREVI((value), 31)
#else
__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
result = value; /* r will be reversed bits of v; first get LSB of v */
for (value >>= 1U; value != 0U; value >>= 1U) {
result <<= 1U;
result |= value & 1U;
s--;
}
result <<= s; /* shift when v's highest bits are zero */
return result;
}
#endif /* defined(__DSP_PRESENT) && (__DSP_PRESENT == 1) */
/**
* \brief Count leading zeros
* \details Counts the number of leading zeros of a data value.
* \param [in] data Value to count the leading zeros
* \return number of leading zeros in value
*/
#if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
#define __CLZ(data) __RV_CLZ32(data)
#else
__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t data)
{
uint8_t ret = 0;
uint32_t temp = ~data;
while (temp & 0x80000000) {
temp <<= 1;
ret++;
}
return ret;
}
#endif /* defined(__DSP_PRESENT) && (__DSP_PRESENT == 1) */
/**
* \brief Count tailing zero
* \details Return the count of least-significant bit zero.for example, return 3 if x=0bxxx1000
* \param [in] data Value to count the tailing zeros
* \return number of tailing zeros in value
*/
__STATIC_FORCEINLINE unsigned long __CTZ(unsigned long data)
{
unsigned long ret = 0;
while (!(data & 1UL)) {
ret++;
data = data >> 1;
}
return ret;
}
/**
* \brief Expand byte to unsigned long value
* \details Expand byte value x to unsigned long value's each byte.
* \param [in] x the byte value to be expand, the input must be uint8_t type
* \return Expanded value in unsigned long
*/
#if __RISCV_XLEN == 32
#define __EXPD_BYTE(x) ((unsigned long)(((unsigned long)(x) << 0) | \
((unsigned long)(x) << 8) | \
((unsigned long)(x) << 16) | \
((unsigned long)(x) << 24)))
#elif __RISCV_XLEN == 64
#define __EXPD_BYTE(x) ((unsigned long)(((unsigned long)(x) << 0) | \
((unsigned long)(x) << 8) | \
((unsigned long)(x) << 16) | \
((unsigned long)(x) << 24) | \
((unsigned long)(x) << 32) | \
((unsigned long)(x) << 40) | \
((unsigned long)(x) << 48) | \
((unsigned long)(x) << 56)))
#endif
/** @} */ /* End of Doxygen Group NMSIS_Core_ARMCompatiable_Functions */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_COMPATIABLE_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_BITMANIP__
#define __CORE_FEATURE_BITMANIP__
/*!
* @file core_feature_bitmanip.h
* @brief Bitmanipulation feature API header file for Nuclei N/NX Core
*/
/*
* Bitmanipulation Feature Configuration Macro:
* 1. __BITMANIP_PRESENT: Define whether Bitmanipulation Unit is present or not
* * 0: Not present
* * 1: Present
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "core_feature_base.h"
#if defined(__BITMANIP_PRESENT) && (__BITMANIP_PRESENT == 1)
/* ########################### CPU Bitmanipulation Intrinsic Functions ########################### */
/**
* \defgroup NMSIS_Core_Bitmanip_Intrinsic Intrinsic Functions for Bitmanipulation Instructions
* \ingroup NMSIS_Core
* \brief Functions that generate RISC-V Bitmanipulation instructions.
* \details
*
* RISC-V Bitmanipulation Intrinsic APIs are provided directly through compiler generated intrinsic function.
*
* This intrinsic function support in compiler is introduced in nuclei riscv gcc 10.2.
*
* API header file can be found in lib/gcc/riscv-nuclei-elf/<gcc_ver>/include/rvintrin.h
*
* For Nuclei GCC 13/Clang 17, this intrinsic header no longer existed, please take care.
*
* @{
*/
/** @} */ /* End of Doxygen Group NMSIS_Core_Bitmanip_Intrinsic */
#if defined(__INC_INTRINSIC_API) && (__INC_INTRINSIC_API == 1)
// deleted in gcc13, you can directly use b extension intrinisc api
//#include <rvintrin.h>
#endif
#endif /* defined(__BITMANIP_PRESENT) && (__BITMANIP_PRESENT == 1) */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_FEATURE_BITMANIP__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,438 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_CIDU_H__
#define __CORE_FEATURE_CIDU_H__
/*!
* @file core_feature_cidu.h
* @brief Cluster Interrupt Distribution Unit feature API header file for Nuclei N/NX Core
*/
/*
* CIDU Feature Configuration Macro:
* 1. __CIDU_PRESENT: Define whether Cluster Interrupt Distribution Unit is present or not.
* * 0: Not present
* * 1: Present
* 2. __CIDU_BASEADDR: Define the base address of the CIDU.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "core_feature_base.h"
#if defined(__CIDU_PRESENT) && (__CIDU_PRESENT == 1)
/* ########################## CIDU functions #################################### */
/**
* \defgroup NMSIS_Core_CIDU CIDU Functions
* \brief Functions that manage external interrupts, inter core interrupts and semaphores.
* @{
*
* Nuclei provide Cluster Interrupt Distribution Unit (CIDU) for scenarios that a SMP system is designed for real
* time application or both Linux and real time application, and Nuclei processor core can optionally support CIDU.
* The CIDU is used to distribute external interrupts to the cores ECLIC, also it provides Inter Core Interrupt (ICI)
* and Semaphores Mechanism. Its features are as follows:
*
* * Support up to 16 Cores in one cluster
* * Support up to 4096 external interrupts sources
* * Support up to 16 Inter Core Interrupts
* * Support 32 Semaphores
*
*/
#ifndef __CIDU_BASEADDR
/* Base address of CIDU(__CIDU_BASEADDR) should be defined in <Device.h> */
#error "__CIDU_BASEADDR is not defined, please check!"
#endif
#define CIDU_BASE __CIDU_BASEADDR
#define CIDU_RECEIVE_INTERRUPT_EN(core_id) (0x1U << core_id) /*!< Indicates the core can receive corresponding interrupt */
#define CIDU_CORE_INT_STATUS_OFS 0x0 /*!< Core n Inter Core Interrupt status register base offset */
#define CIDU_SEMAPHORE_OFS 0x80 /*!< Semaphore n register base offset */
#define CIDU_ICI_SHADOW_OFS 0x3FFC /*!< ICI Interrupt source core ID and target core ID register offset */
#define CIDU_INT_INDICATOR_OFS 0x4000 /*!< External interrupt n indicator register base offset */
#define CIDU_INT_MASK_OFS 0x8000 /*!< External interrupt n mask (mask interrupt n to cores or not when interrupt n indicator on)register base offset */
#define CIDU_CORE_NUM_OFS 0xC084 /*!< Static configuration core num register offset */
#define CIDU_INT_NUM_OFS 0xC090 /*!< Static configuration external interrupt number register offset */
#define CIDU_CORE_INT_STATUS_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_CORE_INT_STATUS_OFS) + ((n) << 2)) /*!< Core n Inter Core Interrupt status register address */
#define CIDU_SEMAPHORE_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_SEMAPHORE_OFS) + ((n) << 2)) /*!< Semaphore n register address */
#define CIDU_ICI_SHADOW_ADDR (unsigned long)((CIDU_BASE) + (CIDU_ICI_SHADOW_OFS)) /*!< ICI Interrupt source core ID and target core ID register address */
#define CIDU_INT_INDICATOR_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_INT_INDICATOR_OFS) + ((n) << 2)) /*!< External interrupt n indicator register address */
#define CIDU_INT_MASK_ADDR(n) (unsigned long)((CIDU_BASE) + (CIDU_INT_MASK_OFS) + ((n) << 2)) /*!< External interrupt n mask (mask interrupt n to cores or not when interrupt n indicator on)register address */
#define CIDU_CORE_NUM_ADDR (unsigned long)((CIDU_BASE) + (CIDU_CORE_NUM_OFS)) /*!< Static configuration core num register address */
#define CIDU_INT_NUM_ADDR (unsigned long)((CIDU_BASE) + (CIDU_INT_NUM_OFS)) /*!< Static configuration external interrupt number register address */
/* SEND_CORE_ID position in ICI_SHADOW_REG register */
#define CIDU_ICI_SEND_CORE_ID_POS 16
/**
* \brief Get core number in the cluster
* \details
* Indicate the static configuration core num in the cluster.
* \return core number configured
* \remarks
* - In a Nulcei multi-core system, each core has an identifiable serial number, the serial number starts from 0 and is
* continuous, also the number is static.
* - CORE_NUM register is read only.
*/
__STATIC_FORCEINLINE uint32_t CIDU_GetCoreNum(void)
{
uint32_t val;
uint32_t* addr = (uint32_t*)CIDU_CORE_NUM_ADDR;
val = __LW(addr);
return val;
}
/**
* \brief Get external interrupt number
* \details
* Indicate the static configuration external interrupt number
* \return interrupt number configured
* \remarks
* - INT_NUM register is read only.
*/
__STATIC_FORCEINLINE uint32_t CIDU_GetIntNum(void)
{
uint32_t val;
uint32_t* addr = (uint32_t*)CIDU_INT_NUM_ADDR;
val = __LW(addr);
return val;
}
/** @} */ /* End of Doxygen Group NMSIS_Core_CIDU */
/**
* \defgroup NMSIS_Core_Distribute_Interrupt External Interrupt Distribution Functions
* \ingroup NMSIS_Core_CIDU
* \brief Functions that distribute external interrupts to cores.
* @{
*/
/**
* \brief Broadcast external interrupt to cores
* \details
* This function broadcasts external interrupt which id is int_id to some/all target cores
* \param [in] int_id external interrupt id
* \param [in] to_cores target cores which can receive interrupt, use bitwise inclusive or
* of \ref CIDU_RECEIVE_INTERRUPT_EN(core_id)
* \remarks
* - External IRQn ID(int_id) is from the hard-wired persperctive,
* which has an offset mapped to the ECLIC IRQn, see Interrupt Number Definition in <Device.h>
* - By default on reset, only core 0 can receive interrupt which id is int_id
*/
__STATIC_FORCEINLINE void CIDU_BroadcastExtInterrupt(uint32_t int_id, uint32_t to_cores)
{
uint32_t* addr = (uint32_t*)CIDU_INT_INDICATOR_ADDR(int_id);
__SW(addr, (uint32_t)to_cores);
}
/**
* \brief get broadcast mode status
* \details
* Just query the INTn_INDICATOR register value
* \param [in] int_id external interrupt id
* \return INTn_INDICATOR register value
* \remarks
* - External IRQn ID(int_id) is from the hard-wired persperctive,
* which has an offset mapped to the ECLIC IRQn, see Interrupt Number Definition in <Device.h>
* - By default on reset, only core 0 can receive interrupt which id is int_id
*/
__STATIC_FORCEINLINE uint32_t CIDU_GetBroadcastModeStatus(uint32_t int_id)
{
uint32_t val = 0;
uint32_t* addr = (uint32_t*)CIDU_INT_INDICATOR_ADDR(int_id);
val = __LW(addr);
return val;
}
/**
* \brief Let the first coming core to first claim the interrupt
* \details
* In external interrupt broadcast mode, make the first coming core to claim this interrupt and then can handle it.
* \param [in] int_id external interrupt id
* \param [in] core_id core id that receive the interrupt
* \return -1 if it fails to claim the interrupt, else it can continue to handle the interrupt
* \remarks
* - External IRQn ID(int_id) is from the hard-wired persperctive,
* which has an offset mapped to the ECLIC IRQn, see Interrupt Number Definition in <Device.h>.
* - If it fails to claim the interrupt, it should quit the interrupt n's handler of all cores
* - When a core claims the interrupt successfully and has handled it, it must call \ref CIDU_ResetFirstClaimMode to reset the claim.
* \sa
* - \ref CIDU_BroadcastExtInterrupt
* - \ref CIDU_ResetFirstClaimMode
*/
__STATIC_FORCEINLINE long CIDU_SetFirstClaimMode(uint32_t int_id, uint32_t core_id)
{
uint32_t val = 0;
uint32_t* addr = (uint32_t*)CIDU_INT_MASK_ADDR(int_id);
uint32_t mask = 1 << core_id;
__SW(addr, mask);
val = __LW(addr);
if (mask == val) {
return 0;
}
return -1;
}
/**
* \brief Reset the claim mode mask
* \details
* Reset the claim mode mask by Writing the reset value (all 1) to it
* \param [in] int_id external interrupt id
* \remarks
* - External IRQn ID(int_id) is from the hard-wired persperctive,
* which has an offset mapped to the ECLIC IRQn, see Interrupt Number Definition in <Device.h>
* - When a core claims the interrupt successfully and handle it, it must call \ref CIDU_ResetFirstClaimMode to reset the claim
* \sa
* - \ref CIDU_SetFirstClaimMode
*/
__STATIC_FORCEINLINE void CIDU_ResetFirstClaimMode(uint32_t int_id)
{
uint32_t val = 0;
uint32_t* addr = (uint32_t*)CIDU_INT_MASK_ADDR(int_id);
/* clear by writing all 1 */
__SW(addr, 0xFFFFFFFF);
}
/**
* \brief Get the claim mask status
* \details
* Get the claim mode staus, each bit[n] indicates whether core n has claimed interrupt successfully,
* 1 means yes, 0 means no.
* \param [in] int_id external interrupt id
* \return claim mode register INTn_MASK value
* \remarks
* - External IRQn ID(int_id) is from the hard-wired persperctive,
* which has an offset mapped to the ECLIC IRQn, see Interrupt Number Definition in <Device.h>
* \sa
* - \ref CIDU_ResetFirstClaimMode
* - \ref CIDU_SetFirstClaimMode
*/
__STATIC_FORCEINLINE uint32_t CIDU_GetClaimStatus(uint32_t int_id)
{
uint32_t val = 0;
uint32_t* addr = (uint32_t*)CIDU_INT_MASK_ADDR(int_id);
val = __LW(addr);
return val;
}
/** @} */ /* End of Doxygen Group NMSIS_Core_Distribute_Interrupt */
/**
* \defgroup NMSIS_Core_ICI Inter Core Interrupt Functions
* \ingroup NMSIS_Core_CIDU
* \brief Functions that implement Inter Core Interrupt mechanism.
* @{
* Inter Core Interrupt (ICI) means that one core can send interrupt to another core in a multi-core cluster. CIDU ICI belongs
* to Internal Interrupt.
*
* * CIDU ICI Interrupt ID is fixed to 16.
*/
/**
* \brief Trigger interrupt to another core in a multi-core cluster
* \details
* When called by core send_core_id, CIDU will trigger ICI to core recv_core_id automatically.
* and core recv_core_id could query \ref CIDU_GetCoreIntSenderId to know the sender.
* \param [in] send_core_id the core id which want to send the inter core interrupt
* \param [in] recv_core_id the core id which will receive the inter core interrupt
* \remarks
* - The core recv_core_id need to call CIDU_ClearInterCoreIntReq to clear the corresponding bit/bits
* of its own COREn_INT_STATUS.
* - It supports that multiple cores call \ref CIDU_TriggerInterCoreInt simultaneously.
* \sa
* - \ref CIDU_GetCoreIntSenderId
* - \ref CIDU_ClearInterCoreIntReq
*/
__STATIC_FORCEINLINE void CIDU_TriggerInterCoreInt(uint32_t send_core_id, uint32_t recv_core_id)
{
uint32_t val = 0;
uint32_t* addr = (uint32_t*)CIDU_ICI_SHADOW_ADDR;
val = (uint32_t)(send_core_id << CIDU_ICI_SEND_CORE_ID_POS) | (uint32_t)(recv_core_id);
__SW(addr, (uint32_t)val);
}
/**
* \brief Core recv_core_id queries out who sends inter core interrupt to itself
* \details
* In the ISR of ICI, receive core can query if bit[n] of this return value is 1, core n sends the current ICI,
* if bit[m] is 1, then core m also sends, etc.
* \param [in] recv_core_id the core id which receives the inter core interrupt
* \return Value that shows sender core's ID n whose bit[n](bit[m] if core m send too, etc.) is 1
* \remarks
* - If the ICI ISR has finished the job, should call \ref CIDU_ClearInterCoreIntReq to clear the IRQ
*/
__STATIC_FORCEINLINE uint32_t CIDU_QueryCoreIntSenderMask(uint32_t recv_core_id)
{
uint32_t val = 0;
uint32_t* addr = (uint32_t*)CIDU_CORE_INT_STATUS_ADDR(recv_core_id);
val = __LW(addr);
return val;
}
/**
* \brief Clear the corresponding bit/bits of ICI request triggered by sender core
* \details
* Core recv_core_id write 1 to clear the bit send_core_id of the core recv_core_id's COREn_INT_STATUS.
* \param [in] send_core_id the core id which wants to send the inter core interrupt
* \param [in] recv_core_id the core id which will receive the inter core interrupt
* \remarks
* - If the ICI ISR has finished the job of send_core_id_n's ICI, then clear bit send_core_id_n;
* if it has finished send_core_id_n and send_core_id_m's, then should clear both the bits, etc.
*/
__STATIC_FORCEINLINE void CIDU_ClearInterCoreIntReq(uint32_t send_core_id, uint32_t recv_core_id)
{
uint32_t val = 0;
uint32_t* addr = (uint32_t*)CIDU_CORE_INT_STATUS_ADDR(recv_core_id);
val = (uint32_t)(1 << send_core_id);
__SW(addr, val);
}
/** @} */ /* End of Doxygen Group NMSIS_Core_ICI */
/**
* \defgroup NMSIS_Core_Semaphore Semaphore Functions
* \ingroup NMSIS_Core_CIDU
* \brief Functions that configure and use semaphores
* @{
* Semaphore is very useful for multi-core cluster without SMP enable.
*
* * All Cores in the cluster agree on using SEMAPHORE_n register to protect a critical resource (an UART device for example).
* * If Core n wants to access the critical resource, it should try to own the SEMPAPHORE_n register, or else it cant access the critical resource.
* * When the Core n owns the register SEMPAPHORE_n and finishes the job related the critical resource, then it should
* release the register by writing all 1 to it.
*/
/**
* \brief Get SEMAPHOREn's value
* \details
* Just query the semaphore n's value
* \param [in] semph_n the semaphore id used to protect a critical resource
* \return register SEMAPHOREn_STATUS value
*/
__STATIC_FORCEINLINE uint32_t CIDU_GetSemaphoreStatus(uint32_t semph_n)
{
uint32_t val;
uint32_t* addr = (uint32_t*)CIDU_SEMAPHORE_ADDR(semph_n);
val = __LW(addr);
return val;
}
/**
* \brief check SEMAPHOREn's acquired status
* \details
* Query that whether SEMAPHOREn has been acquired by one core successfully.
* \param [in] semph_n the semaphore id used to protect a critical resource
* \param [in] core_id the core id that wants to access the critical resource
* \return 0 if core_id has acquired this semaphore successfully, or else -1 if failed
* \remarks
* - When the core n owns the register SEMPAPHORE_n and finishes the job related the critical resource,
* it should call \ref CIDU_ReleaseSemaphore to release it.
* \sa
* - \ref CIDU_GetSemaphoreStatus
* - \ref CIDU_ReleaseSemaphore
*/
__STATIC_FORCEINLINE long CIDU_CheckSemaphoreAcquired(uint32_t semph_n, uint32_t core_id)
{
uint32_t val;
val = CIDU_GetSemaphoreStatus(semph_n);
if (core_id != val) {
return -1;
}
return 0;
}
/**
* \brief Acquire the SEMAPHOREn
* \details
* Acuqire the SEMAPHOREn, and check the acquired status
* \param [in] semph_n the semaphore id used to protect a critical resource
* \param [in] core_id the core id that wants to access the critical resource
* \return 0 if core_id has acquired this semaphore successfully, or else -1 if failed
* \remarks
* - When the core n owns the register SEMPAPHORE_n and finishes the job related the critical resource,
* it should call \ref CIDU_ReleaseSemaphore to release it.
* \sa
* - \ref CIDU_CheckSemaphoreAcquired
* - \ref CIDU_ReleaseSemaphore
*/
__STATIC_FORCEINLINE long CIDU_AcquireSemaphore(uint32_t semph_n, uint32_t core_id)
{
long semaphore_status = -1;
uint32_t* addr = (uint32_t*)CIDU_SEMAPHORE_ADDR(semph_n);
__SW(addr, core_id);
semaphore_status = CIDU_CheckSemaphoreAcquired(semph_n, core_id);
return semaphore_status;
}
/**
* \brief Keep acquiring the SEMAPHOREn until it has acquired this semaphore successfully
* \details
* Query that whether SEMAPHOREn has been owned by one core successfully, if not, keep trying.
* \param [in] semph_n the semaphore id used to protect a critical resource
* \param [in] core_id the core id that wants to access the critical resource
* \remarks
* - Core n will block here acquiring, so take care that core should release the semaphore when related job done.
* \sa
* - \ref CIDU_AcquireSemaphore
* - \ref CIDU_ReleaseSemaphore
*/
__STATIC_FORCEINLINE void CIDU_AcquireSemaphore_Block(uint32_t semph_n, uint32_t core_id)
{
int32_t semaphore_status = -1;
while(0 != semaphore_status) {
semaphore_status = CIDU_AcquireSemaphore(semph_n, core_id);
}
}
/**
* \brief Release the SEMAPHOREn
* \details
* Release the SEMAPHOREn by writing all 1 to SEMAPHOREn register.
* \param [in] semph_n the semaphore id used to protect a critical resource
* \remarks
* - When the core finishes the job related to the critical resource, it should release the corresponding semaphore.
* \sa
* - \ref CIDU_AcquireSemaphore_Block
*/
__STATIC_FORCEINLINE void CIDU_ReleaseSemaphore(uint32_t semph_n)
{
uint32_t* addr = (uint32_t*)CIDU_SEMAPHORE_ADDR(semph_n);
/* Release by writing all 1 */
__SW(addr, 0xFFFFFFFF);
}
/** @} */ /* End of Doxygen Group NMSIS_Core_Semaphore */
#endif /* defined(__CIDU_PRESENT) && (__CIDU_PRESENT == 1) */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_FEATURE_CIDU_H__ */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,308 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_FPU_H__
#define __CORE_FEATURE_FPU_H__
/*!
* @file core_feature_fpu.h
* @brief FPU feature API header file for Nuclei N/NX Core
*/
/*
* FPU Feature Configuration Macro:
* 1. __FPU_PRESENT: Define whether Floating Point Unit(FPU) is present or not
* * 0: Not present
* * 1: Single precision FPU present, __RISCV_FLEN == 32
* * 2: Double precision FPU present, __RISCV_FLEN == 64
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "core_feature_base.h"
/* ===== FPU Operations ===== */
/**
* \defgroup NMSIS_Core_FPU_Functions FPU Functions
* \ingroup NMSIS_Core
* \brief Functions that related to the RISC-V FPU (F and D extension).
* \details
*
* Nuclei provided floating point unit by RISC-V F and D extension.
* * `F extension` adds single-precision floating-point computational
* instructions compliant with the IEEE 754-2008 arithmetic standard, __RISCV_FLEN = 32.
* The F extension adds 32 floating-point registers, f0-f31, each 32 bits wide,
* and a floating-point control and status register fcsr, which contains the
* operating mode and exception status of the floating-point unit.
* * `D extension` adds double-precision floating-point computational instructions
* compliant with the IEEE 754-2008 arithmetic standard.
* The D extension widens the 32 floating-point registers, f0-f31, to 64 bits, __RISCV_FLEN = 64
* @{
*/
#if defined(__FPU_PRESENT) && (__FPU_PRESENT > 0)
#if __FPU_PRESENT == 1
/** \brief Refer to the width of the floating point register in bits(either 32 or 64) */
#define __RISCV_FLEN 32
#elif __FPU_PRESENT == 2
#define __RISCV_FLEN 64
#else
#define __RISCV_FLEN __riscv_flen
#endif /* __FPU_PRESENT == 1 */
/** \brief Get FCSR CSR Register */
#define __get_FCSR() __RV_CSR_READ(CSR_FCSR)
/** \brief Set FCSR CSR Register with val */
#define __set_FCSR(val) __RV_CSR_WRITE(CSR_FCSR, (val))
/** \brief Get FRM CSR Register */
#define __get_FRM() __RV_CSR_READ(CSR_FRM)
/** \brief Set FRM CSR Register with val */
#define __set_FRM(val) __RV_CSR_WRITE(CSR_FRM, (val))
/** \brief Get FFLAGS CSR Register */
#define __get_FFLAGS() __RV_CSR_READ(CSR_FFLAGS)
/** \brief Set FFLAGS CSR Register with val */
#define __set_FFLAGS(val) __RV_CSR_WRITE(CSR_FFLAGS, (val))
/** \brief Enable FPU Unit, and set state to initial */
#define __enable_FPU() { __RV_CSR_CLEAR(CSR_MSTATUS, MSTATUS_FS); \
__RV_CSR_SET(CSR_MSTATUS, MSTATUS_FS_INITIAL); \
}
/**
* \brief Disable FPU Unit
* \details
* * We can save power by disable FPU Unit.
* * When FPU Unit is disabled, any access to FPU related CSR registers
* and FPU instructions will cause illegal Instuction Exception.
* */
#define __disable_FPU() __RV_CSR_CLEAR(CSR_MSTATUS, MSTATUS_FS)
/**
* \brief Load a single-precision value from memory into float point register freg using flw instruction
* \details The FLW instruction loads a single-precision floating point value from memory
* address (addr + ofs) into floating point register freg(f0-f31)
* \param [in] freg The floating point register, eg. FREG(0), f0
* \param [in] addr The memory base address, 4 byte aligned required
* \param [in] ofs a 12-bit immediate signed byte offset value, should be an const value
* \remarks
* * FLW and FSW operations need to make sure the address is 4 bytes aligned,
* otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)
* * FLW and FSW do not modify the bits being transferred; in particular, the payloads of non-canonical
* NaNs are preserved
*
*/
#define __RV_FLW(freg, addr, ofs) \
({ \
rv_csr_t __addr = (rv_csr_t)(addr); \
__ASM volatile("flw " STRINGIFY(freg) ", %0(%1) " \
: : "I"(ofs), "r"(__addr) \
: "memory"); \
})
/**
* \brief Store a single-precision value from float point freg into memory using fsw instruction
* \details The FSW instruction stores a single-precision value from floating point register to memory
* \param [in] freg The floating point register(f0-f31), eg. FREG(0), f0
* \param [in] addr The memory base address, 4 byte aligned required
* \param [in] ofs a 12-bit immediate signed byte offset value, should be an const value
* \remarks
* * FLW and FSW operations need to make sure the address is 4 bytes aligned,
* otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)
* * FLW and FSW do not modify the bits being transferred; in particular, the payloads of non-canonical
* NaNs are preserved
*
*/
#define __RV_FSW(freg, addr, ofs) \
({ \
rv_csr_t __addr = (rv_csr_t)(addr); \
__ASM volatile("fsw " STRINGIFY(freg) ", %0(%1) " \
: : "I"(ofs), "r"(__addr) \
: "memory"); \
})
/**
* \brief Load a double-precision value from memory into float point register freg using fld instruction
* \details The FLD instruction loads a double-precision floating point value from memory
* address (addr + ofs) into floating point register freg(f0-f31)
* \param [in] freg The floating point register, eg. FREG(0), f0
* \param [in] addr The memory base address, 8 byte aligned required
* \param [in] ofs a 12-bit immediate signed byte offset value, should be an const value
* \attention
* * Function only available for double precision floating point unit, FLEN = 64
* \remarks
* * FLD and FSD operations need to make sure the address is 8 bytes aligned,
* otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)
* * FLD and FSD do not modify the bits being transferred; in particular, the payloads of non-canonical
* NaNs are preserved.
*/
#define __RV_FLD(freg, addr, ofs) \
({ \
rv_csr_t __addr = (rv_csr_t)(addr); \
__ASM volatile("fld " STRINGIFY(freg) ", %0(%1) " \
: : "I"(ofs), "r"(__addr) \
: "memory"); \
})
/**
* \brief Store a double-precision value from float point freg into memory using fsd instruction
* \details The FSD instruction stores double-precision value from floating point register to memory
* \param [in] freg The floating point register(f0-f31), eg. FREG(0), f0
* \param [in] addr The memory base address, 8 byte aligned required
* \param [in] ofs a 12-bit immediate signed byte offset value, should be an const value
* \attention
* * Function only available for double precision floating point unit, FLEN = 64
* \remarks
* * FLD and FSD operations need to make sure the address is 8 bytes aligned,
* otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)
* * FLD and FSD do not modify the bits being transferred; in particular, the payloads of non-canonical
* NaNs are preserved.
*
*/
#define __RV_FSD(freg, addr, ofs) \
({ \
rv_csr_t __addr = (rv_csr_t)(addr); \
__ASM volatile("fsd " STRINGIFY(freg) ", %0(%1) " \
: : "I"(ofs), "r"(__addr) \
: "memory"); \
})
/**
* \def __RV_FLOAD
* \brief Load a float point value from memory into float point register freg using flw/fld instruction
* \details
* * For Single-Precison Floating-Point Mode(__FPU_PRESENT == 1, __RISCV_FLEN == 32):
* It will call \ref __RV_FLW to load a single-precision floating point value from memory to floating point register
* * For Double-Precison Floating-Point Mode(__FPU_PRESENT == 2, __RISCV_FLEN == 64):
* It will call \ref __RV_FLD to load a double-precision floating point value from memory to floating point register
*
* \attention
* Function behaviour is different for __FPU_PRESENT = 1 or 2, please see the real function this macro represent
*/
/**
* \def __RV_FSTORE
* \brief Store a float value from float point freg into memory using fsw/fsd instruction
* \details
* * For Single-Precison Floating-Point Mode(__FPU_PRESENT == 1, __RISCV_FLEN == 32):
* It will call \ref __RV_FSW to store floating point register into memory
* * For Double-Precison Floating-Point Mode(__FPU_PRESENT == 2, __RISCV_FLEN == 64):
* It will call \ref __RV_FSD to store floating point register into memory
*
* \attention
* Function behaviour is different for __FPU_PRESENT = 1 or 2, please see the real function this macro represent
*/
#if __FPU_PRESENT == 1
#define __RV_FLOAD __RV_FLW
#define __RV_FSTORE __RV_FSW
/** \brief Type of FPU register, depends on the FLEN defined in RISC-V */
typedef uint32_t rv_fpu_t;
#elif __FPU_PRESENT == 2
#define __RV_FLOAD __RV_FLD
#define __RV_FSTORE __RV_FSD
/** \brief Type of FPU register, depends on the FLEN defined in RISC-V */
typedef uint64_t rv_fpu_t;
#endif /* __FPU_PRESENT == 2 */
/**
* \brief Save FPU context into variables for interrupt nesting
* \details
* This macro is used to declare variables which are used for saving
* FPU context, and it will store the nessary fpu registers into
* these variables, it need to be used in a interrupt when in this
* interrupt fpu registers are used.
* \remarks
* - It need to be used together with \ref RESTORE_FPU_CONTEXT
* - Don't use variable names __fpu_context in your ISR code
* - If you isr code will use fpu registers, and this interrupt is nested.
* Then you can do it like this:
* \code
* void eclic_mtip_handler(void)
* {
* // !!!Interrupt is enabled here!!!
* // !!!Higher priority interrupt could nest it!!!
*
* // Necessary only when you need to use fpu registers
* // in this isr handler functions
* SAVE_FPU_CONTEXT();
*
* // put you own interrupt handling code here
*
* // pair of SAVE_FPU_CONTEXT()
* RESTORE_FPU_CONTEXT();
* }
* \endcode
*/
#define SAVE_FPU_CONTEXT() \
rv_fpu_t __fpu_context[20]; \
__RV_FSTORE(FREG(0), __fpu_context, 0 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(1), __fpu_context, 1 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(2), __fpu_context, 2 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(3), __fpu_context, 3 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(4), __fpu_context, 4 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(5), __fpu_context, 5 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(6), __fpu_context, 6 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(7), __fpu_context, 7 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(10), __fpu_context, 8 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(11), __fpu_context, 9 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(12), __fpu_context, 10 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(13), __fpu_context, 11 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(14), __fpu_context, 12 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(15), __fpu_context, 13 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(16), __fpu_context, 14 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(17), __fpu_context, 15 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(28), __fpu_context, 16 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(29), __fpu_context, 17 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(30), __fpu_context, 18 << LOG_FPREGBYTES); \
__RV_FSTORE(FREG(31), __fpu_context, 19 << LOG_FPREGBYTES);
/**
* \brief Restore necessary fpu registers from variables for interrupt nesting
* \details
* This macro is used restore necessary fpu registers from pre-defined variables
* in \ref SAVE_FPU_CONTEXT macro.
* \remarks
* - It need to be used together with \ref SAVE_FPU_CONTEXT
*/
#define RESTORE_FPU_CONTEXT() \
__RV_FLOAD(FREG(0), __fpu_context, 0 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(1), __fpu_context, 1 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(2), __fpu_context, 2 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(3), __fpu_context, 3 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(4), __fpu_context, 4 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(5), __fpu_context, 5 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(6), __fpu_context, 6 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(7), __fpu_context, 7 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(10), __fpu_context, 8 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(11), __fpu_context, 9 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(12), __fpu_context, 10 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(13), __fpu_context, 11 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(14), __fpu_context, 12 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(15), __fpu_context, 13 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(16), __fpu_context, 14 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(17), __fpu_context, 15 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(28), __fpu_context, 16 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(29), __fpu_context, 17 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(30), __fpu_context, 18 << LOG_FPREGBYTES); \
__RV_FLOAD(FREG(31), __fpu_context, 19 << LOG_FPREGBYTES);
#else
#define SAVE_FPU_CONTEXT()
#define RESTORE_FPU_CONTEXT()
#endif /* __FPU_PRESENT > 0 */
/** @} */ /* End of Doxygen Group NMSIS_Core_FPU_Functions */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_FEATURE_FPU_H__ */
@@ -0,0 +1,426 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_PLIC__
#define __CORE_FEATURE_PLIC__
/*!
* @file core_feature_plic.h
* @brief PLIC feature API header file for RISC-V Core
*/
/*
* PLIC Feature Configuration Macro:
* 1. __PLIC_PRESENT: Define whether Platform Level Interrupt Controller (PLIC) Unit is present or not
* * 0: Not present
* * 1: Present
* 2. __PLIC_BASEADDR: Base address of the PLIC unit.
* 3. __PLIC_INTNUM : Define the external interrupt number of PLIC Unit
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "core_feature_base.h"
#if defined(__PLIC_PRESENT) && (__PLIC_PRESENT == 1)
/**
* \defgroup NMSIS_Core_PLIC_Registers Register Define and Type Definitions Of PLIC
* \ingroup NMSIS_Core_Registers
* \brief Type definitions and defines for plic registers.
*
* @{
*/
/* 32 bits per source */
#define PLIC_PRIORITY_OFFSET _AC(0x0000,UL) /*!< PLIC Priority register offset */
#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2 /*!< PLIC Priority register offset shift per source */
/* 1 bit per source (1 address) */
#define PLIC_PENDING_OFFSET _AC(0x1000,UL) /*!< PLIC Pending register offset */
#define PLIC_PENDING_SHIFT_PER_SOURCE 0 /*!< PLIC Pending register offset shift per source */
/* 0x80 per context */
#define PLIC_ENABLE_OFFSET _AC(0x2000,UL) /*!< PLIC Enable register offset */
#define PLIC_ENABLE_SHIFT_PER_CONTEXT 7 /*!< PLIC Enable register offset shift per context */
#define PLIC_THRESHOLD_OFFSET _AC(0x200000,UL) /*!< PLIC Threshold register offset */
#define PLIC_CLAIM_OFFSET _AC(0x200004,UL) /*!< PLIC Claim register offset */
#define PLIC_THRESHOLD_SHIFT_PER_CONTEXT 12 /*!< PLIC Threshold register offset shift per context */
#define PLIC_CLAIM_SHIFT_PER_CONTEXT 12 /*!< PLIC Claim register offset shift per context */
#ifndef __PLIC_BASEADDR
/* Base address of PLIC(__PLIC_BASEADDR) should be defined in <Device.h> */
#error "__PLIC_BASEADDR is not defined, please check!"
#endif
/* PLIC Memory mapping of Device */
#define PLIC_BASE __PLIC_BASEADDR /*!< PLIC Base Address */
/**
* PLIC_GetHartID() is used to get plic hartid which might not be the same as cpu hart id,
* for example, cpu hartid may be 1, but plic hartid may be 0, then plic hartid offset is 1.
* If defined __PLIC_HARTID, it will use __PLIC_HARTID as plic hartid,
* otherwise, it will use __get_hart_index().
* The cpu hartid is get by using __get_hart_id function
*/
#ifndef __PLIC_HARTID
#define PLIC_GetHartID() (__get_hart_index())
#else
#define PLIC_GetHartID() (__PLIC_HARTID)
#endif
#define PLIC_GetHartMContextID() (PLIC_GetHartID() << 1)
// TODO SMODE HARTID need to handle, maybe use a predefined variable of hartid
#define PLIC_GetHartSContextID() ((PLIC_GetHartID() << 1) + 1)
#define PLIC_PRIORITY_REGADDR(source) ((PLIC_BASE) + (PLIC_PRIORITY_OFFSET) + ((source) << PLIC_PRIORITY_SHIFT_PER_SOURCE))
#define PLIC_PENDING_REGADDR(source) ((PLIC_BASE) + (PLIC_PENDING_OFFSET) + (((source) >> 5) * 4))
#define PLIC_ENABLE_REGADDR(ctxid, source) ((PLIC_BASE) + (PLIC_ENABLE_OFFSET) + ((ctxid) << PLIC_ENABLE_SHIFT_PER_CONTEXT) + ((source) >> 5) * 4)
#define PLIC_THRESHOLD_REGADDR(ctxid) ((PLIC_BASE) + (PLIC_THRESHOLD_OFFSET) + ((ctxid) << PLIC_THRESHOLD_SHIFT_PER_CONTEXT))
#define PLIC_CLAIM_REGADDR(ctxid) ((PLIC_BASE) + (PLIC_CLAIM_OFFSET) + ((ctxid) << PLIC_CLAIM_SHIFT_PER_CONTEXT))
#define PLIC_COMPLETE_REGADDR(ctxid) (PLIC_CLAIM_REGADDR(ctxid))
/** @} */ /* end of group NMSIS_Core_PLIC_Registers */
/* ########################## PLIC functions #################################### */
/**
* \defgroup NMSIS_Core_IntPlic PLIC Interrupt
* \brief Functions that manage interrupts via the PLIC.
*
* @{
*/
/**
* \brief Set priority threshold value of plic for selected context
* \details
* This function set priority threshold value of plic for selected context.
* \param [in] ctxid selected context id
* \param [in] thresh threshold value
* \remarks
* \sa
* - \ref PLIC_GetContextThreshold
*/
__STATIC_FORCEINLINE void PLIC_SetContextThreshold(uint32_t ctxid, uint32_t thresh)
{
volatile uint32_t *thresh_reg = (uint32_t *)PLIC_THRESHOLD_REGADDR(ctxid);
*thresh_reg = thresh;
}
/**
* \brief Get priority threshold value of plic for selected context
* \details
* This function get priority threshold value of plic for selected context.
* \param [in] ctxid selected context id
* \return priority threshold value for selected context
* \remarks
* \sa
* - \ref PLIC_SetContextThreshold
*/
__STATIC_FORCEINLINE uint32_t PLIC_GetContextThreshold(uint32_t ctxid)
{
volatile uint32_t *thresh_reg = (uint32_t *)PLIC_THRESHOLD_REGADDR(ctxid);
return (*thresh_reg);
}
/**
* \brief Enable interrupt of selected source plic for selected context
* \details
* This function enable interrupt of selected source plic for selected context.
* \param [in] ctxid selected context id
* \param [in] source interrupt source
* \remarks
* \sa
* - \ref PLIC_DisableContextInterrupt
*/
__STATIC_FORCEINLINE void PLIC_EnableContextInterrupt(uint32_t ctxid, uint32_t source)
{
volatile uint32_t *enable_reg = (uint32_t *)PLIC_ENABLE_REGADDR(ctxid, source);
uint32_t current = *enable_reg;
current = current | (1 << (source & 0x1F));
*enable_reg = current;
}
/**
* \brief Disable interrupt of selected source plic for selected context
* \details
* This function disable interrupt of selected source plic for selected context
* \param [in] ctxid selected context id
* \param [in] source interrupt source
* \remarks
* \sa
* - \ref PLIC_EnableContextInterrupt
*/
__STATIC_FORCEINLINE void PLIC_DisableContextInterrupt(uint32_t ctxid, uint32_t source)
{
volatile uint32_t *enable_reg = (uint32_t *)PLIC_ENABLE_REGADDR(ctxid, source);
uint32_t current = *enable_reg;
current = current & (~(1 << (source & 0x1F)));
*enable_reg = current;
}
/**
* \brief Get interrupt enable status of selected source plic for selected context
* \details
* This function get interrupt enable of selected source plic for selected context.
* \param [in] ctxid selected context id
* \param [in] source interrupt source
* \return enable status for selected interrupt source for selected context
* \remarks
* \sa
* - \ref PLIC_EnableContextInterrupt
* - \ref PLIC_DisableContextInterrupt
*/
__STATIC_FORCEINLINE uint32_t PLIC_GetContextInterruptEnable(uint32_t ctxid, uint32_t source)
{
volatile uint32_t *enable_reg = (uint32_t *)PLIC_ENABLE_REGADDR(ctxid, source);
uint32_t current = *enable_reg;
current = (current >> (source & 0x1F)) & 0x1;
return current;
}
/**
* \brief Set interrupt pending of selected source plic
* \details
* This function set interrupt pending of selected source plic.
* \param [in] source interrupt source
* \remarks
* \sa
* - \ref PLIC_GetInterruptPending
* - \ref PLIC_CLearInterruptPending
*/
__STATIC_FORCEINLINE void PLIC_SetInterruptPending(uint32_t source)
{
volatile uint32_t *pending_reg = (uint32_t *)PLIC_PENDING_REGADDR(source);
uint32_t current = *pending_reg;
current = current | (1 << (source & 0x1F));
*pending_reg = current;
}
/**
* \brief Clear interrupt pending of selected source plic
* \details
* This function clear interrupt pending of selected source plic
* \param [in] source interrupt source
* \remarks
* \sa
* - \ref PLIC_SetInterruptPending
* - \ref PLIC_GetInterruptPending
*/
__STATIC_FORCEINLINE void PLIC_ClearInterruptPending(uint32_t source)
{
volatile uint32_t *pending_reg = (uint32_t *)PLIC_PENDING_REGADDR(source);
uint32_t current = *pending_reg;
current = current & (~(1 << (source & 0x1F)));
*pending_reg = current;
}
/**
* \brief Get interrupt pending status of selected source plic
* \details
* This function get interrupt pending of selected source plic
* \param [in] source interrupt source
* \return interrupt pending status for selected interrupt source
* \remarks
* \sa
* - \ref PLIC_SetInterruptPending
* - \ref PLIC_ClearInterruptPending
*/
__STATIC_FORCEINLINE uint32_t PLIC_GetInterruptPending(uint32_t source)
{
volatile uint32_t *pending_reg = (uint32_t *)PLIC_PENDING_REGADDR(source);
uint32_t current = *pending_reg;
current = (current >> (source & 0x1F)) & 0x1;
return current;
}
/**
* \brief Set interrupt priority for selected source plic
* \details
* This function set interrupt priority for selected source plic.
* \param [in] source interrupt source
* \param [in] priority interrupt priority
* \remarks
* \sa
* - \ref PLIC_GetPriority
*/
__STATIC_FORCEINLINE void PLIC_SetPriority(uint32_t source, uint32_t priority)
{
volatile uint32_t *priority_reg = (uint32_t *)PLIC_PRIORITY_REGADDR(source);
*priority_reg = priority;
}
/**
* \brief Get interrupt priority for selected source plic
* \details
* This function get interrupt priority for selected source plic.
* \param [in] source interrupt source
* \param [in] priority interrupt priority
* \remarks
* \sa
* - \ref PLIC_SetPriority
*/
__STATIC_FORCEINLINE uint32_t PLIC_GetPriority(uint32_t source)
{
volatile uint32_t *priority_reg = (uint32_t *)PLIC_PRIORITY_REGADDR(source);
return (*priority_reg);
}
/**
* \brief Claim interrupt for plic for selected context
* \details
* This function claim interrupt for plic for selected context.
* \param [in] ctxid selected context id
* \return the ID of the highest priority pending interrupt or
* zero if there is no pending interrupt
* \remarks
* A successful claim will also atomically clear the corresponding pending bit
* on the interrupt source. The PLIC can perform a claim at any time and the
* claim operation is not affected by the setting of the priority threshold register.
* \sa
* - \ref PLIC_CompleteContextInterrupt
*/
__STATIC_FORCEINLINE uint32_t PLIC_ClaimContextInterrupt(uint32_t ctxid)
{
volatile uint32_t *claim_reg = (uint32_t *)PLIC_CLAIM_REGADDR(ctxid);
return (*claim_reg);
}
/**
* \brief Complete interrupt for plic for selected context
* \details
* This function complete interrupt for plic for selected context.
* \param [in] ctxid selected context id
* \return the ID of the highest priority pending interrupt or
* zero if there is no pending interrupt
* \remarks
* The PLIC signals it has completed executing an interrupt handler by writing
* the interrupt ID it received from the claim to the claim/complete register.
* The PLIC does not check whether the completion ID is the same as the last
* claim ID for that context.
* If the completion ID does not match an interrupt source that is currently
* enabled for the context, the completion is silently ignored.
* \sa
* - \ref PLIC_ClaimContextInterrupt
*/
__STATIC_FORCEINLINE void PLIC_CompleteContextInterrupt(uint32_t ctxid, uint32_t source)
{
volatile uint32_t *complete_reg = (uint32_t *)PLIC_COMPLETE_REGADDR(ctxid);
*complete_reg = source;
}
/**
* \brief Perform init for plic for selected context
* \details
* This function perform initialization steps for plic for selected context.
* \param [in] ctxid selected context id
* \param [in] num_sources plic interrupt source count number
* \param [in] enable plic interrupt enable or not
* \param [in] thresh plic interrupt threshold
* \remarks
* * Disable all interrupts
* * Set priority threshold to value specified by thresh
*/
__STATIC_FORCEINLINE void PLIC_Context_Init(uint32_t ctxid, uint32_t num_sources, uint32_t enable, uint32_t thresh)
{
uint32_t i;
for (i = 0; i < num_sources; i ++) {
if (enable) {
PLIC_EnableContextInterrupt(ctxid, i);
} else {
PLIC_DisableContextInterrupt(ctxid, i);
}
}
PLIC_SetContextThreshold(ctxid, thresh);
}
#define PLIC_Init(num_sources, enable, thresh) PLIC_Context_Init(PLIC_GetHartMContextID(), (num_sources), (enable), (thresh))
#define PLIC_Init_S(num_sources, enable, thresh) PLIC_Context_Init(PLIC_GetHartSContextID(), (num_sources), (enable), (thresh))
#define PLIC_ClaimInterrupt() PLIC_ClaimContextInterrupt(PLIC_GetHartMContextID())
#define PLIC_ClaimInterrupt_S() PLIC_ClaimContextInterrupt(PLIC_GetHartSContextID())
#define PLIC_CompleteInterrupt(source) PLIC_CompleteContextInterrupt(PLIC_GetHartMContextID(), (source))
#define PLIC_CompleteInterrupt_S(source) PLIC_CompleteContextInterrupt(PLIC_GetHartSContextID(), (source))
#define PLIC_GetInterruptEnable(source) PLIC_GetContextInterruptEnable(PLIC_GetHartMContextID(), (source))
#define PLIC_GetInterruptEnable_S(source) PLIC_GetContextInterruptEnable(PLIC_GetHartSContextID(), (source))
#define PLIC_EnableInterrupt(source) PLIC_EnableContextInterrupt(PLIC_GetHartMContextID(), (source))
#define PLIC_EnableInterrupt_S(source) PLIC_EnableContextInterrupt(PLIC_GetHartSContextID(), (source))
#define PLIC_DisableInterrupt(source) PLIC_DisableContextInterrupt(PLIC_GetHartMContextID(), (source))
#define PLIC_DisableInterrupt_S(source) PLIC_DisableContextInterrupt(PLIC_GetHartSContextID(), (source))
#define PLIC_SetThreshold(source, thresh) PLIC_SetContextThreshold(PLIC_GetHartMContextID(), (source), (thresh))
#define PLIC_SetThreshold_S(source, thresh) PLIC_SetContextThreshold(PLIC_GetHartSContextID(), (source), (thresh))
#define PLIC_GetThreshold(source) PLIC_GetContextThreshold(PLIC_GetHartMContextID(), (source))
#define PLIC_GetThreshold_S(source) PLIC_GetContextThreshold(PLIC_GetHartSContextID(), (source))
/**
* \brief Set Trap entry address
* \details
* This function set trap entry address to 'CSR_MTVEC'.
* \param [in] addr trap entry address
* \remarks
* - This function use to set trap entry address to 'CSR_MTVEC'.
* \sa
* - \ref __get_trap_entry
*/
__STATIC_FORCEINLINE void __set_trap_entry(rv_csr_t addr)
{
addr &= (rv_csr_t)(~0x7);
__RV_CSR_WRITE(CSR_MTVEC, addr);
}
/**
* \brief Get trap entry address
* \details
* This function get trap entry address from 'CSR_MTVEC'.
* \return trap entry address
* \remarks
* - This function use to get trap entry address from 'CSR_MTVEC'.
* \sa
* - \ref __set_trap_entry
*/
__STATIC_FORCEINLINE rv_csr_t __get_trap_entry(void)
{
unsigned long addr = __RV_CSR_READ(CSR_MTVEC);
return (addr);
}
/** @} */ /* End of Doxygen Group NMSIS_Core_IntExc */
#endif /* defined(__PLIC_PRESENT) && (__PLIC_PRESENT == 1) */
#ifdef __cplusplus
}
#endif
#endif /** __CORE_FEATURE_PLIC__ */
@@ -0,0 +1,384 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_PMP_H__
#define __CORE_FEATURE_PMP_H__
/*!
* @file core_feature_pmp.h
* @brief PMP feature API header file for Nuclei N/NX Core
*/
/*
* PMP Feature Configuration Macro:
* 1. __PMP_PRESENT: Define whether Physical Memory Protection(PMP) is present or not
* * 0: Not present
* * 1: Present
* 2. __PMP_ENTRY_NUM: Define the number of PMP entries, only 8 or 16 is configurable.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "core_feature_base.h"
#include "core_compatiable.h"
#if defined(__PMP_PRESENT) && (__PMP_PRESENT == 1)
/* ===== PMP Operations ===== */
/**
* \defgroup NMSIS_Core_PMP_Functions PMP Functions
* \ingroup NMSIS_Core
* \brief Functions that related to the RISCV Phyiscal Memory Protection.
* \details
* Optional physical memory protection (PMP) unit provides per-hart machine-mode
* control registers to allow physical memory access privileges (read, write, execute)
* to be specified for each physical memory region.
*
* The PMP can supports region access control settings as small as four bytes.
*
* @{
*/
#ifndef __PMP_ENTRY_NUM
/* numbers of PMP entries(__PMP_ENTRY_NUM) should be defined in <Device.h> */
#error "__PMP_ENTRY_NUM is not defined, please check!"
#endif
typedef struct PMP_CONFIG {
/**
* set locking bit, addressing mode, read, write, and instruction execution permissions,
* see \ref PMP_L, \ref PMP_R, \ref PMP_W, \ref PMP_X, .etc in <riscv_encoding.h>
*/
unsigned int protection;
/**
* Size of memory region as power of 2, it has to be minimum 2 and maxium \ref __RISCV_XLEN according to the
* hard-wired granularity 2^N bytes, if N = 12, then order has to be at least 12; if not, the order read out
* is N though you configure less than N.
*/
unsigned long order;
/**
* Base address of memory region
* It must be 2^order aligned address
*/
unsigned long base_addr;
} pmp_config;
/**
* \brief Get PMPCFGx Register by csr index
* \details Return the content of the PMPCFGx Register.
* \param [in] csr_idx PMPCFG CSR index(0-3)
* \return PMPCFGx Register value
* \remark
* - For RV64, only csr_idx = 0 and csr_idx = 2 is allowed.
* pmpcfg0 and pmpcfg2 hold the configurations
* for the 16 PMP entries, pmpcfg1 and pmpcfg3 are illegal
* - For RV32, pmpcfg0pmpcfg3, hold the configurations
* pmp0cfgpmp15cfg for the 16 PMP entries
*/
__STATIC_INLINE rv_csr_t __get_PMPCFGx(uint32_t csr_idx)
{
switch (csr_idx) {
case 0: return __RV_CSR_READ(CSR_PMPCFG0);
case 1: return __RV_CSR_READ(CSR_PMPCFG1);
case 2: return __RV_CSR_READ(CSR_PMPCFG2);
case 3: return __RV_CSR_READ(CSR_PMPCFG3);
default: return 0;
}
}
/**
* \brief Set PMPCFGx by csr index
* \details Write the given value to the PMPCFGx Register.
* \param [in] csr_idx PMPCFG CSR index(0-3)
* \param [in] pmpcfg PMPCFGx Register value to set
* \remark
* - For RV64, only csr_idx = 0 and csr_idx = 2 is allowed.
* pmpcfg0 and pmpcfg2 hold the configurations
* for the 16 PMP entries, pmpcfg1 and pmpcfg3 are illegal
* - For RV32, pmpcfg0pmpcfg3, hold the configurations
* pmp0cfgpmp15cfg for the 16 PMP entries
*/
__STATIC_INLINE void __set_PMPCFGx(uint32_t csr_idx, rv_csr_t pmpcfg)
{
switch (csr_idx) {
case 0: __RV_CSR_WRITE(CSR_PMPCFG0, pmpcfg); break;
case 1: __RV_CSR_WRITE(CSR_PMPCFG1, pmpcfg); break;
case 2: __RV_CSR_WRITE(CSR_PMPCFG2, pmpcfg); break;
case 3: __RV_CSR_WRITE(CSR_PMPCFG3, pmpcfg); break;
default: return;
}
}
/**
* \brief Get 8bit PMPxCFG Register by PMP entry index
* \details Return the content of the PMPxCFG Register.
* \param [in] entry_idx PMP region index(0-15)
* \return PMPxCFG Register value
*/
__STATIC_INLINE uint8_t __get_PMPxCFG(uint32_t entry_idx)
{
rv_csr_t pmpcfgx = 0;
uint8_t csr_cfg_num = 0;
uint16_t csr_idx = 0;
uint16_t cfg_shift = 0;
if (entry_idx >= __PMP_ENTRY_NUM) return 0;
#if __RISCV_XLEN == 32
csr_cfg_num = 4;
csr_idx = entry_idx >> 2;
#elif __RISCV_XLEN == 64
csr_cfg_num = 8;
/* For RV64, pmpcfg0 and pmpcfg2 each hold 8 PMP entries, align by 2 */
csr_idx = (entry_idx >> 2) & ~1;
#else
// TODO Add RV128 Handling
return 0;
#endif
pmpcfgx = __get_PMPCFGx(csr_idx);
/*
* first get specific pmpxcfg's order in one CSR composed of csr_cfg_num pmpxcfgs,
* then get pmpxcfg's bit position in one CSR by left shift 3(each pmpxcfg size is one byte)
*/
cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
/* read specific pmpxcfg register value */
return (uint8_t)(__RV_EXTRACT_FIELD(pmpcfgx, 0xFF << cfg_shift));
}
/**
* \brief Set 8bit PMPxCFG by pmp entry index
* \details Set the given pmpxcfg value to the PMPxCFG Register.
* \param [in] entry_idx PMPx region index(0-15)
* \param [in] pmpxcfg PMPxCFG register value to set
* \remark
* - For RV32, 4 pmpxcfgs are densely packed into one CSR in order
* For RV64, 8 pmpxcfgs are densely packed into one CSR in order
*/
__STATIC_INLINE void __set_PMPxCFG(uint32_t entry_idx, uint8_t pmpxcfg)
{
rv_csr_t pmpcfgx = 0;
uint8_t csr_cfg_num = 0;
uint16_t csr_idx = 0;
uint16_t cfg_shift = 0;
if (entry_idx >= __PMP_ENTRY_NUM) return;
#if __RISCV_XLEN == 32
csr_cfg_num = 4;
csr_idx = entry_idx >> 2;
#elif __RISCV_XLEN == 64
csr_cfg_num = 8;
/* For RV64, pmpcfg0 and pmpcfg2 each hold 8 PMP entries, align by 2 */
csr_idx = (entry_idx >> 2) & ~1;
#else
// TODO Add RV128 Handling
return;
#endif
/* read specific pmpcfgx register value */
pmpcfgx = __get_PMPCFGx(csr_idx);
/*
* first get specific pmpxcfg's order in one CSR composed of csr_cfg_num pmpxcfgs,
* then get pmpxcfg's bit position in one CSR by left shift 3(each pmpxcfg size is one byte)
*/
cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
pmpcfgx = __RV_INSERT_FIELD(pmpcfgx, 0xFFUL << cfg_shift, pmpxcfg);
__set_PMPCFGx(csr_idx, pmpcfgx);
}
/**
* \brief Get PMPADDRx Register by CSR index
* \details Return the content of the PMPADDRx Register.
* \param [in] csr_idx PMP region CSR index(0-15)
* \return PMPADDRx Register value
*/
__STATIC_INLINE rv_csr_t __get_PMPADDRx(uint32_t csr_idx)
{
switch (csr_idx) {
case 0: return __RV_CSR_READ(CSR_PMPADDR0);
case 1: return __RV_CSR_READ(CSR_PMPADDR1);
case 2: return __RV_CSR_READ(CSR_PMPADDR2);
case 3: return __RV_CSR_READ(CSR_PMPADDR3);
case 4: return __RV_CSR_READ(CSR_PMPADDR4);
case 5: return __RV_CSR_READ(CSR_PMPADDR5);
case 6: return __RV_CSR_READ(CSR_PMPADDR6);
case 7: return __RV_CSR_READ(CSR_PMPADDR7);
case 8: return __RV_CSR_READ(CSR_PMPADDR8);
case 9: return __RV_CSR_READ(CSR_PMPADDR9);
case 10: return __RV_CSR_READ(CSR_PMPADDR10);
case 11: return __RV_CSR_READ(CSR_PMPADDR11);
case 12: return __RV_CSR_READ(CSR_PMPADDR12);
case 13: return __RV_CSR_READ(CSR_PMPADDR13);
case 14: return __RV_CSR_READ(CSR_PMPADDR14);
case 15: return __RV_CSR_READ(CSR_PMPADDR15);
default: return 0;
}
}
/**
* \brief Set PMPADDRx by CSR index
* \details Write the given value to the PMPADDRx Register.
* \param [in] csr_idx PMP region CSR index(0-15)
* \param [in] pmpaddr PMPADDRx Register value to set
*/
__STATIC_INLINE void __set_PMPADDRx(uint32_t csr_idx, rv_csr_t pmpaddr)
{
switch (csr_idx) {
case 0: __RV_CSR_WRITE(CSR_PMPADDR0, pmpaddr); break;
case 1: __RV_CSR_WRITE(CSR_PMPADDR1, pmpaddr); break;
case 2: __RV_CSR_WRITE(CSR_PMPADDR2, pmpaddr); break;
case 3: __RV_CSR_WRITE(CSR_PMPADDR3, pmpaddr); break;
case 4: __RV_CSR_WRITE(CSR_PMPADDR4, pmpaddr); break;
case 5: __RV_CSR_WRITE(CSR_PMPADDR5, pmpaddr); break;
case 6: __RV_CSR_WRITE(CSR_PMPADDR6, pmpaddr); break;
case 7: __RV_CSR_WRITE(CSR_PMPADDR7, pmpaddr); break;
case 8: __RV_CSR_WRITE(CSR_PMPADDR8, pmpaddr); break;
case 9: __RV_CSR_WRITE(CSR_PMPADDR9, pmpaddr); break;
case 10: __RV_CSR_WRITE(CSR_PMPADDR10, pmpaddr); break;
case 11: __RV_CSR_WRITE(CSR_PMPADDR11, pmpaddr); break;
case 12: __RV_CSR_WRITE(CSR_PMPADDR12, pmpaddr); break;
case 13: __RV_CSR_WRITE(CSR_PMPADDR13, pmpaddr); break;
case 14: __RV_CSR_WRITE(CSR_PMPADDR14, pmpaddr); break;
case 15: __RV_CSR_WRITE(CSR_PMPADDR15, pmpaddr); break;
default: return;
}
}
/**
* \brief Set PMP entry by entry idx
* \details Write the given value to the PMPxCFG Register and PMPADDRx.
* \param [in] entry_idx PMP entry index(0-15)
* \param [in] pmp_cfg structure of L, X, W, R field of PMP configuration register, memory region base address
* and size of memory region as power of 2
* \remark
* - If the size of memory region is 2^12(4KB) range, pmp_cfg->order makes 12, and the like.
* - Suppose the size of memory region is 2^X bytes range, if X >=3, the NA4 mode is not selectable, NAPOT is selected.
* - TOR of A field in PMP configuration register is not considered here.
*/
__STATIC_INLINE void __set_PMPENTRYx(uint32_t entry_idx, const pmp_config *pmp_cfg)
{
unsigned int cfg_shift, cfg_csr_idx, addr_csr_idx = 0;
unsigned long cfgmask, addrmask = 0;
unsigned long pmpcfg, pmpaddr = 0;
unsigned long protection, csr_cfg_num = 0;
/* check parameters */
if (entry_idx >= __PMP_ENTRY_NUM || pmp_cfg->order > __RISCV_XLEN || pmp_cfg->order < PMP_SHIFT) return;
/* calculate PMP register and offset */
#if __RISCV_XLEN == 32
csr_cfg_num = 4;
cfg_csr_idx = (entry_idx >> 2);
#elif __RISCV_XLEN == 64
csr_cfg_num = 8;
cfg_csr_idx = ((entry_idx >> 2)) & ~1;
#else
// TODO Add RV128 Handling
return;
#endif
/*
* first get specific pmpxcfg's order in one CSR composed of csr_cfg_num pmpxcfgs,
* then get pmpxcfg's bit position in one CSR by left shift 3, each pmpxcfg size is one byte
*/
cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
addr_csr_idx = entry_idx;
/* encode PMP config */
protection = (unsigned long)pmp_cfg->protection;
protection |= (PMP_SHIFT == pmp_cfg->order) ? PMP_A_NA4 : PMP_A_NAPOT;
cfgmask = ~(0xFFUL << cfg_shift);
pmpcfg = (__get_PMPCFGx(cfg_csr_idx) & cfgmask);
pmpcfg |= ((protection << cfg_shift) & ~cfgmask);
/* encode PMP address */
if (PMP_SHIFT == pmp_cfg->order) { /* NA4 */
pmpaddr = (pmp_cfg->base_addr >> PMP_SHIFT);
} else { /* NAPOT */
addrmask = (1UL << (pmp_cfg->order - PMP_SHIFT)) - 1;
pmpaddr = ((pmp_cfg->base_addr >> PMP_SHIFT) & ~addrmask);
pmpaddr |= (addrmask >> 1);
}
/*
* write csrs, update the address first, in case the entry is locked that
* we won't be able to modify it after we set the config csr.
*/
__set_PMPADDRx(addr_csr_idx, pmpaddr);
__set_PMPCFGx(cfg_csr_idx, pmpcfg);
}
/**
* \brief Get PMP entry by entry idx
* \details Write the given value to the PMPxCFG Register and PMPADDRx.
* \param [in] entry_idx PMP entry index(0-15)
* \param [out] pmp_cfg structure of L, X, W, R, A field of PMP configuration register, memory region base
* address and size of memory region as power of 2
* \return -1 failure, else 0 success
* \remark
* - If the size of memory region is 2^12(4KB) range, pmp_cfg->order makes 12, and the like.
* - TOR of A field in PMP configuration register is not considered here.
*/
__STATIC_INLINE int __get_PMPENTRYx(unsigned int entry_idx, pmp_config *pmp_cfg)
{
unsigned int cfg_shift, cfg_csr_idx, addr_csr_idx = 0;
unsigned long cfgmask, pmpcfg, prot = 0;
unsigned long t1, addr, pmpaddr, len = 0;
uint8_t csr_cfg_num = 0;
/* check parameters */
if (entry_idx >= __PMP_ENTRY_NUM || !pmp_cfg) return -1;
/* calculate PMP register and offset */
#if __RISCV_XLEN == 32
csr_cfg_num = 4;
cfg_csr_idx = entry_idx >> 2;
#elif __RISCV_XLEN == 64
csr_cfg_num = 8;
cfg_csr_idx = (entry_idx>> 2) & ~1;
#else
// TODO Add RV128 Handling
return -1;
#endif
cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
addr_csr_idx = entry_idx;
/* decode PMP config */
cfgmask = (0xFFUL << cfg_shift);
pmpcfg = (__get_PMPCFGx(cfg_csr_idx) & cfgmask);
prot = pmpcfg >> cfg_shift;
/* decode PMP address */
pmpaddr = __get_PMPADDRx(addr_csr_idx);
if (PMP_A_NAPOT == (prot & PMP_A)) {
t1 = __CTZ(~pmpaddr);
addr = (pmpaddr & ~((1UL << t1) - 1)) << PMP_SHIFT;
len = (t1 + PMP_SHIFT + 1);
} else {
addr = pmpaddr << PMP_SHIFT;
len = PMP_SHIFT;
}
/* return details */
pmp_cfg->protection = prot;
pmp_cfg->base_addr = addr;
pmp_cfg->order = len;
return 0;
}
/** @} */ /* End of Doxygen Group NMSIS_Core_PMP_Functions */
#endif /* defined(__PMP_PRESENT) && (__PMP_PRESENT == 1) */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_FEATURE_PMP_H__ */
@@ -0,0 +1,449 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_SPMP_H__
#define __CORE_FEATURE_SPMP_H__
/*!
* @file core_feature_spmp.h
* @brief sPMP(has upgraded to S-mode Memory Protection Unit, renamed as SMPU) feature API header file for Nuclei N/NX Core
*/
/*
* sPMP Feature Configuration Macro:
* 1. __SPMP_PRESENT: Define whether sPMP is present or not
* __SMPU_PRESENT: Define whether SMPU is present or not
* * 0: Not present
* * 1: Present
* 2. __SPMP_ENTRY_NUM: Define the number of sPMP entries, only 8 or 16 is configurable
* __SMPU_ENTRY_NUM: Define the number of SMPU entries, only 8 or 16 is configurable
* __SMPU_ENTRY_NUM is the same as __SPMP_ENTRY_NUM
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "core_feature_base.h"
#include "core_compatiable.h"
#if defined(__SPMP_PRESENT) && (__SPMP_PRESENT == 1)
/* ===== sPMP Operations ===== */
/**
* \defgroup NMSIS_Core_SPMP_Functions sPMP Functions
* \ingroup NMSIS_Core
* \brief Functions that related to the RISCV supervisor-mode Phyiscal Memory Protection.
* \details
* Optional superviosr physical memory protection (sPMP) unit provides per-hart supervisor-mode
* control registers to allow physical memory access privileges (read, write, execute)
* to be specified for each physical memory region. The sPMP values are checked after the physical
* address to be accessed pass PMP checks described in the RISC-V privileged spec.
*
* Like PMP, the sPMP can supports region access control settings as small as four bytes.
*
* @{
*/
#ifndef __SPMP_ENTRY_NUM
/* Number of __SPMP_ENTRY_NUM entries should be defined in <Device.h> */
#error "__SPMP_ENTRY_NUM is not defined, please check!"
#endif
typedef struct SPMP_CONFIG {
/**
* Set permissions using macros \ref SMPU_S/\ref SMPU_R/\ref SMPU_W/\ref SMPU_X of SMPU;
* \ref SPMP_L/\ref SPMP_U/\ref SPMP_R/\ref SPMP_W/\ref SPMP_X of sPMP,
* see details in riscv spec of SMPU/sPMP
*/
unsigned int protection;
/**
* Size of memory region as power of 2, it has to be minimum 2 and maxium \ref __RISCV_XLEN according to the
* hardwired granularity 2^N bytes, if N = 12, then order has to be at least 12; if not, the order read out
* is N though you configure less than N.
*/
unsigned long order;
/**
* Base address of memory region
* It must be 2^order aligned address
*/
unsigned long base_addr;
} spmp_config;
/**
* \brief Get sPMPCFGx Register by csr index
* \details Return the content of the sPMPCFGx Register.
* \param [in] csr_idx sPMPCFG CSR index(0-3)
* \return sPMPCFGx Register value
* \remark
* - For RV64, only csr_idx = 0 and csr_idx = 2 is allowed.
* spmpcfg0 and spmpcfg2 hold the configurations
* for the 16 sPMP entries, spmpcfg1 and spmpcfg3 are illegal
* - For RV32, spmpcfg0spmpcfg3, hold the configurations
* spmp0cfgspmp15cfg for the 16 sPMP entries
*/
__STATIC_INLINE rv_csr_t __get_sPMPCFGx(uint32_t csr_idx)
{
switch (csr_idx) {
case 0: return __RV_CSR_READ(CSR_SPMPCFG0);
case 1: return __RV_CSR_READ(CSR_SPMPCFG1);
case 2: return __RV_CSR_READ(CSR_SPMPCFG2);
case 3: return __RV_CSR_READ(CSR_SPMPCFG3);
default: return 0;
}
}
/**
* \brief Set sPMPCFGx by csr index
* \details Write the given value to the sPMPCFGx Register.
* \param [in] csr_idx sPMPCFG CSR index(0-3)
* \param [in] spmpcfg sPMPCFGx Register value to set
* \remark
* - For RV64, only csr_idx = 0 and csr_idx = 2 is allowed.
* spmpcfg0 and spmpcfg2 hold the configurations
* for the 16 sPMP entries, spmpcfg1 and spmpcfg3 are illegal
* - For RV32, spmpcfg0spmpcfg3, hold the configurations
* spmp0cfgspmp15cfg for the 16 sPMP entries
*/
__STATIC_INLINE void __set_sPMPCFGx(uint32_t csr_idx, rv_csr_t spmpcfg)
{
switch (csr_idx) {
case 0: __RV_CSR_WRITE(CSR_SPMPCFG0, spmpcfg); break;
case 1: __RV_CSR_WRITE(CSR_SPMPCFG1, spmpcfg); break;
case 2: __RV_CSR_WRITE(CSR_SPMPCFG2, spmpcfg); break;
case 3: __RV_CSR_WRITE(CSR_SPMPCFG3, spmpcfg); break;
default: return;
}
}
/**
* \brief Get 8bit sPMPxCFG Register by sPMP entry index
* \details Return the content of the sPMPxCFG Register.
* \param [in] entry_idx sPMP region index(0-15)
* \return sPMPxCFG Register value
*/
__STATIC_INLINE uint8_t __get_sPMPxCFG(uint32_t entry_idx)
{
rv_csr_t spmpcfgx = 0;
uint8_t csr_cfg_num = 0;
uint16_t csr_idx = 0;
uint16_t cfg_shift = 0;
if (entry_idx >= __SPMP_ENTRY_NUM) return 0;
#if __RISCV_XLEN == 32
csr_cfg_num = 4;
csr_idx = entry_idx >> 2;
#elif __RISCV_XLEN == 64
csr_cfg_num = 8;
/* For RV64, spmpcfg0 and spmpcfg2 each hold 8 sPMP entries, align by 2 */
csr_idx = (entry_idx >> 2) & ~1;
#else
// TODO Add RV128 Handling
return 0;
#endif
spmpcfgx = __get_sPMPCFGx(csr_idx);
/*
* first get specific spmpxcfg's order in one CSR composed of csr_cfg_num spmpxcfgs,
* then get spmpxcfg's bit position in one CSR by left shift 3(each spmpxcfg size is one byte)
*/
cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
/* read specific spmpxcfg register value */
return (uint8_t)(__RV_EXTRACT_FIELD(spmpcfgx, 0xFF << cfg_shift));
}
/**
* \brief Set 8bit sPMPxCFG by spmp entry index
* \details Set the given spmpxcfg value to the sPMPxCFG Register.
* \param [in] entry_idx sPMPx region index(0-15)
* \param [in] spmpxcfg sPMPxCFG register value to set
* \remark
* - For RV32, 4 spmpxcfgs are densely packed into one CSR in order
* For RV64, 8 spmpxcfgs are densely packed into one CSR in order
*/
__STATIC_INLINE void __set_sPMPxCFG(uint32_t entry_idx, uint8_t spmpxcfg)
{
rv_csr_t spmpcfgx = 0;
uint8_t csr_cfg_num = 0;
uint16_t csr_idx = 0;
uint16_t cfg_shift = 0;
if (entry_idx >= __SPMP_ENTRY_NUM) return;
#if __RISCV_XLEN == 32
csr_cfg_num = 4;
csr_idx = entry_idx >> 2;
#elif __RISCV_XLEN == 64
csr_cfg_num = 8;
/* For RV64, spmpcfg0 and spmpcfg2 each hold 8 sPMP entries, align by 2 */
csr_idx = (entry_idx >> 2) & ~1;
#else
// TODO Add RV128 Handling
return;
#endif
/* read specific spmpcfgx register value */
spmpcfgx = __get_sPMPCFGx(csr_idx);
/*
* first get specific spmpxcfg's order in one CSR composed of csr_cfg_num spmpxcfgs,
* then get spmpxcfg's bit position in one CSR by left shift 3(each spmpxcfg size is one byte)
*/
cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
spmpcfgx = __RV_INSERT_FIELD(spmpcfgx, 0xFFUL << cfg_shift, spmpxcfg);
__set_sPMPCFGx(csr_idx, spmpcfgx);
}
/**
* \brief Get sPMPADDRx Register by CSR index
* \details Return the content of the sPMPADDRx Register.
* \param [in] csr_idx sPMP region CSR index(0-15)
* \return sPMPADDRx Register value
*/
__STATIC_INLINE rv_csr_t __get_sPMPADDRx(uint32_t csr_idx)
{
switch (csr_idx) {
case 0: return __RV_CSR_READ(CSR_SPMPADDR0);
case 1: return __RV_CSR_READ(CSR_SPMPADDR1);
case 2: return __RV_CSR_READ(CSR_SPMPADDR2);
case 3: return __RV_CSR_READ(CSR_SPMPADDR3);
case 4: return __RV_CSR_READ(CSR_SPMPADDR4);
case 5: return __RV_CSR_READ(CSR_SPMPADDR5);
case 6: return __RV_CSR_READ(CSR_SPMPADDR6);
case 7: return __RV_CSR_READ(CSR_SPMPADDR7);
case 8: return __RV_CSR_READ(CSR_SPMPADDR8);
case 9: return __RV_CSR_READ(CSR_SPMPADDR9);
case 10: return __RV_CSR_READ(CSR_SPMPADDR10);
case 11: return __RV_CSR_READ(CSR_SPMPADDR11);
case 12: return __RV_CSR_READ(CSR_SPMPADDR12);
case 13: return __RV_CSR_READ(CSR_SPMPADDR13);
case 14: return __RV_CSR_READ(CSR_SPMPADDR14);
case 15: return __RV_CSR_READ(CSR_SPMPADDR15);
default: return 0;
}
}
/**
* \brief Set sPMPADDRx by CSR index
* \details Write the given value to the sPMPADDRx Register.
* \param [in] csr_idx sPMP region CSR index(0-15)
* \param [in] spmpaddr sPMPADDRx Register value to set
*/
__STATIC_INLINE void __set_sPMPADDRx(uint32_t csr_idx, rv_csr_t spmpaddr)
{
switch (csr_idx) {
case 0: __RV_CSR_WRITE(CSR_SPMPADDR0, spmpaddr); break;
case 1: __RV_CSR_WRITE(CSR_SPMPADDR1, spmpaddr); break;
case 2: __RV_CSR_WRITE(CSR_SPMPADDR2, spmpaddr); break;
case 3: __RV_CSR_WRITE(CSR_SPMPADDR3, spmpaddr); break;
case 4: __RV_CSR_WRITE(CSR_SPMPADDR4, spmpaddr); break;
case 5: __RV_CSR_WRITE(CSR_SPMPADDR5, spmpaddr); break;
case 6: __RV_CSR_WRITE(CSR_SPMPADDR6, spmpaddr); break;
case 7: __RV_CSR_WRITE(CSR_SPMPADDR7, spmpaddr); break;
case 8: __RV_CSR_WRITE(CSR_SPMPADDR8, spmpaddr); break;
case 9: __RV_CSR_WRITE(CSR_SPMPADDR9, spmpaddr); break;
case 10: __RV_CSR_WRITE(CSR_SPMPADDR10, spmpaddr); break;
case 11: __RV_CSR_WRITE(CSR_SPMPADDR11, spmpaddr); break;
case 12: __RV_CSR_WRITE(CSR_SPMPADDR12, spmpaddr); break;
case 13: __RV_CSR_WRITE(CSR_SPMPADDR13, spmpaddr); break;
case 14: __RV_CSR_WRITE(CSR_SPMPADDR14, spmpaddr); break;
case 15: __RV_CSR_WRITE(CSR_SPMPADDR15, spmpaddr); break;
default: return;
}
}
/**
* \brief Set sPMP entry by entry idx
* \details Write the given value to the sPMPxCFG Register and sPMPADDRx.
* \param [in] entry_idx sPMP entry index(0-15)
* \param [in] spmp_cfg structure of L,U,X,W,R field of sPMP configuration register, memory region base address
* and size of memory region as power of 2
* \remark
* - If the size of memory region is 2^12(4KB) range, spmp_cfg->order makes 12, and the like.
* - Suppose the size of memory region is 2^X bytes range, if X >=3, the NA4 mode is not selectable, NAPOT is selected.
* - TOR of A field in sPMP configuration register is not considered here.
*/
__STATIC_INLINE void __set_sPMPENTRYx(uint32_t entry_idx, const spmp_config *spmp_cfg)
{
unsigned int cfg_shift, cfg_csr_idx, addr_csr_idx = 0;
unsigned long cfgmask, addrmask = 0;
unsigned long spmpcfg, spmpaddr = 0;
unsigned long protection, csr_cfg_num = 0;
/* check parameters */
if (entry_idx >= __SPMP_ENTRY_NUM || spmp_cfg->order > __RISCV_XLEN || spmp_cfg->order < SPMP_SHIFT) return;
/* calculate sPMP register and offset */
#if __RISCV_XLEN == 32
csr_cfg_num = 4;
cfg_csr_idx = (entry_idx >> 2);
#elif __RISCV_XLEN == 64
csr_cfg_num = 8;
cfg_csr_idx = ((entry_idx >> 2)) & ~1;
#else
// TODO Add RV128 Handling
return;
#endif
/*
* first get specific spmpxcfg's order in one CSR composed of csr_cfg_num spmpxcfgs,
* then get spmpxcfg's bit position in one CSR by left shift 3, each spmpxcfg size is one byte
*/
cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
addr_csr_idx = entry_idx;
/* encode sPMP config */
protection = (unsigned long)spmp_cfg->protection;
protection |= (SPMP_SHIFT == spmp_cfg->order) ? SPMP_A_NA4 : SPMP_A_NAPOT;
cfgmask = ~(0xFFUL << cfg_shift);
spmpcfg = (__get_sPMPCFGx(cfg_csr_idx) & cfgmask);
spmpcfg |= ((protection << cfg_shift) & ~cfgmask);
/* encode sPMP address */
if (SPMP_SHIFT == spmp_cfg->order) { /* NA4 */
spmpaddr = (spmp_cfg->base_addr >> SPMP_SHIFT);
} else { /* NAPOT */
addrmask = (1UL << (spmp_cfg->order - SPMP_SHIFT)) - 1;
spmpaddr = ((spmp_cfg->base_addr >> SPMP_SHIFT) & ~addrmask);
spmpaddr |= (addrmask >> 1);
}
/*
* write csrs, update the address first, in case the entry is locked that
* we won't be able to modify it after we set the config csr.
*/
__set_sPMPADDRx(addr_csr_idx, spmpaddr);
__set_sPMPCFGx(cfg_csr_idx, spmpcfg);
}
/**
* \brief Get sPMP entry by entry idx
* \details Write the given value to the sPMPxCFG Register and sPMPADDRx.
* \param [in] entry_idx sPMP entry index(0-15)
* \param [out] spmp_cfg structure of L, U, X, W, R, A field of sPMP configuration register, memory region base
* address and size of memory region as power of 2
* \return -1 failure, else 0 success
* \remark
* - If the size of memory region is 2^12(4KB) range, spmp_cfg->order makes 12, and the like.
* - TOR of A field in PMP configuration register is not considered here.
*/
__STATIC_INLINE int __get_sPMPENTRYx(unsigned int entry_idx, spmp_config *spmp_cfg)
{
unsigned int cfg_shift, cfg_csr_idx, addr_csr_idx = 0;
unsigned long cfgmask, spmpcfg, prot = 0;
unsigned long t1, addr, spmpaddr, len = 0;
uint8_t csr_cfg_num = 0;
/* check parameters */
if (entry_idx >= __SPMP_ENTRY_NUM || !spmp_cfg) return -1;
/* calculate sPMP register and offset */
#if __RISCV_XLEN == 32
csr_cfg_num = 4;
cfg_csr_idx = entry_idx >> 2;
#elif __RISCV_XLEN == 64
csr_cfg_num = 8;
cfg_csr_idx = (entry_idx >> 2) & ~1;
#else
// TODO Add RV128 Handling
return -1;
#endif
cfg_shift = (entry_idx & (csr_cfg_num - 1)) << 3;
addr_csr_idx = entry_idx;
/* decode sPMP config */
cfgmask = (0xFFUL << cfg_shift);
spmpcfg = (__get_sPMPCFGx(cfg_csr_idx) & cfgmask);
prot = spmpcfg >> cfg_shift;
/* decode sPMP address */
spmpaddr = __get_sPMPADDRx(addr_csr_idx);
if (SPMP_A_NAPOT == (prot & SPMP_A)) {
t1 = __CTZ(~spmpaddr);
addr = (spmpaddr & ~((1UL << t1) - 1)) << SPMP_SHIFT;
len = (t1 + SPMP_SHIFT + 1);
} else {
addr = spmpaddr << SPMP_SHIFT;
len = SPMP_SHIFT;
}
/* return details */
spmp_cfg->protection = prot;
spmp_cfg->base_addr = addr;
spmp_cfg->order = len;
return 0;
}
#if defined(__SMPU_PRESENT) && (__SMPU_PRESENT == 1)
/**
* sPMP has upgraded to S-mode Memory Protection Unit, renamed as SMPU, but still share the apis with sPMP's
*/
typedef spmp_config smpu_config;
#define __get_SMPUCFGx __get_sPMPCFGx
#define __set_SMPUCFGx __set_sPMPCFGx
#define __get_SMPUxCFG __get_sPMPxCFG
#define __set_SMPUxCFG __set_sPMPxCFG
#define __get_SMPUADDRx __get_sPMPADDRx
#define __set_SMPUADDRx __set_sPMPADDRx
#define __set_SMPUENTRYx __set_sPMPENTRYx
#define __get_SMPUENTRYx __get_sPMPENTRYx
/**
* \brief Set SMPU each entry's on/off status
* \details Write the given value to the SMPUSWITCHx Register.
* \param [in] val activate each entry(max to 64) or not
* \remark
* - Each bit of this register holds on/off status of the corresponding SMPU entry respectively.
* - An SMPU entry is activated only when both corresponding bits in smpuswitch and
* A field of smpuicfg are set. (i.e., smpuswitch[i] & smpu[i]cfg.A).
*/
__STATIC_INLINE void __set_SMPUSWITCHx(uint64_t val)
{
#if __RISCV_XLEN == 32
__RV_CSR_WRITE(CSR_SMPUSWITCH0, (uint32_t)val);
__RV_CSR_WRITE(CSR_SMPUSWITCH1, (uint32_t)(val >> 32));
#elif __RISCV_XLEN == 64
__RV_CSR_WRITE(CSR_SMPUSWITCH0, val);
#else
// TODO Add RV128 Handling
#endif
}
/**
* \brief Get SMPU each entry's on/off status
* \details Get the value of the SMPUSWITCHx Register.
* \remark
* - Each bit of this register holds on/off status of the corresponding SMPU entry respectively.
* - An SMPU entry is activated only when both corresponding bits in smpuswitch and
* A field of smpuicfg are set. (i.e., smpuswitch[i] & smpu[i]cfg.A).
*/
__STATIC_INLINE uint64_t __get_SMPUSWITCHx(void)
{
#if __RISCV_XLEN == 32
uint32_t lo, hi = 0;
lo = __RV_CSR_READ(CSR_SMPUSWITCH0);
hi = __RV_CSR_READ(CSR_SMPUSWITCH1);
return (uint64_t)((((uint64_t)hi) << 32) | lo);
#elif __RISCV_XLEN == 64
return (uint64_t)__RV_CSR_READ(CSR_SMPUSWITCH0);
#else
// TODO Add RV128 Handling
#endif
}
#endif
/** @} */ /* End of Doxygen Group NMSIS_Core_SPMP_Functions */
#endif /* defined(__SPMP_PRESENT) && (__SPMP_PRESENT == 1) */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_FEATURE_SPMP_H__ */
@@ -0,0 +1,683 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_TIMER_H__
#define __CORE_FEATURE_TIMER_H__
/*!
* @file core_feature_timer.h
* @brief System Timer feature API header file for Nuclei N/NX Core
*/
/*
* System Timer Feature Configuration Macro:
* 1. __SYSTIMER_PRESENT: Must, Define whether Private System Timer is present or not.
* * 0: Not present
* * 1: Present
* 2. __SYSTIMER_BASEADDR: Must, Define the base address of the System Timer.
* 3. __SYSTIMER_HARTID: Optional, Define the system timer hart index of the cpu, important for case when cpu hartid and cpu hart index are different, only set it if your cpu is single core.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "core_feature_base.h"
#if defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1)
/**
* \defgroup NMSIS_Core_SysTimer_Registers Register Define and Type Definitions Of System Timer
* \ingroup NMSIS_Core_Registers
* \brief Type definitions and defines for system timer registers.
*
* @{
*/
/**
* \brief Structure type to access the System Timer (SysTimer).
* \details
* Structure definition to access the system timer(SysTimer).
* \remarks
* - MSFTRST register is introduced in Nuclei N Core version 1.3(\ref __NUCLEI_N_REV >= 0x0103)
* - MSTOP register is renamed to MTIMECTL register in Nuclei N Core version 1.4(\ref __NUCLEI_N_REV >= 0x0104)
* - CMPCLREN and CLKSRC bit in MTIMECTL register is introduced in Nuclei N Core version 1.4(\ref __NUCLEI_N_REV >= 0x0104)
*/
typedef struct {
__IOM uint64_t MTIMER; /*!< Offset: 0x000 (R/W) System Timer current value 64bits Register */
__IOM uint64_t MTIMERCMP; /*!< Offset: 0x008 (R/W) System Timer compare Value 64bits Register */
__IOM uint32_t RESERVED0[0x3F8]; /*!< Offset: 0x010 - 0xFEC Reserved */
__IOM uint32_t MSFTRST; /*!< Offset: 0xFF0 (R/W) System Timer Software Core Reset Register */
__IOM uint32_t RESERVED1; /*!< Offset: 0xFF4 Reserved */
__IOM uint32_t MTIMECTL; /*!< Offset: 0xFF8 (R/W) System Timer Control Register, previously MSTOP register */
__IOM uint32_t MSIP; /*!< Offset: 0xFFC (R/W) System Timer SW interrupt Register */
} SysTimer_Type;
/* Timer Control / Status Register Definitions */
#define SysTimer_MTIMECTL_TIMESTOP_Pos 0U /*!< SysTick Timer MTIMECTL: TIMESTOP bit Position */
#define SysTimer_MTIMECTL_TIMESTOP_Msk (1UL << SysTimer_MTIMECTL_TIMESTOP_Pos) /*!< SysTick Timer MTIMECTL: TIMESTOP Mask */
#define SysTimer_MTIMECTL_CMPCLREN_Pos 1U /*!< SysTick Timer MTIMECTL: CMPCLREN bit Position */
#define SysTimer_MTIMECTL_CMPCLREN_Msk (1UL << SysTimer_MTIMECTL_CMPCLREN_Pos) /*!< SysTick Timer MTIMECTL: CMPCLREN Mask */
#define SysTimer_MTIMECTL_CLKSRC_Pos 2U /*!< SysTick Timer MTIMECTL: CLKSRC bit Position */
#define SysTimer_MTIMECTL_CLKSRC_Msk (1UL << SysTimer_MTIMECTL_CLKSRC_Pos) /*!< SysTick Timer MTIMECTL: CLKSRC Mask */
#define SysTimer_MSIP_MSIP_Pos 0U /*!< SysTick Timer MSIP: MSIP bit Position */
#define SysTimer_MSIP_MSIP_Msk (1UL << SysTimer_MSIP_MSIP_Pos) /*!< SysTick Timer MSIP: MSIP Mask */
#define SysTimer_MTIMER_Msk (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMER value Mask */
#define SysTimer_MTIMERCMP_Msk (0xFFFFFFFFFFFFFFFFULL) /*!< SysTick Timer MTIMERCMP value Mask */
#define SysTimer_MTIMECTL_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MTIMECTL/MSTOP value Mask */
#define SysTimer_MSIP_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MSIP value Mask */
#define SysTimer_MSFTRST_Msk (0xFFFFFFFFUL) /*!< SysTick Timer MSFTRST value Mask */
#define SysTimer_MSFRST_KEY (0x80000A5FUL) /*!< SysTick Timer Software Reset Request Key */
#define SysTimer_CLINT_MSIP_OFS (0x1000UL) /*!< Software interrupt register offset of clint mode in SysTick Timer */
#define SysTimer_CLINT_MTIMECMP_OFS (0x5000UL) /*!< MTIMECMP register offset of clint mode in SysTick Timer */
#define SysTimer_CLINT_MTIME_OFS (0xCFF8UL) /*!< MTIME register offset of clint mode in SysTick Timer */
#ifndef __SYSTIMER_BASEADDR
/* Base address of SYSTIMER(__SYSTIMER_BASEADDR) should be defined in <Device.h> */
#error "__SYSTIMER_BASEADDR is not defined, please check!"
#endif
/* System Timer Memory mapping of Device */
#define SysTimer_BASE __SYSTIMER_BASEADDR /*!< SysTick Base Address */
#define SysTimer ((SysTimer_Type *) SysTimer_BASE) /*!< SysTick configuration struct */
/* System Timer Clint register base */
#define SysTimer_CLINT_MSIP_BASE(hartid) (unsigned long)((SysTimer_BASE) + (SysTimer_CLINT_MSIP_OFS) + ((hartid) << 2))
#define SysTimer_CLINT_MTIMECMP_BASE(hartid) (unsigned long)((SysTimer_BASE) + (SysTimer_CLINT_MTIMECMP_OFS) + ((hartid) << 3))
#define SysTimer_CLINT_MTIME_BASE (unsigned long)((SysTimer_BASE) + (SysTimer_CLINT_MTIME_OFS))
/** @} */ /* end of group NMSIS_Core_SysTimer_Registers */
/* ################################## SysTimer function ############################################ */
/**
* \defgroup NMSIS_Core_SysTimer SysTimer Functions
* \brief Functions that configure the Core System Timer.
* @{
*/
/**
* SysTimer_GetHartID() is used to get timer hartid which might not be the same as cpu hart id,
* for example, cpu hartid may be 1, but timer hartid may be 0, then timer hartid offset is 1.
* If defined __SYSTIMER_HARTID, it will use __SYSTIMER_HARTID as timer hartid,
* otherwise, it will use __get_hart_index().
* The cpu hartid is get by using __get_hart_id function
*/
#ifndef __SYSTIMER_HARTID
#define SysTimer_GetHartID() (__get_hart_index())
#else
#define SysTimer_GetHartID() (__SYSTIMER_HARTID)
#endif
/**
* \brief Set system timer load value
* \details
* This function set the system timer load value in MTIMER register.
* \param [in] value value to set system timer MTIMER register.
* \remarks
* - Load value is 64bits wide.
* - \ref SysTimer_GetLoadValue
*/
__STATIC_FORCEINLINE void SysTimer_SetLoadValue(uint64_t value)
{
#if __RISCV_XLEN == 32
uint8_t *addr;
addr = (uint8_t *)(&(SysTimer->MTIMER));
__SW(addr, 0); // prevent carry
__SW(addr + 4, (uint32_t)(value >> 32));
__SW(addr, (uint32_t)(value));
#else
SysTimer->MTIMER = value;
#endif
}
/**
* \brief Get system timer load value
* \details
* This function get the system timer current value in MTIMER register.
* \return current value(64bit) of system timer MTIMER register.
* \remarks
* - Load value is 64bits wide.
* - \ref SysTimer_SetLoadValue
*/
__STATIC_FORCEINLINE uint64_t SysTimer_GetLoadValue(void)
{
#if __RISCV_XLEN == 32
volatile uint32_t high0, low, high;
uint64_t full;
uint8_t *addr;
addr = (uint8_t *)(&(SysTimer->MTIMER));
high0 = __LW(addr + 4);
low = __LW(addr);
high = __LW(addr + 4);
if (high0 != high) {
low = __LW(addr);
}
full = (((uint64_t)high) << 32) | low;
return full;
#else
return SysTimer->MTIMER;
#endif
}
/**
* \brief Set system timer compare value by hartid
* \details
* This function set the system Timer compare value in MTIMERCMP register.
* \param [in] value compare value to set system timer MTIMERCMP register.
* \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
* \remarks
* - Compare value is 64bits wide.
* - If compare value is larger than current value timer interrupt generate.
* - Modify the load value or compare value less to clear the interrupt.
* - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
* - \ref SysTimer_GetHartCompareValue
*/
__STATIC_FORCEINLINE void SysTimer_SetHartCompareValue(uint64_t value, unsigned long hartid)
{
if (hartid == 0) {
#if __RISCV_XLEN == 32
uint8_t *addr;
addr = (uint8_t *)(&(SysTimer->MTIMERCMP));
__SW(addr, -1U); // prevent load > timecmp
__SW(addr + 4, (uint32_t)(value >> 32));
__SW(addr, (uint32_t)(value));
#else
SysTimer->MTIMERCMP = value;
#endif
} else {
uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MTIMECMP_BASE(hartid));
#if __RISCV_XLEN == 32
__SW(addr, -1U); // prevent load > timecmp
__SW(addr + 4, (uint32_t)(value >> 32));
__SW(addr, (uint32_t)value);
#else
__SD(addr, value);
#endif
}
}
/**
* \brief Set system timer compare value in machine mode
* \details
* This function set the system Timer compare value in MTIMERCMP register.
* \param [in] value compare value to set system timer MTIMERCMP register.
* \remarks
* - Compare value is 64bits wide.
* - If compare value is larger than current value timer interrupt generate.
* - Modify the load value or compare value less to clear the interrupt.
* - __get_hart_id function can only be accessed in machine mode, or else exception will occur.
* - \ref SysTimer_GetCompareValue
*/
__STATIC_FORCEINLINE void SysTimer_SetCompareValue(uint64_t value)
{
unsigned long hartid = SysTimer_GetHartID();
SysTimer_SetHartCompareValue(value, hartid);
}
/**
* \brief Get system timer compare value by hartid
* \details
* This function get the system timer compare value in MTIMERCMP register.
* \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
* \return compare value of system timer MTIMERCMP register.
* \remarks
* - Compare value is 64bits wide.
* - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
* - \ref SysTimer_SetHartCompareValue
*/
__STATIC_FORCEINLINE uint64_t SysTimer_GetHartCompareValue(unsigned long hartid)
{
if (hartid == 0) {
return SysTimer->MTIMERCMP;
} else {
uint64_t full;
uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MTIMECMP_BASE(hartid));
#if __RISCV_XLEN == 32
// MTIMECMP didn't increase
uint32_t high, low;
high = __LW(addr + 4);
low = __LW(addr);
full = (((uint64_t)high) << 32) | low;
#else
full = __LD(addr);
#endif
return full;
}
}
/**
* \brief Get system timer compare value in machine mode
* \details
* This function get the system timer compare value in MTIMERCMP register.
* \return compare value of system timer MTIMERCMP register.
* \remarks
* - Compare value is 64bits wide.
* - \ref SysTimer_SetCompareValue
*/
__STATIC_FORCEINLINE uint64_t SysTimer_GetCompareValue(void)
{
unsigned long hartid = SysTimer_GetHartID();
return SysTimer_GetHartCompareValue(hartid);
}
/**
* \brief Enable system timer counter running
* \details
* Enable system timer counter running by clear
* TIMESTOP bit in MTIMECTL register.
*/
__STATIC_FORCEINLINE void SysTimer_Start(void)
{
SysTimer->MTIMECTL &= ~(SysTimer_MTIMECTL_TIMESTOP_Msk);
}
/**
* \brief Stop system timer counter running
* \details
* Stop system timer counter running by set
* TIMESTOP bit in MTIMECTL register.
*/
__STATIC_FORCEINLINE void SysTimer_Stop(void)
{
SysTimer->MTIMECTL |= SysTimer_MTIMECTL_TIMESTOP_Msk;
}
/**
* \brief Set system timer control value
* \details
* This function set the system timer MTIMECTL register value.
* \param [in] mctl value to set MTIMECTL register
* \remarks
* - Bit TIMESTOP is used to start and stop timer.
* Clear TIMESTOP bit to 0 to start timer, otherwise to stop timer.
* - Bit CMPCLREN is used to enable auto MTIMER clear to zero when MTIMER >= MTIMERCMP.
* Clear CMPCLREN bit to 0 to stop auto clear MTIMER feature, otherwise to enable it.
* - Bit CLKSRC is used to select timer clock source.
* Clear CLKSRC bit to 0 to use *mtime_toggle_a*, otherwise use *core_clk_aon*
* - \ref SysTimer_GetControlValue
*/
__STATIC_FORCEINLINE void SysTimer_SetControlValue(uint32_t mctl)
{
SysTimer->MTIMECTL = (mctl & SysTimer_MTIMECTL_Msk);
}
/**
* \brief Get system timer control value
* \details
* This function get the system timer MTIMECTL register value.
* \return MTIMECTL register value
* \remarks
* - \ref SysTimer_SetControlValue
*/
__STATIC_FORCEINLINE uint32_t SysTimer_GetControlValue(void)
{
return (SysTimer->MTIMECTL & SysTimer_MTIMECTL_Msk);
}
/**
* \brief Trigger or set software interrupt via system timer by hartid
* \details
* This function set the system timer MSIP bit in MSIP register.
* \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
* \remarks
* - Set system timer MSIP bit and generate a SW interrupt.
* - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
* - \ref SysTimer_ClearHartSWIRQ
* - \ref SysTimer_GetHartMsipValue
*/
__STATIC_FORCEINLINE void SysTimer_SetHartSWIRQ(unsigned long hartid)
{
if (hartid == 0) {
SysTimer->MSIP |= SysTimer_MSIP_MSIP_Msk;
} else {
uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
__SW(addr, SysTimer_MSIP_MSIP_Msk);
}
}
/**
* \brief Trigger or set software interrupt via system timer in machine mode
* \details
* This function set the system timer MSIP bit in MSIP register.
* \remarks
* - Set system timer MSIP bit and generate a SW interrupt.
* - \ref SysTimer_ClearSWIRQ
* - \ref SysTimer_GetMsipValue
*/
__STATIC_FORCEINLINE void SysTimer_SetSWIRQ(void)
{
unsigned long hartid = SysTimer_GetHartID();
SysTimer_SetHartSWIRQ(hartid);
}
/**
* \brief Clear system timer software interrupt pending request by hartid
* \details
* This function clear the system timer MSIP bit in MSIP register.
* \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
* \remarks
* - Clear system timer MSIP bit in MSIP register to clear the software interrupt pending.
* - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
* - \ref SysTimer_SetHartSWIRQ
* - \ref SysTimer_GetHartMsipValue
*/
__STATIC_FORCEINLINE void SysTimer_ClearHartSWIRQ(unsigned long hartid)
{
if (hartid == 0) {
SysTimer->MSIP &= ~SysTimer_MSIP_MSIP_Msk;
} else {
uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
__SW(addr, 0);
}
}
/**
* \brief Clear system timer software interrupt pending request in machine mode
* \details
* This function clear the system timer MSIP bit in MSIP register.
* \remarks
* - Clear system timer MSIP bit in MSIP register to clear the software interrupt pending.
* - \ref SysTimer_SetSWIRQ
* - \ref SysTimer_GetMsipValue
*/
__STATIC_FORCEINLINE void SysTimer_ClearSWIRQ(void)
{
unsigned long hartid = SysTimer_GetHartID();
SysTimer_ClearHartSWIRQ(hartid);
}
/**
* \brief Get system timer MSIP register value by hartid
* \details
* This function get the system timer MSIP register value.
* \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
* \return Value of Timer MSIP register.
* \remarks
* - Bit0 is SW interrupt flag.
* Bit0 is 1 then SW interrupt set. Bit0 is 0 then SW interrupt clear.
* - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
* - \ref SysTimer_SetHartSWIRQ
* - \ref SysTimer_ClearHartSWIRQ
* - \ref SysTimer_SetHartMsipValue
*/
__STATIC_FORCEINLINE uint32_t SysTimer_GetHartMsipValue(unsigned long hartid)
{
if (hartid == 0) {
return (uint32_t)(SysTimer->MSIP & SysTimer_MSIP_Msk);
} else {
uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
return __LW(addr);
}
}
/**
* \brief Get system timer MSIP register value in machine mode
* \details
* This function get the system timer MSIP register value.
* \return Value of Timer MSIP register.
* \remarks
* - Bit0 is SW interrupt flag.
* Bit0 is 1 then SW interrupt set. Bit0 is 0 then SW interrupt clear.
* - \ref SysTimer_SetSWIRQ
* - \ref SysTimer_ClearSWIRQ
* - \ref SysTimer_SetMsipValue
*/
__STATIC_FORCEINLINE uint32_t SysTimer_GetMsipValue(void)
{
unsigned long hartid = SysTimer_GetHartID();
return SysTimer_GetHartMsipValue(hartid);
}
/**
* \brief Set system timer MSIP register value by hartid
* \details
* This function set the system timer MSIP register value.
* \param [in] msip value to set MSIP register
* \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
* \remarks
* - In S-mode, hartid can't be get using __get_hart_id function, so this api suits S-mode particularly.
* - \ref SysTimer_GetHartMsipValue
*/
__STATIC_FORCEINLINE void SysTimer_SetHartMsipValue(uint32_t msip, unsigned long hartid)
{
if (hartid == 0) {
SysTimer->MSIP = (msip & SysTimer_MSIP_Msk);
} else {
uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
__SW(addr, msip);
}
}
/**
* \brief Set system timer MSIP register value in machine mode
* \details
* This function set the system timer MSIP register value.
* \param [in] msip value to set MSIP register
* - \ref SysTimer_GetMsipValue
*/
__STATIC_FORCEINLINE void SysTimer_SetMsipValue(uint32_t msip)
{
unsigned long hartid = SysTimer_GetHartID();
SysTimer_SetHartMsipValue(msip, hartid);
}
/**
* \brief Do software reset request
* \details
* This function will do software reset request through MTIMER
* - Software need to write \ref SysTimer_MSFRST_KEY to generate software reset request
* - The software request flag can be cleared by reset operation to clear
* \remarks
* - The software reset is sent to SoC, SoC need to generate reset signal and send back to Core
* - This function will not return, it will do while(1) to wait the Core reset happened
*/
__STATIC_FORCEINLINE void SysTimer_SoftwareReset(void)
{
SysTimer->MSFTRST = SysTimer_MSFRST_KEY;
// will reset cpu, never return
while (1);
}
/**
* \brief send ipi to target hart using Systimer Clint
* \details
* This function send ipi using clint timer.
* \param [in] hart target hart
*/
__STATIC_FORCEINLINE void SysTimer_SendIPI(unsigned long hartid)
{
uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
__SW(addr, 1);
}
/**
* \brief clear ipi to target hart using Systimer Clint
* \details
* This function clear ipi using Systimer clint timer.
* \param [in] hart target hart
*/
__STATIC_FORCEINLINE void SysTimer_ClearIPI(unsigned long hartid)
{
uint8_t *addr = (uint8_t *)(SysTimer_CLINT_MSIP_BASE(hartid));
__SW(addr, 0);
}
#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) && defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
/**
* \brief System Tick Configuration
* \details Initializes the System Timer and its non-vector interrupt, and starts the System Tick Timer.
*
* In our default implementation, the timer counter will be set to zero, and it will start a timer compare non-vector interrupt
* when it matchs the ticks user set, during the timer interrupt user should reload the system tick using \ref SysTick_Reload function
* or similar function written by user, so it can produce period timer interrupt.
* \param [in] ticks Number of ticks between two interrupts.
* \return 0 Function succeeded.
* \return 1 Function failed.
* \remarks
* - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
* but we assume that the CMPCLREN bit is set to 0, so MTIMER register will not be
* auto cleared to 0 when MTIMER >= MTIMERCMP.
* - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
* function \ref SysTick_Config is not included.
* - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
* of this function.
* - If user need this function to start a period timer interrupt, then in timer interrupt handler
* routine code, user should call \ref SysTick_Reload with ticks to reload the timer.
* - This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0
* \sa
* - \ref SysTimer_SetCompareValue; SysTimer_SetLoadValue
*/
__STATIC_INLINE uint32_t SysTick_Config(uint64_t ticks)
{
uint64_t loadticks = SysTimer_GetLoadValue();
SysTimer_SetCompareValue(ticks + loadticks);
ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
ECLIC_SetLevelIRQ(SysTimer_IRQn, 0);
ECLIC_EnableIRQ(SysTimer_IRQn);
return (0UL);
}
/**
* \brief System Tick Configuration By hartid
* \details Initializes the System Timer and its non-vector interrupt, and starts the System Tick Timer.
*
* In our default implementation, the timer counter will be set to zero, and it will start a timer compare non-vector interrupt
* when it matchs the ticks user set, during the timer interrupt user should reload the system tick using \ref SysTick_Reload function
* or similar function written by user, so it can produce period timer interrupt.
* \param [in] ticks Number of ticks between two interrupts.
* \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
* \return 0 Function succeeded.
* \return 1 Function failed.
* \remarks
* - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
* but we assume that the CMPCLREN bit is set to 0, so MTIMER register will not be
* auto cleared to 0 when MTIMER >= MTIMERCMP.
* - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
* function \ref SysTick_Config is not included.
* - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
* of this function.
* - If user need this function to start a period timer interrupt, then in timer interrupt handler
* routine code, user should call \ref SysTick_Reload with ticks to reload the timer.
* - This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0
* - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
* \sa
* - \ref SysTimer_SetCompareValue; SysTimer_SetLoadValue
*/
__STATIC_INLINE uint32_t SysTick_HartConfig(uint64_t ticks, unsigned long hartid)
{
uint64_t loadticks = SysTimer_GetLoadValue();
SysTimer_SetHartCompareValue(ticks + loadticks, hartid);
ECLIC_SetShvIRQ(SysTimer_IRQn, ECLIC_NON_VECTOR_INTERRUPT);
ECLIC_SetLevelIRQ(SysTimer_IRQn, 0);
ECLIC_EnableIRQ(SysTimer_IRQn);
return (0UL);
}
/**
* \brief System Tick Reload
* \details Reload the System Timer Tick when the MTIMECMP reached TIME value
*
* \param [in] ticks Number of ticks between two interrupts.
* \return 0 Function succeeded.
* \return 1 Function failed.
* \remarks
* - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
* but for this \ref SysTick_Config function, we assume this CMPCLREN bit is set to 0,
* so in interrupt handler function, user still need to set the MTIMERCMP or MTIMER to reload
* the system tick, if vendor want to use this timer's auto clear feature, they can define
* \ref __Vendor_SysTickConfig to 1, and implement \ref SysTick_Config and \ref SysTick_Reload functions.
* - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
* function \ref SysTick_Reload is not included.
* - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
* of this function.
* - This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0
* - Since the MTIMERCMP value might overflow, if overflowed, MTIMER will be set to 0, and MTIMERCMP set to ticks
* \sa
* - \ref SysTimer_SetCompareValue
* - \ref SysTimer_SetLoadValue
*/
__STATIC_FORCEINLINE uint32_t SysTick_Reload(uint64_t ticks)
{
uint64_t cur_ticks = SysTimer_GetLoadValue();
uint64_t reload_ticks = ticks + cur_ticks;
if (__USUALLY(reload_ticks > cur_ticks)) {
SysTimer_SetCompareValue(reload_ticks);
} else {
/* When added the ticks value, then the MTIMERCMP < TIMER,
* which means the MTIMERCMP is overflowed,
* so we need to reset the counter to zero */
SysTimer_SetLoadValue(0);
SysTimer_SetCompareValue(ticks);
}
return (0UL);
}
/**
* \brief System Tick Reload
* \details Reload the System Timer Tick when the MTIMECMP reached TIME value
*
* \param [in] ticks Number of ticks between two interrupts.
* \param [in] hartid hart ID, one hart is required to have a known hart ID of 0, other harts ID can be in 1~1023.
* \return 0 Function succeeded.
* \return 1 Function failed.
* \remarks
* - For \ref __NUCLEI_N_REV >= 0x0104, the CMPCLREN bit in MTIMECTL is introduced,
* but for this \ref SysTick_Config function, we assume this CMPCLREN bit is set to 0,
* so in interrupt handler function, user still need to set the MTIMERCMP or MTIMER to reload
* the system tick, if vendor want to use this timer's auto clear feature, they can define
* \ref __Vendor_SysTickConfig to 1, and implement \ref SysTick_Config and \ref SysTick_Reload functions.
* - When the variable \ref __Vendor_SysTickConfig is set to 1, then the
* function \ref SysTick_Reload is not included.
* - In this case, the file <b><Device>.h</b> must contain a vendor-specific implementation
* of this function.
* - This function only available when __SYSTIMER_PRESENT == 1 and __ECLIC_PRESENT == 1 and __Vendor_SysTickConfig == 0
* - Since the MTIMERCMP value might overflow, if overflowed, MTIMER will be set to 0, and MTIMERCMP set to ticks
* - In S-mode, hartid can't be get by using __get_hart_id function, so this api suits S-mode particularly.
* \sa
* - \ref SysTimer_SetCompareValue
* - \ref SysTimer_SetLoadValue
*/
__STATIC_FORCEINLINE uint32_t SysTick_HartReload(uint64_t ticks, unsigned long hartid)
{
uint64_t cur_ticks = SysTimer_GetLoadValue();
uint64_t reload_ticks = ticks + cur_ticks;
if (__USUALLY(reload_ticks > cur_ticks)) {
SysTimer_SetHartCompareValue(reload_ticks, hartid);
} else {
/* When added the ticks value, then the MTIMERCMP < TIMER,
* which means the MTIMERCMP is overflowed,
* so we need to reset the counter to zero */
SysTimer_SetLoadValue(0);
SysTimer_SetHartCompareValue(ticks, hartid);
}
return (0UL);
}
#endif /* defined(__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) */
/** @} */ /* End of Doxygen Group NMSIS_Core_SysTimer */
#endif /* defined(__SYSTIMER_PRESENT) && (__SYSTIMER_PRESENT == 1) */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_FEATURE_TIMER_H__ */
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CORE_FEATURE_VECTOR__
#define __CORE_FEATURE_VECTOR__
/*!
* @file core_feature_vector.h
* @brief Vector feature API header file for Nuclei N/NX Core
*/
/*
* Vector Feature Configuration Macro:
* 1. __VECTOR_PRESENT: Define whether Vector Unit is present or not
* * 0: Not present
* * 1: Present
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "core_feature_base.h"
#if defined(__VECTOR_PRESENT) && (__VECTOR_PRESENT == 1)
/* ########################### CPU Vector Intrinsic Functions ########################### */
/**
* \defgroup NMSIS_Core_Vector_Intrinsic Intrinsic Functions for Vector Instructions
* \ingroup NMSIS_Core
* \brief Functions that generate RISC-V Vector instructions.
* \details
*
* RISC-V Vector Intrinsic APIs are provided directly through compiler generated intrinsic function.
*
* This intrinsic function support by compiler:
*
* For Nuclei RISC-V GCC 10.2, it is an very old and not ratified version(no longer supported).
*
* - API header file can be found in lib/gcc/riscv-nuclei-elf/<gcc_ver>/include/riscv_vector.h
*
* For Nuclei RISC-V GCC 13/Clang 17, the intrinsic API supported is v0.12 version, see
* https://github.com/riscv-non-isa/rvv-intrinsic-doc/releases/tag/v0.12.0
*
* @{
*/
#if defined(__INC_INTRINSIC_API) && (__INC_INTRINSIC_API == 1)
#include <riscv_vector.h>
#endif
/**
* \brief Enable Vector Unit
* \details
* Set vector context status bits to enable vector unit,
* and set state to initial
*/
__STATIC_FORCEINLINE void __enable_vector(void)
{
__RV_CSR_CLEAR(CSR_MSTATUS, MSTATUS_VS);
__RV_CSR_SET(CSR_MSTATUS, MSTATUS_VS_INITIAL);
}
/**
* \brief Disable Vector Unit
* \details
* Clear vector context status bits to disable vector unit
*/
__STATIC_FORCEINLINE void __disable_vector(void)
{
__RV_CSR_CLEAR(CSR_MSTATUS, MSTATUS_VS);
}
/** @} */ /* End of Doxygen Group NMSIS_Core_Vector_Intrinsic */
#endif /* defined(__VECTOR_PRESENT) && (__VECTOR_PRESENT == 1) */
#ifdef __cplusplus
}
#endif
#endif /* __CORE_FEATURE_VECTOR__ */
@@ -0,0 +1,289 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __NMSIS_BENCH__
#define __NMSIS_BENCH__
/*!
* @file nmsis_bench.h
* @brief benchmark and helper related API for Nuclei N/NX Core
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "core_feature_base.h"
#include <stdio.h>
/**
* \defgroup NMSIS_Core_Bench_Helpers NMSIS Bench and Test Related Helper Functions
* \ingroup NMSIS_Core
* \brief Functions that used to do benchmark and test suite.
* \details
*
* NMSIS benchmark and test related helper functions are provided to help do benchmark
* and test case pass/fail assertion.
*
* If you want to do calculate cpu cycle cost of a process, you can use BENCH_xxx macros
* defined in this.
*
* In a single c source code file, you should include `nmsis_bench.h`, and then you should place `BENCH_DECLARE_VAR();`
* before call other BENCH_xxx macros. If you want to start to do benchmark, you should only call `BENCH_INIT();`
* once in your source code, and then place `BENCH_START(proc_name);` and `BENCH_END(proc_name)` before
* and after the process you want to measure. You can refer to `<nuclei-sdk>/application/baremetal/demo_dsp`
* for how to use it.
*
* If you want to disable the benchmark calculation, you can place `#define DISABLE_NMSIS_BENCH`
* before include `nmsis_bench.h`
*
* If in your c test source code, you can add `NMSIS_TEST_PASS();` and `NMSIS_TEST_FAIL();` to mark c test
* is pass or fail.
*
* @{
*/
/**
* \brief Prepare benchmark environment
* \details
* Prepare benchmark required environment, such as turn on necessary units
* like vpu, cycle, instret counters, hpm counters
*/
__STATIC_FORCEINLINE void __prepare_bench_env(void)
{
#ifdef __riscv_vector
__RV_CSR_SET(CSR_MSTATUS, MSTATUS_VS);
#endif
__enable_all_counter();
}
#ifndef READ_CYCLE
/** Read run cycle of cpu */
#define READ_CYCLE __get_rv_cycle
#endif
#ifndef DISABLE_NMSIS_BENCH
/** Declare benchmark required variables, need to be placed above all BENCH_xxx macros in each c source code if BENCH_xxx used */
#define BENCH_DECLARE_VAR() static volatile uint64_t _bc_sttcyc, _bc_endcyc, _bc_usecyc, _bc_sumcyc, _bc_lpcnt, _bc_ercd;
/** Initialize benchmark environment, need to called in before other BENCH_xxx macros are called */
#define BENCH_INIT() printf("Benchmark initialized\n"); \
__prepare_bench_env(); \
_bc_ercd = 0; _bc_sumcyc = 0;
/** Reset benchmark sum cycle and use cycle for proc */
#define BENCH_RESET(proc) _bc_sumcyc = 0; _bc_usecyc = 0; _bc_lpcnt = 0; _bc_ercd = 0;
/** Start to do benchmark for proc, and record start cycle, and reset error code */
#define BENCH_START(proc) _bc_ercd = 0; \
_bc_sttcyc = READ_CYCLE();
/** Sample a benchmark for proc, and record this start -> sample cost cycle, and accumulate it to sum cycle */
#define BENCH_SAMPLE(proc) _bc_endcyc = READ_CYCLE(); \
_bc_usecyc = _bc_endcyc - _bc_sttcyc; \
_bc_sumcyc += _bc_usecyc; _bc_lpcnt += 1;
/** Mark end of benchmark for proc, and calc used cycle, and print it */
#define BENCH_END(proc) BENCH_SAMPLE(proc); \
printf("CSV, %s, %lu\n", #proc, (unsigned long)_bc_usecyc);
/** Mark stop of benchmark, start -> sample -> sample -> stop, and print the sum cycle of a proc */
#define BENCH_STOP(proc) printf("CSV, %s, %lu\n", #proc, (unsigned long)_bc_sumcyc);
/** Show statistics of benchmark, format: STAT, proc, loopcnt, sumcyc */
#define BENCH_STAT(proc) printf("STAT, %s, %lu, %lu\n", #proc, (unsigned long)_bc_lpcnt, (unsigned long)_bc_sumcyc);
/** Get benchmark use cycle */
#define BENCH_GET_USECYC() (_bc_usecyc)
/** Get benchmark sum cycle */
#define BENCH_GET_SUMCYC() (_bc_sumcyc)
/** Get benchmark loop count */
#define BENCH_GET_LPCNT() (_bc_lpcnt)
/** Mark benchmark for proc is errored */
#define BENCH_ERROR(proc) _bc_ercd = 1;
/** Show the status of the benchmark */
#define BENCH_STATUS(proc) if (_bc_ercd) { \
printf("ERROR, %s\n", #proc); \
} else { \
printf("SUCCESS, %s\n", #proc); \
}
#else
#define BENCH_DECLARE_VAR() static volatile uint64_t _bc_ercd, _bc_lpcnt;
#define BENCH_INIT() _bc_ercd = 0; __prepare_bench_env();
#define BENCH_RESET(proc)
#define BENCH_START(proc) _bc_ercd = 0;
#define BENCH_SAMPLE(proc) _bc_lpcnt += 1;
#define BENCH_END(proc)
#define BENCH_STOP(proc)
#define BENCH_STAT(proc)
#define BENCH_GET_USECYC() (0)
#define BENCH_GET_SUMCYC() (0)
#define BENCH_GET_LPCNT() (_bc_lpcnt)
#define BENCH_ERROR(proc) _bc_ercd = 1;
#define BENCH_STATUS(proc) if (_bc_ercd) { \
printf("ERROR, %s\n", #proc); \
} else { \
printf("SUCCESS, %s\n", #proc); \
}
#endif
// High performance monitor bench helpers
#ifndef DISABLE_NMSIS_HPM
/* Events type select */
#define EVENT_SEL_INSTRUCTION_COMMIT 0
#define EVENT_SEL_MEMORY_ACCESS 1
/* Instruction commit events idx define*/
#define EVENT_INSTRUCTION_COMMIT_CYCLE_COUNT 1
#define EVENT_INSTRUCTION_COMMIT_RETIRED_COUNT 2
/* Integer load instruction (includes LR) */
#define EVENT_INSTRUCTION_COMMIT_INTEGER_LOAD 3
/* Integer store instruction (includes SC) */
#define EVENT_INSTRUCTION_COMMIT_INTEGER_STORE 4
/* Atomic memory operation (do not include LR and SC) */
#define EVENT_INSTRUCTION_COMMIT_ATOMIC_MEMORY_OPERATION 5
/* System instruction */
#define EVENT_INSTRUCTION_COMMIT_SYSTEM 6
/* Integer computational instruction (excluding multiplication/division/remainder) */
#define EVENT_INSTRUCTION_COMMIT_INTEGER_COMPUTATIONAL 7
#define EVENT_INSTRUCTION_COMMIT_CONDITIONAL_BRANCH 8
#define EVENT_INSTRUCTION_COMMIT_TAKEN_CONDITIONAL_BRANCH 9
#define EVENT_INSTRUCTION_COMMIT_JAL 10
#define EVENT_INSTRUCTION_COMMIT_JALR 11
#define EVENT_INSTRUCTION_COMMIT_RETURN 12
/* Control transfer instruction (CBR+JAL+JALR) */
#define EVENT_INSTRUCTION_COMMIT_CONTROL_TRANSFER 13
/* 14 Reseved */
#define EVENT_INSTRUCTION_COMMIT_INTEGER_MULTIPLICATION 15
/* Integer division/remainder instruction */
#define EVENT_INSTRUCTION_COMMIT_INTEGER_DIVISION_REMAINDER 16
#define EVENT_INSTRUCTION_COMMIT_FLOATING_POINT_LOAD 17
#define EVENT_INSTRUCTION_COMMIT_FLOATING_POINT_STORE 18
/* Floating-point addition/subtraction */
#define EVENT_INSTRUCTION_COMMIT_FLOATING_POINT_ADDITION_SUBTRACTION 19
#define EVENT_INSTRUCTION_COMMIT_FLOATING_POINT_MULTIPLICATION 20
/* Floating-point fused multiply-add (FMADD, FMSUB, FNMSUB, FNMADD) */
#define EVENT_INSTRUCTION_COMMIT_FLOATING_POINT_FUSED_MULTIPLY_ADD_SUB 21
#define EVENT_INSTRUCTION_COMMIT_FLOATING_POINT_DIVISION_OR_SQUARE_ROOT 22
#define EVENT_INSTRUCTION_COMMIT_OTHER_FLOATING_POINT_INSTRUCTION 23
#define EVENT_INSTRUCTION_COMMIT_CONDITIONAL_BRANCH_PREDICTION_FAIL 24
#define EVENT_INSTRUCTION_COMMIT_JAL_PREDICTION_FAIL 25
#define EVENT_INSTRUCTION_COMMIT_JALR_PREDICTION_FAIL 26
/* Memory access events idx define*/
#define EVENT_MEMORY_ACCESS_ICACHE_MISS 1
#define EVENT_MEMORY_ACCESS_DCACHE_MISS 2
#define EVENT_MEMORY_ACCESS_ITLB_MISS 3
#define EVENT_MEMORY_ACCESS_DTLB_MISS 4
#define EVENT_MEMORY_ACCESS_MAIN_DTLB_MISS 5
/* Enable the corresponding performance monitor counter increment for events in Machine/Supervisor/User Mode */
#define MSU_EVENT_ENABLE 0x0F
#define MEVENT_EN 0x08
#define SEVENT_EN 0x02
#define UEVENT_EN 0x01
/** Declare high performance monitor counter idx benchmark required variables, need to be placed above all HPM_xxx macros in each c source code if HPM_xxx used */
#define HPM_DECLARE_VAR(idx) static volatile uint64_t __hpm_sttcyc##idx, __hpm_endcyc##idx, __hpm_usecyc##idx, __hpm_sumcyc##idx, __hpm_lpcnt##idx, __hpm_val##idx;
#define HPM_SEL_ENABLE(ena) (ena << 28)
#define HPM_SEL_EVENT(sel, idx) ((sel) | (idx << 4))
/** Construct a event variable to be set(sel -> event_sel, idx -> event_idx, ena -> m/s/u_enable) */
#define HPM_EVENT(sel, idx, ena) (HPM_SEL_ENABLE(ena) | HPM_SEL_EVENT(sel, idx))
/** Initialize high performance monitor environment, need to called in before other HPM_xxx macros are called */
#define HPM_INIT() printf("High performance monitor initialized\n"); \
__prepare_bench_env();
/** Reset high performance benchmark for proc using counter which index is idx */
#define HPM_RESET(idx, proc, event) __hpm_sumcyc##idx = 0; __hpm_lpcnt##idx = 0;
/** Start to do high performance benchmark for proc, and record start hpm counter */
#define HPM_START(idx, proc, event) \
__hpm_val##idx = (event); \
__set_hpm_event(idx, __hpm_val##idx); \
__set_hpm_counter(idx, 0); \
__hpm_sttcyc##idx = __get_hpm_counter(idx);
/** Do high performance benchmark sample for proc, and sum it into sum counter */
#define HPM_SAMPLE(idx, proc, event) \
__hpm_endcyc##idx = __get_hpm_counter(idx); \
__hpm_usecyc##idx = __hpm_endcyc##idx - __hpm_sttcyc##idx; \
__hpm_sumcyc##idx += __hpm_usecyc##idx; \
__hpm_lpcnt##idx += 1;
/** Mark end of high performance benchmark for proc, and calc used hpm counter value */
#define HPM_END(idx, proc, event) \
HPM_SAMPLE(idx, proc, event); \
printf("HPM%d:0x%x, %s, %lu\n", idx, event, #proc, (unsigned long)__hpm_usecyc##idx);
/** Mark stop of hpm benchmark, start -> sample -> sample -> stop, and print the sum cycle of a proc */
#define HPM_STOP(idx, proc, event) \
printf("HPM%d:0x%x, %s, %lu\n", idx, event, #proc, (unsigned long)__hpm_sumcyc##idx);
/** Show statistics of hpm benchmark, format: STATHPM#idx:event, proc, loopcnt, sumcyc */
#define HPM_STAT(idx, proc, event) \
printf("STATHPM%d:0x%x, %s, %lu, %lu\n", idx, event, #proc, (unsigned long)__hpm_lpcnt##idx, (unsigned long)__hpm_sumcyc##idx);
/** Get hpm benchmark use cycle for counter idx */
#define HPM_GET_USECYC(idx) (__hpm_usecyc##idx)
/** Get hpm benchmark sum cycle for counter idx */
#define HPM_GET_SUMCYC(idx) (__hpm_sumcyc##idx)
/** Get hpm benchmark loop count for counter idx */
#define HPM_GET_LPCNT(idx) (__hpm_lpcnt##idx)
#else
#define HPM_DECLARE_VAR(idx)
#define HPM_EVENT(sel, idx, ena)
#define HPM_INIT()
#define HPM_RESET(idx, proc, event)
#define HPM_START(idx, proc, event)
#define HPM_SAMPLE(idx, proc, event)
#define HPM_END(idx, proc, event)
#define HPM_STOP(idx, proc, event)
#define HPM_STAT(idx, proc, event)
#define HPM_GET_USECYC(idx) (0)
#define HPM_GET_SUMCYC(idx) (0)
#define HPM_GET_LPCNT(idx) (1)
#endif
// NMSIS Helpers
#ifndef DISABLE_NMSIS_HELPER
/** Mark test or application passed */
#define NMSIS_TEST_PASS() printf("\nNMSIS_TEST_PASS\n");
/** Mark test or application failed */
#define NMSIS_TEST_FAIL() printf("\nNMSIS_TEST_FAIL\n");
#else
#define NMSIS_TEST_PASS()
#define NMSIS_TEST_FAIL()
#endif
/** @} */ /* End of Doxygen Group NMSIS_Core_Bench_Helpers */
#ifdef __cplusplus
}
#endif
#endif /* __NMSIS_BENCH__ */
@@ -0,0 +1,105 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __NMSIS_COMPILER_H
#define __NMSIS_COMPILER_H
#include <stdint.h>
/*!
* @file nmsis_compiler.h
* @brief NMSIS compiler generic header file
*/
#if defined ( __GNUC__ )
/* GNU GCC Compiler */
#include "nmsis_gcc.h"
#elif defined ( __ICCRISCV__ )
/* IAR Compiler */
#include "nmsis_iar.h"
#else
#error Unknown compiler.
#endif
/* IO definitions (access restrictions to peripheral registers) */
/**
* \defgroup NMSIS_Core_PeriphAccess Peripheral Access
* \brief Naming conventions and optional features for accessing peripherals.
*
* The section below describes the naming conventions, requirements, and optional features
* for accessing device specific peripherals.
* Most of the rules also apply to the core peripherals.
*
* The **Device Header File <device.h>** contains typically these definition
* and also includes the core specific header files.
*
* @{
*/
/** \brief Defines 'read only' permissions */
#ifdef __cplusplus
#define __I volatile
#else
#define __I volatile const
#endif
/** \brief Defines 'write only' permissions */
#define __O volatile
/** \brief Defines 'read / write' permissions */
#define __IO volatile
/* following defines should be used for structure members */
/** \brief Defines 'read only' structure member permissions */
#define __IM volatile const
/** \brief Defines 'write only' structure member permissions */
#define __OM volatile
/** \brief Defines 'read/write' structure member permissions */
#define __IOM volatile
/**
* \brief Mask and shift a bit field value for use in a register bit range.
* \details The macro \ref _VAL2FLD uses the #define's _Pos and _Msk of the related bit
* field to shift bit-field values for assigning to a register.
*
* **Example**:
* \code
* ECLIC->CFG = _VAL2FLD(CLIC_CLICCFG_NLBIT, 3);
* \endcode
* \param[in] field Name of the register bit field.
* \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
* \return Masked and shifted value.
*/
#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
* \brief Mask and shift a register value to extract a bit filed value.
* \details The macro \ref _FLD2VAL uses the #define's _Pos and _Msk of the related bit
* field to extract the value of a bit field from a register.
*
* **Example**:
* \code
* nlbits = _FLD2VAL(CLIC_CLICCFG_NLBIT, ECLIC->CFG);
* \endcode
* \param[in] field Name of the register bit field.
* \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
* \return Masked and shifted bit field value.
*/
#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/** @} */ /* end of group NMSIS_Core_PeriphAccess */
#endif /* __NMSIS_COMPILER_H */
@@ -0,0 +1,111 @@
/*
* Copyright (c) 2009-2019 Arm Limited. All rights reserved.
* -- Adaptable modifications made for Nuclei Processors. --
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "nmsis_version.h"
/**
* \ingroup NMSIS_Core_VersionControl
* @{
*/
/* The following macro __NUCLEI_N_REV/__NUCLEI_NX_REV/
* __NUCLEI_CPU_REV/__NUCLEI_CPU_SERIES definition in this file
* is only used for doxygen documentation generation,
* The <Device>.h is the real file to define it by vendor
*/
#if defined(__ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__)
/**
* \brief Nuclei N class core revision number
* \details
* Reversion number format: [15:8] revision number, [7:0] patch number
* \attention
* Deprecated, this define is exclusive with \ref __NUCLEI_NX_REV
*/
#define __NUCLEI_N_REV (0x0309)
/**
* \brief Nuclei NX class core revision number
* \details
* Reversion number format: [15:8] revision number, [7:0] patch number
* \attention
* Deprecated, this define is exclusive with \ref __NUCLEI_N_REV
*/
#define __NUCLEI_NX_REV (0x0207)
/**
* \brief Nuclei CPU core revision number
* \details
* Nuclei RISC-V CPU Revision Number vX.Y.Z, eg. v3.10.1
* \attention
* This define is exclusive with \ref __NUCLEI_CPU_SERIES
*/
#define __NUCLEI_CPU_REV (0x030A01)
/**
* \brief Nuclei CPU core series
* \details
* Nuclei RISC-V CPU Series Number, eg, 0x200, 0x300, 0x600, 0x900
* for 200, 300, 600, 900 series.
* \attention
* This define is used together with \ref __NUCLEI_CPU_REV
*/
#define __NUCLEI_CPU_SERIES (0x0200)
#endif /* __ONLY_FOR_DOXYGEN_DOCUMENT_GENERATION__ */
/** @} */ /* End of Group NMSIS_Core_VersionControl */
#include "nmsis_compiler.h" /* NMSIS compiler specific defines */
/* === Include Nuclei Core Related Headers === */
/* Include core base feature header file */
#include "core_feature_base.h"
/* Include core fpu feature header file */
#include "core_feature_fpu.h"
/* Include core dsp feature header file */
#include "core_feature_dsp.h"
/* Include core vector feature header file */
#include "core_feature_vector.h"
/* Include core bitmanip feature header file */
#include "core_feature_bitmanip.h"
/* Include core pmp feature header file */
#include "core_feature_pmp.h"
/* Include core spmp feature header file */
#include "core_feature_spmp.h"
/* Include core cache feature header file */
#include "core_feature_cache.h"
/* Include core cidu feature header file */
#include "core_feature_cidu.h"
/* Include compatiable functions header file */
#include "core_compatiable.h"
#ifndef __NMSIS_GENERIC
/* Include core eclic feature header file */
#include "core_feature_eclic.h"
/* Include core plic feature header file */
#include "core_feature_plic.h"
/* Include core systimer feature header file */
#include "core_feature_timer.h"
#endif
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,210 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __NMSIS_GCC_H__
#define __NMSIS_GCC_H__
/*!
* @file nmsis_gcc.h
* @brief NMSIS compiler GCC header file
*/
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "riscv_encoding.h"
/* ######################### Startup and Lowlevel Init ######################## */
/**
* \defgroup NMSIS_Core_CompilerControl Compiler Control
* \ingroup NMSIS_Core
* \brief Compiler agnostic \#define symbols for generic c/c++ source code
* \details
*
* The NMSIS-Core provides the header file <b>nmsis_compiler.h</b> with consistent \#define symbols for generate C or C++ source files that should be compiler agnostic.
* Each NMSIS compliant compiler should support the functionality described in this section.
*
* The header file <b>nmsis_compiler.h</b> is also included by each Device Header File <device.h> so that these definitions are available.
* @{
*/
/* Fallback for __has_builtin */
#ifndef __has_builtin
#define __has_builtin(x) (0)
#endif
/* NMSIS compiler specific defines */
/** \brief Pass information from the compiler to the assembler. */
#ifndef __ASM
#define __ASM __asm
#endif
/** \brief Recommend that function should be inlined by the compiler. */
#ifndef __INLINE
#define __INLINE inline
#endif
/** \brief Define a static function that may be inlined by the compiler. */
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
/** \brief Define a static function that should be always inlined by the compiler. */
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
#endif
/** \brief Inform the compiler that a function does not return. */
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((__noreturn__))
#endif
/** \brief Inform that a variable shall be retained in executable image. */
#ifndef __USED
#define __USED __attribute__((used))
#endif
/** \brief restrict pointer qualifier to enable additional optimizations. */
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
/** \brief specified the vector size of the variable, measured in bytes */
#ifndef __VECTOR_SIZE
#define __VECTOR_SIZE(x) __attribute__((vector_size(x)))
#endif
/** \brief Request smallest possible alignment. */
#ifndef __PACKED
#define __PACKED __attribute__((packed, aligned(1)))
#endif
/** \brief Request smallest possible alignment for a structure. */
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
#endif
/** \brief Request smallest possible alignment for a union. */
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
#endif
#ifndef __UNALIGNED_UINT16_WRITE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked"
#pragma GCC diagnostic ignored "-Wattributes"
/** \brief Packed struct for unaligned uint16_t write access */
__PACKED_STRUCT T_UINT16_WRITE {
uint16_t v;
};
#pragma GCC diagnostic pop
/** \brief Pointer for unaligned write of a uint16_t variable. */
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked"
#pragma GCC diagnostic ignored "-Wattributes"
/** \brief Packed struct for unaligned uint16_t read access */
__PACKED_STRUCT T_UINT16_READ {
uint16_t v;
};
#pragma GCC diagnostic pop
/** \brief Pointer for unaligned read of a uint16_t variable. */
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked"
#pragma GCC diagnostic ignored "-Wattributes"
/** \brief Packed struct for unaligned uint32_t write access */
__PACKED_STRUCT T_UINT32_WRITE {
uint32_t v;
};
#pragma GCC diagnostic pop
/** \brief Pointer for unaligned write of a uint32_t variable. */
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked"
#pragma GCC diagnostic ignored "-Wattributes"
/** \brief Packed struct for unaligned uint32_t read access */
__PACKED_STRUCT T_UINT32_READ {
uint32_t v;
};
#pragma GCC diagnostic pop
/** \brief Pointer for unaligned read of a uint32_t variable. */
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
/** \brief Minimum `x` bytes alignment for a variable. */
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
/** \brief restrict pointer qualifier to enable additional optimizations. */
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
/** \brief Barrier to prevent compiler from reordering instructions. */
#ifndef __COMPILER_BARRIER
#define __COMPILER_BARRIER() __ASM volatile("":::"memory")
#endif
/** \brief provide the compiler with branch prediction information, the branch is usually true */
#ifndef __USUALLY
#define __USUALLY(exp) __builtin_expect((exp), 1)
#endif
/** \brief provide the compiler with branch prediction information, the branch is rarely true */
#ifndef __RARELY
#define __RARELY(exp) __builtin_expect((exp), 0)
#endif
/** \brief Use this attribute to indicate that the specified function is an interrupt handler run in Machine Mode. */
#ifndef __INTERRUPT
#define __INTERRUPT __attribute__((interrupt))
#endif
/** \brief Use this attribute to indicate that the specified function is an interrupt handler run in Machine Mode. */
#ifndef __MACHINE_INTERRUPT
#define __MACHINE_INTERRUPT __attribute__ ((interrupt ("machine")))
#endif
/** \brief Use this attribute to indicate that the specified function is an interrupt handler run in Supervisor Mode. */
#ifndef __SUPERVISOR_INTERRUPT
#define __SUPERVISOR_INTERRUPT __attribute__ ((interrupt ("supervisor")))
#endif
/** \brief Use this attribute to indicate that the specified function is an interrupt handler run in User Mode. */
#ifndef __USER_INTERRUPT
#define __USER_INTERRUPT __attribute__ ((interrupt ("user")))
#endif
/** @} */ /* End of Doxygen Group NMSIS_Core_CompilerControl */
#ifdef __cplusplus
}
#endif
#endif /* __NMSIS_GCC_H__ */
@@ -0,0 +1,206 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __NMSIS_IAR_H__
#define __NMSIS_IAR_H__
/*!
* @file nmsis_iar.h
* @brief NMSIS compiler IAR header file
*/
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "riscv_encoding.h"
/* ######################### Startup and Lowlevel Init ######################## */
/**
* \defgroup NMSIS_Core_CompilerControl Compiler Control
* \ingroup NMSIS_Core
* \brief Compiler agnostic \#define symbols for generic c/c++ source code
* \details
*
* The NMSIS-Core provides the header file <b>nmsis_compiler.h</b> with consistent \#define symbols for generate C or C++ source files that should be compiler agnostic.
* Each NMSIS compliant compiler should support the functionality described in this section.
*
* The header file <b>nmsis_compiler.h</b> is also included by each Device Header File <device.h> so that these definitions are available.
* @{
*/
/* Fallback for __has_builtin */
#ifndef __has_builtin
#define __has_builtin(x) (0)
#endif
/* NMSIS compiler specific defines */
/** \brief Pass information from the compiler to the assembler. */
#ifndef __ASM
#define __ASM __asm
#endif
/** \brief Recommend that function should be inlined by the compiler. */
#ifndef __INLINE
#define __INLINE inline
#endif
/** \brief Define a static function that may be inlined by the compiler. */
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
/** \brief Define a static function that should be always inlined by the compiler. */
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
#endif
/** \brief Inform the compiler that a function does not return. */
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((__noreturn__))
#endif
/** \brief Inform that a variable shall be retained in executable image. */
#ifndef __USED
#define __USED __attribute__((used))
#endif
/** \brief restrict pointer qualifier to enable additional optimizations. */
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
/** \brief specified the vector size of the variable, measured in bytes, not supported in IAR */
#ifndef __VECTOR_SIZE
#define __VECTOR_SIZE(x)
#endif
/** \brief Request smallest possible alignment. */
#ifndef __PACKED
#define __PACKED __attribute__((packed, aligned(1)))
#endif
/** \brief Request smallest possible alignment for a structure. */
#ifndef __PACKED_STRUCT
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
#endif
/** \brief Request smallest possible alignment for a union. */
#ifndef __PACKED_UNION
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
#endif
#ifndef __UNALIGNED_UINT16_WRITE
#pragma language=save
#pragma language=extended
/** \brief Packed struct for unaligned uint16_t write access */
__PACKED_STRUCT T_UINT16_WRITE {
uint16_t v;
};
#pragma language=restore
/** \brief Pointer for unaligned write of a uint16_t variable. */
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT16_READ
#pragma language=save
#pragma language=extended
/** \brief Packed struct for unaligned uint16_t read access */
__PACKED_STRUCT T_UINT16_READ {
uint16_t v;
};
#pragma language=restore
/** \brief Pointer for unaligned read of a uint16_t variable. */
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
#endif
#ifndef __UNALIGNED_UINT32_WRITE
#pragma language=save
#pragma language=extended
/** \brief Packed struct for unaligned uint32_t write access */
__PACKED_STRUCT T_UINT32_WRITE {
uint32_t v;
};
#pragma language=restore
/** \brief Pointer for unaligned write of a uint32_t variable. */
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
#endif
#ifndef __UNALIGNED_UINT32_READ
#pragma language=save
#pragma language=extended
/** \brief Packed struct for unaligned uint32_t read access */
__PACKED_STRUCT T_UINT32_READ {
uint32_t v;
};
#pragma language=restore
/** \brief Pointer for unaligned read of a uint32_t variable. */
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
#endif
/** \brief Minimum `x` bytes alignment for a variable. */
#ifndef __ALIGNED
#define __ALIGNED(x) __attribute__((aligned(x)))
#endif
/** \brief restrict pointer qualifier to enable additional optimizations. */
#ifndef __RESTRICT
#define __RESTRICT __restrict
#endif
/** \brief Barrier to prevent compiler from reordering instructions. */
#ifndef __COMPILER_BARRIER
#define __COMPILER_BARRIER() __ASM volatile("":::"memory")
#endif
/** \brief provide the compiler with branch prediction information, the branch is usually true */
#ifndef __USUALLY
#define __USUALLY(exp) (exp)
#endif
/** \brief provide the compiler with branch prediction information, the branch is rarely true */
#ifndef __RARELY
#define __RARELY(exp) (exp)
#endif
/** \brief Use this attribute to indicate that the specified function is an interrupt handler run in Machine Mode. */
#ifndef __INTERRUPT
#define __INTERRUPT __machine __interrupt
#endif
/** \brief Use this attribute to indicate that the specified function is an interrupt handler run in Machine Mode. */
#ifndef __MACHINE_INTERRUPT
#define __MACHINE_INTERRUPT __machine __interrupt
#endif
/** \brief Use this attribute to indicate that the specified function is an interrupt handler run in Supervisor Mode. */
#ifndef __SUPERVISOR_INTERRUPT
#define __SUPERVISOR_INTERRUPT __supervisor __interrupt
#endif
/** \brief Use this attribute to indicate that the specified function is an interrupt handler run in User Mode. */
#ifndef __USER_INTERRUPT
#define __USER_INTERRUPT __user __interrupt
#endif
/** @} */ /* End of Doxygen Group NMSIS_Core_CompilerControl */
#ifdef __cplusplus
}
#endif
#endif /* __NMSIS_GCC_H__ */
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2019 Nuclei Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __NMSIS_VERSION_H
#define __NMSIS_VERSION_H
/**
* \defgroup NMSIS_Core_VersionControl Version Control
* \ingroup NMSIS_Core
* \brief Version \#define symbols for NMSIS release specific C/C++ source code
* \details
*
* We followed the [semantic versioning 2.0.0](https://semver.org/) to control NMSIS version.
* The version format is **MAJOR.MINOR.PATCH**, increment the:
* 1. MAJOR version when you make incompatible API changes,
* 2. MINOR version when you add functionality in a backwards compatible manner, and
* 3. PATCH version when you make backwards compatible bug fixes.
*
* The header file `nmsis_version.h` is included by each core header so that these definitions are available.
*
* **Example Usage for NMSIS Version Check**:
* \code
* #if defined(__NMSIS_VERSION) && (__NMSIS_VERSION >= 0x00010105)
* #warning "Yes, we have NMSIS 1.1.5 or later"
* #else
* #error "We need NMSIS 1.1.5 or later!"
* #endif
* \endcode
*
* @{
*/
/*!
* \file nmsis_version.h
* \brief NMSIS Version definitions
**/
/**
* \brief Represent the NMSIS major version
* \details
* The NMSIS major version can be used to
* differentiate between NMSIS major releases.
* */
#define __NMSIS_VERSION_MAJOR (1U)
/**
* \brief Represent the NMSIS minor version
* \details
* The NMSIS minor version can be used to
* query a NMSIS release update including new features.
*
**/
#define __NMSIS_VERSION_MINOR (3U)
/**
* \brief Represent the NMSIS patch version
* \details
* The NMSIS patch version can be used to
* show bug fixes in this package.
**/
#define __NMSIS_VERSION_PATCH (1U)
/**
* \brief Represent the NMSIS Version
* \details
* NMSIS Version format: **MAJOR.MINOR.PATCH**
* * MAJOR: \ref __NMSIS_VERSION_MAJOR, stored in `bits [31:16]` of \ref __NMSIS_VERSION
* * MINOR: \ref __NMSIS_VERSION_MINOR, stored in `bits [15:8]` of \ref __NMSIS_VERSION
* * PATCH: \ref __NMSIS_VERSION_PATCH, stored in `bits [7:0]` of \ref __NMSIS_VERSION
**/
#define __NMSIS_VERSION ((__NMSIS_VERSION_MAJOR << 16U) | (__NMSIS_VERSION_MINOR << 8) | __NMSIS_VERSION_PATCH)
/** @} */ /* End of Doxygen Group NMSIS_Core_VersionControl */
#endif

Some files were not shown because too many files have changed in this diff Show More