first submission

This commit is contained in:
qiyongshuang
2023-02-01 14:19:13 +08:00
parent d534aad004
commit b79c6ac80d
3711 changed files with 745432 additions and 2 deletions
+167
View File
@@ -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="&quot;${workspace_loc:/${ProjName}/Startup}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/common/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/rv32/gcc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/core}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/core/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/hal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/hal/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/pm}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/pm/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/TOS_CONFIG}&quot;"/>
</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="&quot;${workspace_loc:/${ProjName}/Debug}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Core}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/User}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Peripheral/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/common/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/arch/risc-v/rv32/gcc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/core}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/core/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/hal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/hal/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/pm}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/kernel/pm/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/TencentOS_Tiny/TOS_CONFIG}&quot;"/>
</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="&quot;${workspace_loc:/${ProjName}/Ld/Link.ld}&quot;"/>
</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="&quot;../LD&quot;"/>
</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>
+59
View File
@@ -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 &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
</project>
+16
View File
@@ -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£Š ‚«*BP Mš"
@@ -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_ */
@@ -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_ */
@@ -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_ */
@@ -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 */
+94
View File
@@ -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 */