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
+164
View File
@@ -0,0 +1,164 @@
<?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.target.isa.xw.1491146035" name="Extra Compressed extension (RVXW)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.xw" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.saverestore.1175750723" name="Small prologue/epilogue (-msave-restore)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.saverestore" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.nocommon.1177125388" name="No common unitialized (-fno-common)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.nocommon" 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:/ADC_DMA}/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;"/>
</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}/User/Host_UDisk}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/User/USB_Host}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Udisk_Lib}&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;"/>
</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="false" 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">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Udisk_Lib}&quot;"/>
</option>
<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="false" 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">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Udisk_Lib/libRV3UFI.a}&quot;"/>
</option>
<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"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.libs.1062411404" name="Libraries (-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.libs" useByScannerDiscovery="false" valueType="libs">
<listOptionValue builtIn="false" value="RV3UFI"/>
</option>
<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="User/usb_host_iap_0.h|User/usb_host_iap_0.c|Udisk_Lib|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|startup_ch32v20x_D6.S|startup_ch32v30x_D8.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Startup"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Udisk_Lib"/>
</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"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="obj">
<resource resourceType="PROJECT" workspacePath="/ADC_DMA"/>
</configuration>
<configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/000"/>
</configuration>
<configuration configurationName="Release">
<resource resourceType="PROJECT" workspacePath="/000"/>
</configuration>
</storageModule>
</cproject>
+66
View File
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" ?>
<projectDescription>
<name>Host_Udisk_Exams</name>
<comment />
<projects />
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments />
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<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>
<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>
<linkedResources>
<link>
<name>Core</name>
<type>2</type>
<location>PARENT-3-PROJECT_LOC/SRC/Core</location>
</link>
<link>
<name>Debug</name>
<type>2</type>
<location>PARENT-3-PROJECT_LOC/SRC/Debug</location>
</link>
<link>
<name>Ld</name>
<type>2</type>
<location>PARENT-3-PROJECT_LOC/SRC/Ld</location>
</link>
<link>
<name>Peripheral</name>
<type>2</type>
<location>PARENT-3-PROJECT_LOC/SRC/Peripheral</location>
</link>
<link>
<name>Startup</name>
<type>2</type>
<location>PARENT-3-PROJECT_LOC/SRC/Startup</location>
</link>
<link>
<name>Udisk_Lib</name>
<type>2</type>
<location>PARENT-1-PROJECT_LOC/Udisk_Lib</location>
</link>
</linkedResources>
</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="-91903898395255320" 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>
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding//User/Host_UDisk/UDisk_Operation.h=UTF-8
+16
View File
@@ -0,0 +1,16 @@
Mcu Type=CH32V30x
Address=0x08000000
Erase All=true
Program=true
Verify=true
Reset=true
Vendor=WCH
Link=WCH-Link
Toolchain=RISC-V
Series=CH32V307
Description=ROM(byte): 256K, SRAM(byte): 64K, CHIP PINS: 64, GPIO PORTS: 51.\nWCH CH32V3 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.4
Target Path=obj\Host_UDisk_Exams.hex
MCU=CH32V307RVT6
@@ -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,195 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : UDisk_Func_CreatDir.c
* Author : WCH
* Version : V1.0.0
* Date : 2022/11/22
* Description : USB full-speed port host operation functions.
*********************************************************************************
* 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.
*******************************************************************************/
/*******************************************************************************/
/* Header File */
#include "Udisk_Operation.h"
/*******************************************************************************
* Function Name : CreateDirectory
* Description : 新建目录并打开,如果目录已经存在则直接打开,目录名在mCmdParam.Create.mPathName中,与文件名规则相同
* Input :
* Output : None
* Return : ERR_SUCCESS = 打开目录成功或者创建目录成功,
ERR_FOUND_NAME = 已经存在同名文件,
ERR_MISS_DIR = 路径名无效或者上级目录不存在
*******************************************************************************/
uint8_t CreateDirectory( void )
{
uint8_t i, j;
uint32_t UpDirCluster;
uint8_t * DirXramBuf;
uint8_t *DirConstData;
j = 0xFF;
for ( i = 0; i != sizeof( mCmdParam.Create.mPathName ); i ++ ) //检查目录路径
{
if ( mCmdParam.Create.mPathName[ i ] == 0 )
{
break;
}
if ( mCmdParam.Create.mPathName[ i ] == PATH_SEPAR_CHAR1 || mCmdParam.Create.mPathName[ i ] == PATH_SEPAR_CHAR2 )
{
j = i; //记录上级目录
}
}
i = ERR_SUCCESS;
if ( j == 0 || (j == 2 && mCmdParam.Create.mPathName[1] == ':') )
{
UpDirCluster = 0; //在根目录下创建子目录
}
else
{
if ( j != 0xFF ) //对于绝对路径应该获取上级目录的起始簇号
{
mCmdParam.Create.mPathName[ j ] = 0;
i = CHRV3FileOpen( ); //打开上级目录
if ( i == ERR_SUCCESS )
{
i = ERR_MISS_DIR; //是文件而非目录
}
else if ( i == ERR_OPEN_DIR )
{
i = ERR_SUCCESS; //成功打开上级目录
}
mCmdParam.Create.mPathName[ j ] = PATH_SEPAR_CHAR1; //恢复目录分隔符
}
UpDirCluster = CHRV3vStartCluster; //保存上级目录的起始簇号
}
if ( i == ERR_SUCCESS ) //成功获取上级目录的起始簇号
{
i = CHRV3FileOpen( ); //打开本级子目录
if ( i == ERR_SUCCESS )
{
i = ERR_FOUND_NAME; //是文件而非目录
}
else if ( i == ERR_OPEN_DIR )
{
i = ERR_SUCCESS; //目录已经存在
}
else if ( i == ERR_MISS_FILE ) //目录不存在,可以新建
{
i = CHRV3FileCreate( ); //以创建文件的方法创建目录
if ( i == ERR_SUCCESS )
{
if ( pDISK_FAT_BUF == pDISK_BASE_BUF )
{
memset(pDISK_FAT_BUF,0,CHRV3vSectorSize); //如果FILE_DATA_BUF与DISK_BASE_BUF合用则必须清除磁盘缓冲区
}
DirXramBuf = pDISK_FAT_BUF; //文件数据缓冲区
DirConstData = ". \x10\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x21\x30\x0\x0\x0\x0\x0\x0.. \x10\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x21\x30\x0\x0\x0\x0\x0\x0";
for ( i = 0x40; i != 0; i -- ) //目录的保留单元,分别指向自身和上级目录
{
*DirXramBuf = *DirConstData;
DirXramBuf ++;
DirConstData ++;
}
*(pDISK_FAT_BUF+0x1A) = ( (uint8_t *)&CHRV3vStartCluster )[3];//自身的起始簇号
*(pDISK_FAT_BUF+0x1B) = ( (uint8_t *)&CHRV3vStartCluster )[2];
*(pDISK_FAT_BUF+0x14) = ( (uint8_t *)&CHRV3vStartCluster )[1];
*(pDISK_FAT_BUF+0x15) = ( (uint8_t *)&CHRV3vStartCluster )[0];
*(pDISK_FAT_BUF+0x20+0x1A) = ( (uint8_t *)&UpDirCluster )[3];//上级目录的起始簇号
*(pDISK_FAT_BUF+0x20+0x1B) = ( (uint8_t *)&UpDirCluster )[2];
*(pDISK_FAT_BUF+0x20+0x14) = ( (uint8_t *)&UpDirCluster )[1];
*(pDISK_FAT_BUF+0x20+0x15) = ( (uint8_t *)&UpDirCluster )[0];
// for ( count = 0x40; count != CHRV3vSectorSizeH*256; count ++ ) { /* 清空目录区剩余部分 */
// *DirXramBuf = 0;
// DirXramBuf ++;
// }
mCmdParam.Write.mSectorCount = 1;
mCmdParam.Write.mDataBuffer = pDISK_FAT_BUF; //指向文件数据缓冲区的起始地址
i = CHRV3FileWrite( ); //向文件写入数据
if ( i == ERR_SUCCESS )
{
DirXramBuf = pDISK_FAT_BUF;
for ( i = 0x40; i != 0; i -- ) //清空目录区
{
*DirXramBuf = 0;
DirXramBuf ++;
}
for ( j = 1; j != CHRV3vSecPerClus; j ++ )
{
if ( pDISK_FAT_BUF == pDISK_BASE_BUF )
{
memset(pDISK_FAT_BUF,0,CHRV3vSectorSize); //如果FILE_DATA_BUF与DISK_BASE_BUF合用则必须清除磁盘缓冲区
}
mCmdParam.Write.mSectorCount = 1;
mCmdParam.Write.mDataBuffer = pDISK_FAT_BUF; //指向文件数据缓冲区的起始地址
i = CHRV3FileWrite( ); //清空目录的剩余扇区
if ( i != ERR_SUCCESS )
{
break;
}
}
if ( j == CHRV3vSecPerClus ) //成功清空目录
{
mCmdParam.Modify.mFileSize = 0; //目录的长度总是0
mCmdParam.Modify.mFileDate = 0xFFFF;
mCmdParam.Modify.mFileTime = 0xFFFF;
mCmdParam.Modify.mFileAttr = 0x10; //置目录属性
i = CHRV3FileModify( ); //将文件信息修改为目录
}
}
}
}
}
return( i );
}
/*********************************************************************
* @fn UDisk_USBH_CreatDirectory
*
* @brief Demo Function For UDisk Create Directory (EXAM9)
*
* @return none
*/
void UDisk_USBH_CreatDirectory( void )
{
uint8_t i;
uint8_t ret;
ret = UDisk_USBH_DiskReady( );
if( ( ret == DISK_READY )&&( UDisk_Opeation_Flag == 1 ) )
{
UDisk_Opeation_Flag = 0;
printf("CHRV3DiskStatus:%02x\r\n",CHRV3DiskStatus);
printf( "Create Level 1 Directory /YEAR2004 \r\n" );
strcpy( mCmdParam.Create.mPathName, "/YEAR2004" ); //目录名,该目录建在根目录下
ret = CreateDirectory( ); //新建或者打开目录
mStopIfError( ret );
/* 目录新建或者打开成功,下面在这个子目录中新建一个演示文件 */
printf( "Create New File /YEAR2004/DEMO2004.TXT \r\n" );
strcpy( mCmdParam.Create.mPathName, "/YEAR2004/DEMO2004.TXT" );//文件名
ret = CHRV3FileCreate( ); //新建文件并打开,如果文件已经存在则先删除后再新建
mStopIfError( ret );
printf( "Write some data to file DEMO2004.TXT \r\n" );
i = sprintf( Com_Buffer, "演示文件\xd\xa" );
mCmdParam.ByteWrite.mByteCount = i; //指定本次写入的字节数,单次读写的长度不能超过MAX_BYTE_IO
mCmdParam.ByteWrite.mByteBuffer = Com_Buffer; //指向缓冲区
ret = CHRV3ByteWrite( ); //以字节为单位向文件写入数据,单次读写的长度不能超过MAX_BYTE_IO
mStopIfError( ret );
printf( "Close file DEMO2004.TXT \r\n" );
mCmdParam.Close.mUpdateLen = 1; //自动计算文件长度,以字节为单位写文件,建议让程序库关闭文件以便自动更新文件长度
ret = CHRV3FileClose( );
mStopIfError( ret );
/* 下面新建二级子目录,方法与前面的一级子目录完全相同 */
printf( "Create Level 2 Directory /YEAR2004/MONTH05 \r\n" );
strcpy( mCmdParam.Create.mPathName, "/YEAR2004/MONTH05" ); //目录名,该目录建在YEAR2004子目录下,YEAR2004目录必须事先存在
ret = CreateDirectory( ); //新建或者打开目录
mStopIfError( ret );
printf( "Close\r\n" );
mCmdParam.Close.mUpdateLen = 0; //对于目录不需要自动更新文件长度
ret = CHRV3FileClose( ); //关闭目录,目录不需要关闭,关闭只是为了防止下面误操作
mStopIfError( ret );
}
}
@@ -0,0 +1,596 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : Udisk_Func_longname.c
* Author : WCH
* Version : V1.0.0
* Date : 2022/11/22
* Description : USB full-speed port host operation functions.
*********************************************************************************
* 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.
*******************************************************************************/
/*******************************************************************************/
/* Header File */
#include "Udisk_Operation.h"
/*******************************************************************************/
/* Variable Definition */
uint8_t LongNameBuf[ LONG_NAME_BUF_LEN ];
/*
长文件名示例(UNICODE编码的大小端 必须与UNICODE_ENDIAN定义相同)
以下是LongName里编码内容:
建立长文件名,输入两个参数: 1.采用(unicode 大端),字符串末尾用两个0表示结束;2.ANSI编码短文件名.TXT
*/
uint8_t LongName[ ] =
#if UNICODE_ENDIAN == 1
{
0x5E, 0xFA, 0x7A, 0xCB, 0x95, 0x7F, 0x65, 0x87, 0x4E, 0xF6, 0x54, 0x0D, 0xFF, 0x0C, 0x8F, 0x93,
0x51, 0x65, 0x4E, 0x24, 0x4E, 0x2A, 0x53, 0xC2, 0x65, 0x70, 0xFF, 0x1A, 0x00, 0x20, 0x00, 0x31,
0x00, 0x2E, 0x91, 0xC7, 0x75, 0x28, 0x00, 0x28, 0x00, 0x75, 0x00, 0x6E, 0x00, 0x69, 0x00, 0x63,
0x00, 0x6F, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x59, 0x27, 0x7A, 0xEF, 0x00, 0x29, 0xFF, 0x0C,
0x5B, 0x57, 0x7B, 0x26, 0x4E, 0x32, 0x67, 0x2B, 0x5C, 0x3E, 0x75, 0x28, 0x4E, 0x24, 0x4E, 0x2A,
0x00, 0x30, 0x88, 0x68, 0x79, 0x3A, 0x7E, 0xD3, 0x67, 0x5F, 0x00, 0x3B, 0x00, 0x32, 0x00, 0x2E,
0x00, 0x41, 0x00, 0x4E, 0x00, 0x53, 0x00, 0x49, 0x7F, 0x16, 0x78, 0x01, 0x77, 0xED, 0x65, 0x87,
0x4E, 0xF6, 0x54, 0x0D, 0x00, 0x2E, 0x00, 0x54, 0x00, 0x58, 0x00, 0x54
};
#else
{
0xFA, 0x5E, 0xCB, 0x7A, 0x7F, 0x95, 0x87, 0x65, 0xF6, 0x4E, 0x0D, 0x54, 0x0C, 0xFF, 0x93, 0x8F,
0x65, 0x51, 0x24, 0x4E, 0x2A, 0x4E, 0xC2, 0x53, 0x70, 0x65, 0x1A, 0xFF, 0x20, 0x00, 0x31, 0x00,
0x2E, 0x00, 0xC7, 0x91, 0x28, 0x75, 0x28, 0x00, 0x75, 0x00, 0x6E, 0x00, 0x69, 0x00, 0x63, 0x00,
0x6F, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x00, 0x27, 0x59, 0xEF, 0x7A, 0x29, 0x00, 0x0C, 0xFF,
0x57, 0x5B, 0x26, 0x7B, 0x32, 0x4E, 0x2B, 0x67, 0x3E, 0x5C, 0x28, 0x75, 0x24, 0x4E, 0x2A, 0x4E,
0x30, 0x00, 0x68, 0x88, 0x3A, 0x79, 0xD3, 0x7E, 0x5F, 0x67, 0x3B, 0x00, 0x32, 0x00, 0x2E, 0x00,
0x41, 0x00, 0x4E, 0x00, 0x53, 0x00, 0x49, 0x00, 0x16, 0x7F, 0x01, 0x78, 0xED, 0x77, 0x87, 0x65,
0xF6, 0x4E, 0x0D, 0x54, 0x2E, 0x00, 0x54, 0x00, 0x58, 0x00, 0x54, 0x00
};
#endif
/*********************************************************************
* @fn UDisk_USBH_Longname
*
* @brief Demo Function For UDisk long-name Operation(EXAM 13)
*
* @return none
*/
void UDisk_USBH_Longname( void )
{
uint8_t ret, i, len;
uint16_t j;
ret = UDisk_USBH_DiskReady( );
if( ( ret == DISK_READY )&&( UDisk_Opeation_Flag == 1 ) )
{
UDisk_Opeation_Flag = 0;
/*==================== 以下演示创建及读取长文件名 ============================*/
// 复制长文件名(UNICODE 大端)到LongNameBuf里
len = LongName_Len;
memcpy( LongNameBuf, LongName, len );
// 末尾用两个0表示结束
LongNameBuf[len] = 0x00;
LongNameBuf[len + 1] = 0x00;
// 该长文件名的ANSI编码短文件名(8+3格式)
strcpy( mCmdParam.Create.mPathName, "\\长文件名.TXT" );
i = CHRV3CreateLongName( );
if( i == ERR_SUCCESS )
{
DUG_PRINTF( "Created Long Name OK!\r\n" );
}
else
{
/* Error code defined in "udisk_operaion.h" */
DUG_PRINTF( "Error Code: %02X\r\n", (uint16_t)i );
}
DUG_PRINTF( "Get long Name#\r\n" );
strcpy( mCmdParam.Open.mPathName, "\\长文件名.TXT" );
// 以上需要输入文件名的完整路径
i = CHRV3GetLongName( );
if( i == ERR_SUCCESS )
{
// 长文件名收集完成,以UNICODE编码方式(按UNICODE_ENDIAN定义)
// 存放在LongNameBuf缓冲里,长文件名最后用两个0结束.
// 以下显示缓冲区里所有数据
DUG_PRINTF( "LongNameBuf: " );
for( j=0; j!=LONG_NAME_BUF_LEN; j++ )
{
DUG_PRINTF( "%02X ", (uint16_t)LongNameBuf[j] );
}
DUG_PRINTF( "\r\n" );
}
else
{
/* Error code defined in "udisk_operaion.h" */
DUG_PRINTF( "Error Code: %02X\r\n", (uint16_t)i );
}
}
}
/*********************************************************************
* @fn CheckNameSum
*
* @brief 检查长文件名的短文件名检验和
*
* @return 计算后的校验和
*/
uint8_t CheckNameSum( uint8_t *p )
{
uint8_t FcbNameLen;
uint8_t Sum;
Sum = 0;
for (FcbNameLen=0; FcbNameLen!=11; FcbNameLen++)
Sum = ((Sum & 1) ? 0x80 : 0) + (Sum >> 1) + *p++;
return Sum;
}
/*********************************************************************
* @fn AnalyzeLongName
*
* @brief 整理长文件名 返回有几个的26长度
*
* @return 返回有多少个26的长度
*/
uint8_t AnalyzeLongName( void )
{
uint8_t i, j;
uint16_t index;
i = FALSE;
for( index=0; index!=LONG_NAME_BUF_LEN; index = index + 2 )
{
if( ( LongNameBuf[index] == 0 ) && ( LongNameBuf[index+1] == 0 ) )
{
i = TRUE;
break;
}
}
if( ( i == FALSE ) || ( index == 0) )
return 0; // 返回0表示错误的长文件名
i = index % 26;
if( i != 0 )
{
index += 2;
if( index % 26 != 0 ) // 加0刚好结束
{
for( j=i+2; j!=26; j++ )// 把剩余数据填为0XFF
LongNameBuf[index++] = 0xff;
}
}
return (index / 26);
}
/*********************************************************************
* @fn CHRV3CreateLongName
*
* @brief 创建长文件名,需要输入短文件名的完整路径
*
* @return 操作状态
*/
uint8_t CHRV3CreateLongName( void )
{
// 分析 保留文件路径 创建一个空文件 得到FDT偏移和其所在扇区 删除文件
// 向后偏移扇区 可能失败 如FAT12/16处在根目录处 填充完毕后再次创建文件
uint8_t i;
uint8_t len; // 存放路径的长度
uint16_t index; // 长文件偏移索引
uint16_t indexBak; // 长文件偏移索引备份
uint32_t Secoffset; // 扇区偏移
uint8_t Fbit; // 第一次进入写扇区
uint8_t Mult; // 长文件名长度26的倍数
uint8_t MultBak; // 长文件名长度26的倍数备份
uint16_t Backoffset; // 保存文件偏移备份
uint16_t BackoffsetBak; // 保存偏移备份的备份
uint32_t BackFdtSector; // 保寸偏移上一个扇区
uint8_t sum; // 保存长文件名的校验和
uint8_t BackPathBuf[MAX_PATH_LEN]; // 保存文件路径
Mult = AnalyzeLongName( ); // 保存长文件名是26的倍数
if( Mult == 0 )
return ERR_LONG_NAME;
MultBak = Mult;
i = CHRV3FileOpen(); // 短文件名存在则返回错误
if( i == ERR_SUCCESS )
return ERR_NAME_EXIST;
i = CHRV3FileCreate( );
if( i == ERR_SUCCESS )
{
Backoffset = CHRV3vFdtOffset;
BackoffsetBak = Backoffset;
BackFdtSector = CHRV3vFdtLba;
sum = CheckNameSum( &DISK_BASE_BUF[Backoffset ] );
for( i=0; i!=MAX_PATH_LEN; i++ ) // 对文件路径进行备份
BackPathBuf[i] = mCmdParam.Open.mPathName[i];
CHRV3FileErase( ); // 删除此文件
Secoffset = 0; // 从0开始偏移
index = Mult*26; // 得到长文件名的长度
indexBak = index;
Fbit = FALSE; // 默认没有进入
// 打开上级 进行数据填充数据
P_RETRY:
for(len=0; len!=MAX_PATH_LEN; len++)
{
if(mCmdParam.Open.mPathName[len] == 0)
break; // 得到字符串长度
}
for(i=len-1; i!=0xff; i--) // 得到上级目录位置
{
if((mCmdParam.Open.mPathName[i] == '\\') || (mCmdParam.Open.mPathName[i] == '/'))
break;
}
mCmdParam.Open.mPathName[i] = 0x00;
if( i==0 ) // 打开一级目录注意:处在根目录开始的特殊情况
{
mCmdParam.Open.mPathName[0] = '/';
mCmdParam.Open.mPathName[1] = 0;
}
i = CHRV3FileOpen(); // 打开上级目录
if( i == ERR_OPEN_DIR )
{
while( 1 ) // 循环填写 直到完成
{
mCmdParam.Locate.mSectorOffset = Secoffset;
i = CHRV3FileLocate( );
if( i == ERR_SUCCESS )
{
if( Fbit ) // 第二次进入次写扇区
{
if( mCmdParam.Locate.mSectorOffset != 0x0FFFFFFFF )
{
BackFdtSector = mCmdParam.Locate.mSectorOffset;
Backoffset = 0;
}
else
{
for( i=0; i!=MAX_PATH_LEN; i++ )// 还原文件路径
mCmdParam.Open.mPathName[i] = BackPathBuf[i];
i = CHRV3FileCreate( ); // 进行空间扩展
if( i != ERR_SUCCESS )
return i;
CHRV3FileErase( );
goto P_RETRY; // 重新打开上级目录
}
}
if( BackFdtSector == mCmdParam.Locate.mSectorOffset )
{
mCmdParam.Read.mSectorCount = 1; // 读一个扇区到磁盘缓冲区
mCmdParam.Read.mDataBuffer = &DISK_BASE_BUF[0];
i = CHRV3FileRead( );
CHRV3DirtyBuffer( ); // 清除磁盘缓冲区
if( i!= ERR_SUCCESS )
return i;
i = ( CHRV3vSectorSize - Backoffset ) / 32;
if( Mult > i )
Mult = Mult - i; // 剩余的倍数
else
{
i = Mult;
Mult = 0;
}
for( len=i; len!=0; len-- )
{
indexBak -= 26;
index = indexBak;
for( i=0; i!=5; i++) // 长文件名的1-5个字符
{ // 在磁盘上UNICODE用小端方式存放
#if UNICODE_ENDIAN == 1
DISK_BASE_BUF[Backoffset + i*2 + 2 ] =
LongNameBuf[index++];
DISK_BASE_BUF[Backoffset + i*2 + 1 ] =
LongNameBuf[index++];
#else
DISK_BASE_BUF[Backoffset + i*2 + 1 ] =
LongNameBuf[index++];
DISK_BASE_BUF[Backoffset + i*2 + 2 ] =
LongNameBuf[index++];
#endif
}
for( i =0; i!=6; i++) // 长文件名的6-11个字符
{
#if UNICODE_ENDIAN == 1
DISK_BASE_BUF[Backoffset + 14 + i*2 + 1 ] =
LongNameBuf[index++];
DISK_BASE_BUF[Backoffset + 14 + i*2 ] =
LongNameBuf[index++];
#else
DISK_BASE_BUF[Backoffset + 14 + i*2 ] =
LongNameBuf[index++];
DISK_BASE_BUF[Backoffset + 14 + i*2 + 1 ] =
LongNameBuf[index++];
#endif
}
for( i=0; i!=2; i++) // 长文件名的12-13个字符
{
#if UNICODE_ENDIAN == 1
DISK_BASE_BUF[Backoffset + 28 + i*2 + 1 ] =
LongNameBuf[index++];
DISK_BASE_BUF[Backoffset + 28 + i*2 ] =
LongNameBuf[index++];
#else
DISK_BASE_BUF[Backoffset + 28 + i*2 ] =
LongNameBuf[index++];
DISK_BASE_BUF[Backoffset + 28 + i*2 + 1 ] =
LongNameBuf[index++];
#endif
}
DISK_BASE_BUF[Backoffset + 0x0b] = 0x0f;
DISK_BASE_BUF[Backoffset + 0x0c] = 0x00;
DISK_BASE_BUF[Backoffset + 0x0d] = sum;
DISK_BASE_BUF[Backoffset + 0x1a] = 0x00;
DISK_BASE_BUF[Backoffset + 0x1b] = 0x00;
DISK_BASE_BUF[Backoffset] = MultBak--;
Backoffset += 32;
}
if( !Fbit )
{
Fbit = TRUE;
DISK_BASE_BUF[ BackoffsetBak ] |= 0x40;
}
CHRV3vLbaCurrent = BackFdtSector;
i = CHRV3WriteSector( 1, DISK_BASE_BUF );
if( i!= ERR_SUCCESS )
return i;
if( Mult==0 )
{ // 还原文件路径
CHRV3FileClose( );
for( i=0; i!=MAX_PATH_LEN; i++ )
mCmdParam.Open.mPathName[i] = BackPathBuf[i];
i = CHRV3FileCreate( );
return i;
}
}
}
else
return i;
Secoffset++;
}
}
}
return i;
}
/*********************************************************************
* @fn GetUpSectorData
*
* @brief 由当前扇区得到上一个扇区的数据,放在磁盘缓冲区
*
* @return 操作状态
*/
uint8_t GetUpSectorData( uint32_t *NowSector )
{
uint8_t i;
uint8_t len; // 存放路径的长度
uint32_t index; // 目录扇区偏移扇区数
index = 0;
for(len=0; len!=MAX_PATH_LEN; len++)
{
if(mCmdParam.Open.mPathName[len] == 0) // 得到字符串长度
break;
}
for(i=len-1; i!=0xff; i--) // 得到上级目录位置
{
if((mCmdParam.Open.mPathName[i] == '\\') || (mCmdParam.Open.mPathName[i] == '/'))
break;
}
mCmdParam.Open.mPathName[i] = 0x00;
if( i==0 ) // 打开一级目录注意:处在根目录开始的特殊情况
{
mCmdParam.Open.mPathName[0] = '/';
mCmdParam.Open.mPathName[1] = 0;
i = CHRV3FileOpen();
if ( i == ERR_OPEN_DIR )
goto P_NEXT0;
}
else
{
i = CHRV3FileOpen();
if ( i == ERR_OPEN_DIR )
{
while( 1 )
{
P_NEXT0:
mCmdParam.Locate.mSectorOffset = index;
i = CHRV3FileLocate( );
if( i == ERR_SUCCESS )
{
if( *NowSector == mCmdParam.Locate.mSectorOffset )
{
if( index==0 ) // 处于根目录扇区的开始
return ERR_NO_NAME;
mCmdParam.Locate.mSectorOffset = --index;
i = CHRV3FileLocate( ); // 读上一个扇区的数据
if( i == ERR_SUCCESS )
{ // 以下保存当前所在扇区数
*NowSector = mCmdParam.Locate.mSectorOffset;
mCmdParam.Read.mSectorCount = 1; // 读一个扇区到磁盘缓冲区
mCmdParam.Read.mDataBuffer = &DISK_BASE_BUF[0];
i = CHRV3FileRead( );
CHRV3DirtyBuffer( ); // 清除磁盘缓冲区
return i;
}
else
return i;
}
}
else
return i;
index++;
}
}
}
return i;
}
/*********************************************************************
* @fn CHRV3GetLongName
*
* @brief 由完整短文件名路径(可以是文件或文件夹)得到相应的长文件名
*
* @return 操作状态
*/
uint8_t CHRV3GetLongName( void )
{
// 需要变量扇区大小
// 第一步:打开文件是否找到文件,分析文件是否存在,并得到FDT在此扇区的偏移和所在扇区
// 第二步:分析上面的信息看是否有长文件名存在,是否处于目录的第一个扇区的开始
// 第三步:实现向后偏移一个扇区?读取长文件名(扇区512字节的U盘)
uint8_t i;
uint16_t index; // 在长文件名缓冲区内的索引
uint32_t BackFdtSector; // 保寸偏移上一个扇区
uint8_t sum; // 保存长文件名的校验和
//uint16_t Backoffset; // 保存文件偏移备份
uint16_t offset; // 扇区内文件偏移32倍数
uint8_t FirstBit; // 长文件名跨越两个扇区标志位
uint8_t BackPathBuf[MAX_PATH_LEN]; // 保存文件路径
i = CHRV3FileOpen( );
if( ( i == ERR_SUCCESS ) || ( i == ERR_OPEN_DIR ) )
{
for( i=0; i!=MAX_PATH_LEN; i++ )
BackPathBuf[i] = mCmdParam.Open.mPathName[i];
// 以上完成对路径的备份
sum = CheckNameSum( &DISK_BASE_BUF[CHRV3vFdtOffset] );
index = 0;
FirstBit = FALSE;
// Backoffset = CHRV3vFdtOffset;
BackFdtSector = CHRV3vFdtLba;
if( CHRV3vFdtOffset == 0 )
{
// 先判断是否处于一个扇区开始 是否处于根目录开始 ,否则向后偏移
if( FirstBit == FALSE )
FirstBit = TRUE;
i = GetUpSectorData( &BackFdtSector );
if( i == ERR_SUCCESS )
{
CHRV3vFdtOffset = CHRV3vSectorSize;
goto P_NEXT1;
}
}
else
{
// 读取偏移后的数据,直到结束。如果不够则向后偏移
P_NEXT1:
offset = CHRV3vFdtOffset;
while( 1 )
{
if( offset != 0 )
{
offset = offset - 32;
if( ( DISK_BASE_BUF[offset + 11] == ATTR_LONG_NAME )
&& ( DISK_BASE_BUF[offset + 13] == sum ) )
{
if( (index + 26) > LONG_NAME_BUF_LEN )
return ERR_BUF_OVER;
for( i=0; i!=5; i++) // 长文件名的1-5个字符
{ // 在磁盘上UNICODE用小端方式存放
#if UNICODE_ENDIAN == 1
LongNameBuf[index++] =
DISK_BASE_BUF[offset + i*2 + 2];
LongNameBuf[index++] =
DISK_BASE_BUF[offset + i*2 + 1];
#else
LongNameBuf[index++] =
DISK_BASE_BUF[offset + i*2 + 1];
LongNameBuf[index++] =
DISK_BASE_BUF[offset + i*2 + 2];
#endif
}
for( i =0; i!=6; i++) // 长文件名的6-11个字符
{
#if UNICODE_ENDIAN == 1
LongNameBuf[index++] =
DISK_BASE_BUF[offset + 14 + i*2 + 1];
LongNameBuf[index++] =
DISK_BASE_BUF[offset + + 14 + i*2 ];
#else
LongNameBuf[index++] =
DISK_BASE_BUF[offset + + 14 + i*2 ];
LongNameBuf[index++] =
DISK_BASE_BUF[offset + 14 + i*2 + 1];
#endif
}
for( i=0; i!=2; i++) // 长文件名的12-13个字符
{
#if UNICODE_ENDIAN == 1
LongNameBuf[index++] =
DISK_BASE_BUF[offset + 28 + i*2 + 1];
LongNameBuf[index++] =
DISK_BASE_BUF[offset + 28 + i*2 ];
#else
LongNameBuf[index++] =
DISK_BASE_BUF[offset + 28 + i*2 ];
LongNameBuf[index++] =
DISK_BASE_BUF[offset + 28 + i*2 + 1];
#endif
}
if( DISK_BASE_BUF[offset] & 0X40 )
{
if( ! (((LongNameBuf[index -1] ==0x00)
&& (LongNameBuf[index -2] ==0x00))
|| ((LongNameBuf[index -1] ==0xFF)
&& (LongNameBuf[index -2 ] ==0xFF))))
{ // 处理刚好为26字节长倍数的文件名
if(index + 52 >LONG_NAME_BUF_LEN )
return ERR_BUF_OVER;
LongNameBuf[ index ] = 0x00;
LongNameBuf[ index + 1] = 0x00;
}
return ERR_SUCCESS; // 成功完成长文件名收集完成
}
}
else
return ERR_NO_NAME; // 错误的长文件名,程序返回
}
else
{
if( FirstBit == FALSE )
FirstBit = TRUE;
else // 否则第二次进入
{
for( i=0; i!=MAX_PATH_LEN; i++ )// 还原路径
mCmdParam.Open.mPathName[i] = BackPathBuf[i];
}
i = GetUpSectorData( &BackFdtSector );
if( i == ERR_SUCCESS )
{
CHRV3vFdtOffset = CHRV3vSectorSize;
goto P_NEXT1;
}
else
return i;
// 向后偏移扇区
}
}
}
}
return i; // 返回错误
}
@@ -0,0 +1,317 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : UDisk_HW.c
* Author : WCH
* Version : V1.0.0
* Date : 2022/09/01
* Description : USB full-speed port host operation functions.
*********************************************************************************
* 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.
*******************************************************************************/
/*******************************************************************************/
/* Header File */
#include "Udisk_Operation.h"
/*******************************************************************************/
/* Variable Definition */
__attribute__((aligned(4))) uint8_t Com_Buffer[ DEF_COM_BUF_LEN ]; // even address , used for host enumcation and udisk operation
__attribute__((aligned(4))) uint8_t DevDesc_Buf[ 18 ]; // Device Descriptor Buffer
struct _ROOT_HUB_DEVICE RootHubDev[ DEF_TOTAL_ROOT_HUB ];
struct __HOST_CTL HostCtl[ DEF_TOTAL_ROOT_HUB * DEF_ONE_USB_SUP_DEV_TOTAL ];
volatile uint8_t UDisk_Opeation_Flag = 0;
/*********************************************************************
* @fn mStopIfError
*
* @brief Checking the operation status, displaying the error code and stopping if there is an error
* input : iError - Error code input
*
* @return none
*/
void mStopIfError( uint8_t iError )
{
if ( iError == ERR_SUCCESS )
{
/* operation success, return */
return;
}
/* Display the errors */
DUG_PRINTF( "Error:%02x\r\n", iError );
/* After encountering an error, you should analyze the error code and CHRV3DiskStatus status, for example,
* call CHRV3DiskReady to check whether the current USB disk is connected or not,
* if the disk is disconnected then wait for the disk to be plugged in again and operate again,
* Suggested steps to follow after an error:
* 1, call CHRV3DiskReady once, if successful, then continue the operation, such as Open, Read/Write, etc.
* 2?If CHRV3DiskReady is not successful, then the operation will be forced to start from the beginning.
*/
while(1)
{ }
}
/*********************************************************************
* @fn Udisk_USBH_Initialization
*
* @brief USB Host Udisk process Initialization, include usb-host initialization
* usb libs initialization, udisk-related values Initialization
and the others
*
* @para none
*
* @return none
*/
void Udisk_USBH_Initialization( void )
{
/* USB Host Initialization */
printf( "USB Host & UDisk Lib Initialization. \r\n" );
/* Initialize USBFS host */
DUG_PRINTF( "USBFS Host Init\r\n" );
USBFS_RCC_Init( );
USBFS_Host_Init( ENABLE );
memset( &RootHubDev[ DEF_USB_PORT_FS ].bStatus, 0, sizeof( struct _ROOT_HUB_DEVICE ) );
memset( &HostCtl[ DEF_USB_PORT_FS ].InterfaceNum, 0, sizeof( struct __HOST_CTL ) );
/* USB Libs Initialization */
printf( "UDisk library Initialization. \r\n" );
CHRV3LibInit( );
}
/*********************************************************************
* @fn Udisk_USBH_EnumRootDevice
*
* @brief Generally enumerate a device connected to host port.
*
* @para index: USB host port
*
* @return Enumeration result
*/
uint8_t Udisk_USBH_EnumRootDevice( uint8_t usb_port )
{
uint8_t s;
uint8_t enum_cnt;
uint8_t cfg_val;
uint16_t i;
uint16_t len;
DUG_PRINTF( "Enum:\r\n" );
enum_cnt = 0;
ENUM_START:
/* Delay and wait for the device to stabilize */
Delay_Ms( 100 );
enum_cnt++;
Delay_Ms( 8 << enum_cnt );
/* Reset the USB device and wait for the USB device to reconnect */
USBFSH_ResetRootHubPort( 0 );
for( i = 0, s = 0; i < DEF_RE_ATTACH_TIMEOUT; i++ )
{
if( USBFSH_EnableRootHubPort( &RootHubDev[ usb_port ].bSpeed ) == ERR_SUCCESS )
{
i = 0;
s++;
if( s > 6 )
{
break;
}
}
Delay_Ms( 1 );
}
if( i )
{
/* Determine whether the maximum number of retries has been reached, and retry if not reached */
if( enum_cnt <= 5 )
{
goto ENUM_START;
}
return ERR_USB_DISCON;
}
/* Select USB speed */
USBFSH_SetSelfSpeed( RootHubDev[ usb_port].bSpeed );
/* Get USB device device descriptor */
DUG_PRINTF("Get DevDesc: ");
s = USBFSH_GetDeviceDescr( &RootHubDev[ usb_port ].bEp0MaxPks, DevDesc_Buf );
if( s == ERR_SUCCESS )
{
/* Print USB device device descriptor */
#if DEF_DEBUG_PRINTF
for( i = 0; i < 18; i++ )
{
DUG_PRINTF( "%02x ", DevDesc_Buf[ i ] );
}
DUG_PRINTF("\n");
#endif
}
else
{
/* Determine whether the maximum number of retries has been reached, and retry if not reached */
DUG_PRINTF( "Err(%02x)\n", s );
if( enum_cnt <= 5 )
{
goto ENUM_START;
}
return DEF_DEV_DESCR_GETFAIL;
}
/* Set the USB device address */
DUG_PRINTF("Set DevAddr: ");
RootHubDev[ usb_port ].bAddress = (uint8_t)( DEF_USB_PORT_FS + USB_DEVICE_ADDR );
s = USBFSH_SetUsbAddress( RootHubDev[ usb_port ].bEp0MaxPks, RootHubDev[ usb_port ].bAddress );
if( s == ERR_SUCCESS )
{
DUG_PRINTF( "OK\n" );
}
else
{
/* Determine whether the maximum number of retries has been reached, and retry if not reached */
DUG_PRINTF( "Err(%02x)\n", s );
if( enum_cnt <= 5 )
{
goto ENUM_START;
}
return DEF_DEV_ADDR_SETFAIL;
}
Delay_Ms( 5 );
/* Get the USB device configuration descriptor */
DUG_PRINTF("Get CfgDesc: ");
s = USBFSH_GetConfigDescr( RootHubDev[ usb_port ].bEp0MaxPks, Com_Buffer, DEF_COM_BUF_LEN, &len );
if( s == ERR_SUCCESS )
{
cfg_val = ( (PUSB_CFG_DESCR)Com_Buffer )->bConfigurationValue;
/* Print USB device configuration descriptor */
#if DEF_DEBUG_PRINTF
for( i = 0; i < len; i++ )
{
DUG_PRINTF( "%02x ", Com_Buffer[ i ] );
}
DUG_PRINTF("\n");
#endif
}
else
{
/* Determine whether the maximum number of retries has been reached, and retry if not reached */
DUG_PRINTF( "Err(%02x)\n", s );
if( enum_cnt <= 5 )
{
goto ENUM_START;
}
return DEF_CFG_DESCR_GETFAIL;
}
/* Set USB device configuration value */
DUG_PRINTF("Set Cfg: ");
s = USBFSH_SetUsbConfig( RootHubDev[ usb_port ].bEp0MaxPks, cfg_val );
if( s == ERR_SUCCESS )
{
DUG_PRINTF( "OK\n" );
}
else
{
/* Determine whether the maximum number of retries has been reached, and retry if not reached */
DUG_PRINTF( "Err(%02x)\n", s );
if( enum_cnt <= 5 )
{
goto ENUM_START;
}
return ERR_USB_UNSUPPORT;
}
return ERR_SUCCESS;
}
/*********************************************************************
* @fn UDisk_USBH_PreDeal
*
* @brief usb host preemption operations,
* including detecting device insertion and enumerating device information
*
* @return none
*/
uint8_t UDisk_USBH_PreDeal( void )
{
uint8_t usb_port;
uint8_t index;
uint8_t ret;
usb_port = DEF_USB_PORT_FS;
ret = USBFSH_CheckRootHubPortStatus( RootHubDev[ usb_port ].bStatus );
if( ret == ROOT_DEV_CONNECTED )
{
DUG_PRINTF("USB Dev In.\n");
USBFSH_CheckRootHubPortStatus( RootHubDev[ usb_port ].bStatus );
RootHubDev[ usb_port ].bStatus = ROOT_DEV_CONNECTED; // Set connection status_
RootHubDev[ usb_port ].DeviceIndex = usb_port * DEF_ONE_USB_SUP_DEV_TOTAL;
/* Enumerate root device */
ret = Udisk_USBH_EnumRootDevice( usb_port );
if( ret == ERR_SUCCESS )
{
DUG_PRINTF( "USB Port %02x Device Enumeration Succeed\r\n", usb_port );
RootHubDev[ usb_port ].bStatus = ROOT_DEV_SUCCESS;
return ERR_SUCCESS;
}
else
{
DUG_PRINTF( "USB Port %02x Device Enumeration ERR %02x.\r\n", usb_port, ret );
RootHubDev[ usb_port ].bStatus = ROOT_DEV_FAILED;
return ERR_USB_UNAVAILABLE;
}
}
else if( ret == ROOT_DEV_DISCONNECT )
{
DUG_PRINTF("USB Port %02x Device Out.\r\n", usb_port );
/* Clear parameters */
index = RootHubDev[ usb_port ].DeviceIndex;
memset( &RootHubDev[ usb_port ].bStatus, 0, sizeof( struct _ROOT_HUB_DEVICE ) );
memset( &HostCtl[ index ].InterfaceNum, 0, sizeof( struct __HOST_CTL ) );
UDisk_Opeation_Flag = 1;
CHRV3DiskStatus = DISK_UNKNOWN;
return ERR_USB_DISCON;
}
return ERR_USB_UNKNOWN;
}
/*********************************************************************
* @fn UDisk_USBH_DiskReady
*
* @brief Check if UDisk is Ready and update status in 'CHRV3DiskStatus'
*
* @return none
*/
uint8_t UDisk_USBH_DiskReady( void )
{
uint8_t ret, i;
/* Detect USB Device & Enumeration processing */
ret = UDisk_USBH_PreDeal( );
if( ret == ERR_SUCCESS )
{
/* Wait for uDisk Ready */
CHRV3DiskStatus = DISK_USB_ADDR;
for ( i = 0; i != 10; i ++ )
{
DUG_PRINTF( "Wait Disk Ready...\r\n" );
ret = CHRV3DiskReady( );
if ( ret == ERR_SUCCESS )
{
/* Disk Ready */
DUG_PRINTF( "Disk Ready Code:%02x.\r\n", ret );
DUG_PRINTF( "CHRV3DiskStatus:%02x\n", CHRV3DiskStatus);
UDisk_Opeation_Flag = 1;
return DISK_READY;
}
else
{
DUG_PRINTF("Not Ready Code :%02x.\r\n", ret);
DUG_PRINTF("CHRV3DiskStatus:%02x.\n", CHRV3DiskStatus);
}
Delay_Ms( 50 );
}
}
return CHRV3DiskStatus;
}
@@ -0,0 +1,78 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : UDisk_Operation.h
* Author : WCH
* Version : V1.0.0
* Date : 2022/11/20
* Description : This file contains all the functions prototypes for the Udisk
host operation.
*********************************************************************************
* 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 USER_UDISK_OPERATION_H_
#define USER_UDISK_OPERATION_H_
#include "debug.h"
#include "string.h"
#include "CHRV3UFI.h"
#include "ch32v20x_usbfs_host.h"
#include "usb_host_config.h"
/*******************************************************************************/
/* Public Extern Variables */
extern volatile uint8_t UDisk_Opeation_Flag;
extern struct _ROOT_HUB_DEVICE RootHubDev[ DEF_TOTAL_ROOT_HUB ];
extern struct __HOST_CTL HostCtl[ DEF_TOTAL_ROOT_HUB * DEF_ONE_USB_SUP_DEV_TOTAL ];
extern volatile uint8_t UDisk_Opeation_Flag;
extern uint8_t *pCodeStr;
extern __attribute__((aligned(4))) uint8_t Com_Buffer[ DEF_COM_BUF_LEN ]; // even address , used for host enumcation and udisk operation
extern __attribute__((aligned(4))) uint8_t DevDesc_Buf[ 18 ]; // Device Descriptor Buffer
/*******************************************************************************/
/* 长文件名相关的宏定义极其全局变量 */
// 长文件名缓冲区从(0到20)*26
#define LONG_NAME_BUF_LEN (20*26)
#define UNICODE_ENDIAN 0 // 1为UNICDOE大端编码 0为小端
// 长文件名存放缓冲区(Unicode编码)
extern uint8_t LongNameBuf[ ];
// 长文件名(Unicode编码)
extern uint8_t LongName[ ];
#define LongName_Len 124
#define TRUE 1
#define FALSE 0
// 函数返回
#define ERR_NO_NAME 0X44 // 此短文件名没有长文件名或错误的长文件
#define ERR_BUF_OVER 0X45 // 长文件缓冲区溢出
#define ERR_LONG_NAME 0X46 // 错误的长文件名
#define ERR_NAME_EXIST 0X47 // 此短文件名存在
/*******************************************************************************/
/* Extern UDisk Operation Functions */
extern void mStopIfError( uint8_t iError );
extern void Udisk_USBH_Initialization( void );
extern uint8_t Udisk_USBH_EnumRootDevice( uint8_t usb_port );
extern uint8_t UDisk_USBH_PreDeal( void );
extern uint8_t UDisk_USBH_DiskReady( void );
/* Extern Long-name Operation Functions */
extern void UDisk_USBH_Longname( void );
extern uint8_t CHRV3GetLongName( void );
extern uint8_t GetUpSectorData( uint32_t *NowSector );
extern uint8_t CHRV3CreateLongName( void );
extern uint8_t AnalyzeLongName( void );
extern uint8_t CheckNameSum( uint8_t *p );
/* Extern Creating Directory Functions */
extern void UDisk_USBH_CreatDirectory( void );
extern uint8_t CreateDirectory( void );
/* Extern Byte/Sector Open/Read/Modify/Delete and File-Enumeration Functions */
extern void UDisk_USBH_ByteOperation( void );
extern void UDisk_USBH_SectorOperation( void );
extern void UDisk_USBH_EnumFiles( void );
#endif /* USER_UDISK_OPERATION_H_ */
@@ -0,0 +1,345 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : Udisk_Func_BasicOp.c
* Author : WCH
* Version : V1.0.0
* Date : 2022/11/22
* Description : USB full-speed port host operation functions.
*********************************************************************************
* 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.
*******************************************************************************/
/*******************************************************************************/
/* Header File */
#include "Udisk_Operation.h"
uint8_t *pCodeStr;
/*******************************************************************************/
/* Variable Definition */
__attribute__((aligned(4))) uint8_t MY_DATA_BUF[ DISK_BASE_BUF_LEN ]; /* MY_DATA_BUF指向外部RAM的磁盘数据缓冲区,缓冲区长度为至少一个扇区的长度,用于用户数据缓存 */
uint8_t *pCodeStr;
/*********************************************************************
* @fn UDisk_USBH_ByteOperation
*
* @brief Demo Function For UDisk File Byte-operation
* including Create\Modify\Read\Erase (EXAM1)
*
* @return none
*/
void UDisk_USBH_ByteOperation( void )
{
uint8_t ret;
uint8_t i,t;
uint16_t TotalCount = 0;
ret = UDisk_USBH_DiskReady( );
if( (ret == DISK_READY)&&( UDisk_Opeation_Flag == 1 ) )
{
UDisk_Opeation_Flag = 0;
printf("CHRV3DiskStatus:%02x\r\n",CHRV3DiskStatus);
/* 读文件 */
strcpy( (char *)mCmdParam.Open.mPathName, "/C51/NEWFILE.C" ); //设置将要操作的文件路径和文件名/C51/NEWFILE.C
ret = CHRV3FileOpen( ); //打开文件
if ( ret == ERR_MISS_DIR || ret == ERR_MISS_FILE ) //没有找到文件
{
//创建文件演示
printf( "Find No File And Create\r\n" );
strcpy( (char *)mCmdParam.Create.mPathName, "/C51/NEWFILE.C" ); //新文件名,在根目录下,中文文件名
ret = CHRV3FileCreate( ); //新建文件并打开,如果文件已经存在则先删除后再新建
mStopIfError( ret );
printf( "ByteWrite\r\n" );
//实际应该判断写数据长度和定义缓冲区长度是否相符,如果大于缓冲区长度则需要多次写入
i = sprintf( (char *)Com_Buffer,"Note: \xd\xa这个程序是以字节为单位进行U盘文件读写,简单演示功能。\xd\xa");
for(t=0; t<10; t++)
{
mCmdParam.ByteWrite.mByteCount = i; //指定本次写入的字节数
mCmdParam.ByteWrite.mByteBuffer = Com_Buffer; //指向缓冲区
ret = CHRV3ByteWrite( ); //以字节为单位向文件写入数据
mStopIfError( ret );
printf("成功写入 %02X次\r\n",(uint16_t)t);
}
//演示修改文件属性
printf( "Modify\r\n" );
mCmdParam.Modify.mFileAttr = 0xff; //输入参数: 新的文件属性,为0FFH则不修改
mCmdParam.Modify.mFileTime = 0xffff; //输入参数: 新的文件时间,为0FFFFH则不修改,使用新建文件产生的默认时间
mCmdParam.Modify.mFileDate = MAKE_FILE_DATE( 2015, 5, 18 ); //输入参数: 新的文件日期: 2015.05.18
mCmdParam.Modify.mFileSize = 0xffffffff; // 输入参数: 新的文件长度,以字节为单位写文件应该由程序库关闭文件时自动更新长度,所以此处不修改
i = CHRV3FileModify( ); //修改当前文件的信息,修改日期
mStopIfError( i );
printf( "Close\r\n" );
mCmdParam.Close.mUpdateLen = 1; //自动计算文件长度,以字节为单位写文件,建议让程序库关闭文件以便自动更新文件长度
i = CHRV3FileClose( );
mStopIfError( i );
/* 删除某文件 */
// printf( "Erase\n" );
// strcpy( (char *)mCmdParam.Create.mPathName, "/OLD" ); //将被删除的文件名,在根目录下
// i = CHRV3FileErase( ); //删除文件并关闭
// if ( i != ERR_SUCCESS ) printf( "Error: %02X\n", (uint16_t)i ); //显示错误
}
else
{
/* 一、写入文件 */
printf( "ByteWrite\r\n" ); //如果希望将新数据添加到原文件的尾部,可以移动文件指针
mCmdParam.ByteLocate.mByteOffset = 0xffffffff; //移到文件的尾部
CHRV3ByteLocate( ); //实际应该判断写数据长度和定义缓冲区长度是否相符,如果大于缓冲区长度则需要多次写入
i = sprintf( (char *)Com_Buffer,"Note: \xd\xa这个程序是以字节为单位进行U盘文件读写,简单演示功能。\xd\xa"); //演示文字
for(t=0; t<10; t++)
{
mCmdParam.ByteWrite.mByteCount = i; //指定本次写入的字节数
mCmdParam.ByteWrite.mByteBuffer = Com_Buffer; // 指向缓冲区
ret = CHRV3ByteWrite( ); // 以字节为单位向文件写入数据
mStopIfError( ret );
printf("成功写入 %02X次\r\n",(uint16_t)t);
}
/* 二、读取文件前N字节 */
TotalCount = 60; //设置准备读取总长度100字节
strcpy( (char *)mCmdParam.Open.mPathName, "/C51/NEWFILE.C" ); //设置将要操作的文件路径和文件名/C51/NEWFILE.C
CHRV3FileOpen( ); //打开文件
printf( "读出的前%d个字符是:\r\n",TotalCount );
while ( TotalCount )
{
//如果文件比较大,一次读不完,可以再调用CH103ByteRead继续读取,文件指针自动向后移动
if ( TotalCount > (MAX_PATH_LEN-1) )
{
t = MAX_PATH_LEN-1; // 剩余数据较多,限制单次读写的长度不能超过 sizeof( mCmdParam.Other.mBuffer )
}
else
{
t = TotalCount; //最后剩余的字节数
}
mCmdParam.ByteRead.mByteCount = t; //请求读出几十字节数据
mCmdParam.ByteRead.mByteBuffer= &Com_Buffer[0];
ret = CHRV3ByteRead( ); //以字节为单位读取数据块,单次读写的长度不能超过MAX_BYTE_IO,第二次调用时接着刚才的向后读
TotalCount -= mCmdParam.ByteRead.mByteCount; //计数,减去当前实际已经读出的字符数
for ( i=0; i!=mCmdParam.ByteRead.mByteCount; i++ )
{
printf( "%c", mCmdParam.ByteRead.mByteBuffer[i] ); //显示读出的字符
}
printf( "\r\n" );
if ( mCmdParam.ByteRead.mByteCount < t ) //实际读出的字符数少于要求读出的字符数,说明已经到文件的结尾
{
printf( "\r\n" );
printf( "文件已经结束\r\n" );
break;
}
}
i = CHRV3FileClose( ); //关闭文件
mStopIfError( i );
}
}
}
/*********************************************************************
* @fn UDisk_USBH_SectorOperation
*
* @brief Demo Function For UDisk File Sector-operation
* including Create\Modify\Read\Erase (EXAM6)
*
* @return none
*/
void UDisk_USBH_SectorOperation( void )
{
uint8_t ret, SecCount, s;
uint8_t i;
uint16_t tmp;
uint8_t tmpbuf[64];
ret = UDisk_USBH_DiskReady( );
if( ( ret == DISK_READY )&&( UDisk_Opeation_Flag == 1 ) )
{
UDisk_Opeation_Flag = 0;
/* 查询磁盘物理容量 */
printf( "DiskSize\r\n" );
i = CHRV3DiskQuery( );
mStopIfError( i );
printf( "TotalSize = %u MB \n", (unsigned int)( mCmdParam.Query.mTotalSector * CHRV3vSectorSizeB / 2 ) ); //显示为以MB为单位的容量
/* 读取原文件 */
printf( "Open\r\n" );
strcpy( mCmdParam.Open.mPathName, "/NEWFILE.TXT" );//文件名,该文件在C51子目录下
s = CHRV3FileOpen( ); //打开文件
if ( s == ERR_MISS_DIR || s == ERR_MISS_FILE )//没有找到文件
{
printf( "没有找到文件\r\n" );
}
else //找到文件或者出错
{
printf( "Query\r\n" );
i = CHRV3FileQuery( ); //查询当前文件的信息
mStopIfError( i );
printf( "Read\r\n" );
CHRV3vFileSize = CHRV3vFileSize+(sizeof( MY_DATA_BUF )-1); //原文件的长度
SecCount = CHRV3vFileSize/ sizeof( MY_DATA_BUF ) ;//计算文件的扇区数,因为读写是以扇区为单位的,先加CHRV3vSectorSize-1是为了读出文件尾部不足1个扇区的部分
printf( "Size=%ld, Sec=%d\r\n", CHRV3vFileSize, (uint16_t)SecCount );
while(SecCount--)
{
mCmdParam.Read.mSectorCount = sizeof( MY_DATA_BUF )/512; //读取全部数据,如果超过2个扇区则只读取2个扇区
mCmdParam.Read.mDataBuffer = &MY_DATA_BUF[0];//指向文件数据缓冲区的起始地址
i = CHRV3FileRead( ); //从文件读取数据
mStopIfError( i );
if(SecCount == 0) break;
/*
for(tmp=0; tmp<sizeof( MY_DATA_BUF ); tmp++)
{
printf("%02X ",(uint16_t)MY_DATA_BUF[tmp]);
}
printf("\n");
*/
}
tmp = (CHRV3vFileSize-(sizeof( MY_DATA_BUF )-1))%sizeof( MY_DATA_BUF );
if((tmp == 0)&&(CHRV3vFileSize != 0)) tmp = sizeof( MY_DATA_BUF );
CHRV3vFileSize = CHRV3vFileSize-(sizeof( MY_DATA_BUF )-1); //恢复原文件的长度
/*
for(i=0; i<tmp; i++)
{
printf("%02X ",(uint16_t)MY_DATA_BUF[i]);
}
printf("\n");
*/
/*
如果文件比较大,一次读不完,可以再调用CHRV3FileRead继续读取,文件指针自动向后移动
while ( 1 )
{
c = 4; 每次读取4个扇区,缓冲区定义的越大,一次读取的扇区数越多
mCmdParam.Read.mSectorCount = c; 指定读取的扇区数
mCmdParam.Read.mDataBuffer = &MY_DATA_BUF[0]; 指向文件数据缓冲区的起始地址
CHRV3FileRead(); 读完后文件指针自动后移 处理数据
if ( mCmdParam.Read.mSectorCount < c ) break; 实际读出的扇区数较小则说明文件已经结束
}
如果希望从指定位置开始读写,可以移动文件指针
mCmdParam.Locate.mSectorOffset = 3; 跳过文件的前3个扇区开始读写
i = CHRV3FileLocate( );
mCmdParam.Read.mSectorCount = 10;
mCmdParam.Read.mDataBuffer = &MY_DATA_BUF[0]; 指向文件数据缓冲区的起始地址
CHRV3FileRead(); 直接读取从文件的第(CHRV3vSectorSizeH*256*3)个字节开始的数据,前3个扇区被跳过
如果希望将新数据添加到原文件的尾部,可以移动文件指针
i = CHRV3FileOpen( );
mCmdParam.Locate.mSectorOffset = 0xffffffff; 移到文件的尾部,以扇区为单位,如果原文件是3字节,则从CHRV3vSectorSizeH个字节处开始添加
i = CHRV3FileLocate( );
mCmdParam.Write.mSectorCount = 10;
mCmdParam.Write.mDataBuffer = &MY_DATA_BUF[0];
CHRV3FileWrite(); 在原文件的后面添加数据
使用CHRV3FileRead可以自行定义数据缓冲区的起始地址
mCmdParam.Read.mSectorCount = 2;
mCmdParam.Read.mDataBuffer = 0x50; 将读出的数据放到50H开始的缓冲区中,需要指定缓冲区的起始地址
CHRV3FileRead(); 从文件中读取2个扇区到指定缓冲区
使用CHRV3FileWrite可以自行定义数据缓冲区的起始地址
mCmdParam.Wiite.mSectorCount = 2;
mCmdParam.Write.mDataBuffer = 0x50; 将50H开始的缓冲区中的数据写入
CHRV3FileWrite(); 将指定缓冲区中的数据写入2个扇区到文件中
*/
printf( "Close\r\n" );
i = CHRV3FileClose( ); //关闭文件
mStopIfError( i );
}
printf( "Create\r\n" );
strcpy( mCmdParam.Create.mPathName, "/NEWFILE.TXT" );//新文件名,在根目录下,中文文件名
s = CHRV3FileCreate( ); //新建文件并打开,如果文件已经存在则先删除后再新建 */
mStopIfError( s );
printf( "Write\r\n" );
strcpy( tmpbuf, "0000ABCDEFGHIJKLMNOPQRSTUVWXYZ\xd\xa" );//准备写文件数据
for(i=0; i<(DISK_BASE_BUF_LEN/sizeof(tmpbuf)); i++)
{
tmp=i*sizeof(tmpbuf);
strcpy(&MY_DATA_BUF[tmp],tmpbuf);
}
for(tmp=0; tmp<sizeof(MY_DATA_BUF); tmp++)
{
printf("%02X",(uint16_t)MY_DATA_BUF[tmp]);
}
printf("\r\n");
for(s=0; s<10; s++)
{
mCmdParam.Write.mSectorCount = 1; //写入所有扇区的数据
mCmdParam.Write.mDataBuffer = &MY_DATA_BUF[0]; //指向文件数据缓冲区的起始地址
i = CHRV3FileWrite( ); //向文件写入数据
mStopIfError( i );
printf("成功写入 %02X次\r\n",(uint16_t)s);
}
/* printf( "Modify\n" );
mCmdParam.Modify.mFileAttr = 0xff; 输入参数: 新的文件属性,为0FFH则不修改
mCmdParam.Modify.mFileTime = 0xffff; 输入参数: 新的文件时间,为0FFFFH则不修改,使用新建文件产生的默认时间
mCmdParam.Modify.mFileDate = MAKE_FILE_DATE( 2015, 5, 18 ); 输入参数: 新的文件日期: 2015.05.18
mCmdParam.Modify.mFileSize = 0xffffffff; 输入参数: 新的文件长度,以字节为单位写文件应该由程序库关闭文件时自动更新长度,所以此处不修改
i = CHRV3FileModify( ); 修改当前文件的信息,修改日期
mStopIfError( i );
*/
printf( "Close\r\n" );
mCmdParam.Close.mUpdateLen = 1; //自动计算文件长度,以字节为单位写文件,建议让程序库关闭文件以便自动更新文件长度
i = CHRV3FileClose( );
mStopIfError( i );
/* 删除某文件 */
/*printf( "Erase\n" );
strcpy( mCmdParam.Create.mPathName, "/OLD.TXT" ); 将被删除的文件名,在根目录下
i = CHRV3FileErase( ); 删除文件并关闭
if ( i != ERR_SUCCESS ) printf( "Error File not exist: %02X\n", (uint16_t)i ); 显示错误
*/
printf( "U盘演示完成\r\n" );
}
}
/*********************************************************************
* @fn UDisk_USBH_EnumFiles
*
* @brief Demo Function For Enumerating files in UDisk(EXAM11)
*
* @return none
*/
void UDisk_USBH_EnumFiles( void )
{
uint8_t i, s, ret;
uint16_t j;
ret = UDisk_USBH_DiskReady( );
if( ( ret == DISK_READY )&&( UDisk_Opeation_Flag == 1 ) )
{
UDisk_Opeation_Flag = 0;
/* 读取原文件 */
printf( "Open\r\n" );
strcpy( mCmdParam.Open.mPathName, "/C51/CHRV3HFT.C" );//文件名,该文件在C51子目录下
s = CHRV3FileOpen( ); //打开文件
/* 列出文件 */
if ( s == ERR_MISS_DIR )
{
printf("不存在该文件则列出所有文件\r\n"); //C51子目录不存在则列出根目录下的所有文件
pCodeStr = "/*";
}
else
{
pCodeStr = "/C51/*"; //CHRV3HFT.C文件不存在则列出\C51子目录下的以CHRV3开头的文件
}
printf( "List file %s\r\n", pCodeStr );
for ( j = 0; j < 10000; j ++ ) //最多搜索前10000个文件,实际上没有限制
{
strcpy( (char *)mCmdParam.Open.mPathName, pCodeStr );//搜索文件名,*为通配符,适用于所有文件或者子目录
i = strlen( mCmdParam.Open.mPathName );
mCmdParam.Open.mPathName[ i ] = 0xFF; //根据字符串长度将结束符替换为搜索的序号,从0到254,如果是0xFF即255则说明搜索序号在CHRV3vFileSize变量中
CHRV3vFileSize = j; //指定搜索/枚举的序号
i = CHRV3FileOpen( ); //打开文件,如果文件名中含有通配符*,则为搜索文件而不打开
/* CHRV3FileEnum 与 CHRV3FileOpen 的唯一区别是当后者返回ERR_FOUND_NAME时那么对应于前者返回ERR_SUCCESS */
if ( i == ERR_MISS_FILE )
{
break; //再也搜索不到匹配的文件,已经没有匹配的文件名
}
if ( i == ERR_FOUND_NAME )
{
/* 搜索到与通配符相匹配的文件名,文件名及其完整路径在命令缓冲区中 */
printf( " match file %04d#: %s\r\n", (unsigned int)j, mCmdParam.Open.mPathName );//显示序号和搜索到的匹配文件名或者子目录名
continue; //继续搜索下一个匹配的文件名,下次搜索时序号会加1
}
else
{
/* 出错 */
mStopIfError( i );
break;
}
}
printf( "Close\r\n" );
CHRV3FileClose( ); //关闭文件
printf( "U盘演示完成\r\n" );
}
}
@@ -0,0 +1,655 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32f20x_usbfs_host.c
* Author : WCH
* Version : V1.0.0
* Date : 2022/09/01
* Description : USB full-speed port host operation functions.
*********************************************************************************
* 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.
*******************************************************************************/
/*******************************************************************************/
/* Header File */
#include "usb_host_config.h"
/*******************************************************************************/
/* Variable Definition */
__attribute__((aligned(4))) uint8_t RxBuffer[ MAX_PACKET_SIZE ]; // IN, must even address
__attribute__((aligned(4))) uint8_t TxBuffer[ MAX_PACKET_SIZE ]; // OUT, must even address
/*********************************************************************
* @fn USBFS_RCC_Init
*
* @brief Set USB port clock.
*
* @return none
*/
void USBFS_RCC_Init( void )
{
if( SystemCoreClock == 144000000 )
{
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div3 );
}
else if( SystemCoreClock == 96000000 )
{
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div2 );
}
else if( SystemCoreClock == 48000000 )
{
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div1 );
}
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_OTG_FS, ENABLE );
}
/*********************************************************************
* @fn USBFS_Host_Init
*
* @brief Initialize USB port host configuration.
*
* @param sta - ENABLE or DISABLE
*
* @return none
*/
void USBFS_Host_Init( FunctionalState sta )
{
if( sta == ENABLE )
{
USBOTG_H_FS->BASE_CTRL = USBFS_UC_HOST_MODE;
USBOTG_H_FS->HOST_CTRL = 0;
USBOTG_H_FS->DEV_ADDR = 0;
USBOTG_H_FS->HOST_EP_MOD = USBFS_UH_EP_TX_EN | USBFS_UH_EP_RX_EN;
USBOTG_H_FS->HOST_RX_DMA = (uint32_t)USBFS_RX_Buf;
USBOTG_H_FS->HOST_TX_DMA = (uint32_t)USBFS_TX_Buf;
USBOTG_H_FS->HOST_RX_CTRL = 0;
USBOTG_H_FS->HOST_TX_CTRL = 0;
USBOTG_H_FS->BASE_CTRL = USBFS_UC_HOST_MODE | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN;
USBOTG_H_FS->INT_FG = 0xFF;
USBOTG_H_FS->INT_EN = USBFS_UIE_TRANSFER | USBFS_UIE_DETECT;
}
else
{
USBOTG_H_FS->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
}
}
/*********************************************************************
* @fn USBFSH_CheckRootHubPortStatus
*
* @brief Check status of USB port.
*
* @para dev_sta: The status of the root device connected to this port.
*
* @return The current status of the port.
*/
uint8_t USBFSH_CheckRootHubPortStatus( uint8_t dev_sta )
{
/* Check USB device connection or disconnection */
if( ( USBOTG_H_FS->INT_FG ) & USBFS_UIF_DETECT )
{
USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT; // Clear flag
if( USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH ) // Check that the USB device has been connected to the port
{
if( ( dev_sta == ROOT_DEV_DISCONNECT ) || ( ( dev_sta != ROOT_DEV_FAILED ) && ( USBFSH_CheckRootHubPortEnable( ) == 0x00 ) ) )
{
return ROOT_DEV_CONNECTED;
}
else
{
return ROOT_DEV_FAILED;
}
}
else
{
return ROOT_DEV_DISCONNECT;
}
}
else
{
return ROOT_DEV_FAILED;
}
}
/*********************************************************************
* @fn USBFSH_CheckRootHubPortEnable
*
* @brief Check the enable status of the USB port.
*
* @return The current enable status of the port.
*/
uint8_t USBFSH_CheckRootHubPortEnable( void )
{
return ( USBOTG_H_FS->HOST_CTRL & USBFS_UH_PORT_EN );
}
/*********************************************************************
* @fn USBFSH_CheckRootHubPortSpeed
*
* @brief Check the speed of the USB port.
*
* @return The current speed of the port.
*/
uint8_t USBFSH_CheckRootHubPortSpeed( void )
{
return ( USBOTG_H_FS->MIS_ST & USBFS_UMS_DM_LEVEL? USB_LOW_SPEED: USB_FULL_SPEED );
}
/*********************************************************************
* @fn USBFSH_SetSelfAddr
*
* @brief Set the USB device address.
*
* @para addr: USB device address.
*
* @return none
*/
void USBFSH_SetSelfAddr( uint8_t addr )
{
USBOTG_H_FS->DEV_ADDR = ( USBOTG_H_FS->DEV_ADDR & USBFS_UDA_GP_BIT ) | ( addr & USBFS_USB_ADDR_MASK );
}
/*********************************************************************
* @fn USBFSH_SetSelfSpeed
*
* @brief Set USB speed.
*
* @para speed: USB speed.
*
* @return none
*/
void USBFSH_SetSelfSpeed( uint8_t speed )
{
if( speed )
{
USBOTG_H_FS->BASE_CTRL &= ~USBFS_UC_LOW_SPEED;
USBOTG_H_FS->HOST_SETUP &= ~USBFS_UH_PRE_PID_EN;
}
else
{
USBOTG_H_FS->BASE_CTRL |= USBFS_UC_LOW_SPEED;
}
}
/*********************************************************************
* @fn USBFSH_ResetRootHubPort
*
* @brief Reset USB port.
*
* @para mod: Reset host port operating mode.
* 0 -> reset and wait end
* 1 -> begin reset
* 2 -> end reset
*
* @return none
*/
void USBFSH_ResetRootHubPort( uint8_t mode )
{
USBFSH_SetSelfAddr( 0x00 );
USBFSH_SetSelfSpeed( 1 );
if( mode <= 1 )
{
USBOTG_H_FS->HOST_CTRL = ( USBOTG_H_FS->HOST_CTRL & ~USBFS_UH_LOW_SPEED ) | USBFS_UH_BUS_RESET;
}
if( mode == 0 )
{
Delay_Ms( DEF_BUS_RESET_TIME ); // Reset time from 10mS to 20mS
}
if( mode != 1 )
{
USBOTG_H_FS->HOST_CTRL = USBOTG_H_FS->HOST_CTRL & ~USBFS_UH_BUS_RESET; // End Reset
}
Delay_Ms( 2 );
USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT;
}
/*********************************************************************
* @fn USBFSH_EnableRootHubPort
*
* @brief Enable USB host port.
*
* @para *pspeed: USB speed.
*
* @return Operation result of the enabled port.
*/
uint8_t USBFSH_EnableRootHubPort( uint8_t *pspeed )
{
if( USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH )
{
if( USBFSH_CheckRootHubPortEnable( ) == 0x00 )
{
*pspeed = USBFSH_CheckRootHubPortSpeed( );
if( *pspeed == 0 )
{
USBOTG_H_FS->HOST_CTRL |= USBFS_UH_LOW_SPEED;
}
}
USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN;
USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN;
return ERR_SUCCESS;
}
return ERR_USB_DISCON;
}
/*********************************************************************
* @fn USBFSH_Transact
*
* @brief Perform USB transaction.
*
* @para endp_pid: Token PID.
* endp_tog: Toggle
* timeout: Timeout time.
*
* @return USB transfer result.
*/
uint8_t USBFSH_Transact( uint8_t endp_pid, uint8_t endp_tog, uint16_t timeout )
{
uint8_t r, trans_rerty;
uint16_t i;
USBOTG_H_FS->HOST_TX_CTRL = USBOTG_H_FS->HOST_RX_CTRL = endp_tog;
trans_rerty = 0;
do
{
USBOTG_H_FS->HOST_EP_PID = endp_pid; // Specify token PID and endpoint number
USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; // Allow transmission
for( i = DEF_WAIT_USB_TOUT_200US; ( i != 0 ) && ( ( USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER ) == 0 ); i-- )
{
Delay_Us( 1 );
}
USBOTG_H_FS->HOST_EP_PID = 0x00; // Stop USB transfer
if( ( USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER ) == 0 )
{
return ERR_USB_UNKNOWN;
}
else
{
/* Complete transfer */
if( USBOTG_H_FS->INT_ST & USBFS_UIS_TOG_OK )
{
return ERR_SUCCESS;
}
r = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK; // USB device answer status
if( r == USB_PID_STALL )
{
return ( r | ERR_USB_TRANSFER );
}
if( r == USB_PID_NAK )
{
if( timeout == 0 )
{
return ( r | ERR_USB_TRANSFER );
}
if( timeout < 0xFFFF )
{
timeout--;
}
--trans_rerty;
}
else switch ( endp_pid >> 4 )
{
case USB_PID_SETUP:
case USB_PID_OUT:
if( r )
{
return ( r | ERR_USB_TRANSFER );
}
break;
case USB_PID_IN:
if( ( r == USB_PID_DATA0 ) && ( r == USB_PID_DATA1 ) )
{
;
}
else if( r )
{
return ( r | ERR_USB_TRANSFER );
}
break;
default:
return ERR_USB_UNKNOWN;
}
}
Delay_Us( 15 );
if( USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT )
{
Delay_Us( 200 );
if( USBFSH_CheckRootHubPortEnable( ) == 0 )
{
return ERR_USB_DISCON; // USB device disconnect event
}
}
}while( ++trans_rerty < 10 );
return ERR_USB_TRANSFER; // Reply timeout
}
/*********************************************************************
* @fn USBFSH_CtrlTransfer
*
* @brief USB host control transfer.
*
* @para ep0_size: Device endpoint 0 size
* pbuf: Data buffer
* plen: Data length
*
* @return USB control transfer result.
*/
uint8_t USBFSH_CtrlTransfer( uint8_t ep0_size, uint8_t *pbuf, uint16_t *plen )
{
uint8_t s;
uint16_t rem_len, rx_len, rx_cnt, tx_cnt;
if( plen )
{
*plen = 0;
}
USBOTG_H_FS->HOST_TX_LEN = sizeof( USB_SETUP_REQ );
s = USBFSH_Transact( USB_PID_SETUP << 4 | 0x00, 0x00, DEF_CTRL_TRANS_TIMEOVER_CNT ); // SETUP stage, 200mS timeout
if( s != ERR_SUCCESS )
{
return s;
}
USBOTG_H_FS->HOST_TX_CTRL = USBOTG_H_FS->HOST_RX_CTRL = USBFS_UH_T_TOG | USBFS_UH_R_TOG | USBFS_UH_T_AUTO_TOG | USBFS_UH_R_AUTO_TOG; // Default DATA1
USBOTG_H_FS->HOST_TX_LEN = 0x01; // The default no-data state stage is IN
rem_len = pUSBFS_SetupRequest->wLength;
if( rem_len && pbuf )
{
if( pUSBFS_SetupRequest->bRequestType & USB_REQ_TYP_IN )
{
/* Receive data */
while( rem_len )
{
Delay_Us( 100 );
s = USBFSH_Transact( USB_PID_IN << 4 | 0x00, USBOTG_H_FS->HOST_RX_CTRL, DEF_CTRL_TRANS_TIMEOVER_CNT ); // IN
if( s != ERR_SUCCESS )
{
return s;
}
rx_len = ( USBOTG_H_FS->RX_LEN < rem_len )? USBOTG_H_FS->RX_LEN : rem_len;
rem_len -= rx_len;
if( plen )
{
*plen += rx_len; // The total length of the actual successful transmission and reception
}
for( rx_cnt = 0; rx_cnt != rx_len; rx_cnt++ )
{
*pbuf = USBFS_RX_Buf[ rx_cnt ];
pbuf++;
}
if( ( USBOTG_H_FS->RX_LEN == 0 ) || ( USBOTG_H_FS->RX_LEN & ( ep0_size - 1 ) ) )
{
break; // Short package
}
}
USBOTG_H_FS->HOST_TX_LEN = 0x00; // Status stage is OUT
}
else
{
/* Send data */
while( rem_len )
{
Delay_Us( 100 );
USBOTG_H_FS->HOST_TX_LEN = ( rem_len >= ep0_size )? ep0_size : rem_len;
for( tx_cnt = 0; tx_cnt != USBOTG_H_FS->HOST_TX_LEN; tx_cnt++ )
{
USBFS_TX_Buf[ tx_cnt ] = *pbuf;
pbuf++;
}
s = USBFSH_Transact( USB_PID_OUT << 4 | 0x00, USBOTG_H_FS->HOST_TX_CTRL, DEF_CTRL_TRANS_TIMEOVER_CNT ); // OUT
if( s != ERR_SUCCESS )
{
return s;
}
rem_len -= USBOTG_H_FS->HOST_TX_LEN;
if( plen )
{
*plen += USBOTG_H_FS->HOST_TX_LEN; // The total length of the actual successful transmission and reception
}
}
}
}
Delay_Us( 100 );
s = USBFSH_Transact( ( USBOTG_H_FS->HOST_TX_LEN )? ( USB_PID_IN << 4 | 0x00 ) : ( USB_PID_OUT << 4 | 0x00 ), USBFS_UH_R_TOG | USBFS_UH_T_TOG, DEF_CTRL_TRANS_TIMEOVER_CNT ); /* STATUS½×¶Î */
if( s != ERR_SUCCESS )
{
return s;
}
if( USBOTG_H_FS->HOST_TX_LEN == 0 )
{
return ERR_SUCCESS;
}
if( USBOTG_H_FS->RX_LEN == 0 )
{
return ERR_SUCCESS;
}
return ERR_USB_BUF_OVER;
}
/*********************************************************************
* @fn USBFSH_GetDeviceDescr
*
* @brief Get the device descriptor of the USB device.
*
* @para pep0_size: Device endpoint 0 size
* pbuf: Data buffer
*
* @return The result of getting the device descriptor.
*/
uint8_t USBFSH_GetDeviceDescr( uint8_t *pep0_size, uint8_t *pbuf )
{
uint8_t s;
uint16_t len;
*pep0_size = DEFAULT_ENDP0_SIZE;
memcpy( pUSBFS_SetupRequest, SetupGetDevDesc, sizeof( USB_SETUP_REQ ) );
s = USBFSH_CtrlTransfer( *pep0_size, pbuf, &len );
if( s != ERR_SUCCESS )
{
return s;
}
*pep0_size = ( (PUSB_DEV_DESCR)pbuf )->bMaxPacketSize0;
if( len < ( (PUSB_SETUP_REQ)SetupGetDevDesc )->wLength )
{
return ERR_USB_BUF_OVER;
}
return ERR_SUCCESS;
}
/*********************************************************************
* @fn USBFSH_GetConfigDescr
*
* @brief Get the configuration descriptor of the USB device.
*
* @para ep0_size: Device endpoint 0 size
* pbuf: Data buffer
* buf_len: Data buffer length
* pcfg_len: The length of the device configuration descriptor
*
* @return The result of getting the configuration descriptor.
*/
uint8_t USBFSH_GetConfigDescr( uint8_t ep0_size, uint8_t *pbuf, uint16_t buf_len, uint16_t *pcfg_len )
{
uint8_t s;
memcpy( pUSBFS_SetupRequest, SetupGetCfgDesc, sizeof( USB_SETUP_REQ ) );
s = USBFSH_CtrlTransfer( ep0_size, pbuf, pcfg_len );
if( s != ERR_SUCCESS )
{
return s;
}
if( *pcfg_len < ( (PUSB_SETUP_REQ)SetupGetCfgDesc )->wLength )
{
return ERR_USB_BUF_OVER;
}
*pcfg_len = ( (PUSB_CFG_DESCR)pbuf )->wTotalLength;
if( *pcfg_len > buf_len )
{
*pcfg_len = buf_len;
}
memcpy( pUSBFS_SetupRequest, SetupGetCfgDesc, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wLength = *pcfg_len;
s = USBFSH_CtrlTransfer( ep0_size, pbuf, pcfg_len );
return s;
}
/*********************************************************************
* @fn USBFSH_GetStrDescr
*
* @brief Get the string descriptor of the USB device.
*
* @para ep0_size: Device endpoint 0 size
* str_num: Index of string descriptor
* pbuf: Data buffer
*
* @return The result of getting the string descriptor.
*/
uint8_t USBFSH_GetStrDescr( uint8_t ep0_size, uint8_t str_num, uint8_t *pbuf )
{
uint8_t s;
uint16_t len;
/* Get the string descriptor of the first 4 bytes */
memcpy( pUSBFS_SetupRequest, SetupGetStrDesc, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wValue = ( (uint16_t)USB_DESCR_TYP_STRING << 8 ) | str_num;
s = USBFSH_CtrlTransfer( ep0_size, pbuf, &len );
if( s != ERR_SUCCESS )
{
return s;
}
/* Get the complete string descriptor */
len = pbuf[ 0 ];
memcpy( pUSBFS_SetupRequest, SetupGetStrDesc, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wValue = ( (uint16_t)USB_DESCR_TYP_STRING << 8 ) | str_num;
pUSBFS_SetupRequest->wLength = len;
s = USBFSH_CtrlTransfer( ep0_size, pbuf, &len );
if( s != ERR_SUCCESS )
{
return s;
}
return ERR_SUCCESS;
}
/*********************************************************************
* @fn USBFSH_SetUsbAddress
*
* @brief Set USB device address.
*
* @para ep0_size: Device endpoint 0 size
* addr: Device address
*
* @return The result of setting device address.
*/
uint8_t USBFSH_SetUsbAddress( uint8_t ep0_size, uint8_t addr )
{
uint8_t s;
memcpy( pUSBFS_SetupRequest, SetupSetAddr, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wValue = (uint16_t)addr;
s = USBFSH_CtrlTransfer( ep0_size, NULL, NULL );
if( s != ERR_SUCCESS )
{
return s;
}
USBFSH_SetSelfAddr( addr );
Delay_Ms( DEF_BUS_RESET_TIME >> 1 ); // Wait for the USB device to complete its operation.
return ERR_SUCCESS;
}
/*********************************************************************
* @fn USBFSH_SetUsbConfig
*
* @brief Set USB configuration.
*
* @para ep0_size: Device endpoint 0 size
* cfg: Device configuration value
*
* @return The result of setting device configuration.
*/
uint8_t USBFSH_SetUsbConfig( uint8_t ep0_size, uint8_t cfg_val )
{
memcpy( pUSBFS_SetupRequest, SetupSetConfig, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wValue = (uint16_t)cfg_val;
return USBFSH_CtrlTransfer( ep0_size, NULL, NULL );
}
/*********************************************************************
* @fn USBFSH_ClearEndpStall
*
* @brief Clear endpoint stall.
*
* @para ep0_size: Device endpoint 0 size
* endp_num: Endpoint number.
*
* @return The result of clearing endpoint stall.
*/
uint8_t USBFSH_ClearEndpStall( uint8_t ep0_size, uint8_t endp_num )
{
memcpy( pUSBFS_SetupRequest, SetupClearEndpStall, sizeof( USB_SETUP_REQ ) );
pUSBFS_SetupRequest->wIndex = (uint16_t)endp_num;
return USBFSH_CtrlTransfer( ep0_size, NULL, NULL );
}
/*********************************************************************
* @fn USBFSH_GetEndpData
*
* @brief Get data from USB device input endpoint.
*
* @para endp_num: Endpoint number
* pendp_tog: Endpoint toggle
* pbuf: Data Buffer
* plen: Data length
*
* @return The result of getting data.
*/
uint8_t USBFSH_GetEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t *plen )
{
uint8_t s;
s = USBFSH_Transact( ( USB_PID_IN << 4 ) | endp_num, *pendp_tog, 0 );
if( s == ERR_SUCCESS )
{
*pendp_tog ^= USBFS_UH_T_TOG | USBFS_UH_R_TOG;
*plen = USBOTG_H_FS->RX_LEN;
memcpy( pbuf, USBFS_RX_Buf, *plen );
}
return s;
}
/*********************************************************************
* @fn USBFSH_SendEndpData
*
* @brief Send data to the USB device output endpoint.
*
* @para endp_num: Endpoint number
* pendp_tog: Endpoint toggle
* pbuf: Data Buffer
* plen: Data length
*
* @return The result of sending data.
*/
uint8_t USBFSH_SendEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t len )
{
uint8_t s;
memcpy( USBFS_TX_Buf, pbuf, len );
USBOTG_H_FS->HOST_TX_LEN = len;
s = USBFSH_Transact( ( USB_PID_OUT << 4 ) | endp_num, *pendp_tog, 0 );
if( s == ERR_SUCCESS )
{
*pendp_tog ^= USBFS_UH_T_TOG | USBFS_UH_R_TOG;
}
return s;
}
@@ -0,0 +1,103 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_usbfs_host.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : USBOTG full speed host 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 __CH32V20x_USBFS_HOST_H__
#define __CH32V20x_USBFS_HOST_H__
/*******************************************************************************/
/* Header File */
#include "ch32v20x.h"
#include "ch32v20x_usb.h"
/*******************************************************************************/
/* USB Setup Request Macro Definition */
#define pUSBFS_SetupRequest ( (PUSB_SETUP_REQ)USBFS_TX_Buf )
/*******************************************************************************/
/* Constant Definition */
#ifndef DEF_GET_USB_DEV_DESC
#define DEF_GET_USB_DEV_DESC
/* Get Device Descriptor Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupGetDevDesc[ ] =
{
USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_DEVICE, 0x00, 0x00, sizeof( USB_DEV_DESCR ), 0x00
};
/* Get Configuration Descriptor Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupGetCfgDesc[ ] =
{
USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_CONFIG, 0x00, 0x00, 0x04, 0x00
};
/* Get String Descriptor Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupGetStrDesc[ ] =
{
USB_REQ_TYP_IN, USB_GET_DESCRIPTOR, 0x00, USB_DESCR_TYP_STRING, 0x09, 0x04, 0x04, 0x00
};
/* Set USB Address Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupSetAddr[ ] =
{
USB_REQ_TYP_OUT, USB_SET_ADDRESS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Set USB Configuration Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupSetConfig[ ] =
{
USB_REQ_TYP_OUT, USB_SET_CONFIGURATION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Clear Endpoint STALL Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupClearEndpStall[ ] =
{
USB_REQ_TYP_OUT | USB_REQ_RECIP_ENDP, USB_CLEAR_FEATURE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Set Device Interface Command Packet */
__attribute__((aligned(4))) static const uint8_t SetupSetInterface[ ] =
{
USB_REQ_RECIP_INTERF, USB_SET_INTERFACE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#endif
/*******************************************************************************/
/* Variable Declaration */
extern __attribute__((aligned(4))) uint8_t RxBuffer[ ]; // IN, must even address
extern __attribute__((aligned(4))) uint8_t TxBuffer[ ]; // OUT, must even address
#define USBFS_RX_Buf RxBuffer
#define USBFS_TX_Buf TxBuffer
/*******************************************************************************/
/* Function Declaration */
extern void USBFS_RCC_Init( void );
extern void USBFS_Host_Init( FunctionalState sta );
extern uint8_t USBFSH_CheckRootHubPortStatus( uint8_t dev_sta );
extern uint8_t USBFSH_CheckRootHubPortEnable( void );
extern uint8_t USBFSH_CheckRootHubPortSpeed( void );
extern void USBFSH_SetSelfAddr( uint8_t addr );
extern void USBFSH_SetSelfSpeed( uint8_t speed );
extern void USBFSH_ResetRootHubPort( uint8_t mode );
extern uint8_t USBFSH_EnableRootHubPort( uint8_t *pspeed );
extern uint8_t USBFSH_Transact( uint8_t endp_pid, uint8_t endp_tog, uint16_t timeout );
extern uint8_t USBFSH_CtrlTransfer( uint8_t ep0_size, uint8_t *pbuf, uint16_t *plen );
extern uint8_t USBFSH_GetDeviceDescr( uint8_t *pep0_size, uint8_t *pbuf );
extern uint8_t USBFSH_GetConfigDescr( uint8_t ep0_size, uint8_t *pbuf, uint16_t buf_len, uint16_t *pcfg_len );
extern uint8_t USBFSH_GetStrDescr( uint8_t ep0_size, uint8_t str_num, uint8_t *pbuf );
extern uint8_t USBFSH_SetUsbAddress( uint8_t ep0_size, uint8_t addr );
extern uint8_t USBFSH_SetUsbConfig( uint8_t ep0_size, uint8_t cfg_val );
extern uint8_t USBFSH_ClearEndpStall( uint8_t ep0_size, uint8_t endp_num );
extern uint8_t USBFSH_GetEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t *plen );
extern uint8_t USBFSH_SendEndpData( uint8_t endp_num, uint8_t *pendp_tog, uint8_t *pbuf, uint16_t len );
extern uint8_t USBFSH_PortDetect( uint8_t status );
#endif
@@ -0,0 +1,169 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_host_config.h
* Author : WCH
* Version : V1.0.0
* Date : 2022/08/29
* Description :
*********************************************************************************
* 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 __USB_HOST_CONFIG_H
#define __USB_HOST_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************/
/* Header File */
#include "string.h"
#include "debug.h"
#include "ch32v20x_usb.h"
#include "ch32v20x_usbfs_host.h"
/******************************************************************************/
/* USB Host Communication Related Macro Definition */
/* USB Host Port General Control */
#define DEF_TOTAL_ROOT_HUB 1
#define DEF_USB_PORT_FS_EN 1
#define DEF_USB_PORT_FS 0x00
/* USB Root Device Status */
#define ROOT_DEV_DISCONNECT 0
#define ROOT_DEV_CONNECTED 1
#define ROOT_DEV_FAILED 2
#define ROOT_DEV_SUCCESS 3
/* USB Device Address */
#define USB_DEVICE_ADDR 0x02
/* USB Speed */
#define USB_LOW_SPEED 0x00
#define USB_FULL_SPEED 0x01
#define USB_HIGH_SPEED 0x02
#define USB_SPEED_CHECK_ERR 0xFF
/* Configuration Descriptor Type */
#define DEF_DECR_CONFIG 0x02
#define DEF_DECR_INTERFACE 0x04
#define DEF_DECR_ENDPOINT 0x05
#define DEF_DECR_HID 0x21
/* USB Communication Status Code */
#define ERR_SUCCESS 0x00
#define ERR_USB_CONNECT 0x15
#define ERR_USB_DISCON 0x16
#define ERR_USB_BUF_OVER 0x17
#define ERR_USB_DISK_ERR 0x1F
#define ERR_USB_TRANSFER 0x20
#define ERR_USB_UNSUPPORT 0xFB
#define ERR_USB_UNAVAILABLE 0xFC
#define ERR_USB_UNKNOWN 0xFE
/* USB Device Enumeration Status Code */
#define DEF_DEV_DESCR_GETFAIL 0x45
#define DEF_DEV_ADDR_SETFAIL 0x46
#define DEF_CFG_DESCR_GETFAIL 0x47
#define DEF_REP_DESCR_GETFAIL 0x48
#define DEF_DEV_TYPE_UNKNOWN 0xFF
/* USB Communication Time */
#define DEF_BUS_RESET_TIME 11 // USB bus reset time
#define DEF_RE_ATTACH_TIMEOUT 100 // Wait for the USB device to reconnect after reset, 100mS timeout
#define DEF_WAIT_USB_TOUT_200US 1000
#define DEF_CTRL_TRANS_TIMEOVER_CNT 60000 // Control transmission delay timing
/* General */
#define DEF_ONE_USB_SUP_DEV_TOTAL 1
#define DEF_NEXT_HUB_PORT_NUM_MAX 4
#define DEF_INTERFACE_NUM_MAX 4
#define DEF_COM_BUF_LEN 255
/* Debug */
#define DEF_DEBUG_PRINTF 1
#if ( DEF_DEBUG_PRINTF == 1 )
#define DUG_PRINTF( format, arg... ) printf( format, ##arg )
#else
#define DUG_PRINTF( format, arg... ) do{ if( 0 )printf( format, ##arg ); }while( 0 );
#endif
/* HUB Port Device */
typedef struct _HUB_DEVICE
{
uint8_t bStatus;
uint8_t bType;
uint8_t bAddress;
uint8_t bSpeed;
uint8_t bEp0MaxPks;
uint8_t DeviceIndex;
}HUB_DEVICE, *PHUB_DEVICE;
/* Root HUB Device Structure, Physical Interface */
typedef struct _ROOT_HUB_DEVICE
{
uint8_t bStatus;
uint8_t bType;
uint8_t bAddress;
uint8_t bSpeed;
uint8_t bEp0MaxPks;
uint8_t DeviceIndex;
uint8_t bPortNum;
HUB_DEVICE Device[ DEF_NEXT_HUB_PORT_NUM_MAX ];
} ROOT_HUB_DEVICE, *PROOT_HUB_DEVICE;
/* USB Host Control Structure */
struct __HOST_CTL
{
uint8_t InterfaceNum;
uint8_t ErrorCount;
struct interface
{
uint8_t Type;
uint16_t HidDescLen;
uint8_t HidReportID;
uint8_t Full_KB_Flag;
uint8_t InEndpNum;
uint8_t InEndpAddr[ 4 ];
uint8_t InEndpType[ 4 ];
uint16_t InEndpSize[ 4 ];
uint8_t InEndpTog[ 4 ];
uint8_t InEndpInterval[ 4 ];
uint8_t InEndpTimeCount[ 4 ];
uint8_t OutEndpNum;
uint8_t OutEndpAddr[ 4 ];
uint8_t OutEndpType[ 4 ];
uint16_t OutEndpSize[ 4 ];
uint8_t OutEndpTog[ 4 ];
uint8_t IDFlag;
uint8_t ReportID;
uint8_t LED_Usage_Min;
uint8_t LED_Usage_Max;
uint8_t SetReport_Swi;
uint8_t SetReport_Value;
uint8_t SetReport_Flag;
}Interface[ DEF_INTERFACE_NUM_MAX ];
};
/*******************************************************************************/
/* Variable Declaration */
extern uint8_t DevDesc_Buf[ ];
extern uint8_t Com_Buf[ ];
extern struct _ROOT_HUB_DEVICE RootHubDev[ ];
extern struct __HOST_CTL HostCtl[ ];
#ifdef __cplusplus
}
#endif
#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,41 @@
/********************************** (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("WCH-Interrupt-fast")));
void HardFault_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
/*********************************************************************
* @fn NMI_Handler
*
* @brief This function handles NMI exception.
*
* @return none
*/
void NMI_Handler(void)
{
}
/*********************************************************************
* @fn HardFault_Handler
*
* @brief This function handles Hard Fault exception.
*
* @return none
*/
void HardFault_Handler(void)
{
while (1)
{
}
}
@@ -0,0 +1,20 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_it.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : This file contains the headers of the interrupt handlers.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH32V20x_IT_H
#define __CH32V20x_IT_H
#include "debug.h"
#endif /* __CH32V20x_IT_H */
@@ -0,0 +1,539 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32v30x.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : CH32V30x 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 __CH32V20x_USB_H
#define __CH32V20x_USB_H
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************/
/* Header Files */
#include "stdint.h"
/*******************************************************************************/
/* USB Communication Related Macro Definition */
/* USB Endpoint0 Size */
#ifndef DEFAULT_ENDP0_SIZE
#define DEFAULT_ENDP0_SIZE 8 // default maximum packet size for endpoint 0
#endif
#ifndef MAX_PACKET_SIZE
#define MAX_PACKET_SIZE 64 // maximum packet size
#endif
/* USB PID */
#ifndef USB_PID_SETUP
#define USB_PID_NULL 0x00
#define USB_PID_SOF 0x05
#define USB_PID_SETUP 0x0D
#define USB_PID_IN 0x09
#define USB_PID_OUT 0x01
#define USB_PID_NYET 0x06
#define USB_PID_ACK 0x02
#define USB_PID_NAK 0x0A
#define USB_PID_STALL 0x0E
#define USB_PID_DATA0 0x03
#define USB_PID_DATA1 0x0B
#define USB_PID_PRE 0x0C
#endif
/* USB standard device request code */
#ifndef USB_GET_DESCRIPTOR
#define USB_GET_STATUS 0x00
#define USB_CLEAR_FEATURE 0x01
#define USB_SET_FEATURE 0x03
#define USB_SET_ADDRESS 0x05
#define USB_GET_DESCRIPTOR 0x06
#define USB_SET_DESCRIPTOR 0x07
#define USB_GET_CONFIGURATION 0x08
#define USB_SET_CONFIGURATION 0x09
#define USB_GET_INTERFACE 0x0A
#define USB_SET_INTERFACE 0x0B
#define USB_SYNCH_FRAME 0x0C
#endif
#define DEF_STRING_DESC_LANG 0x00
#define DEF_STRING_DESC_MANU 0x01
#define DEF_STRING_DESC_PROD 0x02
#define DEF_STRING_DESC_SERN 0x03
/* USB hub class request code */
#ifndef HUB_GET_DESCRIPTOR
#define HUB_GET_STATUS 0x00
#define HUB_CLEAR_FEATURE 0x01
#define HUB_GET_STATE 0x02
#define HUB_SET_FEATURE 0x03
#define HUB_GET_DESCRIPTOR 0x06
#define HUB_SET_DESCRIPTOR 0x07
#endif
/* USB HID class request code */
#ifndef HID_GET_REPORT
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
#define HID_GET_PROTOCOL 0x03
#define HID_SET_REPORT 0x09
#define HID_SET_IDLE 0x0A
#define HID_SET_PROTOCOL 0x0B
#endif
/* Bit Define for USB Request Type */
#ifndef USB_REQ_TYP_MASK
#define USB_REQ_TYP_IN 0x80
#define USB_REQ_TYP_OUT 0x00
#define USB_REQ_TYP_READ 0x80
#define USB_REQ_TYP_WRITE 0x00
#define USB_REQ_TYP_MASK 0x60
#define USB_REQ_TYP_STANDARD 0x00
#define USB_REQ_TYP_CLASS 0x20
#define USB_REQ_TYP_VENDOR 0x40
#define USB_REQ_TYP_RESERVED 0x60
#define USB_REQ_RECIP_MASK 0x1F
#define USB_REQ_RECIP_DEVICE 0x00
#define USB_REQ_RECIP_INTERF 0x01
#define USB_REQ_RECIP_ENDP 0x02
#define USB_REQ_RECIP_OTHER 0x03
#define USB_REQ_FEAT_REMOTE_WAKEUP 0x01
#define USB_REQ_FEAT_ENDP_HALT 0x00
#endif
/* USB Descriptor Type */
#ifndef USB_DESCR_TYP_DEVICE
#define USB_DESCR_TYP_DEVICE 0x01
#define USB_DESCR_TYP_CONFIG 0x02
#define USB_DESCR_TYP_STRING 0x03
#define USB_DESCR_TYP_INTERF 0x04
#define USB_DESCR_TYP_ENDP 0x05
#define USB_DESCR_TYP_QUALIF 0x06
#define USB_DESCR_TYP_SPEED 0x07
#define USB_DESCR_TYP_OTG 0x09
#define USB_DESCR_TYP_BOS 0X0F
#define USB_DESCR_TYP_HID 0x21
#define USB_DESCR_TYP_REPORT 0x22
#define USB_DESCR_TYP_PHYSIC 0x23
#define USB_DESCR_TYP_CS_INTF 0x24
#define USB_DESCR_TYP_CS_ENDP 0x25
#define USB_DESCR_TYP_HUB 0x29
#endif
/* USB Device Class */
#ifndef USB_DEV_CLASS_HUB
#define USB_DEV_CLASS_RESERVED 0x00
#define USB_DEV_CLASS_AUDIO 0x01
#define USB_DEV_CLASS_COMMUNIC 0x02
#define USB_DEV_CLASS_HID 0x03
#define USB_DEV_CLASS_MONITOR 0x04
#define USB_DEV_CLASS_PHYSIC_IF 0x05
#define USB_DEV_CLASS_POWER 0x06
#define USB_DEV_CLASS_PRINTER 0x07
#define USB_DEV_CLASS_STORAGE 0x08
#define USB_DEV_CLASS_HUB 0x09
#define USB_DEV_CLASS_VEN_SPEC 0xFF
#endif
/* USB Hub Class Request */
#ifndef HUB_GET_HUB_DESCRIPTOR
#define HUB_CLEAR_HUB_FEATURE 0x20
#define HUB_CLEAR_PORT_FEATURE 0x23
#define HUB_GET_BUS_STATE 0xA3
#define HUB_GET_HUB_DESCRIPTOR 0xA0
#define HUB_GET_HUB_STATUS 0xA0
#define HUB_GET_PORT_STATUS 0xA3
#define HUB_SET_HUB_DESCRIPTOR 0x20
#define HUB_SET_HUB_FEATURE 0x20
#define HUB_SET_PORT_FEATURE 0x23
#endif
/* Hub Class Feature Selectors */
#ifndef HUB_PORT_RESET
#define HUB_C_HUB_LOCAL_POWER 0
#define HUB_C_HUB_OVER_CURRENT 1
#define HUB_PORT_CONNECTION 0
#define HUB_PORT_ENABLE 1
#define HUB_PORT_SUSPEND 2
#define HUB_PORT_OVER_CURRENT 3
#define HUB_PORT_RESET 4
#define HUB_PORT_POWER 8
#define HUB_PORT_LOW_SPEED 9
#define HUB_C_PORT_CONNECTION 16
#define HUB_C_PORT_ENABLE 17
#define HUB_C_PORT_SUSPEND 18
#define HUB_C_PORT_OVER_CURRENT 19
#define HUB_C_PORT_RESET 20
#endif
/* USB HID Class Request Code */
#ifndef HID_GET_REPORT
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
#define HID_GET_PROTOCOL 0x03
#define HID_SET_REPORT 0x09
#define HID_SET_IDLE 0x0A
#define HID_SET_PROTOCOL 0x0B
#endif
/* USB UDisk */
#ifndef USB_BO_CBW_SIZE
#define USB_BO_CBW_SIZE 0x1F
#define USB_BO_CSW_SIZE 0x0D
#endif
#ifndef USB_BO_CBW_SIG0
#define USB_BO_CBW_SIG0 0x55
#define USB_BO_CBW_SIG1 0x53
#define USB_BO_CBW_SIG2 0x42
#define USB_BO_CBW_SIG3 0x43
#define USB_BO_CSW_SIG0 0x55
#define USB_BO_CSW_SIG1 0x53
#define USB_BO_CSW_SIG2 0x42
#define USB_BO_CSW_SIG3 0x53
#endif
/*******************************************************************************/
/* USBFS Related Register Macro Definition */
/* R8_USB_CTRL */
#define USBFS_UC_HOST_MODE 0x80
#define USBFS_UC_LOW_SPEED 0x40
#define USBFS_UC_DEV_PU_EN 0x20
#define USBFS_UC_SYS_CTRL_MASK 0x30
#define USBFS_UC_SYS_CTRL0 0x00
#define USBFS_UC_SYS_CTRL1 0x10
#define USBFS_UC_SYS_CTRL2 0x20
#define USBFS_UC_SYS_CTRL3 0x30
#define USBFS_UC_INT_BUSY 0x08
#define USBFS_UC_RESET_SIE 0x04
#define USBFS_UC_CLR_ALL 0x02
#define USBFS_UC_DMA_EN 0x01
/* R8_USB_INT_EN */
#define USBFS_UIE_DEV_SOF 0x80
#define USBFS_UIE_DEV_NAK 0x40
#define USBFS_UIE_FIFO_OV 0x10
#define USBFS_UIE_HST_SOF 0x08
#define USBFS_UIE_SUSPEND 0x04
#define USBFS_UIE_TRANSFER 0x02
#define USBFS_UIE_DETECT 0x01
#define USBFS_UIE_BUS_RST 0x01
/* R8_USB_DEV_AD */
#define USBFS_UDA_GP_BIT 0x80
#define USBFS_USB_ADDR_MASK 0x7F
/* R8_USB_MIS_ST */
#define USBFS_UMS_SOF_PRES 0x80
#define USBFS_UMS_SOF_ACT 0x40
#define USBFS_UMS_SIE_FREE 0x20
#define USBFS_UMS_R_FIFO_RDY 0x10
#define USBFS_UMS_BUS_RESET 0x08
#define USBFS_UMS_SUSPEND 0x04
#define USBFS_UMS_DM_LEVEL 0x02
#define USBFS_UMS_DEV_ATTACH 0x01
/* R8_USB_INT_FG */
#define USBFS_U_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received
#define USBFS_U_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
#define USBFS_U_SIE_FREE 0x20 // RO, indicate USB SIE free status
#define USBFS_UIF_FIFO_OV 0x10 // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear
#define USBFS_UIF_HST_SOF 0x08 // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear
#define USBFS_UIF_SUSPEND 0x04 // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear
#define USBFS_UIF_TRANSFER 0x02 // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear
#define USBFS_UIF_DETECT 0x01 // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear
#define USBFS_UIF_BUS_RST 0x01 // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear
/* R8_USB_INT_ST */
#define USBFS_UIS_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received for USB device mode
#define USBFS_UIS_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
#define USBFS_UIS_TOKEN_MASK 0x30 // RO, bit mask of current token PID code received for USB device mode
#define USBFS_UIS_TOKEN_OUT 0x00
#define USBFS_UIS_TOKEN_SOF 0x10
#define USBFS_UIS_TOKEN_IN 0x20
#define USBFS_UIS_TOKEN_SETUP 0x30
// bUIS_TOKEN1 & bUIS_TOKEN0: current token PID code received for USB device mode
// 00: OUT token PID received
// 01: SOF token PID received
// 10: IN token PID received
// 11: SETUP token PID received
#define USBFS_UIS_ENDP_MASK 0x0F // RO, bit mask of current transfer endpoint number for USB device mode
#define USBFS_UIS_H_RES_MASK 0x0F // RO, bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received
/* R32_USB_OTG_CR */
#define USBFS_CR_SESS_VTH 0x20
#define USBFS_CR_VBUS_VTH 0x10
#define USBFS_CR_OTG_EN 0x08
#define USBFS_CR_IDPU 0x04
#define USBFS_CR_CHARGE_VBUS 0x02
#define USBFS_CR_DISCHAR_VBUS 0x01
/* R32_USB_OTG_SR */
#define USBFS_SR_ID_DIG 0x08
#define USBFS_SR_SESS_END 0x04
#define USBFS_SR_SESS_VLD 0x02
#define USBFS_SR_VBUS_VLD 0x01
/* R8_UDEV_CTRL */
#define USBFS_UD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
#define USBFS_UD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
#define USBFS_UD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
#define USBFS_UD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed
#define USBFS_UD_GP_BIT 0x02 // general purpose bit
#define USBFS_UD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable
/* R8_UEP4_1_MOD */
#define USBFS_UEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT)
#define USBFS_UEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN)
#define USBFS_UEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1
// bUEPn_RX_EN & bUEPn_TX_EN & bUEPn_BUF_MOD: USB endpoint 1/2/3 buffer mode, buffer start address is UEPn_DMA
// 0 0 x: disable endpoint and disable buffer
// 1 0 0: 64 bytes buffer for receiving (OUT endpoint)
// 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receiving (OUT endpoint), total=128bytes
// 0 1 0: 64 bytes buffer for transmittal (IN endpoint)
// 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmittal (IN endpoint), total=128bytes
// 1 1 0: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes
// 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receiving (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmittal (IN endpoint), total=256bytes
#define USBFS_UEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT)
#define USBFS_UEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN)
// bUEP4_RX_EN & bUEP4_TX_EN: USB endpoint 4 buffer mode, buffer start address is UEP0_DMA
// 0 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint)
// 1 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receiving (OUT endpoint), total=128bytes
// 0 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=128bytes
// 1 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint)
// + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes
#define USBFS_UEP4_BUF_MOD 0x01
/* R8_UEP2_3_MOD */
#define USBFS_UEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT)
#define USBFS_UEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN)
#define USBFS_UEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3
#define USBFS_UEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT)
#define USBFS_UEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN)
#define USBFS_UEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2
/* R8_UEP5_6_MOD */
#define USBFS_UEP6_RX_EN 0x80 // enable USB endpoint 6 receiving (OUT)
#define USBFS_UEP6_TX_EN 0x40 // enable USB endpoint 6 transmittal (IN)
#define USBFS_UEP6_BUF_MOD 0x10 // buffer mode of USB endpoint 6
#define USBFS_UEP5_RX_EN 0x08 // enable USB endpoint 5 receiving (OUT)
#define USBFS_UEP5_TX_EN 0x04 // enable USB endpoint 5 transmittal (IN)
#define USBFS_UEP5_BUF_MOD 0x01 // buffer mode of USB endpoint 5
/* R8_UEP7_MOD */
#define USBFS_UEP7_RX_EN 0x08 // enable USB endpoint 7 receiving (OUT)
#define USBFS_UEP7_TX_EN 0x04 // enable USB endpoint 7 transmittal (IN)
#define USBFS_UEP7_BUF_MOD 0x01 // buffer mode of USB endpoint 7
/* R8_UEPn_TX_CTRL */
#define USBFS_UEP_T_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
#define USBFS_UEP_T_TOG 0x04 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1
#define USBFS_UEP_T_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN)
#define USBFS_UEP_T_RES_ACK 0x00
#define USBFS_UEP_T_RES_NONE 0x01
#define USBFS_UEP_T_RES_NAK 0x02
#define USBFS_UEP_T_RES_STALL 0x03
// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN)
// 00: DATA0 or DATA1 then expecting ACK (ready)
// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions
// 10: NAK (busy)
// 11: STALL (error)
// host aux setup
/* R8_UEPn_RX_CTRL, n=0-7 */
#define USBFS_UEP_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
#define USBFS_UEP_R_TOG 0x04 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1
#define USBFS_UEP_R_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X receiving (OUT)
#define USBFS_UEP_R_RES_ACK 0x00
#define USBFS_UEP_R_RES_NONE 0x01
#define USBFS_UEP_R_RES_NAK 0x02
#define USBFS_UEP_R_RES_STALL 0x03
// RB_UEP_R_RES1 & RB_UEP_R_RES0: handshake response type for USB endpoint X receiving (OUT)
// 00: ACK (ready)
// 01: no response, time out to host, for non-zero endpoint isochronous transactions
// 10: NAK (busy)
// 11: STALL (error)
/* R8_UHOST_CTRL */
#define USBFS_UH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
#define USBFS_UH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
#define USBFS_UH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
#define USBFS_UH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed
#define USBFS_UH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset
#define USBFS_UH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached
/* R32_UH_EP_MOD */
#define USBFS_UH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal
#define USBFS_UH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint
// bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA
// 0 x: disable endpoint and disable buffer
// 1 0: 64 bytes buffer for transmittal (OUT endpoint)
// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes
#define USBFS_UH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving
#define USBFS_UH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint
// bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA
// 0 x: disable endpoint and disable buffer
// 1 0: 64 bytes buffer for receiving (IN endpoint)
// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes
/* R16_UH_SETUP */
#define USBFS_UH_PRE_PID_EN 0x0400 // USB host PRE PID enable for low speed device via hub
#define USBFS_UH_SOF_EN 0x0004 // USB host automatic SOF enable
/* R8_UH_EP_PID */
#define USBFS_UH_TOKEN_MASK 0xF0 // bit mask of token PID for USB host transfer
#define USBFS_UH_ENDP_MASK 0x0F // bit mask of endpoint number for USB host transfer
/* R8_UH_RX_CTRL */
#define USBFS_UH_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
#define USBFS_UH_R_TOG 0x04 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1
#define USBFS_UH_R_RES 0x01 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions
/* R8_UH_TX_CTRL */
#define USBFS_UH_T_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
#define USBFS_UH_T_TOG 0x04 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1
#define USBFS_UH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions
/*******************************************************************************/
/* Struct Definition */
/* USB Setup Request */
typedef struct __attribute__((packed)) _USB_SETUP_REQ
{
uint8_t bRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} USB_SETUP_REQ, *PUSB_SETUP_REQ;
/* USB Device Descriptor */
typedef struct __attribute__((packed)) _USB_DEVICE_DESCR
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
} USB_DEV_DESCR, *PUSB_DEV_DESCR;
/* USB Configuration Descriptor */
typedef struct __attribute__((packed)) _USB_CONFIG_DESCR
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t MaxPower;
} USB_CFG_DESCR, *PUSB_CFG_DESCR;
/* USB Interface Descriptor */
typedef struct __attribute__((packed)) _USB_INTERF_DESCR
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
} USB_ITF_DESCR, *PUSB_ITF_DESCR;
/* USB Endpoint Descriptor */
typedef struct __attribute__((packed)) _USB_ENDPOINT_DESCR
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint8_t wMaxPacketSizeL;
uint8_t wMaxPacketSizeH;
uint8_t bInterval;
} USB_ENDP_DESCR, *PUSB_ENDP_DESCR;
/* USB Configuration Descriptor Set */
typedef struct __attribute__((packed)) _USB_CONFIG_DESCR_LONG
{
USB_CFG_DESCR cfg_descr;
USB_ITF_DESCR itf_descr;
USB_ENDP_DESCR endp_descr[ 1 ];
} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG;
/* USB HUB Descriptor */
typedef struct __attribute__((packed)) _USB_HUB_DESCR
{
uint8_t bDescLength;
uint8_t bDescriptorType;
uint8_t bNbrPorts;
uint8_t wHubCharacteristicsL;
uint8_t wHubCharacteristicsH;
uint8_t bPwrOn2PwrGood;
uint8_t bHubContrCurrent;
uint8_t DeviceRemovable;
uint8_t PortPwrCtrlMask;
} USB_HUB_DESCR, *PUSB_HUB_DESCR;
/* USB HID Descriptor */
typedef struct __attribute__((packed)) _USB_HID_DESCR
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bDescriptorTypeX;
uint8_t wDescriptorLengthL;
uint8_t wDescriptorLengthH;
} USB_HID_DESCR, *PUSB_HID_DESCR;
/* USB UDisk */
typedef struct __attribute__((packed)) _UDISK_BOC_CBW
{
uint32_t mCBW_Sig;
uint32_t mCBW_Tag;
uint32_t mCBW_DataLen;
uint8_t mCBW_Flag;
uint8_t mCBW_LUN;
uint8_t mCBW_CB_Len;
uint8_t mCBW_CB_Buf[ 16 ];
} UDISK_BOC_CBW, *PXUDISK_BOC_CBW;
/* USB UDisk */
typedef struct __attribute__((packed)) _UDISK_BOC_CSW
{
uint32_t mCBW_Sig;
uint32_t mCBW_Tag;
uint32_t mCSW_Residue;
uint8_t mCSW_Status;
} UDISK_BOC_CSW, *PXUDISK_BOC_CSW;
#ifdef __cplusplus
}
#endif
#endif /* __CH32V20x_USB_H */
+77
View File
@@ -0,0 +1,77 @@
/********************************** (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
1,Exam 1 :
USBFS host controller enumeration routines for byte manipulation of USB flash drives,
including file creation, modification, reading and deletion.
2,Exam 6 :
USBFS host controller enumeration routines for sector manipulation of USB flash drives,
including file creation, modification, reading and deletion
3,Exam 9 :
The USBFS host controller enumerates the USB flash drive to create folders on the drive,
including the primary and secondary directories, and the demo files in the corresponding directories.
4,Exam 11 :
USBFS host controller enumerates USB flash drives, enabling the enumeration of
the first 1000 files on the drive.
5,Exam 13 :USBFS host controller enumerates USB drives to create long filename files,
or to get long filename files.
Important: Only FAT12/FAT16/FAT32 formats are supported:
*/
#include "debug.h"
#include "stdio.h"
#include "string.h"
#include "Udisk_Operation.h"
/* Switches for code demonstration, 1:Enable 0:Disable */
#define DEF_TEST_FUNC_NUM DEF_TEST_FUNC_1
#define DEF_TEST_FUNC_1 1 /* Test 1 , Operation for Open/Read/Modify/Delete a file by bytes */
#define DEF_TEST_FUNC_6 6 /* Test 6 , Operation for Open/Read/Modify/Delete a file by sectors */
#define DEF_TEST_FUNC_9 9 /* Test 9 , Operation for creating folders */
#define DEF_TEST_FUNC_11 11 /* Test 11 , Operation for enumeration of the first 1000 files */
#define DEF_TEST_FUNC_13 13 /* Test 13 , Operation for creating long filename files */
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
USART_Printf_Init( 115200 );
Delay_Init( );
printf( "SystemClk:%d\r\n", SystemCoreClock );
printf( "USBFS HOST Test EXAM %d\r\n", DEF_TEST_FUNC_NUM );
/* General USB Host UDisk Operation Initialization */
Udisk_USBH_Initialization( );
while(1)
{
#if DEF_TEST_FUNC_NUM == DEF_TEST_FUNC_1
UDisk_USBH_ByteOperation( );
#elif DEF_TEST_FUNC_NUM == DEF_TEST_FUNC_6
UDisk_USBH_SectorOperation( );
#elif DEF_TEST_FUNC_NUM == DEF_TEST_FUNC_9
UDisk_USBH_CreatDirectory( );
#elif DEF_TEST_FUNC_NUM == DEF_TEST_FUNC_11
UDisk_USBH_EnumFiles( );
#elif DEF_TEST_FUNC_NUM == DEF_TEST_FUNC_13
UDisk_USBH_Longname( );
#endif
}
}
@@ -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 */