first submission
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
<?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.release.1008047074">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.1008047074" moduleId="org.eclipse.cdt.core.settings" name="obj">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<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.1008047074" name="obj" parent="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release">
|
||||
<folderInfo id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.1008047074." name="/" resourcePath="">
|
||||
<toolChain id="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.release.231146001" name="RISC-V Cross GCC" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.release">
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash.1311852988" name="Create flash image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting.1983282875" name="Create extended listing" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize.1000761142" name="Print size" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.514997414" name="Optimization Level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level" useByScannerDiscovery="true" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.size" valueType="enumerated"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength.1008570639" name="Message length (-fmessage-length=0)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength" useByScannerDiscovery="true" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar.467272439" name="'char' is signed (-fsigned-char)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar" useByScannerDiscovery="true" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections.2047756949" name="Function sections (-ffunction-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections" useByScannerDiscovery="true" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections.207613650" name="Data sections (-fdata-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections" useByScannerDiscovery="true" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level.1204865254" name="Debug level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level" useByScannerDiscovery="true"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format.867779652" name="Debug format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format" useByScannerDiscovery="true"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.base.1900297968" name="Architecture" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.base" useByScannerDiscovery="false" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.arch.rv32i" valueType="enumerated"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.abi.integer.387605487" name="Integer ABI" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.abi.integer" useByScannerDiscovery="false" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.abi.integer.ilp32" valueType="enumerated"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.multiply.1509705449" name="Multiply extension (RVM)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.multiply" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.compressed.1038505275" name="Compressed extension (RVC)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.compressed" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name.1218760634" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name" useByScannerDiscovery="false" value="GNU MCU RISC-V GCC" valueType="string"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix.103341323" name="Prefix" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix" useByScannerDiscovery="false" value="riscv-none-embed-" valueType="string"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c.487601824" name="C compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c" useByScannerDiscovery="false" value="gcc" valueType="string"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp.1062130429" name="C++ compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp" useByScannerDiscovery="false" value="g++" valueType="string"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar.1194282993" name="Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar" useByScannerDiscovery="false" value="ar" valueType="string"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy.1529355265" name="Hex/Bin converter" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy" useByScannerDiscovery="false" value="objcopy" valueType="string"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump.1053750745" name="Listing generator" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump" useByScannerDiscovery="false" value="objdump" valueType="string"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size.1441326233" name="Size command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size" useByScannerDiscovery="false" value="size" valueType="string"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make.550105535" name="Build command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make" useByScannerDiscovery="false" value="make" valueType="string"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm.719280496" name="Remove command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm" useByScannerDiscovery="false" value="rm" valueType="string"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.id.226017994" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.id" useByScannerDiscovery="false" value="512258282" valueType="string"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.atomic.1590833110" name="Atomic extension (RVA)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.atomic" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.warnings.unused.1961191588" name="Warn on various unused elements (-Wunused)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.warnings.unused" useByScannerDiscovery="true" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.warnings.uninitialized.929829166" name="Warn on uninitialized variables (-Wuninitialized)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.warnings.uninitialized" useByScannerDiscovery="true" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.nocommon.1035914972" name="No common unitialized (-fno-common)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.nocommon" useByScannerDiscovery="true" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.xw.182881275" name="Extra Compressed extension (RVXW)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.xw" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.saverestore.1426074328" name="Small prologue/epilogue (-msave-restore)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.saverestore" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform.1944008784" isAbstract="false" osList="all" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform"/>
|
||||
<builder buildPath="${workspace_loc:/GPIO_Toggle}/obj" id="ilg.gnumcueclipse.managedbuild.cross.riscv.builder.1421508906" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.builder"/>
|
||||
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.1244756189" name="GNU RISC-V Cross Assembler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler">
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor.1692176068" name="Use preprocessor" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.include.paths.1034038285" name="Include paths (-I)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.include.paths" useByScannerDiscovery="true" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/Startup}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/common}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/common/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/rv32/gcc}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/core}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/core/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/hal}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/hal/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/pm}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/pm/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/TOS_CONFIG}""/>
|
||||
</option>
|
||||
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input.126366858" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input"/>
|
||||
</tool>
|
||||
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.1731377187" 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.include.paths.1567947810" name="Include paths (-I)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.include.paths" useByScannerDiscovery="true" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/Debug}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/Core}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/User}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/Peripheral/inc}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/common}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/common/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/rv32/gcc}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/core}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/core/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/hal}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/hal/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/pm}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/pm/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/TencentOS_Tiny/TOS_CONFIG}""/>
|
||||
</option>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.std.2020844713" 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.gnu99" valueType="enumerated"/>
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs.177116515" name="Defined symbols (-D)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols"/>
|
||||
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.2036806839" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input"/>
|
||||
</tool>
|
||||
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler.1610882921" name="GNU RISC-V Cross C++ Compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler"/>
|
||||
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.1620074387" 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.194760422" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.gcsections" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.paths.2057340378" name="Library search path (-L)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.paths" useByScannerDiscovery="false" valueType="libPaths"/>
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.scriptfile.1390103472" name="Script files (-T)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.scriptfile" useByScannerDiscovery="false" valueType="stringList">
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/Ld/Link.ld}""/>
|
||||
</option>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nostart.913830613" name="Do not use standard start files (-nostartfiles)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nostart" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.usenewlibnano.239404511" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.usenewlibnano" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.usenewlibnosys.351964161" name="Do not use syscalls (--specs=nosys.specs)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.usenewlibnosys" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.otherobjs.16994550" name="Other objects" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.otherobjs" useByScannerDiscovery="false" valueType="userObjs"/>
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.flags.1125808200" name="Linker flags (-Xlinker [option])" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.flags" useByScannerDiscovery="false" valueType="stringList"/>
|
||||
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.input.1859223768" 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.1947503520" 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.1689063433" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.gcsections" value="true" valueType="boolean"/>
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.paths.1029177148" name="Library search path (-L)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.paths" valueType="libPaths">
|
||||
<listOptionValue builtIn="false" value=""../LD""/>
|
||||
</option>
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.scriptfile.1751226764" name="Script files (-T)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.scriptfile" valueType="stringList">
|
||||
<listOptionValue builtIn="false" value="Link.ld"/>
|
||||
</option>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.nostart.642896175" name="Do not use standard start files (-nostartfiles)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.nostart" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.usenewlibnano.1540675679" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.usenewlibnano" value="true" valueType="boolean"/>
|
||||
</tool>
|
||||
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver.1292785366" name="GNU RISC-V Cross Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver"/>
|
||||
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash.1801165667" name="GNU RISC-V Cross Create Flash Image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash"/>
|
||||
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createlisting.1356766765" 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.2052761852" name="Display source (--source|-S)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.source" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders.439659821" name="Display all headers (--all-headers|-x)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle.67111865" name="Demangle names (--demangle|-C)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers.1549373929" name="Display line numbers (--line-numbers|-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide.1298918921" name="Wide lines (--wide|-w)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide" useByScannerDiscovery="false" value="false" valueType="boolean"/>
|
||||
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.disassemble.1859590835" name="Disassemble (--disassemble|-d)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.disassemble" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
</tool>
|
||||
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.printsize.712424314" 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.1404031980" name="Size format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.printsize.format" useByScannerDiscovery="false"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry excluding="Startup|Peripheral|Ld|Debug|Core" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core"/>
|
||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Debug"/>
|
||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Ld"/>
|
||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Peripheral"/>
|
||||
<entry excluding="startup_ch32v20x_D8W.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Startup"/>
|
||||
</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="999.ilg.gnumcueclipse.managedbuild.cross.riscv.target.elf.275846018" name="Executable file" projectType="ilg.gnumcueclipse.managedbuild.cross.riscv.target.elf"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<scannerConfigBuildInfo instanceId="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.767917625;ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.767917625.;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.1375371130;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.1473381709">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.1008047074;ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.1008047074.;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.1731377187;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.2036806839">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
|
||||
</cproject>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<projectDescription>
|
||||
<name>TencentOS</name>
|
||||
<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>Core</name>
|
||||
<type>2</type>
|
||||
<locationURI>PARENT-2-PROJECT_LOC/SRC/Core</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>Debug</name>
|
||||
<type>2</type>
|
||||
<locationURI>PARENT-2-PROJECT_LOC/SRC/Debug</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>Ld</name>
|
||||
<type>2</type>
|
||||
<locationURI>PARENT-2-PROJECT_LOC/SRC/Ld</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>Peripheral</name>
|
||||
<type>2</type>
|
||||
<locationURI>PARENT-2-PROJECT_LOC/SRC/Peripheral</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
<filteredResources>
|
||||
<filter>
|
||||
<id>1595986042669</id>
|
||||
<name/>
|
||||
<type>22</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||
<arguments>1.0-name-matches-false-false-*.wvproj</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
</filteredResources>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project>
|
||||
<configuration id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.1008047074" name="obj">
|
||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-506084330057943373" id="ilg.gnumcueclipse.managedbuild.cross.riscv.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT RISC-V Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
</extension>
|
||||
</configuration>
|
||||
</project>
|
||||
@@ -0,0 +1,16 @@
|
||||
Mcu Type=CH32V20x
|
||||
Address=0x08000000
|
||||
Target Path=obj/TencentOS.hex
|
||||
Erase All=true
|
||||
Program=true
|
||||
Verify=true
|
||||
Reset=true
|
||||
|
||||
Vendor=WCH
|
||||
Link=WCH-Link
|
||||
Toolchain=RISC-V
|
||||
Series=CH32V203
|
||||
Description=ROM(byte): 64K, SRAM(byte): 20K, CHIP PINS: 32, GPIO PORTS: 27.\nWCH CH32V2 series of mainstream MCUs covers the needs of a large variety of applications in the industrial,medical and consumer markets. High performance with first-class peripherals and low-power,low-voltage operation is paired with a high level of integration at accessible prices with a simple architecture and easy-to-use tools.
|
||||
|
||||
PeripheralVersion=1.0
|
||||
MCU=CH32V203RBT6
|
||||
@@ -0,0 +1,266 @@
|
||||
;/********************************** (C) COPYRIGHT *******************************
|
||||
;* File Name : startup_ch32v20x_D6.s
|
||||
;* Author : WCH
|
||||
;* Version : V1.0.0
|
||||
;* Date : 2021/06/06
|
||||
;* Description : CH32V203F6-CH32V203F8-CH32V203G6-CH32V203G8-CH32V203K6-CH32V203K8-CH32V203C6-CH32V203C8
|
||||
;* vector table for eclipse toolchain.
|
||||
;*********************************************************************************
|
||||
;* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
;* Attention: This software (modified or not) and binary are used for
|
||||
;* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
.section .init,"ax",@progbits
|
||||
.global _start
|
||||
.align 1
|
||||
_start:
|
||||
j handle_reset
|
||||
.word 0x00000013
|
||||
.word 0x00000013
|
||||
.word 0x00000013
|
||||
.word 0x00000013
|
||||
.word 0x00000013
|
||||
.word 0x00000013
|
||||
.word 0x00000013
|
||||
.word 0x00000013
|
||||
.word 0x00000013
|
||||
.word 0x00000013
|
||||
.word 0x00000013
|
||||
.word 0x00000013
|
||||
.word 0x00100073
|
||||
.section .vector,"ax",@progbits
|
||||
.align 1
|
||||
_vector_base:
|
||||
.option norvc;
|
||||
.word _start
|
||||
.word 0
|
||||
.word NMI_Handler /* NMI */
|
||||
.word HardFault_Handler /* Hard Fault */
|
||||
.word 0
|
||||
.word Ecall_M_Mode_Handler /* Ecall M Mode */
|
||||
.word 0
|
||||
.word 0
|
||||
.word Ecall_U_Mode_Handler /* Ecall U Mode */
|
||||
.word Break_Point_Handler /* Break Point */
|
||||
.word 0
|
||||
.word 0
|
||||
.word SysTick_Handler /* SysTick */
|
||||
.word 0
|
||||
.word SW_Handler /* SW */
|
||||
.word 0
|
||||
/* External Interrupts */
|
||||
.word WWDG_IRQHandler /* Window Watchdog */
|
||||
.word PVD_IRQHandler /* PVD through EXTI Line detect */
|
||||
.word TAMPER_IRQHandler /* TAMPER */
|
||||
.word RTC_IRQHandler /* RTC */
|
||||
.word FLASH_IRQHandler /* Flash */
|
||||
.word RCC_IRQHandler /* RCC */
|
||||
.word EXTI0_IRQHandler /* EXTI Line 0 */
|
||||
.word EXTI1_IRQHandler /* EXTI Line 1 */
|
||||
.word EXTI2_IRQHandler /* EXTI Line 2 */
|
||||
.word EXTI3_IRQHandler /* EXTI Line 3 */
|
||||
.word EXTI4_IRQHandler /* EXTI Line 4 */
|
||||
.word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */
|
||||
.word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */
|
||||
.word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */
|
||||
.word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */
|
||||
.word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */
|
||||
.word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */
|
||||
.word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */
|
||||
.word ADC1_2_IRQHandler /* ADC1_2 */
|
||||
.word USB_HP_CAN1_TX_IRQHandler /* USB HP and CAN1 TX */
|
||||
.word USB_LP_CAN1_RX0_IRQHandler /* USB LP and CAN1RX0 */
|
||||
.word CAN1_RX1_IRQHandler /* CAN1 RX1 */
|
||||
.word CAN1_SCE_IRQHandler /* CAN1 SCE */
|
||||
.word EXTI9_5_IRQHandler /* EXTI Line 9..5 */
|
||||
.word TIM1_BRK_IRQHandler /* TIM1 Break */
|
||||
.word TIM1_UP_IRQHandler /* TIM1 Update */
|
||||
.word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation */
|
||||
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
|
||||
.word TIM2_IRQHandler /* TIM2 */
|
||||
.word TIM3_IRQHandler /* TIM3 */
|
||||
.word TIM4_IRQHandler /* TIM4 */
|
||||
.word I2C1_EV_IRQHandler /* I2C1 Event */
|
||||
.word I2C1_ER_IRQHandler /* I2C1 Error */
|
||||
.word I2C2_EV_IRQHandler /* I2C2 Event */
|
||||
.word I2C2_ER_IRQHandler /* I2C2 Error */
|
||||
.word SPI1_IRQHandler /* SPI1 */
|
||||
.word SPI2_IRQHandler /* SPI2 */
|
||||
.word USART1_IRQHandler /* USART1 */
|
||||
.word USART2_IRQHandler /* USART2 */
|
||||
.word USART3_IRQHandler /* USART3 */
|
||||
.word EXTI15_10_IRQHandler /* EXTI Line 15..10 */
|
||||
.word RTCAlarm_IRQHandler /* RTC Alarm through EXTI Line */
|
||||
.word USBWakeUp_IRQHandler /* USB Wake up from suspend */
|
||||
.word USBHD_IRQHandler /* USBHD Break */
|
||||
.word USBHDWakeUp_IRQHandler /* USBHD Wake up from suspend */
|
||||
.word UART4_IRQHandler /* UART4 */
|
||||
.word DMA1_Channel8_IRQHandler /* DMA1 Channel8 */
|
||||
|
||||
.option rvc;
|
||||
|
||||
.section .text.vector_handler, "ax", @progbits
|
||||
.weak NMI_Handler /* NMI */
|
||||
.weak HardFault_Handler /* Hard Fault */
|
||||
.weak Ecall_M_Mode_Handler /* Ecall M Mode */
|
||||
.weak Ecall_U_Mode_Handler /* Ecall U Mode */
|
||||
.weak Break_Point_Handler /* Break Point */
|
||||
.weak SysTick_Handler /* SysTick */
|
||||
.weak SW_Handler /* SW */
|
||||
.weak WWDG_IRQHandler /* Window Watchdog */
|
||||
.weak PVD_IRQHandler /* PVD through EXTI Line detect */
|
||||
.weak TAMPER_IRQHandler /* TAMPER */
|
||||
.weak RTC_IRQHandler /* RTC */
|
||||
.weak FLASH_IRQHandler /* Flash */
|
||||
.weak RCC_IRQHandler /* RCC */
|
||||
.weak EXTI0_IRQHandler /* EXTI Line 0 */
|
||||
.weak EXTI1_IRQHandler /* EXTI Line 1 */
|
||||
.weak EXTI2_IRQHandler /* EXTI Line 2 */
|
||||
.weak EXTI3_IRQHandler /* EXTI Line 3 */
|
||||
.weak EXTI4_IRQHandler /* EXTI Line 4 */
|
||||
.weak DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */
|
||||
.weak DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */
|
||||
.weak DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */
|
||||
.weak DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */
|
||||
.weak DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */
|
||||
.weak DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */
|
||||
.weak DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */
|
||||
.weak ADC1_2_IRQHandler /* ADC1_2 */
|
||||
.weak USB_HP_CAN1_TX_IRQHandler /* USB HP and CAN1 TX */
|
||||
.weak USB_LP_CAN1_RX0_IRQHandler /* USB LP and CAN1RX0 */
|
||||
.weak CAN1_RX1_IRQHandler /* CAN1 RX1 */
|
||||
.weak CAN1_SCE_IRQHandler /* CAN1 SCE */
|
||||
.weak EXTI9_5_IRQHandler /* EXTI Line 9..5 */
|
||||
.weak TIM1_BRK_IRQHandler /* TIM1 Break */
|
||||
.weak TIM1_UP_IRQHandler /* TIM1 Update */
|
||||
.weak TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation */
|
||||
.weak TIM1_CC_IRQHandler /* TIM1 Capture Compare */
|
||||
.weak TIM2_IRQHandler /* TIM2 */
|
||||
.weak TIM3_IRQHandler /* TIM3 */
|
||||
.weak TIM4_IRQHandler /* TIM4 */
|
||||
.weak I2C1_EV_IRQHandler /* I2C1 Event */
|
||||
.weak I2C1_ER_IRQHandler /* I2C1 Error */
|
||||
.weak I2C2_EV_IRQHandler /* I2C2 Event */
|
||||
.weak I2C2_ER_IRQHandler /* I2C2 Error */
|
||||
.weak SPI1_IRQHandler /* SPI1 */
|
||||
.weak SPI2_IRQHandler /* SPI2 */
|
||||
.weak USART1_IRQHandler /* USART1 */
|
||||
.weak USART2_IRQHandler /* USART2 */
|
||||
.weak USART3_IRQHandler /* USART3 */
|
||||
.weak EXTI15_10_IRQHandler /* EXTI Line 15..10 */
|
||||
.weak RTCAlarm_IRQHandler /* RTC Alarm through EXTI Line */
|
||||
.weak USBWakeUp_IRQHandler /* USB Wakeup from suspend */
|
||||
.weak USBHD_IRQHandler /* USBHD */
|
||||
.weak USBHDWakeUp_IRQHandler /* USBHD Wake Up */
|
||||
.weak UART4_IRQHandler /* UART4 */
|
||||
.weak DMA1_Channel8_IRQHandler /* DMA1 Channel8 */
|
||||
|
||||
NMI_Handler: 1: j 1b
|
||||
HardFault_Handler: 1: j 1b
|
||||
Ecall_M_Mode_Handler: 1: j 1b
|
||||
Ecall_U_Mode_Handler: 1: j 1b
|
||||
Break_Point_Handler: 1: j 1b
|
||||
SysTick_Handler: 1: j 1b
|
||||
SW_Handler: 1: j 1b
|
||||
WWDG_IRQHandler: 1: j 1b
|
||||
PVD_IRQHandler: 1: j 1b
|
||||
TAMPER_IRQHandler: 1: j 1b
|
||||
RTC_IRQHandler: 1: j 1b
|
||||
FLASH_IRQHandler: 1: j 1b
|
||||
RCC_IRQHandler: 1: j 1b
|
||||
EXTI0_IRQHandler: 1: j 1b
|
||||
EXTI1_IRQHandler: 1: j 1b
|
||||
EXTI2_IRQHandler: 1: j 1b
|
||||
EXTI3_IRQHandler: 1: j 1b
|
||||
EXTI4_IRQHandler: 1: j 1b
|
||||
DMA1_Channel1_IRQHandler: 1: j 1b
|
||||
DMA1_Channel2_IRQHandler: 1: j 1b
|
||||
DMA1_Channel3_IRQHandler: 1: j 1b
|
||||
DMA1_Channel4_IRQHandler: 1: j 1b
|
||||
DMA1_Channel5_IRQHandler: 1: j 1b
|
||||
DMA1_Channel6_IRQHandler: 1: j 1b
|
||||
DMA1_Channel7_IRQHandler: 1: j 1b
|
||||
ADC1_2_IRQHandler: 1: j 1b
|
||||
USB_HP_CAN1_TX_IRQHandler: 1: j 1b
|
||||
USB_LP_CAN1_RX0_IRQHandler: 1: j 1b
|
||||
CAN1_RX1_IRQHandler: 1: j 1b
|
||||
CAN1_SCE_IRQHandler: 1: j 1b
|
||||
EXTI9_5_IRQHandler: 1: j 1b
|
||||
TIM1_BRK_IRQHandler: 1: j 1b
|
||||
TIM1_UP_IRQHandler: 1: j 1b
|
||||
TIM1_TRG_COM_IRQHandler: 1: j 1b
|
||||
TIM1_CC_IRQHandler: 1: j 1b
|
||||
TIM2_IRQHandler: 1: j 1b
|
||||
TIM3_IRQHandler: 1: j 1b
|
||||
TIM4_IRQHandler: 1: j 1b
|
||||
I2C1_EV_IRQHandler: 1: j 1b
|
||||
I2C1_ER_IRQHandler: 1: j 1b
|
||||
I2C2_EV_IRQHandler: 1: j 1b
|
||||
I2C2_ER_IRQHandler: 1: j 1b
|
||||
SPI1_IRQHandler: 1: j 1b
|
||||
SPI2_IRQHandler: 1: j 1b
|
||||
USART1_IRQHandler: 1: j 1b
|
||||
USART2_IRQHandler: 1: j 1b
|
||||
USART3_IRQHandler: 1: j 1b
|
||||
EXTI15_10_IRQHandler: 1: j 1b
|
||||
RTCAlarm_IRQHandler: 1: j 1b
|
||||
USBWakeUp_IRQHandler: 1: j 1b
|
||||
USBHD_IRQHandler: 1: j 1b
|
||||
USBHDWakeUp_IRQHandler: 1: j 1b
|
||||
UART4_IRQHandler: 1: j 1b
|
||||
DMA1_Channel8_IRQHandler: 1: j 1b
|
||||
|
||||
.section .text.handle_reset,"ax",@progbits
|
||||
.weak handle_reset
|
||||
.align 1
|
||||
handle_reset:
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
1:
|
||||
la sp, _eusrstack
|
||||
2:
|
||||
/* Load data section from flash to RAM */
|
||||
la a0, _data_lma
|
||||
la a1, _data_vma
|
||||
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:
|
||||
/* Clear bss section */
|
||||
la a0, _sbss
|
||||
la a1, _ebss
|
||||
bgeu a0, a1, 2f
|
||||
1:
|
||||
sw zero, (a0)
|
||||
addi a0, a0, 4
|
||||
bltu a0, a1, 1b
|
||||
2:
|
||||
li t0, 0x1f
|
||||
csrw 0xbc0, t0
|
||||
|
||||
/* Enable nested */
|
||||
li t0, 0x2
|
||||
csrw 0x804, t0
|
||||
|
||||
/* Enable interrupt */
|
||||
li t0, 0x1800
|
||||
csrs mstatus, t0
|
||||
|
||||
la t0, _vector_base
|
||||
ori t0, t0, 3
|
||||
csrw mtvec, t0
|
||||
|
||||
jal SystemInit
|
||||
la t0, main
|
||||
csrw mepc, t0
|
||||
mret
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
�i“CZ ?"Ç�¸rŸ�F<Fy8E9Y‡½„%Pa³D¶La†%Ã'y€¡]Ç;’¶ŸS)1†1+R4><‚.„ÇÅ¿º°?/£XO©Ä¿ChQN$*¢”»EÅBk‹!2tŒ+buh†nUb]xl‹l|
|
||||
+"Ÿ<“¯AH42}z8p;m€u1Ž-¦eh»Od¼Âwµª7x{5�CqEx©=;¦¢e¢º»2£Š ‚«*BPMš"
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef INC_TOS_CONFIG_H_
|
||||
#define INC_TOS_CONFIG_H_
|
||||
|
||||
#include "ch32v20x.h"
|
||||
#include "stddef.h"
|
||||
|
||||
|
||||
#define TOS_CFG_TASK_PRIO_MAX 10u
|
||||
|
||||
|
||||
#define TOS_CFG_ROUND_ROBIN_EN 0u
|
||||
|
||||
|
||||
#define TOS_CFG_OBJECT_VERIFY 0u
|
||||
|
||||
#define TOS_CFG_TASK_DYNAMIC_CREATE_EN 0u
|
||||
|
||||
|
||||
#define TOS_CFG_EVENT_EN 1u
|
||||
|
||||
#define TOS_CFG_MMBLK_EN 1u
|
||||
|
||||
#define TOS_CFG_MMHEAP_EN 1u
|
||||
|
||||
|
||||
#define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE 0x2000
|
||||
|
||||
#define TOS_CFG_MAIL_QUEUE_EN 1u
|
||||
|
||||
#define TOS_CFG_MUTEX_EN 1u
|
||||
|
||||
#define TOS_CFG_TIMER_EN 0u
|
||||
|
||||
#define TOS_CFG_SEM_EN 1u
|
||||
|
||||
#define TOS_CFG_CPU_SYSTICK_PRIO 0xF0 //V307ÓÅÏȼ¶¸ßËÄλÓÐЧ
|
||||
|
||||
#if (TOS_CFG_QUEUE_EN > 0u)
|
||||
#define TOS_CFG_MSG_EN 1u
|
||||
#else
|
||||
#define TOS_CFG_MSG_EN 0u
|
||||
#endif
|
||||
|
||||
|
||||
#define TOS_CFG_MSG_POOL_SIZE 10u
|
||||
|
||||
|
||||
#define TOS_CFG_IDLE_TASK_STK_SIZE 512u
|
||||
|
||||
|
||||
#define TOS_CFG_IRQ_STK_SIZE 512u
|
||||
|
||||
|
||||
#define TOS_CFG_CPU_TICK_PER_SECOND 1000u
|
||||
|
||||
|
||||
#define TOS_CFG_CPU_CLOCK (SystemCoreClock)
|
||||
|
||||
|
||||
#define TOS_CFG_TIMER_AS_PROC 1u
|
||||
|
||||
|
||||
|
||||
#endif /* INC_TOS_CONFIG_H_ */
|
||||
@@ -0,0 +1,173 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_CPU_H_
|
||||
#define _TOS_CPU_H_
|
||||
#include "port_config.h"
|
||||
|
||||
typedef struct cpu_context_st {
|
||||
cpu_data_t mepc;
|
||||
cpu_data_t mstatus;
|
||||
union { cpu_data_t x1, ra; };
|
||||
union { cpu_data_t x3, gp; };
|
||||
union { cpu_data_t x4, tp; };
|
||||
union { cpu_data_t x5, t0; };
|
||||
union { cpu_data_t x6, t1; };
|
||||
union { cpu_data_t x7, t2; };
|
||||
union { cpu_data_t x8, s0, fp; };
|
||||
union { cpu_data_t x9, s1; };
|
||||
union { cpu_data_t x10, a0; };
|
||||
union { cpu_data_t x11, a1; };
|
||||
union { cpu_data_t x12, a2; };
|
||||
union { cpu_data_t x13, a3; };
|
||||
union { cpu_data_t x14, a4; };
|
||||
union { cpu_data_t x15, a5; };
|
||||
union { cpu_data_t x16, a6; };
|
||||
union { cpu_data_t x17, a7; };
|
||||
union { cpu_data_t x18, s2; };
|
||||
union { cpu_data_t x19, s3; };
|
||||
union { cpu_data_t x20, s4; };
|
||||
union { cpu_data_t x21, s5; };
|
||||
union { cpu_data_t x22, s6; };
|
||||
union { cpu_data_t x23, s7; };
|
||||
union { cpu_data_t x24, s8; };
|
||||
union { cpu_data_t x25, s9; };
|
||||
union { cpu_data_t x26, s10; };
|
||||
union { cpu_data_t x27, s11; };
|
||||
union { cpu_data_t x28, t3; };
|
||||
union { cpu_data_t x29, t4; };
|
||||
union { cpu_data_t x30, t5; };
|
||||
union { cpu_data_t x31, t6; };
|
||||
|
||||
#if ARCH_RISCV_FPU
|
||||
/* float reg table */
|
||||
union { cpu_data_t f0, ft0; };
|
||||
union { cpu_data_t f1, ft1; };
|
||||
union { cpu_data_t f2, ft2; };
|
||||
union { cpu_data_t f3, ft3; };
|
||||
union { cpu_data_t f4, ft4; };
|
||||
union { cpu_data_t f5, ft5; };
|
||||
union { cpu_data_t f6, ft6; };
|
||||
union { cpu_data_t f7, ft7; };
|
||||
union { cpu_data_t f8, fs0; };
|
||||
union { cpu_data_t f9, fs1; };
|
||||
union { cpu_data_t f10, fa0; };
|
||||
union { cpu_data_t f11, fa1; };
|
||||
union { cpu_data_t f12, fa2; };
|
||||
union { cpu_data_t f13, fa3; };
|
||||
union { cpu_data_t f14, fa4; };
|
||||
union { cpu_data_t f15, fa5; };
|
||||
union { cpu_data_t f16, fa6; };
|
||||
union { cpu_data_t f17, fa7; };
|
||||
union { cpu_data_t f18, fs2; };
|
||||
union { cpu_data_t f19, fs3; };
|
||||
union { cpu_data_t f20, fs4; };
|
||||
union { cpu_data_t f21, fs5; };
|
||||
union { cpu_data_t f22, fs6; };
|
||||
union { cpu_data_t f23, fs7; };
|
||||
union { cpu_data_t f24, fs8; };
|
||||
union { cpu_data_t f25, fs9; };
|
||||
union { cpu_data_t f26, fs10; };
|
||||
union { cpu_data_t f27, fs11; };
|
||||
union { cpu_data_t f28, ft8; };
|
||||
union { cpu_data_t f29, ft9; };
|
||||
union { cpu_data_t f30, ft10;};
|
||||
union { cpu_data_t f31, ft11;};
|
||||
#endif
|
||||
} cpu_context_t;
|
||||
|
||||
|
||||
__API__ uint32_t tos_cpu_clz(uint32_t val);
|
||||
|
||||
__API__ void tos_cpu_int_disable(void);
|
||||
|
||||
__API__ void tos_cpu_int_enable(void);
|
||||
|
||||
__API__ cpu_cpsr_t tos_cpu_cpsr_save(void);
|
||||
|
||||
__API__ void tos_cpu_cpsr_restore(cpu_cpsr_t cpsr);
|
||||
|
||||
|
||||
__KNL__ void cpu_init(void);
|
||||
|
||||
__KNL__ void cpu_reset(void);
|
||||
|
||||
__KNL__ void cpu_systick_init(k_cycle_t cycle_per_tick);
|
||||
|
||||
__KNL__ void cpu_sched_start(void);
|
||||
|
||||
__KNL__ void cpu_context_switch(void);
|
||||
|
||||
__KNL__ void cpu_irq_context_switch(void);
|
||||
|
||||
__KNL__ k_stack_t *cpu_task_stk_init(void *entry,
|
||||
void *arg,
|
||||
void *exit,
|
||||
k_stack_t *stk_base,
|
||||
size_t stk_size);
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
|
||||
__KNL__ void cpu_systick_resume(void);
|
||||
|
||||
__KNL__ void cpu_systick_suspend(void);
|
||||
|
||||
__KNL__ void cpu_systick_reload_reset(void);
|
||||
|
||||
__KNL__ void cpu_systick_pending_reset(void);
|
||||
|
||||
__KNL__ k_time_t cpu_systick_max_delay_millisecond(void);
|
||||
|
||||
__KNL__ void cpu_systick_expires_set(k_time_t millisecond);
|
||||
|
||||
__KNL__ void cpu_systick_reset(void);
|
||||
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_PWR_MGR_EN > 0u
|
||||
|
||||
__KNL__ void cpu_sleep_mode_enter(void);
|
||||
|
||||
__KNL__ void cpu_stop_mode_enter(void);
|
||||
|
||||
__KNL__ void cpu_standby_mode_enter(void);
|
||||
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_FAULT_BACKTRACE_EN > 0u
|
||||
|
||||
#error "unsupport now"
|
||||
|
||||
#endif
|
||||
|
||||
/* Allocates CPU status register word. */
|
||||
#define TOS_CPU_CPSR_ALLOC() cpu_cpsr_t cpu_cpsr = (cpu_cpsr_t)0u
|
||||
|
||||
/* Save CPU status word & disable interrupts.*/
|
||||
#define TOS_CPU_INT_DISABLE() \
|
||||
do { \
|
||||
cpu_cpsr = tos_cpu_cpsr_save(); \
|
||||
} while (0)
|
||||
|
||||
/* Restore CPU status word. */
|
||||
#define TOS_CPU_INT_ENABLE() \
|
||||
do { \
|
||||
tos_cpu_cpsr_restore(cpu_cpsr); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#endif /* _TOS_CPU_H_ */
|
||||
@@ -0,0 +1,33 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_CPU_DEF_H_
|
||||
#define _TOS_CPU_DEF_H_
|
||||
|
||||
#define CPU_WORD_SIZE_08 1
|
||||
#define CPU_WORD_SIZE_16 2
|
||||
#define CPU_WORD_SIZE_32 3
|
||||
#define CPU_WORD_SIZE_64 4
|
||||
|
||||
#define CPU_STK_GROWTH_ASCENDING 1
|
||||
#define CPU_STK_GROWTH_DESCENDING 2
|
||||
|
||||
#define CPU_BYTE_ORDER_LITTLE_ENDIAN 1
|
||||
#define CPU_BYTE_ORDER_BIG_ENDIAN 2
|
||||
|
||||
#endif /* _TOS_CPU_DEF_H_ */
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_CPU_TYPES_H_
|
||||
#define _TOS_CPU_TYPES_H_
|
||||
|
||||
/* CPU address type based on address bus size. */
|
||||
#if (TOS_CFG_CPU_ADDR_SIZE == CPU_WORD_SIZE_32)
|
||||
typedef uint32_t cpu_addr_t;
|
||||
#elif (TOS_CFG_CPU_ADDR_SIZE == CPU_WORD_SIZE_16)
|
||||
typedef uint16_t cpu_addr_t;
|
||||
#else
|
||||
typedef uint8_t cpu_addr_t;
|
||||
#endif
|
||||
|
||||
/* CPU data type based on data bus size. */
|
||||
#if (TOS_CFG_CPU_DATA_SIZE == CPU_WORD_SIZE_32)
|
||||
typedef uint32_t cpu_data_t;
|
||||
#elif (TOS_CFG_CPU_DATA_SIZE == CPU_WORD_SIZE_16)
|
||||
typedef uint16_t cpu_data_t;
|
||||
#else
|
||||
typedef uint8_t cpu_data_t;
|
||||
#endif
|
||||
|
||||
#if (TOS_CFG_CPU_HRTIMER_EN > 0)
|
||||
#if (TOS_CFG_CPU_HRTIMER_SIZE == CPU_WORD_SIZE_08)
|
||||
typedef uint8_t cpu_hrtimer_t;
|
||||
#elif (TOS_CFG_CPU_HRTIMER_SIZE == CPU_WORD_SIZE_16)
|
||||
typedef uint16_t cpu_hrtimer_t;
|
||||
#elif (TOS_CFG_CPU_HRTIMER_SIZE == CPU_WORD_SIZE_64)
|
||||
typedef uint64_t cpu_hrtimer_t;
|
||||
#else
|
||||
typedef uint32_t cpu_hrtimer_t;
|
||||
#endif
|
||||
#else
|
||||
typedef uint32_t cpu_hrtimer_t;
|
||||
#endif
|
||||
|
||||
typedef cpu_addr_t cpu_cpsr_t;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_FAULT_H_
|
||||
#define _TOS_FAULT_H_
|
||||
|
||||
#if TOS_CFG_FAULT_BACKTRACE_EN > 0u
|
||||
|
||||
#error "unsupport now"
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _TOS_FAULT_H_ */
|
||||
@@ -0,0 +1,191 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include <tos_k.h>
|
||||
|
||||
#ifndef TOS_CFG_IRQ_STK_SIZE
|
||||
#warning "did not specify the irq stack size, use default value"
|
||||
#define TOS_CFG_IRQ_STK_SIZE 128
|
||||
#endif
|
||||
|
||||
__aligned(4) k_stack_t k_irq_stk[TOS_CFG_IRQ_STK_SIZE];
|
||||
k_stack_t *k_irq_stk_top = k_irq_stk + TOS_CFG_IRQ_STK_SIZE;
|
||||
|
||||
|
||||
__API__ void tos_cpu_int_disable(void)
|
||||
{
|
||||
port_int_disable();
|
||||
}
|
||||
|
||||
__API__ void tos_cpu_int_enable(void)
|
||||
{
|
||||
port_int_enable();
|
||||
}
|
||||
|
||||
__API__ cpu_cpsr_t tos_cpu_cpsr_save(void)
|
||||
{
|
||||
return port_cpsr_save();
|
||||
}
|
||||
|
||||
__API__ void tos_cpu_cpsr_restore(cpu_cpsr_t cpsr)
|
||||
{
|
||||
port_cpsr_restore(cpsr);
|
||||
}
|
||||
|
||||
|
||||
__KNL__ void cpu_context_switch(void)
|
||||
{
|
||||
port_context_switch();
|
||||
}
|
||||
|
||||
__KNL__ void cpu_irq_context_switch(void)
|
||||
{
|
||||
|
||||
port_irq_context_switch();
|
||||
}
|
||||
|
||||
__KNL__ void cpu_sched_start(void)
|
||||
{
|
||||
port_sched_start();
|
||||
}
|
||||
|
||||
__KNL__ void cpu_systick_init(k_cycle_t cycle_per_tick)
|
||||
{
|
||||
port_systick_priority_set(TOS_CFG_CPU_SYSTICK_PRIO);
|
||||
port_systick_config(cycle_per_tick);
|
||||
}
|
||||
|
||||
__KNL__ void cpu_init(void) {
|
||||
|
||||
// reserve storage space for sp registers
|
||||
k_irq_stk_top = (k_stack_t *)(((cpu_addr_t) k_irq_stk_top) - sizeof(cpu_data_t));
|
||||
|
||||
k_irq_stk_top = (k_stack_t *)(((cpu_addr_t) k_irq_stk_top) & 0xFFFFFFFC);
|
||||
|
||||
k_cpu_cycle_per_tick = TOS_CFG_CPU_CLOCK / k_cpu_tick_per_second;
|
||||
|
||||
cpu_systick_init(k_cpu_cycle_per_tick);
|
||||
port_cpu_init();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Inx Offset Register
|
||||
31 124 x31 t6
|
||||
32 120 x30 t5
|
||||
29 116 x29 t4
|
||||
28 112 x28 t3
|
||||
27 108 x27 s11
|
||||
26 104 x26 s10
|
||||
25 100 x25 s9
|
||||
24 096 x24 s8
|
||||
23 092 x23 s7
|
||||
22 088 x22 s6
|
||||
21 084 x21 s5
|
||||
20 080 x20 s4
|
||||
19 076 x19 s3
|
||||
18 072 x18 s2
|
||||
17 068 x17 a7
|
||||
16 064 x16 a6
|
||||
15 060 x15 a5
|
||||
14 056 x14 a4
|
||||
13 052 x13 a3
|
||||
12 048 x12 a2
|
||||
11 044 x11 a1
|
||||
10 040 x10 a0
|
||||
09 036 x9 s1
|
||||
08 032 x8 s0/fp
|
||||
07 028 x7 t2
|
||||
06 024 x6 t1
|
||||
05 020 x5 t0
|
||||
04 016 x4 tp
|
||||
03 012 x3 gp
|
||||
02 008 x1 ra
|
||||
01 004 mstatus
|
||||
00 000 mepc
|
||||
|
||||
*/
|
||||
|
||||
__KNL__ k_stack_t *cpu_task_stk_init(void *entry,
|
||||
void *arg,
|
||||
void *exit,
|
||||
k_stack_t *stk_base,
|
||||
size_t stk_size)
|
||||
{
|
||||
cpu_data_t *sp = 0;
|
||||
cpu_context_t *regs = 0;
|
||||
|
||||
sp = (cpu_data_t *)&stk_base[stk_size];
|
||||
sp = (cpu_data_t *)((cpu_addr_t)(sp) & 0xFFFFFFFC);
|
||||
|
||||
sp -= (sizeof(cpu_context_t)/sizeof(cpu_data_t));
|
||||
|
||||
regs = (cpu_context_t*) sp;
|
||||
|
||||
for(int i=1; i<(sizeof(cpu_context_t)/sizeof(cpu_data_t)); i++) {
|
||||
*(sp + i) = 0xACEADD00 | ((i / 10) << 4) | (i % 10);
|
||||
}
|
||||
|
||||
cpu_data_t gp = 0;
|
||||
__ASM__ __VOLATILE__ ("mv %0, gp":"=r"(gp));
|
||||
|
||||
regs->gp = (cpu_data_t)gp; // global pointer
|
||||
regs->a0 = (cpu_data_t)arg; // argument
|
||||
regs->ra = (cpu_data_t)exit; // return address
|
||||
regs->mstatus = (cpu_data_t)0x00001880; // return to machine mode and enable interrupt
|
||||
regs->mepc = (cpu_data_t)entry; // task entry
|
||||
|
||||
return (k_stack_t*)sp;
|
||||
}
|
||||
|
||||
|
||||
__API__ uint32_t tos_cpu_clz(uint32_t val)
|
||||
{
|
||||
uint32_t nbr_lead_zeros = 0;
|
||||
|
||||
if (!(val & 0xFFFF0000)) {
|
||||
val <<= 16;
|
||||
nbr_lead_zeros += 16;
|
||||
}
|
||||
|
||||
if (!(val & 0xFF000000)) {
|
||||
val <<= 8;
|
||||
nbr_lead_zeros += 8;
|
||||
}
|
||||
|
||||
if (!(val & 0xF0000000)) {
|
||||
val <<= 4;
|
||||
nbr_lead_zeros += 4;
|
||||
}
|
||||
|
||||
if (!(val & 0xC0000000)) {
|
||||
val <<= 2;
|
||||
nbr_lead_zeros += 2;
|
||||
}
|
||||
|
||||
if (!(val & 0x80000000)) {
|
||||
nbr_lead_zeros += 1;
|
||||
}
|
||||
|
||||
if (!val) {
|
||||
nbr_lead_zeros += 1;
|
||||
}
|
||||
|
||||
return (nbr_lead_zeros);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _PORT_H_
|
||||
#define _PORT_H_
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
|
||||
/* defined by wch */
|
||||
#define GET_INT_SP() {asm("mv t0, sp");asm("lw sp, k_irq_stk_top");asm("sw t0,0(sp)");}
|
||||
#define FREE_INT_SP() {asm("lw sp,0(sp)");}
|
||||
__PORT__ void sw_clearpend(void);
|
||||
|
||||
|
||||
|
||||
__PORT__ void port_int_disable(void); //at port.s
|
||||
|
||||
__PORT__ void port_int_enable(void); //at port.s
|
||||
|
||||
/* risc-v 无cpsr,此函数用于读取mstatus,并清除MIE */
|
||||
__PORT__ cpu_cpsr_t port_cpsr_save(void); //at port.s
|
||||
|
||||
/* risc-v 无cpsr,此函数给mstatus赋值 */
|
||||
__PORT__ void port_cpsr_restore(cpu_cpsr_t cpsr); //at port.s
|
||||
|
||||
|
||||
__PORT__ void port_cpu_reset(void); //at port.c
|
||||
|
||||
__PORT__ void port_sched_start(void) __NO_RETURN__; //at port.s
|
||||
|
||||
__PORT__ void port_context_switch(void); //at port.c
|
||||
|
||||
__PORT__ void port_irq_context_switch(void); //at port.c
|
||||
|
||||
__PORT__ void port_systick_config(uint32_t cycle_per_tick); //at port.c
|
||||
|
||||
__PORT__ void port_systick_priority_set(uint32_t prio); //at port.c
|
||||
|
||||
__PORT__ void port_cpu_init(); //at port.c
|
||||
|
||||
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
|
||||
__PORT__ void port_systick_resume(void);
|
||||
|
||||
__PORT__ void port_systick_suspend(void);
|
||||
|
||||
__PORT__ void port_systick_reload(uint32_t cycle_per_tick);
|
||||
|
||||
__PORT__ void port_systick_pending_reset(void);
|
||||
|
||||
__PORT__ k_time_t port_systick_max_delay_millisecond(void);
|
||||
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_PWR_MGR_EN > 0u
|
||||
|
||||
__PORT__ void port_sleep_mode_enter(void);
|
||||
|
||||
__PORT__ void port_stop_mode_enter(void);
|
||||
|
||||
__PORT__ void port_standby_mode_enter(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if TOS_CFG_FAULT_BACKTRACE_EN > 0u
|
||||
__PORT__ void HardFault_Handler(void);
|
||||
|
||||
__PORT__ void port_fault_diagnosis(void);
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
|
||||
#define REGBYTES 4
|
||||
|
||||
#endif /* _PORT_H_ */
|
||||
@@ -0,0 +1,170 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include <tos_k.h>
|
||||
#include "ch32v20x.h"
|
||||
#include "core_riscv.h"
|
||||
|
||||
|
||||
__PORT__ void port_int_disable(void)
|
||||
{
|
||||
asm("csrw mstatus, %0" : :"r"(0x1800));
|
||||
}
|
||||
|
||||
__PORT__ void port_int_enable(void)
|
||||
{
|
||||
asm("csrw mstatus, %0" : :"r"(0x1888));
|
||||
}
|
||||
|
||||
__PORT__ cpu_cpsr_t port_cpsr_save(void)
|
||||
{
|
||||
cpu_cpsr_t value=0;
|
||||
asm("csrrw %0, mstatus, %1":"=r"(value):"r"(0x1800));
|
||||
return value;
|
||||
}
|
||||
__PORT__ void port_cpsr_restore(cpu_cpsr_t cpsr)
|
||||
{
|
||||
asm("csrw mstatus, %0": :"r"(cpsr));
|
||||
}
|
||||
|
||||
|
||||
__PORT__ void port_cpu_reset(void)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
/* clear soft interrupt */
|
||||
__PORT__ void sw_clearpend(void)
|
||||
{
|
||||
SysTick->CTLR &= ~(1<<31);
|
||||
}
|
||||
|
||||
/* trigger software interrupt */
|
||||
__PORT__ void port_context_switch(void)
|
||||
{
|
||||
SysTick->CTLR |= (1<<31);
|
||||
}
|
||||
|
||||
/* trigger software interrupt */
|
||||
__PORT__ void port_irq_context_switch(void)
|
||||
{
|
||||
SysTick->CTLR |= (1<<31);
|
||||
}
|
||||
|
||||
__PORT__ void port_systick_config(uint32_t cycle_per_tick)
|
||||
{
|
||||
SysTick->CTLR=0;
|
||||
SysTick->SR=0;
|
||||
SysTick->CNT=0;
|
||||
SysTick->CMP=cycle_per_tick-1;
|
||||
SysTick->CTLR=0xF;
|
||||
}
|
||||
|
||||
__PORT__ void port_systick_priority_set(uint32_t prio)
|
||||
{
|
||||
NVIC_SetPriority(SysTicK_IRQn, prio);
|
||||
}
|
||||
|
||||
__PORT__ void port_cpu_init()
|
||||
{
|
||||
NVIC_SetPriority(Software_IRQn,0xf0);
|
||||
NVIC_EnableIRQ(SysTicK_IRQn);
|
||||
NVIC_EnableIRQ(Software_IRQn);
|
||||
}
|
||||
|
||||
|
||||
void SysTick_Handler(void) __attribute__((interrupt()));
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
GET_INT_SP(); /* 切换中断栈 */
|
||||
if (tos_knl_is_running())
|
||||
{
|
||||
tos_knl_irq_enter();
|
||||
SysTick->SR=0;
|
||||
tos_tick_handler();
|
||||
tos_knl_irq_leave();
|
||||
}
|
||||
FREE_INT_SP(); /* 释放中断栈 */
|
||||
}
|
||||
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
__PORT__ k_time_t port_systick_max_delay_millisecond(void)
|
||||
{
|
||||
k_time_t max_millisecond;
|
||||
uint32_t max_cycle;
|
||||
|
||||
max_cycle = 0xffffffff; // systick 是64位,这里用低32位
|
||||
max_millisecond = (k_time_t)((uint64_t)max_cycle * K_TIME_MILLISEC_PER_SEC / TOS_CFG_CPU_CLOCK); // CLOCK: cycle per second
|
||||
return max_millisecond;
|
||||
}
|
||||
|
||||
__PORT__ void port_systick_resume(void)
|
||||
{
|
||||
SysTick->CTLR |= (3<<0);
|
||||
}
|
||||
|
||||
__PORT__ void port_systick_suspend(void)
|
||||
{
|
||||
SysTick->CTLR &= ~(3<<0);
|
||||
}
|
||||
|
||||
__PORT__ k_cycle_t port_systick_max_reload_cycle(void)
|
||||
{
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
__PORT__ void port_systick_reload(uint32_t cycle_per_tick)
|
||||
{
|
||||
port_systick_config(cycle_per_tick);
|
||||
}
|
||||
|
||||
__PORT__ void port_systick_pending_reset(void)
|
||||
{
|
||||
PFIC->IPRR[0] |= (1<<12); //clear pend
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if TOS_CFG_PWR_MGR_EN > 0u
|
||||
__PORT__ void port_sleep_mode_enter(void)
|
||||
{
|
||||
/* only CPU sleep */
|
||||
PFIC->SCTLR |= (1<<2);
|
||||
__WFI();
|
||||
PFIC->SCTLR &= ~(1<<2);
|
||||
}
|
||||
|
||||
__PORT__ void port_stop_mode_enter(void)
|
||||
{
|
||||
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
|
||||
}
|
||||
|
||||
__PORT__ void port_standby_mode_enter(void)
|
||||
{
|
||||
PWR_EnterSTANDBYMode();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _PORT_CONFIG_H_
|
||||
#define _PORT_CONFIG_H_
|
||||
|
||||
/* FPU is used */
|
||||
#define ARCH_RISCV_FPU 0u
|
||||
|
||||
#define TOS_CFG_CPU_ADDR_SIZE CPU_WORD_SIZE_32
|
||||
#define TOS_CFG_CPU_DATA_SIZE CPU_WORD_SIZE_32
|
||||
#define TOS_CFG_CPU_STK_GROWTH CPU_STK_GROWTH_DESCENDING
|
||||
#define TOS_CFG_CPU_HRTIMER_EN 0u
|
||||
#define TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT 0u
|
||||
#define TOS_CFG_CPU_BYTE_ORDER CPU_BYTE_ORDER_LITTLE_ENDIAN
|
||||
|
||||
|
||||
|
||||
/* int reg offset table */
|
||||
#define __reg_mepc_OFFSET 0x00
|
||||
#define __reg_mstatus_OFFSET 0x04
|
||||
#define __reg_x1_OFFSET 0x08
|
||||
#define __reg_x3_OFFSET 0x0C
|
||||
#define __reg_x4_OFFSET 0x10
|
||||
#define __reg_x5_OFFSET 0x14
|
||||
#define __reg_x6_OFFSET 0x18
|
||||
#define __reg_x7_OFFSET 0x1C
|
||||
#define __reg_x8_OFFSET 0x20
|
||||
#define __reg_x9_OFFSET 0x24
|
||||
#define __reg_x10_OFFSET 0x28
|
||||
#define __reg_x11_OFFSET 0x2C
|
||||
#define __reg_x12_OFFSET 0x30
|
||||
#define __reg_x13_OFFSET 0x34
|
||||
#define __reg_x14_OFFSET 0x38
|
||||
#define __reg_x15_OFFSET 0x3C
|
||||
#define __reg_x16_OFFSET 0x40
|
||||
#define __reg_x17_OFFSET 0x44
|
||||
#define __reg_x18_OFFSET 0x48
|
||||
#define __reg_x19_OFFSET 0x4C
|
||||
#define __reg_x20_OFFSET 0x50
|
||||
#define __reg_x21_OFFSET 0x54
|
||||
#define __reg_x22_OFFSET 0x58
|
||||
#define __reg_x23_OFFSET 0x5C
|
||||
#define __reg_x24_OFFSET 0x60
|
||||
#define __reg_x25_OFFSET 0x64
|
||||
#define __reg_x26_OFFSET 0x68
|
||||
#define __reg_x27_OFFSET 0x6C
|
||||
#define __reg_x28_OFFSET 0x70
|
||||
#define __reg_x29_OFFSET 0x74
|
||||
#define __reg_x30_OFFSET 0x78
|
||||
#define __reg_x31_OFFSET 0x7C
|
||||
|
||||
#define __reg_mepc__OFFSET __reg_mepc_OFFSET
|
||||
#define __reg_mstatus__OFFSET __reg_mstatus_OFFSET
|
||||
#define __reg_ra__OFFSET __reg_x1_OFFSET
|
||||
#define __reg_gp__OFFSET __reg_x3_OFFSET
|
||||
#define __reg_tp__OFFSET __reg_x4_OFFSET
|
||||
#define __reg_t0__OFFSET __reg_x5_OFFSET
|
||||
#define __reg_t1__OFFSET __reg_x6_OFFSET
|
||||
#define __reg_t2__OFFSET __reg_x7_OFFSET
|
||||
#define __reg_s0__OFFSET __reg_x8_OFFSET
|
||||
#define __reg_fp__OFFSET __reg_x8_OFFSET
|
||||
#define __reg_s1__OFFSET __reg_x9_OFFSET
|
||||
#define __reg_a0__OFFSET __reg_x10_OFFSET
|
||||
#define __reg_a1__OFFSET __reg_x11_OFFSET
|
||||
#define __reg_a2__OFFSET __reg_x12_OFFSET
|
||||
#define __reg_a3__OFFSET __reg_x13_OFFSET
|
||||
#define __reg_a4__OFFSET __reg_x14_OFFSET
|
||||
#define __reg_a5__OFFSET __reg_x15_OFFSET
|
||||
#define __reg_a6__OFFSET __reg_x16_OFFSET
|
||||
#define __reg_a7__OFFSET __reg_x17_OFFSET
|
||||
#define __reg_s2__OFFSET __reg_x18_OFFSET
|
||||
#define __reg_s3__OFFSET __reg_x19_OFFSET
|
||||
#define __reg_s4__OFFSET __reg_x20_OFFSET
|
||||
#define __reg_s5__OFFSET __reg_x21_OFFSET
|
||||
#define __reg_s6__OFFSET __reg_x22_OFFSET
|
||||
#define __reg_s7__OFFSET __reg_x23_OFFSET
|
||||
#define __reg_s8__OFFSET __reg_x24_OFFSET
|
||||
#define __reg_s9__OFFSET __reg_x25_OFFSET
|
||||
#define __reg_s10__OFFSET __reg_x26_OFFSET
|
||||
#define __reg_s11__OFFSET __reg_x27_OFFSET
|
||||
#define __reg_t3__OFFSET __reg_x28_OFFSET
|
||||
#define __reg_t4__OFFSET __reg_x29_OFFSET
|
||||
#define __reg_t5__OFFSET __reg_x30_OFFSET
|
||||
#define __reg_t6__OFFSET __reg_x31_OFFSET
|
||||
|
||||
|
||||
#if ARCH_RISCV_FPU
|
||||
/* float reg offset table */
|
||||
#define __reg_f0_OFFSET 0x00
|
||||
#define __reg_f1_OFFSET 0x04
|
||||
#define __reg_f2_OFFSET 0x08
|
||||
#define __reg_f3_OFFSET 0x0C
|
||||
#define __reg_f4_OFFSET 0x10
|
||||
#define __reg_f5_OFFSET 0x14
|
||||
#define __reg_f6_OFFSET 0x18
|
||||
#define __reg_f7_OFFSET 0x1C
|
||||
#define __reg_f8_OFFSET 0x20
|
||||
#define __reg_f9_OFFSET 0x24
|
||||
#define __reg_f10_OFFSET 0x28
|
||||
#define __reg_f11_OFFSET 0x2C
|
||||
#define __reg_f12_OFFSET 0x30
|
||||
#define __reg_f13_OFFSET 0x34
|
||||
#define __reg_f14_OFFSET 0x38
|
||||
#define __reg_f15_OFFSET 0x3C
|
||||
#define __reg_f16_OFFSET 0x40
|
||||
#define __reg_f17_OFFSET 0x44
|
||||
#define __reg_f18_OFFSET 0x48
|
||||
#define __reg_f19_OFFSET 0x4C
|
||||
#define __reg_f20_OFFSET 0x50
|
||||
#define __reg_f21_OFFSET 0x54
|
||||
#define __reg_f22_OFFSET 0x58
|
||||
#define __reg_f23_OFFSET 0x5C
|
||||
#define __reg_f24_OFFSET 0x60
|
||||
#define __reg_f25_OFFSET 0x64
|
||||
#define __reg_f26_OFFSET 0x68
|
||||
#define __reg_f27_OFFSET 0x6C
|
||||
#define __reg_f28_OFFSET 0x70
|
||||
#define __reg_f29_OFFSET 0x74
|
||||
#define __reg_f30_OFFSET 0x78
|
||||
#define __reg_f31_OFFSET 0x7C
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* _PORT_CONFIG_H_ */
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
#include "port_config.h"
|
||||
|
||||
.global port_sched_start
|
||||
.extern k_curr_task
|
||||
.extern k_next_task
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.type port_sched_start, %function
|
||||
port_sched_start:
|
||||
|
||||
/* load sp from k_curr_task->sp */
|
||||
lw t0, k_curr_task
|
||||
/* sp = k_curr_task->sp */
|
||||
lw sp, (t0)
|
||||
j restore_context
|
||||
|
||||
|
||||
.align 2
|
||||
.type restore_context, %function
|
||||
restore_context:
|
||||
// restore context
|
||||
lw t0, __reg_mepc_OFFSET(sp)
|
||||
csrw mepc, t0
|
||||
lw t0, __reg_mstatus_OFFSET(sp)
|
||||
csrw mstatus, t0
|
||||
|
||||
lw x1, __reg_x1_OFFSET(sp)
|
||||
lw x3, __reg_x3_OFFSET(sp)
|
||||
lw x4, __reg_x4_OFFSET(sp)
|
||||
lw x5, __reg_x5_OFFSET(sp)
|
||||
lw x6, __reg_x6_OFFSET(sp)
|
||||
lw x7, __reg_x7_OFFSET(sp)
|
||||
lw x8, __reg_x8_OFFSET(sp)
|
||||
lw x9, __reg_x9_OFFSET(sp)
|
||||
lw x10, __reg_x10_OFFSET(sp)
|
||||
lw x11, __reg_x11_OFFSET(sp)
|
||||
lw x12, __reg_x12_OFFSET(sp)
|
||||
lw x13, __reg_x13_OFFSET(sp)
|
||||
lw x14, __reg_x14_OFFSET(sp)
|
||||
lw x15, __reg_x15_OFFSET(sp)
|
||||
lw x16, __reg_x16_OFFSET(sp)
|
||||
lw x17, __reg_x17_OFFSET(sp)
|
||||
lw x18, __reg_x18_OFFSET(sp)
|
||||
lw x19, __reg_x19_OFFSET(sp)
|
||||
lw x20, __reg_x20_OFFSET(sp)
|
||||
lw x21, __reg_x21_OFFSET(sp)
|
||||
lw x22, __reg_x22_OFFSET(sp)
|
||||
lw x23, __reg_x23_OFFSET(sp)
|
||||
lw x24, __reg_x24_OFFSET(sp)
|
||||
lw x25, __reg_x25_OFFSET(sp)
|
||||
lw x26, __reg_x26_OFFSET(sp)
|
||||
lw x27, __reg_x27_OFFSET(sp)
|
||||
lw x28, __reg_x28_OFFSET(sp)
|
||||
lw x29, __reg_x29_OFFSET(sp)
|
||||
lw x30, __reg_x30_OFFSET(sp)
|
||||
lw x31, __reg_x31_OFFSET(sp)
|
||||
addi sp, sp, 128
|
||||
|
||||
#if ARCH_RISCV_FPU
|
||||
flw f0, __reg_f0_OFFSET(sp)
|
||||
flw f1, __reg_f1_OFFSET(sp)
|
||||
flw f2, __reg_f2_OFFSET(sp)
|
||||
flw f3, __reg_f3_OFFSET(sp)
|
||||
flw f4, __reg_f4_OFFSET(sp)
|
||||
flw f5, __reg_f5_OFFSET(sp)
|
||||
flw f6, __reg_f6_OFFSET(sp)
|
||||
flw f7, __reg_f7_OFFSET(sp)
|
||||
flw f8, __reg_f8_OFFSET(sp)
|
||||
flw f9, __reg_f9_OFFSET(sp)
|
||||
flw f10, __reg_f10_OFFSET(sp)
|
||||
flw f11, __reg_f11_OFFSET(sp)
|
||||
flw f12, __reg_f12_OFFSET(sp)
|
||||
flw f13, __reg_f13_OFFSET(sp)
|
||||
flw f14, __reg_f14_OFFSET(sp)
|
||||
flw f15, __reg_f15_OFFSET(sp)
|
||||
flw f16, __reg_f16_OFFSET(sp)
|
||||
flw f17, __reg_f17_OFFSET(sp)
|
||||
flw f18, __reg_f18_OFFSET(sp)
|
||||
flw f19, __reg_f19_OFFSET(sp)
|
||||
flw f20, __reg_f20_OFFSET(sp)
|
||||
flw f21, __reg_f21_OFFSET(sp)
|
||||
flw f22, __reg_f22_OFFSET(sp)
|
||||
flw f23, __reg_f23_OFFSET(sp)
|
||||
flw f24, __reg_f24_OFFSET(sp)
|
||||
flw f25, __reg_f25_OFFSET(sp)
|
||||
flw f26, __reg_f26_OFFSET(sp)
|
||||
flw f27, __reg_f27_OFFSET(sp)
|
||||
flw f28, __reg_f28_OFFSET(sp)
|
||||
flw f29, __reg_f29_OFFSET(sp)
|
||||
flw f30, __reg_f30_OFFSET(sp)
|
||||
flw f31, __reg_f31_OFFSET(sp)
|
||||
addi sp, sp, 128
|
||||
#endif
|
||||
|
||||
mret
|
||||
|
||||
|
||||
/* just switch at Software interrupt */
|
||||
.align 2
|
||||
.global SW_Handler
|
||||
SW_Handler:
|
||||
#if ARCH_RISCV_FPU
|
||||
addi sp, sp, -128
|
||||
fsw f0, __reg_f0_OFFSET(sp)
|
||||
fsw f1, __reg_f1_OFFSET(sp)
|
||||
fsw f2, __reg_f2_OFFSET(sp)
|
||||
fsw f3, __reg_f3_OFFSET(sp)
|
||||
fsw f4, __reg_f4_OFFSET(sp)
|
||||
fsw f5, __reg_f5_OFFSET(sp)
|
||||
fsw f6, __reg_f6_OFFSET(sp)
|
||||
fsw f7, __reg_f7_OFFSET(sp)
|
||||
fsw f8, __reg_f8_OFFSET(sp)
|
||||
fsw f9, __reg_f9_OFFSET(sp)
|
||||
fsw f10, __reg_f10_OFFSET(sp)
|
||||
fsw f11, __reg_f11_OFFSET(sp)
|
||||
fsw f12, __reg_f12_OFFSET(sp)
|
||||
fsw f13, __reg_f13_OFFSET(sp)
|
||||
fsw f14, __reg_f14_OFFSET(sp)
|
||||
fsw f15, __reg_f15_OFFSET(sp)
|
||||
fsw f16, __reg_f16_OFFSET(sp)
|
||||
fsw f17, __reg_f17_OFFSET(sp)
|
||||
fsw f18, __reg_f18_OFFSET(sp)
|
||||
fsw f19, __reg_f19_OFFSET(sp)
|
||||
fsw f20, __reg_f20_OFFSET(sp)
|
||||
fsw f21, __reg_f21_OFFSET(sp)
|
||||
fsw f22, __reg_f22_OFFSET(sp)
|
||||
fsw f23, __reg_f23_OFFSET(sp)
|
||||
fsw f24, __reg_f24_OFFSET(sp)
|
||||
fsw f25, __reg_f25_OFFSET(sp)
|
||||
fsw f26, __reg_f26_OFFSET(sp)
|
||||
fsw f27, __reg_f27_OFFSET(sp)
|
||||
fsw f28, __reg_f28_OFFSET(sp)
|
||||
fsw f29, __reg_f29_OFFSET(sp)
|
||||
fsw f30, __reg_f30_OFFSET(sp)
|
||||
fsw f31, __reg_f31_OFFSET(sp)
|
||||
#endif
|
||||
addi sp, sp, -128
|
||||
sw t0, __reg_x5_OFFSET(sp)
|
||||
|
||||
/* disable HPE */
|
||||
// li t0, 0x20
|
||||
// csrs 0x804, t0
|
||||
|
||||
csrr t0, mstatus
|
||||
sw t0, __reg_mstatus_OFFSET(sp)
|
||||
csrr t0, mepc
|
||||
sw t0, __reg_mepc_OFFSET(sp)
|
||||
|
||||
sw x1, __reg_x1_OFFSET(sp)
|
||||
sw x3, __reg_x3_OFFSET(sp)
|
||||
sw x4, __reg_x4_OFFSET(sp)
|
||||
|
||||
sw x6, __reg_x6_OFFSET(sp)
|
||||
sw x7, __reg_x7_OFFSET(sp)
|
||||
sw x8, __reg_x8_OFFSET(sp)
|
||||
sw x9, __reg_x9_OFFSET(sp)
|
||||
sw x10, __reg_x10_OFFSET(sp)
|
||||
sw x11, __reg_x11_OFFSET(sp)
|
||||
sw x12, __reg_x12_OFFSET(sp)
|
||||
sw x13, __reg_x13_OFFSET(sp)
|
||||
sw x14, __reg_x14_OFFSET(sp)
|
||||
sw x15, __reg_x15_OFFSET(sp)
|
||||
sw x16, __reg_x16_OFFSET(sp)
|
||||
sw x17, __reg_x17_OFFSET(sp)
|
||||
sw x18, __reg_x18_OFFSET(sp)
|
||||
sw x19, __reg_x19_OFFSET(sp)
|
||||
sw x20, __reg_x20_OFFSET(sp)
|
||||
sw x21, __reg_x21_OFFSET(sp)
|
||||
sw x22, __reg_x22_OFFSET(sp)
|
||||
sw x23, __reg_x23_OFFSET(sp)
|
||||
sw x24, __reg_x24_OFFSET(sp)
|
||||
sw x25, __reg_x25_OFFSET(sp)
|
||||
sw x26, __reg_x26_OFFSET(sp)
|
||||
sw x27, __reg_x27_OFFSET(sp)
|
||||
sw x28, __reg_x28_OFFSET(sp)
|
||||
sw x29, __reg_x29_OFFSET(sp)
|
||||
sw x30, __reg_x30_OFFSET(sp)
|
||||
sw x31, __reg_x31_OFFSET(sp)
|
||||
|
||||
/* switch to irq stk */
|
||||
mv t0, sp
|
||||
lw sp, k_irq_stk_top /* cpu_initÖмõÈ¥Ò»¸ö×Ö¿Õ¼ä */
|
||||
sw t0, 0(sp)
|
||||
/* clear software interrupt */
|
||||
call sw_clearpend
|
||||
/* resume sp */
|
||||
lw sp, 0(sp)
|
||||
|
||||
la t0, k_curr_task // t0 = &k_curr_task
|
||||
la t1, k_next_task // t1 = &k_next_task
|
||||
// save sp to k_curr_task.sp
|
||||
lw t2, (t0)
|
||||
sw sp, (t2)
|
||||
|
||||
# switch task
|
||||
# k_curr_task = k_next_task
|
||||
lw t1, (t1)
|
||||
sw t1, (t0)
|
||||
# load new task sp
|
||||
lw sp, (t1)
|
||||
|
||||
/* new thread restore */
|
||||
lw t0, __reg_mstatus_OFFSET(sp)
|
||||
csrw mstatus, t0
|
||||
lw t0, __reg_mepc_OFFSET(sp)
|
||||
csrw mepc, t0
|
||||
|
||||
lw x1, __reg_x1_OFFSET(sp)
|
||||
lw x3, __reg_x3_OFFSET(sp)
|
||||
lw x4, __reg_x4_OFFSET(sp)
|
||||
lw x5, __reg_x5_OFFSET(sp)
|
||||
lw x6, __reg_x6_OFFSET(sp)
|
||||
lw x7, __reg_x7_OFFSET(sp)
|
||||
lw x8, __reg_x8_OFFSET(sp)
|
||||
lw x9, __reg_x9_OFFSET(sp)
|
||||
lw x10, __reg_x10_OFFSET(sp)
|
||||
lw x11, __reg_x11_OFFSET(sp)
|
||||
lw x12, __reg_x12_OFFSET(sp)
|
||||
lw x13, __reg_x13_OFFSET(sp)
|
||||
lw x14, __reg_x14_OFFSET(sp)
|
||||
lw x15, __reg_x15_OFFSET(sp)
|
||||
lw x16, __reg_x16_OFFSET(sp)
|
||||
lw x17, __reg_x17_OFFSET(sp)
|
||||
lw x18, __reg_x18_OFFSET(sp)
|
||||
lw x19, __reg_x19_OFFSET(sp)
|
||||
lw x20, __reg_x20_OFFSET(sp)
|
||||
lw x21, __reg_x21_OFFSET(sp)
|
||||
lw x22, __reg_x22_OFFSET(sp)
|
||||
lw x23, __reg_x23_OFFSET(sp)
|
||||
lw x24, __reg_x24_OFFSET(sp)
|
||||
lw x25, __reg_x25_OFFSET(sp)
|
||||
lw x26, __reg_x26_OFFSET(sp)
|
||||
lw x27, __reg_x27_OFFSET(sp)
|
||||
lw x28, __reg_x28_OFFSET(sp)
|
||||
lw x29, __reg_x29_OFFSET(sp)
|
||||
lw x30, __reg_x30_OFFSET(sp)
|
||||
lw x31, __reg_x31_OFFSET(sp)
|
||||
addi sp, sp, 128
|
||||
|
||||
#if ARCH_RISCV_FPU
|
||||
flw f0, __reg_f0_OFFSET(sp)
|
||||
flw f1, __reg_f1_OFFSET(sp)
|
||||
flw f2, __reg_f2_OFFSET(sp)
|
||||
flw f3, __reg_f3_OFFSET(sp)
|
||||
flw f4, __reg_f4_OFFSET(sp)
|
||||
flw f5, __reg_f5_OFFSET(sp)
|
||||
flw f6, __reg_f6_OFFSET(sp)
|
||||
flw f7, __reg_f7_OFFSET(sp)
|
||||
flw f8, __reg_f8_OFFSET(sp)
|
||||
flw f9, __reg_f9_OFFSET(sp)
|
||||
flw f10, __reg_f10_OFFSET(sp)
|
||||
flw f11, __reg_f11_OFFSET(sp)
|
||||
flw f12, __reg_f12_OFFSET(sp)
|
||||
flw f13, __reg_f13_OFFSET(sp)
|
||||
flw f14, __reg_f14_OFFSET(sp)
|
||||
flw f15, __reg_f15_OFFSET(sp)
|
||||
flw f16, __reg_f16_OFFSET(sp)
|
||||
flw f17, __reg_f17_OFFSET(sp)
|
||||
flw f18, __reg_f18_OFFSET(sp)
|
||||
flw f19, __reg_f19_OFFSET(sp)
|
||||
flw f20, __reg_f20_OFFSET(sp)
|
||||
flw f21, __reg_f21_OFFSET(sp)
|
||||
flw f22, __reg_f22_OFFSET(sp)
|
||||
flw f23, __reg_f23_OFFSET(sp)
|
||||
flw f24, __reg_f24_OFFSET(sp)
|
||||
flw f25, __reg_f25_OFFSET(sp)
|
||||
flw f26, __reg_f26_OFFSET(sp)
|
||||
flw f27, __reg_f27_OFFSET(sp)
|
||||
flw f28, __reg_f28_OFFSET(sp)
|
||||
flw f29, __reg_f29_OFFSET(sp)
|
||||
flw f30, __reg_f30_OFFSET(sp)
|
||||
flw f31, __reg_f31_OFFSET(sp)
|
||||
addi sp, sp, 128
|
||||
#endif
|
||||
|
||||
mret
|
||||
@@ -0,0 +1,90 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_BARRIER_H_
|
||||
#define _TOS_BARRIER_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_BARRIER_EN > 0
|
||||
|
||||
typedef struct k_barrier_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
pend_obj_t pend_obj;
|
||||
k_barrier_cnt_t count;
|
||||
} k_barrier_t;
|
||||
|
||||
/**
|
||||
* @brief Create a thread barrier.
|
||||
*
|
||||
* @attention the count must be greater then zero.
|
||||
*
|
||||
* @param[in] barrier the barrier.
|
||||
* @param[in] count the number of threads(task) must call tos_barrier_pend before any of them successfully return from the call.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_BARRIER_COUNT_INVALID the count is equals to zero.
|
||||
*/
|
||||
__API__ k_err_t tos_barrier_create(k_barrier_t *barrier, k_barrier_cnt_t count);
|
||||
|
||||
/**
|
||||
* @brief Destroy a thread barrier.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] barrier the barrier.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_BARRIER_COUNT_INVALID the count is equals to zero.
|
||||
*/
|
||||
__API__ k_err_t tos_barrier_destroy(k_barrier_t *barrier);
|
||||
|
||||
/**
|
||||
* @brief Pend on a barrier.
|
||||
*
|
||||
* @attention until (countdownlatch->count) of tasks have called the pend, the pender would wake up.
|
||||
*
|
||||
* @param[in] barrier the barrier.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_BARRIER_OVERFLOW the barrier is pended too many times.
|
||||
*/
|
||||
__API__ k_err_t tos_barrier_pend(k_barrier_t *barrier);
|
||||
|
||||
/**
|
||||
* @brief Reset a barrier.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] barrier the barrier.
|
||||
* @param[in] count the count of the barrier to be reset.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_barrier_reset(k_barrier_t *barrier, k_barrier_cnt_t count);
|
||||
|
||||
#endif /* TOS_CFG_BARRIER_EN */
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_BARRIER_H_ */
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_BINARY_HEAP_H_
|
||||
#define _TOS_BINARY_HEAP_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
typedef int (*k_bin_heap_cmp)(void *first, void *second);
|
||||
|
||||
typedef struct k_binary_heap_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
size_t total;
|
||||
|
||||
k_bin_heap_cmp cmp;
|
||||
size_t item_size;
|
||||
size_t item_cnt;
|
||||
uint8_t *pool;
|
||||
} k_bin_heap_t;
|
||||
|
||||
#define BIN_HEAP_FIRST_ITEM(bin_heap) (void *)(&bin_heap->pool[0])
|
||||
#define BIN_HEAP_LAST_ITEM(bin_heap) (void *)(&bin_heap->pool[bin_heap->total * bin_heap->item_size])
|
||||
#define BIN_HEAP_THE_ITEM(bin_heap, index) (void *)(&bin_heap->pool[index * bin_heap->item_size])
|
||||
|
||||
#define BIN_HEAP_PARENT(index) ((index - 1) / 2)
|
||||
#define BIN_HEAP_RCHILD(index) (2 * (index + 1))
|
||||
#define BIN_HEAP_LSIBLING(index) (index - 1)
|
||||
|
||||
/**
|
||||
* @brief Create a binary heap.
|
||||
* create a binary heap.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] bin_heap pointer to the handler of the binary heap.
|
||||
* @param[in] pool pool buffer of the binary heap.
|
||||
* @param[in] item_cnt item count of the binary heap.
|
||||
* @param[in] item_size size of each item of the binary heap.
|
||||
* @param[in] cmp compare function to determine two items which is bigger or smaller.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_bin_heap_create(k_bin_heap_t *bin_heap, void *pool, size_t item_cnt, size_t item_size, k_bin_heap_cmp cmp);
|
||||
|
||||
/**
|
||||
* @brief Destroy a binary heap.
|
||||
* destroy a binary heap.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] bin_heap pointer to the handler of the binary heap.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_bin_heap_destroy(k_bin_heap_t *bin_heap);
|
||||
|
||||
/**
|
||||
* @brief Create a binary heap with a dynamic allocated pool.
|
||||
* create a binary heap with a dynamic allocated pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] bin_heap pointer to the handler of the binary heap.
|
||||
* @param[in] item_cnt item count of the binary heap.
|
||||
* @param[in] item_size size of each item of the binary heap.
|
||||
* @param[in] cmp compare function to determine two items which is bigger or smaller.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_bin_heap_create_dyn(k_bin_heap_t *bin_heap, size_t item_cnt, size_t item_size, k_bin_heap_cmp cmp);
|
||||
|
||||
/**
|
||||
* @brief Destroy a binary heap with a dynamic allocated pool.
|
||||
* destroy a binary heap with a dynamic allocated pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] bin_heap pointer to the handler of the binary heap.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_bin_heap_destroy_dyn(k_bin_heap_t *bin_heap);
|
||||
|
||||
/**
|
||||
* @brief Push an item.
|
||||
* push an item into the binary heap.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] bin_heap pointer to the handler of the binary heap.
|
||||
* @param[in] item the item to be pushed.
|
||||
* @param[in] item_size size of the item(should be consistent with the item_size passed to tos_bin_heap_create).
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_BIN_HEAP_ITEM_SIZE_NOT_MATCH the item_size is not consistent with the item_size passed to tos_bin_heap_create.
|
||||
* @retval #K_ERR_BIN_HEAP_FULL the binary heap is full.
|
||||
*/
|
||||
__API__ k_err_t tos_bin_heap_push(k_bin_heap_t *bin_heap, void *item, size_t item_size);
|
||||
|
||||
/**
|
||||
* @brief Pop an item.
|
||||
* pop an item from the binary heap.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] bin_heap pointer to the handler of the binary heap.
|
||||
* @param[out] item buffer to hold the item poped.
|
||||
* @param[out] item_size size of the item poped(should be consistent with the item_size passed to tos_bin_heap_create).
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_BIN_HEAP_EMPTY the ring queue is empty.
|
||||
*/
|
||||
__API__ k_err_t tos_bin_heap_pop(k_bin_heap_t *bin_heap, void *item, size_t *item_size);
|
||||
|
||||
/**
|
||||
* @brief Flush the binary heap.
|
||||
* flush the binary heap.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] bin_heap pointer to the handler of the binary heap.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_bin_heap_flush(k_bin_heap_t *bin_heap);
|
||||
|
||||
/**
|
||||
* @brief Whether the binary heap is empty.
|
||||
* Whether the binary heap is empty.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] bin_heap pointer to the handler of the binary heap.
|
||||
*
|
||||
* @return whether the binary heap is emtpy.
|
||||
* @retval #0 the binary heap is not empty.
|
||||
* @retval #Not 0 the binary heap is empty.
|
||||
*/
|
||||
__API__ int tos_bin_heap_is_empty(k_bin_heap_t *bin_heap);
|
||||
|
||||
/**
|
||||
* @brief Whether the binary heap is full.
|
||||
* Whether the binary heap is full.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] bin_heap pointer to the handler of the binary heap.
|
||||
*
|
||||
* @return whether the binary hea is full.
|
||||
* @retval #0 the binary hea is not full.
|
||||
* @retval #Not 0 the binary hea is full.
|
||||
*/
|
||||
__API__ int tos_bin_heap_is_full(k_bin_heap_t *bin_heap);
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_BINARY_HEAP_H_ */
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_BITMAP_H_
|
||||
#define _TOS_BITMAP_H_
|
||||
|
||||
typedef uint32_t k_bmtbl_t;
|
||||
|
||||
typedef struct k_bitmap_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
uint32_t bit_ndx_max;
|
||||
uint32_t bit_max;
|
||||
k_bmtbl_t *bitmap_tbl;
|
||||
} k_bitmap_t;
|
||||
|
||||
#define K_BITMAP_SLOT_SIZE (sizeof(k_bmtbl_t) * 8) /* in bits */
|
||||
|
||||
#define K_BITMAP_TBL_SIZE(bit_max) ((bit_max + K_BITMAP_SLOT_SIZE - 1) / K_BITMAP_SLOT_SIZE)
|
||||
|
||||
#define K_BITMAP_NDX(bit) ((bit) >> 5u) /* bit / K_BITMAP_SLOT_SIZE */
|
||||
|
||||
#define K_BITMAP_BIT(bit) ((uint32_t)1u << (K_BITMAP_SLOT_SIZE - 1u - ((bit) & (K_BITMAP_SLOT_SIZE - 1u))))
|
||||
|
||||
#define TOS_BITMAP_SIZE(bit_max) (K_BITMAP_TBL_SIZE(bit_max))
|
||||
|
||||
/**
|
||||
* @brief Create a bitmap with all bit are set to 0.
|
||||
*
|
||||
* @attention the size of bitmap_tabl can be caculated by the macro TOS_BITMAP_SIZE
|
||||
*
|
||||
* @param[in] bitmap pointer to the handler of the bitmap.
|
||||
* @param[in] bitmap_tbl bitmap table buffer.
|
||||
* @param[in] bit_max maximal bit.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_OBJ_PTR_NULL bitmap is NULL.
|
||||
*/
|
||||
__API__ k_err_t tos_bitmap_create_empty(k_bitmap_t *bitmap, k_bmtbl_t *bitmap_tbl, uint32_t bit_max);
|
||||
|
||||
/**
|
||||
* @brief Create a bitmap with all bit are set to 1.
|
||||
*
|
||||
* @attention the size of bitmap_tabl can be caculated by the macro TOS_BITMAP_SIZE
|
||||
*
|
||||
* @param[in] bitmap pointer to the handler of the bitmap.
|
||||
* @param[in] bitmap_tbl bitmap table buffer.
|
||||
* @param[in] bit_max maximal bit.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_OBJ_PTR_NULL bitmap is NULL.
|
||||
*/
|
||||
__API__ k_err_t tos_bitmap_create_full(k_bitmap_t *bitmap, k_bmtbl_t *bitmap_tbl, uint32_t bit_max);
|
||||
|
||||
/**
|
||||
* @brief Destroy the bitmap.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] bitmap pointer to the handler of the bitmap.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_OBJ_PTR_NULL bitmap is NULL.
|
||||
*/
|
||||
__API__ k_err_t tos_bitmap_destroy(k_bitmap_t *bitmap);
|
||||
|
||||
/**
|
||||
* @brief Set a certain bit of the bitmap to 1.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] bitmap pointer to the handler of the bitmap.
|
||||
* @param[in] bit the bit to set.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_BITMAP_EXCEED bit is larger than the bit_max passed to tos_bitmap_create_*.
|
||||
*/
|
||||
__API__ k_err_t tos_bitmap_set(k_bitmap_t *bitmap, uint32_t bit);
|
||||
|
||||
/**
|
||||
* @brief Set a certain bit of the bitmap to 0.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] bitmap pointer to the handler of the bitmap.
|
||||
* @param[in] bit the bit to set.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_BITMAP_EXCEED bit is larger than the bit_max passed to tos_bitmap_create_*.
|
||||
*/
|
||||
__API__ k_err_t tos_bitmap_reset(k_bitmap_t *bitmap, uint32_t bit);
|
||||
|
||||
/**
|
||||
* @brief Test whether a certain bit of the bitmap is 1.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] bitmap pointer to the handler of the bitmap.
|
||||
* @param[in] bit the bit to set.
|
||||
*
|
||||
* @return whether the bit is 1
|
||||
* @retval #K_TRUE the certain bit is 1.
|
||||
* @retval #K_FALSE the certain bit is not 1(that means is 0).
|
||||
*/
|
||||
__API__ int tos_bitmap_is_set(k_bitmap_t *bitmap, uint32_t bit);
|
||||
|
||||
/**
|
||||
* @brief Test whether a certain bit of the bitmap is 0.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] bitmap pointer to the handler of the bitmap.
|
||||
* @param[in] bit the bit to set.
|
||||
*
|
||||
* @return whether the bit is 0
|
||||
* @retval #K_TRUE the certain bit is 0.
|
||||
* @retval #K_FALSE the certain bit is not 0(that means is 1).
|
||||
*/
|
||||
__API__ int tos_bitmap_is_reset(k_bitmap_t *bitmap, uint32_t bit);
|
||||
|
||||
/**
|
||||
* @brief Get the lowest significant bit of the bitmap.
|
||||
*
|
||||
* @attention The very first bit which is set to 1.
|
||||
*
|
||||
* @param[in] bitmap pointer to the handler of the bitmap.
|
||||
*
|
||||
* @return the lowest significant bit of the bitmap.
|
||||
*/
|
||||
__API__ int tos_bitmap_lsb(k_bitmap_t *bitmap);
|
||||
|
||||
#endif /* _TOS_BITMAP_H_ */
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_CHAR_FIFO_H_
|
||||
#define _TOS_CHAR_FIFO_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
typedef struct k_char_fifo_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
k_ring_q_t ring_q;
|
||||
} k_chr_fifo_t;
|
||||
|
||||
/**
|
||||
* @brief Create a character fifo.
|
||||
* Create a character fifo.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] fifo pointer to the handler of the fifo.
|
||||
* @param[in] buffer memory buffer provided to be as the inner buffer.
|
||||
* @param[in] size size of the memory buffer.
|
||||
*
|
||||
* @return errno
|
||||
* @retval #K_ERR_OBJ_PTR_NULL fifo is a NULL pointer.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_chr_fifo_create(k_chr_fifo_t *chr_fifo, void *buffer, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a character fifo.
|
||||
* Destroy a character fifo.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] fifo pointer to the handler of the fifo.
|
||||
*
|
||||
* @return errno
|
||||
* @retval #K_ERR_OBJ_PTR_NULL fifo is a NULL pointer.
|
||||
* @retval #K_ERR_OBJ_INVALID not a valid pointer to a fifo.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_chr_fifo_destroy(k_chr_fifo_t *chr_fifo);
|
||||
|
||||
/**
|
||||
* @brief Create a character fifo with a dynamic allocated buffer.
|
||||
* Create a character fifo with a dynamic allocated buffer.
|
||||
*
|
||||
* @attention the buffer is dynamic allocated(tos_mmheap_alloc)
|
||||
*
|
||||
* @param[in] fifo pointer to the handler of the fifo.
|
||||
* @param[in] fifo_size size of the fifo.
|
||||
*
|
||||
* @return errno
|
||||
* @retval #K_ERR_OBJ_PTR_NULL fifo is a NULL pointer.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_chr_fifo_create_dyn(k_chr_fifo_t *chr_fifo, size_t fifo_size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a character fifo with a dynamic allocated buffer.
|
||||
* Destroy a character fifo with a dynamic allocated buffer.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] fifo pointer to the handler of the fifo.
|
||||
*
|
||||
* @return errno
|
||||
* @retval #K_ERR_OBJ_PTR_NULL fifo is a NULL pointer.
|
||||
* @retval #K_ERR_OBJ_INVALID not a valid pointer to a fifo.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_chr_fifo_destroy_dyn(k_chr_fifo_t *chr_fifo);
|
||||
|
||||
/**
|
||||
* @brief Push data into character fifo.
|
||||
* Push one single data into the character fifo.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] fifo pointer to the handler of the character fifo.
|
||||
* @param[in] data data to push into the fifo.
|
||||
*
|
||||
* @return errno
|
||||
* @retval #K_ERR_RING_Q_FULL the character fifo is full.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_chr_fifo_push(k_chr_fifo_t *chr_fifo, uint8_t data);
|
||||
|
||||
/**
|
||||
* @brief Push stream into character fifo.
|
||||
* Push a stream data into the character fifo.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] fifo pointer to the handler of the character fifo.
|
||||
* @param[IN] stream stream to be pushed into the character fifo.
|
||||
* @param[OUT] size size of the stream.
|
||||
*
|
||||
* @return the actual number of the data pushed into the character fifo.
|
||||
*/
|
||||
__API__ int tos_chr_fifo_push_stream(k_chr_fifo_t *chr_fifo, uint8_t *stream, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Pop data from character fifo.
|
||||
* Pop one single data from the character fifo.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] fifo pointer to the handler of the character fifo.
|
||||
* @param[OUT] out one signle buffer to hold the data poped from the character fifo.
|
||||
*
|
||||
* @return errno
|
||||
* @retval #K_ERR_FIFO_EMPTY the character fifo is empty.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_chr_fifo_pop(k_chr_fifo_t *chr_fifo, uint8_t *out);
|
||||
|
||||
/**
|
||||
* @brief Pop stream from character fifo.
|
||||
* Pop a stream data from the character fifo.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] fifo pointer to the handler of the character fifo.
|
||||
* @param[OUT] buffer pointer to the buffer to receive the stream poped.
|
||||
* @param[OUT] size size of the buffer.
|
||||
*
|
||||
* @return the actual number of the data poped from the character fifo.
|
||||
*/
|
||||
__API__ int tos_chr_fifo_pop_stream(k_chr_fifo_t *chr_fifo, uint8_t *buffer, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Flush character fifo.
|
||||
* Flush/reset the character fifo.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] fifo pointer to the handler of the character fifo.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
__API__ k_err_t tos_chr_fifo_flush(k_chr_fifo_t *chr_fifo);
|
||||
|
||||
/**
|
||||
* @brief Whether the character fifo is empty.
|
||||
* Whether the character fifo is empty.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] fifo pointer to the handler of the character fifo.
|
||||
*
|
||||
* @return whether the character fifo is emtpy.
|
||||
* @retval #0 the character fifo is not empty.
|
||||
* @retval #Not 0 the character fifo is empty.
|
||||
*/
|
||||
__API__ int tos_chr_fifo_is_empty(k_chr_fifo_t *chr_fifo);
|
||||
|
||||
/**
|
||||
* @brief Whether the character fifo is full.
|
||||
* Whether the character fifo is full.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] fifo pointer to the handler of the character fifo.
|
||||
*
|
||||
* @return whether the character fifo is full.
|
||||
* @retval #0 the character fifo is not full.
|
||||
* @retval #Not 0 the character fifo is full.
|
||||
*/
|
||||
__API__ int tos_chr_fifo_is_full(k_chr_fifo_t *chr_fifo);
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_CHAR_FIFO_H_ */
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_COMPILER_H_
|
||||
#define _TOS_COMPILER_H_
|
||||
|
||||
/* function with __API__ prefix, api for user */
|
||||
#define __API__
|
||||
|
||||
/* function with __KNL__ prefix, only for kernel */
|
||||
#define __KNL__
|
||||
|
||||
/* function with __HOOK__ prefix, should be implemented by user */
|
||||
#define __HOOK__
|
||||
|
||||
/* function with __DEBUG__ prefix, only for debug */
|
||||
#define __DEBUG__
|
||||
|
||||
/* function with __PORT__ is architecture depended */
|
||||
#define __PORT__
|
||||
|
||||
/* CPP header guards */
|
||||
#ifdef __cplusplus
|
||||
#define __CDECLS_BEGIN extern "C" {
|
||||
#define __CDECLS_END }
|
||||
#else
|
||||
#define __CDECLS_BEGIN
|
||||
#define __CDECLS_END
|
||||
#endif
|
||||
|
||||
/*------------------ RealView Compiler -----------------*/
|
||||
#if defined(__CC_ARM)
|
||||
|
||||
#define ARMCC_V5
|
||||
|
||||
#define __ASM__ __asm
|
||||
#define __VOLATILE__ volatile
|
||||
|
||||
#define __INLINE__ inline
|
||||
#define __STATIC__ static
|
||||
|
||||
#if (__ARMCC_VERSION < 5060750) // how to know the exact number?
|
||||
#define __STATIC_INLINE__ static
|
||||
#else
|
||||
#define __STATIC_INLINE__ static inline
|
||||
#endif
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#define __UNUSED__ __attribute__((__unused__))
|
||||
#define __USED__ __attribute__((__used__))
|
||||
#define __PACKED__ __attribute__((packed))
|
||||
#define __ALIGNED__(x) __attribute__((aligned(x)))
|
||||
#define __PURE__ __attribute__((__pure__))
|
||||
#define __CONST__ __attribute__((__const__))
|
||||
#define __NO_RETURN__ __attribute__((__noreturn__))
|
||||
#define __WEAK__ __attribute__((weak))
|
||||
|
||||
/*------------------ ARM Compiler V6 -------------------*/
|
||||
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
|
||||
#define ARMCC_V6
|
||||
|
||||
#define __ASM__ __asm
|
||||
#define __VOLATILE__ volatile
|
||||
|
||||
#define __INLINE__ inline
|
||||
#define __STATIC__ static
|
||||
#define __STATIC_INLINE__ static inline
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#define __UNUSED__ __attribute__((__unused__))
|
||||
#define __USED__ __attribute__((__used__))
|
||||
#define __PACKED__ __attribute__((packed))
|
||||
#define __ALIGNED__(x) __attribute__((aligned(x)))
|
||||
#define __PURE__ __attribute__((__pure__))
|
||||
#define __CONST__ __attribute__((__const__))
|
||||
#define __NO_RETURN__ __attribute__((__noreturn__))
|
||||
#define __NAKED__ __attribute__((naked))
|
||||
#define __WEAK__ __attribute__((weak))
|
||||
|
||||
/*------------------ ICC Compiler ----------------------*/
|
||||
#elif defined(__ICCARM__) || defined(__ICC430__) // __IAR_SYSTEMS_ICC__
|
||||
|
||||
#define __ASM__ __asm
|
||||
#define __VOLATILE__ volatile
|
||||
|
||||
#define __INLINE__ inline
|
||||
#define __STATIC__ static
|
||||
#define __STATIC_INLINE__ static inline
|
||||
|
||||
#define likely(x) (x)
|
||||
#define unlikely(x) (x)
|
||||
#define __UNUSED__
|
||||
#define __USED__
|
||||
#define __PACKED__
|
||||
#define __ALIGNED__(x)
|
||||
#define __PURE__
|
||||
#define __CONST__
|
||||
#define __NO_RETURN__
|
||||
#define __NAKED__
|
||||
#define __WEAK__ __weak
|
||||
|
||||
/*------------------ ICC Compiler for STM8/AVR ----------------------*/
|
||||
#elif defined(__IAR_SYSTEMS_ICC__)
|
||||
|
||||
#define __ASM__ __asm
|
||||
#define __VOLATILE__ volatile
|
||||
|
||||
#define __INLINE__ inline
|
||||
#define __STATIC__ static
|
||||
#define __STATIC_INLINE__ static inline
|
||||
|
||||
#define likely(x) (x)
|
||||
#define unlikely(x) (x)
|
||||
#define __UNUSED__
|
||||
#define __USED__
|
||||
#define __PACKED__
|
||||
#define __ALIGNED__(x)
|
||||
#define __PURE__
|
||||
#define __CONST__
|
||||
#define __NO_RETURN__
|
||||
#define __NAKED__
|
||||
#define __WEAK__ __weak
|
||||
|
||||
/*------------------ GNU Compiler ----------------------*/
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
#define __ASM__ __asm
|
||||
#define __VOLATILE__ volatile
|
||||
|
||||
#define __INLINE__ inline
|
||||
#define __STATIC__ static
|
||||
#define __STATIC_INLINE__ static inline
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#define __UNUSED__ __attribute__((__unused__))
|
||||
#define __USED__ __attribute__((__used__))
|
||||
#define __PACKED__ __attribute__((packed))
|
||||
#define __ALIGNED__(x) __attribute__((aligned(x)))
|
||||
#define __PURE__ __attribute__((__pure__))
|
||||
#define __CONST__ __attribute__((__const__))
|
||||
#define __NO_RETURN__ __attribute__((__noreturn__))
|
||||
#define __NAKED__ __attribute__((naked))
|
||||
#define __WEAK__ __attribute__((weak))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _TOS_COMPILER_H_ */
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_COMPLETION_H_
|
||||
#define _TOS_COMPLETION_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_COMPLETION_EN > 0
|
||||
|
||||
typedef uint16_t completion_done_t;
|
||||
|
||||
typedef struct k_completion_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
pend_obj_t pend_obj;
|
||||
completion_done_t done;
|
||||
} k_completion_t;
|
||||
|
||||
/**
|
||||
* @brief Create a completion.
|
||||
* create a completion.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] completion pointer to the handler of the completion.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_completion_create(k_completion_t *completion);
|
||||
|
||||
/**
|
||||
* @brief Destroy a completion.
|
||||
* destroy a completion.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] completion pointer to the handler of the completion.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_OBJ_INVALID completion is not a valid pointer to completion
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_completion_destroy(k_completion_t *completion);
|
||||
|
||||
/**
|
||||
* @brief Pend a completion.
|
||||
* pend a completion.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] completion pointer to the handler of the completion.
|
||||
* @param[in] timeout how much time(in k_tick_t) we would like to wait.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PEND_NOWAIT we get nothing, and we don't wanna wait.
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED we can wait, but scheduler is locked.
|
||||
* @retval #K_ERR_PEND_TIMEOUT the time we wait is up, we get nothing.
|
||||
* @retval #K_ERR_PEND_DESTROY the completion we are pending is destroyed.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_completion_pend_timed(k_completion_t *completion, k_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Pend a completion.
|
||||
* pend a completion.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] completion pointer to the handler of the completion.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED we can wait, but scheduler is locked.
|
||||
* @retval #K_ERR_PEND_DESTROY the completion we are pending is destroyed.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_completion_pend(k_completion_t *completion);
|
||||
|
||||
/**
|
||||
* @brief Post a completion.
|
||||
* post a completion and wakeup one pending task.
|
||||
*
|
||||
* @attention when tos_completion_post return successfully, only one task who are waitting for the completion will be woken up.
|
||||
*
|
||||
* @param[in] completion pointer to the handler of the completion.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_COMPLETION_OVERFLOW we are nesting post a completion too much.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_completion_post(k_completion_t *completion);
|
||||
|
||||
/**
|
||||
* @brief Post a completion.
|
||||
* post a completion and wakeup all the pending task.
|
||||
*
|
||||
* @attention when tos_completion_post_all return successfully, all of the tasks who are waitting for the completion will be woken up.
|
||||
*
|
||||
* @param[in] completion pointer to the handler of the completion.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_COMPLETION_OVERFLOW we are nesting post a completion too much.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_completion_post_all(k_completion_t *completion);
|
||||
|
||||
/**
|
||||
* @brief Reset a completion.
|
||||
* reset a completion to un-done.
|
||||
*
|
||||
* @attention None.
|
||||
*
|
||||
* @param[in] completion pointer to the handler of the completion.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_completion_reset(k_completion_t *completion);
|
||||
|
||||
/**
|
||||
* @brief Test whether a completion is done.
|
||||
* test whether a completion is done.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] completion pointer to the handler of the completion.
|
||||
*
|
||||
* @return whether a completion is done
|
||||
* @retval K_TRUE the completion is done.
|
||||
* @retval K_FALSE the completion is not done.
|
||||
*/
|
||||
__API__ int tos_completion_is_done(k_completion_t *completion);
|
||||
|
||||
#endif /* TOS_CFG_COMPLETION_EN */
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_COMPLETION_H_ */
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_CONFIG_CHECK_H_
|
||||
#define _TOS_CONFIG_CHECK_H_
|
||||
|
||||
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN == 1u
|
||||
#error "INVALID config, tickless not supported in event-driven yet"
|
||||
#endif
|
||||
|
||||
#if (TOS_CFG_MMHEAP_EN > 0u) && (TOS_CFG_MMHEAP_DEFAULT_POOL_EN > 0u)
|
||||
#if !defined(TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE) || (TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE == 0u)
|
||||
#error "INVALID config, must define a valid TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else /* TOS_CFG_EVENT_DRIVEN_EN */
|
||||
|
||||
#if TOS_CFG_TASK_PRIO_MAX < 8u
|
||||
#error "INVALID config, TOS_CFG_TASK_PRIO_MAX must be >= 8"
|
||||
#endif
|
||||
|
||||
#if ((TOS_CFG_TIMER_EN > 0u) && !defined(TOS_CFG_TIMER_AS_PROC))
|
||||
#error "UNDECLARED config, TOS_CFG_TIMER_AS_PROC"
|
||||
#endif
|
||||
|
||||
#if (TOS_CFG_MMHEAP_EN > 0u) && (TOS_CFG_MMHEAP_DEFAULT_POOL_EN > 0u)
|
||||
#if !defined(TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE) || (TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE == 0u)
|
||||
#error "INVALID config, must define a valid TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_CPU_HRTIMER_EN
|
||||
#error "UNDECLARED config, TOS_CFG_CPU_HRTIMER_EN should be declared in 'port_config.h'"
|
||||
#elif (TOS_CFG_CPU_HRTIMER_EN > 0u) && !defined(TOS_CFG_CPU_HRTIMER_SIZE)
|
||||
#error "UNDECLARED config, TOS_CFG_CPU_HRTIMER_SIZE should be declared in 'port_config.h'"
|
||||
#elif (TOS_CFG_CPU_HRTIMER_EN > 0u) && ((TOS_CFG_CPU_HRTIMER_SIZE != CPU_WORD_SIZE_08) && \
|
||||
(TOS_CFG_CPU_HRTIMER_SIZE != CPU_WORD_SIZE_16) && \
|
||||
(TOS_CFG_CPU_HRTIMER_SIZE != CPU_WORD_SIZE_32) && \
|
||||
(TOS_CFG_CPU_HRTIMER_SIZE != CPU_WORD_SIZE_64))
|
||||
#error "INVALID config, TOS_CFG_CPU_HRTIMER_SIZE"
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT
|
||||
#error "UNDECLARED config, TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT, should be declared in 'port_config.h'"
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_CPU_BYTE_ORDER
|
||||
#error "UNDECLARED config, TOS_CFG_CPU_BYTE_ORDER, should be declared in 'port_config.h'"
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_CPU_STK_GROWTH
|
||||
#error "UNDECLARED config, TOS_CFG_CPU_STK_GROWTH, should be declared in 'port_config.h'"
|
||||
#elif ((TOS_CFG_CPU_STK_GROWTH != CPU_STK_GROWTH_ASCENDING) && \
|
||||
(TOS_CFG_CPU_STK_GROWTH != CPU_STK_GROWTH_DESCENDING))
|
||||
#error "INVALID config, TOS_CFG_CPU_STK_GROWTH"
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_CPU_ADDR_SIZE
|
||||
#error "UNDECLARED config, TOS_CFG_CPU_ADDR_SIZE, should be declared in 'port_config.h'"
|
||||
#elif ((TOS_CFG_CPU_ADDR_SIZE != CPU_WORD_SIZE_08) && \
|
||||
(TOS_CFG_CPU_ADDR_SIZE != CPU_WORD_SIZE_16) && \
|
||||
(TOS_CFG_CPU_ADDR_SIZE != CPU_WORD_SIZE_32) && \
|
||||
(TOS_CFG_CPU_ADDR_SIZE != CPU_WORD_SIZE_64))
|
||||
#error "INVALID config, TOS_CFG_CPU_ADDR_SIZE"
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_CPU_DATA_SIZE
|
||||
#error "UNDECLARED config, TOS_CFG_CPU_DATA_SIZE, should be declared in 'port_config.h'"
|
||||
#elif ((TOS_CFG_CPU_DATA_SIZE != CPU_WORD_SIZE_08) && \
|
||||
(TOS_CFG_CPU_DATA_SIZE != CPU_WORD_SIZE_16) && \
|
||||
(TOS_CFG_CPU_DATA_SIZE != CPU_WORD_SIZE_32) && \
|
||||
(TOS_CFG_CPU_DATA_SIZE != CPU_WORD_SIZE_64))
|
||||
#error "INVALID config, TOS_CFG_CPU_DATA_SIZE"
|
||||
#endif
|
||||
|
||||
#endif /* TOS_CFG_EVENT_DRIVEN_EN */
|
||||
|
||||
#endif /* _TOS_CONFIG_CHECK_H_ */
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_CONFIG_DEFAULT_H_
|
||||
#define _TOS_CONFIG_DEFAULT_H_
|
||||
|
||||
#ifndef TOS_CFG_EVENT_DRIVEN_EN
|
||||
#define TOS_CFG_EVENT_DRIVEN_EN 0u
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
|
||||
|
||||
/////////////////////////////////////////
|
||||
// disable round robin
|
||||
#ifdef TOS_CFG_ROUND_ROBIN_EN
|
||||
#undef TOS_CFG_ROUND_ROBIN_EN
|
||||
#endif
|
||||
#define TOS_CFG_ROUND_ROBIN_EN 0u
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
// disable dynamic task create
|
||||
#ifdef TOS_CFG_TASK_DYNAMIC_CREATE_EN
|
||||
#undef TOS_CFG_TASK_DYNAMIC_CREATE_EN
|
||||
#endif
|
||||
#define TOS_CFG_TASK_DYNAMIC_CREATE_EN 0u
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
// disable event
|
||||
#ifdef TOS_CFG_EVENT_EN
|
||||
#undef TOS_CFG_EVENT_EN
|
||||
#endif
|
||||
#define TOS_CFG_EVENT_EN 0u
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
// disable mutex
|
||||
#ifdef TOS_CFG_MUTEX_EN
|
||||
#undef TOS_CFG_MUTEX_EN
|
||||
#endif
|
||||
#define TOS_CFG_MUTEX_EN 0u
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
// disable semaphore
|
||||
#ifdef TOS_CFG_SEM_EN
|
||||
#undef TOS_CFG_SEM_EN
|
||||
#endif
|
||||
#define TOS_CFG_SEM_EN 0u
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
// disable the "traditional" timer
|
||||
#ifdef TOS_CFG_TIMER_EN
|
||||
#undef TOS_CFG_TIMER_EN
|
||||
#endif
|
||||
#define TOS_CFG_TIMER_EN 0u
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
// disable stack draught depth detact
|
||||
#ifdef TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN
|
||||
#undef TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN
|
||||
#endif
|
||||
#define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 0u
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
// enable mmheap
|
||||
#ifndef TOS_CFG_MMHEAP_EN
|
||||
#define TOS_CFG_MMHEAP_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_MMHEAP_DEFAULT_POOL_EN
|
||||
#define TOS_CFG_MMHEAP_DEFAULT_POOL_EN 1u
|
||||
#endif
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
// disable default
|
||||
#ifndef TOS_CFG_FAULT_BACKTRACE_EN
|
||||
#define TOS_CFG_FAULT_BACKTRACE_EN 0u
|
||||
#endif
|
||||
/////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////
|
||||
#ifndef TOS_CFG_CPU_SYSTICK_PRIO
|
||||
#define TOS_CFG_CPU_SYSTICK_PRIO 0u
|
||||
#endif
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
// disable default
|
||||
#ifndef TOS_CFG_PWR_MGR_EN
|
||||
#define TOS_CFG_PWR_MGR_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_TICKLESS_EN
|
||||
#define TOS_CFG_TICKLESS_EN 0u
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
// we donot really need these, it's a compromise to the compiler.
|
||||
#ifndef TOS_CFG_TASK_PRIO_MAX
|
||||
#define TOS_CFG_TASK_PRIO_MAX 8u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_IDLE_TASK_STK_SIZE
|
||||
#define TOS_CFG_IDLE_TASK_STK_SIZE 128u
|
||||
#endif
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
|
||||
#else /* TOS_CFG_EVENT_DRIVEN_EN */
|
||||
|
||||
#ifndef TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN
|
||||
#define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_TASK_DYNAMIC_CREATE_EN
|
||||
#define TOS_CFG_TASK_DYNAMIC_CREATE_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_ROUND_ROBIN_EN
|
||||
#define TOS_CFG_ROUND_ROBIN_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_EVENT_EN
|
||||
#define TOS_CFG_EVENT_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_MUTEX_EN
|
||||
#define TOS_CFG_MUTEX_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_MESSAGE_QUEUE_EN
|
||||
#define TOS_CFG_MESSAGE_QUEUE_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_MAIL_QUEUE_EN
|
||||
#define TOS_CFG_MAIL_QUEUE_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN
|
||||
#define TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_PRIORITY_MAIL_QUEUE_EN
|
||||
#define TOS_CFG_PRIORITY_MAIL_QUEUE_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_SEM_EN
|
||||
#define TOS_CFG_SEM_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_TIMER_EN
|
||||
#define TOS_CFG_TIMER_EN 0u
|
||||
#endif
|
||||
|
||||
#if (TOS_CFG_TIMER_EN > 0u) && !defined(TOS_CFG_TIMER_AS_PROC)
|
||||
#define TOS_CFG_TIMER_AS_PROC 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_IDLE_TASK_STK_SIZE
|
||||
#define TOS_CFG_IDLE_TASK_STK_SIZE 128u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_OBJECT_VERIFY_EN
|
||||
#define TOS_CFG_OBJECT_VERIFY_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_LIBC_PRINTF_EN
|
||||
#define TOS_CFG_LIBC_PRINTF_EN 1u // we enable this by default
|
||||
#endif
|
||||
|
||||
#if (TOS_CFG_TIMER_AS_PROC == 0u) && !defined(TOS_CFG_TIMER_TASK_PRIO)
|
||||
#define TOS_CFG_TIMER_TASK_PRIO (k_prio_t)(K_TASK_PRIO_IDLE - (k_prio_t)1u)
|
||||
#endif
|
||||
|
||||
#if (TOS_CFG_TIMER_AS_PROC == 0u) && !defined(TOS_CFG_TIMER_TASK_STK_SIZE)
|
||||
#define TOS_CFG_TIMER_TASK_STK_SIZE 128u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_CPU_SYSTICK_PRIO
|
||||
#define TOS_CFG_CPU_SYSTICK_PRIO 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_CPU_TICK_PER_SECOND
|
||||
#define TOS_CFG_CPU_TICK_PER_SECOND 1000u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_CPU_CLOCK
|
||||
#define TOS_CFG_CPU_CLOCK 16000000u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_TASK_PRIO_MAX
|
||||
#define TOS_CFG_TASK_PRIO_MAX 8u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_MMHEAP_EN
|
||||
#define TOS_CFG_MMHEAP_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_MMHEAP_DEFAULT_POOL_EN
|
||||
#define TOS_CFG_MMHEAP_DEFAULT_POOL_EN 1u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_PWR_MGR_EN
|
||||
#define TOS_CFG_PWR_MGR_EN 0u
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_TICKLESS_EN
|
||||
#define TOS_CFG_TICKLESS_EN 0u
|
||||
#endif
|
||||
|
||||
#if (TOS_CFG_PWR_MGR_EN > 0u) || (TOS_CFG_TICKLESS_EN > 0u)
|
||||
#if TOS_CFG_IDLE_TASK_STK_SIZE < 256
|
||||
#undef TOS_CFG_IDLE_TASK_STK_SIZE
|
||||
#define TOS_CFG_IDLE_TASK_STK_SIZE 256u
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (TOS_CFG_TASK_DYNAMIC_CREATE_EN > 0u)
|
||||
#if TOS_CFG_IDLE_TASK_STK_SIZE < 512
|
||||
#undef TOS_CFG_IDLE_TASK_STK_SIZE
|
||||
#define TOS_CFG_IDLE_TASK_STK_SIZE 512u
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TOS_CFG_FAULT_BACKTRACE_EN
|
||||
#define TOS_CFG_FAULT_BACKTRACE_EN 0u
|
||||
#endif
|
||||
|
||||
#endif /* TOS_CFG_EVENT_DRIVEN_EN */
|
||||
|
||||
#endif /* _TOS_CONFIG_DEFAULT_H_ */
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_COUNTDOWNLATCH_H_
|
||||
#define _TOS_COUNTDOWNLATCH_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_COUNTDOWNLATCH_EN > 0
|
||||
typedef struct k_countdownlatch_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
pend_obj_t pend_obj;
|
||||
k_countdownlatch_cnt_t count;
|
||||
} k_countdownlatch_t;
|
||||
|
||||
/**
|
||||
* @brief Create a countdown-latch.
|
||||
* create a countdown latch.
|
||||
*
|
||||
* @attention the count is how many posts have been done the pender would wakeup.
|
||||
*
|
||||
* @param[in] countdownlatch pointer to the handler of the countdown-latch.
|
||||
* @param[in] count the count to wait of the countdown-latch.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_countdownlatch_create(k_countdownlatch_t *countdownlatch, k_countdownlatch_cnt_t count);
|
||||
|
||||
/**
|
||||
* @brief Destroy a countdown-latch.
|
||||
* destroy a countdown-latch.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] countdownlatch pointer to the handler of the countdown-latch.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_countdownlatch_destroy(k_countdownlatch_t *countdownlatch);
|
||||
|
||||
/**
|
||||
* @brief Pend a countdown-latch.
|
||||
* pend a countdown-latch.
|
||||
*
|
||||
* @attention The task will keep blocked until the countdown-latch is obtained or a timeout comes.
|
||||
*
|
||||
* @param[in] countdownlatch pointer to the handler of the countdown-latch.
|
||||
* @param[in] timeout how much time(in k_tick_t) we would like to wait.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PEND_NOWAIT we get nothing, and we don't wanna wait.
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED we can wait, but scheduler is locked.
|
||||
* @retval #K_ERR_PEND_TIMEOUT the time we wait is up, we get nothing.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_countdownlatch_pend_timed(k_countdownlatch_t *countdownlatch, k_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Pend a countdown-latch.
|
||||
* pend a countdown latch.
|
||||
*
|
||||
* @attention until (countdownlatch->count) of tasks have done the post, the pender would wake up.
|
||||
*
|
||||
* @param[in] countdownlatch pointer to the handler of the countdown-latch.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED the schedule is locked.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_countdownlatch_pend(k_countdownlatch_t *countdownlatch);
|
||||
|
||||
/**
|
||||
* @brief Post a countdown-latch.
|
||||
* post a countdown-latch.
|
||||
*
|
||||
* @attention until (countdownlatch->count) of tasks have done the post, the pender would wake up.
|
||||
*
|
||||
* @param[in] countdownlatch pointer to the handler of the countdown-latch.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_COUNTDOWNLATCH_OVERFLOW we are posting the countdown-latch too much.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_countdownlatch_post(k_countdownlatch_t *countdownlatch);
|
||||
|
||||
/**
|
||||
* @brief Reset a countdown-latch.
|
||||
* reset a countdown-latch's count.
|
||||
*
|
||||
* @attention None.
|
||||
*
|
||||
* @param[in] countdownlatch pointer to the handler of the countdown-latch.
|
||||
* @param[in] count the count to wait of the countdown-latch.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_countdownlatch_reset(k_countdownlatch_t *countdownlatch, k_countdownlatch_cnt_t count);
|
||||
|
||||
#endif /* TOS_CFG_COUNTDOWNLATCH_EN */
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_COUNTDOWNLATCH_H_ */
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_EVENT_H_
|
||||
#define _TOS_EVENT_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_EVENT_EN > 0
|
||||
|
||||
// if we are pending an event, for any flag we expect is set is ok, this flag should be passed to tos_event_pend
|
||||
#define TOS_OPT_EVENT_PEND_ANY (k_opt_t)0x0001
|
||||
|
||||
// if we are pending an event, must all the flag we expect is set is ok, this flag should be passed to tos_event_pend
|
||||
#define TOS_OPT_EVENT_PEND_ALL (k_opt_t)0x0002
|
||||
|
||||
// if we are pending an event, and we wanna clear the event's flag after we read, this flag should be passed to tos_event_pend
|
||||
/* ATTENTION:
|
||||
we can pass both TOS_OPT_EVENT_PEND_CLR and TOS_OPT_EVENT_PEND_ANY, or TOS_OPT_EVENT_PEND_CLR and TOS_OPT_EVENT_PEND_ALL
|
||||
to tos_event_pend, if we wanna do this, a (TOS_OPT_EVENT_PEND_CLR | TOS_OPT_EVENT_PEND_ANY) or
|
||||
(TOS_OPT_EVENT_PEND_CLR | TOS_OPT_EVENT_PEND_ALL) should be passed.
|
||||
but, (TOS_OPT_EVENT_PEND_ANY | TOS_OPT_EVENT_PEND_ALL) is invalid, we cannot both wanna any and all flag is set.
|
||||
*/
|
||||
#define TOS_OPT_EVENT_PEND_CLR (k_opt_t)0x0004
|
||||
|
||||
typedef enum opt_event_post_en {
|
||||
OPT_EVENT_POST_KEP,
|
||||
OPT_EVENT_POST_CLR,
|
||||
} opt_event_post_t;
|
||||
|
||||
typedef struct k_event_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
pend_obj_t pend_obj;
|
||||
k_event_flag_t flag;
|
||||
} k_event_t;
|
||||
|
||||
/**
|
||||
* @brief Create an event.
|
||||
* create an event.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] event pointer to the handler of the event.
|
||||
* @param[in] init_flag initial flag of the event.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_event_create(k_event_t *event, k_event_flag_t init_flag);
|
||||
|
||||
/**
|
||||
* @brief Destroy an event.
|
||||
* destroy an event.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] event pointer to the handler of the event.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_event_destroy(k_event_t *event);
|
||||
|
||||
/**
|
||||
* @brief Pend an event.
|
||||
* pend an event.
|
||||
*
|
||||
* @attention if opt is TOS_OPT_EVENT_PEND_ANY, any of the flag_expect is set is ok;
|
||||
* if opt is TOS_OPT_EVENT_PEND_ALL�� must all the flag_expect is set is ok.
|
||||
*
|
||||
* @param[in] event pointer to the handler of the event.
|
||||
* @param[in] flag_expect the flag we expect from the event.
|
||||
* @param[OUT] flag_match if we get the flag we expect, what exactly they are?
|
||||
* @param[in] timeout how much time(in k_tick_t) we would like to wait.
|
||||
* @param[in] opt option for pend.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_EVENT_PEND_OPT_INVALID opt is invalid
|
||||
* @retval #K_ERR_PEND_NOWAIT we get nothing, and we don't wanna wait.
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED we can wait, but scheduler is locked.
|
||||
* @retval #K_ERR_PEND_TIMEOUT the time we wait is up, we get nothing.
|
||||
* @retval #K_ERR_PEND_DESTROY the event we are pending is destroyed.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_event_pend(k_event_t *event, k_event_flag_t flag_expect, k_event_flag_t *flag_match, k_tick_t timeout, k_opt_t opt);
|
||||
|
||||
/**
|
||||
* @brief Post an event.
|
||||
* post an event.
|
||||
*
|
||||
* @attention if you are posting an event in tos_event_post, event's own flag will be overwrited by the flag we post.
|
||||
* eg. if an event's own flag is 0x0001, and we are posting a flag 0x0030, after the post, the event's flag
|
||||
* will be overwrited to 0x0030.
|
||||
*
|
||||
* @param[in] event pointer to the handler of the event.
|
||||
* @param[in] flag the flag we post.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_event_post(k_event_t *event, k_event_flag_t flag);
|
||||
|
||||
/**
|
||||
* @brief Post an event.
|
||||
* post an event, and keep the original own flag of the event.
|
||||
*
|
||||
* @attention the original own flag of the event will be keeped.
|
||||
* eg.if an event's own flag is 0x0001, and we are posting a flag 0x0030, after the post, the event's flag
|
||||
* will be changed to 0x0031(0x0030 | 0x0001), which means the event's original flag is keeped.
|
||||
*
|
||||
* @param[in] event pointer to the handler of the event.
|
||||
* @param[in] flag the flag we post.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_event_post_keep(k_event_t *event, k_event_flag_t flag);
|
||||
|
||||
#endif
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_EVENT_H_ */
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_GLOBAL_H_
|
||||
#define _TOS_GLOBAL_H_
|
||||
|
||||
/* interrupt nesting count */
|
||||
extern k_nesting_t k_irq_nest_cnt;
|
||||
|
||||
/* schedule lock nesting count */
|
||||
extern k_nesting_t k_sched_lock_nest_cnt;
|
||||
|
||||
/* kernel running state */
|
||||
extern knl_state_t k_knl_state;
|
||||
|
||||
/* ready queue of tasks */
|
||||
extern readyqueue_t k_rdyq;
|
||||
|
||||
/* ticks since boot up */
|
||||
extern k_tick_t k_tick_count;
|
||||
|
||||
/* current task */
|
||||
extern k_task_t *k_curr_task;
|
||||
/* next task to run */
|
||||
extern k_task_t *k_next_task;
|
||||
|
||||
/* idle task related stuff */
|
||||
extern k_task_t k_idle_task;
|
||||
extern k_stack_t k_idle_task_stk[];
|
||||
extern k_stack_t *const k_idle_task_stk_addr;
|
||||
extern size_t const k_idle_task_stk_size;
|
||||
|
||||
#if TOS_CFG_TASK_DYNAMIC_CREATE_EN > 0u
|
||||
/* list to hold all the destroyed dynamic created tasks */
|
||||
extern k_list_t k_dead_task_list;
|
||||
#endif
|
||||
|
||||
/* list to hold all the tasks for statistics */
|
||||
extern k_list_t k_stat_list;
|
||||
|
||||
/* list to hold all the tasks delayed or pend for timeout */
|
||||
extern k_list_t k_tick_list;
|
||||
|
||||
/* how many ticks will be triggered in a second */
|
||||
extern k_tick_t k_cpu_tick_per_second;
|
||||
|
||||
/* how many cycle per tick */
|
||||
extern k_cycle_t k_cpu_cycle_per_tick;
|
||||
|
||||
#if TOS_CFG_FAULT_BACKTRACE_EN > 0u
|
||||
|
||||
extern k_fault_log_writer_t k_fault_log_writer;
|
||||
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_MMHEAP_EN > 0u
|
||||
#if TOS_CFG_MMHEAP_DEFAULT_POOL_EN > 0u
|
||||
extern uint8_t k_mmheap_default_pool[] __ALIGNED__(4);
|
||||
#endif
|
||||
extern k_mmheap_ctl_t k_mmheap_ctl;
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_ROUND_ROBIN_EN > 0u
|
||||
extern k_timeslice_t k_robin_default_timeslice;
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_TIMER_EN > 0u
|
||||
/* list holding all the timer */
|
||||
extern timer_ctl_t k_timer_ctl;
|
||||
#if TOS_CFG_TIMER_AS_PROC == 0u
|
||||
extern k_task_t k_timer_task;
|
||||
extern k_stack_t k_timer_task_stk[];
|
||||
extern k_prio_t const k_timer_task_prio;
|
||||
extern k_stack_t *const k_timer_task_stk_addr;
|
||||
extern size_t const k_timer_task_stk_size;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_PWR_MGR_EN > 0u
|
||||
extern pm_device_ctl_t k_pm_device_ctl;
|
||||
|
||||
extern idle_pwrmgr_mode_t k_idle_pwr_mgr_mode;
|
||||
|
||||
extern k_cpu_lpwr_mode_t k_cpu_lpwr_mode;
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
extern k_tickless_wkup_alarm_t *k_tickless_wkup_alarm[__LOW_POWER_MODE_DUMMY];
|
||||
#endif
|
||||
|
||||
#endif /* _TOS_GLOBAL_H_ */
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_K_H_
|
||||
#define _TOS_K_H_
|
||||
|
||||
#include <tos_compiler.h>
|
||||
#include <tos_kerr.h>
|
||||
#include <tos_cpu_def.h>
|
||||
#include <tos_config.h>
|
||||
#include <tos_config_default.h>
|
||||
#include <port_config.h>
|
||||
#include <tos_config_check.h>
|
||||
#include <tos_ktypes.h>
|
||||
#include <tos_cpu_types.h>
|
||||
#include <port.h>
|
||||
#include <tos_cpu.h>
|
||||
#include <tos_fault.h>
|
||||
#include <tos_klib.h>
|
||||
#include <tos_list.h>
|
||||
#include <tos_slist.h>
|
||||
#include <tos_pend.h>
|
||||
#include <tos_sys.h>
|
||||
#include <tos_bitmap.h>
|
||||
#include <tos_ring_queue.h>
|
||||
#include <tos_char_fifo.h>
|
||||
#include <tos_mail_queue.h>
|
||||
#include <tos_message_queue.h>
|
||||
#include <tos_binary_heap.h>
|
||||
#include <tos_priority_queue.h>
|
||||
#include <tos_priority_mail_queue.h>
|
||||
#include <tos_priority_message_queue.h>
|
||||
#include <tos_task.h>
|
||||
#include <tos_robin.h>
|
||||
#include <tos_mutex.h>
|
||||
#include <tos_sem.h>
|
||||
#include <tos_event.h>
|
||||
#include <tos_barrier.h>
|
||||
#include <tos_completion.h>
|
||||
#include <tos_countdownlatch.h>
|
||||
#include <tos_rwlock.h>
|
||||
#include <tos_timer.h>
|
||||
#include <tos_time.h>
|
||||
#include <tos_stopwatch.h>
|
||||
#include <tos_mmblk.h>
|
||||
#include <tos_mmheap.h>
|
||||
#include <tos_tick.h>
|
||||
#include <tos_sched.h>
|
||||
#if TOS_CFG_PWR_MGR_EN > 0u
|
||||
#include <tos_pm.h>
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
#include <tos_tickless.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <tos_global.h>
|
||||
#include <tos_version.h>
|
||||
|
||||
#endif /* _TOS_K_H_ */
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_ERR_H_
|
||||
#define _TOS_ERR_H_
|
||||
|
||||
typedef enum k_err_en {
|
||||
K_ERR_NONE = 0u,
|
||||
|
||||
K_ERR_BARRIER_COUNT_INVALID = 5u,
|
||||
K_ERR_BARRIER_OVERFLOW,
|
||||
|
||||
K_ERR_BITMAP_EXCEED = 10u,
|
||||
|
||||
K_ERR_BIN_HEAP_FULL = 15u,
|
||||
K_ERR_BIN_HEAP_EMPTY,
|
||||
K_ERR_BIN_HEAP_ITEM_SIZE_NOT_MATCH,
|
||||
|
||||
K_ERR_COMPLETION_OVERFLOW = 25u,
|
||||
|
||||
K_ERR_COUNTDOWNLATCH_OVERFLOW = 50u,
|
||||
|
||||
K_ERR_DELAY_ZERO = 100u,
|
||||
K_ERR_DELAY_FOREVER,
|
||||
|
||||
K_ERR_EVENT_PEND_OPT_INVALID = 200u,
|
||||
|
||||
K_ERR_IN_IRQ = 400u,
|
||||
|
||||
K_ERR_KNL_NOT_RUNNING = 500u,
|
||||
K_ERR_KNL_RUNNING,
|
||||
|
||||
K_ERR_LOCK_NESTING_OVERFLOW = 600u,
|
||||
|
||||
K_ERR_MMBLK_POOL_FULL = 700u,
|
||||
K_ERR_MMBLK_POOL_EMPTY,
|
||||
K_ERR_MMBLK_INVALID_BLK_SIZE,
|
||||
K_ERR_MMBLK_INVALID_POOL_ADDR,
|
||||
K_ERR_MMBLK_POOL_OUT_OF_MEMORY,
|
||||
K_ERR_MMBLK_OUT_OF_MEMORY,
|
||||
|
||||
K_ERR_MMHEAP_INVALID_POOL_ADDR = 800u,
|
||||
K_ERR_MMHEAP_INVALID_POOL_SIZE,
|
||||
K_ERR_MMHEAP_POOL_OVERFLOW,
|
||||
K_ERR_MMHEAP_POOL_ALREADY_EXIST,
|
||||
K_ERR_MMHEAP_POOL_NOT_EXIST,
|
||||
|
||||
K_ERR_MUTEX_NOT_OWNER = 1000u,
|
||||
K_ERR_MUTEX_NESTING,
|
||||
K_ERR_MUTEX_NESTING_OVERFLOW,
|
||||
|
||||
K_ERR_OBJ_PTR_NULL = 1100u,
|
||||
K_ERR_OBJ_INVALID,
|
||||
K_ERR_OBJ_INVALID_ALLOC_TYPE,
|
||||
|
||||
K_ERR_OUT_OF_MEMORY = 1150u,
|
||||
|
||||
K_ERR_PEND_NOWAIT = 1200u,
|
||||
K_ERR_PEND_SCHED_LOCKED,
|
||||
K_ERR_PEND_ABNORMAL,
|
||||
K_ERR_PEND_TIMEOUT,
|
||||
K_ERR_PEND_DESTROY,
|
||||
K_ERR_PEND_OWNER_DIE,
|
||||
|
||||
K_ERR_PM_DEVICE_ALREADY_REG = 1300u,
|
||||
K_ERR_PM_DEVICE_OVERFLOW,
|
||||
K_ERR_PM_WKUP_SOURCE_NOT_INSTALL,
|
||||
|
||||
K_ERR_PRIO_Q_EMPTY = 1400u,
|
||||
K_ERR_PRIO_Q_FULL,
|
||||
K_ERR_PRIO_Q_SLOT_NOT_TAKEN,
|
||||
K_ERR_PRIO_Q_ITEM_SIZE_NOT_MATCH,
|
||||
|
||||
K_ERR_RING_Q_FULL = 1500u,
|
||||
K_ERR_RING_Q_EMPTY,
|
||||
K_ERR_RING_Q_ITEM_SIZE_NOT_MATCH,
|
||||
|
||||
K_ERR_RWLOCK_READERS_TO_MANY = 1600u,
|
||||
K_ERR_RWLOCK_IS_READING,
|
||||
K_ERR_RWLOCK_IS_WRITTING,
|
||||
K_ERR_RWLOCK_NOT_READING,
|
||||
K_ERR_RWLOCK_NOT_WRITTING,
|
||||
K_ERR_RWLOCK_NOT_TAKEN,
|
||||
K_ERR_RWLOCK_WAITING_WRITERS_TO_MANY,
|
||||
|
||||
K_ERR_SCHED_LOCKED = 1700u,
|
||||
K_ERR_SCHED_NOT_LOCKED,
|
||||
|
||||
K_ERR_SEM_OVERFLOW = 1800u,
|
||||
|
||||
K_ERR_TASK_ALREADY_CREATED = 1900u,
|
||||
K_ERR_TASK_DESTROY_IDLE,
|
||||
K_ERR_TASK_NOT_DELAY,
|
||||
K_ERR_TASK_PRIO_INVALID,
|
||||
K_ERR_TASK_RESUME_SELF,
|
||||
K_ERR_TASK_SUSPENDED,
|
||||
K_ERR_TASK_SUSPEND_IDLE,
|
||||
K_ERR_TASK_STK_OVERFLOW,
|
||||
K_ERR_TASK_STK_SIZE_INVALID,
|
||||
K_ERR_TASK_OUT_OF_MEMORY,
|
||||
|
||||
K_ERR_TICKLESS_WKUP_ALARM_NOT_INSTALLED = 2000u,
|
||||
K_ERR_TICKLESS_WKUP_ALARM_NO_INIT,
|
||||
K_ERR_TICKLESS_WKUP_ALARM_INIT_FAILED,
|
||||
|
||||
K_ERR_TIMER_INACTIVE = 2100u,
|
||||
K_ERR_TIMER_DELAY_FOREVER,
|
||||
K_ERR_TIMER_PERIOD_FOREVER,
|
||||
K_ERR_TIMER_INVALID_DELAY,
|
||||
K_ERR_TIMER_INVALID_PERIOD,
|
||||
K_ERR_TIMER_INVALID_STATE,
|
||||
K_ERR_TIMER_INVALID_OPT,
|
||||
K_ERR_TIMER_STOPPED,
|
||||
K_ERR_TIMER_RUNNING,
|
||||
|
||||
K_ERR_SEM_OUT_OF_MEMORY = 2200u,
|
||||
|
||||
K_ERR_MUTEX_OUT_OF_MEMORY = 2300u,
|
||||
} k_err_t;
|
||||
|
||||
#endif /* _TOS_ERR_H_ */
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_KLIB_H_
|
||||
#define _TOS_KLIB_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define __MACRO_BEGIN do {
|
||||
#define __MACRO_END } while (0)
|
||||
|
||||
#define TOS_OFFSET_OF_FIELD(type, field) \
|
||||
((uint32_t)&(((type *)0)->field))
|
||||
|
||||
#define TOS_CONTAINER_OF_FIELD(ptr, type, field) \
|
||||
((type *)((uint8_t *)(ptr) - TOS_OFFSET_OF_FIELD(type, field)))
|
||||
|
||||
#define TOS_COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#define TOS_PTR_SANITY_CHECK(ptr) \
|
||||
__MACRO_BEGIN \
|
||||
if (unlikely(!(ptr))) { \
|
||||
return K_ERR_OBJ_PTR_NULL; \
|
||||
} \
|
||||
__MACRO_END
|
||||
|
||||
#define TOS_PTR_SANITY_CHECK_RC(ptr, return_code) \
|
||||
__MACRO_BEGIN \
|
||||
if (unlikely(!(ptr))) { \
|
||||
return return_code; \
|
||||
} \
|
||||
__MACRO_END
|
||||
|
||||
#define TOS_IN_IRQ_CHECK() \
|
||||
__MACRO_BEGIN \
|
||||
if (unlikely(knl_is_inirq())) { \
|
||||
return K_ERR_IN_IRQ; \
|
||||
} \
|
||||
__MACRO_END
|
||||
|
||||
#if TOS_CFG_OBJECT_VERIFY_EN > 0u
|
||||
|
||||
#define TOS_OBJ_INIT(obj, obj_type) knl_object_init(&obj->knl_obj, obj_type)
|
||||
#define TOS_OBJ_DEINIT(obj) knl_object_deinit(&obj->knl_obj)
|
||||
|
||||
#define TOS_OBJ_VERIFY(obj, obj_type) \
|
||||
__MACRO_BEGIN \
|
||||
if (!knl_object_verify(&obj->knl_obj, obj_type)) { \
|
||||
return K_ERR_OBJ_INVALID; \
|
||||
} \
|
||||
__MACRO_END
|
||||
|
||||
#define TOS_OBJ_VERIFY_RC(obj, obj_type, return_code) \
|
||||
__MACRO_BEGIN \
|
||||
if (!knl_object_verify(&obj->knl_obj, obj_type)) { \
|
||||
return return_code; \
|
||||
} \
|
||||
__MACRO_END
|
||||
|
||||
#define TOS_OBJ_TEST(obj, obj_type) \
|
||||
__MACRO_BEGIN \
|
||||
if (knl_object_verify(&obj->knl_obj, obj_type)) { \
|
||||
return K_ERR_OBJ_INVALID; \
|
||||
} \
|
||||
__MACRO_END
|
||||
|
||||
#define TOS_OBJ_TEST_RC(obj, obj_type, return_code) \
|
||||
__MACRO_BEGIN \
|
||||
if (knl_object_verify(&obj->knl_obj, obj_type)) { \
|
||||
return return_code; \
|
||||
} \
|
||||
__MACRO_END
|
||||
|
||||
#else
|
||||
|
||||
#define TOS_OBJ_INIT(obj, obj_type)
|
||||
#define TOS_OBJ_DEINIT(obj)
|
||||
#define TOS_OBJ_VERIFY(obj, obj_type)
|
||||
#define TOS_OBJ_VERIFY_RC(obj, obj_type, return_code)
|
||||
#define TOS_OBJ_TEST(obj, obj_type)
|
||||
#define TOS_OBJ_TEST_RC(obj, obj_type, return_code)
|
||||
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_LIBC_PRINTF_EN > 0u
|
||||
#define LIBC_PRINTF printf
|
||||
#else
|
||||
#define LIBC_PRINTF(...)
|
||||
#endif
|
||||
|
||||
// currently we use default microlib supplied by mdk
|
||||
#define tos_kprintf(...) LIBC_PRINTF(__VA_ARGS__);
|
||||
|
||||
#define tos_kprintln(...) \
|
||||
LIBC_PRINTF(__VA_ARGS__); \
|
||||
LIBC_PRINTF("\n");
|
||||
|
||||
#define TOS_ASSERT_AUX(exp, function, line) \
|
||||
if (!(exp)) { \
|
||||
tos_kprintln("assert failed: %s %d\n", function, line); \
|
||||
tos_knl_sched_lock(); \
|
||||
tos_cpu_int_disable(); \
|
||||
while (K_TRUE) { \
|
||||
; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define TOS_ASSERT(exp) TOS_ASSERT_AUX(exp, __FUNCTION__, __LINE__)
|
||||
|
||||
#endif /* _TOS_KLIB_H_ */
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_KTYPES_H_
|
||||
#define _TOS_KTYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef uint8_t k_prio_t;
|
||||
typedef uint8_t k_stack_t;
|
||||
typedef uint8_t k_task_state_t;
|
||||
typedef struct k_task_st k_task_t;
|
||||
|
||||
typedef uint8_t k_nesting_t;
|
||||
|
||||
typedef uint16_t k_opt_t;
|
||||
|
||||
typedef uint16_t k_sem_cnt_t;
|
||||
typedef uint32_t k_event_flag_t;
|
||||
typedef uint16_t k_barrier_cnt_t;
|
||||
typedef uint16_t k_countdownlatch_cnt_t;
|
||||
|
||||
typedef uint32_t k_time_t;
|
||||
typedef uint32_t k_timeslice_t;
|
||||
|
||||
typedef uint32_t k_cycle_t;
|
||||
|
||||
#if TOS_CFG_CPU_DATA_SIZE == CPU_WORD_SIZE_08
|
||||
typedef uint32_t k_tick_t;
|
||||
#else
|
||||
typedef uint64_t k_tick_t;
|
||||
#endif
|
||||
|
||||
#define K_TRUE (1u)
|
||||
#define K_FALSE (0u)
|
||||
|
||||
#ifndef K_NULL
|
||||
#define K_NULL 0
|
||||
#endif
|
||||
|
||||
#endif /* _TOS_KTYPES_H_ */
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_LIST_H_
|
||||
#define _TOS_LIST_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
typedef struct k_list_node_st {
|
||||
struct k_list_node_st *next;
|
||||
struct k_list_node_st *prev;
|
||||
} k_list_t;
|
||||
|
||||
#define TOS_LIST_NODE(node) \
|
||||
{ &(node), &(node) }
|
||||
|
||||
#define TOS_LIST_DEFINE(list) \
|
||||
k_list_t list = { &(list), &(list) }
|
||||
|
||||
#define TOS_LIST_ENTRY(node, type, field) \
|
||||
TOS_CONTAINER_OF_FIELD(node, type, field)
|
||||
|
||||
#define TOS_LIST_FIRST_ENTRY(list, type, field) \
|
||||
TOS_LIST_ENTRY((list)->next, type, field)
|
||||
|
||||
#define TOS_LIST_FIRST_ENTRY_OR_NULL(list, type, field) \
|
||||
(tos_list_empty(list) ? K_NULL : TOS_LIST_FIRST_ENTRY(list, type, field))
|
||||
|
||||
#define TOS_LIST_FOR_EACH(curr, list) \
|
||||
for (curr = (list)->next; curr != (list); curr = curr->next)
|
||||
|
||||
#define TOS_LIST_FOR_EACH_PREV(curr, list) \
|
||||
for (curr = (list)->prev; curr != (list); curr = curr->prev)
|
||||
|
||||
#define TOS_LIST_FOR_EACH_SAFE(curr, next, list) \
|
||||
for (curr = (list)->next, next = curr->next; curr != (list); \
|
||||
curr = next, next = curr->next)
|
||||
|
||||
#define TOS_LIST_FOR_EACH_PREV_SAFE(curr, next, list) \
|
||||
for (curr = (list)->prev, next = curr->prev; \
|
||||
curr != (list); \
|
||||
curr = next, next = curr->prev)
|
||||
|
||||
#define TOS_LIST_FOR_EACH_ENTRY(entry, type, field, list) \
|
||||
for (entry = TOS_LIST_ENTRY((list)->next, type, field); \
|
||||
&entry->field != (list); \
|
||||
entry = TOS_LIST_ENTRY(entry->field.next, type, field))
|
||||
|
||||
#define TOS_LIST_FOR_EACH_ENTRY_REVERSE(entry, type, field, list) \
|
||||
for (entry = TOS_LIST_ENTRY((list)->prev, type, field); \
|
||||
&entry->field != (list); \
|
||||
entry = TOS_LIST_ENTRY(entry->field.prev, type, field))
|
||||
|
||||
#define TOS_LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, type, field, list) \
|
||||
for (entry = TOS_LIST_ENTRY((list)->next, type, field), \
|
||||
tmp = TOS_LIST_ENTRY(entry->field.next, type, field); \
|
||||
&entry->field != (list); \
|
||||
entry = tmp, tmp = TOS_LIST_ENTRY(entry->field.next, type, field))
|
||||
|
||||
#define TOS_LIST_FOR_EACH_ENTRY_SAFE_REVERSE(entry, tmp, type, field, list) \
|
||||
for (entry = TOS_LIST_ENTRY((list)->prev, type, field), \
|
||||
tmp = TOS_LIST_ENTRY(entry->field.prev, type, field); \
|
||||
&entry->field != (list); \
|
||||
entry = tmp, tmp = TOS_LIST_ENTRY(entry->field.prev, type, field))
|
||||
|
||||
__STATIC_INLINE__ void _list_add(k_list_t *node, k_list_t *prev, k_list_t *next)
|
||||
{
|
||||
next->prev = node;
|
||||
node->next = next;
|
||||
node->prev = prev;
|
||||
prev->next = node;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void _list_del(k_list_t *prev, k_list_t *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void _list_del_node(k_list_t *node)
|
||||
{
|
||||
_list_del(node->prev, node->next);
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_list_init(k_list_t *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_list_add(k_list_t *node, k_list_t *list)
|
||||
{
|
||||
_list_add(node, list, list->next);
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_list_add_tail(k_list_t *node, k_list_t *list)
|
||||
{
|
||||
_list_add(node, list->prev, list);
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_list_del(k_list_t *node)
|
||||
{
|
||||
_list_del(node->prev, node->next);
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_list_del_init(k_list_t *node)
|
||||
{
|
||||
_list_del_node(node);
|
||||
tos_list_init(node);
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_list_move(k_list_t *node, k_list_t *list)
|
||||
{
|
||||
_list_del_node(node);
|
||||
tos_list_add(node, list);
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_list_move_tail(k_list_t *node, k_list_t *list)
|
||||
{
|
||||
_list_del_node(node);
|
||||
tos_list_add_tail(node, list);
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ int tos_list_empty(const k_list_t *list)
|
||||
{
|
||||
return list->next == list;
|
||||
}
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_LIST_H_ */
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_MAIL_QUEUE_H_
|
||||
#define _TOS_MAIL_QUEUE_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_MAIL_QUEUE_EN > 0u
|
||||
|
||||
typedef struct k_mail_queue_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
pend_obj_t pend_obj;
|
||||
k_ring_q_t ring_q;
|
||||
} k_mail_q_t;
|
||||
|
||||
/**
|
||||
* @brief Create a mail queue.
|
||||
* create a mail queue.
|
||||
*
|
||||
* @attention a MAIL is a buffer with a certain size.
|
||||
*
|
||||
* @param[in] mail_q pointer to the handler of the mail queue.
|
||||
* @param[in] pool pool buffer of the mail queue.
|
||||
* @param[in] mail_cnt mail count of the mail queue.
|
||||
* @param[in] mail_size size of each mail in the mail queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mail_q_create(k_mail_q_t *mail_q, void *pool, size_t mail_cnt, size_t mail_size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a mail queue.
|
||||
* destroy a mail queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mail_q pointer to the handler of the mail queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mail_q_destroy(k_mail_q_t *mail_q);
|
||||
|
||||
/**
|
||||
* @brief Create a mail queue with dynamic allocated pool.
|
||||
* create a mail queue with dynamic allocated pool.
|
||||
*
|
||||
* @attention a MAIL is a buffer with a certain size.
|
||||
*
|
||||
* @param[in] mail_q pointer to the handler of the mail queue.
|
||||
* @param[in] mail_cnt mail count of the mail queue.
|
||||
* @param[in] mail_size size of each mail in the mail queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mail_q_create_dyn(k_mail_q_t *mail_q, size_t mail_cnt, size_t mail_size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a mail queue with dynamic allocated pool.
|
||||
* destroy a mail queue with dynamic allocated pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mail_q pointer to the handler of the mail queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mail_q_destroy_dyn(k_mail_q_t *mail_q);
|
||||
|
||||
/**
|
||||
* @brief Flush the mail queue.
|
||||
* flush the mail queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mail_q pointer to the handler of the mail queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mail_q_flush(k_mail_q_t *mail_q);
|
||||
|
||||
/**
|
||||
* @brief Pend a mail queue.
|
||||
* pend a mail queue.
|
||||
*
|
||||
* @attention we WILL perform a memcpy when mail_buf is received(a MAIL is a buffer with a certain size).
|
||||
*
|
||||
* @param[in] mail_q pointer to the handler of the mail queue.
|
||||
* @param[OUT] mail_buf a pointer to the mail buffer we wanna receive.
|
||||
* @param[OUT] mail_size size of the mail buffer received(should be consistent with the mail_size passed to tos_mail_q_create).
|
||||
* @param[in] timeout how much time(in k_tick_t) we would like to wait.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PEND_NOWAIT we get nothing, and we don't wanna wait.
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED we can wait, but scheduler is locked.
|
||||
* @retval #K_ERR_PEND_TIMEOUT the time we wait is up, we get nothing.
|
||||
* @retval #K_ERR_PEND_DESTROY the queue we are pending is destroyed.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mail_q_pend(k_mail_q_t *mail_q, void *mail_buf, size_t *mail_size, k_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Post a mail queue.
|
||||
* post a mail queue and wakeup one pending task.
|
||||
*
|
||||
* @attention when tos_mail_q_post return successfully, only one task who are waitting for the mail queue will be woken up.
|
||||
*
|
||||
* @param[in] mail_q pointer to the handler of the mail queue.
|
||||
* @param[in] mail_buf the mail to post(a MAIL is a buffer).
|
||||
* @param[in] mail_size the size of the mail to post(a MAIL is just a buffer).
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_RING_Q_FULL the mail queue is full.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mail_q_post(k_mail_q_t *mail_q, void *mail_buf, size_t mail_size);
|
||||
|
||||
/**
|
||||
* @brief Post a mail queue.
|
||||
* post a mail queue and wakeup all the pending task.
|
||||
*
|
||||
* @attention when tos_mail_q_post_all return successfully, all of the tasks who are waitting for the message queue will be woken up.
|
||||
*
|
||||
* @param[in] mail_q pointer to the handler of the mail queue.
|
||||
* @param[in] mail_buf the mail to post(a MAIL is a buffer).
|
||||
* @param[in] mail_size the size of the mail to post(a MAIL is just a buffer).
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_RING_Q_FULL the mail queue is full.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mail_q_post_all(k_mail_q_t *mail_q, void *mail_buf, size_t mail_size);
|
||||
|
||||
#endif
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_MAIL_QUEUE_H_ */
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_MESSAGE_QUEUE_H_
|
||||
#define _TOS_MESSAGE_QUEUE_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_MESSAGE_QUEUE_EN > 0u
|
||||
|
||||
typedef struct k_message_queue_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
pend_obj_t pend_obj;
|
||||
k_ring_q_t ring_q;
|
||||
} k_msg_q_t;
|
||||
|
||||
/**
|
||||
* @brief Create a message queue.
|
||||
* create a message queue.
|
||||
*
|
||||
* @attention a MESSAGE is a "void *" pointer.
|
||||
*
|
||||
* @param[in] msg_q pointer to the handler of the message queue.
|
||||
* @param[in] pool pool buffer of the message queue.
|
||||
* @param[in] msg_cnt message count of the message queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_msg_q_create(k_msg_q_t *msg_q, void *pool, size_t msg_cnt);
|
||||
|
||||
/**
|
||||
* @brief Destroy a message queue.
|
||||
* destroy a message queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] msg_q pointer to the handler of the message queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_msg_q_destroy(k_msg_q_t *msg_q);
|
||||
|
||||
/**
|
||||
* @brief Create a message queue with dynamic allocated pool.
|
||||
* create a message queue with dynamic allocated pool.
|
||||
*
|
||||
* @attention a MESSAGE is a "void *" pointer.
|
||||
*
|
||||
* @param[in] msg_q pointer to the handler of the message queue.
|
||||
* @param[in] msg_cnt message count of the message queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_msg_q_create_dyn(k_msg_q_t *msg_q, size_t msg_cnt);
|
||||
|
||||
/**
|
||||
* @brief Destroy a message queue with dynamic allocated pool.
|
||||
* destroy a message queue with dynamic allocated pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] msg_q pointer to the handler of the message queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_msg_q_destroy_dyn(k_msg_q_t *msg_q);
|
||||
|
||||
/**
|
||||
* @brief Flush the message queue.
|
||||
* flush the message queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] msg_q pointer to the handler of the message queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_msg_q_flush(k_msg_q_t *msg_q);
|
||||
|
||||
/**
|
||||
* @brief Pend a message queue.
|
||||
* pend a message queue.
|
||||
*
|
||||
* @attention we DONNOT perform a memcpy when msg_ptr is received(a MESSAGE is just a pointer).
|
||||
*
|
||||
* @param[in] msg_q pointer to the handler of the message queue.
|
||||
* @param[OUT] msg_ptr a pointer to the message we wanna receive.
|
||||
* @param[in] timeout how much time(in k_tick_t) we would like to wait.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PEND_NOWAIT we get nothing, and we don't wanna wait.
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED we can wait, but scheduler is locked.
|
||||
* @retval #K_ERR_PEND_TIMEOUT the time we wait is up, we get nothing.
|
||||
* @retval #K_ERR_PEND_DESTROY the queue we are pending is destroyed.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_msg_q_pend(k_msg_q_t *msg_q, void **msg_ptr, k_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Post a message queue.
|
||||
* post a message queue and wakeup one pending task.
|
||||
*
|
||||
* @attention when tos_msg_q_post return successfully, only one task who are waitting for the message queue will be woken up.
|
||||
*
|
||||
* @param[in] msg_q pointer to the handler of the message queue.
|
||||
* @param[in] msg_ptr the message to post(a MESSAGE is just a pointer).
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_RING_Q_FULL the message queue is full.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_msg_q_post(k_msg_q_t *msg_q, void *msg_ptr);
|
||||
|
||||
/**
|
||||
* @brief Post a message queue.
|
||||
* post a message queue and wakeup all the pending task.
|
||||
*
|
||||
* @attention when tos_msg_q_post_all return successfully, all of the tasks who are waitting for the message queue will be woken up.
|
||||
*
|
||||
* @param[in] msg_q pointer to the handler of the message queue.
|
||||
* @param[in] msg_ptr the message to post(a MESSAGE is just a pointer).
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_RING_Q_FULL the message queue is full.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_msg_q_post_all(k_msg_q_t *msg_q, void *msg_ptr);
|
||||
|
||||
#endif
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_MESSAGE_QUEUE_H_ */
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_MMBLK_H_
|
||||
#define _TOS_MMBLK_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#define K_MMBLK_NEXT_BLK(blk_curr, blk_size) ((void *)((cpu_addr_t)blk_curr + blk_size))
|
||||
#define K_MMBLK_ALIGN_MASK (sizeof(void *) - 1u)
|
||||
|
||||
typedef struct k_mmblk_pool_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
void *pool_start;
|
||||
void *free_list;
|
||||
size_t blk_size;
|
||||
size_t blk_max;
|
||||
size_t blk_free;
|
||||
} k_mmblk_pool_t;
|
||||
|
||||
/**
|
||||
* @brief Create a memory manage block pool.
|
||||
* Create a memory manage block pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mbp pointer to the memory block pool handler.
|
||||
* @param[in] pool_start start address of the pool.
|
||||
* @param[in] blk_num number of the blocks in the pool.
|
||||
* @param[in] blk_size size of each block in the pool.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_MMBLK_INVALID_POOL_ADDR start address of the pool is invalid.
|
||||
* @retval #K_ERR_MMBLK_INVALID_BLK_SIZE size of the block is invalid.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mmblk_pool_create(k_mmblk_pool_t *mbp, void *pool_start, size_t blk_num, size_t blk_size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a memory manage block pool.
|
||||
* Destroy a memory manage block pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mbp pointer to the memory block pool handler.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_OBJ_INVALID mbp is not a valid memory block pool handler.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mmblk_pool_destroy(k_mmblk_pool_t *mbp);
|
||||
|
||||
/**
|
||||
* @brief Create a dynamic memory manage block pool.
|
||||
* Create a dynamic memory manage block pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mbp pointer to the pointer of memory block pool handler.
|
||||
* @param[in] blk_num number of the blocks in the pool.
|
||||
* @param[in] blk_size size of each block in the pool.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_MMBLK_INVALID_POOL_ADDR start address of the pool is invalid.
|
||||
* @retval #K_ERR_MMBLK_INVALID_BLK_SIZE size of the block is invalid.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mmblk_pool_create_dyn(k_mmblk_pool_t **mbp, size_t blk_num, size_t blk_size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a dynamic memory manage block pool.
|
||||
* Destroy a memory dynamic manage block pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mbp pointer to the memory block pool handler.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_OBJ_INVALID mbp is not a valid memory block pool handler.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mmblk_pool_destroy_dyn(k_mmblk_pool_t *mbp);
|
||||
|
||||
/**
|
||||
* @brief Allocate a memory manage block.
|
||||
* Allocate a memory manage block.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mbp pointer to the memory block pool handler.
|
||||
* @param[in] blk start address of the memory manage block.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_MMBLK_POOL_EMPTY the pool is empty.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mmblk_alloc(k_mmblk_pool_t *mbp, void **blk);
|
||||
|
||||
/**
|
||||
* @brief Free a memory manage block.
|
||||
* Free a memory manage block.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mbp pointer to the memory block pool handler.
|
||||
* @param[in] blk start address of the memory manage block.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_MMBLK_POOL_FULL the pool is full.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mmblk_free(k_mmblk_pool_t *mbp, void *blk);
|
||||
|
||||
#endif
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
** Two Level Segregated Fit memory allocator, version 3.1.
|
||||
** Written by Matthew Conte
|
||||
** http://tlsf.baisoku.org
|
||||
**
|
||||
** Based on the original documentation by Miguel Masmano:
|
||||
** http://www.gii.upv.es/tlsf/main/docs
|
||||
**
|
||||
** This implementation was written to the specification
|
||||
** of the document, therefore no GPL restrictions apply.
|
||||
**
|
||||
** Copyright (c) 2006-2016, Matthew Conte
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** * Neither the name of the copyright holder nor the
|
||||
** names of its contributors may be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY
|
||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _TOS_MMHEAP_H_
|
||||
#define _TOS_MMHEAP_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_MMHEAP_EN > 0u
|
||||
|
||||
/**
|
||||
* log2 of number of linear subdivisions of block sizes. Larger
|
||||
* values require more memory in the control structure. Values of
|
||||
* 4 or 5 are typical.
|
||||
*/
|
||||
#define K_MMHEAP_SL_INDEX_COUNT_LOG2 5
|
||||
|
||||
/* All allocation sizes and addresses are aligned to 4 bytes. */
|
||||
#define K_MMHEAP_ALIGN_SIZE_LOG2 2
|
||||
#define K_MMHEAP_ALIGN_SIZE (1 << K_MMHEAP_ALIGN_SIZE_LOG2)
|
||||
|
||||
/*
|
||||
* We support allocations of sizes up to (1 << K_MMHEAP_FL_INDEX_MAX) bits.
|
||||
* However, because we linearly subdivide the second-level lists, and
|
||||
* our minimum size granularity is 4 bytes, it doesn't make sense to
|
||||
* create first-level lists for sizes smaller than K_MMHEAP_SL_INDEX_COUNT * 4,
|
||||
* or (1 << (K_MMHEAP_SL_INDEX_COUNT_LOG2 + 2)) bytes, as there we will be
|
||||
* trying to split size ranges into more slots than we have available.
|
||||
* Instead, we calculate the minimum threshold size, and place all
|
||||
* blocks below that size into the 0th first-level list.
|
||||
*/
|
||||
#define K_MMHEAP_FL_INDEX_MAX 30
|
||||
#define K_MMHEAP_SL_INDEX_COUNT (1 << K_MMHEAP_SL_INDEX_COUNT_LOG2)
|
||||
#define K_MMHEAP_FL_INDEX_SHIFT (K_MMHEAP_SL_INDEX_COUNT_LOG2 + K_MMHEAP_ALIGN_SIZE_LOG2)
|
||||
#define K_MMHEAP_FL_INDEX_COUNT (K_MMHEAP_FL_INDEX_MAX - K_MMHEAP_FL_INDEX_SHIFT + 1)
|
||||
|
||||
#define K_MMHEAP_SMALL_BLOCK_SIZE (1 << K_MMHEAP_FL_INDEX_SHIFT)
|
||||
|
||||
#define K_MMHEAP_BLOCK_CURR_FREE (1 << 0)
|
||||
#define K_MMHEAP_BLOCK_PREV_FREE (1 << 1)
|
||||
#define K_MMHEAP_BLOCK_SIZE_MASK ~(K_MMHEAP_BLOCK_CURR_FREE | K_MMHEAP_BLOCK_PREV_FREE)
|
||||
#define K_MMHEAP_BLOCK_STATE_MASK (K_MMHEAP_BLOCK_CURR_FREE | K_MMHEAP_BLOCK_PREV_FREE)
|
||||
|
||||
typedef struct k_mmheap_information_st {
|
||||
uint32_t used; /* space is used */
|
||||
uint32_t free; /* space is free */
|
||||
} k_mmheap_info_t;
|
||||
|
||||
/**
|
||||
* Block structure.
|
||||
*
|
||||
* There are several implementation subtleties involved:
|
||||
* - The prev_phys_block field is only valid if the previous block is free.
|
||||
* - The prev_phys_block field is actually stored at the end of the
|
||||
* previous block. It appears at the beginning of this structure only to
|
||||
* simplify the implementation.
|
||||
* - The next_free / prev_free fields are only valid if the block is free.
|
||||
*/
|
||||
typedef struct mmheap_blk_st {
|
||||
struct mmheap_blk_st *prev_phys_blk;
|
||||
|
||||
size_t size;
|
||||
|
||||
struct mmheap_blk_st *next_free;
|
||||
struct mmheap_blk_st *prev_free;
|
||||
} mmheap_blk_t;
|
||||
|
||||
/**
|
||||
* A free block must be large enough to store its header minus the size of
|
||||
* the prev_phys_block field, and no larger than the number of addressable
|
||||
* bits for FL_INDEX.
|
||||
*/
|
||||
#define K_MMHEAP_BLK_SIZE_MIN (sizeof(mmheap_blk_t) - sizeof(mmheap_blk_t *))
|
||||
#define K_MMHEAP_BLK_SIZE_MAX (1 << K_MMHEAP_FL_INDEX_MAX)
|
||||
|
||||
#define K_MMHEAP_BLK_HEADER_OVERHEAD (sizeof(size_t))
|
||||
#define K_MMHEAP_BLK_START_OFFSET (TOS_OFFSET_OF_FIELD(mmheap_blk_t, size) + sizeof(size_t))
|
||||
|
||||
#define K_MMHEAP_POOL_MAX 3
|
||||
|
||||
/**
|
||||
* memory heap control
|
||||
*/
|
||||
typedef struct k_mmheap_control_st {
|
||||
int pool_cnt;
|
||||
void *pool_start[K_MMHEAP_POOL_MAX];
|
||||
|
||||
mmheap_blk_t block_null; /**< Empty lists point at this block to indicate they are free. */
|
||||
|
||||
uint32_t fl_bitmap; /**< Bitmaps for free lists. */
|
||||
uint32_t sl_bitmap[K_MMHEAP_FL_INDEX_COUNT];
|
||||
|
||||
mmheap_blk_t *blocks[K_MMHEAP_FL_INDEX_COUNT][K_MMHEAP_SL_INDEX_COUNT]; /**< Head of free lists. */
|
||||
} k_mmheap_ctl_t;
|
||||
|
||||
/**
|
||||
* @brief Add a pool.
|
||||
* Add addtional pool to the heap.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] pool_start start address of the pool.
|
||||
* @param[in] pool_size size of the pool.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_MMHEAP_INVALID_POOL_ADDR start address of the pool is invalid.
|
||||
* @retval #K_ERR_MMHEAP_INVALID_POOL_SIZE size of the pool is invalid.
|
||||
* @retval #K_ERR_MMHEAP_POOL_OVERFLOW too many pools are added.
|
||||
* @retval #K_ERR_MMHEAP_POOL_ALREADY_EXIST the pool is already exist.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mmheap_pool_add(void *pool_start, size_t pool_size);
|
||||
|
||||
/**
|
||||
* @brief Remove a pool.
|
||||
* Remove a pool from the heap.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] pool_start start address of the pool.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_OBJ_PTR_NULL start address of the pool is NULL
|
||||
* @retval #K_ERR_MMHEAP_POOL_NOT_EXIST the pool is not exist
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mmheap_pool_rmv(void *pool_start);
|
||||
|
||||
/**
|
||||
* @brief Alloc memory.
|
||||
* Allocate size bytes and returns a pointer to the allocated memory.
|
||||
*
|
||||
* @attention size should no bigger than K_MMHEAP_BLK_SIZE_MAX.
|
||||
*
|
||||
* @param[in] size size of the memory.
|
||||
*
|
||||
* @return the pointer to the allocated memory.
|
||||
*/
|
||||
__API__ void *tos_mmheap_alloc(size_t size);
|
||||
|
||||
__API__ void *tos_mmheap_calloc(size_t num, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Alloc start address aligned memory from the heap.
|
||||
* Alloc aligned address and specified size memory from the heap.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] size size of the memory.
|
||||
* @param[in] align address align mask of the memory.
|
||||
*
|
||||
* @return the pointer to the allocated memory.
|
||||
*/
|
||||
__API__ void *tos_mmheap_aligned_alloc(size_t size, size_t align);
|
||||
|
||||
/**
|
||||
* @brief Realloc memory from the heap.
|
||||
* Change the size of the memory block pointed to by ptr to size bytes.
|
||||
*
|
||||
* @attention
|
||||
* <ul>
|
||||
* <li> if ptr is K_NULL, then the call is equivalent to tos_mmheap_alloc(size), for all values of size.
|
||||
* <li> if ptr is if size is equal to zero, and ptr is not K_NULL, then the call is equivalent to tos_mmheap_free(ptr).
|
||||
* </ul>
|
||||
*
|
||||
* @param[in] ptr old pointer to the memory space.
|
||||
* @param[in] size new size of the memory space.
|
||||
*
|
||||
* @return the new pointer to the allocated memory.
|
||||
*/
|
||||
__API__ void *tos_mmheap_realloc(void *ptr, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Free the memory.
|
||||
* Free the memory space pointed to by ptr, which must have been returned by a previous call to tos_mmheap_alloc(), tos_mmheap_aligned_alloc(), or tos_mmheap_realloc().
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] ptr pointer to the memory.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
__API__ void tos_mmheap_free(void *ptr);
|
||||
|
||||
/**
|
||||
* @brief Check the pool.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] pool_start start address of the pool.
|
||||
* @param[out] info pointer to the information struct.
|
||||
*
|
||||
* @return errcode.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mmheap_pool_check(void *pool_start, k_mmheap_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Check the heap.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[out] info pointer to the information struct.
|
||||
*
|
||||
* @return errcode.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mmheap_check(k_mmheap_info_t *info);
|
||||
|
||||
__KNL__ k_err_t mmheap_init(void);
|
||||
|
||||
__KNL__ k_err_t mmheap_init_with_pool(void *pool_start, size_t pool_size);
|
||||
|
||||
#else /* if mmheap is not enabled, use libc instead */
|
||||
|
||||
#define tos_mmheap_alloc malloc
|
||||
#define tos_mmheap_calloc calloc
|
||||
#define tos_mmheap_realloc realloc
|
||||
#define tos_mmheap_free free
|
||||
|
||||
#endif
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_MMHEAP_H_ */
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_MUTEX_H_
|
||||
#define _TOS_MUTEX_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_MUTEX_EN > 0u
|
||||
|
||||
typedef struct k_mutex_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
pend_obj_t pend_obj;
|
||||
k_nesting_t pend_nesting;
|
||||
k_task_t *owner;
|
||||
k_prio_t owner_orig_prio;
|
||||
k_list_t owner_anchor;
|
||||
} k_mutex_t;
|
||||
|
||||
/**
|
||||
* @brief Create a mutex.
|
||||
* create a mutex.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mutex pointer to the handler of the mutex.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mutex_create(k_mutex_t *mutex);
|
||||
|
||||
/**
|
||||
* @brief Create a dynamic mutex.
|
||||
* create a dynamic mutex.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mutex pointer to the pointer of the mutex.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mutex_create_dyn(k_mutex_t **mutex);
|
||||
|
||||
/**
|
||||
* @brief Destroy a mutex.
|
||||
* destroy a mutex.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mutex pointer to the handler of the mutex.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mutex_destroy(k_mutex_t *mutex);
|
||||
|
||||
/**
|
||||
* @brief Pend a mutex.
|
||||
* pend a mutex.
|
||||
*
|
||||
* @attention The task will keep blocked until the mutex is obtained or a timeout comes.
|
||||
*
|
||||
* @param[in] mutex pointer to the handler of the mutex.
|
||||
* @param[in] timeout how much time(in k_tick_t) we would like to wait.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_MUTEX_NESTING_OVERFLOW we are the owner of the mutex, and we are nesting pend too much on this mutex.
|
||||
* @retval #K_ERR_MUTEX_NESTING we are the owner of the mutex, and we are nesting pend on it.
|
||||
* @retval #K_ERR_PEND_NOWAIT we get nothing, and we don't wanna wait.
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED we can wait, but scheduler is locked.
|
||||
* @retval #K_ERR_PEND_TIMEOUT the time we wait is up, we get nothing.
|
||||
* @retval #K_ERR_PEND_DESTROY the mutex we are pending is destroyed.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mutex_pend_timed(k_mutex_t *mutex, k_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Pend a mutex.
|
||||
* pend a mutex.
|
||||
*
|
||||
* @attention The task will keep blocked until the mutex is obtained.
|
||||
*
|
||||
* @param[in] mutex pointer to the handler of the mutex.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_MUTEX_NESTING_OVERFLOW we are the owner of the mutex, and we are nesting pend too much on this mutex.
|
||||
* @retval #K_ERR_MUTEX_NESTING we are the owner of the mutex, and we are nesting pend on it.
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED we can wait, but scheduler is locked.
|
||||
* @retval #K_ERR_PEND_DESTROY the mutex we are pending is destroyed.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mutex_pend(k_mutex_t *mutex);
|
||||
|
||||
/**
|
||||
* @brief Post a mutex.
|
||||
* post a mutex.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] mutex pointer to the handler of the mutex.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_MUTEX_NOT_OWNER we are posting a mutex of which the owner is not us.
|
||||
* @retval #K_ERR_MUTEX_NESTING we are posting a mutex owned by us, and we are still in a nesting.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_mutex_post(k_mutex_t *mutex);
|
||||
|
||||
__KNL__ void mutex_release(k_mutex_t *mutex);
|
||||
|
||||
#endif
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_MUTEX_H_ */
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_PEND_H_
|
||||
#define _TOS_PEND_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
/**
|
||||
* The reason why we wakeup from a pend.
|
||||
* when we wakeup, we need to know why.
|
||||
*/
|
||||
typedef enum pend_state_en {
|
||||
PEND_STATE_NONE, /**< nothing. */
|
||||
PEND_STATE_POST, /**< someone has post, we get what we want. */
|
||||
PEND_STATE_TIMEOUT, /**< a post has never came until time is out. */
|
||||
PEND_STATE_DESTROY, /**< someone has destroyed what we are pending for. */
|
||||
PEND_STATE_OWNER_DIE, /**< the pend object owner task is destroyed. */
|
||||
} pend_state_t;
|
||||
|
||||
typedef enum opt_post_en {
|
||||
OPT_POST_ONE,
|
||||
OPT_POST_ALL,
|
||||
} opt_post_t;
|
||||
|
||||
typedef struct pend_object_st {
|
||||
k_list_t list;
|
||||
} pend_obj_t;
|
||||
|
||||
__KNL__ void pend_object_init(pend_obj_t *object);
|
||||
|
||||
__KNL__ void pend_object_deinit(pend_obj_t *object);
|
||||
|
||||
__KNL__ int pend_is_nopending(pend_obj_t *object);
|
||||
|
||||
__KNL__ k_prio_t pend_highest_pending_prio_get(pend_obj_t *object);
|
||||
|
||||
__KNL__ k_task_t *pend_highest_pending_task_get(pend_obj_t *object);
|
||||
|
||||
__KNL__ void pend_list_remove(k_task_t *task);
|
||||
|
||||
__KNL__ void pend_list_adjust(k_task_t *task);
|
||||
|
||||
__KNL__ k_err_t pend_state2errno(pend_state_t state);
|
||||
|
||||
__KNL__ void pend_task_wakeup(k_task_t *task, pend_state_t state);
|
||||
|
||||
__KNL__ void pend_task_block(k_task_t *task, pend_obj_t *object, k_tick_t timeout);
|
||||
|
||||
__KNL__ void pend_wakeup_one(pend_obj_t *object, pend_state_t state);
|
||||
|
||||
__KNL__ void pend_wakeup_all(pend_obj_t *object, pend_state_t state);
|
||||
|
||||
__KNL__ void pend_wakeup(pend_obj_t *object, pend_state_t state, opt_post_t opt);
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_PEND_H_ */
|
||||
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_PRIORITY_MAIL_QUEUE_H_
|
||||
#define _TOS_PRIORITY_MAIL_QUEUE_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_PRIORITY_MAIL_QUEUE_EN > 0u
|
||||
|
||||
typedef struct k_priority_mail_queue_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
pend_obj_t pend_obj;
|
||||
|
||||
void *prio_q_mgr_array;
|
||||
k_prio_q_t prio_q;
|
||||
} k_prio_mail_q_t;
|
||||
|
||||
/**
|
||||
* @brief Create a priority mail queue.
|
||||
* create a priority mail queue.
|
||||
*
|
||||
* @attention a MAIL is a buffer with a certain size.
|
||||
*
|
||||
* @param[in] prio_mail_q pointer to the handler of the priority mail queue.
|
||||
* @param[in] pool pool buffer of the priority mail queue.
|
||||
* @param[in] mail_cnt mail count of the priority mail queue.
|
||||
* @param[in] mail_size size of each mail in the priority mail queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_mail_q_create(k_prio_mail_q_t *prio_mail_q, void *pool, size_t mail_cnt, size_t mail_size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a priority mail queue.
|
||||
* destroy a priority mail queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_mail_q pointer to the handler of the priority mail queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_mail_q_destroy(k_prio_mail_q_t *prio_mail_q);
|
||||
|
||||
/**
|
||||
* @brief Create a priority mail queue with dynamic allocated pool.
|
||||
* create a priority mail queue with dynamic allocated pool.
|
||||
*
|
||||
* @attention a MAIL is a buffer with a certain size.
|
||||
*
|
||||
* @param[in] prio_mail_q pointer to the handler of the priority mail queue.
|
||||
* @param[in] mail_cnt mail count of the priority mail queue.
|
||||
* @param[in] mail_size size of each mail in the priority mail queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_mail_q_create_dyn(k_prio_mail_q_t *prio_mail_q, size_t mail_cnt, size_t mail_size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a priority mail queue with dynamic allocated pool.
|
||||
* destroy a priority mail queue with dynamic allocated pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_mail_q pointer to the handler of the priority mail queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_mail_q_destroy_dyn(k_prio_mail_q_t *prio_mail_q);
|
||||
|
||||
/**
|
||||
* @brief Flush the priority mail queue.
|
||||
* flush the priority mail queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_mail_q pointer to the handler of the priority mail queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_mail_q_flush(k_prio_mail_q_t *prio_mail_q);
|
||||
|
||||
/**
|
||||
* @brief Pend a priority mail queue.
|
||||
* pend a priority mail queue.
|
||||
*
|
||||
* @attention
|
||||
* 1. we WILL perform a memcpy when mail_buf is received(a MAIL is a buffer with a certain size).
|
||||
* 2. With priority mail queue, if the poster has post several mail with different priority, the pender will receive
|
||||
* the mail in priority order(numerically bigger, actually smaller, means the mail with highest priority(numerically
|
||||
* smallest) will be received first, then the second highest priority mail, and so on).
|
||||
*
|
||||
* @param[in] prio_mail_q pointer to the handler of the priority mail queue.
|
||||
* @param[OUT] mail_buf a pointer to the mail buffer we wanna receive.
|
||||
* @param[OUT] mail_size size of the mail buffer received(should be consistent with the mail_size passed to tos_prio_mail_q_create).
|
||||
* @param[in] timeout how much time(in k_tick_t) we would like to wait.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PEND_NOWAIT we get nothing, and we don't wanna wait.
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED we can wait, but scheduler is locked.
|
||||
* @retval #K_ERR_PEND_TIMEOUT the time we wait is up, we get nothing.
|
||||
* @retval #K_ERR_PEND_DESTROY the queue we are pending is destroyed.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_mail_q_pend(k_prio_mail_q_t *prio_mail_q, void *mail_buf, size_t *mail_size, k_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Post a priority mail queue.
|
||||
* post a priority mail queue and wakeup one pending task.
|
||||
*
|
||||
* @attention when tos_prio_mail_q_post return successfully, only one task who are waitting for the mail queue will be woken up.
|
||||
*
|
||||
* @param[in] prio_mail_q pointer to the handler of the priority mail queue.
|
||||
* @param[in] mail_buf the mail to post(a MAIL is a buffer).
|
||||
* @param[in] mail_size the size of the mail to post(a MAIL is just a buffer).
|
||||
* @param[in] prio the priority of the mail.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PRIO_Q_FULL the mail queue is full.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_mail_q_post(k_prio_mail_q_t *prio_mail_q, void *mail_buf, size_t mail_size, k_prio_t prio);
|
||||
|
||||
/**
|
||||
* @brief Post a priority mail queue.
|
||||
* post a priority mail queue and wakeup all the pending task.
|
||||
*
|
||||
* @attention when tos_prio_mail_q_post_all return successfully, all of the tasks who are waitting for the message queue will be woken up.
|
||||
*
|
||||
* @param[in] prio_mail_q pointer to the handler of the priority mail queue.
|
||||
* @param[in] mail_buf the mail to post(a MAIL is a buffer).
|
||||
* @param[in] mail_size the size of the mail to post(a MAIL is just a buffer).
|
||||
* @param[in] prio the priority of the mail.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PRIO_Q_FULL the mail queue is full.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_mail_q_post_all(k_prio_mail_q_t *prio_mail_q, void *mail_buf, size_t mail_size, k_prio_t prio);
|
||||
|
||||
#endif /* TOS_CFG_PRIORITY_MAIL_QUEUE_EN */
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_PRIORITY_MAIL_QUEUE_H_ */
|
||||
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_PRIORITY_MESSAGE_QUEUE_H_
|
||||
#define _TOS_PRIORITY_MESSAGE_QUEUE_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN > 0u
|
||||
|
||||
typedef struct k_priority_message_queue_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
pend_obj_t pend_obj;
|
||||
|
||||
void *prio_q_mgr_array;
|
||||
k_prio_q_t prio_q;
|
||||
} k_prio_msg_q_t;
|
||||
|
||||
/**
|
||||
* @brief Create a priority message queue.
|
||||
* create a priority message queue.
|
||||
*
|
||||
* @attention a MESSAGE is a "void *" pointer.
|
||||
*
|
||||
* @param[in] prio_msg_q pointer to the handler of the priority message queue.
|
||||
* @param[in] pool pool buffer of the priority message queue.
|
||||
* @param[in] msg_cnt message count of the priority message queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_msg_q_create(k_prio_msg_q_t *prio_msg_q, void *pool, size_t msg_cnt);
|
||||
|
||||
/**
|
||||
* @brief Destroy a priority message queue.
|
||||
* destroy a priority message queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_msg_q pointer to the handler of the priority message queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_msg_q_destroy(k_prio_msg_q_t *prio_msg_q);
|
||||
|
||||
/**
|
||||
* @brief Create a priority message queue with dynamic allocated pool.
|
||||
* create a priority message queue with dynamic allocated pool.
|
||||
*
|
||||
* @attention a MESSAGE is a "void *" pointer.
|
||||
*
|
||||
* @param[in] prio_msg_q pointer to the handler of the priority message queue.
|
||||
* @param[in] msg_cnt message count of the priority message queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_msg_q_create_dyn(k_prio_msg_q_t *prio_msg_q, size_t msg_cnt);
|
||||
|
||||
/**
|
||||
* @brief Destroy a priority message queue with dynamic allocated pool.
|
||||
* destroy a priority message queue with dynamic allocated pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_msg_q pointer to the handler of the priority message queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_msg_q_destroy_dyn(k_prio_msg_q_t *prio_msg_q);
|
||||
|
||||
/**
|
||||
* @brief Flush the priority message queue.
|
||||
* flush the priority message queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_msg_q pointer to the handler of the priority message queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_msg_q_flush(k_prio_msg_q_t *prio_msg_q);
|
||||
|
||||
/**
|
||||
* @brief Pend a priority message queue.
|
||||
* pend a priority message queue.
|
||||
*
|
||||
* @attentio
|
||||
* 1. we DONNOT perform a memcpy when msg_ptr is received(a MESSAGE is just a pointer).
|
||||
* 2. With priority message queue, if the poster has post several message with different priority, the pender will receive
|
||||
* the message in priority order(numerically bigger, actually smaller, means the message with highest priority(numerically
|
||||
* smallest) will be received first, then the second highest priority message, and so on).
|
||||
*
|
||||
* @param[in] prio_msg_q pointer to the handler of the priority message queue.
|
||||
* @param[OUT] msg_ptr a pointer to the message we wanna receive.
|
||||
* @param[in] timeout how much time(in k_tick_t) we would like to wait.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PEND_NOWAIT we get nothing, and we don't wanna wait.
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED we can wait, but scheduler is locked.
|
||||
* @retval #K_ERR_PEND_TIMEOUT the time we wait is up, we get nothing.
|
||||
* @retval #K_ERR_PEND_DESTROY the queue we are pending is destroyed.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_msg_q_pend(k_prio_msg_q_t *prio_msg_q, void **msg_ptr, k_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Post a priority message queue.
|
||||
* post a priority message queue and wakeup one pending task.
|
||||
*
|
||||
* @attention when tos_prio_msg_q_post return successfully, only one task who are waitting for the priority message queue will be woken up.
|
||||
*
|
||||
* @param[in] prio_msg_q pointer to the handler of the priority message queue.
|
||||
* @param[in] msg_ptr the message to post(a MESSAGE is just a pointer).
|
||||
* @param[in] prio the priority of the message.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PRIO_Q_FULL the priority message queue is full.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_msg_q_post(k_prio_msg_q_t *prio_msg_q, void *msg_ptr, k_prio_t prio);
|
||||
|
||||
/**
|
||||
* @brief Post a priority message queue.
|
||||
* post a priority message queue and wakeup all the pending task.
|
||||
*
|
||||
* @attention when tos_prio_msg_q_post_all return successfully, all of the tasks who are waitting for the priority message queue will be woken up.
|
||||
*
|
||||
* @param[in] prio_msg_q pointer to the handler of the priority message queue.
|
||||
* @param[in] msg_ptr the priority message to post(a MESSAGE is just a pointer).
|
||||
* @param[in] prio the priority of the message.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PRIO_Q_FULL the priority message queue is full.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_msg_q_post_all(k_prio_msg_q_t *prio_msg_q, void *msg_ptr, k_prio_t prio);
|
||||
|
||||
#endif
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_PRIORITY_MESSAGE_QUEUE_H_ */
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_PRIORITY_QUEUE_H_
|
||||
#define _TOS_PRIORITY_QUEUE_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
typedef uint16_t prio_q_slot_t;
|
||||
|
||||
typedef struct prio_q_pool_manager_entry_st {
|
||||
prio_q_slot_t next;
|
||||
} prio_q_pool_mgr_ent_t;
|
||||
|
||||
typedef struct prio_q_pool_manager_st {
|
||||
prio_q_slot_t first_free;
|
||||
prio_q_pool_mgr_ent_t *pool_mgr_ent_array;
|
||||
} prio_q_pool_mgr_t;
|
||||
|
||||
typedef struct prio_q_priority_manager_entry_st {
|
||||
k_prio_t priority;
|
||||
prio_q_slot_t slot;
|
||||
} prio_q_prio_mgr_ent_t;
|
||||
|
||||
typedef struct prio_q_prio_manager_st {
|
||||
k_bin_heap_t prio_mgr_bin_heap;
|
||||
prio_q_prio_mgr_ent_t *prio_mgr_ent_pool;
|
||||
} prio_q_prio_mgr_t;
|
||||
|
||||
typedef struct k_priority_queue_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
prio_q_pool_mgr_t pool_mgr;
|
||||
prio_q_prio_mgr_t prio_mgr;
|
||||
|
||||
size_t total;
|
||||
size_t item_size;
|
||||
size_t item_cnt;
|
||||
|
||||
uint8_t *mgr_pool;
|
||||
uint8_t *data_pool;
|
||||
} k_prio_q_t;
|
||||
|
||||
#define PRIO_Q_POOL_SLOT_INVALID ((prio_q_slot_t)-1)
|
||||
|
||||
#define PRIO_Q_POOL_MGR_ENT_ARRAY_SIZE(item_cnt) \
|
||||
(item_cnt * sizeof(prio_q_pool_mgr_ent_t))
|
||||
|
||||
#define PRIO_Q_PRIO_MGR_ENT_POOL_SIZE(item_cnt) \
|
||||
(item_cnt * sizeof(prio_q_prio_mgr_ent_t))
|
||||
|
||||
#define PRIO_Q_THE_ITEM(prio_q, slot) (void *)(&prio_q->data_pool[slot * prio_q->item_size])
|
||||
|
||||
// get the size of mgr_array to create a priority queue
|
||||
#define TOS_PRIO_Q_MGR_ARRAY_SIZE(item_cnt) \
|
||||
(PRIO_Q_POOL_MGR_ENT_ARRAY_SIZE(item_cnt) + PRIO_Q_PRIO_MGR_ENT_POOL_SIZE(item_cnt))
|
||||
|
||||
/**
|
||||
* @brief Create a priority queue.
|
||||
* create a priority queue.
|
||||
*
|
||||
* @attention if we wanna create a priority queue, we should offer a manager array buffer of which the size can be calculated by TOS_PRIO_Q_MGR_ARRAY_SIZE.
|
||||
*
|
||||
* @param[in] prio_q pointer to the handler of the priority queue.
|
||||
* @param[in] mgr_array manager array buffer of the priority queue.
|
||||
* @param[in] pool pool buffer of the priority queue.
|
||||
* @param[in] item_cnt item count of the priority queue.
|
||||
* @param[in] item_size size of each item of the priority queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_q_create(k_prio_q_t *prio_q, void *mgr_array, void *pool, size_t item_cnt, size_t item_size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a priority queue.
|
||||
* destroy a priority queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_q pointer to the handler of the bpriority queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_q_destroy(k_prio_q_t *prio_q);
|
||||
|
||||
/**
|
||||
* @brief Create a priority queue with dynamic allocated mgr array and data pool.
|
||||
* create a priority queue with dynamic allocated mgr array and data pool.
|
||||
*
|
||||
* @attention if we wanna create a priority queue, we should offer a manager array buffer of which the size can be calculated by TOS_PRIO_Q_MGR_ARRAY_SIZE.
|
||||
*
|
||||
* @param[in] prio_q pointer to the handler of the priority queue.
|
||||
* @param[in] item_cnt item count of the priority queue.
|
||||
* @param[in] item_size size of each item of the priority queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_q_create_dyn(k_prio_q_t *prio_q, size_t item_cnt, size_t item_size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a priority queue with dynamic allocated mgr array and data pool.
|
||||
* destroy a priority queue with dynamic allocated mgr array and data pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_q pointer to the handler of the bpriority queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_q_destroy_dyn(k_prio_q_t *prio_q);
|
||||
|
||||
/**
|
||||
* @brief Enqueue an priority queue.
|
||||
* enqueue an item into the priority queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_q pointer to the handler of priority queue.
|
||||
* @param[in] item the item to be enqueued.
|
||||
* @param[in] item_size size of the item(should be consistent with the item_size passed to tos_prio_q_create).
|
||||
* @param[in] prio priority of the item to be enqueued(should be consistent with the item_size passed to tos_prio_q_create).
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_PRIO_Q_ITEM_SIZE_NOT_MATCH the item_size is not consistent with the item_size passed to tos_prio_q_create.
|
||||
* @retval #K_ERR_PRIO_Q_FULL the priority queue is full.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_q_enqueue(k_prio_q_t *prio_q, void *item, size_t item_size, k_prio_t prio);
|
||||
|
||||
/**
|
||||
* @brief Dequeue an item.
|
||||
* dequeue an item from the priority queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_q pointer to the handler of the priority queue.
|
||||
* @param[out] item buffer to hold the item dequeued.
|
||||
* @param[out] item_size size of the item dequeued(should be consistent with the item_size passed to tos_prio_q_create).
|
||||
* @param[out] prio priority of the item dequeued.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_PRIO_Q_EMPTY the priority queue is empty.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_q_dequeue(k_prio_q_t *prio_q, void *item, size_t *item_size, k_prio_t *prio);
|
||||
|
||||
/**
|
||||
* @brief Flush the priority queue.
|
||||
* flush the priority queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_q pointer to the handler of the priority queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_prio_q_flush(k_prio_q_t *prio_q);
|
||||
|
||||
/**
|
||||
* @brief Whether the priority queue is empty.
|
||||
* Whether the priority queue is empty.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_q pointer to the handler of the priority queue.
|
||||
*
|
||||
* @return whether the priority queue is emtpy.
|
||||
* @retval #0 the priority queue is not empty.
|
||||
* @retval #Not 0 the priority queue is empty.
|
||||
*/
|
||||
__API__ int tos_prio_q_is_empty(k_prio_q_t *prio_q);
|
||||
|
||||
/**
|
||||
* @brief Whether the priority queue is full.
|
||||
* Whether the priority queue is full.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] prio_q pointer to the handler of the priority queue.
|
||||
*
|
||||
* @return whether the priority queue is full.
|
||||
* @retval #0 the priority queue is not full.
|
||||
* @retval #Not 0 the priority queue is full.
|
||||
*/
|
||||
__API__ int tos_prio_q_is_full(k_prio_q_t *prio_q);
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_PRIORITY_QUEUE_H_ */
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_RING_QUEUE_H_
|
||||
#define _TOS_RING_QUEUE_H_
|
||||
|
||||
typedef struct k_ring_queue_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
uint16_t head;
|
||||
uint16_t tail;
|
||||
size_t total;
|
||||
|
||||
uint8_t *pool;
|
||||
|
||||
size_t item_size;
|
||||
size_t item_cnt;
|
||||
} k_ring_q_t;
|
||||
|
||||
#define RING_HEAD_ITEM(ring_q) (uint8_t *)(&ring_q->pool[ring_q->head * ring_q->item_size])
|
||||
#define RING_TAIL_ITEM(ring_q) (uint8_t *)(&ring_q->pool[ring_q->tail * ring_q->item_size])
|
||||
#define RING_NEXT(ring_q, index) ((index + 1) % ring_q->item_cnt)
|
||||
|
||||
/**
|
||||
* @brief Create a ring queue.
|
||||
* create a ring queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] ring_q pointer to the handler of the ring queue.
|
||||
* @param[in] pool pool buffer of the ring queue.
|
||||
* @param[in] item_cnt item count of the ring queue.
|
||||
* @param[in] item_size size of each item of the ring queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_ring_q_create(k_ring_q_t *ring_q, void *pool, size_t item_cnt, size_t item_size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a ring queue.
|
||||
* destroy a ring queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] ring_q pointer to the handler of the ring queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_OBJ_INVALID_ALLOC_TYPE invalid alloc type(is dynamic allocated not static)
|
||||
*/
|
||||
__API__ k_err_t tos_ring_q_destroy(k_ring_q_t *ring_q);
|
||||
|
||||
/**
|
||||
* @brief Create a ring queue with dynamic allocated pool.
|
||||
* create a ring queue with dynamic allocated pool.
|
||||
*
|
||||
* @attention pool inside is dynamic allocated.
|
||||
*
|
||||
* @param[in] ring_q pointer to the handler of the ring queue.
|
||||
* @param[in] item_cnt item count of the ring queue.
|
||||
* @param[in] item_size size of each item of the ring queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_OUT_OF_MEMORY out of memory
|
||||
*/
|
||||
__API__ k_err_t tos_ring_q_create_dyn(k_ring_q_t *ring_q, size_t item_cnt, size_t item_size);
|
||||
|
||||
/**
|
||||
* @brief Destroy a ring queue with a dynamic allocated pool.
|
||||
* destroy a ring queue with a dynamic allocated pool.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] ring_q pointer to the handler of the ring queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_OBJ_INVALID_ALLOC_TYPE invalid alloc type(is static allocated not dynamic)
|
||||
*/
|
||||
__API__ k_err_t tos_ring_q_destroy_dyn(k_ring_q_t *ring_q);
|
||||
|
||||
/**
|
||||
* @brief Enqueue an item.
|
||||
* enqueue an item into the ring queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] ring_q pointer to the handler of the ring queue.
|
||||
* @param[in] item the item to be enqueued.
|
||||
* @param[in] item_size size of the item(should be consistent with the item_size passed to tos_ring_q_create).
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_RING_Q_ITEM_SIZE_NOT_MATCH the item_size is not consistent with the item_size passed to tos_ring_q_create.
|
||||
* @retval #K_ERR_RING_Q_FULL the ring queue is full.
|
||||
*/
|
||||
__API__ k_err_t tos_ring_q_enqueue(k_ring_q_t *ring_q, void *item, size_t item_size);
|
||||
|
||||
/**
|
||||
* @brief Dequeue an item.
|
||||
* dequeue an item from the ring queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] ring_q pointer to the handler of the ring queue.
|
||||
* @param[out] item buffer to hold the item dequeued.
|
||||
* @param[out] item_size size of the item dequeued(should be consistent with the item_size passed to tos_ring_q_create).
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_RING_Q_EMPTY the ring queue is empty.
|
||||
*/
|
||||
__API__ k_err_t tos_ring_q_dequeue(k_ring_q_t *ring_q, void *item, size_t *item_size);
|
||||
|
||||
/**
|
||||
* @brief Flush the ring queue.
|
||||
* flush the ring queue.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] ring_q pointer to the handler of the ring queue.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_ring_q_flush(k_ring_q_t *ring_q);
|
||||
|
||||
/**
|
||||
* @brief Whether the ring queue is empty.
|
||||
* Whether the ring queue is empty.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] ring_q pointer to the handler of the ring queue.
|
||||
*
|
||||
* @return whether the ring queue is emtpy.
|
||||
* @retval #0 the ring queue is not empty.
|
||||
* @retval #Not 0 the ring queue is empty.
|
||||
*/
|
||||
__API__ int tos_ring_q_is_empty(k_ring_q_t *ring_q);
|
||||
|
||||
/**
|
||||
* @brief Whether the ring queue is full.
|
||||
* Whether the ring queue is full.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] ring_q pointer to the handler of the ring queue.
|
||||
*
|
||||
* @return whether the ring queue is full.
|
||||
* @retval #0 the ring queue is not full.
|
||||
* @retval #Not 0 the ring queue is full.
|
||||
*/
|
||||
__API__ int tos_ring_q_is_full(k_ring_q_t *ring_q);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_ROBIN_H_
|
||||
#define _TOS_ROBIN_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_ROUND_ROBIN_EN > 0u
|
||||
|
||||
/**
|
||||
* @brief Set time slice.
|
||||
* Set time slice of a task.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] task pointer to the handler of the task.
|
||||
* @param[in] timeslice time slice of the task
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__API__ void tos_robin_timeslice_set(k_task_t *task, k_timeslice_t timeslice);
|
||||
|
||||
/**
|
||||
* @brief Configure round robin.
|
||||
* Set the default time slice of the task.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] default_timeslice default time slice of the task.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__API__ void tos_robin_default_timeslice_config(k_timeslice_t default_timeslice);
|
||||
|
||||
__KNL__ void robin_sched(k_prio_t prio);
|
||||
|
||||
#endif /* TOS_CFG_ROUND_ROBIN_EN */
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_ROBIN_H_ */
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_RWLOCK_H_
|
||||
#define _TOS_RWLOCK_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if (TOS_CFG_SEM_EN > 0u) && (TOS_CFG_MUTEX_EN > 0u)
|
||||
|
||||
typedef uint16_t rw_cnt_t;
|
||||
|
||||
typedef struct k_rwlock_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
k_mutex_t lock;
|
||||
k_sem_t signal;
|
||||
|
||||
rw_cnt_t n_readers; /* how many readers are reading? */
|
||||
rw_cnt_t n_writers; /* how many writers are waiting to obtain the wlock? */
|
||||
int is_writting;
|
||||
} k_rwlock_t;
|
||||
|
||||
/**
|
||||
* @brief Create a read-write lock.
|
||||
*
|
||||
* @attention a read-write lock can be hold by multi-readers, that means simultaneously reading is allowed;
|
||||
* but a read-write lock can only be hold by one writes, that means simultaneously writting or read while writting is not allowed.
|
||||
*
|
||||
* @param[in] rwlock the read-write lock.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_rwlock_create(k_rwlock_t *rwlock);
|
||||
|
||||
/**
|
||||
* @brief Destroy a read-write lock.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] rwlock the read-write lock.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_rwlock_destroy(k_rwlock_t *rwlock);
|
||||
|
||||
/**
|
||||
* @brief Pend on the read-lock of a read-write lock.
|
||||
*
|
||||
* @attention if one reader already hold the read-lock, other reader can hold the read-lock simultaneously.
|
||||
* and no writers can hold the write-lock.
|
||||
*
|
||||
* @param[in] rwlock the read-write lock.
|
||||
* @param[in] timeout how much time(in k_tick_t) we would like to wait.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_RWLOCK_READERS_TO_MANY too many reader are holding the read-lock
|
||||
*/
|
||||
__API__ k_err_t tos_rwlock_rpend_timed(k_rwlock_t *rwlock, k_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Pend on the read-lock of a read-write lock.
|
||||
*
|
||||
* @attention if one reader already hold the read-lock, other reader can hold the read-lock simultaneously.
|
||||
* and no writers can hold the write-lock.
|
||||
*
|
||||
* @param[in] rwlock the read-write lock.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_RWLOCK_READERS_TO_MANY too many reader are holding the read-lock
|
||||
*/
|
||||
__API__ k_err_t tos_rwlock_rpend(k_rwlock_t *rwlock);
|
||||
|
||||
/**
|
||||
* @brief Try pend on the read-lock of a read-write lock.
|
||||
*
|
||||
* @attention Try means just take a look, if can obtain the read-lock, then we obtain it; otherwise, just return with no-waiting.
|
||||
*
|
||||
* @param[in] rwlock the read-write lock.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_RWLOCK_IS_WRITTING the read-write lock is hold by a writter(is writting).
|
||||
*/
|
||||
__API__ k_err_t tos_rwlock_rpend_try(k_rwlock_t *rwlock);
|
||||
|
||||
/**
|
||||
* @brief Pend on the write-lock of a read-write lock.
|
||||
*
|
||||
* @attention if one writer already hold the write-lock, other writer CANNOT hold the write-lock any more.
|
||||
* and no readers can hold the read-lock.
|
||||
*
|
||||
* @param[in] rwlock the read-write lock.
|
||||
* @param[in] timeout how much time(in k_tick_t) we would like to wait.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_RWLOCK_WAITING_WRITERS_TO_MANY too many writers are waiting for the write-lock
|
||||
*/
|
||||
__API__ k_err_t tos_rwlock_wpend_timed(k_rwlock_t *rwlock, k_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Pend on the write-lock of a read-write lock.
|
||||
*
|
||||
* @attention if one writer already hold the write-lock, other writer CANNOT hold the write-lock any more.
|
||||
* and no readers can hold the read-lock.
|
||||
*
|
||||
* @param[in] rwlock the read-write lock.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_RWLOCK_WAITING_WRITERS_TO_MANY too many writers are waiting for the write-lock
|
||||
*/
|
||||
__API__ k_err_t tos_rwlock_wpend(k_rwlock_t *rwlock);
|
||||
|
||||
/**
|
||||
* @brief Pend on the write-lock of a read-write lock.
|
||||
*
|
||||
* @attention Try means just take a look, if can obtain the write-lock, then we obtain it; otherwise, just return with no-waiting.
|
||||
*
|
||||
* @param[in] rwlock the read-write lock.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_RWLOCK_IS_READING the read-write lock is hold by other reader[s](is reading).
|
||||
* @retval #K_ERR_RWLOCK_IS_WRITTING the read-write lock is hold by another writter(is writting).
|
||||
*/
|
||||
__API__ k_err_t tos_rwlock_wpend_try(k_rwlock_t *rwlock);
|
||||
|
||||
/**
|
||||
* @brief Post the read-lock of a read-write lock.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] rwlock the read-write lock.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_RWLOCK_NOT_READING the read-lock is not held by reader[s].
|
||||
*/
|
||||
__API__ k_err_t tos_rwlock_rpost(k_rwlock_t *rwlock);
|
||||
|
||||
/**
|
||||
* @brief Post the write-lock of a read-write lock.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] rwlock the read-write lock.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_RWLOCK_NOT_WRITTING the write-lock is not held by a writter.
|
||||
*/
|
||||
__API__ k_err_t tos_rwlock_wpost(k_rwlock_t *rwlock);
|
||||
|
||||
/**
|
||||
* @brief Post the read&write-lock of a read-write lock.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] rwlock the read-write lock.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
* @retval #K_ERR_RWLOCK_NOT_TAKEN the read-write lock is neither held by reader[s] nor held by a writter.
|
||||
*/
|
||||
__API__ k_err_t tos_rwlock_post(k_rwlock_t *rwlock);
|
||||
|
||||
#endif
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_RWLOCK_H_ */
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_SCHED_H_
|
||||
#define _TOS_SCHED_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#define K_PRIO_TBL_SIZE ((TOS_CFG_TASK_PRIO_MAX + 31) / 32)
|
||||
#define K_PRIO_TBL_SLOT_SIZE (8 * sizeof(uint32_t))
|
||||
|
||||
#define K_PRIO_NDX(prio) ((prio) >> 5u) /* prio / 32u */
|
||||
#define K_PRIO_BIT(prio) ((uint32_t)1u << (K_PRIO_TBL_SLOT_SIZE - 1u - ((prio) & (K_PRIO_TBL_SLOT_SIZE - 1u))))
|
||||
|
||||
typedef struct readyqueue_st {
|
||||
k_list_t task_list_head[TOS_CFG_TASK_PRIO_MAX];
|
||||
uint32_t prio_mask[K_PRIO_TBL_SIZE];
|
||||
k_prio_t highest_prio;
|
||||
} readyqueue_t;
|
||||
|
||||
__KNL__ void readyqueue_init(void);
|
||||
|
||||
__KNL__ int readyqueue_is_prio_onlyone(k_prio_t prio);
|
||||
|
||||
__KNL__ k_task_t *readyqueue_first_task_get(k_prio_t prio);
|
||||
|
||||
__KNL__ k_task_t *readyqueue_highest_ready_task_get(void);
|
||||
|
||||
__KNL__ void readyqueue_add_head(k_task_t *task);
|
||||
|
||||
__KNL__ void readyqueue_add_tail(k_task_t *task);
|
||||
|
||||
__KNL__ void readyqueue_add(k_task_t *task);
|
||||
|
||||
__KNL__ void readyqueue_remove(k_task_t *task);
|
||||
|
||||
__KNL__ void readyqueue_move_head_to_tail(k_prio_t prio);
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_SCHED_H_ */
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_SEM_H_
|
||||
#define _TOS_SEM_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_SEM_EN > 0u
|
||||
|
||||
typedef struct k_sem_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
pend_obj_t pend_obj;
|
||||
k_sem_cnt_t count;
|
||||
k_sem_cnt_t count_max;
|
||||
} k_sem_t;
|
||||
|
||||
/**
|
||||
* @brief Create a semaphore with a limitation of maximum count.
|
||||
* create a semaphore with a limitation of maximum count.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] sem pointer to the handler of the semaphore.
|
||||
* @param[in] init_count initial count of the semaphore.
|
||||
* @param[in] max_count maximum count of the semaphore.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_sem_create_max(k_sem_t *sem, k_sem_cnt_t init_count, k_sem_cnt_t max_count);
|
||||
|
||||
/**
|
||||
* @brief Create a semaphore.
|
||||
* create a semaphore.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] sem pointer to the handler of the semaphore.
|
||||
* @param[in] init_count initial count of the semaphore.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_sem_create(k_sem_t *sem, k_sem_cnt_t init_count);
|
||||
|
||||
/**
|
||||
* @brief Create a dynamic semaphore with a limitation of maximum count.
|
||||
* create a dynamic semaphore with a limitation of maximum count.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] sem pointer to the pointer of the semaphore.
|
||||
* @param[in] init_count initial count of the semaphore.
|
||||
* @param[in] max_count maximum count of the semaphore.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_sem_create_max_dyn(k_sem_t **sem, k_sem_cnt_t init_count, k_sem_cnt_t max_count);
|
||||
|
||||
/**
|
||||
* @brief Create a dynamic semaphore.
|
||||
* create a dynamic semaphore.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] sem pointer to the pointer of the semaphore.
|
||||
* @param[in] init_count initial count of the semaphore.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_sem_create_dyn(k_sem_t **sem, k_sem_cnt_t init_count);
|
||||
|
||||
/**
|
||||
* @brief Destroy a semaphore.
|
||||
* destroy a semaphore.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] semaphore pointer to the handler of the semaphore.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_sem_destroy(k_sem_t *sem);
|
||||
|
||||
/**
|
||||
* @brief Pend a semaphore.
|
||||
* pend a semaphore.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] sem pointer to the handler of the semaphore.
|
||||
* @param[in] timeout how much time(in k_tick_t) we would like to wait.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_PEND_NOWAIT we get nothing, and we don't wanna wait.
|
||||
* @retval #K_ERR_PEND_SCHED_LOCKED we can wait, but scheduler is locked.
|
||||
* @retval #K_ERR_PEND_TIMEOUT the time we wait is up, we get nothing.
|
||||
* @retval #K_ERR_PEND_DESTROY the semaphore we are pending is destroyed.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_sem_pend(k_sem_t *sem, k_tick_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Post a semaphore.
|
||||
* post a semaphore and wakeup one pending task.
|
||||
*
|
||||
* @attention when tos_sem_post return successfully, only one task who are waitting for the semaphore will be woken up.
|
||||
*
|
||||
* @param[in] sem pointer to the handler of the semaphore.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_SEM_OVERFLOW we are nesting post a semaphore too much.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_sem_post(k_sem_t *sem);
|
||||
|
||||
/**
|
||||
* @brief Post a semaphore.
|
||||
* post a semaphore and wakeup all the pending task.
|
||||
*
|
||||
* @attention when tos_sem_post_all return successfully, all of the tasks who are waitting for the semaphore will be woken up.
|
||||
*
|
||||
* @param[in] sem pointer to the handler of the semaphore.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_SEM_OVERFLOW we are nesting post a semaphore too much.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_sem_post_all(k_sem_t *sem);
|
||||
|
||||
#endif
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_SEM_H_ */
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_SLIST_H_
|
||||
#define _TOS_SLIST_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
typedef struct k_slist_node_st {
|
||||
struct k_slist_node_st *next;
|
||||
} k_slist_t;
|
||||
|
||||
#define TOS_SLIST_NODE(dummy) \
|
||||
{ K_NULL }
|
||||
|
||||
#define TOS_SLIST_DEFINE(slist) \
|
||||
k_slist_t slist = { K_NULL }
|
||||
|
||||
#define TOS_SLIST_ENTRY(node, type, field) \
|
||||
TOS_CONTAINER_OF_FIELD(node, type, field)
|
||||
|
||||
#define TOS_SLIST_FIRST_ENTRY(slist, type, field) \
|
||||
TOS_SLIST_ENTRY((slist)->next, type, field)
|
||||
|
||||
#define TOS_SLIST_FIRST_ENTRY_OR_NULL(slist, type, field) \
|
||||
(tos_slist_empty(slist) ? K_NULL : TOS_SLIST_FIRST_ENTRY(slist, type, field))
|
||||
|
||||
#define TOS_SLIST_FOR_EACH(curr, slist) \
|
||||
for (curr = (slist)->next; curr; curr = curr->next)
|
||||
|
||||
#define TOS_SLIST_FOR_EACH_SAFE(curr, next, slist) \
|
||||
for (curr = (slist)->next, next = curr->next; curr; \
|
||||
curr = next, next = curr->next)
|
||||
|
||||
#define TOS_SLIST_FOR_EACH_ENTRY(entry, type, field, slist) \
|
||||
for (entry = TOS_SLIST_ENTRY((slist)->next, type, field); \
|
||||
&entry->field; \
|
||||
entry = TOS_SLIST_ENTRY(entry->field.next, type, field))
|
||||
|
||||
#define TOS_SLIST_FOR_EACH_ENTRY_SAFE(entry, tmp, type, field, slist) \
|
||||
for (entry = TOS_SLIST_ENTRY((slist)->next, type, field), \
|
||||
tmp = TOS_SLIST_ENTRY(entry->field.next, type, field); \
|
||||
&entry->field; \
|
||||
entry = tmp, tmp = TOS_SLIST_ENTRY(entry->field.next, type, field))
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_slist_init(k_slist_t *slist)
|
||||
{
|
||||
slist->next = K_NULL;
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ k_slist_t *tos_slist_head(k_slist_t *slist)
|
||||
{
|
||||
return slist->next;
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ k_slist_t *tos_slist_tail(k_slist_t *slist)
|
||||
{
|
||||
if (!slist->next) {
|
||||
return K_NULL;
|
||||
}
|
||||
|
||||
while (slist->next) {
|
||||
slist = slist->next;
|
||||
}
|
||||
|
||||
return slist;
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_slist_add_head(k_slist_t *node, k_slist_t *slist)
|
||||
{
|
||||
node->next = slist->next;
|
||||
slist->next = node;
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_slist_add_tail(k_slist_t *node, k_slist_t *slist)
|
||||
{
|
||||
node->next = K_NULL;
|
||||
|
||||
while (slist->next) {
|
||||
slist = slist->next;
|
||||
}
|
||||
|
||||
tos_slist_add_head(node, slist);
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_slist_insert(k_slist_t *next_node, k_slist_t *new_node, k_slist_t *slist)
|
||||
{
|
||||
if (!next_node) {
|
||||
tos_slist_add_tail(new_node, slist);
|
||||
return;
|
||||
}
|
||||
|
||||
while (slist->next) {
|
||||
if (slist->next == next_node) {
|
||||
slist->next = new_node;
|
||||
new_node->next = next_node;
|
||||
}
|
||||
|
||||
slist = slist->next;
|
||||
}
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ k_slist_t *tos_slist_del_head(k_slist_t *slist)
|
||||
{
|
||||
k_slist_t *head;
|
||||
|
||||
if (!slist->next) {
|
||||
return K_NULL;
|
||||
}
|
||||
|
||||
head = slist->next;
|
||||
slist->next = head->next;
|
||||
head->next = K_NULL;
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ k_slist_t *tos_slist_del_tail(k_slist_t *slist)
|
||||
{
|
||||
while (slist->next) {
|
||||
if (!slist->next->next) {
|
||||
return tos_slist_del_head(slist);
|
||||
}
|
||||
|
||||
slist = slist->next;
|
||||
}
|
||||
|
||||
return K_NULL;
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ void tos_slist_del(k_slist_t *node, k_slist_t *slist)
|
||||
{
|
||||
while (slist->next) {
|
||||
if (slist->next == node) {
|
||||
slist->next = node->next;
|
||||
break;
|
||||
}
|
||||
|
||||
slist = slist->next;
|
||||
}
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ int tos_slist_length(k_slist_t *slist)
|
||||
{
|
||||
int len = 0;
|
||||
k_slist_t *iter;
|
||||
|
||||
TOS_SLIST_FOR_EACH(iter, slist) {
|
||||
++len;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
__API__ __STATIC_INLINE__ int tos_slist_contains(k_slist_t *node, k_slist_t *slist)
|
||||
{
|
||||
while (slist->next) {
|
||||
if (slist->next == node) {
|
||||
return K_TRUE;
|
||||
}
|
||||
|
||||
slist = slist->next;
|
||||
}
|
||||
|
||||
return K_FALSE;
|
||||
}
|
||||
__API__ __STATIC_INLINE__ int tos_slist_empty(k_slist_t *slist)
|
||||
{
|
||||
return !slist->next;
|
||||
}
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_SLIST_H_ */
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_STOPWATCH_H_
|
||||
#define _TOS_STOPWATCH_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
typedef struct k_stopwatch_st {
|
||||
knl_obj_t knl_obj;
|
||||
|
||||
k_tick_t until;
|
||||
} k_stopwatch_t;
|
||||
|
||||
/**
|
||||
* @brief Create a stopwatch.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] stopwatch the stopwatch.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_stopwatch_create(k_stopwatch_t *stopwatch);
|
||||
|
||||
/**
|
||||
* @brief Destroy a stopwatch.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] stopwatch the stopwatch.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_stopwatch_destroy(k_stopwatch_t *stopwatch);
|
||||
|
||||
/**
|
||||
* @brief Count down for a certain tick.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] stopwatch the stopwatch.
|
||||
* @param[in] tick tick to count down.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_stopwatch_countdown(k_stopwatch_t *stopwatch, k_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief Count down for a certain time(in millisecond).
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] stopwatch the stopwatch.
|
||||
* @param[in] millisec time(in millisecond) to count down.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_stopwatch_countdown_ms(k_stopwatch_t *stopwatch, k_time_t millisec);
|
||||
|
||||
/**
|
||||
* @brief Delay for a certain tick.
|
||||
*
|
||||
* @attention the stopwatch delay is a "busy" delay without give up of CPU(compared to tos_task_delay)
|
||||
*
|
||||
* @param[in] tick tick to delay.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__API__ void tos_stopwatch_delay(k_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief Delay for a certain time(in millisecond).
|
||||
*
|
||||
* @attention the stopwatch delay is a "busy" delay without give up of CPU(compared to tos_task_delay)
|
||||
*
|
||||
* @param[in] millisec time(in millisecond) to delay.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__API__ void tos_stopwatch_delay_ms(k_time_t millisec);
|
||||
|
||||
/**
|
||||
* @brief How much time remain of the stopwatch(in tick).
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] stopwatch the stopwatch.
|
||||
*
|
||||
* @return ticks remain
|
||||
*/
|
||||
__API__ k_tick_t tos_stopwatch_remain(k_stopwatch_t *stopwatch);
|
||||
|
||||
/**
|
||||
* @brief How much time remain of the stopwatch(in millisecond).
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] stopwatch the stopwatch.
|
||||
*
|
||||
* @return milliseconds remain
|
||||
*/
|
||||
__API__ k_time_t tos_stopwatch_remain_ms(k_stopwatch_t *stopwatch);
|
||||
|
||||
/**
|
||||
* @brief Whether the stopwatch is expired.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] stopwatch the stopwatch.
|
||||
*
|
||||
* @return whether the stopwatch is expired
|
||||
* @retval #K_TRUE the stopwatch is expired.
|
||||
* @retval #K_FALSE the stopwatch is no expired.
|
||||
*/
|
||||
__API__ int tos_stopwatch_is_expired(k_stopwatch_t *stopwatch);
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_STOPWATCH_H_ */
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_SYS_H_
|
||||
#define _TOS_SYS_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#define K_NESTING_LIMIT_IRQ (k_nesting_t)250u
|
||||
#define K_NESTING_LIMIT_SCHED_LOCK (k_nesting_t)250u
|
||||
|
||||
typedef enum knl_state_en {
|
||||
KNL_STATE_STOPPED,
|
||||
KNL_STATE_RUNNING,
|
||||
} knl_state_t;
|
||||
|
||||
// some kind of magic number, mainly for identifing whether the object is initialized, or whether user pass the correct parameter.
|
||||
typedef enum knl_obj_type_en {
|
||||
KNL_OBJ_TYPE_NONE = 0x0000,
|
||||
|
||||
KNL_OBJ_TYPE_BINARY_HEAP = 0xDAD0,
|
||||
KNL_OBJ_TYPE_BITMAP = 0xDAD1,
|
||||
KNL_OBJ_TYPE_CHAR_FIFO = 0xDAD2,
|
||||
KNL_OBJ_TYPE_MMBLK_POOL = 0xDAD3,
|
||||
KNL_OBJ_TYPE_MSG_QUEUE = 0xDAD4,
|
||||
KNL_OBJ_TYPE_PRIORITY_QUEUE = 0xDAD5,
|
||||
KNL_OBJ_TYPE_RING_QUEUE = 0xDAD6,
|
||||
KNL_OBJ_TYPE_STOPWATCH = 0xDAD7,
|
||||
KNL_OBJ_TYPE_TASK = 0xDAD8,
|
||||
KNL_OBJ_TYPE_TIMER = 0xDAD9,
|
||||
|
||||
// ipc object
|
||||
KNL_OBJ_TYPE_BARRIER = 0x0BEE,
|
||||
KNL_OBJ_TYPE_COMPLETION = 0x1BEE,
|
||||
KNL_OBJ_TYPE_COUNTDOWNLATCH = 0x2BEE,
|
||||
KNL_OBJ_TYPE_EVENT = 0x3BEE,
|
||||
KNL_OBJ_TYPE_MAIL_QUEUE = 0x4BEE,
|
||||
KNL_OBJ_TYPE_MESSAGE_QUEUE = 0x5BEE,
|
||||
KNL_OBJ_TYPE_MUTEX = 0x6BEE,
|
||||
KNL_OBJ_TYPE_PRIORITY_MAIL_QUEUE = 0x7BEE,
|
||||
KNL_OBJ_TYPE_PRIORITY_MESSAGE_QUEUE = 0x8BEE,
|
||||
KNL_OBJ_TYPE_RWLOCK = 0x9BEE,
|
||||
KNL_OBJ_TYPE_SEMAPHORE = 0xABEE,
|
||||
} knl_obj_type_t;
|
||||
|
||||
typedef enum knl_obj_alloc_type_en {
|
||||
KNL_OBJ_ALLOC_TYPE_NONE,
|
||||
KNL_OBJ_ALLOC_TYPE_STATIC,
|
||||
KNL_OBJ_ALLOC_TYPE_DYNAMIC,
|
||||
} knl_obj_alloc_type_t;
|
||||
|
||||
typedef struct knl_object_st {
|
||||
knl_obj_alloc_type_t alloc_type; /* is dynamic allocated(using tos_mmheap) or static memory? */
|
||||
#if TOS_CFG_OBJECT_VERIFY_EN > 0u
|
||||
knl_obj_type_t type;
|
||||
#endif
|
||||
} knl_obj_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the kernel.
|
||||
* initialize the tos tiny kernel.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return errcode
|
||||
* @retval Non-#K_ERR_NONE return failed.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_knl_init(void);
|
||||
|
||||
/**
|
||||
* @brief Start the kernel.
|
||||
* get the kernel start to run, which means start the multitask scheduling.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_KNL_RUNNING the kernel is already running.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_knl_start(void);
|
||||
|
||||
/**
|
||||
* @brief Get the kernel state.
|
||||
* whether the kernel is running.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return whether the kernel is running.
|
||||
* @retval Non-0 the kernel is running.
|
||||
* @retval 0 the kernel is not running.
|
||||
*/
|
||||
__API__ int tos_knl_is_running(void);
|
||||
|
||||
/**
|
||||
* @brief Kernel enter the interrupt.
|
||||
* this function should be called in the entrance of a interrupt handler.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__API__ void tos_knl_irq_enter(void);
|
||||
|
||||
/**
|
||||
* @brief Kernel exit the interrupt.
|
||||
* this function should be called in the exit of a interrupt handler.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__API__ void tos_knl_irq_leave(void);
|
||||
|
||||
/**
|
||||
* @brief Lock the scheduler.
|
||||
* prevent the kernel from performing task schedule.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return errcode
|
||||
* @retval K_ERR_KNL_NOT_RUNNING the kernel is not running.
|
||||
* @retval K_ERR_LOCK_NESTING_OVERFLOW the schedule lock nesting is overflow.
|
||||
* @retval K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_knl_sched_lock(void);
|
||||
|
||||
/**
|
||||
* @brief Unlock the scheduler.
|
||||
* re-enable the task schedule.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return errcode
|
||||
* @retval K_ERR_KNL_NOT_RUNNING the kernel is not running.
|
||||
* @retval K_ERR_SCHED_NOT_LOCKED the scheduler is not locked.
|
||||
* @retval K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_knl_sched_unlock(void);
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
__KNL__ k_tick_t knl_next_expires_get(void);
|
||||
#endif
|
||||
|
||||
__KNL__ void knl_sched(void);
|
||||
__KNL__ int knl_is_sched_locked(void);
|
||||
__KNL__ int knl_is_inirq(void);
|
||||
__KNL__ int knl_is_idle(k_task_t *task);
|
||||
__KNL__ int knl_is_self(k_task_t *task);
|
||||
__KNL__ k_err_t knl_idle_init(void);
|
||||
|
||||
#if TOS_CFG_OBJECT_VERIFY_EN > 0u
|
||||
|
||||
__KNL__ __STATIC_INLINE__ int knl_object_verify(knl_obj_t *knl_obj, knl_obj_type_t type)
|
||||
{
|
||||
return knl_obj->type == type;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void knl_object_init(knl_obj_t *knl_obj, knl_obj_type_t type)
|
||||
{
|
||||
knl_obj->type = type;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void knl_object_deinit(knl_obj_t *knl_obj)
|
||||
{
|
||||
knl_obj->type = KNL_OBJ_TYPE_NONE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void knl_object_alloc_reset(knl_obj_t *knl_obj)
|
||||
{
|
||||
knl_obj->alloc_type = KNL_OBJ_ALLOC_TYPE_NONE;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void knl_object_alloc_set_dynamic(knl_obj_t *knl_obj)
|
||||
{
|
||||
knl_obj->alloc_type = KNL_OBJ_ALLOC_TYPE_DYNAMIC;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void knl_object_alloc_set_static(knl_obj_t *knl_obj)
|
||||
{
|
||||
knl_obj->alloc_type = KNL_OBJ_ALLOC_TYPE_STATIC;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ int knl_object_alloc_is_dynamic(knl_obj_t *knl_obj)
|
||||
{
|
||||
return knl_obj->alloc_type == KNL_OBJ_ALLOC_TYPE_DYNAMIC;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ int knl_object_alloc_is_static(knl_obj_t *knl_obj)
|
||||
{
|
||||
return knl_obj->alloc_type == KNL_OBJ_ALLOC_TYPE_STATIC;
|
||||
}
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_SYS_H_ */
|
||||
|
||||
@@ -0,0 +1,445 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_TASK_H_
|
||||
#define _TOS_TASK_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#define K_TASK_NAME_LEN_MAX (15u)
|
||||
#define K_TASK_NAME_MAX (K_TASK_NAME_LEN_MAX + 1)
|
||||
#define K_TASK_STK_SIZE_MIN (sizeof(cpu_context_t))
|
||||
|
||||
// task state is just a flag, indicating which manager list we are in.
|
||||
|
||||
// ready to schedule
|
||||
// a task's pend_list is in readyqueue
|
||||
#define K_TASK_STATE_READY (k_task_state_t)0x0000
|
||||
|
||||
// delayed, or pend for a timeout
|
||||
// a task's tick_list is in k_tick_list
|
||||
#define K_TASK_STATE_SLEEP (k_task_state_t)0x0001
|
||||
|
||||
// pend for something
|
||||
// a task's pend_list is in some pend object's list
|
||||
#define K_TASK_STATE_PEND (k_task_state_t)0x0002
|
||||
|
||||
// suspended
|
||||
#define K_TASK_STATE_SUSPENDED (k_task_state_t)0x0004
|
||||
|
||||
// deleted
|
||||
#define K_TASK_STATE_DELETED (k_task_state_t)0x0008
|
||||
|
||||
// actually we don't really need those TASK_STATE below, if you understand the task state deeply, the code can be much more elegant.
|
||||
|
||||
// we are pending, also we are waitting for a timeout(eg. tos_sem_pend with a valid timeout, not TOS_TIME_FOREVER)
|
||||
// both a task's tick_list and pend_list is not empty
|
||||
#define K_TASK_STATE_PENDTIMEOUT (k_task_state_t)(K_TASK_STATE_PEND | K_TASK_STATE_SLEEP)
|
||||
|
||||
// suspended when sleeping
|
||||
#define K_TASK_STATE_SLEEP_SUSPENDED (k_task_state_t)(K_TASK_STATE_SLEEP | K_TASK_STATE_SUSPENDED)
|
||||
|
||||
// suspended when pending
|
||||
#define K_TASK_STATE_PEND_SUSPENDED (k_task_state_t)(K_TASK_STATE_PEND | K_TASK_STATE_SUSPENDED)
|
||||
|
||||
// suspended when pendtimeout
|
||||
#define K_TASK_STATE_PENDTIMEOUT_SUSPENDED (k_task_state_t)(K_TASK_STATE_PENDTIMEOUT | K_TASK_STATE_SUSPENDED)
|
||||
|
||||
|
||||
// if you configure TOS_CFG_TASK_PRIO_MAX as 10, means the priority for kernel is (0 ... 9]
|
||||
// the priority 9(TOS_CFG_TASK_PRIO_MAX - 1) is only for idle, so avaliable priority for you is (0 ... 8]
|
||||
#define K_TASK_PRIO_IDLE (k_prio_t)(TOS_CFG_TASK_PRIO_MAX - (k_prio_t)1u)
|
||||
#define K_TASK_PRIO_INVALID (k_prio_t)(TOS_CFG_TASK_PRIO_MAX)
|
||||
|
||||
typedef void (*k_task_entry_t)(void *arg);
|
||||
|
||||
typedef void (*k_task_walker_t)(k_task_t *task);
|
||||
|
||||
/**
|
||||
* task control block
|
||||
*/
|
||||
struct k_task_st {
|
||||
k_stack_t *sp; /**< task stack pointer. This lady always comes first, we count on her in port_s.S for context switch. */
|
||||
|
||||
knl_obj_t knl_obj; /**< just for verification, test whether current object is really a task. */
|
||||
|
||||
char name[K_TASK_NAME_MAX]; /**< task name */
|
||||
k_task_entry_t entry; /**< task entry */
|
||||
void *arg; /**< argument for task entry */
|
||||
k_task_state_t state; /**< just state */
|
||||
k_prio_t prio; /**< just priority */
|
||||
|
||||
k_stack_t *stk_base; /**< task stack base address */
|
||||
size_t stk_size; /**< stack size of the task */
|
||||
|
||||
#if TOS_CFG_TASK_DYNAMIC_CREATE_EN > 0u
|
||||
k_list_t dead_list; /**< when a dynamic allocated task destroyed, we hook the task's dead_list to the k_dead_task_list */
|
||||
#endif
|
||||
|
||||
k_list_t stat_list; /**< list for hooking us to the k_stat_list */
|
||||
|
||||
k_tick_t tick_expires; /**< if we are in k_tick_list, how much time will we wait for? */
|
||||
|
||||
k_list_t tick_list; /**< list for hooking us to the k_tick_list */
|
||||
k_list_t pend_list; /**< when we are ready, our pend_list is in readyqueue; when pend, in a certain pend object's list. */
|
||||
|
||||
#if TOS_CFG_MUTEX_EN > 0u
|
||||
k_list_t mutex_own_list; /**< the list hold all the mutex we own.
|
||||
When we die(tos_task_destroy), we have an obligation to wakeup all the task pending for those mutexs we own;
|
||||
if not, those pending tasks may never get a chance to wakeup. */
|
||||
k_prio_t prio_pending; /*< when tos_task_prio_change called, we may be just the owner of a mutex.
|
||||
to avoid PRIORITY INVERSION, must make sure our priority is higher than any one who is pending for
|
||||
the mutex we hold. So, if the prio_new of tos_task_prio_change is not appropriate
|
||||
(may against the principle of PRIORITY INVERSION), we just mark the prio_new here, do the real priority
|
||||
change in the right time(mutex_old_owner_release) later. */
|
||||
#endif
|
||||
|
||||
pend_obj_t *pending_obj; /**< if we are pending, which pend object's list we are in? */
|
||||
pend_state_t pend_state; /**< why we wakeup from a pend */
|
||||
|
||||
#if TOS_CFG_ROUND_ROBIN_EN > 0u
|
||||
k_timeslice_t timeslice_reload; /**< if current time slice is used up, use time_slice_reload to reload our time slice */
|
||||
k_timeslice_t timeslice; /**< how much time slice left for us? */
|
||||
#endif
|
||||
|
||||
#if (TOS_CFG_MESSAGE_QUEUE_EN > 0u) || (TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN > 0u)
|
||||
void *msg; /**< if we pend a message queue successfully, our msg will be set by the message queue poster */
|
||||
#endif
|
||||
|
||||
#if (TOS_CFG_MAIL_QUEUE_EN > 0u) || (TOS_CFG_PRIORITY_MAIL_QUEUE_EN > 0u)
|
||||
void *mail; /**< if we pend a mail queue successfully, our mail and mail_size will be set by the message queue poster */
|
||||
size_t mail_size;
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_EVENT_EN > 0u
|
||||
k_opt_t opt_event_pend; /**< if we are pending an event, what's the option for the pending(TOS_OPT_EVENT_PEND_*)? */
|
||||
k_event_flag_t flag_expect; /**< if we are pending an event, what event flag are we pending for ? */
|
||||
k_event_flag_t *flag_match; /**< if we pend an event successfully, flag_match will be set by the event poster, and will be returned
|
||||
by tos_event_pend to the caller */
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a task.
|
||||
* create a task.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] task pointer to the handler of the task.
|
||||
* @param[in] name name of the task.
|
||||
* @param[in] entry running entry of the task.
|
||||
* @param[in] arg argument for the entry of the task.
|
||||
* @param[in] prio priority of the task.
|
||||
* @param[in] stk_base stack base address of the task.
|
||||
* @param[in] stk_size stack size of the task.
|
||||
* @param[in] timeslice time slice of the task.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TASK_STK_SIZE_INVALID stack size is invalid.
|
||||
* @retval #K_ERR_TASK_PRIO_INVALID priority is invalid.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_task_create(k_task_t *task,
|
||||
char *name,
|
||||
k_task_entry_t entry,
|
||||
void *arg,
|
||||
k_prio_t prio,
|
||||
k_stack_t *stk_base,
|
||||
size_t stk_size,
|
||||
k_timeslice_t timeslice);
|
||||
|
||||
/**
|
||||
* @brief Destroy a task.
|
||||
* delete a task.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] task pointer to the handler of the task to be deleted.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TASK_DESTROY_IDLE attempt to destroy idle task.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_task_destroy(k_task_t *task);
|
||||
|
||||
#if TOS_CFG_TASK_DYNAMIC_CREATE_EN > 0u
|
||||
|
||||
/**
|
||||
* @brief Create a task with a dynamic allocated task handler and stack.
|
||||
* create a task with a dynamic allocated task handler and stack.
|
||||
*
|
||||
* @param[out] task dynamic allocated task handler.
|
||||
* @param[in] name name of the task.
|
||||
* @param[in] entry running entry of the task.
|
||||
* @param[in] arg argument for the entry of the task.
|
||||
* @param[in] prio priority of the task.
|
||||
* @param[in] stk_size stack size of the task.
|
||||
* @param[in] timeslice time slice of the task.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TASK_STK_SIZE_INVALID stack size is invalid.
|
||||
* @retval #K_ERR_TASK_PRIO_INVALID priority is invalid.
|
||||
* @retval #K_ERR_TASK_OUT_OF_MEMORY out of memory(insufficient heap memory).
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_task_create_dyn(k_task_t **task,
|
||||
char *name,
|
||||
k_task_entry_t entry,
|
||||
void *arg,
|
||||
k_prio_t prio,
|
||||
size_t stk_size,
|
||||
k_timeslice_t timeslice);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Delay current task for ticks.
|
||||
* Delay for a specified amount of ticks.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] delay amount of ticks to delay.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_DELAY_ZERO delay is zero.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_task_delay(k_tick_t delay);
|
||||
|
||||
/**
|
||||
* @brief Resume task from delay.
|
||||
* Resume a delayed task from delay.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] task the pointer to the handler of the task.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TASK_NOT_DELAY task is not delayed.
|
||||
* @retval #K_ERR_TASK_SUSPENDED task is suspended.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_task_delay_abort(k_task_t *task);
|
||||
|
||||
/**
|
||||
* @brief Suspend a task.
|
||||
* Bring a task to sleep.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] task pointer to the handler of the task to be resume.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TASK_SUSPEND_IDLE attempt to suspend idle task.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_task_suspend(k_task_t *task);
|
||||
|
||||
/**
|
||||
* @brief Resume a task.
|
||||
* Bring a task to run.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] task pointer to the handler of the task to be resume.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TASK_RESUME_SELF attempt to resume self-task.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_task_resume(k_task_t *task);
|
||||
|
||||
/**
|
||||
* @brief Change task priority.
|
||||
* Change a priority of the task.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] task pointer to the handler of the task to be resume.
|
||||
* @param[in] prio_new new priority.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TASK_PRIO_INVALID new priority is invalid.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_task_prio_change(k_task_t *task, k_prio_t prio_new);
|
||||
|
||||
/**
|
||||
* @brief Quit schedule this time.
|
||||
* Quit the cpu this time.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__API__ void tos_task_yield(void);
|
||||
|
||||
/**
|
||||
* @brief Get current running task.
|
||||
* Get current running task.
|
||||
*
|
||||
* @attention if kernel is not running, you'll get K_NULL
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return current running task handler
|
||||
*/
|
||||
__API__ k_task_t *tos_task_curr_task_get(void);
|
||||
|
||||
|
||||
#if TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN > 0u
|
||||
|
||||
/**
|
||||
* @brief Get the maximum stack draught depth of a task.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] task pointer to the handler of the task.
|
||||
* @param[out] depth task stack draught depth.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_NONE get depth successfully.
|
||||
* @retval #K_ERR_TASK_STK_OVERFLOW task stack is overflow.
|
||||
*/
|
||||
__API__ k_err_t tos_task_stack_draught_depth(k_task_t *task, int *depth);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Walk through all the tasks in the statistic list.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] walker a function involved when meeting each tasks in the list.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__API__ void tos_task_walkthru(k_task_walker_t walker);
|
||||
|
||||
/**
|
||||
* @brief A debug API for display all tasks information.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__DEBUG__ void tos_task_info_display(void);
|
||||
|
||||
__KNL__ void task_free_all(void);
|
||||
|
||||
__KNL__ __STATIC_INLINE__ int task_state_is_ready(k_task_t *task)
|
||||
{
|
||||
return task->state == K_TASK_STATE_READY;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ int task_state_is_sleeping(k_task_t *task)
|
||||
{
|
||||
return task->state & K_TASK_STATE_SLEEP;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ int task_state_is_pending(k_task_t *task)
|
||||
{
|
||||
return task->state & K_TASK_STATE_PEND;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ int task_state_is_suspended(k_task_t *task)
|
||||
{
|
||||
return task->state & K_TASK_STATE_SUSPENDED;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void task_state_reset_pending(k_task_t *task)
|
||||
{
|
||||
task->state &= ~K_TASK_STATE_PEND;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void task_state_reset_sleeping(k_task_t *task)
|
||||
{
|
||||
task->state &= ~K_TASK_STATE_SLEEP;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void task_state_reset_suspended(k_task_t *task)
|
||||
{
|
||||
task->state &= ~K_TASK_STATE_SUSPENDED;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void task_state_set_suspended(k_task_t *task)
|
||||
{
|
||||
task->state |= K_TASK_STATE_SUSPENDED;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void task_state_set_pend(k_task_t *task)
|
||||
{
|
||||
task->state |= K_TASK_STATE_PEND;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void task_state_set_ready(k_task_t *task)
|
||||
{
|
||||
task->state = K_TASK_STATE_READY;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void task_state_set_deleted(k_task_t *task)
|
||||
{
|
||||
task->state = K_TASK_STATE_DELETED;
|
||||
}
|
||||
|
||||
__KNL__ __STATIC_INLINE__ void task_state_set_sleeping(k_task_t *task)
|
||||
{
|
||||
task->state |= K_TASK_STATE_SLEEP;
|
||||
}
|
||||
|
||||
__DEBUG__ __STATIC_INLINE__ void task_default_walker(k_task_t *task)
|
||||
{
|
||||
char *state_str = "ABNORMAL";
|
||||
|
||||
state_str = state_str;
|
||||
tos_kprintln("tsk name: %s", task->name);
|
||||
|
||||
if (tos_task_curr_task_get() == task) {
|
||||
state_str = "RUNNING";
|
||||
} else if (task->state == K_TASK_STATE_PENDTIMEOUT_SUSPENDED) {
|
||||
state_str = "PENDTIMEOUT_SUSPENDED";
|
||||
} else if (task->state == K_TASK_STATE_PEND_SUSPENDED) {
|
||||
state_str = "PEND_SUSPENDED";
|
||||
} else if (task->state == K_TASK_STATE_SLEEP_SUSPENDED) {
|
||||
state_str = "SLEEP_SUSPENDED";
|
||||
} else if (task->state == K_TASK_STATE_PENDTIMEOUT) {
|
||||
state_str = "PENDTIMEOUT";
|
||||
} else if (task->state == K_TASK_STATE_SUSPENDED) {
|
||||
state_str = "SUSPENDED";
|
||||
} else if (task->state == K_TASK_STATE_PEND) {
|
||||
state_str = "PEND";
|
||||
} else if (task->state == K_TASK_STATE_SLEEP) {
|
||||
state_str = "SLEEP";
|
||||
} else if (task->state == K_TASK_STATE_READY) {
|
||||
state_str = "READY";
|
||||
}
|
||||
tos_kprintln("tsk stat: %s", state_str);
|
||||
|
||||
tos_kprintln("stk size: %d", task->stk_size);
|
||||
tos_kprintln("stk base: 0x%p", task->stk_base);
|
||||
tos_kprintln("stk top : 0x%p", task->stk_base + task->stk_size);
|
||||
tos_kprintf("\n");
|
||||
}
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_TASK_H_ */
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_TICK_H_
|
||||
#define _TOS_TICK_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
/**
|
||||
* @brief Systick interrupt handler.
|
||||
* systick interrupt handler.
|
||||
*
|
||||
* @attention called from the systick interrupt entrance.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__API__ void tos_tick_handler(void);
|
||||
|
||||
__KNL__ void tick_update(k_tick_t tick);
|
||||
|
||||
__KNL__ void tick_list_add(k_task_t *task, k_tick_t timeout);
|
||||
|
||||
__KNL__ void tick_list_remove(k_task_t *task);
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
__KNL__ k_tick_t tick_next_expires_get(void);
|
||||
#endif
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_TICK_H_ */
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_TIME_H_
|
||||
#define _TOS_TIME_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
// if you wanna pend for something forever, use TOS_TIME_FOREVER
|
||||
#define TOS_TIME_FOREVER (k_tick_t)(-1)
|
||||
// if you don't wanna wait when you pend nothing, use TOS_TIME_NOWAIT
|
||||
#define TOS_TIME_NOWAIT (k_tick_t)0u
|
||||
|
||||
// those two are not for you, for kernel only.
|
||||
#define K_TIME_MILLISEC_PER_SEC 1000u
|
||||
#define K_TIME_MAX (k_tick_t)(TOS_TIME_FOREVER - 1)
|
||||
|
||||
/**
|
||||
* @brief Get system tick.
|
||||
* Get the number of ticks since boot.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return tick count since boot
|
||||
*/
|
||||
__API__ k_tick_t tos_systick_get(void);
|
||||
|
||||
/**
|
||||
* @brief Set system tick.
|
||||
* Set the number of ticks.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param tick systick count to set
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__API__ void tos_systick_set(k_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief Convert ticks to milliseconds.
|
||||
* Convert tick to millisecond.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] tick tick to convert.
|
||||
*
|
||||
* @return milliseconds equals to the ticks.
|
||||
*/
|
||||
__API__ k_time_t tos_tick2millisec(k_tick_t tick);
|
||||
|
||||
/**
|
||||
* @brief Convert milliseconds to ticks.
|
||||
* Convert milliseconds to ticks.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] millisec millisecond to convert.
|
||||
*
|
||||
* @return ticks equals to the millisecond.
|
||||
*/
|
||||
__API__ k_tick_t tos_millisec2tick(k_time_t millisec);
|
||||
|
||||
/**
|
||||
* @brief Sleep current task.
|
||||
* Sleep for a specified amount of milliseconds.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] millisec amount of milliseconds to delay.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_DELAY_ZERO millisec is zero.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_sleep_ms(k_time_t millisec);
|
||||
|
||||
/**
|
||||
* @brief Sleep current task.
|
||||
* Sleep for a specified amount of time.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] hour amount of hours.
|
||||
* @param[in] minute amount of minutes.
|
||||
* @param[in] second amount of seconds.
|
||||
* @param[in] millisec amount of milliseconds.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_DELAY_ZERO time is zero.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_sleep_hmsm(k_time_t hour, k_time_t minute, k_time_t second, k_time_t millisec);
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_TIME_H_ */
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_TIMER_H_
|
||||
#define _TOS_TIMER_H_
|
||||
|
||||
__CDECLS_BEGIN
|
||||
|
||||
#if TOS_CFG_TIMER_EN > 0u
|
||||
|
||||
// if we just want the timer to run only once, this option should be passed to tos_timer_create.
|
||||
#define TOS_OPT_TIMER_ONESHOT (k_opt_t)(0x0001u)
|
||||
|
||||
// if we want the timer run periodically, this option should be passed to tos_timer_create.
|
||||
#define TOS_OPT_TIMER_PERIODIC (k_opt_t)(0x0002u)
|
||||
|
||||
typedef enum timer_change_type_en {
|
||||
TIMER_CHANGE_TYPE_DELAY,
|
||||
TIMER_CHANGE_TYPE_PERIOD,
|
||||
} timer_change_type_t;
|
||||
|
||||
/**
|
||||
* state for timer
|
||||
*/
|
||||
typedef enum timer_state_en {
|
||||
TIMER_STATE_UNUSED, /**< the timer has been destroyed */
|
||||
TIMER_STATE_STOPPED, /**< the timer has been created but not been started, or just be stopped(tos_timer_stop) */
|
||||
TIMER_STATE_RUNNING, /**< the timer has been created and been started */
|
||||
TIMER_STATE_COMPLETED /**< the timer has finished its expires, it can only happen when the timer's opt is TOS_OPT_TIMER_ONESHOT */
|
||||
} timer_state_t;
|
||||
|
||||
// callback function type for a timer
|
||||
typedef void (*k_timer_callback_t)(void *arg);
|
||||
|
||||
/**
|
||||
* timer control block
|
||||
*/
|
||||
typedef struct k_timer_st {
|
||||
knl_obj_t knl_obj; /**< just for verification, test whether current object is really a timer */
|
||||
|
||||
k_timer_callback_t cb; /**< callback when time is up */
|
||||
void *cb_arg; /**< argument for callback */
|
||||
k_list_t list; /**< list for hooking us to the k_tick_list */
|
||||
k_tick_t expires; /**< how much time left until time expires */
|
||||
k_tick_t delay; /**< how much time from now to begin the first run of the timer */
|
||||
k_tick_t period; /**< if the time expires, how much time after should we begin the next round */
|
||||
k_opt_t opt; /**< option for the timer, see TOS_OPT_TIMER_* */
|
||||
timer_state_t state; /**< state for the timer, see TIMER_STATE_* */
|
||||
} k_timer_t;
|
||||
|
||||
typedef struct timer_control_st {
|
||||
k_tick_t next_expires;
|
||||
k_list_t list;
|
||||
} timer_ctl_t;
|
||||
|
||||
/**
|
||||
* @brief Create a timer.
|
||||
* Create a timer.
|
||||
*
|
||||
* @attention I dont't think a timer need a name. If you do, help yourself.
|
||||
*
|
||||
* @param[in] tmr pointer to the handler of the timer.
|
||||
* @param[in] delay time interval for a timer to run.
|
||||
* @param[in] period period for a timer to restart to run.
|
||||
* @param[in] callback callback function called when the timer expires.
|
||||
* @param[in] cb_arg argument for the callback.
|
||||
* @param[in] opt option for the function call.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TIMER_INVALID_PERIOD period is invalid.
|
||||
* @retval #K_ERR_TIMER_INVALID_DELAY delay is invalid.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_timer_create(k_timer_t *tmr, k_tick_t delay, k_tick_t period,
|
||||
k_timer_callback_t callback, void *cb_arg, k_opt_t opt);
|
||||
|
||||
/**
|
||||
* @brief Delete a timer.
|
||||
* Delete the timer.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] tmr pointer to the handler of the timer.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TIMER_INACTIVE the timer is not active yet.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_timer_destroy(k_timer_t *tmr);
|
||||
|
||||
/**
|
||||
* @brief Start a timer.
|
||||
* Start the timer to run.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] tmr pointer to the handler of the timer.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TIMER_INACTIVE the timer is not active yet.
|
||||
* @retval #K_ERR_TIMER_INVALID_STATE state of the timer is invalid.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_timer_start(k_timer_t *tmr);
|
||||
|
||||
/**
|
||||
* @brief Stop a timer.
|
||||
* Stop the timer from running.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] tmr pointer to the handler of the timer.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TIMER_INACTIVE the timer is not active yet.
|
||||
* @retval #K_ERR_TIMER_STOPPED the timer is already stoppped.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_timer_stop(k_timer_t *tmr);
|
||||
|
||||
/**
|
||||
* @brief Change a timer's delay.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] tmr pointer to the handler of the timer.
|
||||
* @param[in] delay new delay of the timer.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TIMER_INACTIVE the timer is not active yet.
|
||||
* @retval #K_ERR_TIMER_RUNNING the timer is running.
|
||||
* @retval #K_ERR_TIMER_INVALID_DELAY the delay is invalid.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_timer_delay_change(k_timer_t *tmr, k_tick_t delay);
|
||||
|
||||
/**
|
||||
* @brief Change a timer's period.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param[in] tmr pointer to the handler of the timer.
|
||||
* @param[in] period new period of the timer.
|
||||
*
|
||||
* @return errcode
|
||||
* @retval #K_ERR_TIMER_INACTIVE the timer is not active yet.
|
||||
* @retval #K_ERR_TIMER_RUNNING the timer is running.
|
||||
* @retval #K_ERR_TIMER_INVALID_PERIOD the period is invalid.
|
||||
* @retval #K_ERR_NONE return successfully.
|
||||
*/
|
||||
__API__ k_err_t tos_timer_period_change(k_timer_t *tmr, k_tick_t period);
|
||||
|
||||
|
||||
#if TOS_CFG_TIMER_AS_PROC > 0u
|
||||
|
||||
/**
|
||||
* @brief Timer update function.
|
||||
* When enable timer as a process function not a task, this will be the function entry.
|
||||
*
|
||||
* @attention None
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
__KNL__ void timer_update(void);
|
||||
|
||||
#endif
|
||||
|
||||
__KNL__ k_err_t timer_init(void);
|
||||
|
||||
__KNL__ k_tick_t timer_next_expires_get(void);
|
||||
|
||||
#endif
|
||||
|
||||
__CDECLS_END
|
||||
|
||||
#endif /* _TOS_TIMER_H_ */
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_VERSION_H_
|
||||
#define _TOS_VERSION_H_
|
||||
|
||||
// the format of the tencentos-tiny version is major.minor.patch
|
||||
// major is updated for major changes that will need user code changes
|
||||
// minor is updated for minor changes/bug fixes that may need user code changes
|
||||
// patch is updated for patch changes/bug fixes that should not need user code changes
|
||||
|
||||
#define TOS_VERSION_MAJOR 0x02
|
||||
#define TOS_VERSION_MINOR 0x04
|
||||
#define TOS_VERSION_PATCH 0x05
|
||||
#define TOS_VERSION "2.4.5"
|
||||
|
||||
#endif /* _TOS_VERSION_H_ */
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_BARRIER_EN > 0
|
||||
|
||||
__API__ k_err_t tos_barrier_create(k_barrier_t *barrier, k_barrier_cnt_t count)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(barrier);
|
||||
|
||||
if (count == 0u) {
|
||||
return K_ERR_BARRIER_COUNT_INVALID;
|
||||
}
|
||||
|
||||
barrier->count = count;
|
||||
pend_object_init(&barrier->pend_obj);
|
||||
TOS_OBJ_INIT(barrier, KNL_OBJ_TYPE_BARRIER);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_barrier_destroy(k_barrier_t *barrier)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(barrier);
|
||||
TOS_OBJ_VERIFY(barrier, KNL_OBJ_TYPE_BARRIER);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
pend_wakeup_all(&barrier->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
pend_object_deinit(&barrier->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(barrier);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_barrier_pend(k_barrier_t *barrier)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(barrier);
|
||||
TOS_OBJ_VERIFY(barrier, KNL_OBJ_TYPE_BARRIER);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (barrier->count == 0u) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_BARRIER_OVERFLOW;
|
||||
}
|
||||
|
||||
if (barrier->count == (k_barrier_cnt_t)1u) {
|
||||
barrier->count = (k_barrier_cnt_t)0u;
|
||||
pend_wakeup_all(&barrier->pend_obj, PEND_STATE_POST);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
--barrier->count;
|
||||
pend_task_block(k_curr_task, &barrier->pend_obj, TOS_TIME_FOREVER);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return pend_state2errno(k_curr_task->pend_state);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_barrier_reset(k_barrier_t *barrier, k_barrier_cnt_t count)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(barrier);
|
||||
TOS_OBJ_VERIFY(barrier, KNL_OBJ_TYPE_BARRIER);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
barrier->count = count;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
#endif /* TOS_CFG_BARRIER_EN */
|
||||
@@ -0,0 +1,296 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__STATIC_INLINE__ void bin_heap_item_copy_to(k_bin_heap_t *bin_heap, void *item_out, size_t *item_size)
|
||||
{
|
||||
memcpy(item_out, BIN_HEAP_FIRST_ITEM(bin_heap), bin_heap->item_size);
|
||||
if (item_size) {
|
||||
*item_size = bin_heap->item_size;
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void bin_heap_item_copy_from(k_bin_heap_t *bin_heap, void *item_in)
|
||||
{
|
||||
memcpy(BIN_HEAP_LAST_ITEM(bin_heap), item_in, bin_heap->item_size);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void bin_heap_item_increase(k_bin_heap_t *bin_heap)
|
||||
{
|
||||
++bin_heap->total;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void bin_heap_item_decrease(k_bin_heap_t *bin_heap)
|
||||
{
|
||||
--bin_heap->total;
|
||||
}
|
||||
|
||||
__STATIC__ void bin_heap_do_percolate_up(k_bin_heap_t *bin_heap, uint16_t hole, void *item_backup)
|
||||
{
|
||||
k_bin_heap_cmp cmp;
|
||||
size_t item_size;
|
||||
uint16_t parent, top;
|
||||
void *hole_item, *parent_item;
|
||||
|
||||
top = 0u;
|
||||
parent = BIN_HEAP_PARENT(hole);
|
||||
cmp = bin_heap->cmp;
|
||||
item_size = bin_heap->item_size;
|
||||
|
||||
hole_item = BIN_HEAP_THE_ITEM(bin_heap, hole);
|
||||
parent_item = BIN_HEAP_THE_ITEM(bin_heap, parent);
|
||||
|
||||
while (hole > top && cmp(item_backup, parent_item)) {
|
||||
memcpy(hole_item, parent_item, item_size);
|
||||
hole = parent;
|
||||
parent = BIN_HEAP_PARENT(hole);
|
||||
hole_item = BIN_HEAP_THE_ITEM(bin_heap, hole);
|
||||
parent_item = BIN_HEAP_THE_ITEM(bin_heap, parent);
|
||||
}
|
||||
hole_item = BIN_HEAP_THE_ITEM(bin_heap, hole);
|
||||
memcpy(hole_item, item_backup, item_size);
|
||||
}
|
||||
|
||||
__STATIC__ void bin_heap_percolate_up(k_bin_heap_t *bin_heap, void *item_backup)
|
||||
{
|
||||
bin_heap_do_percolate_up(bin_heap, bin_heap->total, item_backup);
|
||||
}
|
||||
|
||||
__STATIC__ void bin_heap_percolate_down(k_bin_heap_t *bin_heap)
|
||||
{
|
||||
k_bin_heap_cmp cmp;
|
||||
size_t item_size;
|
||||
uint16_t lchild, rchild, the_child, hole;
|
||||
void *hole_item, *rchild_item, *lchild_item, *the_child_item;
|
||||
|
||||
hole = 0u;
|
||||
rchild = BIN_HEAP_RCHILD(hole);
|
||||
lchild = BIN_HEAP_LSIBLING(rchild);
|
||||
the_child = rchild;
|
||||
cmp = bin_heap->cmp;
|
||||
item_size = bin_heap->item_size;
|
||||
|
||||
hole_item = BIN_HEAP_THE_ITEM(bin_heap, hole);
|
||||
rchild_item = BIN_HEAP_THE_ITEM(bin_heap, rchild);
|
||||
lchild_item = BIN_HEAP_THE_ITEM(bin_heap, lchild);
|
||||
|
||||
while (the_child < bin_heap->total) {
|
||||
if (cmp(lchild_item, rchild_item)) {
|
||||
the_child = lchild;
|
||||
}
|
||||
the_child_item = BIN_HEAP_THE_ITEM(bin_heap, the_child);
|
||||
memcpy(hole_item, the_child_item, item_size);
|
||||
|
||||
hole = the_child;
|
||||
the_child = BIN_HEAP_RCHILD(the_child);
|
||||
rchild = the_child;
|
||||
lchild = BIN_HEAP_LSIBLING(rchild);
|
||||
|
||||
hole_item = BIN_HEAP_THE_ITEM(bin_heap, hole);
|
||||
rchild_item = BIN_HEAP_THE_ITEM(bin_heap, rchild);
|
||||
lchild_item = BIN_HEAP_THE_ITEM(bin_heap, lchild);
|
||||
}
|
||||
|
||||
if (the_child == bin_heap->total) {
|
||||
memcpy(hole_item, lchild_item, item_size);
|
||||
hole = lchild;
|
||||
hole_item = BIN_HEAP_THE_ITEM(bin_heap, hole);
|
||||
}
|
||||
bin_heap_do_percolate_up(bin_heap, hole, BIN_HEAP_LAST_ITEM(bin_heap));
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_bin_heap_create(k_bin_heap_t *bin_heap, void *pool, size_t item_cnt, size_t item_size, k_bin_heap_cmp cmp)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(bin_heap);
|
||||
TOS_PTR_SANITY_CHECK(pool);
|
||||
TOS_PTR_SANITY_CHECK(cmp);
|
||||
|
||||
bin_heap->total = 0;
|
||||
bin_heap->cmp = cmp;
|
||||
bin_heap->item_size = item_size;
|
||||
bin_heap->item_cnt = item_cnt;
|
||||
bin_heap->pool = (uint8_t *)pool;
|
||||
|
||||
TOS_OBJ_INIT(bin_heap, KNL_OBJ_TYPE_BINARY_HEAP);
|
||||
knl_object_alloc_set_static(&bin_heap->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_bin_heap_destroy(k_bin_heap_t *bin_heap)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(bin_heap);
|
||||
TOS_OBJ_VERIFY(bin_heap, KNL_OBJ_TYPE_BINARY_HEAP);
|
||||
|
||||
if (!knl_object_alloc_is_static(&bin_heap->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
bin_heap->total = 0;
|
||||
bin_heap->cmp = K_NULL;
|
||||
bin_heap->item_size = 0;
|
||||
bin_heap->item_cnt = 0;
|
||||
bin_heap->pool = K_NULL;
|
||||
|
||||
TOS_OBJ_DEINIT(bin_heap);
|
||||
knl_object_alloc_reset(&bin_heap->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_bin_heap_create_dyn(k_bin_heap_t *bin_heap, size_t item_cnt, size_t item_size, k_bin_heap_cmp cmp)
|
||||
{
|
||||
void *pool;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(bin_heap);
|
||||
TOS_PTR_SANITY_CHECK(cmp);
|
||||
|
||||
pool = tos_mmheap_alloc(item_cnt * item_size);
|
||||
if (!pool) {
|
||||
return K_ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
bin_heap->total = 0;
|
||||
bin_heap->cmp = cmp;
|
||||
bin_heap->item_size = item_size;
|
||||
bin_heap->item_cnt = item_cnt;
|
||||
bin_heap->pool = (uint8_t *)pool;
|
||||
|
||||
TOS_OBJ_INIT(bin_heap, KNL_OBJ_TYPE_BINARY_HEAP);
|
||||
knl_object_alloc_set_dynamic(&bin_heap->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_bin_heap_destroy_dyn(k_bin_heap_t *bin_heap)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(bin_heap);
|
||||
TOS_OBJ_VERIFY(bin_heap, KNL_OBJ_TYPE_BINARY_HEAP);
|
||||
|
||||
if (!knl_object_alloc_is_dynamic(&bin_heap->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
tos_mmheap_free(bin_heap->pool);
|
||||
|
||||
bin_heap->total = 0;
|
||||
bin_heap->cmp = K_NULL;
|
||||
bin_heap->item_size = 0;
|
||||
bin_heap->item_cnt = 0;
|
||||
bin_heap->pool = K_NULL;
|
||||
|
||||
TOS_OBJ_DEINIT(bin_heap);
|
||||
knl_object_alloc_reset(&bin_heap->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_bin_heap_push(k_bin_heap_t *bin_heap, void *item, size_t item_size)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(bin_heap);
|
||||
TOS_PTR_SANITY_CHECK(item);
|
||||
TOS_OBJ_VERIFY(bin_heap, KNL_OBJ_TYPE_BINARY_HEAP);
|
||||
|
||||
if (item_size != bin_heap->item_size) {
|
||||
return K_ERR_BIN_HEAP_ITEM_SIZE_NOT_MATCH;
|
||||
}
|
||||
|
||||
if (tos_bin_heap_is_full(bin_heap)) {
|
||||
return K_ERR_BIN_HEAP_FULL;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
bin_heap_item_copy_from(bin_heap, item);
|
||||
bin_heap_percolate_up(bin_heap, item);
|
||||
bin_heap_item_increase(bin_heap);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_bin_heap_pop(k_bin_heap_t *bin_heap, void *item, size_t *item_size)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(bin_heap);
|
||||
TOS_PTR_SANITY_CHECK(item);
|
||||
TOS_OBJ_VERIFY(bin_heap, KNL_OBJ_TYPE_BINARY_HEAP);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (tos_bin_heap_is_empty(bin_heap)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_BIN_HEAP_EMPTY;
|
||||
}
|
||||
|
||||
bin_heap_item_copy_to(bin_heap, item, item_size);
|
||||
bin_heap_item_decrease(bin_heap);
|
||||
bin_heap_percolate_down(bin_heap);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_bin_heap_flush(k_bin_heap_t *bin_heap)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(bin_heap);
|
||||
TOS_OBJ_VERIFY(bin_heap, KNL_OBJ_TYPE_BINARY_HEAP);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
bin_heap->total = 0;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ int tos_bin_heap_is_empty(k_bin_heap_t *bin_heap)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
int is_empty = K_FALSE;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(bin_heap, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(bin_heap, KNL_OBJ_TYPE_BINARY_HEAP, K_FALSE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
is_empty = (bin_heap->total == 0);
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return is_empty;
|
||||
}
|
||||
|
||||
__API__ int tos_bin_heap_is_full(k_bin_heap_t *bin_heap)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
int is_full = K_FALSE;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(bin_heap, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(bin_heap, KNL_OBJ_TYPE_BINARY_HEAP, K_FALSE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
is_full = (bin_heap->total == bin_heap->item_cnt ? K_TRUE : K_FALSE);
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return is_full;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__API__ k_err_t tos_bitmap_create_empty(k_bitmap_t *bitmap, k_bmtbl_t *bitmap_tbl, uint32_t bit_max)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(bitmap);
|
||||
|
||||
bitmap->bitmap_tbl = bitmap_tbl;
|
||||
bitmap->bit_max = bit_max;
|
||||
bitmap->bit_ndx_max = K_BITMAP_TBL_SIZE(bit_max);
|
||||
|
||||
for (i = 0; i < bitmap->bit_ndx_max; ++i) {
|
||||
/* all bits are 0 */
|
||||
bitmap_tbl[i] = 0;
|
||||
}
|
||||
TOS_OBJ_INIT(bitmap, KNL_OBJ_TYPE_BITMAP);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_bitmap_create_full(k_bitmap_t *bitmap, k_bmtbl_t *bitmap_tbl, uint32_t bit_max)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(bitmap);
|
||||
|
||||
bitmap->bitmap_tbl = bitmap_tbl;
|
||||
bitmap->bit_max = bit_max;
|
||||
bitmap->bit_ndx_max = K_BITMAP_TBL_SIZE(bit_max);
|
||||
|
||||
for (i = 0; i < bitmap->bit_ndx_max; ++i) {
|
||||
/* all bits are 1 */
|
||||
bitmap_tbl[i] = ~0;
|
||||
}
|
||||
TOS_OBJ_INIT(bitmap, KNL_OBJ_TYPE_BITMAP);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_bitmap_destroy(k_bitmap_t *bitmap)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(bitmap);
|
||||
TOS_OBJ_VERIFY(bitmap, KNL_OBJ_TYPE_BITMAP);
|
||||
|
||||
TOS_OBJ_DEINIT(bitmap);
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_bitmap_set(k_bitmap_t *bitmap, uint32_t bit)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(bitmap);
|
||||
TOS_OBJ_VERIFY(bitmap, KNL_OBJ_TYPE_BITMAP);
|
||||
|
||||
if (bit > bitmap->bit_max) {
|
||||
return K_ERR_BITMAP_EXCEED;
|
||||
}
|
||||
|
||||
bitmap->bitmap_tbl[K_BITMAP_NDX(bit)] |= K_BITMAP_BIT(bit);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_bitmap_reset(k_bitmap_t *bitmap, uint32_t bit)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(bitmap);
|
||||
TOS_OBJ_VERIFY(bitmap, KNL_OBJ_TYPE_BITMAP);
|
||||
|
||||
if (bit > bitmap->bit_max) {
|
||||
return K_ERR_BITMAP_EXCEED;
|
||||
}
|
||||
|
||||
bitmap->bitmap_tbl[K_BITMAP_NDX(bit)] &= ~K_BITMAP_BIT(bit);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ int tos_bitmap_is_set(k_bitmap_t *bitmap, uint32_t bit)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK_RC(bitmap, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(bitmap, KNL_OBJ_TYPE_BITMAP, K_FALSE);
|
||||
|
||||
if (bit > bitmap->bit_max) {
|
||||
return K_FALSE;
|
||||
}
|
||||
|
||||
return (bitmap->bitmap_tbl[K_BITMAP_NDX(bit)] & K_BITMAP_BIT(bit)) ? K_TRUE : K_FALSE;
|
||||
}
|
||||
|
||||
__API__ int tos_bitmap_is_reset(k_bitmap_t *bitmap, uint32_t bit)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK_RC(bitmap, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(bitmap, KNL_OBJ_TYPE_BITMAP, K_FALSE);
|
||||
|
||||
if (bit > bitmap->bit_max) {
|
||||
return K_FALSE;
|
||||
}
|
||||
|
||||
return tos_bitmap_is_set(bitmap, bit) ? K_FALSE : K_TRUE;
|
||||
}
|
||||
|
||||
__API__ int tos_bitmap_lsb(k_bitmap_t *bitmap)
|
||||
{
|
||||
int lsb = 0, i = 0;
|
||||
k_bmtbl_t *bitmap_tbl;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(bitmap, -1);
|
||||
TOS_OBJ_VERIFY_RC(bitmap, KNL_OBJ_TYPE_BITMAP, -1);
|
||||
|
||||
bitmap_tbl = bitmap->bitmap_tbl;
|
||||
|
||||
for (i = 0; i < bitmap->bit_ndx_max - 1; ++i) {
|
||||
if (*bitmap_tbl == 0) {
|
||||
lsb += K_BITMAP_SLOT_SIZE;
|
||||
++bitmap_tbl;
|
||||
}
|
||||
}
|
||||
|
||||
lsb += tos_cpu_clz(*bitmap_tbl);
|
||||
if (lsb > bitmap->bit_max) {
|
||||
return bitmap->bit_max + 1;
|
||||
}
|
||||
|
||||
return lsb;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__API__ k_err_t tos_chr_fifo_create(k_chr_fifo_t *chr_fifo, void *buffer, size_t size)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(chr_fifo);
|
||||
TOS_PTR_SANITY_CHECK(buffer);
|
||||
|
||||
err = tos_ring_q_create(&chr_fifo->ring_q, buffer, size, sizeof(uint8_t));
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
TOS_OBJ_INIT(chr_fifo, KNL_OBJ_TYPE_CHAR_FIFO);
|
||||
knl_object_alloc_set_static(&chr_fifo->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_chr_fifo_destroy(k_chr_fifo_t *chr_fifo)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(chr_fifo);
|
||||
TOS_OBJ_VERIFY(chr_fifo, KNL_OBJ_TYPE_CHAR_FIFO);
|
||||
|
||||
if (!knl_object_alloc_is_static(&chr_fifo->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
err = tos_ring_q_destroy(&chr_fifo->ring_q);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
TOS_OBJ_DEINIT(chr_fifo);
|
||||
knl_object_alloc_reset(&chr_fifo->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_chr_fifo_create_dyn(k_chr_fifo_t *chr_fifo, size_t fifo_size)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(chr_fifo);
|
||||
|
||||
err = tos_ring_q_create_dyn(&chr_fifo->ring_q, fifo_size, sizeof(uint8_t));
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
TOS_OBJ_INIT(chr_fifo, KNL_OBJ_TYPE_CHAR_FIFO);
|
||||
knl_object_alloc_set_dynamic(&chr_fifo->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_chr_fifo_destroy_dyn(k_chr_fifo_t *chr_fifo)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(chr_fifo);
|
||||
TOS_OBJ_VERIFY(chr_fifo, KNL_OBJ_TYPE_CHAR_FIFO);
|
||||
|
||||
if (!knl_object_alloc_is_dynamic(&chr_fifo->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
err = tos_ring_q_destroy_dyn(&chr_fifo->ring_q);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
TOS_OBJ_DEINIT(chr_fifo);
|
||||
knl_object_alloc_reset(&chr_fifo->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_chr_fifo_push(k_chr_fifo_t *chr_fifo, uint8_t data)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(chr_fifo);
|
||||
TOS_OBJ_VERIFY(chr_fifo, KNL_OBJ_TYPE_CHAR_FIFO);
|
||||
|
||||
return tos_ring_q_enqueue(&chr_fifo->ring_q, &data, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
__API__ int tos_chr_fifo_push_stream(k_chr_fifo_t *chr_fifo, uint8_t *stream, size_t size)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
int i = 0;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(chr_fifo, 0);
|
||||
TOS_OBJ_VERIFY_RC(chr_fifo, KNL_OBJ_TYPE_CHAR_FIFO, 0);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
while (i < size) {
|
||||
err = tos_ring_q_enqueue(&chr_fifo->ring_q, &stream[i], sizeof(uint8_t));
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return i;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_chr_fifo_pop(k_chr_fifo_t *chr_fifo, uint8_t *out)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(chr_fifo);
|
||||
TOS_OBJ_VERIFY(chr_fifo, KNL_OBJ_TYPE_CHAR_FIFO);
|
||||
|
||||
return tos_ring_q_dequeue(&chr_fifo->ring_q, (void *)out, K_NULL);
|
||||
}
|
||||
|
||||
__API__ int tos_chr_fifo_pop_stream(k_chr_fifo_t *chr_fifo, uint8_t *buffer, size_t size)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
int i = 0;
|
||||
uint8_t data;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(chr_fifo, 0);
|
||||
TOS_OBJ_VERIFY_RC(chr_fifo, KNL_OBJ_TYPE_CHAR_FIFO, 0);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
while (i < size) {
|
||||
if (tos_ring_q_dequeue(&chr_fifo->ring_q, &data, K_NULL) != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return i;
|
||||
}
|
||||
buffer[i++] = data;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return i;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_chr_fifo_flush(k_chr_fifo_t *chr_fifo)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(chr_fifo);
|
||||
TOS_OBJ_VERIFY(chr_fifo, KNL_OBJ_TYPE_CHAR_FIFO);
|
||||
|
||||
return tos_ring_q_flush(&chr_fifo->ring_q);
|
||||
}
|
||||
|
||||
__API__ int tos_chr_fifo_is_empty(k_chr_fifo_t *chr_fifo)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK_RC(chr_fifo, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(chr_fifo, KNL_OBJ_TYPE_CHAR_FIFO, K_FALSE);
|
||||
|
||||
return tos_ring_q_is_empty(&chr_fifo->ring_q);
|
||||
}
|
||||
|
||||
__API__ int tos_chr_fifo_is_full(k_chr_fifo_t *chr_fifo)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK_RC(chr_fifo, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(chr_fifo, KNL_OBJ_TYPE_CHAR_FIFO, K_FALSE);
|
||||
|
||||
return tos_ring_q_is_full(&chr_fifo->ring_q);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_COMPLETION_EN > 0
|
||||
|
||||
__API__ k_err_t tos_completion_create(k_completion_t *completion)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(completion);
|
||||
|
||||
completion->done = (completion_done_t)0u;
|
||||
pend_object_init(&completion->pend_obj);
|
||||
TOS_OBJ_INIT(completion, KNL_OBJ_TYPE_COMPLETION);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_completion_destroy(k_completion_t *completion)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(completion);
|
||||
TOS_OBJ_VERIFY(completion, KNL_OBJ_TYPE_COMPLETION);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
pend_wakeup_all(&completion->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
pend_object_deinit(&completion->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(completion);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_completion_pend_timed(k_completion_t *completion, k_tick_t timeout)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(completion);
|
||||
TOS_OBJ_VERIFY(completion, KNL_OBJ_TYPE_COMPLETION);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (completion->done > (completion_done_t)0u) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (timeout == TOS_TIME_NOWAIT) { // no wait, return immediately
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_NOWAIT;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
pend_task_block(k_curr_task, &completion->pend_obj, timeout);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return pend_state2errno(k_curr_task->pend_state);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_completion_pend(k_completion_t *completion)
|
||||
{
|
||||
return tos_completion_pend_timed(completion, TOS_TIME_FOREVER);
|
||||
}
|
||||
|
||||
__STATIC__ k_err_t completion_do_post(k_completion_t *completion, opt_post_t opt)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(completion);
|
||||
TOS_OBJ_VERIFY(completion, KNL_OBJ_TYPE_COMPLETION);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (completion->done == (completion_done_t)-1) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_COMPLETION_OVERFLOW;
|
||||
}
|
||||
|
||||
++completion->done;
|
||||
|
||||
if (pend_is_nopending(&completion->pend_obj)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
pend_wakeup(&completion->pend_obj, PEND_STATE_POST, opt);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_completion_post(k_completion_t *completion)
|
||||
{
|
||||
return completion_do_post(completion, OPT_POST_ONE);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_completion_post_all(k_completion_t *completion)
|
||||
{
|
||||
return completion_do_post(completion, OPT_POST_ALL);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_completion_reset(k_completion_t *completion)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(completion);
|
||||
TOS_OBJ_VERIFY(completion, KNL_OBJ_TYPE_COMPLETION);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
completion->done = (completion_done_t)0u;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ int tos_completion_is_done(k_completion_t *completion)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
int is_done = K_FALSE;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(completion, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(completion, KNL_OBJ_TYPE_COMPLETION, K_FALSE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
is_done = (completion->done > (completion_done_t)0u ? K_TRUE : K_FALSE);
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return is_done;
|
||||
}
|
||||
|
||||
#endif /* TOS_CFG_COMPLETION_EN */
|
||||
@@ -0,0 +1,135 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_COUNTDOWNLATCH_EN > 0
|
||||
|
||||
__API__ k_err_t tos_countdownlatch_create(k_countdownlatch_t *countdownlatch, k_countdownlatch_cnt_t count)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(countdownlatch);
|
||||
|
||||
countdownlatch->count = count;
|
||||
pend_object_init(&countdownlatch->pend_obj);
|
||||
TOS_OBJ_INIT(countdownlatch, KNL_OBJ_TYPE_COUNTDOWNLATCH);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_countdownlatch_destroy(k_countdownlatch_t *countdownlatch)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(countdownlatch);
|
||||
TOS_OBJ_VERIFY(countdownlatch, KNL_OBJ_TYPE_COUNTDOWNLATCH);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
pend_wakeup_all(&countdownlatch->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
pend_object_deinit(&countdownlatch->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(countdownlatch);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_countdownlatch_pend_timed(k_countdownlatch_t *countdownlatch, k_tick_t timeout)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(countdownlatch);
|
||||
TOS_OBJ_VERIFY(countdownlatch, KNL_OBJ_TYPE_COUNTDOWNLATCH);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (countdownlatch->count == (k_countdownlatch_cnt_t)0u) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (timeout == TOS_TIME_NOWAIT) { // no wait, return immediately
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_NOWAIT;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
pend_task_block(k_curr_task, &countdownlatch->pend_obj, timeout);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return pend_state2errno(k_curr_task->pend_state);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_countdownlatch_pend(k_countdownlatch_t *countdownlatch)
|
||||
{
|
||||
return tos_countdownlatch_pend_timed(countdownlatch, TOS_TIME_FOREVER);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_countdownlatch_post(k_countdownlatch_t *countdownlatch)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(countdownlatch);
|
||||
TOS_OBJ_VERIFY(countdownlatch, KNL_OBJ_TYPE_COUNTDOWNLATCH);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (countdownlatch->count == (k_countdownlatch_cnt_t)0) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_COUNTDOWNLATCH_OVERFLOW;
|
||||
}
|
||||
|
||||
--countdownlatch->count;
|
||||
|
||||
if (countdownlatch->count > (k_countdownlatch_cnt_t)0) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
pend_wakeup_one(&countdownlatch->pend_obj, PEND_STATE_POST);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_countdownlatch_reset(k_countdownlatch_t *countdownlatch, k_countdownlatch_cnt_t count)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(countdownlatch);
|
||||
TOS_OBJ_VERIFY(countdownlatch, KNL_OBJ_TYPE_COUNTDOWNLATCH);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
countdownlatch->count = count;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
#endif /* TOS_CFG_COUNTDOWNLATCH_EN */
|
||||
@@ -0,0 +1,170 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_EVENT_EN > 0
|
||||
|
||||
__API__ k_err_t tos_event_create(k_event_t *event, k_event_flag_t init_flag)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(event);
|
||||
|
||||
event->flag = init_flag;
|
||||
pend_object_init(&event->pend_obj);
|
||||
TOS_OBJ_INIT(event, KNL_OBJ_TYPE_EVENT);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_event_destroy(k_event_t *event)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(event);
|
||||
TOS_OBJ_VERIFY(event, KNL_OBJ_TYPE_EVENT);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
pend_wakeup_all(&event->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
event->flag = (k_event_flag_t)0u;
|
||||
|
||||
pend_object_deinit(&event->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(event);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__STATIC__ int event_is_match(k_event_flag_t event, k_event_flag_t flag_expect, k_event_flag_t *flag_match, k_opt_t opt_pend)
|
||||
{
|
||||
if (opt_pend & TOS_OPT_EVENT_PEND_ALL) {
|
||||
if ((event & flag_expect) == flag_expect) {
|
||||
*flag_match = flag_expect;
|
||||
return K_TRUE;
|
||||
}
|
||||
} else if (opt_pend & TOS_OPT_EVENT_PEND_ANY) {
|
||||
if (event & flag_expect) {
|
||||
*flag_match = event & flag_expect;
|
||||
return K_TRUE;
|
||||
}
|
||||
}
|
||||
return K_FALSE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_event_pend(k_event_t *event, k_event_flag_t flag_expect, k_event_flag_t *flag_match, k_tick_t timeout, k_opt_t opt_pend)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(event);
|
||||
TOS_PTR_SANITY_CHECK(flag_match);
|
||||
TOS_OBJ_VERIFY(event, KNL_OBJ_TYPE_EVENT);
|
||||
|
||||
if (!(opt_pend & TOS_OPT_EVENT_PEND_ALL) && !(opt_pend & TOS_OPT_EVENT_PEND_ANY)) {
|
||||
return K_ERR_EVENT_PEND_OPT_INVALID;
|
||||
}
|
||||
|
||||
if ((opt_pend & TOS_OPT_EVENT_PEND_ALL) && (opt_pend & TOS_OPT_EVENT_PEND_ANY)) {
|
||||
return K_ERR_EVENT_PEND_OPT_INVALID;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (event_is_match(event->flag, flag_expect, flag_match, opt_pend)) {
|
||||
if (opt_pend & TOS_OPT_EVENT_PEND_CLR) { // destroy the bridge after get across the river
|
||||
event->flag = (k_event_flag_t)0u;
|
||||
}
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (timeout == TOS_TIME_NOWAIT) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_NOWAIT;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
k_curr_task->flag_expect = flag_expect;
|
||||
k_curr_task->flag_match = flag_match;
|
||||
k_curr_task->opt_event_pend = opt_pend;
|
||||
|
||||
pend_task_block(k_curr_task, &event->pend_obj, timeout);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
k_curr_task->flag_expect = (k_event_flag_t)0u;
|
||||
k_curr_task->flag_match = (k_event_flag_t *)K_NULL;
|
||||
k_curr_task->opt_event_pend = (k_opt_t)0u;
|
||||
|
||||
return pend_state2errno(k_curr_task->pend_state);
|
||||
}
|
||||
|
||||
__STATIC__ k_err_t event_do_post(k_event_t *event, k_event_flag_t flag, opt_event_post_t opt_post)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_task_t *task, *tmp;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(event);
|
||||
TOS_OBJ_VERIFY(event, KNL_OBJ_TYPE_EVENT);
|
||||
|
||||
if (opt_post == OPT_EVENT_POST_KEP) {
|
||||
event->flag |= flag;
|
||||
} else {
|
||||
event->flag = flag;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
TOS_LIST_FOR_EACH_ENTRY_SAFE(task, tmp, k_task_t, pend_list, &event->pend_obj.list) {
|
||||
if (event_is_match(event->flag, task->flag_expect, task->flag_match, task->opt_event_pend)) {
|
||||
pend_task_wakeup(task, PEND_STATE_POST);
|
||||
|
||||
// if anyone pending the event has set the TOS_OPT_EVENT_PEND_CLR, then no wakeup for the others pendig for the event.
|
||||
if (task->opt_event_pend & TOS_OPT_EVENT_PEND_CLR) {
|
||||
event->flag = (k_event_flag_t)0u;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_event_post(k_event_t *event, k_event_flag_t flag)
|
||||
{
|
||||
return event_do_post(event, flag, OPT_EVENT_POST_CLR);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_event_post_keep(k_event_t *event, k_event_flag_t flag)
|
||||
{
|
||||
return event_do_post(event, flag, OPT_EVENT_POST_KEP);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include <tos_k.h>
|
||||
|
||||
k_nesting_t k_irq_nest_cnt = (k_nesting_t)0;
|
||||
k_nesting_t k_sched_lock_nest_cnt = (k_nesting_t)0;
|
||||
knl_state_t k_knl_state = KNL_STATE_STOPPED;
|
||||
|
||||
readyqueue_t k_rdyq;
|
||||
|
||||
k_tick_t k_tick_count = (k_tick_t)0u;
|
||||
k_task_t *k_curr_task = K_NULL;
|
||||
k_task_t *k_next_task = K_NULL;
|
||||
|
||||
k_task_t k_idle_task;
|
||||
k_stack_t k_idle_task_stk[TOS_CFG_IDLE_TASK_STK_SIZE];
|
||||
k_stack_t *const k_idle_task_stk_addr = &k_idle_task_stk[0];
|
||||
size_t const k_idle_task_stk_size = TOS_CFG_IDLE_TASK_STK_SIZE;
|
||||
|
||||
k_tick_t k_cpu_tick_per_second = TOS_CFG_CPU_TICK_PER_SECOND;
|
||||
|
||||
k_cycle_t k_cpu_cycle_per_tick = (k_cycle_t)0u;
|
||||
|
||||
#if TOS_CFG_TASK_DYNAMIC_CREATE_EN > 0u
|
||||
TOS_LIST_DEFINE(k_dead_task_list);
|
||||
#endif
|
||||
|
||||
TOS_LIST_DEFINE(k_stat_list);
|
||||
|
||||
TOS_LIST_DEFINE(k_tick_list);
|
||||
|
||||
#if TOS_CFG_FAULT_BACKTRACE_EN > 0u
|
||||
k_fault_log_writer_t k_fault_log_writer = fault_default_log_writer;
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_MMHEAP_EN > 0u
|
||||
#if TOS_CFG_MMHEAP_DEFAULT_POOL_EN > 0u
|
||||
uint8_t k_mmheap_default_pool[TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE] __ALIGNED__(4);
|
||||
#endif
|
||||
k_mmheap_ctl_t k_mmheap_ctl;
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_ROUND_ROBIN_EN > 0u
|
||||
k_timeslice_t k_robin_default_timeslice = TOS_CFG_CPU_TICK_PER_SECOND / 10;
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_TIMER_EN > 0u
|
||||
timer_ctl_t k_timer_ctl = { TOS_TIME_FOREVER, TOS_LIST_NODE(k_timer_ctl.list) };
|
||||
|
||||
#if TOS_CFG_TIMER_AS_PROC == 0u
|
||||
k_task_t k_timer_task;
|
||||
k_stack_t k_timer_task_stk[TOS_CFG_TIMER_TASK_STK_SIZE];
|
||||
k_prio_t const k_timer_task_prio = TOS_CFG_TIMER_TASK_PRIO;
|
||||
k_stack_t *const k_timer_task_stk_addr = &k_timer_task_stk[0];
|
||||
size_t const k_timer_task_stk_size = TOS_CFG_TIMER_TASK_STK_SIZE;
|
||||
#endif /* TOS_CFG_TIMER_AS_PROC == 0u */
|
||||
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_PWR_MGR_EN > 0u
|
||||
pm_device_ctl_t k_pm_device_ctl = { 0u };
|
||||
|
||||
/* default idle power manager mode is SLEEP */
|
||||
idle_pwrmgr_mode_t k_idle_pwr_mgr_mode = IDLE_POWER_MANAGER_MODE_SLEEP;
|
||||
|
||||
k_cpu_lpwr_mode_t k_cpu_lpwr_mode = TOS_LOW_POWER_MODE_NONE;
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
k_tickless_wkup_alarm_t *k_tickless_wkup_alarm[__LOW_POWER_MODE_DUMMY] = { K_NULL };
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_MAIL_QUEUE_EN > 0u
|
||||
|
||||
__API__ k_err_t tos_mail_q_create(k_mail_q_t *mail_q, void *pool, size_t mail_cnt, size_t mail_size)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(mail_q);
|
||||
|
||||
err = tos_ring_q_create(&mail_q->ring_q, pool, mail_cnt, mail_size);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_object_init(&mail_q->pend_obj);
|
||||
|
||||
TOS_OBJ_INIT(mail_q, KNL_OBJ_TYPE_MAIL_QUEUE);
|
||||
knl_object_alloc_set_static(&mail_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mail_q_destroy(k_mail_q_t *mail_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(mail_q);
|
||||
TOS_OBJ_VERIFY(mail_q, KNL_OBJ_TYPE_MAIL_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_static(&mail_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
err = tos_ring_q_destroy(&mail_q->ring_q);
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_wakeup_all(&mail_q->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
pend_object_deinit(&mail_q->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(mail_q);
|
||||
knl_object_alloc_reset(&mail_q->knl_obj);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mail_q_create_dyn(k_mail_q_t *mail_q, size_t mail_cnt, size_t mail_size)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(mail_q);
|
||||
|
||||
err = tos_ring_q_create_dyn(&mail_q->ring_q, mail_cnt, mail_size);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_object_init(&mail_q->pend_obj);
|
||||
|
||||
TOS_OBJ_INIT(mail_q, KNL_OBJ_TYPE_MAIL_QUEUE);
|
||||
knl_object_alloc_set_dynamic(&mail_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mail_q_destroy_dyn(k_mail_q_t *mail_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(mail_q);
|
||||
TOS_OBJ_VERIFY(mail_q, KNL_OBJ_TYPE_MAIL_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_dynamic(&mail_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
err = tos_ring_q_destroy_dyn(&mail_q->ring_q);
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_wakeup_all(&mail_q->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
pend_object_deinit(&mail_q->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(mail_q);
|
||||
knl_object_alloc_reset(&mail_q->knl_obj);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mail_q_flush(k_mail_q_t *mail_q)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(mail_q);
|
||||
TOS_OBJ_VERIFY(mail_q, KNL_OBJ_TYPE_MAIL_QUEUE);
|
||||
|
||||
return tos_ring_q_flush(&mail_q->ring_q);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mail_q_pend(k_mail_q_t *mail_q, void *mail_buf, size_t *mail_size, k_tick_t timeout)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(mail_q);
|
||||
TOS_PTR_SANITY_CHECK(mail_buf);
|
||||
TOS_OBJ_VERIFY(mail_q, KNL_OBJ_TYPE_MAIL_QUEUE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (tos_ring_q_dequeue(&mail_q->ring_q, mail_buf, mail_size) == K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (timeout == TOS_TIME_NOWAIT) {
|
||||
*mail_size = 0;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_NOWAIT;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
k_curr_task->mail = mail_buf;
|
||||
pend_task_block(k_curr_task, &mail_q->pend_obj, timeout);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
err = pend_state2errno(k_curr_task->pend_state);
|
||||
if (err == K_ERR_NONE) {
|
||||
*mail_size = k_curr_task->mail_size;
|
||||
k_curr_task->mail = K_NULL;
|
||||
k_curr_task->mail_size = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
__STATIC__ void mail_task_recv(k_task_t *task, void *mail_buf, size_t mail_size)
|
||||
{
|
||||
memcpy(task->mail, mail_buf, mail_size);
|
||||
task->mail_size = mail_size;
|
||||
pend_task_wakeup(task, PEND_STATE_POST);
|
||||
}
|
||||
|
||||
__STATIC__ k_err_t mail_q_do_post(k_mail_q_t *mail_q, void *mail_buf, size_t mail_size, opt_post_t opt)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
k_task_t *task, *tmp;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(mail_q);
|
||||
TOS_PTR_SANITY_CHECK(mail_buf);
|
||||
TOS_OBJ_VERIFY(mail_q, KNL_OBJ_TYPE_MAIL_QUEUE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (pend_is_nopending(&mail_q->pend_obj)) {
|
||||
err = tos_ring_q_enqueue(&mail_q->ring_q, mail_buf, mail_size);
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (opt == OPT_POST_ONE) {
|
||||
mail_task_recv(TOS_LIST_FIRST_ENTRY(&mail_q->pend_obj.list, k_task_t, pend_list),
|
||||
mail_buf, mail_size);
|
||||
} else { // OPT_POST_ALL
|
||||
TOS_LIST_FOR_EACH_ENTRY_SAFE(task, tmp, k_task_t, pend_list, &mail_q->pend_obj.list) {
|
||||
mail_task_recv(task, mail_buf, mail_size);
|
||||
}
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mail_q_post(k_mail_q_t *mail_q, void *mail_buf, size_t mail_size)
|
||||
{
|
||||
return mail_q_do_post(mail_q, mail_buf, mail_size, OPT_POST_ONE);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mail_q_post_all(k_mail_q_t *mail_q, void *mail_buf, size_t mail_size)
|
||||
{
|
||||
return mail_q_do_post(mail_q, mail_buf, mail_size, OPT_POST_ALL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_MESSAGE_QUEUE_EN > 0u
|
||||
|
||||
__API__ k_err_t tos_msg_q_create(k_msg_q_t *msg_q, void *pool, size_t msg_cnt)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(msg_q);
|
||||
TOS_PTR_SANITY_CHECK(pool);
|
||||
|
||||
err = tos_ring_q_create(&msg_q->ring_q, pool, msg_cnt, sizeof(void *));
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_object_init(&msg_q->pend_obj);
|
||||
|
||||
TOS_OBJ_INIT(msg_q, KNL_OBJ_TYPE_MESSAGE_QUEUE);
|
||||
knl_object_alloc_set_static(&msg_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_msg_q_destroy(k_msg_q_t *msg_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(msg_q);
|
||||
TOS_OBJ_VERIFY(msg_q, KNL_OBJ_TYPE_MESSAGE_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_static(&msg_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
err = tos_ring_q_destroy(&msg_q->ring_q);
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_wakeup_all(&msg_q->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
pend_object_deinit(&msg_q->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(msg_q);
|
||||
knl_object_alloc_reset(&msg_q->knl_obj);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_msg_q_create_dyn(k_msg_q_t *msg_q, size_t msg_cnt)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(msg_q);
|
||||
|
||||
err = tos_ring_q_create_dyn(&msg_q->ring_q, msg_cnt, sizeof(void *));
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_object_init(&msg_q->pend_obj);
|
||||
|
||||
TOS_OBJ_INIT(msg_q, KNL_OBJ_TYPE_MESSAGE_QUEUE);
|
||||
knl_object_alloc_set_dynamic(&msg_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_msg_q_destroy_dyn(k_msg_q_t *msg_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(msg_q);
|
||||
TOS_OBJ_VERIFY(msg_q, KNL_OBJ_TYPE_MESSAGE_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_dynamic(&msg_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
err = tos_ring_q_destroy_dyn(&msg_q->ring_q);
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_wakeup_all(&msg_q->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
pend_object_deinit(&msg_q->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(msg_q);
|
||||
knl_object_alloc_reset(&msg_q->knl_obj);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_msg_q_flush(k_msg_q_t *msg_q)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(msg_q);
|
||||
TOS_OBJ_VERIFY(msg_q, KNL_OBJ_TYPE_MESSAGE_QUEUE);
|
||||
|
||||
return tos_ring_q_flush(&msg_q->ring_q);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_msg_q_pend(k_msg_q_t *msg_q, void **msg_ptr, k_tick_t timeout)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(msg_q);
|
||||
TOS_PTR_SANITY_CHECK(msg_ptr);
|
||||
TOS_OBJ_VERIFY(msg_q, KNL_OBJ_TYPE_MESSAGE_QUEUE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (tos_ring_q_dequeue(&msg_q->ring_q, msg_ptr, K_NULL) == K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (timeout == TOS_TIME_NOWAIT) {
|
||||
*msg_ptr = K_NULL;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_NOWAIT;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
pend_task_block(k_curr_task, &msg_q->pend_obj, timeout);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
err = pend_state2errno(k_curr_task->pend_state);
|
||||
if (err == K_ERR_NONE) {
|
||||
*msg_ptr = k_curr_task->msg;
|
||||
k_curr_task->msg = K_NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
__STATIC__ void msg_q_task_recv(k_task_t *task, void *msg_ptr)
|
||||
{
|
||||
task->msg = msg_ptr;
|
||||
pend_task_wakeup(task, PEND_STATE_POST);
|
||||
}
|
||||
|
||||
__STATIC__ k_err_t msg_q_do_post(k_msg_q_t *msg_q, void *msg_ptr, opt_post_t opt)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
k_task_t *task, *tmp;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(msg_q);
|
||||
TOS_OBJ_VERIFY(msg_q, KNL_OBJ_TYPE_MESSAGE_QUEUE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (pend_is_nopending(&msg_q->pend_obj)) {
|
||||
err = tos_ring_q_enqueue(&msg_q->ring_q, &msg_ptr, sizeof(void*));
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (opt == OPT_POST_ONE) {
|
||||
msg_q_task_recv(TOS_LIST_FIRST_ENTRY(&msg_q->pend_obj.list, k_task_t, pend_list), msg_ptr);
|
||||
} else { // OPT_POST_ALL
|
||||
TOS_LIST_FOR_EACH_ENTRY_SAFE(task, tmp, k_task_t, pend_list, &msg_q->pend_obj.list) {
|
||||
msg_q_task_recv(task, msg_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_msg_q_post(k_msg_q_t *msg_q, void *msg_ptr)
|
||||
{
|
||||
return msg_q_do_post(msg_q, msg_ptr, OPT_POST_ONE);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_msg_q_post_all(k_msg_q_t *msg_q, void *msg_ptr)
|
||||
{
|
||||
return msg_q_do_post(msg_q, msg_ptr, OPT_POST_ALL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__API__ k_err_t tos_mmblk_pool_create(k_mmblk_pool_t *mbp, void *pool_start, size_t blk_num, size_t blk_size)
|
||||
{
|
||||
uint32_t i;
|
||||
void *blk_curr, *blk_next;
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(pool_start);
|
||||
|
||||
if (((cpu_addr_t)pool_start & K_MMBLK_ALIGN_MASK) != 0u) {
|
||||
return K_ERR_MMBLK_INVALID_POOL_ADDR;
|
||||
}
|
||||
|
||||
if ((blk_size & K_MMBLK_ALIGN_MASK) != 0u) {
|
||||
return K_ERR_MMBLK_INVALID_BLK_SIZE;
|
||||
}
|
||||
|
||||
blk_curr = pool_start;
|
||||
blk_next = K_MMBLK_NEXT_BLK(blk_curr, blk_size);
|
||||
|
||||
for (i = 0; i < blk_num - 1u; ++i) {
|
||||
*(void **)blk_curr = blk_next;
|
||||
blk_curr = blk_next;
|
||||
blk_next = K_MMBLK_NEXT_BLK(blk_next, blk_size);
|
||||
}
|
||||
*(void **)blk_curr = K_NULL;
|
||||
|
||||
mbp->pool_start = pool_start;
|
||||
mbp->free_list = pool_start;
|
||||
mbp->blk_free = blk_num;
|
||||
mbp->blk_max = blk_num;
|
||||
mbp->blk_size = blk_size;
|
||||
|
||||
TOS_OBJ_INIT(mbp, KNL_OBJ_TYPE_MMBLK_POOL);
|
||||
|
||||
knl_object_alloc_set_static(&mbp->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mmblk_pool_destroy(k_mmblk_pool_t *mbp)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(mbp);
|
||||
TOS_OBJ_VERIFY(mbp, KNL_OBJ_TYPE_MMBLK_POOL);
|
||||
|
||||
#if TOS_CFG_MMHEAP_EN > 0u
|
||||
if (!knl_object_alloc_is_static(&mbp->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
#endif
|
||||
|
||||
mbp->pool_start = K_NULL;
|
||||
mbp->free_list = K_NULL;
|
||||
mbp->blk_free = 0;
|
||||
mbp->blk_max = 0;
|
||||
mbp->blk_size = 0;
|
||||
|
||||
TOS_OBJ_DEINIT(mbp);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
#if TOS_CFG_MMHEAP_EN > 0u
|
||||
|
||||
__API__ k_err_t tos_mmblk_pool_create_dyn(k_mmblk_pool_t **mbp, size_t blk_num, size_t blk_size)
|
||||
{
|
||||
uint32_t i;
|
||||
void *pool_start;
|
||||
k_mmblk_pool_t *the_mbp;
|
||||
void *blk_curr, *blk_next;
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(mbp);
|
||||
|
||||
if ((blk_size & K_MMBLK_ALIGN_MASK) != 0u) {
|
||||
return K_ERR_MMBLK_INVALID_BLK_SIZE;
|
||||
}
|
||||
|
||||
the_mbp = tos_mmheap_calloc(1, sizeof(k_mmblk_pool_t));
|
||||
if (!the_mbp) {
|
||||
return K_ERR_MMBLK_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pool_start = tos_mmheap_alloc(blk_num * blk_size);
|
||||
if (!pool_start) {
|
||||
return K_ERR_MMBLK_POOL_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
blk_curr = pool_start;
|
||||
blk_next = K_MMBLK_NEXT_BLK(blk_curr, blk_size);
|
||||
|
||||
for (i = 0; i < blk_num - 1u; ++i) {
|
||||
*(void **)blk_curr = blk_next;
|
||||
blk_curr = blk_next;
|
||||
blk_next = K_MMBLK_NEXT_BLK(blk_next, blk_size);
|
||||
}
|
||||
|
||||
*(void **)blk_curr = K_NULL;
|
||||
|
||||
the_mbp->pool_start = pool_start;
|
||||
the_mbp->free_list = pool_start;
|
||||
the_mbp->blk_free = blk_num;
|
||||
the_mbp->blk_max = blk_num;
|
||||
the_mbp->blk_size = blk_size;
|
||||
|
||||
TOS_OBJ_INIT(the_mbp, KNL_OBJ_TYPE_MMBLK_POOL);
|
||||
|
||||
knl_object_alloc_set_dynamic(&the_mbp->knl_obj);
|
||||
|
||||
*mbp = the_mbp;
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mmblk_pool_destroy_dyn(k_mmblk_pool_t *mbp)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(mbp);
|
||||
TOS_OBJ_VERIFY(mbp, KNL_OBJ_TYPE_MMBLK_POOL);
|
||||
|
||||
if (!knl_object_alloc_is_dynamic(&mbp->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
tos_mmheap_free(mbp->pool_start);
|
||||
|
||||
mbp->pool_start = K_NULL;
|
||||
mbp->free_list = K_NULL;
|
||||
mbp->blk_free = 0;
|
||||
mbp->blk_max = 0;
|
||||
mbp->blk_size = 0;
|
||||
|
||||
TOS_OBJ_DEINIT(mbp);
|
||||
tos_mmheap_free(mbp);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
__API__ k_err_t tos_mmblk_alloc(k_mmblk_pool_t *mbp, void **blk)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(mbp);
|
||||
TOS_OBJ_VERIFY(mbp, KNL_OBJ_TYPE_MMBLK_POOL);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
if (mbp->blk_free == 0) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
*blk = K_NULL;
|
||||
return K_ERR_MMBLK_POOL_EMPTY;
|
||||
}
|
||||
*blk = mbp->free_list;
|
||||
mbp->free_list = *(void **)mbp->free_list;
|
||||
--mbp->blk_free;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mmblk_free(k_mmblk_pool_t *mbp, void *blk)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(mbp);
|
||||
TOS_PTR_SANITY_CHECK(blk);
|
||||
TOS_OBJ_VERIFY(mbp, KNL_OBJ_TYPE_MMBLK_POOL);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
if (mbp->blk_free >= mbp->blk_max) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_MMBLK_POOL_FULL;
|
||||
}
|
||||
|
||||
*(void **)blk = mbp->free_list;
|
||||
mbp->free_list = blk;
|
||||
++mbp->blk_free;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,825 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
** Two Level Segregated Fit memory allocator, version 3.1.
|
||||
** Written by Matthew Conte
|
||||
** http://tlsf.baisoku.org
|
||||
**
|
||||
** Based on the original documentation by Miguel Masmano:
|
||||
** http://www.gii.upv.es/tlsf/main/docs
|
||||
**
|
||||
** This implementation was written to the specification
|
||||
** of the document, therefore no GPL restrictions apply.
|
||||
**
|
||||
** Copyright (c) 2006-2016, Matthew Conte
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** * Neither the name of the copyright holder nor the
|
||||
** names of its contributors may be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY
|
||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_MMHEAP_EN > 0u
|
||||
|
||||
#if defined(TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT) && (TOS_CFG_CPU_LEAD_ZEROS_ASM_PRESENT == 0u)
|
||||
__STATIC__ int generic_fls(uint32_t x)
|
||||
{
|
||||
int r = 32;
|
||||
if (!x)
|
||||
return 0;
|
||||
|
||||
if (!(x & 0xffff0000u)) {
|
||||
x <<= 16;
|
||||
r -= 16;
|
||||
}
|
||||
if (!(x & 0xff000000u)) {
|
||||
x <<= 8;
|
||||
r -= 8;
|
||||
}
|
||||
if (!(x & 0xf0000000u)) {
|
||||
x <<= 4;
|
||||
r -= 4;
|
||||
}
|
||||
if (!(x & 0xc0000000u)) {
|
||||
x <<= 2;
|
||||
r -= 2;
|
||||
}
|
||||
if (!(x & 0x80000000u)) {
|
||||
x <<= 1;
|
||||
r -= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#else
|
||||
__STATIC__ int generic_fls(uint32_t x)
|
||||
{
|
||||
return 32 - tos_cpu_clz(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
__STATIC__ int __ffs(uint32_t word)
|
||||
{
|
||||
return generic_fls(word & (~word + 1)) - 1;
|
||||
}
|
||||
|
||||
__STATIC__ int __fls(uint32_t word)
|
||||
{
|
||||
return generic_fls(word) - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** TLSF utility functions. In most cases, these are direct translations of
|
||||
** the documentation found in the white paper.
|
||||
*/
|
||||
__STATIC__ void mapping_insert(size_t size, int *fli, int *sli)
|
||||
{
|
||||
int fl, sl;
|
||||
|
||||
if (size < K_MMHEAP_SMALL_BLOCK_SIZE) {
|
||||
/* Store small blocks in first list. */
|
||||
fl = 0;
|
||||
sl = (int)size / (K_MMHEAP_SMALL_BLOCK_SIZE / K_MMHEAP_SL_INDEX_COUNT);
|
||||
} else {
|
||||
fl = __fls(size);
|
||||
sl = ((int)size >> (fl - K_MMHEAP_SL_INDEX_COUNT_LOG2)) ^ (1 << K_MMHEAP_SL_INDEX_COUNT_LOG2);
|
||||
fl -= (K_MMHEAP_FL_INDEX_SHIFT - 1);
|
||||
}
|
||||
*fli = fl;
|
||||
*sli = sl;
|
||||
}
|
||||
|
||||
/* This version rounds up to the next block size (for allocations) */
|
||||
__STATIC__ void mapping_search(size_t size, int *fli, int *sli)
|
||||
{
|
||||
size_t round;
|
||||
|
||||
if (size >= K_MMHEAP_SMALL_BLOCK_SIZE) {
|
||||
round = (1 << (__fls(size) - K_MMHEAP_SL_INDEX_COUNT_LOG2)) - 1;
|
||||
size += round;
|
||||
}
|
||||
mapping_insert(size, fli, sli);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ size_t blk_size(const mmheap_blk_t *blk)
|
||||
{
|
||||
return blk->size & K_MMHEAP_BLOCK_SIZE_MASK;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ int blk_is_last(const mmheap_blk_t* blk)
|
||||
{
|
||||
return blk_size(blk) == 0;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void blk_set_size(mmheap_blk_t *blk, size_t size)
|
||||
{
|
||||
blk->size = size | (blk->size & K_MMHEAP_BLOCK_STATE_MASK);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ int blk_is_free(const mmheap_blk_t *blk)
|
||||
{
|
||||
return blk->size & K_MMHEAP_BLOCK_CURR_FREE;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void blk_set_free(mmheap_blk_t *blk)
|
||||
{
|
||||
blk->size |= K_MMHEAP_BLOCK_CURR_FREE;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void blk_set_used(mmheap_blk_t *blk)
|
||||
{
|
||||
blk->size &= ~K_MMHEAP_BLOCK_CURR_FREE;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ int blk_is_prev_free(const mmheap_blk_t *blk)
|
||||
{
|
||||
return blk->size & K_MMHEAP_BLOCK_PREV_FREE;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void blk_set_prev_free(mmheap_blk_t *blk)
|
||||
{
|
||||
blk->size |= K_MMHEAP_BLOCK_PREV_FREE;
|
||||
}
|
||||
|
||||
__STATIC__ void blk_set_prev_used(mmheap_blk_t *blk)
|
||||
{
|
||||
blk->size &= ~K_MMHEAP_BLOCK_PREV_FREE;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ mmheap_blk_t *blk_from_ptr(const void *ptr)
|
||||
{
|
||||
return (mmheap_blk_t *)((cpu_addr_t)ptr - K_MMHEAP_BLK_START_OFFSET);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void *blk_to_ptr(const mmheap_blk_t *blk)
|
||||
{
|
||||
return (void *)((cpu_addr_t)blk + K_MMHEAP_BLK_START_OFFSET);
|
||||
}
|
||||
|
||||
/* Return location of next block after block of given size. */
|
||||
__STATIC_INLINE__ mmheap_blk_t *offset_to_blk(const void *ptr, int diff)
|
||||
{
|
||||
return (mmheap_blk_t *)((cpu_addr_t)ptr + diff);
|
||||
}
|
||||
|
||||
/* Return location of previous block. */
|
||||
__STATIC_INLINE__ mmheap_blk_t *blk_prev(const mmheap_blk_t *blk)
|
||||
{
|
||||
return blk->prev_phys_blk;
|
||||
}
|
||||
|
||||
/* Return location of next existing block. */
|
||||
__STATIC__ mmheap_blk_t *blk_next(const mmheap_blk_t *blk)
|
||||
{
|
||||
mmheap_blk_t *next_blk;
|
||||
|
||||
next_blk = offset_to_blk(blk_to_ptr(blk), blk_size(blk) - K_MMHEAP_BLK_HEADER_OVERHEAD);
|
||||
return next_blk;
|
||||
}
|
||||
|
||||
/* Link a new block with its physical neighbor, return the neighbor. */
|
||||
__STATIC__ mmheap_blk_t *blk_link_next(mmheap_blk_t *blk)
|
||||
{
|
||||
mmheap_blk_t *next_blk;
|
||||
|
||||
next_blk = blk_next(blk);
|
||||
next_blk->prev_phys_blk = blk;
|
||||
return next_blk;
|
||||
}
|
||||
|
||||
__STATIC__ void blk_mark_as_free(mmheap_blk_t *blk)
|
||||
{
|
||||
mmheap_blk_t *next_blk;
|
||||
|
||||
/* Link the block to the next block, first. */
|
||||
next_blk = blk_link_next(blk);
|
||||
blk_set_prev_free(next_blk);
|
||||
blk_set_free(blk);
|
||||
}
|
||||
|
||||
__STATIC__ void blk_mark_as_used(mmheap_blk_t *blk)
|
||||
{
|
||||
mmheap_blk_t *next_blk;
|
||||
|
||||
next_blk = blk_next(blk);
|
||||
blk_set_prev_used(next_blk);
|
||||
blk_set_used(blk);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ size_t align_up(size_t x, size_t align)
|
||||
{
|
||||
return (x + (align - 1)) & ~(align - 1);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ size_t align_down(size_t x, size_t align)
|
||||
{
|
||||
return x - (x & (align - 1));
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void *align_ptr(const void *ptr, size_t align)
|
||||
{
|
||||
return (void *)(((cpu_addr_t)ptr + (align -1)) & ~(align -1));
|
||||
}
|
||||
|
||||
/* Insert a free block into the free block list. */
|
||||
__STATIC__ void insert_free_block(mmheap_blk_t *blk, int fl, int sl)
|
||||
{
|
||||
mmheap_blk_t *curr;
|
||||
|
||||
curr = k_mmheap_ctl.blocks[fl][sl];
|
||||
blk->next_free = curr;
|
||||
blk->prev_free = &k_mmheap_ctl.block_null;
|
||||
curr->prev_free = blk;
|
||||
|
||||
/*
|
||||
** Insert the new block at the head of the list, and mark the first-
|
||||
** and second-level bitmaps appropriately.
|
||||
*/
|
||||
k_mmheap_ctl.blocks[fl][sl] = blk;
|
||||
k_mmheap_ctl.fl_bitmap |= (1 << fl);
|
||||
k_mmheap_ctl.sl_bitmap[fl] |= (1 << sl);
|
||||
}
|
||||
|
||||
/* Remove a free block from the free list.*/
|
||||
__STATIC__ void remove_free_block(mmheap_blk_t *blk, int fl, int sl)
|
||||
{
|
||||
mmheap_blk_t *prev_blk;
|
||||
mmheap_blk_t *next_blk;
|
||||
|
||||
prev_blk = blk->prev_free;
|
||||
next_blk = blk->next_free;
|
||||
next_blk->prev_free = prev_blk;
|
||||
prev_blk->next_free = next_blk;
|
||||
|
||||
/* If this block is the head of the free list, set new head. */
|
||||
if (k_mmheap_ctl.blocks[fl][sl] == blk) {
|
||||
k_mmheap_ctl.blocks[fl][sl] = next_blk;
|
||||
|
||||
/* If the new head is null, clear the bitmap. */
|
||||
if (next_blk == &k_mmheap_ctl.block_null) {
|
||||
k_mmheap_ctl.sl_bitmap[fl] &= ~(1 << sl);
|
||||
|
||||
/* If the second bitmap is now empty, clear the fl bitmap. */
|
||||
if (!k_mmheap_ctl.sl_bitmap[fl]) {
|
||||
k_mmheap_ctl.fl_bitmap &= ~(1 << fl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove a given block from the free list. */
|
||||
__STATIC__ void blk_remove(mmheap_blk_t *blk)
|
||||
{
|
||||
int fl, sl;
|
||||
|
||||
mapping_insert(blk_size(blk), &fl, &sl);
|
||||
remove_free_block(blk, fl, sl);
|
||||
}
|
||||
|
||||
/* Insert a given block into the free list. */
|
||||
__STATIC__ void blk_insert(mmheap_blk_t *blk)
|
||||
{
|
||||
int fl, sl;
|
||||
|
||||
mapping_insert(blk_size(blk), &fl, &sl);
|
||||
insert_free_block(blk, fl, sl);
|
||||
}
|
||||
|
||||
__STATIC__ int blk_can_split(mmheap_blk_t *blk, size_t size)
|
||||
{
|
||||
return blk_size(blk) >= sizeof(mmheap_blk_t) + size;
|
||||
}
|
||||
|
||||
/* Split a block into two, the second of which is free. */
|
||||
__STATIC__ mmheap_blk_t *blk_split(mmheap_blk_t *blk, size_t size)
|
||||
{
|
||||
mmheap_blk_t *remaining;
|
||||
size_t remain_size;
|
||||
|
||||
/* Calculate the amount of space left in the remaining block. */
|
||||
remaining = offset_to_blk(blk_to_ptr(blk), size - K_MMHEAP_BLK_HEADER_OVERHEAD);
|
||||
remain_size = blk_size(blk) - (size + K_MMHEAP_BLK_HEADER_OVERHEAD);
|
||||
|
||||
blk_set_size(remaining, remain_size);
|
||||
|
||||
blk_set_size(blk, size);
|
||||
blk_mark_as_free(remaining);
|
||||
|
||||
return remaining;
|
||||
}
|
||||
|
||||
/* Absorb a free block's storage into an adjacent previous free block. */
|
||||
__STATIC__ mmheap_blk_t *blk_absorb(mmheap_blk_t *prev_blk, mmheap_blk_t *blk)
|
||||
{
|
||||
prev_blk->size += blk_size(blk) + K_MMHEAP_BLK_HEADER_OVERHEAD;
|
||||
blk_link_next(prev_blk);
|
||||
return prev_blk;
|
||||
}
|
||||
|
||||
/* Merge a just-freed block with an adjacent previous free block. */
|
||||
__STATIC__ mmheap_blk_t *blk_merge_prev(mmheap_blk_t *blk)
|
||||
{
|
||||
mmheap_blk_t *prev_blk;
|
||||
|
||||
if (blk_is_prev_free(blk)) {
|
||||
prev_blk = blk_prev(blk);
|
||||
blk_remove(prev_blk);
|
||||
blk = blk_absorb(prev_blk, blk);
|
||||
}
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
/* Merge a just-freed block with an adjacent free block. */
|
||||
__STATIC__ mmheap_blk_t *blk_merge_next(mmheap_blk_t *blk)
|
||||
{
|
||||
mmheap_blk_t *next_blk;
|
||||
|
||||
next_blk = blk_next(blk);
|
||||
if (blk_is_free(next_blk)) {
|
||||
blk_remove(next_blk);
|
||||
blk = blk_absorb(blk, next_blk);
|
||||
}
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
/* Trim any trailing block space off the end of a block, return to pool. */
|
||||
__STATIC__ void blk_trim_free(mmheap_blk_t *blk, size_t size)
|
||||
{
|
||||
mmheap_blk_t *remaining_blk;
|
||||
|
||||
if (blk_can_split(blk, size)) {
|
||||
remaining_blk = blk_split(blk, size);
|
||||
blk_link_next(blk);
|
||||
blk_set_prev_free(remaining_blk);
|
||||
blk_insert(remaining_blk);
|
||||
}
|
||||
}
|
||||
|
||||
/* Trim any trailing block space off the end of a used block, return to pool. */
|
||||
__STATIC__ void blk_trim_used(mmheap_blk_t *blk, size_t size)
|
||||
{
|
||||
mmheap_blk_t *remaining_blk;
|
||||
|
||||
if (blk_can_split(blk, size)) {
|
||||
/* If the next block is free, we must coalesce. */
|
||||
remaining_blk = blk_split(blk, size);
|
||||
blk_set_prev_used(remaining_blk);
|
||||
|
||||
remaining_blk = blk_merge_next(remaining_blk);
|
||||
blk_insert(remaining_blk);
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC__ mmheap_blk_t *blk_trim_free_leading(mmheap_blk_t *blk, size_t size)
|
||||
{
|
||||
mmheap_blk_t *remaining_blk;
|
||||
|
||||
remaining_blk = blk;
|
||||
if (blk_can_split(blk, size)) {
|
||||
/* We want the 2nd block. */
|
||||
remaining_blk = blk_split(blk, size - K_MMHEAP_BLK_HEADER_OVERHEAD);
|
||||
blk_set_prev_free(remaining_blk);
|
||||
|
||||
blk_link_next(blk);
|
||||
blk_insert(blk);
|
||||
}
|
||||
|
||||
return remaining_blk;
|
||||
}
|
||||
|
||||
__STATIC__ mmheap_blk_t *blk_search_suitable(int *fli, int *sli)
|
||||
{
|
||||
int fl, sl;
|
||||
uint32_t sl_map, fl_map;
|
||||
|
||||
fl = *fli;
|
||||
sl = *sli;
|
||||
|
||||
/*
|
||||
** First, search for a block in the list associated with the given
|
||||
** fl/sl index.
|
||||
*/
|
||||
sl_map = k_mmheap_ctl.sl_bitmap[fl] & (~0U << sl);
|
||||
if (!sl_map) {
|
||||
/* No block exists. Search in the next largest first-level list. */
|
||||
fl_map = k_mmheap_ctl.fl_bitmap & (~0U << (fl + 1));
|
||||
if (!fl_map) {
|
||||
/* No free blocks available, memory has been exhausted. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
fl = __ffs(fl_map);
|
||||
*fli = fl;
|
||||
sl_map = k_mmheap_ctl.sl_bitmap[fl];
|
||||
}
|
||||
sl = __ffs(sl_map);
|
||||
*sli = sl;
|
||||
|
||||
/* Return the first block in the free list. */
|
||||
return k_mmheap_ctl.blocks[fl][sl];
|
||||
}
|
||||
|
||||
__STATIC__ mmheap_blk_t *blk_locate_free(size_t size)
|
||||
{
|
||||
int fl = 0, sl = 0;
|
||||
mmheap_blk_t *blk = K_NULL;
|
||||
|
||||
if (!size) {
|
||||
return K_NULL;
|
||||
}
|
||||
|
||||
mapping_search(size, &fl, &sl);
|
||||
|
||||
/*
|
||||
** mapping_search can futz with the size, so for excessively large sizes it can sometimes wind up
|
||||
** with indices that are off the end of the block array.
|
||||
** So, we protect against that here, since this is the only callsite of mapping_search.
|
||||
** Note that we don't need to check sl, since it comes from a modulo operation that guarantees it's always in range.
|
||||
*/
|
||||
if (fl < K_MMHEAP_FL_INDEX_COUNT) {
|
||||
blk = blk_search_suitable(&fl, &sl);
|
||||
}
|
||||
|
||||
if (blk) {
|
||||
remove_free_block(blk, fl, sl);
|
||||
}
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
/*
|
||||
** Adjust an allocation size to be aligned to word size, and no smaller
|
||||
** than internal minimum.
|
||||
*/
|
||||
__STATIC__ size_t adjust_request_size(size_t size, size_t align)
|
||||
{
|
||||
size_t adjust_size = 0;
|
||||
|
||||
if (!size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
adjust_size = align_up(size, align);
|
||||
if (!adjust_size || adjust_size > K_MMHEAP_BLK_SIZE_MAX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* aligned sized must not exceed block_size_max or we'll go out of bounds on sl_bitmap */
|
||||
return adjust_size > K_MMHEAP_BLK_SIZE_MIN ? adjust_size : K_MMHEAP_BLK_SIZE_MIN;
|
||||
}
|
||||
|
||||
__STATIC__ void *blk_prepare_used(mmheap_blk_t *blk, size_t size)
|
||||
{
|
||||
if (!blk) {
|
||||
return K_NULL;
|
||||
}
|
||||
blk_trim_free(blk, size);
|
||||
blk_mark_as_used(blk);
|
||||
return blk_to_ptr(blk);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ int mmheap_pool_is_full(void)
|
||||
{
|
||||
return k_mmheap_ctl.pool_cnt == K_MMHEAP_POOL_MAX;
|
||||
}
|
||||
|
||||
__STATIC__ int mmheap_pool_is_exist(void *pool_start)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < k_mmheap_ctl.pool_cnt; ++i) {
|
||||
if (k_mmheap_ctl.pool_start[i] == pool_start) {
|
||||
return K_TRUE;
|
||||
}
|
||||
}
|
||||
return K_FALSE;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void mmheap_pool_record(void *pool_start)
|
||||
{
|
||||
k_mmheap_ctl.pool_start[k_mmheap_ctl.pool_cnt++] = pool_start;
|
||||
}
|
||||
|
||||
__STATIC__ void mmheap_pool_unrecord(void *pool_start)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < k_mmheap_ctl.pool_cnt; ++i) {
|
||||
if (k_mmheap_ctl.pool_start[i] == pool_start) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != k_mmheap_ctl.pool_cnt - 1) {
|
||||
k_mmheap_ctl.pool_start[i] = k_mmheap_ctl.pool_start[k_mmheap_ctl.pool_cnt - 1];
|
||||
}
|
||||
--k_mmheap_ctl.pool_cnt;
|
||||
}
|
||||
|
||||
__STATIC__ void mmheap_ctl_init(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
k_mmheap_ctl.pool_cnt = 0u;
|
||||
for (i = 0; i < K_MMHEAP_POOL_MAX; ++i) {
|
||||
k_mmheap_ctl.pool_start[i] = (void *)K_NULL;
|
||||
}
|
||||
|
||||
k_mmheap_ctl.block_null.next_free = &k_mmheap_ctl.block_null;
|
||||
k_mmheap_ctl.block_null.prev_free = &k_mmheap_ctl.block_null;
|
||||
|
||||
k_mmheap_ctl.fl_bitmap = 0;
|
||||
for (i = 0; i < K_MMHEAP_FL_INDEX_COUNT; ++i) {
|
||||
k_mmheap_ctl.sl_bitmap[i] = 0;
|
||||
for (j = 0; j < K_MMHEAP_SL_INDEX_COUNT; ++j) {
|
||||
k_mmheap_ctl.blocks[i][j] = &k_mmheap_ctl.block_null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__KNL__ k_err_t mmheap_init(void)
|
||||
{
|
||||
mmheap_ctl_init();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__KNL__ k_err_t mmheap_init_with_pool(void *pool_start, size_t pool_size)
|
||||
{
|
||||
mmheap_ctl_init();
|
||||
|
||||
return tos_mmheap_pool_add(pool_start, pool_size);
|
||||
}
|
||||
|
||||
__API__ void *tos_mmheap_alloc(size_t size)
|
||||
{
|
||||
size_t adjust_size;
|
||||
mmheap_blk_t *blk;
|
||||
|
||||
if (size > K_MMHEAP_BLK_SIZE_MAX) {
|
||||
return K_NULL;
|
||||
}
|
||||
|
||||
adjust_size = adjust_request_size(size, K_MMHEAP_ALIGN_SIZE);
|
||||
blk = blk_locate_free(adjust_size);
|
||||
if (!blk) {
|
||||
return K_NULL;
|
||||
}
|
||||
|
||||
return blk_prepare_used(blk, adjust_size);
|
||||
}
|
||||
|
||||
__API__ void *tos_mmheap_calloc(size_t num, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
ptr = tos_mmheap_alloc(num * size);
|
||||
if (ptr) {
|
||||
memset(ptr, 0, num * size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
__API__ void *tos_mmheap_aligned_alloc(size_t size, size_t align)
|
||||
{
|
||||
mmheap_blk_t *blk;
|
||||
void *ptr, *aligned, *next_aligned;
|
||||
size_t adjust_size, aligned_size;
|
||||
size_t gap_minimum, size_with_gap, gap, gap_remain, offset;
|
||||
|
||||
adjust_size = adjust_request_size(size, K_MMHEAP_ALIGN_SIZE);
|
||||
gap_minimum = sizeof(mmheap_blk_t);
|
||||
size_with_gap = adjust_request_size(adjust_size + align + gap_minimum, align);
|
||||
aligned_size = (adjust_size && align > K_MMHEAP_ALIGN_SIZE) ? size_with_gap : adjust_size;
|
||||
|
||||
blk = blk_locate_free(aligned_size);
|
||||
if (!blk) {
|
||||
return K_NULL;
|
||||
}
|
||||
|
||||
ptr = blk_to_ptr(blk);
|
||||
aligned = align_ptr(ptr, align);
|
||||
gap = (size_t)((cpu_addr_t)aligned - (cpu_addr_t)ptr);
|
||||
|
||||
if (gap && gap < gap_minimum) {
|
||||
gap_remain = gap_minimum - gap;
|
||||
offset = gap_remain > align ? gap_remain : align;
|
||||
next_aligned = (void *)((cpu_data_t)aligned + offset);
|
||||
|
||||
aligned = align_ptr(next_aligned, align);
|
||||
gap = (size_t)((cpu_addr_t)aligned - (cpu_addr_t)ptr);
|
||||
}
|
||||
|
||||
if (gap) {
|
||||
blk = blk_trim_free_leading(blk, gap);
|
||||
}
|
||||
|
||||
return blk_prepare_used(blk, adjust_size);
|
||||
}
|
||||
|
||||
__API__ void tos_mmheap_free(void *ptr)
|
||||
{
|
||||
mmheap_blk_t *blk;
|
||||
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
blk = blk_from_ptr(ptr);
|
||||
blk_mark_as_free(blk);
|
||||
blk = blk_merge_prev(blk);
|
||||
blk = blk_merge_next(blk);
|
||||
blk_insert(blk);
|
||||
}
|
||||
|
||||
__API__ void *tos_mmheap_realloc(void *ptr, size_t size)
|
||||
{
|
||||
void *p = 0;
|
||||
mmheap_blk_t *curr_blk, *next_blk;
|
||||
size_t curr_size, combined_size, adjust_size, min_size;
|
||||
|
||||
if (ptr && size == 0) {
|
||||
tos_mmheap_free(ptr);
|
||||
return K_NULL;
|
||||
}
|
||||
|
||||
if (!ptr) {
|
||||
return tos_mmheap_alloc(size);
|
||||
}
|
||||
|
||||
curr_blk = blk_from_ptr(ptr);
|
||||
next_blk = blk_next(curr_blk);
|
||||
|
||||
curr_size = blk_size(curr_blk);
|
||||
combined_size = curr_size + blk_size(next_blk) + K_MMHEAP_BLK_HEADER_OVERHEAD;
|
||||
adjust_size = adjust_request_size(size, K_MMHEAP_ALIGN_SIZE);
|
||||
|
||||
if (adjust_size > curr_size && (!blk_is_free(next_blk) || adjust_size > combined_size)) {
|
||||
p = tos_mmheap_alloc(size);
|
||||
if (p) {
|
||||
min_size = curr_size < size ? curr_size : size;
|
||||
memcpy(p, ptr, min_size);
|
||||
tos_mmheap_free(ptr);
|
||||
}
|
||||
} else {
|
||||
if (adjust_size > curr_size) {
|
||||
blk_merge_next(curr_blk);
|
||||
blk_mark_as_used(curr_blk);
|
||||
}
|
||||
|
||||
blk_trim_used(curr_blk, adjust_size);
|
||||
p = ptr;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mmheap_pool_add(void *pool_start, size_t pool_size)
|
||||
{
|
||||
mmheap_blk_t *curr_blk;
|
||||
mmheap_blk_t *next_blk;
|
||||
size_t size_aligned;
|
||||
|
||||
if (mmheap_pool_is_full()) {
|
||||
return K_ERR_MMHEAP_POOL_OVERFLOW;
|
||||
}
|
||||
|
||||
if (mmheap_pool_is_exist(pool_start)) {
|
||||
return K_ERR_MMHEAP_POOL_ALREADY_EXIST;
|
||||
}
|
||||
|
||||
size_aligned = align_down(pool_size - 2 * K_MMHEAP_BLK_HEADER_OVERHEAD, K_MMHEAP_ALIGN_SIZE);
|
||||
|
||||
if (((cpu_addr_t)pool_start % K_MMHEAP_ALIGN_SIZE) != 0u) {
|
||||
return K_ERR_MMHEAP_INVALID_POOL_ADDR;
|
||||
}
|
||||
|
||||
if (size_aligned < K_MMHEAP_BLK_SIZE_MIN ||
|
||||
size_aligned > K_MMHEAP_BLK_SIZE_MAX) {
|
||||
return K_ERR_MMHEAP_INVALID_POOL_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create the main free block. Offset the start of the block slightly
|
||||
** so that the prev_phys_block field falls outside of the pool -
|
||||
** it will never be used.
|
||||
*/
|
||||
curr_blk = offset_to_blk(pool_start, -K_MMHEAP_BLK_HEADER_OVERHEAD);
|
||||
blk_set_size(curr_blk, size_aligned);
|
||||
blk_set_free(curr_blk);
|
||||
blk_set_prev_used(curr_blk);
|
||||
blk_insert(curr_blk);
|
||||
|
||||
/* Split the block to create a zero-size sentinel block. */
|
||||
next_blk = blk_link_next(curr_blk);
|
||||
blk_set_size(next_blk, 0);
|
||||
blk_set_used(next_blk);
|
||||
blk_set_prev_free(next_blk);
|
||||
|
||||
mmheap_pool_record(pool_start);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mmheap_pool_rmv(void *pool_start)
|
||||
{
|
||||
int fl = 0, sl = 0;
|
||||
mmheap_blk_t *blk;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(pool_start);
|
||||
|
||||
if (!mmheap_pool_is_exist(pool_start)) {
|
||||
return K_ERR_MMHEAP_POOL_NOT_EXIST;
|
||||
}
|
||||
|
||||
blk = offset_to_blk(pool_start, -K_MMHEAP_BLK_HEADER_OVERHEAD);
|
||||
mapping_insert(blk_size(blk), &fl, &sl);
|
||||
remove_free_block(blk, fl, sl);
|
||||
|
||||
mmheap_pool_unrecord(pool_start);
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mmheap_pool_check(void *pool_start, k_mmheap_info_t *info)
|
||||
{
|
||||
mmheap_blk_t* blk;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(pool_start);
|
||||
TOS_PTR_SANITY_CHECK(info);
|
||||
|
||||
memset(info, 0, sizeof(k_mmheap_info_t));
|
||||
|
||||
blk = offset_to_blk(pool_start, -K_MMHEAP_BLK_HEADER_OVERHEAD);
|
||||
|
||||
while (blk && !blk_is_last(blk)) {
|
||||
if (blk_is_free(blk)) {
|
||||
info->free += blk_size(blk);
|
||||
} else {
|
||||
info->used += blk_size(blk);
|
||||
}
|
||||
blk = blk_next(blk);
|
||||
}
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mmheap_check(k_mmheap_info_t *info)
|
||||
{
|
||||
int i;
|
||||
k_err_t err;
|
||||
k_mmheap_info_t pool_info;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(info);
|
||||
|
||||
memset(info, 0, sizeof(k_mmheap_info_t));
|
||||
|
||||
for (i = 0; i < k_mmheap_ctl.pool_cnt; ++i) {
|
||||
err = tos_mmheap_pool_check(k_mmheap_ctl.pool_start[i], &pool_info);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
info->free += pool_info.free;
|
||||
info->used += pool_info.used;
|
||||
}
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_MUTEX_EN > 0u
|
||||
|
||||
__STATIC_INLINE__ void mutex_old_owner_release(k_mutex_t *mutex)
|
||||
{
|
||||
k_task_t *owner;
|
||||
|
||||
owner = mutex->owner;
|
||||
|
||||
tos_list_del(&mutex->owner_anchor);
|
||||
mutex->owner = K_NULL;
|
||||
mutex->pend_nesting = (k_nesting_t)0u;
|
||||
|
||||
// the right time comes! let's do it!
|
||||
if (owner->prio_pending != K_TASK_PRIO_INVALID) {
|
||||
tos_task_prio_change(owner, owner->prio_pending);
|
||||
owner->prio_pending = K_TASK_PRIO_INVALID;
|
||||
} else if (owner->prio != mutex->owner_orig_prio) {
|
||||
tos_task_prio_change(owner, mutex->owner_orig_prio);
|
||||
mutex->owner_orig_prio = K_TASK_PRIO_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void mutex_fresh_owner_mark(k_mutex_t *mutex, k_task_t *task)
|
||||
{
|
||||
mutex->owner = task;
|
||||
mutex->owner_orig_prio = task->prio;
|
||||
mutex->pend_nesting = (k_nesting_t)1u;
|
||||
|
||||
tos_list_add(&mutex->owner_anchor, &task->mutex_own_list);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void mutex_new_owner_mark(k_mutex_t *mutex, k_task_t *task)
|
||||
{
|
||||
k_prio_t highest_pending_prio;
|
||||
|
||||
mutex_fresh_owner_mark(mutex, task);
|
||||
|
||||
// we own the mutex now, make sure our priority is higher than any one in the pend list.
|
||||
highest_pending_prio = pend_highest_pending_prio_get(&mutex->pend_obj);
|
||||
if (task->prio > highest_pending_prio) {
|
||||
tos_task_prio_change(task, highest_pending_prio);
|
||||
}
|
||||
}
|
||||
|
||||
__KNL__ void mutex_release(k_mutex_t *mutex)
|
||||
{
|
||||
mutex_old_owner_release(mutex);
|
||||
pend_wakeup_all(&mutex->pend_obj, PEND_STATE_OWNER_DIE);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mutex_create(k_mutex_t *mutex)
|
||||
{
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(mutex);
|
||||
|
||||
pend_object_init(&mutex->pend_obj);
|
||||
mutex->pend_nesting = (k_nesting_t)0u;
|
||||
mutex->owner = K_NULL;
|
||||
mutex->owner_orig_prio = K_TASK_PRIO_INVALID;
|
||||
tos_list_init(&mutex->owner_anchor);
|
||||
|
||||
TOS_OBJ_INIT(mutex, KNL_OBJ_TYPE_MUTEX);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mutex_create_dyn(k_mutex_t **mutex)
|
||||
{
|
||||
k_mutex_t *the_mutex;
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(mutex);
|
||||
|
||||
the_mutex = tos_mmheap_calloc(1, sizeof(k_mutex_t));
|
||||
if (!the_mutex) {
|
||||
return K_ERR_MUTEX_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pend_object_init(&the_mutex->pend_obj);
|
||||
the_mutex->pend_nesting = (k_nesting_t)0u;
|
||||
the_mutex->owner = K_NULL;
|
||||
the_mutex->owner_orig_prio = K_TASK_PRIO_INVALID;
|
||||
tos_list_init(&the_mutex->owner_anchor);
|
||||
TOS_OBJ_INIT(the_mutex, KNL_OBJ_TYPE_MUTEX);
|
||||
|
||||
knl_object_alloc_set_dynamic(&the_mutex->knl_obj);
|
||||
|
||||
*mutex = the_mutex;
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mutex_destroy(k_mutex_t *mutex)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(mutex);
|
||||
TOS_OBJ_VERIFY(mutex, KNL_OBJ_TYPE_MUTEX);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
pend_wakeup_all(&mutex->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
if (mutex->owner) {
|
||||
mutex_old_owner_release(mutex);
|
||||
}
|
||||
|
||||
pend_object_deinit(&mutex->pend_obj);
|
||||
|
||||
if (knl_object_alloc_is_dynamic(&mutex->knl_obj)) {
|
||||
TOS_OBJ_DEINIT(mutex);
|
||||
tos_mmheap_free(mutex);
|
||||
} else {
|
||||
TOS_OBJ_DEINIT(mutex);
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mutex_pend_timed(k_mutex_t *mutex, k_tick_t timeout)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(mutex);
|
||||
TOS_OBJ_VERIFY(mutex, KNL_OBJ_TYPE_MUTEX);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
if (mutex->pend_nesting == (k_nesting_t)0u) { // first come
|
||||
mutex_fresh_owner_mark(mutex, k_curr_task);
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (knl_is_self(mutex->owner)) { // come again
|
||||
if (mutex->pend_nesting == (k_nesting_t)-1) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_MUTEX_NESTING_OVERFLOW;
|
||||
}
|
||||
++mutex->pend_nesting;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_MUTEX_NESTING;
|
||||
}
|
||||
|
||||
if (timeout == TOS_TIME_NOWAIT) { // no wait, return immediately
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_NOWAIT;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
if (mutex->owner->prio > k_curr_task->prio) {
|
||||
// PRIORITY INVERSION:
|
||||
// we are declaring a mutex, which's owner has a lower(numerically bigger) priority.
|
||||
// make owner the same priority with us.
|
||||
tos_task_prio_change(mutex->owner, k_curr_task->prio);
|
||||
}
|
||||
|
||||
pend_task_block(k_curr_task, &mutex->pend_obj, timeout);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return pend_state2errno(k_curr_task->pend_state);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mutex_pend(k_mutex_t *mutex)
|
||||
{
|
||||
return tos_mutex_pend_timed(mutex, TOS_TIME_FOREVER);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_mutex_post(k_mutex_t *mutex)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_task_t *pending_task;
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(mutex);
|
||||
TOS_OBJ_VERIFY(mutex, KNL_OBJ_TYPE_MUTEX);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
if (!knl_is_self(mutex->owner)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_MUTEX_NOT_OWNER;
|
||||
}
|
||||
|
||||
--mutex->pend_nesting;
|
||||
if (mutex->pend_nesting > (k_nesting_t)0u) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_MUTEX_NESTING;
|
||||
}
|
||||
|
||||
mutex_old_owner_release(mutex);
|
||||
|
||||
if (pend_is_nopending(&mutex->pend_obj)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
/* must do the mutex owner switch right here
|
||||
if the pender don't get a chance to schedule, the poster(old owner) may obtain the mutex immediately again
|
||||
but the pender already get ready(already in the critical section).
|
||||
we switch the owner right here to avoid the old owner obtain the mutex again
|
||||
*/
|
||||
pending_task = pend_highest_pending_task_get(&mutex->pend_obj);
|
||||
mutex_new_owner_mark(mutex, pending_task);
|
||||
|
||||
pend_wakeup_one(&mutex->pend_obj, PEND_STATE_POST);
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__STATIC__ void pend_list_add(k_task_t *task, pend_obj_t *pend_obj)
|
||||
{
|
||||
k_task_t *iter;
|
||||
|
||||
/* keep priority in descending order, the boss(task with highest priority,
|
||||
numerically smallest) always comes first
|
||||
*/
|
||||
TOS_LIST_FOR_EACH_ENTRY(iter, k_task_t, pend_list, &pend_obj->list) {
|
||||
if (task->prio < iter->prio) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tos_list_add_tail(&task->pend_list, &iter->pend_list);
|
||||
|
||||
// remember me, you may use me someday
|
||||
task->pending_obj = pend_obj;
|
||||
task_state_set_pend(task);
|
||||
}
|
||||
|
||||
__KNL__ k_prio_t pend_highest_pending_prio_get(pend_obj_t *object)
|
||||
{
|
||||
k_task_t *task;
|
||||
|
||||
// we keep the task priority in descending order, so the first one is just fine.
|
||||
task = TOS_LIST_FIRST_ENTRY_OR_NULL(&object->list, k_task_t, pend_list);
|
||||
return task ? task->prio : K_TASK_PRIO_INVALID;
|
||||
}
|
||||
|
||||
__KNL__ k_task_t *pend_highest_pending_task_get(pend_obj_t *object)
|
||||
{
|
||||
return TOS_LIST_FIRST_ENTRY(&object->list, k_task_t, pend_list);
|
||||
}
|
||||
|
||||
__KNL__ void pend_list_remove(k_task_t *task)
|
||||
{
|
||||
tos_list_del(&task->pend_list);
|
||||
|
||||
task->pending_obj = (pend_obj_t *)K_NULL;
|
||||
task_state_reset_pending(task);
|
||||
}
|
||||
|
||||
__KNL__ void pend_object_init(pend_obj_t *object)
|
||||
{
|
||||
tos_list_init(&object->list);
|
||||
}
|
||||
|
||||
__KNL__ void pend_object_deinit(pend_obj_t *object)
|
||||
{
|
||||
tos_list_init(&object->list);
|
||||
}
|
||||
|
||||
__KNL__ int pend_is_nopending(pend_obj_t *object)
|
||||
{
|
||||
return tos_list_empty(&object->list);
|
||||
}
|
||||
|
||||
__KNL__ void pend_list_adjust(k_task_t *task)
|
||||
{
|
||||
// we may be the boss, so re-enter the pend list
|
||||
tos_list_del(&task->pend_list);
|
||||
// the "someday" comes
|
||||
pend_list_add(task, task->pending_obj);
|
||||
}
|
||||
|
||||
__KNL__ k_err_t pend_state2errno(pend_state_t state)
|
||||
{
|
||||
if (state == PEND_STATE_POST) {
|
||||
return K_ERR_NONE;
|
||||
} else if (state == PEND_STATE_TIMEOUT) {
|
||||
return K_ERR_PEND_TIMEOUT;
|
||||
} else if (state == PEND_STATE_DESTROY) {
|
||||
return K_ERR_PEND_DESTROY;
|
||||
} else if (state == PEND_STATE_OWNER_DIE) {
|
||||
return K_ERR_PEND_OWNER_DIE;
|
||||
} else {
|
||||
return K_ERR_PEND_ABNORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
__KNL__ void pend_task_wakeup(k_task_t *task, pend_state_t state)
|
||||
{
|
||||
if (task_state_is_pending(task)) {
|
||||
// mark why we wakeup
|
||||
task->pend_state = state;
|
||||
pend_list_remove(task);
|
||||
}
|
||||
|
||||
if (task_state_is_sleeping(task)) {
|
||||
tick_list_remove(task);
|
||||
}
|
||||
|
||||
if (task_state_is_suspended(task)) {
|
||||
return;
|
||||
}
|
||||
|
||||
readyqueue_add(task);
|
||||
}
|
||||
|
||||
__KNL__ void pend_task_block(k_task_t *task, pend_obj_t *object, k_tick_t timeout)
|
||||
{
|
||||
readyqueue_remove(task);
|
||||
|
||||
task->pend_state = PEND_STATE_NONE;
|
||||
pend_list_add(task, object);
|
||||
|
||||
if (timeout != TOS_TIME_FOREVER) {
|
||||
tick_list_add(task, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
__KNL__ void pend_wakeup_one(pend_obj_t *object, pend_state_t state)
|
||||
{
|
||||
pend_task_wakeup(TOS_LIST_FIRST_ENTRY(&object->list, k_task_t, pend_list), state);
|
||||
}
|
||||
|
||||
__KNL__ void pend_wakeup_all(pend_obj_t *object, pend_state_t state)
|
||||
{
|
||||
k_task_t *task, *tmp;
|
||||
|
||||
TOS_LIST_FOR_EACH_ENTRY_SAFE(task, tmp, k_task_t, pend_list, &object->list) {
|
||||
pend_task_wakeup(task, state);
|
||||
}
|
||||
}
|
||||
|
||||
__KNL__ void pend_wakeup(pend_obj_t *object, pend_state_t state, opt_post_t opt)
|
||||
{
|
||||
if (opt == OPT_POST_ONE) {
|
||||
pend_wakeup_one(object, state);
|
||||
} else {
|
||||
pend_wakeup_all(object, state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_PRIORITY_MAIL_QUEUE_EN > 0u
|
||||
|
||||
__API__ k_err_t tos_prio_mail_q_create(k_prio_mail_q_t *prio_mail_q, void *pool, size_t mail_cnt, size_t mail_size)
|
||||
{
|
||||
k_err_t err;
|
||||
void *prio_q_mgr_array = K_NULL;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_mail_q);
|
||||
|
||||
prio_q_mgr_array = tos_mmheap_alloc(TOS_PRIO_Q_MGR_ARRAY_SIZE(mail_cnt));
|
||||
if (!prio_q_mgr_array) {
|
||||
return K_ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
err = tos_prio_q_create(&prio_mail_q->prio_q, prio_q_mgr_array, pool, mail_cnt, mail_size);
|
||||
if (err != K_ERR_NONE) {
|
||||
tos_mmheap_free(prio_q_mgr_array);
|
||||
return err;
|
||||
}
|
||||
|
||||
prio_mail_q->prio_q_mgr_array = prio_q_mgr_array;
|
||||
pend_object_init(&prio_mail_q->pend_obj);
|
||||
|
||||
TOS_OBJ_INIT(prio_mail_q, KNL_OBJ_TYPE_PRIORITY_MAIL_QUEUE);
|
||||
knl_object_alloc_set_static(&prio_mail_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_mail_q_destroy(k_prio_mail_q_t *prio_mail_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_mail_q);
|
||||
TOS_OBJ_VERIFY(prio_mail_q, KNL_OBJ_TYPE_PRIORITY_MAIL_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_static(&prio_mail_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
err = tos_prio_q_destroy(&prio_mail_q->prio_q);
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_wakeup_all(&prio_mail_q->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
tos_mmheap_free(prio_mail_q->prio_q_mgr_array);
|
||||
prio_mail_q->prio_q_mgr_array = K_NULL;
|
||||
|
||||
pend_object_deinit(&prio_mail_q->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(prio_mail_q);
|
||||
knl_object_alloc_reset(&prio_mail_q->knl_obj);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_mail_q_create_dyn(k_prio_mail_q_t *prio_mail_q, size_t mail_cnt, size_t mail_size)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_mail_q);
|
||||
|
||||
err = tos_prio_q_create_dyn(&prio_mail_q->prio_q, mail_cnt, mail_size);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_object_init(&prio_mail_q->pend_obj);
|
||||
|
||||
TOS_OBJ_INIT(prio_mail_q, KNL_OBJ_TYPE_PRIORITY_MAIL_QUEUE);
|
||||
knl_object_alloc_set_dynamic(&prio_mail_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_mail_q_destroy_dyn(k_prio_mail_q_t *prio_mail_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_mail_q);
|
||||
TOS_OBJ_VERIFY(prio_mail_q, KNL_OBJ_TYPE_PRIORITY_MAIL_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_dynamic(&prio_mail_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
err = tos_prio_q_destroy_dyn(&prio_mail_q->prio_q);
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_wakeup_all(&prio_mail_q->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
pend_object_deinit(&prio_mail_q->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(prio_mail_q);
|
||||
knl_object_alloc_reset(&prio_mail_q->knl_obj);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_mail_q_flush(k_prio_mail_q_t *prio_mail_q)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(prio_mail_q);
|
||||
TOS_OBJ_VERIFY(prio_mail_q, KNL_OBJ_TYPE_PRIORITY_MAIL_QUEUE);
|
||||
|
||||
return tos_prio_q_flush(&prio_mail_q->prio_q);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_mail_q_pend(k_prio_mail_q_t *prio_mail_q, void *mail_buf, size_t *mail_size, k_tick_t timeout)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(prio_mail_q);
|
||||
TOS_PTR_SANITY_CHECK(mail_buf);
|
||||
TOS_OBJ_VERIFY(prio_mail_q, KNL_OBJ_TYPE_PRIORITY_MAIL_QUEUE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (tos_prio_q_dequeue(&prio_mail_q->prio_q, mail_buf, mail_size, K_NULL) == K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (timeout == TOS_TIME_NOWAIT) {
|
||||
*mail_size = 0;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_NOWAIT;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
k_curr_task->mail = mail_buf;
|
||||
pend_task_block(k_curr_task, &prio_mail_q->pend_obj, timeout);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
err = pend_state2errno(k_curr_task->pend_state);
|
||||
if (err == K_ERR_NONE) {
|
||||
*mail_size = k_curr_task->mail_size;
|
||||
k_curr_task->mail = K_NULL;
|
||||
k_curr_task->mail_size = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
__STATIC__ void prio_mail_task_recv(k_task_t *task, void *mail_buf, size_t mail_size)
|
||||
{
|
||||
memcpy(task->mail, mail_buf, mail_size);
|
||||
task->mail_size = mail_size;
|
||||
pend_task_wakeup(task, PEND_STATE_POST);
|
||||
}
|
||||
|
||||
__STATIC__ k_err_t prio_mail_q_do_post(k_prio_mail_q_t *prio_mail_q, void *mail_buf, size_t mail_size, k_prio_t prio, opt_post_t opt)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
k_task_t *task, *tmp;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_mail_q);
|
||||
TOS_PTR_SANITY_CHECK(mail_buf);
|
||||
TOS_OBJ_VERIFY(prio_mail_q, KNL_OBJ_TYPE_PRIORITY_MAIL_QUEUE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (pend_is_nopending(&prio_mail_q->pend_obj)) {
|
||||
err = tos_prio_q_enqueue(&prio_mail_q->prio_q, mail_buf, mail_size, prio);
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (opt == OPT_POST_ONE) {
|
||||
prio_mail_task_recv(TOS_LIST_FIRST_ENTRY(&prio_mail_q->pend_obj.list, k_task_t, pend_list),
|
||||
mail_buf, mail_size);
|
||||
} else { // OPT_POST_ALL
|
||||
TOS_LIST_FOR_EACH_ENTRY_SAFE(task, tmp, k_task_t, pend_list, &prio_mail_q->pend_obj.list) {
|
||||
prio_mail_task_recv(task, mail_buf, mail_size);
|
||||
}
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_mail_q_post(k_prio_mail_q_t *prio_mail_q, void *mail_buf, size_t mail_size, k_prio_t prio)
|
||||
{
|
||||
return prio_mail_q_do_post(prio_mail_q, mail_buf, mail_size, prio, OPT_POST_ONE);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_mail_q_post_all(k_prio_mail_q_t *prio_mail_q, void *mail_buf, size_t mail_size, k_prio_t prio)
|
||||
{
|
||||
return prio_mail_q_do_post(prio_mail_q, mail_buf, mail_size, prio, OPT_POST_ALL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN > 0u
|
||||
|
||||
__API__ k_err_t tos_prio_msg_q_create(k_prio_msg_q_t *prio_msg_q, void *pool, size_t msg_cnt)
|
||||
{
|
||||
k_err_t err;
|
||||
void *prio_q_mgr_array = K_NULL;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_msg_q);
|
||||
|
||||
prio_q_mgr_array = tos_mmheap_alloc(TOS_PRIO_Q_MGR_ARRAY_SIZE(msg_cnt));
|
||||
if (!prio_q_mgr_array) {
|
||||
return K_ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
err = tos_prio_q_create(&prio_msg_q->prio_q, prio_q_mgr_array, pool, msg_cnt, sizeof(void *));
|
||||
if (err != K_ERR_NONE) {
|
||||
tos_mmheap_free(prio_q_mgr_array);
|
||||
return err;
|
||||
}
|
||||
|
||||
prio_msg_q->prio_q_mgr_array = prio_q_mgr_array;
|
||||
pend_object_init(&prio_msg_q->pend_obj);
|
||||
|
||||
TOS_OBJ_INIT(prio_msg_q, KNL_OBJ_TYPE_PRIORITY_MESSAGE_QUEUE);
|
||||
knl_object_alloc_set_static(&prio_msg_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_msg_q_destroy(k_prio_msg_q_t *prio_msg_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_msg_q);
|
||||
TOS_OBJ_VERIFY(prio_msg_q, KNL_OBJ_TYPE_PRIORITY_MESSAGE_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_static(&prio_msg_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
err = tos_prio_q_destroy(&prio_msg_q->prio_q);
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_wakeup_all(&prio_msg_q->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
tos_mmheap_free(prio_msg_q->prio_q_mgr_array);
|
||||
prio_msg_q->prio_q_mgr_array = K_NULL;
|
||||
|
||||
pend_object_deinit(&prio_msg_q->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(prio_msg_q);
|
||||
knl_object_alloc_reset(&prio_msg_q->knl_obj);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_msg_q_create_dyn(k_prio_msg_q_t *prio_msg_q, size_t msg_cnt)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_msg_q);
|
||||
|
||||
err = tos_prio_q_create_dyn(&prio_msg_q->prio_q, msg_cnt, sizeof(void *));
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_object_init(&prio_msg_q->pend_obj);
|
||||
|
||||
TOS_OBJ_INIT(prio_msg_q, KNL_OBJ_TYPE_PRIORITY_MESSAGE_QUEUE);
|
||||
knl_object_alloc_set_dynamic(&prio_msg_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_msg_q_destroy_dyn(k_prio_msg_q_t *prio_msg_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_msg_q);
|
||||
TOS_OBJ_VERIFY(prio_msg_q, KNL_OBJ_TYPE_PRIORITY_MESSAGE_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_dynamic(&prio_msg_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
err = tos_prio_q_destroy_dyn(&prio_msg_q->prio_q);
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
|
||||
pend_wakeup_all(&prio_msg_q->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
tos_mmheap_free(prio_msg_q->prio_q_mgr_array);
|
||||
prio_msg_q->prio_q_mgr_array = K_NULL;
|
||||
|
||||
pend_object_deinit(&prio_msg_q->pend_obj);
|
||||
|
||||
TOS_OBJ_DEINIT(prio_msg_q);
|
||||
knl_object_alloc_reset(&prio_msg_q->knl_obj);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_msg_q_flush(k_prio_msg_q_t *prio_msg_q)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(prio_msg_q);
|
||||
TOS_OBJ_VERIFY(prio_msg_q, KNL_OBJ_TYPE_PRIORITY_MESSAGE_QUEUE);
|
||||
|
||||
return tos_prio_q_flush(&prio_msg_q->prio_q);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_msg_q_pend(k_prio_msg_q_t *prio_msg_q, void **msg_ptr, k_tick_t timeout)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(prio_msg_q);
|
||||
TOS_PTR_SANITY_CHECK(msg_ptr);
|
||||
TOS_OBJ_VERIFY(prio_msg_q, KNL_OBJ_TYPE_PRIORITY_MESSAGE_QUEUE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (tos_prio_q_dequeue(&prio_msg_q->prio_q, msg_ptr, K_NULL, K_NULL) == K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (timeout == TOS_TIME_NOWAIT) {
|
||||
*msg_ptr = K_NULL;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_NOWAIT;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
pend_task_block(k_curr_task, &prio_msg_q->pend_obj, timeout);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
err = pend_state2errno(k_curr_task->pend_state);
|
||||
if (err == K_ERR_NONE) {
|
||||
*msg_ptr = k_curr_task->msg;
|
||||
k_curr_task->msg = K_NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
__STATIC__ void prio_msg_q_task_recv(k_task_t *task, void *msg_ptr)
|
||||
{
|
||||
task->msg = msg_ptr;
|
||||
pend_task_wakeup(task, PEND_STATE_POST);
|
||||
}
|
||||
|
||||
__STATIC__ k_err_t prio_msg_q_do_post(k_prio_msg_q_t *prio_msg_q, void *msg_ptr, k_prio_t prio, opt_post_t opt)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t err;
|
||||
k_task_t *task, *tmp;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_msg_q);
|
||||
TOS_OBJ_VERIFY(prio_msg_q, KNL_OBJ_TYPE_PRIORITY_MESSAGE_QUEUE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (pend_is_nopending(&prio_msg_q->pend_obj)) {
|
||||
err = tos_prio_q_enqueue(&prio_msg_q->prio_q, &msg_ptr, sizeof(void *), prio);
|
||||
if (err != K_ERR_NONE) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return err;
|
||||
}
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (opt == OPT_POST_ONE) {
|
||||
prio_msg_q_task_recv(TOS_LIST_FIRST_ENTRY(&prio_msg_q->pend_obj.list, k_task_t, pend_list), msg_ptr);
|
||||
} else { // OPT_POST_ALL
|
||||
TOS_LIST_FOR_EACH_ENTRY_SAFE(task, tmp, k_task_t, pend_list, &prio_msg_q->pend_obj.list) {
|
||||
prio_msg_q_task_recv(task, msg_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_msg_q_post(k_prio_msg_q_t *prio_msg_q, void *msg_ptr, k_prio_t prio)
|
||||
{
|
||||
return prio_msg_q_do_post(prio_msg_q, msg_ptr, prio, OPT_POST_ONE);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_msg_q_post_all(k_prio_msg_q_t *prio_msg_q, void *msg_ptr, k_prio_t prio)
|
||||
{
|
||||
return prio_msg_q_do_post(prio_msg_q, msg_ptr, prio, OPT_POST_ALL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,377 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__STATIC_INLINE__ void prio_q_item_copy_to(k_prio_q_t *prio_q, void *item_out, size_t *item_size, prio_q_slot_t slot)
|
||||
{
|
||||
memcpy(item_out, PRIO_Q_THE_ITEM(prio_q, slot), prio_q->item_size);
|
||||
if (item_size) {
|
||||
*item_size = prio_q->item_size;
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void prio_q_item_copy_from(k_prio_q_t *prio_q, void *item_in, prio_q_slot_t slot)
|
||||
{
|
||||
memcpy(PRIO_Q_THE_ITEM(prio_q, slot), item_in, prio_q->item_size);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void prio_q_item_increase(k_prio_q_t *prio_q)
|
||||
{
|
||||
++prio_q->total;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void prio_q_item_decrease(k_prio_q_t *prio_q)
|
||||
{
|
||||
--prio_q->total;
|
||||
}
|
||||
|
||||
__STATIC__ void prio_q_pool_mgr_init(prio_q_pool_mgr_t *pool_mgr, prio_q_pool_mgr_ent_t *pool_mgr_ent_array, size_t item_cnt)
|
||||
{
|
||||
prio_q_slot_t i;
|
||||
|
||||
pool_mgr->first_free = (prio_q_slot_t)0u;
|
||||
pool_mgr->pool_mgr_ent_array = pool_mgr_ent_array;
|
||||
|
||||
for (i = 0; i < item_cnt; ++i) {
|
||||
pool_mgr_ent_array[i].next = i + 1;
|
||||
}
|
||||
pool_mgr_ent_array[item_cnt - 1].next = PRIO_Q_POOL_SLOT_INVALID;
|
||||
}
|
||||
|
||||
__STATIC__ void prio_q_pool_mgr_reset(prio_q_pool_mgr_t *pool_mgr, size_t item_cnt)
|
||||
{
|
||||
prio_q_slot_t i;
|
||||
prio_q_pool_mgr_ent_t *pool_mgr_ent_array;
|
||||
|
||||
pool_mgr->first_free = (prio_q_slot_t)0u;
|
||||
pool_mgr_ent_array = pool_mgr->pool_mgr_ent_array;
|
||||
|
||||
for (i = 0; i < item_cnt; ++i) {
|
||||
pool_mgr_ent_array[i].next = i + 1;
|
||||
}
|
||||
pool_mgr_ent_array[item_cnt - 1].next = PRIO_Q_POOL_SLOT_INVALID;
|
||||
}
|
||||
|
||||
__STATIC__ void prio_q_pool_mgr_deinit(prio_q_pool_mgr_t *pool_mgr)
|
||||
{
|
||||
pool_mgr->first_free = (prio_q_slot_t)0u;
|
||||
pool_mgr->pool_mgr_ent_array = K_NULL;
|
||||
}
|
||||
|
||||
__STATIC__ int prio_q_mgr_entry_cmp(void *first, void *second)
|
||||
{
|
||||
prio_q_prio_mgr_ent_t *first_entry, *second_entry;
|
||||
|
||||
first_entry = (prio_q_prio_mgr_ent_t *)first;
|
||||
second_entry = (prio_q_prio_mgr_ent_t *)second;
|
||||
|
||||
// numerically bigger, actually smaller, we build a minimal binary heap here
|
||||
if (first_entry->priority < second_entry->priority) {
|
||||
return K_TRUE;
|
||||
}
|
||||
return K_FALSE;
|
||||
}
|
||||
|
||||
__STATIC__ void prio_q_prio_mgr_init(prio_q_prio_mgr_t *prio_mgr, prio_q_prio_mgr_ent_t *prio_mgr_ent_pool, size_t item_cnt)
|
||||
{
|
||||
prio_mgr->prio_mgr_ent_pool = prio_mgr_ent_pool;
|
||||
tos_bin_heap_create(&prio_mgr->prio_mgr_bin_heap, prio_mgr_ent_pool, item_cnt, sizeof(prio_q_prio_mgr_ent_t), prio_q_mgr_entry_cmp);
|
||||
}
|
||||
|
||||
__STATIC__ void prio_q_prio_mgr_reset(prio_q_prio_mgr_t *prio_mgr)
|
||||
{
|
||||
tos_bin_heap_flush(&prio_mgr->prio_mgr_bin_heap);
|
||||
}
|
||||
|
||||
__STATIC__ void prio_q_prio_mgr_deinit(prio_q_prio_mgr_t *prio_mgr)
|
||||
{
|
||||
prio_mgr->prio_mgr_ent_pool = K_NULL;
|
||||
tos_bin_heap_destroy(&prio_mgr->prio_mgr_bin_heap);
|
||||
}
|
||||
|
||||
__STATIC__ prio_q_slot_t prio_q_pool_mgr_slot_alloc(prio_q_pool_mgr_t *pool_mgr)
|
||||
{
|
||||
prio_q_slot_t fresh;
|
||||
prio_q_pool_mgr_ent_t *first_free;
|
||||
|
||||
if (pool_mgr->first_free == PRIO_Q_POOL_SLOT_INVALID) {
|
||||
return PRIO_Q_POOL_SLOT_INVALID;
|
||||
}
|
||||
|
||||
fresh = pool_mgr->first_free;
|
||||
first_free = &pool_mgr->pool_mgr_ent_array[pool_mgr->first_free];
|
||||
pool_mgr->first_free = first_free->next;
|
||||
|
||||
return fresh;
|
||||
}
|
||||
|
||||
__STATIC__ void prio_q_pool_mgr_slot_free(prio_q_pool_mgr_t *pool_mgr, prio_q_slot_t slot)
|
||||
{
|
||||
prio_q_pool_mgr_ent_t *slot_entry;
|
||||
|
||||
slot_entry = &pool_mgr->pool_mgr_ent_array[slot];
|
||||
slot_entry->next = pool_mgr->first_free;
|
||||
pool_mgr->first_free = slot;
|
||||
}
|
||||
|
||||
__STATIC__ void prio_q_prio_mgr_slot_enqueue(prio_q_prio_mgr_t *prio_mgr, prio_q_slot_t slot, k_prio_t prio)
|
||||
{
|
||||
k_err_t err;
|
||||
prio_q_prio_mgr_ent_t prio_mgr_entry;
|
||||
|
||||
prio_mgr_entry.priority = prio;
|
||||
prio_mgr_entry.slot = slot;
|
||||
|
||||
err = tos_bin_heap_push(&prio_mgr->prio_mgr_bin_heap, &prio_mgr_entry, sizeof(prio_q_prio_mgr_ent_t));
|
||||
TOS_ASSERT(err == K_ERR_NONE);
|
||||
}
|
||||
|
||||
__STATIC__ prio_q_slot_t prio_q_prio_mgr_slot_dequeue(prio_q_prio_mgr_t *prio_mgr, k_prio_t *prio)
|
||||
{
|
||||
k_err_t err;
|
||||
size_t dummy;
|
||||
prio_q_prio_mgr_ent_t prio_mgr_entry;
|
||||
|
||||
err = tos_bin_heap_pop(&prio_mgr->prio_mgr_bin_heap, &prio_mgr_entry, &dummy);
|
||||
TOS_ASSERT(err == K_ERR_NONE);
|
||||
TOS_ASSERT(dummy == sizeof(prio_q_prio_mgr_ent_t));
|
||||
|
||||
if (prio) {
|
||||
*prio = prio_mgr_entry.priority;
|
||||
}
|
||||
|
||||
return prio_mgr_entry.slot;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_q_create(k_prio_q_t *prio_q, void *mgr_array, void *pool, size_t item_cnt, size_t item_size)
|
||||
{
|
||||
prio_q_pool_mgr_ent_t *pool_mgr_ent_array;
|
||||
prio_q_prio_mgr_ent_t *prio_mgr_ent_pool;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_q);
|
||||
TOS_PTR_SANITY_CHECK(mgr_array);
|
||||
TOS_PTR_SANITY_CHECK(pool);
|
||||
|
||||
pool_mgr_ent_array = (prio_q_pool_mgr_ent_t *)mgr_array;
|
||||
prio_mgr_ent_pool = (prio_q_prio_mgr_ent_t *)((uint8_t *)mgr_array + PRIO_Q_POOL_MGR_ENT_ARRAY_SIZE(item_cnt));
|
||||
|
||||
prio_q_pool_mgr_init(&prio_q->pool_mgr, pool_mgr_ent_array, item_cnt);
|
||||
prio_q_prio_mgr_init(&prio_q->prio_mgr, prio_mgr_ent_pool, item_cnt);
|
||||
|
||||
prio_q->total = 0;
|
||||
prio_q->item_size = item_size;
|
||||
prio_q->item_cnt = item_cnt;
|
||||
prio_q->mgr_pool = (uint8_t *)mgr_array;
|
||||
prio_q->data_pool = (uint8_t *)pool;
|
||||
|
||||
TOS_OBJ_INIT(prio_q, KNL_OBJ_TYPE_PRIORITY_QUEUE);
|
||||
knl_object_alloc_set_static(&prio_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_q_destroy(k_prio_q_t *prio_q)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(prio_q);
|
||||
TOS_OBJ_VERIFY(prio_q, KNL_OBJ_TYPE_PRIORITY_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_static(&prio_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
prio_q_pool_mgr_deinit(&prio_q->pool_mgr);
|
||||
prio_q_prio_mgr_deinit(&prio_q->prio_mgr);
|
||||
|
||||
prio_q->total = 0;
|
||||
prio_q->item_size = 0;
|
||||
prio_q->item_cnt = 0;
|
||||
prio_q->mgr_pool = K_NULL;
|
||||
prio_q->data_pool = K_NULL;
|
||||
|
||||
TOS_OBJ_DEINIT(prio_q);
|
||||
knl_object_alloc_reset(&prio_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_q_create_dyn(k_prio_q_t *prio_q, size_t item_cnt, size_t item_size)
|
||||
{
|
||||
k_err_t err;
|
||||
void *mgr_pool, *data_pool;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_q);
|
||||
|
||||
mgr_pool = tos_mmheap_alloc(TOS_PRIO_Q_MGR_ARRAY_SIZE(item_cnt));
|
||||
if (!mgr_pool) {
|
||||
return K_ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
data_pool = tos_mmheap_alloc(item_cnt * item_size);
|
||||
if (!data_pool) {
|
||||
tos_mmheap_free(mgr_pool);
|
||||
return K_ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
err = tos_prio_q_create(prio_q, mgr_pool, data_pool, item_cnt, item_size);
|
||||
if (err != K_ERR_NONE) {
|
||||
tos_mmheap_free(data_pool);
|
||||
tos_mmheap_free(mgr_pool);
|
||||
}
|
||||
|
||||
knl_object_alloc_set_dynamic(&prio_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_q_destroy_dyn(k_prio_q_t *prio_q)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(prio_q);
|
||||
TOS_OBJ_VERIFY(prio_q, KNL_OBJ_TYPE_PRIORITY_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_dynamic(&prio_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
prio_q_pool_mgr_deinit(&prio_q->pool_mgr);
|
||||
prio_q_prio_mgr_deinit(&prio_q->prio_mgr);
|
||||
|
||||
tos_mmheap_free(prio_q->mgr_pool);
|
||||
tos_mmheap_free(prio_q->data_pool);
|
||||
|
||||
prio_q->total = 0;
|
||||
prio_q->item_size = 0;
|
||||
prio_q->item_cnt = 0;
|
||||
prio_q->mgr_pool = K_NULL;
|
||||
prio_q->data_pool = K_NULL;
|
||||
|
||||
TOS_OBJ_DEINIT(prio_q);
|
||||
knl_object_alloc_reset(&prio_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__STATIC__ void prio_q_do_enqueue(k_prio_q_t *prio_q, void *item, prio_q_slot_t slot, k_prio_t prio)
|
||||
{
|
||||
prio_q_item_copy_from(prio_q, item, slot);
|
||||
prio_q_prio_mgr_slot_enqueue(&prio_q->prio_mgr, slot, prio);
|
||||
prio_q_item_increase(prio_q);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_q_enqueue(k_prio_q_t *prio_q, void *item, size_t item_size, k_prio_t prio)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
prio_q_slot_t the_slot;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_q);
|
||||
TOS_PTR_SANITY_CHECK(item);
|
||||
TOS_OBJ_VERIFY(prio_q, KNL_OBJ_TYPE_PRIORITY_QUEUE);
|
||||
|
||||
if (item_size != prio_q->item_size) {
|
||||
return K_ERR_PRIO_Q_ITEM_SIZE_NOT_MATCH;
|
||||
}
|
||||
|
||||
if (tos_prio_q_is_full(prio_q)) {
|
||||
return K_ERR_PRIO_Q_FULL;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
the_slot = prio_q_pool_mgr_slot_alloc(&prio_q->pool_mgr);
|
||||
TOS_ASSERT(the_slot != PRIO_Q_POOL_SLOT_INVALID);
|
||||
prio_q_do_enqueue(prio_q, item, the_slot, prio);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__STATIC__ void prio_q_do_dequeue(k_prio_q_t *prio_q, void *item, size_t *item_size, prio_q_slot_t slot)
|
||||
{
|
||||
prio_q_pool_mgr_slot_free(&prio_q->pool_mgr, slot);
|
||||
prio_q_item_copy_to(prio_q, item, item_size, slot);
|
||||
prio_q_item_decrease(prio_q);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_q_dequeue(k_prio_q_t *prio_q, void *item, size_t *item_size, k_prio_t *prio)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
prio_q_slot_t the_slot;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_q);
|
||||
TOS_PTR_SANITY_CHECK(item);
|
||||
TOS_OBJ_VERIFY(prio_q, KNL_OBJ_TYPE_PRIORITY_QUEUE);
|
||||
|
||||
if (tos_prio_q_is_empty(prio_q)) {
|
||||
return K_ERR_PRIO_Q_EMPTY;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
the_slot = prio_q_prio_mgr_slot_dequeue(&prio_q->prio_mgr, prio);
|
||||
prio_q_do_dequeue(prio_q, item, item_size, the_slot);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_prio_q_flush(k_prio_q_t *prio_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(prio_q);
|
||||
TOS_OBJ_VERIFY(prio_q, KNL_OBJ_TYPE_PRIORITY_QUEUE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
prio_q_pool_mgr_reset(&prio_q->pool_mgr, prio_q->item_cnt);
|
||||
prio_q_prio_mgr_reset(&prio_q->prio_mgr);
|
||||
prio_q->total = 0;
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ int tos_prio_q_is_empty(k_prio_q_t *prio_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
int is_empty = K_FALSE;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(prio_q, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(prio_q, KNL_OBJ_TYPE_PRIORITY_QUEUE, K_FALSE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
is_empty = (prio_q->total == 0);
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return is_empty;
|
||||
}
|
||||
|
||||
__API__ int tos_prio_q_is_full(k_prio_q_t *prio_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
int is_full = K_FALSE;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(prio_q, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(prio_q, KNL_OBJ_TYPE_PRIORITY_QUEUE, K_FALSE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
is_full = (prio_q->total == prio_q->item_cnt);
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return is_full;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__STATIC_INLINE__ void ring_q_item_copy_to(k_ring_q_t *ring_q, void *item_out, size_t *item_size)
|
||||
{
|
||||
memcpy(item_out, RING_HEAD_ITEM(ring_q), ring_q->item_size);
|
||||
if (item_size) {
|
||||
*item_size = ring_q->item_size;
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void ring_q_item_copy_from(k_ring_q_t *ring_q, void *item_in)
|
||||
{
|
||||
memcpy(RING_TAIL_ITEM(ring_q), item_in, ring_q->item_size);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void ring_q_item_increase(k_ring_q_t *ring_q)
|
||||
{
|
||||
ring_q->tail = RING_NEXT(ring_q, ring_q->tail);
|
||||
++ring_q->total;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void ring_q_item_decrease(k_ring_q_t *ring_q)
|
||||
{
|
||||
ring_q->head = RING_NEXT(ring_q, ring_q->head);
|
||||
--ring_q->total;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_ring_q_create(k_ring_q_t *ring_q, void *pool, size_t item_cnt, size_t item_size)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(ring_q);
|
||||
TOS_PTR_SANITY_CHECK(pool);
|
||||
|
||||
ring_q->head = 0u;
|
||||
ring_q->tail = 0u;
|
||||
ring_q->total = 0;
|
||||
|
||||
ring_q->pool = (uint8_t *)pool;
|
||||
ring_q->item_size = item_size;
|
||||
ring_q->item_cnt = item_cnt;
|
||||
|
||||
TOS_OBJ_INIT(ring_q, KNL_OBJ_TYPE_RING_QUEUE);
|
||||
knl_object_alloc_set_static(&ring_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_ring_q_destroy(k_ring_q_t *ring_q)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(ring_q);
|
||||
TOS_OBJ_VERIFY(ring_q, KNL_OBJ_TYPE_RING_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_static(&ring_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
ring_q->head = 0u;
|
||||
ring_q->tail = 0u;
|
||||
ring_q->total = 0;
|
||||
|
||||
ring_q->pool = K_NULL;
|
||||
ring_q->item_size = 0u;
|
||||
ring_q->item_cnt = 0u;
|
||||
|
||||
TOS_OBJ_DEINIT(ring_q);
|
||||
knl_object_alloc_reset(&ring_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_ring_q_create_dyn(k_ring_q_t *ring_q, size_t item_cnt, size_t item_size)
|
||||
{
|
||||
void *pool;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(ring_q);
|
||||
|
||||
pool = tos_mmheap_alloc(item_cnt * item_size);
|
||||
if (!pool) {
|
||||
return K_ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
ring_q->head = 0u;
|
||||
ring_q->tail = 0u;
|
||||
ring_q->total = 0;
|
||||
|
||||
ring_q->pool = (uint8_t *)pool;
|
||||
ring_q->item_size = item_size;
|
||||
ring_q->item_cnt = item_cnt;
|
||||
|
||||
TOS_OBJ_INIT(ring_q, KNL_OBJ_TYPE_RING_QUEUE);
|
||||
knl_object_alloc_set_dynamic(&ring_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_ring_q_destroy_dyn(k_ring_q_t *ring_q)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(ring_q);
|
||||
TOS_OBJ_VERIFY(ring_q, KNL_OBJ_TYPE_RING_QUEUE);
|
||||
|
||||
if (!knl_object_alloc_is_dynamic(&ring_q->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
|
||||
tos_mmheap_free(ring_q->pool);
|
||||
|
||||
ring_q->head = 0u;
|
||||
ring_q->tail = 0u;
|
||||
ring_q->total = 0;
|
||||
|
||||
ring_q->pool = K_NULL;
|
||||
ring_q->item_size = 0u;
|
||||
ring_q->item_cnt = 0u;
|
||||
|
||||
TOS_OBJ_DEINIT(ring_q);
|
||||
knl_object_alloc_reset(&ring_q->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_ring_q_enqueue(k_ring_q_t *ring_q, void *item, size_t item_size)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(ring_q);
|
||||
TOS_PTR_SANITY_CHECK(item);
|
||||
TOS_OBJ_VERIFY(ring_q, KNL_OBJ_TYPE_RING_QUEUE);
|
||||
|
||||
if (item_size != ring_q->item_size) {
|
||||
return K_ERR_RING_Q_ITEM_SIZE_NOT_MATCH;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (tos_ring_q_is_full(ring_q)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_RING_Q_FULL;
|
||||
}
|
||||
|
||||
ring_q_item_copy_from(ring_q, item);
|
||||
ring_q_item_increase(ring_q);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_ring_q_dequeue(k_ring_q_t *ring_q, void *item, size_t *item_size)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(ring_q);
|
||||
TOS_PTR_SANITY_CHECK(item);
|
||||
TOS_OBJ_VERIFY(ring_q, KNL_OBJ_TYPE_RING_QUEUE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (tos_ring_q_is_empty(ring_q)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_RING_Q_EMPTY;
|
||||
}
|
||||
|
||||
ring_q_item_copy_to(ring_q, item, item_size);
|
||||
ring_q_item_decrease(ring_q);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_ring_q_flush(k_ring_q_t *ring_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(ring_q);
|
||||
TOS_OBJ_VERIFY(ring_q, KNL_OBJ_TYPE_RING_QUEUE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
ring_q->head = 0u;
|
||||
ring_q->tail = 0u;
|
||||
ring_q->total = 0;
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ int tos_ring_q_is_empty(k_ring_q_t *ring_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
int is_empty = K_FALSE;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(ring_q, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(ring_q, KNL_OBJ_TYPE_RING_QUEUE, K_FALSE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
is_empty = (ring_q->total == 0 ? K_TRUE : K_FALSE);
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return is_empty;
|
||||
}
|
||||
|
||||
__API__ int tos_ring_q_is_full(k_ring_q_t *ring_q)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
int is_full = K_FALSE;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(ring_q, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(ring_q, KNL_OBJ_TYPE_RING_QUEUE, K_FALSE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
is_full = (ring_q->total == ring_q->item_cnt ? K_TRUE : K_FALSE);
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return is_full;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_ROUND_ROBIN_EN > 0u
|
||||
|
||||
__API__ void tos_robin_default_timeslice_config(k_timeslice_t default_timeslice)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (default_timeslice > (k_timeslice_t)0u) {
|
||||
k_robin_default_timeslice = default_timeslice;
|
||||
} else {
|
||||
k_robin_default_timeslice = TOS_CFG_CPU_TICK_PER_SECOND / 10;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__API__ void tos_robin_timeslice_set(k_task_t *task, k_timeslice_t timeslice)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
if (!task) {
|
||||
task = k_curr_task;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (timeslice == (k_timeslice_t)0u) {
|
||||
task->timeslice_reload = k_robin_default_timeslice;
|
||||
} else {
|
||||
task->timeslice_reload = timeslice;
|
||||
}
|
||||
|
||||
if (task->timeslice_reload > task->timeslice) {
|
||||
task->timeslice = task->timeslice_reload;
|
||||
}
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__KNL__ void robin_sched(k_prio_t prio)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_task_t *task;
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
task = readyqueue_first_task_get(prio);
|
||||
if (!task || knl_is_idle(task)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
if (readyqueue_is_prio_onlyone(prio)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
if (task->timeslice > (k_timeslice_t)0u) {
|
||||
--task->timeslice;
|
||||
}
|
||||
|
||||
if (task->timeslice > (k_timeslice_t)0u) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
readyqueue_move_head_to_tail(k_curr_task->prio);
|
||||
|
||||
task = readyqueue_first_task_get(prio);
|
||||
if (task->timeslice_reload == (k_timeslice_t)0u) {
|
||||
task->timeslice = k_robin_default_timeslice;
|
||||
} else {
|
||||
task->timeslice = task->timeslice_reload;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if (TOS_CFG_SEM_EN > 0u) && (TOS_CFG_MUTEX_EN > 0u)
|
||||
|
||||
__API__ k_err_t tos_rwlock_create(k_rwlock_t *rwlock)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(rwlock);
|
||||
|
||||
err = tos_sem_create(&rwlock->signal, 0u);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = tos_mutex_create(&rwlock->lock);
|
||||
if (err != K_ERR_NONE) {
|
||||
tos_sem_destroy(&rwlock->signal);
|
||||
return err;
|
||||
}
|
||||
|
||||
rwlock->n_readers = (rw_cnt_t)0u;
|
||||
rwlock->n_writers = (rw_cnt_t)0u;
|
||||
rwlock->is_writting = K_FALSE;
|
||||
TOS_OBJ_INIT(rwlock, KNL_OBJ_TYPE_RWLOCK);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_rwlock_destroy(k_rwlock_t *rwlock)
|
||||
{
|
||||
k_err_t err0, err1;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(rwlock);
|
||||
TOS_OBJ_VERIFY(rwlock, KNL_OBJ_TYPE_RWLOCK);
|
||||
|
||||
err0 = tos_sem_destroy(&rwlock->signal);
|
||||
err1 = tos_mutex_destroy(&rwlock->lock);
|
||||
|
||||
rwlock->n_readers = (rw_cnt_t)0u;
|
||||
rwlock->n_writers = (rw_cnt_t)0u;
|
||||
rwlock->is_writting = K_FALSE;
|
||||
TOS_OBJ_DEINIT(rwlock);
|
||||
|
||||
if (err0 != K_ERR_NONE) {
|
||||
return err0;
|
||||
}
|
||||
|
||||
return err1;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_rwlock_rpend_timed(k_rwlock_t *rwlock, k_tick_t timeout)
|
||||
{
|
||||
k_err_t err;
|
||||
k_stopwatch_t stopwatch;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(rwlock);
|
||||
TOS_OBJ_VERIFY(rwlock, KNL_OBJ_TYPE_RWLOCK);
|
||||
|
||||
if (timeout != TOS_TIME_FOREVER) {
|
||||
tos_stopwatch_create(&stopwatch);
|
||||
tos_stopwatch_countdown(&stopwatch, timeout);
|
||||
}
|
||||
|
||||
err = tos_mutex_pend_timed(&rwlock->lock, timeout);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rwlock->n_readers == (rw_cnt_t)-1) {
|
||||
/* number of reader reachs limit */
|
||||
return K_ERR_RWLOCK_READERS_TO_MANY;
|
||||
}
|
||||
|
||||
if (rwlock->n_writers == 0u && !rwlock->is_writting) {
|
||||
/* no writer is now holding or waiting to hold the lock */
|
||||
++rwlock->n_readers;
|
||||
tos_mutex_post(&rwlock->lock);
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (timeout != TOS_TIME_FOREVER) {
|
||||
timeout = tos_stopwatch_remain(&stopwatch);
|
||||
if (timeout == 0u) {
|
||||
timeout = 1u;
|
||||
}
|
||||
}
|
||||
|
||||
while (rwlock->n_writers > 0u || rwlock->is_writting) {
|
||||
/* util no one is writting or waiting to hold the lock */
|
||||
err = tos_sem_pend(&rwlock->signal, timeout);
|
||||
if (err != K_ERR_NONE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout != TOS_TIME_FOREVER) {
|
||||
timeout = tos_stopwatch_remain(&stopwatch);
|
||||
if (timeout == 0u) {
|
||||
err = K_ERR_PEND_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tos_mutex_post(&rwlock->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_rwlock_rpend(k_rwlock_t *rwlock)
|
||||
{
|
||||
return tos_rwlock_rpend_timed(rwlock, TOS_TIME_FOREVER);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_rwlock_rpend_try(k_rwlock_t *rwlock)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(rwlock);
|
||||
TOS_OBJ_VERIFY(rwlock, KNL_OBJ_TYPE_RWLOCK);
|
||||
|
||||
err = tos_mutex_pend_timed(&rwlock->lock, TOS_TIME_NOWAIT);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rwlock->n_readers == (rw_cnt_t)-1) {
|
||||
/* number of reader reachs limit */
|
||||
return K_ERR_RWLOCK_READERS_TO_MANY;
|
||||
}
|
||||
|
||||
if (rwlock->n_writers == 0u && !rwlock->is_writting) {
|
||||
/* no writer is holding or waiting to hold the lock */
|
||||
++rwlock->n_readers;
|
||||
tos_mutex_post(&rwlock->lock);
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
/* the rwlock is held by other writters */
|
||||
tos_mutex_post(&rwlock->lock);
|
||||
return K_ERR_RWLOCK_IS_WRITTING;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_rwlock_wpend_timed(k_rwlock_t *rwlock, k_tick_t timeout)
|
||||
{
|
||||
k_err_t err;
|
||||
k_stopwatch_t stopwatch;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(rwlock);
|
||||
TOS_OBJ_VERIFY(rwlock, KNL_OBJ_TYPE_RWLOCK);
|
||||
|
||||
if (timeout != TOS_TIME_FOREVER) {
|
||||
tos_stopwatch_create(&stopwatch);
|
||||
tos_stopwatch_countdown(&stopwatch, timeout);
|
||||
}
|
||||
|
||||
err = tos_mutex_pend_timed(&rwlock->lock, timeout);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rwlock->n_writers == (rw_cnt_t)-1) {
|
||||
/* number of waitting writer reachs limit */
|
||||
return K_ERR_RWLOCK_WAITING_WRITERS_TO_MANY;
|
||||
}
|
||||
|
||||
++rwlock->n_writers;
|
||||
|
||||
if (timeout != TOS_TIME_FOREVER) {
|
||||
timeout = tos_stopwatch_remain(&stopwatch);
|
||||
if (timeout == 0u) {
|
||||
timeout = 1u;
|
||||
}
|
||||
}
|
||||
|
||||
while (rwlock->n_readers > 0u || rwlock->is_writting) {
|
||||
/* until no one is writting or reading */
|
||||
err = tos_sem_pend(&rwlock->signal, timeout);
|
||||
if (err != K_ERR_NONE) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout != TOS_TIME_FOREVER) {
|
||||
timeout = tos_stopwatch_remain(&stopwatch);
|
||||
if (timeout == 0u) {
|
||||
err = K_ERR_PEND_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err == K_ERR_NONE) {
|
||||
/* we hold the wlock now */
|
||||
rwlock->is_writting = K_TRUE;
|
||||
} else {
|
||||
tos_sem_post_all(&rwlock->signal);
|
||||
}
|
||||
|
||||
--rwlock->n_writers;
|
||||
|
||||
tos_mutex_post(&rwlock->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_rwlock_wpend(k_rwlock_t *rwlock)
|
||||
{
|
||||
return tos_rwlock_wpend_timed(rwlock, TOS_TIME_FOREVER);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_rwlock_wpend_try(k_rwlock_t *rwlock)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(rwlock);
|
||||
TOS_OBJ_VERIFY(rwlock, KNL_OBJ_TYPE_RWLOCK);
|
||||
|
||||
err = tos_mutex_pend_timed(&rwlock->lock, TOS_TIME_NOWAIT);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rwlock->n_readers > 0u) {
|
||||
err = K_ERR_RWLOCK_IS_READING;
|
||||
} else if (rwlock->is_writting) {
|
||||
err = K_ERR_RWLOCK_IS_WRITTING;
|
||||
} else {
|
||||
rwlock->is_writting = K_TRUE;
|
||||
}
|
||||
|
||||
tos_mutex_post(&rwlock->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_rwlock_rpost(k_rwlock_t *rwlock)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(rwlock);
|
||||
TOS_OBJ_VERIFY(rwlock, KNL_OBJ_TYPE_RWLOCK);
|
||||
|
||||
err = tos_mutex_pend(&rwlock->lock);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rwlock->n_readers == 0u) {
|
||||
err = K_ERR_RWLOCK_NOT_READING;
|
||||
} else {
|
||||
--rwlock->n_readers;
|
||||
if (rwlock->n_readers == 0u) {
|
||||
err = tos_sem_post_all(&rwlock->signal);
|
||||
}
|
||||
}
|
||||
|
||||
tos_mutex_post(&rwlock->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_rwlock_wpost(k_rwlock_t *rwlock)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(rwlock);
|
||||
TOS_OBJ_VERIFY(rwlock, KNL_OBJ_TYPE_RWLOCK);
|
||||
|
||||
err = tos_mutex_pend(&rwlock->lock);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!rwlock->is_writting) {
|
||||
err = K_ERR_RWLOCK_NOT_WRITTING;
|
||||
} else {
|
||||
rwlock->is_writting = K_FALSE;
|
||||
err = tos_sem_post_all(&rwlock->signal);
|
||||
}
|
||||
|
||||
tos_mutex_post(&rwlock->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_rwlock_post(k_rwlock_t *rwlock)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(rwlock);
|
||||
TOS_OBJ_VERIFY(rwlock, KNL_OBJ_TYPE_RWLOCK);
|
||||
|
||||
err = tos_mutex_pend(&rwlock->lock);
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rwlock->n_readers > 0u) {
|
||||
--rwlock->n_readers;
|
||||
if (rwlock->n_readers == 0u) {
|
||||
err = tos_sem_post_all(&rwlock->signal);
|
||||
}
|
||||
} else if (rwlock->is_writting) {
|
||||
rwlock->is_writting = K_FALSE;
|
||||
err = tos_sem_post_all(&rwlock->signal);
|
||||
} else {
|
||||
err = K_ERR_RWLOCK_NOT_TAKEN;
|
||||
}
|
||||
|
||||
tos_mutex_post(&rwlock->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__STATIC__ k_prio_t readyqueue_prio_highest_get(void)
|
||||
{
|
||||
uint32_t *tbl;
|
||||
k_prio_t prio;
|
||||
|
||||
prio = 0;
|
||||
tbl = &k_rdyq.prio_mask[0];
|
||||
|
||||
while (*tbl == 0) {
|
||||
prio += K_PRIO_TBL_SLOT_SIZE;
|
||||
++tbl;
|
||||
}
|
||||
prio += tos_cpu_clz(*tbl);
|
||||
return prio;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void readyqueue_prio_insert(k_prio_t prio)
|
||||
{
|
||||
k_rdyq.prio_mask[K_PRIO_NDX(prio)] |= K_PRIO_BIT(prio);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void readyqueue_prio_remove(k_prio_t prio)
|
||||
{
|
||||
k_rdyq.prio_mask[K_PRIO_NDX(prio)] &= ~K_PRIO_BIT(prio);
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void readyqueue_prio_mark(k_prio_t prio)
|
||||
{
|
||||
readyqueue_prio_insert(prio);
|
||||
|
||||
if (prio < k_rdyq.highest_prio) {
|
||||
k_rdyq.highest_prio = prio;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* when this function involved, must be at least one task in the task list of the certain priority
|
||||
*/
|
||||
__KNL__ int readyqueue_is_prio_onlyone(k_prio_t prio)
|
||||
{
|
||||
k_list_t *task_list;
|
||||
k_task_t *task;
|
||||
|
||||
task_list = &k_rdyq.task_list_head[prio];
|
||||
task = TOS_LIST_FIRST_ENTRY(task_list, k_task_t, pend_list);
|
||||
return task->pend_list.next == task_list;
|
||||
}
|
||||
|
||||
__KNL__ k_task_t *readyqueue_first_task_get(k_prio_t prio)
|
||||
{
|
||||
k_list_t *task_list;
|
||||
|
||||
task_list = &k_rdyq.task_list_head[prio];
|
||||
return TOS_LIST_FIRST_ENTRY_OR_NULL(task_list, k_task_t, pend_list);
|
||||
}
|
||||
|
||||
__KNL__ k_task_t *readyqueue_highest_ready_task_get(void)
|
||||
{
|
||||
k_list_t *task_list;
|
||||
|
||||
task_list = &k_rdyq.task_list_head[k_rdyq.highest_prio];
|
||||
return TOS_LIST_FIRST_ENTRY(task_list, k_task_t, pend_list);
|
||||
}
|
||||
|
||||
__KNL__ void readyqueue_init(void)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
k_rdyq.highest_prio = TOS_CFG_TASK_PRIO_MAX;
|
||||
|
||||
for (i = 0; i < TOS_CFG_TASK_PRIO_MAX; ++i) {
|
||||
tos_list_init(&k_rdyq.task_list_head[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < K_PRIO_TBL_SIZE; ++i) {
|
||||
k_rdyq.prio_mask[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
__KNL__ void readyqueue_add_head(k_task_t *task)
|
||||
{
|
||||
k_prio_t task_prio;
|
||||
k_list_t *task_list;
|
||||
|
||||
task_prio = task->prio;
|
||||
task_list = &k_rdyq.task_list_head[task_prio];
|
||||
|
||||
if (tos_list_empty(task_list)) {
|
||||
readyqueue_prio_mark(task_prio);
|
||||
}
|
||||
|
||||
tos_list_add(&task->pend_list, task_list);
|
||||
}
|
||||
|
||||
__KNL__ void readyqueue_add_tail(k_task_t *task)
|
||||
{
|
||||
k_prio_t task_prio;
|
||||
k_list_t *task_list;
|
||||
|
||||
task_prio = task->prio;
|
||||
task_list = &k_rdyq.task_list_head[task_prio];
|
||||
|
||||
if (tos_list_empty(task_list)) {
|
||||
readyqueue_prio_mark(task_prio);
|
||||
}
|
||||
|
||||
tos_list_add_tail(&task->pend_list, task_list);
|
||||
}
|
||||
|
||||
__KNL__ void readyqueue_add(k_task_t *task)
|
||||
{
|
||||
if (task->prio == k_curr_task->prio) {
|
||||
readyqueue_add_tail(task);
|
||||
} else {
|
||||
readyqueue_add_head(task);
|
||||
}
|
||||
}
|
||||
|
||||
__KNL__ void readyqueue_remove(k_task_t *task)
|
||||
{
|
||||
k_prio_t task_prio;
|
||||
k_list_t *task_list;
|
||||
|
||||
// protect the idle task.
|
||||
if (knl_is_idle(task)) {
|
||||
return;
|
||||
}
|
||||
|
||||
task_prio = task->prio;
|
||||
task_list = &k_rdyq.task_list_head[task_prio];
|
||||
|
||||
tos_list_del(&task->pend_list);
|
||||
|
||||
if (tos_list_empty(task_list)) {
|
||||
readyqueue_prio_remove(task_prio);
|
||||
}
|
||||
|
||||
if (task_prio == k_rdyq.highest_prio) {
|
||||
k_rdyq.highest_prio = readyqueue_prio_highest_get();
|
||||
}
|
||||
}
|
||||
|
||||
__KNL__ void readyqueue_move_head_to_tail(k_prio_t prio)
|
||||
{
|
||||
k_list_t *task_list;
|
||||
|
||||
task_list = &k_rdyq.task_list_head[prio];
|
||||
|
||||
if (!tos_list_empty(task_list)) {
|
||||
tos_list_move_tail(task_list->next, task_list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_SEM_EN > 0u
|
||||
|
||||
__API__ k_err_t tos_sem_create_max(k_sem_t *sem, k_sem_cnt_t init_count, k_sem_cnt_t max_count)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(sem);
|
||||
|
||||
if (unlikely(init_count > max_count)) {
|
||||
init_count = max_count;
|
||||
}
|
||||
|
||||
sem->count = init_count;
|
||||
sem->count_max = max_count;
|
||||
|
||||
pend_object_init(&sem->pend_obj);
|
||||
TOS_OBJ_INIT(sem, KNL_OBJ_TYPE_SEMAPHORE);
|
||||
|
||||
knl_object_alloc_set_static(&sem->knl_obj);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_sem_create(k_sem_t *sem, k_sem_cnt_t init_count)
|
||||
{
|
||||
return tos_sem_create_max(sem, init_count, (k_sem_cnt_t)-1);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_sem_create_max_dyn(k_sem_t **sem, k_sem_cnt_t init_count, k_sem_cnt_t max_count)
|
||||
{
|
||||
k_sem_t *the_sem;
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(sem);
|
||||
|
||||
if (unlikely(init_count > max_count)) {
|
||||
init_count = max_count;
|
||||
}
|
||||
|
||||
the_sem = tos_mmheap_calloc(1, sizeof(k_sem_t));
|
||||
if (!the_sem) {
|
||||
return K_ERR_SEM_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
the_sem->count = init_count;
|
||||
the_sem->count_max = max_count;
|
||||
|
||||
pend_object_init(&the_sem->pend_obj);
|
||||
TOS_OBJ_INIT(the_sem, KNL_OBJ_TYPE_SEMAPHORE);
|
||||
|
||||
knl_object_alloc_set_dynamic(&the_sem->knl_obj);
|
||||
|
||||
*sem = the_sem;
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_sem_create_dyn(k_sem_t **sem, k_sem_cnt_t init_count)
|
||||
{
|
||||
return tos_sem_create_max_dyn(sem, init_count, (k_sem_cnt_t)-1);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_sem_destroy(k_sem_t *sem)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(sem);
|
||||
TOS_OBJ_VERIFY(sem, KNL_OBJ_TYPE_SEMAPHORE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
pend_wakeup_all(&sem->pend_obj, PEND_STATE_DESTROY);
|
||||
|
||||
pend_object_deinit(&sem->pend_obj);
|
||||
|
||||
if (knl_object_alloc_is_dynamic(&sem->knl_obj)) {
|
||||
TOS_OBJ_DEINIT(sem);
|
||||
tos_mmheap_free(sem);
|
||||
} else {
|
||||
TOS_OBJ_DEINIT(sem);
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__STATIC__ k_err_t sem_do_post(k_sem_t *sem, opt_post_t opt)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(sem);
|
||||
TOS_OBJ_VERIFY(sem, KNL_OBJ_TYPE_SEMAPHORE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (sem->count == sem->count_max) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_SEM_OVERFLOW;
|
||||
}
|
||||
|
||||
if (pend_is_nopending(&sem->pend_obj)) {
|
||||
++sem->count;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
pend_wakeup(&sem->pend_obj, PEND_STATE_POST, opt);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_sem_post(k_sem_t *sem)
|
||||
{
|
||||
return sem_do_post(sem, OPT_POST_ONE);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_sem_post_all(k_sem_t *sem)
|
||||
{
|
||||
return sem_do_post(sem, OPT_POST_ALL);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_sem_pend(k_sem_t *sem, k_tick_t timeout)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(sem);
|
||||
TOS_OBJ_VERIFY(sem, KNL_OBJ_TYPE_SEMAPHORE);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (sem->count > (k_sem_cnt_t)0u) {
|
||||
--sem->count;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (timeout == TOS_TIME_NOWAIT) { // no wait, return immediately
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_NOWAIT;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_PEND_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
pend_task_block(k_curr_task, &sem->pend_obj, timeout);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return pend_state2errno(k_curr_task->pend_state);
|
||||
}
|
||||
|
||||
#endif // TOS_CFG_SEM_EN
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__API__ k_err_t tos_stopwatch_create(k_stopwatch_t *stopwatch)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(stopwatch);
|
||||
|
||||
stopwatch->until = 0u;
|
||||
TOS_OBJ_INIT(stopwatch, KNL_OBJ_TYPE_STOPWATCH);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_stopwatch_destroy(k_stopwatch_t *stopwatch)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(stopwatch);
|
||||
TOS_OBJ_VERIFY(stopwatch, KNL_OBJ_TYPE_STOPWATCH);
|
||||
|
||||
stopwatch->until = 0u;
|
||||
TOS_OBJ_DEINIT(stopwatch);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_stopwatch_countdown(k_stopwatch_t *stopwatch, k_tick_t tick)
|
||||
{
|
||||
k_tick_t now;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(stopwatch);
|
||||
TOS_OBJ_VERIFY(stopwatch, KNL_OBJ_TYPE_STOPWATCH);
|
||||
|
||||
now = tos_systick_get();
|
||||
stopwatch->until = now + tick;
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_stopwatch_countdown_ms(k_stopwatch_t *stopwatch, k_time_t millisec)
|
||||
{
|
||||
k_tick_t tick;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(stopwatch);
|
||||
TOS_OBJ_VERIFY(stopwatch, KNL_OBJ_TYPE_STOPWATCH);
|
||||
|
||||
tick = tos_millisec2tick(millisec);
|
||||
return tos_stopwatch_countdown(stopwatch, tick);
|
||||
}
|
||||
|
||||
__API__ void tos_stopwatch_delay(k_tick_t tick)
|
||||
{
|
||||
k_tick_t now;
|
||||
|
||||
now = tos_systick_get();
|
||||
while ((tos_systick_get() - now) < tick) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
__API__ void tos_stopwatch_delay_ms(k_time_t millisec)
|
||||
{
|
||||
k_tick_t tick;
|
||||
|
||||
tick = tos_millisec2tick(millisec);
|
||||
tos_stopwatch_delay(tick);
|
||||
}
|
||||
|
||||
__API__ k_tick_t tos_stopwatch_remain(k_stopwatch_t *stopwatch)
|
||||
{
|
||||
k_tick_t now;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(stopwatch, (k_tick_t)-1);
|
||||
TOS_OBJ_VERIFY_RC(stopwatch, KNL_OBJ_TYPE_STOPWATCH, (k_tick_t)-1);
|
||||
|
||||
if (tos_stopwatch_is_expired(stopwatch)) {
|
||||
return (k_tick_t)0u;
|
||||
}
|
||||
|
||||
now = tos_systick_get();
|
||||
return stopwatch->until - now;
|
||||
}
|
||||
|
||||
__API__ k_time_t tos_stopwatch_remain_ms(k_stopwatch_t *stopwatch)
|
||||
{
|
||||
k_tick_t now;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(stopwatch, (k_time_t)-1);
|
||||
TOS_OBJ_VERIFY_RC(stopwatch, KNL_OBJ_TYPE_STOPWATCH, (k_time_t)-1);
|
||||
|
||||
if (tos_stopwatch_is_expired(stopwatch)) {
|
||||
return (k_tick_t)0u;
|
||||
}
|
||||
|
||||
now = tos_systick_get();
|
||||
return (k_time_t)(((stopwatch->until) - now + TOS_CFG_CPU_TICK_PER_SECOND - 1) / TOS_CFG_CPU_TICK_PER_SECOND);
|
||||
}
|
||||
|
||||
__API__ int tos_stopwatch_is_expired(k_stopwatch_t *stopwatch)
|
||||
{
|
||||
k_tick_t now;
|
||||
|
||||
TOS_PTR_SANITY_CHECK_RC(stopwatch, K_FALSE);
|
||||
TOS_OBJ_VERIFY_RC(stopwatch, KNL_OBJ_TYPE_STOPWATCH, K_FALSE);
|
||||
|
||||
now = tos_systick_get();
|
||||
return now >= stopwatch->until ? K_TRUE : K_FALSE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__API__ k_err_t tos_knl_init(void)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
cpu_init();
|
||||
|
||||
readyqueue_init();
|
||||
|
||||
#if TOS_CFG_MMHEAP_EN > 0
|
||||
#if TOS_CFG_MMHEAP_DEFAULT_POOL_EN > 0u
|
||||
err = mmheap_init_with_pool(k_mmheap_default_pool, TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE);
|
||||
#else
|
||||
err = mmheap_init();
|
||||
#endif
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = knl_idle_init();
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
||||
#if TOS_CFG_TIMER_EN > 0
|
||||
err = timer_init();
|
||||
if (err != K_ERR_NONE) {
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_PWR_MGR_EN > 0U
|
||||
pm_init();
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
tickless_init();
|
||||
#endif
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ void tos_knl_irq_enter(void)
|
||||
{
|
||||
if (!tos_knl_is_running()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(k_irq_nest_cnt >= K_NESTING_LIMIT_IRQ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
++k_irq_nest_cnt;
|
||||
}
|
||||
|
||||
__API__ void tos_knl_irq_leave(void)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
if (!tos_knl_is_running()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
if (!knl_is_inirq()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
--k_irq_nest_cnt;
|
||||
|
||||
if (knl_is_inirq()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
k_next_task = readyqueue_highest_ready_task_get();
|
||||
if (knl_is_self(k_next_task)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_irq_context_switch();
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_knl_sched_lock(void)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
|
||||
if (!tos_knl_is_running()) {
|
||||
return K_ERR_KNL_NOT_RUNNING;
|
||||
}
|
||||
|
||||
if (k_sched_lock_nest_cnt >= K_NESTING_LIMIT_SCHED_LOCK) {
|
||||
return K_ERR_LOCK_NESTING_OVERFLOW;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
++k_sched_lock_nest_cnt;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_knl_sched_unlock(void)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
|
||||
if (!tos_knl_is_running()) {
|
||||
return K_ERR_KNL_NOT_RUNNING;
|
||||
}
|
||||
|
||||
if (!knl_is_sched_locked()) {
|
||||
return K_ERR_SCHED_NOT_LOCKED;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
--k_sched_lock_nest_cnt;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
knl_sched();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_knl_start(void)
|
||||
{
|
||||
if (unlikely(tos_knl_is_running())) {
|
||||
return K_ERR_KNL_RUNNING;
|
||||
}
|
||||
|
||||
k_next_task = readyqueue_highest_ready_task_get();
|
||||
k_curr_task = k_next_task;
|
||||
k_knl_state = KNL_STATE_RUNNING;
|
||||
|
||||
// printf("start\r\n");
|
||||
cpu_sched_start();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ int tos_knl_is_running(void)
|
||||
{
|
||||
return k_knl_state == KNL_STATE_RUNNING;
|
||||
}
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
|
||||
/**
|
||||
* @brief Get the remain ticks of the first oncoming task.
|
||||
*
|
||||
* @return The remian ticks of the first oncoming task to be scheduled.
|
||||
*/
|
||||
__KNL__ k_tick_t knl_next_expires_get(void)
|
||||
{
|
||||
k_tick_t tick_next_expires;
|
||||
#if TOS_CFG_TIMER_EN > 0u
|
||||
k_tick_t timer_next_expires;
|
||||
#endif
|
||||
|
||||
tick_next_expires = tick_next_expires_get();
|
||||
|
||||
#if TOS_CFG_TIMER_EN > 0u
|
||||
timer_next_expires = timer_next_expires_get();
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_TIMER_EN > 0u
|
||||
return tick_next_expires < timer_next_expires ? tick_next_expires : timer_next_expires;
|
||||
#else
|
||||
return tick_next_expires;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
__KNL__ void knl_sched(void)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
if (unlikely(!tos_knl_is_running())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (knl_is_inirq()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
k_next_task = readyqueue_highest_ready_task_get();
|
||||
if (knl_is_self(k_next_task)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_context_switch();
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__KNL__ int knl_is_sched_locked(void)
|
||||
{
|
||||
return k_sched_lock_nest_cnt > 0u;
|
||||
}
|
||||
|
||||
__KNL__ int knl_is_inirq(void)
|
||||
{
|
||||
return k_irq_nest_cnt > 0u;
|
||||
}
|
||||
|
||||
__KNL__ int knl_is_idle(k_task_t *task)
|
||||
{
|
||||
return task == &k_idle_task;
|
||||
}
|
||||
|
||||
__KNL__ int knl_is_self(k_task_t *task)
|
||||
{
|
||||
return task == k_curr_task;
|
||||
}
|
||||
|
||||
__STATIC__ void knl_idle_entry(void *arg)
|
||||
{
|
||||
arg = arg; // make compiler happy
|
||||
|
||||
while (K_TRUE) {
|
||||
#if TOS_CFG_TASK_DYNAMIC_CREATE_EN > 0u
|
||||
task_free_all();
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_PWR_MGR_EN > 0u
|
||||
pm_power_manager();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
__KNL__ k_err_t knl_idle_init(void)
|
||||
{
|
||||
return tos_task_create(&k_idle_task, "idle",
|
||||
knl_idle_entry, K_NULL,
|
||||
K_TASK_PRIO_IDLE,
|
||||
k_idle_task_stk_addr,
|
||||
k_idle_task_stk_size,
|
||||
0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,585 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__STATIC_INLINE__ void task_reset(k_task_t *task)
|
||||
{
|
||||
#if TOS_CFG_TASK_DYNAMIC_CREATE_EN > 0u
|
||||
knl_object_alloc_reset(&task->knl_obj);
|
||||
|
||||
tos_list_init(&task->dead_list);
|
||||
#endif
|
||||
tos_list_init(&task->stat_list);
|
||||
tos_list_init(&task->tick_list);
|
||||
tos_list_init(&task->pend_list);
|
||||
|
||||
#if TOS_CFG_MUTEX_EN > 0u
|
||||
tos_list_init(&task->mutex_own_list);
|
||||
task->prio_pending = K_TASK_PRIO_INVALID;
|
||||
#endif
|
||||
|
||||
task->pend_state = PEND_STATE_NONE;
|
||||
task->pending_obj = (pend_obj_t *)K_NULL;
|
||||
|
||||
#if TOS_CFG_MESSAGE_QUEUE_EN > 0u
|
||||
task->msg = K_NULL;
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_MAIL_QUEUE_EN > 0u
|
||||
task->mail = K_NULL;
|
||||
task->mail_size = 0;
|
||||
#endif
|
||||
|
||||
TOS_OBJ_DEINIT(task);
|
||||
}
|
||||
|
||||
__STATIC__ void task_exit(void)
|
||||
{
|
||||
tos_task_destroy(K_NULL);
|
||||
}
|
||||
|
||||
#if TOS_CFG_MUTEX_EN > 0u
|
||||
__STATIC__ k_prio_t task_highest_pending_prio_get(k_task_t *task)
|
||||
{
|
||||
k_mutex_t *mutex;
|
||||
k_prio_t prio, highest_prio_pending = K_TASK_PRIO_INVALID;
|
||||
|
||||
TOS_LIST_FOR_EACH_ENTRY(mutex, k_mutex_t, owner_anchor, &task->mutex_own_list) {
|
||||
prio = pend_highest_pending_prio_get(&mutex->pend_obj);
|
||||
if (prio < highest_prio_pending) {
|
||||
highest_prio_pending = prio;
|
||||
}
|
||||
}
|
||||
|
||||
return highest_prio_pending;
|
||||
}
|
||||
|
||||
__STATIC__ void task_mutex_release(k_task_t *task)
|
||||
{
|
||||
k_mutex_t *mutex, *tmp;
|
||||
|
||||
TOS_LIST_FOR_EACH_ENTRY_SAFE(mutex, tmp, k_mutex_t, owner_anchor, &task->mutex_own_list) {
|
||||
mutex_release(mutex);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__API__ k_err_t tos_task_create(k_task_t *task,
|
||||
char *name,
|
||||
k_task_entry_t entry,
|
||||
void *arg,
|
||||
k_prio_t prio,
|
||||
k_stack_t *stk_base,
|
||||
size_t stk_size,
|
||||
k_timeslice_t timeslice)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(task);
|
||||
TOS_PTR_SANITY_CHECK(entry);
|
||||
TOS_PTR_SANITY_CHECK(stk_base);
|
||||
|
||||
/* try to re-create a task, kind of dangerous */
|
||||
TOS_OBJ_TEST_RC(task, KNL_OBJ_TYPE_TASK, K_ERR_TASK_ALREADY_CREATED);
|
||||
|
||||
if (unlikely(stk_size < K_TASK_STK_SIZE_MIN)) {
|
||||
return K_ERR_TASK_STK_SIZE_INVALID;
|
||||
}
|
||||
|
||||
if (unlikely(prio == K_TASK_PRIO_IDLE && !knl_is_idle(task))) {
|
||||
return K_ERR_TASK_PRIO_INVALID;
|
||||
}
|
||||
|
||||
if (unlikely(prio > K_TASK_PRIO_IDLE)) {
|
||||
return K_ERR_TASK_PRIO_INVALID;
|
||||
}
|
||||
|
||||
task_reset(task);
|
||||
tos_list_add(&task->stat_list, &k_stat_list);
|
||||
|
||||
TOS_OBJ_INIT(task, KNL_OBJ_TYPE_TASK);
|
||||
#if TOS_CFG_TASK_DYNAMIC_CREATE_EN > 0u
|
||||
knl_object_alloc_set_static(&task->knl_obj);
|
||||
#endif
|
||||
|
||||
task->sp = cpu_task_stk_init((void *)entry, arg, (void *)task_exit, stk_base, stk_size);
|
||||
task->entry = entry;
|
||||
task->arg = arg;
|
||||
task->prio = prio;
|
||||
task->stk_base = stk_base;
|
||||
task->stk_size = stk_size;
|
||||
strncpy(task->name, name, K_TASK_NAME_LEN_MAX);
|
||||
|
||||
#if TOS_CFG_ROUND_ROBIN_EN > 0u
|
||||
task->timeslice_reload = timeslice;
|
||||
|
||||
if (timeslice == (k_timeslice_t)0u) {
|
||||
task->timeslice = k_robin_default_timeslice;
|
||||
} else {
|
||||
task->timeslice = timeslice;
|
||||
}
|
||||
#endif
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
task_state_set_ready(task);
|
||||
readyqueue_add_tail(task);
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
if (tos_knl_is_running()) {
|
||||
knl_sched();
|
||||
}
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__STATIC__ k_err_t task_do_destroy(k_task_t *task)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
if (knl_is_idle(task)) {
|
||||
return K_ERR_TASK_DESTROY_IDLE;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
#if TOS_CFG_MUTEX_EN > 0u
|
||||
// when we die, wakeup all the people in this land.
|
||||
if (!tos_list_empty(&task->mutex_own_list)) {
|
||||
task_mutex_release(task);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (task_state_is_ready(task)) { // that's simple, good kid
|
||||
readyqueue_remove(task);
|
||||
}
|
||||
if (task_state_is_sleeping(task)) {
|
||||
tick_list_remove(task);
|
||||
}
|
||||
if (task_state_is_pending(task)) {
|
||||
pend_list_remove(task);
|
||||
}
|
||||
|
||||
tos_list_del(&task->stat_list);
|
||||
task_reset(task);
|
||||
|
||||
task_state_set_deleted(task);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__STATIC__ k_err_t task_destroy_static(k_task_t *task)
|
||||
{
|
||||
#if TOS_CFG_TASK_DYNAMIC_CREATE_EN > 0u
|
||||
if (!knl_object_alloc_is_static(&task->knl_obj)) {
|
||||
return K_ERR_OBJ_INVALID_ALLOC_TYPE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return task_do_destroy(task);
|
||||
}
|
||||
|
||||
#if TOS_CFG_TASK_DYNAMIC_CREATE_EN > 0u
|
||||
|
||||
__STATIC__ void task_free(k_task_t *task)
|
||||
{
|
||||
tos_mmheap_free(task->stk_base);
|
||||
tos_mmheap_free(task);
|
||||
}
|
||||
|
||||
__KNL__ void task_free_all(void)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_task_t *task, *tmp;
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
TOS_LIST_FOR_EACH_ENTRY_SAFE(task, tmp, k_task_t, dead_list, &k_dead_task_list) {
|
||||
tos_list_del(&task->dead_list);
|
||||
task_free(task);
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_task_create_dyn(k_task_t **task,
|
||||
char *name,
|
||||
k_task_entry_t entry,
|
||||
void *arg,
|
||||
k_prio_t prio,
|
||||
size_t stk_size,
|
||||
k_timeslice_t timeslice)
|
||||
{
|
||||
k_err_t err;
|
||||
k_task_t *the_task;
|
||||
k_stack_t *stk_base;
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(task);
|
||||
TOS_PTR_SANITY_CHECK(entry);
|
||||
|
||||
if (unlikely(stk_size < sizeof(cpu_context_t))) {
|
||||
return K_ERR_TASK_STK_SIZE_INVALID;
|
||||
}
|
||||
|
||||
if (unlikely(prio == K_TASK_PRIO_IDLE)) {
|
||||
return K_ERR_TASK_PRIO_INVALID;
|
||||
}
|
||||
|
||||
if (unlikely(prio > K_TASK_PRIO_IDLE)) {
|
||||
return K_ERR_TASK_PRIO_INVALID;
|
||||
}
|
||||
|
||||
the_task = tos_mmheap_calloc(1, sizeof(k_task_t));
|
||||
if (!the_task) {
|
||||
return K_ERR_TASK_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
stk_base = tos_mmheap_alloc(stk_size);
|
||||
if (!stk_base) {
|
||||
tos_mmheap_free(the_task);
|
||||
return K_ERR_TASK_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
the_task->stk_base = stk_base;
|
||||
err = tos_task_create(the_task, name, entry, arg, prio, stk_base, stk_size, timeslice);
|
||||
if (err != K_ERR_NONE) {
|
||||
task_free(the_task);
|
||||
return err;
|
||||
}
|
||||
|
||||
knl_object_alloc_set_dynamic(&the_task->knl_obj);
|
||||
|
||||
*task = the_task;
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__STATIC__ k_err_t task_destroy_dyn(k_task_t *task)
|
||||
{
|
||||
k_err_t err;
|
||||
|
||||
tos_knl_sched_lock();
|
||||
|
||||
err = task_do_destroy(task);
|
||||
if (err != K_ERR_NONE) {
|
||||
tos_knl_sched_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
if (knl_is_self(task)) { // we are destroying ourself
|
||||
// in this situation, we cannot just free ourself's task stack because we are using it
|
||||
// we count on the idle task to free the memory
|
||||
tos_list_add(&task->dead_list, &k_dead_task_list);
|
||||
} else {
|
||||
task_free(task);
|
||||
}
|
||||
|
||||
tos_knl_sched_unlock();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
__API__ k_err_t tos_task_destroy(k_task_t *task)
|
||||
{
|
||||
TOS_IN_IRQ_CHECK();
|
||||
|
||||
if (unlikely(!task)) {
|
||||
task = k_curr_task;
|
||||
}
|
||||
|
||||
TOS_OBJ_VERIFY(task, KNL_OBJ_TYPE_TASK);
|
||||
|
||||
if (knl_is_self(task) && knl_is_sched_locked()) {
|
||||
return K_ERR_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
#if TOS_CFG_TASK_DYNAMIC_CREATE_EN > 0u
|
||||
if (knl_object_alloc_is_dynamic(&task->knl_obj)) {
|
||||
return task_destroy_dyn(task);
|
||||
}
|
||||
#endif
|
||||
|
||||
return task_destroy_static(task);
|
||||
}
|
||||
|
||||
__API__ void tos_task_yield(void)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
if (knl_is_inirq()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
readyqueue_remove(k_curr_task);
|
||||
readyqueue_add_tail(k_curr_task);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_task_prio_change(k_task_t *task, k_prio_t prio_new)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
#if TOS_CFG_MUTEX_EN > 0u
|
||||
k_prio_t highest_pending_prio;
|
||||
#endif
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(task);
|
||||
TOS_OBJ_VERIFY(task, KNL_OBJ_TYPE_TASK);
|
||||
|
||||
if (unlikely(prio_new >= K_TASK_PRIO_IDLE)) {
|
||||
return K_ERR_TASK_PRIO_INVALID;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (task->prio == prio_new) { // just kidding
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
#if TOS_CFG_MUTEX_EN > 0u
|
||||
if (!tos_list_empty(&task->mutex_own_list)) {
|
||||
highest_pending_prio = task_highest_pending_prio_get(task);
|
||||
if (prio_new > highest_pending_prio) {
|
||||
task->prio_pending = prio_new;
|
||||
prio_new = highest_pending_prio;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (task_state_is_pending(task)) {
|
||||
task->prio = prio_new;
|
||||
pend_list_adjust(task);
|
||||
} else if (task_state_is_sleeping(task)) {
|
||||
task->prio = prio_new;
|
||||
} else if (task_state_is_ready(task)) { // good kid
|
||||
readyqueue_remove(task);
|
||||
|
||||
/* ATTENTION:
|
||||
must do the prio assignment after readyqueue_remove
|
||||
otherwise the k_rdyq.highest_prio refresh in readyqueue_remove will be wrong.
|
||||
*/
|
||||
task->prio = prio_new;
|
||||
if (knl_is_self(task)) {
|
||||
readyqueue_add_head(task);
|
||||
} else {
|
||||
readyqueue_add_tail(task);
|
||||
}
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_task_suspend(k_task_t *task)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
if (unlikely(!task)) {
|
||||
task = k_curr_task;
|
||||
}
|
||||
|
||||
TOS_OBJ_VERIFY(task, KNL_OBJ_TYPE_TASK);
|
||||
|
||||
if (knl_is_idle(task)) {
|
||||
return K_ERR_TASK_SUSPEND_IDLE;
|
||||
}
|
||||
|
||||
if (unlikely(knl_is_self(task)) && knl_is_sched_locked()) { // if not you, who?
|
||||
return K_ERR_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (task_state_is_ready(task)) { // kill the good kid
|
||||
readyqueue_remove(task);
|
||||
}
|
||||
task_state_set_suspended(task);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_task_resume(k_task_t *task)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_PTR_SANITY_CHECK(task);
|
||||
TOS_OBJ_VERIFY(task, KNL_OBJ_TYPE_TASK);
|
||||
|
||||
if (unlikely(knl_is_self(task))) {
|
||||
return K_ERR_TASK_RESUME_SELF;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (!task_state_is_suspended(task)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
task_state_reset_suspended(task);
|
||||
if (task_state_is_ready(task)) { // we are good kid now
|
||||
readyqueue_add(task);
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_task_delay(k_tick_t delay)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
|
||||
if (knl_is_sched_locked()) {
|
||||
return K_ERR_SCHED_LOCKED;
|
||||
}
|
||||
|
||||
if (unlikely(delay == (k_tick_t)0u)) {
|
||||
tos_task_yield();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (unlikely(delay == TOS_TIME_FOREVER)) {
|
||||
// if you wanna delay your task forever, why don't just suspend?
|
||||
return K_ERR_DELAY_FOREVER;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
tick_list_add(k_curr_task, delay);
|
||||
readyqueue_remove(k_curr_task);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_task_delay_abort(k_task_t *task)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_IN_IRQ_CHECK();
|
||||
TOS_PTR_SANITY_CHECK(task);
|
||||
TOS_OBJ_VERIFY(task, KNL_OBJ_TYPE_TASK);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (knl_is_self(task) || !task_state_is_sleeping(task)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_TASK_NOT_DELAY;
|
||||
}
|
||||
|
||||
if (task_state_is_suspended(task)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_TASK_SUSPENDED;
|
||||
}
|
||||
|
||||
tick_list_remove(task);
|
||||
readyqueue_add(task);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
knl_sched();
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_task_t *tos_task_curr_task_get(void)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_task_t *curr_task = K_NULL;
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
if (likely(tos_knl_is_running())) {
|
||||
curr_task = k_curr_task;
|
||||
}
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return curr_task;
|
||||
}
|
||||
|
||||
__API__ void tos_task_walkthru(k_task_walker_t walker)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_task_t *task;
|
||||
|
||||
if (!walker) {
|
||||
return;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
TOS_LIST_FOR_EACH_ENTRY(task, k_task_t, stat_list, &k_stat_list) {
|
||||
walker(task);
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__DEBUG__ void tos_task_info_display(void)
|
||||
{
|
||||
tos_task_walkthru(task_default_walker);
|
||||
}
|
||||
|
||||
#if TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN > 0u
|
||||
|
||||
__API__ k_err_t tos_task_stack_draught_depth(k_task_t *task, int *depth)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_err_t rc;
|
||||
|
||||
TOS_PTR_SANITY_CHECK(depth);
|
||||
|
||||
if (unlikely(!task)) {
|
||||
task = k_curr_task;
|
||||
}
|
||||
|
||||
TOS_OBJ_VERIFY(task, KNL_OBJ_TYPE_TASK);
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
rc = cpu_task_stack_draught_depth(task->stk_base, task->stk_size, depth);
|
||||
TOS_CPU_INT_ENABLE();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__STATIC__ void tick_task_place(k_task_t *task, k_tick_t timeout)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_task_t *curr_task = K_NULL;
|
||||
k_tick_t curr_expires, prev_expires = (k_tick_t)0u;
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
task->tick_expires = timeout;
|
||||
|
||||
TOS_LIST_FOR_EACH_ENTRY(curr_task, k_task_t, tick_list, &k_tick_list) {
|
||||
curr_expires = prev_expires + curr_task->tick_expires;
|
||||
|
||||
if (task->tick_expires < curr_expires) {
|
||||
break;
|
||||
}
|
||||
if (task->tick_expires == curr_expires &&
|
||||
task->prio < curr_task->prio) {
|
||||
break;
|
||||
}
|
||||
prev_expires = curr_expires;
|
||||
}
|
||||
task->tick_expires -= prev_expires;
|
||||
if (&curr_task->tick_list != &k_tick_list) {
|
||||
curr_task->tick_expires -= task->tick_expires;
|
||||
}
|
||||
tos_list_add_tail(&task->tick_list, &curr_task->tick_list);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__STATIC__ void tick_task_takeoff(k_task_t *task)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_task_t *next;
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
next = TOS_LIST_FIRST_ENTRY_OR_NULL(&task->tick_list, k_task_t, tick_list);
|
||||
if (next && task->tick_list.next != &k_tick_list) { // not the only one
|
||||
if (next->tick_expires <= K_TIME_MAX - task->tick_expires) {
|
||||
next->tick_expires += task->tick_expires;
|
||||
} else {
|
||||
next->tick_expires = K_TIME_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
tos_list_del(&task->tick_list);
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__KNL__ void tick_list_add(k_task_t *task, k_tick_t timeout)
|
||||
{
|
||||
tick_task_place(task, timeout);
|
||||
task_state_set_sleeping(task);
|
||||
}
|
||||
|
||||
__KNL__ void tick_list_remove(k_task_t *task)
|
||||
{
|
||||
tick_task_takeoff(task);
|
||||
task_state_reset_sleeping(task);
|
||||
}
|
||||
|
||||
__KNL__ void tick_update(k_tick_t tick)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_task_t *first, *task, *tmp;
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
k_tick_count += tick;
|
||||
|
||||
if (tos_list_empty(&k_tick_list)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
first = TOS_LIST_FIRST_ENTRY(&k_tick_list, k_task_t, tick_list);
|
||||
if (first->tick_expires <= tick) {
|
||||
first->tick_expires = (k_tick_t)0u;
|
||||
} else {
|
||||
first->tick_expires -= tick;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
TOS_LIST_FOR_EACH_ENTRY_SAFE(task, tmp, k_task_t, tick_list, &k_tick_list) {
|
||||
if (task->tick_expires > (k_tick_t)0u) {
|
||||
break;
|
||||
}
|
||||
|
||||
// we are pending for something, but tick's up, no longer waitting
|
||||
pend_task_wakeup(task, PEND_STATE_TIMEOUT);
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__KNL__ k_tick_t tick_next_expires_get(void)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_tick_t next_expires;
|
||||
k_task_t *first;
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
first = TOS_LIST_FIRST_ENTRY_OR_NULL(&k_tick_list, k_task_t, tick_list);
|
||||
next_expires = first ? first->tick_expires : TOS_TIME_FOREVER;
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return next_expires;
|
||||
}
|
||||
|
||||
__API__ void tos_tick_handler(void)
|
||||
{
|
||||
if (unlikely(!tos_knl_is_running())) {
|
||||
return;
|
||||
}
|
||||
|
||||
tick_update((k_tick_t)1u);
|
||||
|
||||
#if TOS_CFG_TIMER_EN > 0u && TOS_CFG_TIMER_AS_PROC > 0u
|
||||
timer_update();
|
||||
#endif
|
||||
|
||||
#if TOS_CFG_ROUND_ROBIN_EN > 0u
|
||||
robin_sched(k_curr_task->prio);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
__API__ k_tick_t tos_systick_get(void)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_tick_t tick;
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
tick = k_tick_count;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return tick;
|
||||
}
|
||||
|
||||
__API__ void tos_systick_set(k_tick_t tick)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
k_tick_count = tick;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__API__ k_time_t tos_tick2millisec(k_tick_t tick)
|
||||
{
|
||||
return (k_time_t)(tick * (K_TIME_MILLISEC_PER_SEC / TOS_CFG_CPU_TICK_PER_SECOND));
|
||||
}
|
||||
|
||||
__API__ k_tick_t tos_millisec2tick(k_time_t ms)
|
||||
{
|
||||
return (k_tick_t)(ms * (TOS_CFG_CPU_TICK_PER_SECOND / K_TIME_MILLISEC_PER_SEC));
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_sleep_ms(k_time_t ms)
|
||||
{
|
||||
return tos_task_delay(tos_millisec2tick(ms));
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ k_tick_t time_hmsm2tick(k_time_t hour, k_time_t minute, k_time_t second, k_time_t millisec)
|
||||
{
|
||||
return ((k_tick_t)hour * (k_tick_t)3600u + (k_tick_t)minute * (k_tick_t)60u +
|
||||
(k_tick_t)second) * TOS_CFG_CPU_TICK_PER_SECOND +
|
||||
(TOS_CFG_CPU_TICK_PER_SECOND * ((k_tick_t)millisec + (k_tick_t)500u / TOS_CFG_CPU_TICK_PER_SECOND)) / (k_tick_t)1000u;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_sleep_hmsm(k_time_t hour, k_time_t minute, k_time_t second, k_time_t millisec)
|
||||
{
|
||||
return tos_task_delay(time_hmsm2tick(hour, minute, second, millisec));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,367 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_TIMER_EN > 0u
|
||||
|
||||
__STATIC__ void timer_place(k_timer_t *tmr)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_timer_t *iter = K_NULL;
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
tmr->expires += k_tick_count;
|
||||
|
||||
TOS_LIST_FOR_EACH_ENTRY(iter, k_timer_t, list, &k_timer_ctl.list) {
|
||||
if (tmr->expires < iter->expires) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tos_list_add_tail(&tmr->list, &iter->list);
|
||||
|
||||
if (k_timer_ctl.list.next == &tmr->list) {
|
||||
// we are the first guy now
|
||||
k_timer_ctl.next_expires = tmr->expires;
|
||||
|
||||
#if TOS_CFG_TIMER_AS_PROC == 0u
|
||||
if (task_state_is_sleeping(&k_timer_task)) {
|
||||
tos_task_delay_abort(&k_timer_task);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TOS_CFG_TIMER_AS_PROC == 0u
|
||||
if (task_state_is_suspended(&k_timer_task)) {
|
||||
tos_task_resume(&k_timer_task);
|
||||
}
|
||||
#endif
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__STATIC__ void timer_takeoff(k_timer_t *tmr)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_timer_t *first, *next;
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
first = TOS_LIST_FIRST_ENTRY(&k_timer_ctl.list, k_timer_t, list);
|
||||
|
||||
tos_list_del(&tmr->list);
|
||||
|
||||
if (first == tmr) {
|
||||
// if the first guy removed, we need to refresh k_timer_ctl.next_expires
|
||||
next = TOS_LIST_FIRST_ENTRY_OR_NULL(&tmr->list, k_timer_t, list);
|
||||
if (!next) {
|
||||
// the only guy removed
|
||||
k_timer_ctl.next_expires = TOS_TIME_FOREVER;
|
||||
} else {
|
||||
k_timer_ctl.next_expires = next->expires;
|
||||
}
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void timer_reset(k_timer_t *tmr)
|
||||
{
|
||||
tmr->state = TIMER_STATE_UNUSED;
|
||||
tmr->delay = (k_tick_t)0u;
|
||||
tmr->expires = (k_tick_t)0u;
|
||||
tmr->period = (k_tick_t)0u;
|
||||
tmr->opt = (k_opt_t)0u;
|
||||
tmr->cb = K_NULL;
|
||||
tmr->cb_arg = K_NULL;
|
||||
tos_list_init(&tmr->list);
|
||||
|
||||
TOS_OBJ_DEINIT(tmr);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_timer_create(k_timer_t *tmr,
|
||||
k_tick_t delay,
|
||||
k_tick_t period,
|
||||
k_timer_callback_t callback,
|
||||
void *cb_arg,
|
||||
k_opt_t opt)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(tmr);
|
||||
TOS_PTR_SANITY_CHECK(callback);
|
||||
|
||||
if (opt == TOS_OPT_TIMER_PERIODIC && period == (k_tick_t)0u) {
|
||||
return K_ERR_TIMER_INVALID_PERIOD;
|
||||
}
|
||||
|
||||
if (opt == TOS_OPT_TIMER_ONESHOT && delay == (k_tick_t)0u) {
|
||||
// if you create a oneshot timer and delay 0 to trigger, why don't just call the timer_callback?
|
||||
return K_ERR_TIMER_INVALID_DELAY;
|
||||
}
|
||||
|
||||
if (opt != TOS_OPT_TIMER_ONESHOT && opt != TOS_OPT_TIMER_PERIODIC) {
|
||||
return K_ERR_TIMER_INVALID_OPT;
|
||||
}
|
||||
|
||||
if (delay == TOS_TIME_FOREVER) {
|
||||
return K_ERR_TIMER_DELAY_FOREVER;
|
||||
}
|
||||
|
||||
if (period == TOS_TIME_FOREVER) {
|
||||
return K_ERR_TIMER_PERIOD_FOREVER;
|
||||
}
|
||||
|
||||
tmr->state = TIMER_STATE_STOPPED;
|
||||
tmr->delay = delay;
|
||||
tmr->expires = (k_tick_t)0u;
|
||||
tmr->period = period;
|
||||
tmr->opt = opt;
|
||||
tmr->cb = callback;
|
||||
tmr->cb_arg = cb_arg;
|
||||
tos_list_init(&tmr->list);
|
||||
|
||||
TOS_OBJ_INIT(tmr, KNL_OBJ_TYPE_TIMER);
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_timer_destroy(k_timer_t *tmr)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(tmr);
|
||||
TOS_OBJ_VERIFY(tmr, KNL_OBJ_TYPE_TIMER);
|
||||
|
||||
if (tmr->state == TIMER_STATE_UNUSED) {
|
||||
return K_ERR_TIMER_INACTIVE;
|
||||
}
|
||||
|
||||
if (tmr->state == TIMER_STATE_RUNNING) {
|
||||
timer_takeoff(tmr);
|
||||
}
|
||||
|
||||
timer_reset(tmr);
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_timer_start(k_timer_t *tmr)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(tmr);
|
||||
TOS_OBJ_VERIFY(tmr, KNL_OBJ_TYPE_TIMER);
|
||||
|
||||
if (tmr->state == TIMER_STATE_UNUSED) {
|
||||
return K_ERR_TIMER_INACTIVE;
|
||||
}
|
||||
|
||||
if (tmr->state == TIMER_STATE_RUNNING) {
|
||||
timer_takeoff(tmr);
|
||||
tmr->expires = tmr->delay;
|
||||
timer_place(tmr);
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
if (tmr->state == TIMER_STATE_STOPPED ||
|
||||
tmr->state == TIMER_STATE_COMPLETED) {
|
||||
tmr->state = TIMER_STATE_RUNNING;
|
||||
if (tmr->delay == (k_tick_t)0u) {
|
||||
tmr->expires = tmr->period;
|
||||
} else {
|
||||
tmr->expires = tmr->delay;
|
||||
}
|
||||
timer_place(tmr);
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
return K_ERR_TIMER_INVALID_STATE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_timer_stop(k_timer_t *tmr)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(tmr);
|
||||
TOS_OBJ_VERIFY(tmr, KNL_OBJ_TYPE_TIMER);
|
||||
|
||||
if (tmr->state == TIMER_STATE_UNUSED) {
|
||||
return K_ERR_TIMER_INACTIVE;
|
||||
}
|
||||
|
||||
if (tmr->state == TIMER_STATE_COMPLETED ||
|
||||
tmr->state == TIMER_STATE_STOPPED) {
|
||||
return K_ERR_TIMER_STOPPED;
|
||||
}
|
||||
|
||||
if (tmr->state == TIMER_STATE_RUNNING) {
|
||||
tmr->state = TIMER_STATE_STOPPED;
|
||||
timer_takeoff(tmr);
|
||||
}
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__STATIC__ k_err_t timer_change(k_timer_t *tmr, k_tick_t new_val, timer_change_type_t change_type)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(tmr);
|
||||
TOS_OBJ_VERIFY(tmr, KNL_OBJ_TYPE_TIMER);
|
||||
|
||||
if (tmr->state == TIMER_STATE_UNUSED) {
|
||||
return K_ERR_TIMER_INACTIVE;
|
||||
}
|
||||
|
||||
if (tmr->state == TIMER_STATE_RUNNING) {
|
||||
return K_ERR_TIMER_RUNNING;
|
||||
}
|
||||
|
||||
if (tmr->opt == TOS_OPT_TIMER_ONESHOT &&
|
||||
change_type == TIMER_CHANGE_TYPE_DELAY &&
|
||||
new_val == (k_tick_t)0u) {
|
||||
return K_ERR_TIMER_INVALID_DELAY;
|
||||
}
|
||||
|
||||
if (tmr->opt == TOS_OPT_TIMER_PERIODIC &&
|
||||
change_type == TIMER_CHANGE_TYPE_PERIOD &&
|
||||
new_val == (k_tick_t)0u) {
|
||||
return K_ERR_TIMER_INVALID_PERIOD;
|
||||
}
|
||||
|
||||
if (change_type == TIMER_CHANGE_TYPE_DELAY) {
|
||||
tmr->delay = new_val;
|
||||
} else {
|
||||
tmr->period = new_val;
|
||||
}
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_timer_delay_change(k_timer_t *tmr, k_tick_t delay)
|
||||
{
|
||||
return timer_change(tmr, delay, TIMER_CHANGE_TYPE_DELAY);
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_timer_period_change(k_timer_t *tmr, k_tick_t period)
|
||||
{
|
||||
return timer_change(tmr, period, TIMER_CHANGE_TYPE_PERIOD);
|
||||
}
|
||||
|
||||
__KNL__ k_tick_t timer_next_expires_get(void)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_tick_t next_expires;
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
if (k_timer_ctl.next_expires == TOS_TIME_FOREVER) {
|
||||
next_expires = TOS_TIME_FOREVER;
|
||||
} else if (k_timer_ctl.next_expires <= k_tick_count) {
|
||||
next_expires = (k_tick_t)0u;
|
||||
} else {
|
||||
next_expires = k_timer_ctl.next_expires - k_tick_count;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return next_expires;
|
||||
}
|
||||
|
||||
#if TOS_CFG_TIMER_AS_PROC > 0u
|
||||
|
||||
__KNL__ void timer_update(void)
|
||||
{
|
||||
k_timer_t *tmr, *tmp;
|
||||
|
||||
if (k_timer_ctl.next_expires > k_tick_count) { // not yet
|
||||
return;
|
||||
}
|
||||
|
||||
tos_knl_sched_lock();
|
||||
|
||||
TOS_LIST_FOR_EACH_ENTRY_SAFE(tmr, tmp, k_timer_t, list, &k_timer_ctl.list) {
|
||||
if (tmr->expires > k_tick_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
// time's up
|
||||
timer_takeoff(tmr);
|
||||
|
||||
if (tmr->opt == TOS_OPT_TIMER_PERIODIC) {
|
||||
tmr->expires = tmr->period;
|
||||
timer_place(tmr);
|
||||
} else {
|
||||
tmr->state = TIMER_STATE_COMPLETED;
|
||||
}
|
||||
|
||||
(*tmr->cb)(tmr->cb_arg);
|
||||
}
|
||||
|
||||
tos_knl_sched_unlock();
|
||||
}
|
||||
|
||||
#else /* TOS_CFG_TIMER_AS_PROC > 0u */
|
||||
|
||||
__STATIC__ void timer_task_entry(void *arg)
|
||||
{
|
||||
k_timer_t *tmr, *tmp;
|
||||
k_tick_t next_expires;
|
||||
|
||||
arg = arg; // make compiler happy
|
||||
while (K_TRUE) {
|
||||
next_expires = timer_next_expires_get();
|
||||
if (next_expires == TOS_TIME_FOREVER) {
|
||||
tos_task_suspend(K_NULL);
|
||||
} else if (next_expires > (k_tick_t)0u) {
|
||||
tos_task_delay(next_expires);
|
||||
}
|
||||
|
||||
tos_knl_sched_lock();
|
||||
|
||||
TOS_LIST_FOR_EACH_ENTRY_SAFE(tmr, tmp, k_timer_t, list, &k_timer_ctl.list) {
|
||||
if (tmr->expires > k_tick_count) { // not yet
|
||||
break;
|
||||
}
|
||||
|
||||
// time's up
|
||||
timer_takeoff(tmr);
|
||||
|
||||
if (tmr->opt == TOS_OPT_TIMER_PERIODIC) {
|
||||
tmr->expires = tmr->period;
|
||||
timer_place(tmr);
|
||||
} else {
|
||||
tmr->state = TIMER_STATE_COMPLETED;
|
||||
}
|
||||
|
||||
(*tmr->cb)(tmr->cb_arg);
|
||||
}
|
||||
|
||||
tos_knl_sched_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
__KNL__ k_err_t timer_init(void)
|
||||
{
|
||||
#if TOS_CFG_TIMER_AS_PROC > 0u
|
||||
return K_ERR_NONE;
|
||||
#else
|
||||
return tos_task_create(&k_timer_task,
|
||||
"timer",
|
||||
timer_task_entry,
|
||||
K_NULL,
|
||||
k_timer_task_prio,
|
||||
k_timer_task_stk_addr,
|
||||
k_timer_task_stk_size,
|
||||
0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_HAL_H_
|
||||
#define _TOS_HAL_H_
|
||||
|
||||
#include "tos_k.h"
|
||||
#include "tos_hal_sd.h"
|
||||
#include "tos_hal_uart.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_HAL_SD_H_
|
||||
#define _TOS_HAL_SD_H_
|
||||
|
||||
typedef enum hal_sd_state_en {
|
||||
HAL_SD_STAT_RESET, /*< not yet initialized or disabled */
|
||||
HAL_SD_STAT_READY, /*< initialized and ready for use */
|
||||
HAL_SD_STAT_TIMEOUT, /*< timeout state */
|
||||
HAL_SD_STAT_BUSY, /*< process ongoing */
|
||||
HAL_SD_STAT_PROGRAMMING, /*< programming state */
|
||||
HAL_SD_STAT_RECEIVING, /*< receinving state */
|
||||
HAL_SD_STAT_TRANSFER, /*< transfert state */
|
||||
HAL_SD_STAT_ERROR, /*< error state */
|
||||
} hal_sd_state_t;
|
||||
|
||||
typedef struct hal_sd_info_st {
|
||||
uint32_t card_type; /*< card type */
|
||||
uint32_t card_version; /*< card version */
|
||||
uint32_t class; /*< card class */
|
||||
uint32_t relative_card_addr; /*< relative card address */
|
||||
uint32_t blk_num; /*< card capacity in blocks */
|
||||
uint32_t blk_size; /*< one block size in bytes */
|
||||
uint32_t logical_blk_num; /*< card logical capacity in blocks */
|
||||
uint32_t logical_blk_size; /*< logical block size in bytes */
|
||||
} hal_sd_info_t;
|
||||
|
||||
typedef struct hal_sd_st {
|
||||
void *private_sd;
|
||||
} hal_sd_t;
|
||||
|
||||
__API__ int tos_hal_sd_init(hal_sd_t *sd);
|
||||
|
||||
__API__ int tos_hal_sd_read(hal_sd_t *sd, uint8_t *buf, uint32_t blk_addr, uint32_t blk_num, uint32_t timeout);
|
||||
|
||||
__API__ int tos_hal_sd_write(hal_sd_t *sd, const uint8_t *buf, uint32_t blk_addr, uint32_t blk_num, uint32_t timeout);
|
||||
|
||||
__API__ int tos_hal_sd_read_dma(hal_sd_t *sd, uint8_t *buf, uint32_t blk_addr, uint32_t blk_num);
|
||||
|
||||
__API__ int tos_hal_sd_write_dma(hal_sd_t *sd, const uint8_t *buf, uint32_t blk_addr, uint32_t blk_num);
|
||||
|
||||
__API__ int tos_hal_sd_erase(hal_sd_t *sd, uint32_t blk_add_start, uint32_t blk_addr_end);
|
||||
|
||||
__API__ int tos_hal_sd_info_get(hal_sd_t *sd, hal_sd_info_t *info);
|
||||
|
||||
__API__ int tos_hal_sd_state_get(hal_sd_t *sd, hal_sd_state_t *state);
|
||||
|
||||
__API__ int tos_hal_sd_deinit(hal_sd_t *sd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_HAL_UART_H_
|
||||
#define _TOS_HAL_UART_H_
|
||||
|
||||
typedef enum hal_uart_port_en {
|
||||
HAL_UART_PORT_0 = 0,
|
||||
HAL_UART_PORT_1,
|
||||
HAL_UART_PORT_2,
|
||||
HAL_UART_PORT_3,
|
||||
HAL_UART_PORT_4,
|
||||
HAL_UART_PORT_5,
|
||||
HAL_UART_PORT_6,
|
||||
} hal_uart_port_t;
|
||||
|
||||
typedef struct hal_uart_st {
|
||||
hal_uart_port_t port;
|
||||
void *private_uart;
|
||||
} hal_uart_t;
|
||||
|
||||
__API__ int tos_hal_uart_init(hal_uart_t *uart, hal_uart_port_t port);
|
||||
|
||||
__API__ int tos_hal_uart_write(hal_uart_t *uart, const uint8_t *buf, size_t size, uint32_t timeout);
|
||||
|
||||
__API__ int tos_hal_uart_read(hal_uart_t *uart, const uint8_t *buf, size_t size, uint32_t timeout);
|
||||
|
||||
__API__ int tos_hal_uart_deinit(hal_uart_t *uart);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_PM_H_
|
||||
#define _TOS_PM_H_
|
||||
|
||||
#if TOS_CFG_PWR_MGR_EN > 0u
|
||||
|
||||
#define K_PM_DEVICE_MAX_COUNT 10u
|
||||
|
||||
typedef enum idle_power_manager_mode_en {
|
||||
IDLE_POWER_MANAGER_MODE_SLEEP,
|
||||
IDLE_POWER_MANAGER_MODE_TICKLESS,
|
||||
} idle_pwrmgr_mode_t;
|
||||
|
||||
/*
|
||||
Low-power mode summary
|
||||
|-------------------------------------------------------------------------------------------------------------------|
|
||||
| Mode name | Entry | Wakeup | Effect on 1.8V | Effect on VDD | Voltage regulator |
|
||||
| | | | domain clocks | domain clocks | |
|
||||
|----------------|------------------|--------------------|--------------------|-----------------|-------------------|
|
||||
| Sleep | WFI | Any interrupt | CPU clock OFF | | |
|
||||
| (Sleep now or |------------------|--------------------| no effect on other | None | ON |
|
||||
| Sleep-on-exit) | WFE | Wakeup event | clocks or analog | | |
|
||||
| | | | clock sources | | |
|
||||
|----------------|------------------|--------------------|--------------------|-----------------|-------------------|
|
||||
| | | | | | ON or in |
|
||||
| Stop | PDDS and LPDS | Any EXTI line | | | low-power mode |
|
||||
| | bits + SLEEPDEEP | (configured in the | | | (depends on Power |
|
||||
| | bit + WFI or WFE | EXTI registers | | | control register |
|
||||
| | | | | | (PWR_CR) |
|
||||
|----------------|------------------|--------------------| All 1.8V domain | HSI and HSE |-------------------|
|
||||
| | | WKUP pin rising | clocks OFF | oscillators OFF | |
|
||||
| Standby | PDDS bit + | edge, RTC alarm, | | | |
|
||||
| | SLEEPDEEP bit + | external reset in | | | OFF |
|
||||
| | WFI or WFE | NRST pin, | | | |
|
||||
| | | IWDG reset | | | |
|
||||
| | | | | | |
|
||||
|-------------------------------------------------------------------------------------------------------------------|
|
||||
*/
|
||||
typedef enum k_cpu_low_power_mode_en {
|
||||
TOS_LOW_POWER_MODE_NONE = 0, /* if set to NONE, disable low power mode */
|
||||
TOS_LOW_POWER_MODE_SLEEP, /* wakeup source: systick/tim/rtc */
|
||||
TOS_LOW_POWER_MODE_STOP, /* wakeup source: rtc wakeup/alarm */
|
||||
TOS_LOW_POWER_MODE_STANDBY, /* wakeup source: rtc alarm */
|
||||
__LOW_POWER_MODE_DUMMY,
|
||||
} k_cpu_lpwr_mode_t;
|
||||
|
||||
typedef struct k_pm_device_st {
|
||||
char *name;
|
||||
|
||||
int (*init)(void);
|
||||
int (*suspend)(void);
|
||||
int (*resume)(void);
|
||||
} k_pm_device_t;
|
||||
|
||||
typedef struct pm_device_control_st {
|
||||
uint8_t count;
|
||||
k_pm_device_t *mgr[K_PM_DEVICE_MAX_COUNT];
|
||||
} pm_device_ctl_t;
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
__API__ k_err_t tos_pm_cpu_lpwr_mode_set(k_cpu_lpwr_mode_t cpu_lpwr_mode);
|
||||
#endif
|
||||
|
||||
__API__ k_err_t tos_pm_device_register(k_pm_device_t *device);
|
||||
|
||||
__KNL__ void pm_init(void);
|
||||
|
||||
__KNL__ void pm_cpu_lpwr_mode_enter(k_cpu_lpwr_mode_t lpwr_mode);
|
||||
|
||||
__KNL__ k_cpu_lpwr_mode_t pm_cpu_lpwr_mode_get(void);
|
||||
|
||||
__KNL__ void pm_idle_pwr_mgr_mode_set(idle_pwrmgr_mode_t idle_pwrmgr_mode);
|
||||
|
||||
__KNL__ int pm_idle_pwr_mgr_mode_is_sleep(void);
|
||||
|
||||
__KNL__ int pm_idle_pwr_mgr_mode_is_tickless(void);
|
||||
|
||||
__KNL__ void pm_power_manager(void);
|
||||
|
||||
__KNL__ int pm_device_suspend(void);
|
||||
|
||||
__KNL__ int pm_device_resume(void);
|
||||
|
||||
#endif /* TOS_CFG_PWR_MGR_EN */
|
||||
|
||||
#endif /* _TOS_PM_H_ */
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _TOS_TICKLESS_H_
|
||||
#define _TOS_TICKLESS_H_
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
|
||||
typedef struct k_tickless_wakeup_alarm_st {
|
||||
int (*init)(void);
|
||||
int (*setup)(k_time_t millisecond);
|
||||
int (*dismiss)(void);
|
||||
k_time_t (*max_delay)(void); /* in millisecond */
|
||||
} k_tickless_wkup_alarm_t;
|
||||
|
||||
__API__ void tos_tickless_wkup_alarm_install(k_cpu_lpwr_mode_t mode, k_tickless_wkup_alarm_t *wkup_alarm);
|
||||
|
||||
__API__ k_err_t tos_tickless_wkup_alarm_init(k_cpu_lpwr_mode_t mode);
|
||||
|
||||
__HOOK__ int tos_bsp_tickless_setup(void);
|
||||
|
||||
__KNL__ int tickless_wkup_alarm_is_installed(k_cpu_lpwr_mode_t mode);
|
||||
|
||||
__KNL__ void tickless_init(void);
|
||||
|
||||
__KNL__ void tickless_proc(void);
|
||||
|
||||
#endif /* TOS_CFG_TICKLESS_EN */
|
||||
|
||||
#endif /* _TOS_TICKLESS_H_ */
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_PWR_MGR_EN > 0u
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
__API__ k_err_t tos_pm_cpu_lpwr_mode_set(k_cpu_lpwr_mode_t cpu_lpwr_mode)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
if (cpu_lpwr_mode != TOS_LOW_POWER_MODE_NONE &&
|
||||
!tickless_wkup_alarm_is_installed(cpu_lpwr_mode)) {
|
||||
return K_ERR_PM_WKUP_SOURCE_NOT_INSTALL;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
k_cpu_lpwr_mode = cpu_lpwr_mode;
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
__STATIC__ int pm_device_is_registered(k_pm_device_t *device)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < k_pm_device_ctl.count; ++i) {
|
||||
if (strcmp(k_pm_device_ctl.mgr[i]->name, device->name) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_pm_device_register(k_pm_device_t *device)
|
||||
{
|
||||
TOS_PTR_SANITY_CHECK(device);
|
||||
|
||||
if (pm_device_is_registered(device)) {
|
||||
return K_ERR_PM_DEVICE_ALREADY_REG;
|
||||
}
|
||||
|
||||
if (k_pm_device_ctl.count >= K_PM_DEVICE_MAX_COUNT) {
|
||||
return K_ERR_PM_DEVICE_OVERFLOW;
|
||||
}
|
||||
|
||||
k_pm_device_ctl.mgr[k_pm_device_ctl.count++] = device;
|
||||
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__KNL__ void pm_init(void)
|
||||
{
|
||||
memset(&k_pm_device_ctl, 0, sizeof(k_pm_device_ctl));
|
||||
k_pm_device_ctl.count = 0u;
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void pm_cpu_sleep_mode_enter(void)
|
||||
{
|
||||
cpu_sleep_mode_enter();
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void pm_cpu_stop_mode_enter(void)
|
||||
{
|
||||
cpu_stop_mode_enter();
|
||||
}
|
||||
|
||||
__STATIC_INLINE__ void pm_cpu_standby_mode_enter(void)
|
||||
{
|
||||
cpu_standby_mode_enter();
|
||||
}
|
||||
|
||||
__KNL__ void pm_cpu_lpwr_mode_enter(k_cpu_lpwr_mode_t lpwr_mode)
|
||||
{
|
||||
if (TOS_LOW_POWER_MODE_SLEEP == lpwr_mode) {
|
||||
pm_cpu_sleep_mode_enter();
|
||||
} else if (TOS_LOW_POWER_MODE_STOP == lpwr_mode) {
|
||||
pm_device_suspend();
|
||||
pm_cpu_stop_mode_enter();
|
||||
pm_device_resume();
|
||||
} else if (TOS_LOW_POWER_MODE_STANDBY == lpwr_mode) {
|
||||
pm_device_suspend();
|
||||
pm_cpu_standby_mode_enter();
|
||||
pm_device_resume();
|
||||
}
|
||||
}
|
||||
|
||||
__KNL__ k_cpu_lpwr_mode_t pm_cpu_lpwr_mode_get(void)
|
||||
{
|
||||
return k_cpu_lpwr_mode;
|
||||
}
|
||||
|
||||
__KNL__ void pm_idle_pwr_mgr_mode_set(idle_pwrmgr_mode_t idle_pwrmgr_mode)
|
||||
{
|
||||
k_idle_pwr_mgr_mode = idle_pwrmgr_mode;
|
||||
}
|
||||
|
||||
__KNL__ int pm_idle_pwr_mgr_mode_is_sleep(void)
|
||||
{
|
||||
return k_idle_pwr_mgr_mode == IDLE_POWER_MANAGER_MODE_SLEEP;
|
||||
}
|
||||
|
||||
__KNL__ int pm_idle_pwr_mgr_mode_is_tickless(void)
|
||||
{
|
||||
return k_idle_pwr_mgr_mode == IDLE_POWER_MANAGER_MODE_TICKLESS;
|
||||
}
|
||||
|
||||
__KNL__ void pm_power_manager(void)
|
||||
{
|
||||
if (pm_idle_pwr_mgr_mode_is_sleep()) {
|
||||
pm_cpu_sleep_mode_enter();
|
||||
}
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
else if (pm_idle_pwr_mgr_mode_is_tickless()) {
|
||||
tickless_proc();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
__KNL__ int pm_device_suspend(void)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < k_pm_device_ctl.count; ++i) {
|
||||
if (*k_pm_device_ctl.mgr[i]->suspend) {
|
||||
(*k_pm_device_ctl.mgr[i]->suspend)();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__KNL__ int pm_device_resume(void)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i = 0; i < k_pm_device_ctl.count; ++i) {
|
||||
if (*k_pm_device_ctl.mgr[i]->resume) {
|
||||
(*k_pm_device_ctl.mgr[i]->resume)();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
/*----------------------------------------------------------------------------
|
||||
* Tencent is pleased to support the open source community by making TencentOS
|
||||
* available.
|
||||
*
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* If you have downloaded a copy of the TencentOS binary from Tencent, please
|
||||
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
|
||||
*
|
||||
* If you have downloaded a copy of the TencentOS source code from Tencent,
|
||||
* please note that TencentOS source code is licensed under the BSD 3-Clause
|
||||
* License, except for the third-party components listed below which are
|
||||
* subject to different license terms. Your integration of TencentOS into your
|
||||
* own projects may require compliance with the BSD 3-Clause License, as well
|
||||
* as the other licenses applicable to the third-party components included
|
||||
* within TencentOS.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "tos_k.h"
|
||||
|
||||
#if TOS_CFG_TICKLESS_EN > 0u
|
||||
|
||||
__API__ void tos_tickless_wkup_alarm_install(k_cpu_lpwr_mode_t mode, k_tickless_wkup_alarm_t *wkup_alarm)
|
||||
{
|
||||
k_tickless_wkup_alarm[mode] = wkup_alarm;
|
||||
}
|
||||
|
||||
__API__ k_err_t tos_tickless_wkup_alarm_init(k_cpu_lpwr_mode_t mode)
|
||||
{
|
||||
if (!k_tickless_wkup_alarm[mode]) {
|
||||
return K_ERR_TICKLESS_WKUP_ALARM_NOT_INSTALLED;
|
||||
}
|
||||
|
||||
if (!k_tickless_wkup_alarm[mode]->init) {
|
||||
return K_ERR_TICKLESS_WKUP_ALARM_NO_INIT;
|
||||
}
|
||||
|
||||
if (k_tickless_wkup_alarm[mode]->init() != 0) {
|
||||
return K_ERR_TICKLESS_WKUP_ALARM_INIT_FAILED;
|
||||
}
|
||||
return K_ERR_NONE;
|
||||
}
|
||||
|
||||
__KNL__ int tickless_wkup_alarm_is_installed(k_cpu_lpwr_mode_t mode)
|
||||
{
|
||||
return k_tickless_wkup_alarm[mode] != K_NULL;
|
||||
}
|
||||
|
||||
__STATIC__ int tickless_wkup_alarm_setup(k_cpu_lpwr_mode_t mode, k_time_t expires)
|
||||
{
|
||||
if (k_tickless_wkup_alarm[mode] && k_tickless_wkup_alarm[mode]->setup) {
|
||||
return k_tickless_wkup_alarm[mode]->setup(expires);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
__STATIC__ int tickless_wkup_alarm_dismiss(k_cpu_lpwr_mode_t mode)
|
||||
{
|
||||
if (k_tickless_wkup_alarm[mode] && k_tickless_wkup_alarm[mode]->dismiss) {
|
||||
return k_tickless_wkup_alarm[mode]->dismiss();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
__STATIC__ k_time_t tickless_wkup_alarm_max_delay(k_cpu_lpwr_mode_t mode)
|
||||
{
|
||||
if (k_tickless_wkup_alarm[mode] && k_tickless_wkup_alarm[mode]->max_delay) {
|
||||
return k_tickless_wkup_alarm[mode]->max_delay();
|
||||
}
|
||||
return (k_time_t)0u;
|
||||
}
|
||||
|
||||
__STATIC__ k_time_t tickless_cpu_sleep_time_get(k_cpu_lpwr_mode_t lpwr_mode)
|
||||
{
|
||||
k_tick_t next_expires;
|
||||
k_time_t time_sleep_ms, max_delay_ms;
|
||||
|
||||
/* the max time(in millisecond) we can sleep */
|
||||
max_delay_ms = tickless_wkup_alarm_max_delay(lpwr_mode);
|
||||
|
||||
next_expires = knl_next_expires_get();
|
||||
if (next_expires == TOS_TIME_FOREVER) {
|
||||
return max_delay_ms;
|
||||
}
|
||||
|
||||
/* how much time should we sleep(in millisecond) */
|
||||
time_sleep_ms = (k_time_t)(next_expires * K_TIME_MILLISEC_PER_SEC / k_cpu_tick_per_second);
|
||||
|
||||
return time_sleep_ms > max_delay_ms ? max_delay_ms : time_sleep_ms;
|
||||
}
|
||||
|
||||
__STATIC__ void tickless_tick_suspend(void)
|
||||
{
|
||||
cpu_systick_suspend();
|
||||
cpu_systick_pending_reset();
|
||||
}
|
||||
|
||||
__STATIC__ void tickless_tick_resume(void)
|
||||
{
|
||||
cpu_systick_suspend();
|
||||
cpu_systick_reset();
|
||||
cpu_systick_resume();
|
||||
}
|
||||
|
||||
__STATIC__ void tickless_tick_fix(k_tick_t tick_sleep)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
/* we wakeup from SLEEP mode, fix the system's tick & timer */
|
||||
tick_update(tick_sleep);
|
||||
|
||||
#if TOS_CFG_TIMER_EN > 0u && TOS_CFG_TIMER_AS_PROC > 0u
|
||||
timer_update();
|
||||
#endif
|
||||
|
||||
tickless_tick_resume();
|
||||
|
||||
TOS_CPU_INT_ENABLE();
|
||||
}
|
||||
|
||||
__STATIC__ void tickless_enter(void)
|
||||
{
|
||||
tickless_tick_suspend();
|
||||
}
|
||||
|
||||
__STATIC__ void tickless_leave(k_time_t time_sleep_ms)
|
||||
{
|
||||
k_tick_t tick_sleep;
|
||||
|
||||
/* how many "ticks" have we sleep */
|
||||
tick_sleep = k_cpu_tick_per_second * time_sleep_ms / K_TIME_MILLISEC_PER_SEC;
|
||||
|
||||
tickless_tick_fix(tick_sleep);
|
||||
|
||||
knl_sched();
|
||||
}
|
||||
|
||||
__KNL__ void tickless_proc(void)
|
||||
{
|
||||
TOS_CPU_CPSR_ALLOC();
|
||||
k_time_t time_sleep;
|
||||
k_cpu_lpwr_mode_t lpwr_mode;
|
||||
|
||||
lpwr_mode = pm_cpu_lpwr_mode_get();
|
||||
if (lpwr_mode == TOS_LOW_POWER_MODE_NONE ||
|
||||
!tickless_wkup_alarm_is_installed(lpwr_mode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TOS_CPU_INT_DISABLE();
|
||||
|
||||
time_sleep = tickless_cpu_sleep_time_get(lpwr_mode); /* in millisecond */
|
||||
if (unlikely(time_sleep == (k_time_t)0)) {
|
||||
TOS_CPU_INT_ENABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
tickless_enter();
|
||||
TOS_CPU_INT_ENABLE();
|
||||
tickless_wkup_alarm_setup(lpwr_mode, time_sleep);
|
||||
pm_cpu_lpwr_mode_enter(lpwr_mode);
|
||||
tickless_wkup_alarm_dismiss(lpwr_mode);
|
||||
tickless_leave(time_sleep);
|
||||
}
|
||||
|
||||
__KNL__ void tickless_init(void)
|
||||
{
|
||||
pm_idle_pwr_mgr_mode_set(IDLE_POWER_MANAGER_MODE_TICKLESS);
|
||||
|
||||
tos_bsp_tickless_setup();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : ch32v20x_conf.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : Library configuration file.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#ifndef __CH32V20x_CONF_H
|
||||
#define __CH32V20x_CONF_H
|
||||
|
||||
#include "ch32v20x_adc.h"
|
||||
#include "ch32v20x_bkp.h"
|
||||
#include "ch32v20x_can.h"
|
||||
#include "ch32v20x_crc.h"
|
||||
#include "ch32v20x_dbgmcu.h"
|
||||
#include "ch32v20x_dma.h"
|
||||
#include "ch32v20x_exti.h"
|
||||
#include "ch32v20x_flash.h"
|
||||
#include "ch32v20x_gpio.h"
|
||||
#include "ch32v20x_i2c.h"
|
||||
#include "ch32v20x_iwdg.h"
|
||||
#include "ch32v20x_pwr.h"
|
||||
#include "ch32v20x_rcc.h"
|
||||
#include "ch32v20x_rtc.h"
|
||||
#include "ch32v20x_spi.h"
|
||||
#include "ch32v20x_tim.h"
|
||||
#include "ch32v20x_usart.h"
|
||||
#include "ch32v20x_wwdg.h"
|
||||
#include "ch32v20x_it.h"
|
||||
#include "ch32v20x_misc.h"
|
||||
|
||||
|
||||
#endif /* __CH32V20x_CONF_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : ch32v20x_it.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : Main Interrupt Service Routines.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#include "ch32v20x_it.h"
|
||||
|
||||
void NMI_Handler(void) __attribute__((interrupt()));
|
||||
void HardFault_Handler(void) __attribute__((interrupt()));
|
||||
|
||||
/*********************************************************************
|
||||
* @fn NMI_Handler
|
||||
*
|
||||
* @brief This function handles NMI exception.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void NMI_Handler(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn HardFault_Handler
|
||||
*
|
||||
* @brief This function handles Hard Fault exception.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : ch32v20x_it.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : This file contains the headers of the interrupt handlers.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#ifndef __CH32V20x_IT_H
|
||||
#define __CH32V20x_IT_H
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#endif /* __CH32V20x_IT_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : main.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : Main program body.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
*@Note
|
||||
task1 and task2 alternate printing
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include "tos_k.h"
|
||||
|
||||
/* Global define */
|
||||
#define TASK1_STK_SIZE 1024
|
||||
#define TASK2_STK_SIZE 1024
|
||||
|
||||
|
||||
/* Global Variable */
|
||||
k_task_t task1;
|
||||
__aligned(4) uint8_t task1_stk[TASK1_STK_SIZE];
|
||||
k_task_t task2;
|
||||
__aligned(4) uint8_t task2_stk[TASK2_STK_SIZE];
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* @fn task1_entry
|
||||
*
|
||||
* @brief task1 program.
|
||||
*
|
||||
* @param *arg - Parameters point of task1
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void task1_entry(void *arg)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
printf("###I am task1\r\n");
|
||||
tos_task_delay(2000);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn task2_entry
|
||||
*
|
||||
* @brief task2 program.
|
||||
*
|
||||
* @param *arg - Parameters point of task2
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void task2_entry(void *arg)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
printf("***I am task2\r\n");
|
||||
tos_task_delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* @fn main
|
||||
*
|
||||
* @brief Main program.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
USART_Printf_Init(115200);
|
||||
printf("SystemClk:%d\r\n",SystemCoreClock);
|
||||
printf("Welcome to TencentOS tiny(%s)\r\n", TOS_VERSION);
|
||||
tos_knl_init();
|
||||
tos_task_create(&task1, "task1", task1_entry, NULL, 3, task1_stk, TASK1_STK_SIZE, 0); // Create task1
|
||||
tos_task_create(&task2, "task2", task2_entry, NULL, 3, task2_stk, TASK2_STK_SIZE, 0);// Create task2
|
||||
tos_knl_start();
|
||||
|
||||
printf("should not run at here!\r\n");
|
||||
|
||||
while(1)
|
||||
{
|
||||
asm("nop");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,986 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : system_ch32v20x.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : CH32V20x Device Peripheral Access Layer System Source File.
|
||||
* For HSE = 32Mhz (CH32V208x/CH32V203RBT6)
|
||||
* For HSE = 8Mhz (other CH32V203x)
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#include "ch32v20x.h"
|
||||
|
||||
/*
|
||||
* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
|
||||
* reset the HSI is used as SYSCLK source).
|
||||
* If none of the define below is enabled, the HSI is used as System clock source.
|
||||
*/
|
||||
//#define SYSCLK_FREQ_HSE HSE_VALUE
|
||||
//#define SYSCLK_FREQ_48MHz_HSE 48000000
|
||||
//#define SYSCLK_FREQ_56MHz_HSE 56000000
|
||||
//#define SYSCLK_FREQ_72MHz_HSE 72000000
|
||||
#define SYSCLK_FREQ_96MHz_HSE 96000000
|
||||
//#define SYSCLK_FREQ_120MHz_HSE 120000000
|
||||
//#define SYSCLK_FREQ_144MHz_HSE 144000000
|
||||
//#define SYSCLK_FREQ_HSI HSI_VALUE
|
||||
//#define SYSCLK_FREQ_48MHz_HSI 48000000
|
||||
//#define SYSCLK_FREQ_56MHz_HSI 56000000
|
||||
//#define SYSCLK_FREQ_72MHz_HSI 72000000
|
||||
//#define SYSCLK_FREQ_96MHz_HSI 96000000
|
||||
//#define SYSCLK_FREQ_120MHz_HSI 120000000
|
||||
//#define SYSCLK_FREQ_144MHz_HSI 144000000
|
||||
|
||||
/* Clock Definitions */
|
||||
#ifdef SYSCLK_FREQ_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSE
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSE; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSI
|
||||
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSI; /* System Clock Frequency (Core Clock) */
|
||||
#else
|
||||
uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */
|
||||
|
||||
#endif
|
||||
|
||||
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
|
||||
|
||||
/* system_private_function_proto_types */
|
||||
static void SetSysClock(void);
|
||||
|
||||
#ifdef SYSCLK_FREQ_HSE
|
||||
static void SetSysClockToHSE( void );
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSE
|
||||
static void SetSysClockTo48_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSE
|
||||
static void SetSysClockTo56_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSE
|
||||
static void SetSysClockTo72_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSE
|
||||
static void SetSysClockTo96_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSE
|
||||
static void SetSysClockTo120_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSE
|
||||
static void SetSysClockTo144_HSE( void );
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSI
|
||||
static void SetSysClockTo48_HSI( void );
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSI
|
||||
static void SetSysClockTo56_HSI( void );
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSI
|
||||
static void SetSysClockTo72_HSI( void );
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSI
|
||||
static void SetSysClockTo96_HSI( void );
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSI
|
||||
static void SetSysClockTo120_HSI( void );
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSI
|
||||
static void SetSysClockTo144_HSI( void );
|
||||
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SystemInit
|
||||
*
|
||||
* @brief Setup the microcontroller system Initialize the Embedded Flash Interface,
|
||||
* the PLL and update the SystemCoreClock variable.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void SystemInit (void)
|
||||
{
|
||||
RCC->CTLR |= (uint32_t)0x00000001;
|
||||
RCC->CFGR0 &= (uint32_t)0xF8FF0000;
|
||||
RCC->CTLR &= (uint32_t)0xFEF6FFFF;
|
||||
RCC->CTLR &= (uint32_t)0xFFFBFFFF;
|
||||
RCC->CFGR0 &= (uint32_t)0xFF80FFFF;
|
||||
RCC->INTR = 0x009F0000;
|
||||
SetSysClock();
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SystemCoreClockUpdate
|
||||
*
|
||||
* @brief Update SystemCoreClock variable according to Clock Register Values.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void SystemCoreClockUpdate (void)
|
||||
{
|
||||
uint32_t tmp = 0, pllmull = 0, pllsource = 0, Pll_6_5 = 0;
|
||||
|
||||
tmp = RCC->CFGR0 & RCC_SWS;
|
||||
|
||||
switch (tmp)
|
||||
{
|
||||
case 0x00:
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
break;
|
||||
case 0x04:
|
||||
SystemCoreClock = HSE_VALUE;
|
||||
break;
|
||||
case 0x08:
|
||||
pllmull = RCC->CFGR0 & RCC_PLLMULL;
|
||||
pllsource = RCC->CFGR0 & RCC_PLLSRC;
|
||||
pllmull = ( pllmull >> 18) + 2;
|
||||
|
||||
if(pllmull == 17) pllmull = 18;
|
||||
|
||||
if (pllsource == 0x00)
|
||||
{
|
||||
if(EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE){
|
||||
SystemCoreClock = HSI_VALUE * pllmull;
|
||||
}
|
||||
else{
|
||||
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (CH32V20x_D8W)
|
||||
if((RCC->CFGR0 & (3<<22)) == (3<<22))
|
||||
{
|
||||
SystemCoreClock = ((HSE_VALUE>>1)) * pllmull;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET)
|
||||
{
|
||||
#if defined (CH32V20x_D8) || defined (CH32V20x_D8W)
|
||||
SystemCoreClock = ((HSE_VALUE>>2) >> 1) * pllmull;
|
||||
#else
|
||||
SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (CH32V20x_D8) || defined (CH32V20x_D8W)
|
||||
SystemCoreClock = (HSE_VALUE>>2) * pllmull;
|
||||
#else
|
||||
SystemCoreClock = HSE_VALUE * pllmull;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if(Pll_6_5 == 1) SystemCoreClock = (SystemCoreClock / 2);
|
||||
|
||||
break;
|
||||
default:
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)];
|
||||
SystemCoreClock >>= tmp;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClock
|
||||
*
|
||||
* @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClock(void)
|
||||
{
|
||||
#ifdef SYSCLK_FREQ_HSE
|
||||
SetSysClockToHSE();
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSE
|
||||
SetSysClockTo48_HSE();
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSE
|
||||
SetSysClockTo56_HSE();
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSE
|
||||
SetSysClockTo72_HSE();
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSE
|
||||
SetSysClockTo96_HSE();
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSE
|
||||
SetSysClockTo120_HSE();
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSE
|
||||
SetSysClockTo144_HSE();
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSI
|
||||
SetSysClockTo48_HSI();
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSI
|
||||
SetSysClockTo56_HSI();
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSI
|
||||
SetSysClockTo72_HSI();
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSI
|
||||
SetSysClockTo96_HSI();
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSI
|
||||
SetSysClockTo120_HSI();
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSI
|
||||
SetSysClockTo144_HSI();
|
||||
|
||||
#endif
|
||||
|
||||
/* If none of the define above is enabled, the HSI is used as System clock
|
||||
* source (default after reset)
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
#ifdef SYSCLK_FREQ_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockToHSE
|
||||
*
|
||||
* @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockToHSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
|
||||
|
||||
/* Select HSE as system clock source
|
||||
* CH32V20x_D6 (HSE=8MHZ)
|
||||
* CH32V20x_D8 (HSE=32MHZ)
|
||||
* CH32V20x_D8W (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_HSE;
|
||||
|
||||
/* Wait till HSE is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo48_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo48_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 6 = 48 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo56_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo56_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 7 = 56 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo72_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo72_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 9 = 72 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
|
||||
RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo96_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo96_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
|
||||
RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo120_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo120_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if(HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
#if defined (CH32V20x_D8W)
|
||||
RCC->CFGR0 |= (uint32_t)(3<<22);
|
||||
/* HCLK = SYSCLK/2 */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2;
|
||||
#else
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
#endif
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 15 = 120 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 15 = 120 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/2 * 15 = 240 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
|
||||
RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSE
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo144_HSE
|
||||
*
|
||||
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo144_HSE(void)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
|
||||
RCC->CTLR |= ((uint32_t)RCC_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CTLR & RCC_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CTLR & RCC_HSERDY) != RESET)
|
||||
{
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
}
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 18 = 144 MHz (HSE=8MHZ)
|
||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ)
|
||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ)
|
||||
*/
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
|
||||
RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If HSE fails to start-up, the application will have wrong clock
|
||||
* configuration. User can add here some code to deal with this error
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_48MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo48_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo48_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 6 = 48 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_56MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo56_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo56_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 7 = 48 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined SYSCLK_FREQ_72MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo72_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo72_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 9 = 72 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined SYSCLK_FREQ_96MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo96_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo96_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 12 = 96 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL12);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined SYSCLK_FREQ_120MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo120_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo120_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 15 = 120 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
|
||||
RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL15);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
#elif defined SYSCLK_FREQ_144MHz_HSI
|
||||
|
||||
/*********************************************************************
|
||||
* @fn SetSysClockTo144_HSI
|
||||
*
|
||||
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static void SetSysClockTo144_HSI(void)
|
||||
{
|
||||
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
|
||||
|
||||
/* PLL configuration: PLLCLK = HSI * 18 = 144 MHz */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
|
||||
|
||||
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL18);
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CTLR & RCC_PLLRDY) == 0)
|
||||
{
|
||||
}
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
|
||||
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : system_ch32v20x.h
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2021/06/06
|
||||
* Description : CH32V20x Device Peripheral Access Layer System Header File.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#ifndef __SYSTEM_ch32v20x_H
|
||||
#define __SYSTEM_ch32v20x_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */
|
||||
|
||||
/* System_Exported_Functions */
|
||||
extern void SystemInit(void);
|
||||
extern void SystemCoreClockUpdate(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__CH32V20x_SYSTEM_H */
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user