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
@@ -0,0 +1,144 @@
<?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>
<externalSetting/>
</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 (-Wuninitialised)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.warnings.uninitialized" useByScannerDiscovery="true" 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="false" 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}/USBLIB/USB-Driver/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Debug}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Core}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/User}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Peripheral/inc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/CONFIG}&quot;"/>
</option>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.std.2020844713" name="Language standard" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.std" useByScannerDiscovery="true" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.std.gnu99" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs.177116515" name="Defined symbols (-D)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols"/>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.2036806839" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler.1610882921" name="GNU RISC-V Cross C++ Compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler"/>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.1620074387" name="GNU RISC-V Cross C Linker" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.gcsections.194760422" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.gcsections" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.paths.2057340378" name="Library search path (-L)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.paths" useByScannerDiscovery="false" valueType="libPaths"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.scriptfile.1390103472" name="Script files (-T)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.scriptfile" useByScannerDiscovery="false" valueType="stringList">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/Ld/Link.ld}&quot;"/>
</option>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nostart.913830613" name="Do not use standard start files (-nostartfiles)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.nostart" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.usenewlibnano.239404511" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.usenewlibnano" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.usenewlibnosys.351964161" name="Do not use syscalls (--specs=nosys.specs)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.usenewlibnosys" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.otherobjs.16994550" name="Other objects" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.otherobjs" useByScannerDiscovery="false" valueType="userObjs"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.flags.1125808200" name="Linker flags (-Xlinker [option])" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.flags" useByScannerDiscovery="false" valueType="stringList"/>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.input.1859223768" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.linker.1947503520" name="GNU RISC-V Cross C++ Linker" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.linker">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.gcsections.1689063433" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.gcsections" value="true" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.paths.1029177148" name="Library search path (-L)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.paths" valueType="libPaths">
<listOptionValue builtIn="false" value="&quot;../LD&quot;"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.scriptfile.1751226764" name="Script files (-T)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.scriptfile" valueType="stringList">
<listOptionValue builtIn="false" value="Link.ld"/>
</option>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.nostart.642896175" name="Do not use standard start files (-nostartfiles)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.nostart" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.usenewlibnano.1540675679" name="Use newlib-nano (--specs=nano.specs)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.usenewlibnano" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver.1292785366" name="GNU RISC-V Cross Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver"/>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash.1801165667" name="GNU RISC-V Cross Create Flash Image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash"/>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createlisting.1356766765" name="GNU RISC-V Cross Create Listing" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createlisting">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.source.2052761852" name="Display source (--source|-S)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.source" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders.439659821" name="Display all headers (--all-headers|-x)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle.67111865" name="Demangle names (--demangle|-C)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers.1549373929" name="Display line numbers (--line-numbers|-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide.1298918921" name="Wide lines (--wide|-w)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.disassemble.1859590835" name="Disassemble (--disassemble|-d)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.disassemble" useByScannerDiscovery="false" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.printsize.712424314" name="GNU RISC-V Cross Print Size" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.printsize">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.printsize.format.1404031980" name="Size format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.printsize.format" useByScannerDiscovery="false"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="USB-Driver|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_D6.S|startup_ch32v20x_D8.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Startup"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="ilg.gnumcueclipse.managedbuild.packs"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="999.ilg.gnumcueclipse.managedbuild.cross.riscv.target.elf.275846018" name="Executable file" projectType="ilg.gnumcueclipse.managedbuild.cross.riscv.target.elf"/>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.767917625;ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.767917625.;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.1375371130;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.1473381709">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.1008047074;ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.1008047074.;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.1731377187;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.2036806839">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
</cproject>
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<projectDescription>
<name>CH32V20x_IAP</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>
</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="-1720682931388470200" 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,4 @@
eclipse.preferences.version=1
encoding//CONFIG/usb_desc.c=UTF-8
encoding//User/ch32v20x_usbotg_device.c=UTF-8
encoding//User/iap.c=UTF-8
@@ -0,0 +1,16 @@
Mcu Type=CH32V20x
Address=0x08000000
Target Path=obj/CH32V20x_IAP.hex
Erase All=true
Program=true
Verify=true
Reset=true
Vendor=WCH
Link=WCH-Link
Toolchain=RISC-V
Series=CH32V203
Description=ROM(byte): 64K, SRAM(byte): 20K, CHIP PINS: 32, GPIO PORTS: 27.\nWCH CH32V2 series of mainstream MCUs covers the needs of a large variety of applications in the industrial,medical and consumer markets. High performance with first-class peripherals and low-power,low-voltage operation is paired with a high level of integration at accessible prices with a simple architecture and easy-to-use tools.
PeripheralVersion=1.0
MCU=CH32V203RBT6
@@ -0,0 +1,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,157 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : hw_config.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : USB 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.
*******************************************************************************/
#include "usb_lib.h"
#include "usb_prop.h"
#include "usb_desc.h"
#include "usb_istr.h"
#include "hw_config.h"
#include "usb_pwr.h"
#include "string.h"
#include "stdarg.h"
#include "stdio.h"
void USBWakeUp_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USB_LP_CAN1_RX0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
/*******************************************************************************
* @fn USBWakeUp_IRQHandler
*
* @brief This function handles USB wake up exception.
*
* @return None
*/
void USBWakeUp_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line18);
}
/*******************************************************************************
* @fn USBWakeUp_IRQHandler
*
* @brief T his function handles USB exception.
*
* @return None
*/
void USB_LP_CAN1_RX0_IRQHandler(void)
{
USB_Istr();
}
/*******************************************************************************
* @fn Set_USBConfig
*
* @brief Set_USBConfig .
*
* @return None
*/
void Set_USBConfig( )
{
RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
}
/*******************************************************************************
* @fn Enter_LowPowerMode
*
* @brief Enter low power mode.
*
* @return None
*/
void Enter_LowPowerMode(void)
{
bDeviceState=SUSPENDED;
}
/*******************************************************************************
* @fn Leave_LowPowerMode
*
* @brief Leave low power mode.
*
* @return None
*/
void Leave_LowPowerMode(void)
{
DEVICE_INFO *pInfo=&Device_Info;
if (pInfo->Current_Configuration!=0)bDeviceState=CONFIGURED;
else bDeviceState = ATTACHED;
}
/*******************************************************************************
* @fn USB_Interrupts_Config
*
* @brief Configrate USB interrupt.
*
* @return None
*/
void USB_Interrupts_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_ClearITPendingBit(EXTI_Line18);
EXTI_InitStructure.EXTI_Line = EXTI_Line18;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_Init(&NVIC_InitStructure);
}
/*******************************************************************************
* @fn USB_Port_Set
*
* @brief Set USB IO port.
*
* @param NewState: DISABLE or ENABLE.
* Pin_In_IPU: Enables or Disables intenal pull-up resistance.
*
* @return None
*/
void USB_Port_Set(FunctionalState NewState, FunctionalState Pin_In_IPU)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
if(NewState) {
_SetCNTR(_GetCNTR()&(~(1<<1)));
GPIOA->CFGHR&=0XFFF00FFF;
GPIOA->OUTDR&=~(3<<11); //PA11/12=0
GPIOA->CFGHR|=0X00044000; //float
}
else
{
_SetCNTR(_GetCNTR()|(1<<1));
GPIOA->CFGHR&=0XFFF00FFF;
GPIOA->OUTDR&=~(3<<11); //PA11/12=0
GPIOA->CFGHR|=0X00033000; // LOW
}
if(Pin_In_IPU) (EXTEN->EXTEN_CTR) |= EXTEN_USBD_PU_EN;
else (EXTEN->EXTEN_CTR) &= ~EXTEN_USBD_PU_EN;
}
@@ -0,0 +1,38 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : hw_config.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Configuration file for USB.
*********************************************************************************
* 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 __HW_CONFIG_H
#define __HW_CONFIG_H
#include "usb_type.h"
#ifdef DEBUG
#define printf_usb(X...) printf(X)
#else
#define printf_usb(X...)
#endif
void Set_USBConfig(void);
void Enter_LowPowerMode(void);
void Leave_LowPowerMode(void);
void USB_Interrupts_Config(void);
void USB_Port_Set(FunctionalState NewState, FunctionalState Pin_In_IPU);
#endif /* __HW_CONFIG_H */
@@ -0,0 +1,77 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_conf.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : This file contains all the functions prototypes for the
* USB configration firmware library.
*********************************************************************************
* 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_CONF_H
#define __USB_CONF_H
#define EP_NUM (5)
/* Buffer Description Table */
/* buffer table base address */
/* buffer table base address */
#define BTABLE_ADDRESS (0x00)
/* EP0 */
/* rx/tx buffer base address */
#define ENDP0_RXADDR (0x40)
#define ENDP0_TXADDR (0x80)
/* EP1 */
/* tx buffer base address */
#define ENDP1_TXADDR (0xC0)
#define ENDP1_RXADDR (ENDP1_TXADDR + 0x10)
#define ENDP2_TXADDR (ENDP1_RXADDR + 0x10)
#define ENDP2_RXADDR (ENDP2_TXADDR + 0x10)
/* ISTR events */
/* IMR_MSK */
/* mask defining which events has to be handled */
/* by the device application software */
#define IMR_MSK (CNTR_CTRM | CNTR_WKUPM | CNTR_SUSPM | CNTR_ERRM | CNTR_SOFM \
| CNTR_ESOFM | CNTR_RESETM )
/*#define CTR_CALLBACK*/
/*#define DOVR_CALLBACK*/
/*#define ERR_CALLBACK*/
/*#define WKUP_CALLBACK*/
/*#define SUSP_CALLBACK*/
/*#define RESET_CALLBACK*/
#define SOF_CALLBACK
/*#define ESOF_CALLBACK*/
/* CTR service routines */
/* associated to defined endpoints */
#define EP1_IN_Callback NOP_Process
//#define EP2_IN_Callback NOP_Process
#define EP3_IN_Callback NOP_Process
#define EP4_IN_Callback NOP_Process
#define EP5_IN_Callback NOP_Process
#define EP6_IN_Callback NOP_Process
#define EP7_IN_Callback NOP_Process
#define EP1_OUT_Callback NOP_Process
//#define EP2_OUT_Callback NOP_Process
#define EP3_OUT_Callback NOP_Process
#define EP4_OUT_Callback NOP_Process
#define EP5_OUT_Callback NOP_Process
#define EP6_OUT_Callback NOP_Process
#define EP7_OUT_Callback NOP_Process
#endif /* __USB_CONF_H */
@@ -0,0 +1,68 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_desc.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Descriptors for Virtual Com Port Demo.
*********************************************************************************
* 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 "usb_lib.h"
#include "usb_desc.h"
#include "iap.h"
#define DevEP0SIZE 0x40
/* USB Device Descriptors */
const uint8_t USBD_DeviceDescriptor[] = {
0x12, 0x01, 0x10, 0x01,
0xFF, 0x80, 0x55, DevEP0SIZE,
0x48, 0x43, 0xe0, 0x55, //USB MODULE
(u8)Version_Num, (u8)(Version_Num>>8),
0x00, 0x00,0x00, 0x01
};
/* USB Configration Descriptors */
const uint8_t USBD_ConfigDescriptor[] = {
0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32,
0x09, 0x04, 0x00, 0x00, 0x02, 0xFF, 0x80, 0x55, 0x00,
0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00,
0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00
};
/* USB String Descriptors */
const uint8_t USBD_StringLangID[USBD_SIZE_STRING_LANGID] = {
USBD_SIZE_STRING_LANGID,
USB_STRING_DESCRIPTOR_TYPE,
0x09,
0x04
};
/* USB Device String Vendor */
const uint8_t USBD_StringVendor[USBD_SIZE_STRING_VENDOR] = {
USBD_SIZE_STRING_VENDOR,
USB_STRING_DESCRIPTOR_TYPE,
'W', 0, 'C', 0, 'H', 0, 'I', 0, 'C', 0, 'r', 0, 'o', 0, 'e', 0,
'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0,
'c', 0, 's', 0
};
/* USB Device String Product */
const uint8_t USBD_StringProduct[USBD_SIZE_STRING_PRODUCT] = {
USBD_SIZE_STRING_PRODUCT,
USB_STRING_DESCRIPTOR_TYPE,
'W', 0, 'C', 0, 'H', 0, '3', 0, '2', 0, ' ', 0, 'V', 0, 'i', 0,
'r', 0, 't', 0, 'u', 0, 'a', 0, 'l', 0, ' ', 0, 'C', 0, 'O', 0,
'M', 0, ' ', 0, 'P', 0, 'o', 0, 'r', 0, 't', 0, ' ', 0, ' ', 0
};
/* USB Device String Serial */
uint8_t USBD_StringSerial[USBD_SIZE_STRING_SERIAL] = {
USBD_SIZE_STRING_SERIAL,
USB_STRING_DESCRIPTOR_TYPE,
'W', 0, 'C', 0, 'H', 0, '3', 0, '2', 0
};
@@ -0,0 +1,54 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_desc.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : This file contains all the functions prototypes for the
* USB description firmware library.
*********************************************************************************
* 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_DESC_H
#define __USB_DESC_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v20x.h"
#define Version_Num 0x0100 //V0100
#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02
#define USB_STRING_DESCRIPTOR_TYPE 0x03
#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05
#define USBD_DATA_SIZE 64
#define USBD_INT_SIZE 8
#define USBD_SIZE_DEVICE_DESC 18
#define USBD_SIZE_CONFIG_DESC 0x20
#define USBD_SIZE_STRING_LANGID 4
#define USBD_SIZE_STRING_VENDOR 38
#define USBD_SIZE_STRING_PRODUCT 50
#define USBD_SIZE_STRING_SERIAL 26
#define STANDARD_ENDPOINT_DESC_SIZE 0x09
extern const uint8_t USBD_DeviceDescriptor[USBD_SIZE_DEVICE_DESC];
extern const uint8_t USBD_ConfigDescriptor[USBD_SIZE_CONFIG_DESC];
extern const uint8_t USBD_StringLangID [USBD_SIZE_STRING_LANGID];
extern const uint8_t USBD_StringVendor [USBD_SIZE_STRING_VENDOR];
extern const uint8_t USBD_StringProduct[USBD_SIZE_STRING_PRODUCT];
extern uint8_t USBD_StringSerial [USBD_SIZE_STRING_SERIAL];
#ifdef __cplusplus
}
#endif
#endif /* __USB_DESC_H */
@@ -0,0 +1,79 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_endp.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Endpoint 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 "usb_lib.h"
#include "usb_desc.h"
#include "usb_mem.h"
#include "hw_config.h"
#include "usb_istr.h"
#include "usb_pwr.h"
/* Interval between sending IN packets in frame number (1 frame = 1ms) */
#define IN_FRAME_INTERVAL 5
u8 EP2_Rx_Buffer[USBD_DATA_SIZE];
u16 EP2_Rx_Cnt=0;
u8 EP2_Tx_Buffer[2];
u16 EP2_Tx_Cnt=0;
u8 EP2_IN_Flag = 0;
u8 EP2_OUT_Flag = 0;
/*********************************************************************
* @fn EP2_IN_Callback
*
* @brief Endpoint 2 IN.
*
* @return none
*/
void EP2_IN_Callback (void)
{
EP2_IN_Flag = 0;
SetEPTxStatus(ENDP2, EP_TX_NAK);
}
/*********************************************************************
* @fn EP2_OUT_Callback
*
* @brief Endpoint 2 OUT.
*
* @return none
*/
void EP2_OUT_Callback(void)
{
EP2_OUT_Flag = 1;
}
/*********************************************************************
* @fn SOF_Callback
*
* @brief SOF call back.
*
* @return none
*/
void SOF_Callback(void)
{
static uint32_t FrameCount = 0;
if(bDeviceState == CONFIGURED)
{
if (FrameCount++ == IN_FRAME_INTERVAL)
{
FrameCount = 0;
//Handle_USBAsynchXfer();
}
}
}
@@ -0,0 +1,196 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_istr.c
* Author : WCH
* Version : V1.0.1
* Date : 2022/12/28
* Description : ISTR events 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 "usb_lib.h"
#include "usb_prop.h"
#include "usb_pwr.h"
#include "usb_istr.h"
uint16_t Ep0RxBlks;
/* Private variables */
__IO uint16_t wIstr;
__IO uint8_t bIntPackSOF = 0;
__IO uint32_t esof_counter =0;
__IO uint32_t wCNTR=0;
/* function pointers to non-control endpoints service routines */
void (*pEpInt_IN[7])(void) ={
EP1_IN_Callback,
EP2_IN_Callback,
EP3_IN_Callback,
EP4_IN_Callback,
EP5_IN_Callback,
EP6_IN_Callback,
EP7_IN_Callback,
};
void (*pEpInt_OUT[7])(void) ={
EP1_OUT_Callback,
EP2_OUT_Callback,
EP3_OUT_Callback,
EP4_OUT_Callback,
EP5_OUT_Callback,
EP6_OUT_Callback,
EP7_OUT_Callback,
};
/*******************************************************************************
* @fn USB_Istr
*
* @brief ISTR events interrupt service routine
*
* @return None.
*/
void USB_Istr(void)
{
uint32_t i=0;
__IO uint32_t EP[8];
if ((*_pEPRxCount(0) & 0xFC00 )!= Ep0RxBlks)
{
*_pEPRxCount(0) |= (Ep0RxBlks & 0xFC00);
}
wIstr = _GetISTR();
#if (IMR_MSK & ISTR_SOF)
if (wIstr & ISTR_SOF & wInterrupt_Mask)
{
_SetISTR((uint16_t)CLR_SOF);
bIntPackSOF++;
#ifdef SOF_CALLBACK
SOF_Callback();
#endif
}
#endif
#if (IMR_MSK & ISTR_CTR)
if (wIstr & ISTR_CTR & wInterrupt_Mask)
{
CTR_LP();
#ifdef CTR_CALLBACK
CTR_Callback();
#endif
}
#endif
#if (IMR_MSK & ISTR_RESET)
if (wIstr & ISTR_RESET & wInterrupt_Mask)
{
_SetISTR((uint16_t)CLR_RESET);
Device_Property.Reset();
#ifdef RESET_CALLBACK
RESET_Callback();
#endif
}
#endif
#if (IMR_MSK & ISTR_DOVR)
if (wIstr & ISTR_DOVR & wInterrupt_Mask)
{
_SetISTR((uint16_t)CLR_DOVR);
#ifdef DOVR_CALLBACK
DOVR_Callback();
#endif
}
#endif
#if (IMR_MSK & ISTR_ERR)
if (wIstr & ISTR_ERR & wInterrupt_Mask)
{
_SetISTR((uint16_t)CLR_ERR);
#ifdef ERR_CALLBACK
ERR_Callback();
#endif
}
#endif
#if (IMR_MSK & ISTR_WKUP)
if (wIstr & ISTR_WKUP & wInterrupt_Mask)
{
_SetISTR((uint16_t)CLR_WKUP);
Resume(RESUME_EXTERNAL);
#ifdef WKUP_CALLBACK
WKUP_Callback();
#endif
}
#endif
#if (IMR_MSK & ISTR_SUSP)
if (wIstr & ISTR_SUSP & wInterrupt_Mask)
{
if (fSuspendEnabled)
{
Suspend();
}
else
{
Resume(RESUME_LATER);
}
_SetISTR((uint16_t)CLR_SUSP);
#ifdef SUSP_CALLBACK
SUSP_Callback();
#endif
}
#endif
#if (IMR_MSK & ISTR_ESOF)
if (wIstr & ISTR_ESOF & wInterrupt_Mask)
{
_SetISTR((uint16_t)CLR_ESOF);
if ((_GetFNR()&FNR_RXDP)!=0)
{
esof_counter ++;
if ((esof_counter >3)&&((_GetCNTR()&CNTR_FSUSP)==0))
{
wCNTR = _GetCNTR();
for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i);
wCNTR|=CNTR_FRES;
_SetCNTR(wCNTR);
wCNTR&=~CNTR_FRES;
_SetCNTR(wCNTR);
while((_GetISTR()&ISTR_RESET) == 0);
_SetISTR((uint16_t)CLR_RESET);
for (i=0;i<8;i++)
_SetENDPOINT(i, EP[i]);
esof_counter = 0;
}
}
else
{
esof_counter = 0;
}
Resume(RESUME_ESOF);
#ifdef ESOF_CALLBACK
ESOF_Callback();
#endif
}
#endif
} /* USB_Istr */
@@ -0,0 +1,77 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_istr.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : This file includes the peripherals header files in the
* user application.
*********************************************************************************
* 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_ISTR_H
#define __USB_ISTR_H
#include "usb_conf.h"
void USB_Istr(void);
void EP1_IN_Callback(void);
void EP2_IN_Callback(void);
void EP3_IN_Callback(void);
void EP4_IN_Callback(void);
void EP5_IN_Callback(void);
void EP6_IN_Callback(void);
void EP7_IN_Callback(void);
void EP1_OUT_Callback(void);
void EP2_OUT_Callback(void);
void EP3_OUT_Callback(void);
void EP4_OUT_Callback(void);
void EP5_OUT_Callback(void);
void EP6_OUT_Callback(void);
void EP7_OUT_Callback(void);
#ifdef CTR_CALLBACK
void CTR_Callback(void);
#endif
#ifdef DOVR_CALLBACK
void DOVR_Callback(void);
#endif
#ifdef ERR_CALLBACK
void ERR_Callback(void);
#endif
#ifdef WKUP_CALLBACK
void WKUP_Callback(void);
#endif
#ifdef SUSP_CALLBACK
void SUSP_Callback(void);
#endif
#ifdef RESET_CALLBACK
void RESET_Callback(void);
#endif
#ifdef SOF_CALLBACK
void SOF_Callback(void);
#endif
#ifdef ESOF_CALLBACK
void ESOF_Callback(void);
#endif
#endif /*__USB_ISTR_H*/
@@ -0,0 +1,315 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_prop.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : All processing related to Virtual Com Port Demo
*********************************************************************************
* 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 "usb_lib.h"
#include "usb_conf.h"
#include "usb_prop.h"
#include "usb_desc.h"
#include "usb_pwr.h"
#include "hw_config.h"
uint8_t Request = 0;
DEVICE Device_Table =
{
EP_NUM,
1
};
DEVICE_PROP Device_Property =
{
USBD_init,
USBD_Reset,
USBD_Status_In,
USBD_Status_Out,
USBD_Data_Setup,
USBD_NoData_Setup,
USBD_Get_Interface_Setting,
USBD_GetDeviceDescriptor,
USBD_GetConfigDescriptor,
USBD_GetStringDescriptor,
0,
0x40
};
USER_STANDARD_REQUESTS User_Standard_Requests =
{
USBD_GetConfiguration,
USBD_SetConfiguration,
USBD_GetInterface,
USBD_SetInterface,
USBD_GetStatus,
USBD_ClearFeature,
USBD_SetEndPointFeature,
USBD_SetDeviceFeature,
USBD_SetDeviceAddress
};
ONE_DESCRIPTOR Device_Descriptor =
{
(uint8_t*)USBD_DeviceDescriptor,
USBD_SIZE_DEVICE_DESC
};
ONE_DESCRIPTOR Config_Descriptor =
{
(uint8_t*)USBD_ConfigDescriptor,
USBD_SIZE_CONFIG_DESC
};
ONE_DESCRIPTOR String_Descriptor[4] =
{
{(uint8_t*)USBD_StringLangID, USBD_SIZE_STRING_LANGID},
{(uint8_t*)USBD_StringVendor, USBD_SIZE_STRING_VENDOR},
{(uint8_t*)USBD_StringProduct,USBD_SIZE_STRING_PRODUCT},
{(uint8_t*)USBD_StringSerial, USBD_SIZE_STRING_SERIAL}
};
/*********************************************************************
* @fn USBD_SetConfiguration.
*
* @brief Update the device state to configured.
*
* @return none
*/
void USBD_SetConfiguration(void)
{
DEVICE_INFO *pInfo = &Device_Info;
if (pInfo->Current_Configuration != 0)
{
bDeviceState = CONFIGURED;
}
}
/*********************************************************************
* @fn USBD_SetDeviceAddress.
*
* @brief Update the device state to addressed.
*
* @return none
*/
void USBD_SetDeviceAddress (void)
{
bDeviceState = ADDRESSED;
}
/*********************************************************************
* @fn USBD_Status_In.
*
* @brief USBD Status In Routine.
*
* @return none.
*/
void USBD_Status_In(void)
{
}
/*********************************************************************
* @fn USBD_Status_Out
*
* @brief USBD Status OUT Routine.
*
* @return none.
*/
void USBD_Status_Out(void)
{
}
/*********************************************************************
* @fn USB_init.
*
* @brief init routine.
*
* @return none.
*/
void USBD_init(void)
{
uint8_t i;
pInformation->Current_Configuration = 0;
PowerOn();
for (i=0;i<8;i++) _SetENDPOINT(i,_GetENDPOINT(i) & 0x7F7F & EPREG_MASK);//all clear
_SetISTR((uint16_t)0x00FF);//all clear
USB_SIL_Init();
bDeviceState = UNCONNECTED;
}
/*********************************************************************
* @fn USBD_Reset
*
* @brief Virtual_Com_Port Mouse reset routine
*
* @return none.
*/
void USBD_Reset(void)
{
pInformation->Current_Configuration = 0;
pInformation->Current_Feature = USBD_ConfigDescriptor[7];
pInformation->Current_Interface = 0;
SetBTABLE(BTABLE_ADDRESS);
//EP0
SetEPType(ENDP0, EP_CONTROL);
SetEPTxStatus(ENDP0, EP_TX_STALL);
SetEPRxAddr(ENDP0, ENDP0_RXADDR);
SetEPTxAddr(ENDP0, ENDP0_TXADDR);
Clear_Status_Out(ENDP0);
SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
SetEPRxValid(ENDP0);
_ClearDTOG_RX(ENDP0);
_ClearDTOG_TX(ENDP0);
//EP2
SetEPType(ENDP2, EP_BULK);
SetEPTxAddr(ENDP2, ENDP2_TXADDR);
SetEPRxAddr(ENDP2, ENDP2_RXADDR);
SetEPRxCount(ENDP2, USBD_DATA_SIZE);
SetEPRxStatus(ENDP2, EP_RX_VALID);
SetEPTxStatus(ENDP2, EP_TX_NAK);
_ClearDTOG_RX(ENDP2);
_ClearDTOG_TX(ENDP2);
SetDeviceAddress(0);
bDeviceState = ATTACHED;
}
/*********************************************************************
* @fn USBD_GetDeviceDescriptor.
*
* @brief Gets the device descriptor.
*
* @param Length.
*
* @return The address of the device descriptor.
*/
uint8_t *USBD_GetDeviceDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &Device_Descriptor);
}
/*********************************************************************
* @fn USBD_GetConfigDescriptor.
*
* @brief get the configuration descriptor.
*
* @param Length.
*
* @return The address of the configuration descriptor.
*/
uint8_t *USBD_GetConfigDescriptor(uint16_t Length)
{
return Standard_GetDescriptorData(Length, &Config_Descriptor);
}
/*********************************************************************
* @fn USBD_GetStringDescriptor
*
* @brief Gets the string descriptors according to the needed index
*
* @param Length.
*
* @return The address of the string descriptors.
*/
uint8_t *USBD_GetStringDescriptor(uint16_t Length)
{
uint8_t wValue0 = pInformation->USBwValue0;
if (wValue0 > 4)
{
return NULL;
}
else
{
return Standard_GetDescriptorData(Length, &String_Descriptor[wValue0]);
}
}
/*********************************************************************
* @fn USBD_Get_Interface_Setting.
*
* @brief test the interface and the alternate setting according to the
* supported one.
* @param Interface - interface number.
* AlternateSetting - Alternate Setting number.
*
* @return none
*/
RESULT USBD_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting)
{
if (AlternateSetting > 0)
{
return USB_UNSUPPORT;
}
else if (Interface > 1)
{
return USB_UNSUPPORT;
}
return USB_SUCCESS;
}
/*********************************************************************
* @fn USBD_Data_Setup
*
* @brief handle the data class specific requests
*
* @return USB_UNSUPPORT or USB_SUCCESS.
*/
RESULT USBD_Data_Setup(uint8_t RequestNo)
{
return USB_SUCCESS;
}
/*********************************************************************
* @fn USBD_NoData_Setup.
*
* @brief handle the no data class specific requests.
*
* @return USB_UNSUPPORT or USB_SUCCESS.
*/
RESULT USBD_NoData_Setup(uint8_t RequestNo)
{
return USB_SUCCESS;
}
/*********************************************************************
* @fn Virtual_Com_Port_GetLineCoding.
*
* @brief send the linecoding structure to the PC host.
*
* @return Linecoding structure base address.
*/
uint8_t *Virtual_Com_Port_GetLineCoding(uint16_t Length)
{
return 0;
}
/*********************************************************************
* @fn Virtual_Com_Port_SetLineCoding.
*
* @brief Set the linecoding structure fields.
*
* @return Linecoding structure base address.
*/
uint8_t *Virtual_Com_Port_SetLineCoding(uint16_t Length)
{
return 0;
}
@@ -0,0 +1,61 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_prop.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : All processing related to Virtual COM Port Demo (Endpoint 0)
*********************************************************************************
* 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_prop_H
#define __usb_prop_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v20x.h"
#define USBD_GetConfiguration NOP_Process
//#define USBD_SetConfiguration NOP_Process
#define USBD_GetInterface NOP_Process
#define USBD_SetInterface NOP_Process
#define USBD_GetStatus NOP_Process
#define USBD_ClearFeature NOP_Process
#define USBD_SetEndPointFeature NOP_Process
#define USBD_SetDeviceFeature NOP_Process
//#define USBD_SetDeviceAddress NOP_Process
#define SEND_ENCAPSULATED_COMMAND 0x00
#define GET_ENCAPSULATED_RESPONSE 0x01
#define SET_COMM_FEATURE 0x02
#define GET_COMM_FEATURE 0x03
#define CLEAR_COMM_FEATURE 0x04
#define SET_LINE_CODING 0x20
#define GET_LINE_CODING 0x21
#define SET_CONTROL_LINE_STATE 0x22
#define SEND_BREAK 0x23
void USBD_init(void);
void USBD_Reset(void);
void USBD_SetConfiguration(void);
void USBD_SetDeviceAddress(void);
void USBD_Status_In(void);
void USBD_Status_Out(void);
RESULT USBD_Data_Setup(uint8_t);
RESULT USBD_NoData_Setup(uint8_t);
RESULT USBD_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting);
uint8_t *USBD_GetDeviceDescriptor(uint16_t);
uint8_t *USBD_GetConfigDescriptor(uint16_t);
uint8_t *USBD_GetStringDescriptor(uint16_t);
uint8_t *USBD_GetLineCoding(uint16_t Length);
uint8_t *USBD_SetLineCoding(uint16_t Length);
#ifdef __cplusplus
}
#endif
#endif /* __usb_prop_H */
@@ -0,0 +1,215 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_pwr.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Connection/disconnection & power management
*********************************************************************************
* 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 "usb_lib.h"
#include "usb_conf.h"
#include "usb_pwr.h"
#include "hw_config.h"
__IO uint32_t bDeviceState = UNCONNECTED;
__IO bool fSuspendEnabled = TRUE;
__IO uint32_t EP[8];
struct
{
__IO RESUME_STATE eState;
__IO uint8_t bESOFcnt;
}
ResumeS;
__IO uint32_t remotewakeupon=0;
/*******************************************************************************
* @fn PowerOn
*
* @brief Enable power on.
*
* @return USB_SUCCESS.
*/
RESULT PowerOn(void)
{
uint16_t wRegVal;
wRegVal = CNTR_FRES;
_SetCNTR(wRegVal);
wInterrupt_Mask = 0;
_SetCNTR(wInterrupt_Mask);
_SetISTR(0);
wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM;
_SetCNTR(wInterrupt_Mask);
return USB_SUCCESS;
}
/*******************************************************************************
* @fn PowerOff
*
* @brief handles switch-off conditions
*
* @return USB_SUCCESS.
*/
RESULT PowerOff()
{
_SetCNTR(CNTR_FRES);
_SetISTR(0);
_SetCNTR(CNTR_FRES + CNTR_PDWN);
return USB_SUCCESS;
}
/*******************************************************************************
* @fn Suspend
*
* @brief sets suspend mode operating conditions
*
* @return USB_SUCCESS.
*/
void Suspend(void)
{
uint32_t i =0;
uint16_t wCNTR;
wCNTR = _GetCNTR();
for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i);
wCNTR|=CNTR_RESETM;
_SetCNTR(wCNTR);
wCNTR|=CNTR_FRES;
_SetCNTR(wCNTR);
wCNTR&=~CNTR_FRES;
_SetCNTR(wCNTR);
while((_GetISTR()&ISTR_RESET) == 0);
_SetISTR((uint16_t)CLR_RESET);
for (i=0;i<8;i++)
_SetENDPOINT(i, EP[i]);
wCNTR |= CNTR_FSUSP;
_SetCNTR(wCNTR);
wCNTR = _GetCNTR();
wCNTR |= CNTR_LPMODE;
_SetCNTR(wCNTR);
Enter_LowPowerMode();
}
/*******************************************************************************
* @fn Resume_Init
*
* @brief Handles wake-up restoring normal operations
*
* @return USB_SUCCESS.
*/
void Resume_Init(void)
{
uint16_t wCNTR;
wCNTR = _GetCNTR();
wCNTR &= (~CNTR_LPMODE);
_SetCNTR(wCNTR);
Leave_LowPowerMode();
_SetCNTR(IMR_MSK);
}
/*******************************************************************************
* @fn Resume
*
* @brief This is the state machine handling resume operations and
* timing sequence. The control is based on the Resume structure
* variables and on the ESOF interrupt calling this subroutine
* without changing machine state.
*
* @param a state machine value (RESUME_STATE)
* RESUME_ESOF doesn't change ResumeS.eState allowing
* decrementing of the ESOF counter in different states.
*
* @return None.
*/
void Resume(RESUME_STATE eResumeSetVal)
{
uint16_t wCNTR;
if (eResumeSetVal != RESUME_ESOF)
{
ResumeS.eState = eResumeSetVal;
}
switch (ResumeS.eState)
{
case RESUME_EXTERNAL:
if (remotewakeupon ==0)
{
Resume_Init();
ResumeS.eState = RESUME_OFF;
}
else
{
ResumeS.eState = RESUME_ON;
}
break;
case RESUME_INTERNAL:
Resume_Init();
ResumeS.eState = RESUME_START;
remotewakeupon = 1;
break;
case RESUME_LATER:
ResumeS.bESOFcnt = 2;
ResumeS.eState = RESUME_WAIT;
break;
case RESUME_WAIT:
ResumeS.bESOFcnt--;
if (ResumeS.bESOFcnt == 0)
ResumeS.eState = RESUME_START;
break;
case RESUME_START:
wCNTR = _GetCNTR();
wCNTR |= CNTR_RESUME;
_SetCNTR(wCNTR);
ResumeS.eState = RESUME_ON;
ResumeS.bESOFcnt = 10;
break;
case RESUME_ON:
ResumeS.bESOFcnt--;
if (ResumeS.bESOFcnt == 0)
{
wCNTR = _GetCNTR();
wCNTR &= (~CNTR_RESUME);
_SetCNTR(wCNTR);
ResumeS.eState = RESUME_OFF;
remotewakeupon = 0;
}
break;
case RESUME_OFF:
case RESUME_ESOF:
default:
ResumeS.eState = RESUME_OFF;
break;
}
}
@@ -0,0 +1,62 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_pwr.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Connection/disconnection & power management header
*********************************************************************************
* 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_PWR_H
#define __USB_PWR_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v20x.h"
typedef enum _RESUME_STATE
{
RESUME_EXTERNAL,
RESUME_INTERNAL,
RESUME_LATER,
RESUME_WAIT,
RESUME_START,
RESUME_ON,
RESUME_OFF,
RESUME_ESOF
} RESUME_STATE;
typedef enum _DEVICE_STATE
{
UNCONNECTED,
ATTACHED,
POWERED,
SUSPENDED,
ADDRESSED,
CONFIGURED
} DEVICE_STATE;
void Suspend(void);
void Resume_Init(void);
void Resume(RESUME_STATE eResumeSetVal);
RESULT PowerOn(void);
RESULT PowerOff(void);
extern __IO uint32_t bDeviceState; /* USB device status */
extern __IO bool fSuspendEnabled; /* true when suspend is possible */
#ifdef __cplusplus
}
#endif
#endif /*__USB_PWR_H*/
@@ -0,0 +1,191 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_core.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : This file contains all the functions prototypes for the
* USB cor firmware library.
*********************************************************************************
* 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_CORE_H
#define __USB_CORE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v20x.h"
typedef enum _CONTROL_STATE
{
WAIT_SETUP, /* 0 */
SETTING_UP, /* 1 */
IN_DATA, /* 2 */
OUT_DATA, /* 3 */
LAST_IN_DATA, /* 4 */
LAST_OUT_DATA, /* 5 */
WAIT_STATUS_IN, /* 7 */
WAIT_STATUS_OUT, /* 8 */
STALLED, /* 9 */
PAUSE /* 10 */
} CONTROL_STATE; /* The state machine states of a control pipe */
typedef struct OneDescriptor
{
uint8_t *Descriptor;
uint16_t Descriptor_Size;
}
ONE_DESCRIPTOR, *PONE_DESCRIPTOR;
typedef enum _RESULT
{
USB_SUCCESS = 0, /* Process successfully */
USB_ERROR,
USB_UNSUPPORT,
USB_NOT_READY /* The process has not been finished, endpoint will be
NAK to further request */
} RESULT;
/* Definitions for endpoint level */
typedef struct _ENDPOINT_INFO
{
uint16_t Usb_wLength;
uint16_t Usb_wOffset;
uint16_t PacketSize;
uint8_t *(*CopyData)(uint16_t Length);
}ENDPOINT_INFO;
/* Definitions for device level */
typedef struct _DEVICE
{
uint8_t Total_Endpoint; /* Number of endpoints that are used */
uint8_t Total_Configuration;/* Number of configuration available */
}
DEVICE;
typedef union
{
uint16_t w;
struct BW
{
uint8_t bb1;
uint8_t bb0;
}
bw;
} uint16_t_uint8_t;
typedef struct _DEVICE_INFO
{
uint8_t USBbmRequestType; /* bmRequestType */
uint8_t USBbRequest; /* bRequest */
uint16_t_uint8_t USBwValues; /* wValue */
uint16_t_uint8_t USBwIndexs; /* wIndex */
uint16_t_uint8_t USBwLengths; /* wLength */
uint8_t ControlState; /* of type CONTROL_STATE */
uint8_t Current_Feature;
uint8_t Current_Configuration; /* Selected configuration */
uint8_t Current_Interface; /* Selected interface of current configuration */
uint8_t Current_AlternateSetting;/* Selected Alternate Setting of current
interface*/
ENDPOINT_INFO Ctrl_Info;
}DEVICE_INFO;
typedef struct _DEVICE_PROP
{
void (*Init)(void); /* Initialize the device */
void (*Reset)(void); /* Reset routine of this device */
void (*Process_Status_IN)(void);
void (*Process_Status_OUT)(void);
RESULT (*Class_Data_Setup)(uint8_t RequestNo);
RESULT (*Class_NoData_Setup)(uint8_t RequestNo);
RESULT (*Class_Get_Interface_Setting)(uint8_t Interface, uint8_t AlternateSetting);
uint8_t* (*GetDeviceDescriptor)(uint16_t Length);
uint8_t* (*GetConfigDescriptor)(uint16_t Length);
uint8_t* (*GetStringDescriptor)(uint16_t Length);
void* RxEP_buffer;
uint8_t MaxPacketSize;
}DEVICE_PROP;
typedef struct _USER_STANDARD_REQUESTS
{
void (*User_GetConfiguration)(void); /* Get Configuration */
void (*User_SetConfiguration)(void); /* Set Configuration */
void (*User_GetInterface)(void); /* Get Interface */
void (*User_SetInterface)(void); /* Set Interface */
void (*User_GetStatus)(void); /* Get Status */
void (*User_ClearFeature)(void); /* Clear Feature */
void (*User_SetEndPointFeature)(void); /* Set Endpoint Feature */
void (*User_SetDeviceFeature)(void); /* Set Device Feature */
void (*User_SetDeviceAddress)(void); /* Set Device Address */
}
USER_STANDARD_REQUESTS;
#define Type_Recipient (pInformation->USBbmRequestType & (REQUEST_TYPE | RECIPIENT))
#define Usb_rLength Usb_wLength
#define Usb_rOffset Usb_wOffset
#define USBwValue USBwValues.w
#define USBwValue0 USBwValues.bw.bb0
#define USBwValue1 USBwValues.bw.bb1
#define USBwIndex USBwIndexs.w
#define USBwIndex0 USBwIndexs.bw.bb0
#define USBwIndex1 USBwIndexs.bw.bb1
#define USBwLength USBwLengths.w
#define USBwLength0 USBwLengths.bw.bb0
#define USBwLength1 USBwLengths.bw.bb1
uint8_t Setup0_Process(void);
uint8_t Post0_Process(void);
uint8_t Out0_Process(void);
uint8_t In0_Process(void);
RESULT Standard_SetEndPointFeature(void);
RESULT Standard_SetDeviceFeature(void);
uint8_t *Standard_GetConfiguration(uint16_t Length);
RESULT Standard_SetConfiguration(void);
uint8_t *Standard_GetInterface(uint16_t Length);
RESULT Standard_SetInterface(void);
uint8_t *Standard_GetDescriptorData(uint16_t Length, PONE_DESCRIPTOR pDesc);
uint8_t *Standard_GetStatus(uint16_t Length);
RESULT Standard_ClearFeature(void);
void SetDeviceAddress(uint8_t);
void NOP_Process(void);
extern DEVICE_PROP Device_Property;
extern USER_STANDARD_REQUESTS User_Standard_Requests;
extern DEVICE Device_Table;
extern DEVICE_INFO Device_Info;
/* cells saving status during interrupt servicing */
extern __IO uint16_t SaveRState;
extern __IO uint16_t SaveTState;
#ifdef __cplusplus
}
#endif
#endif /* __USB_CORE_H */
@@ -0,0 +1,82 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_def.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : This file contains all the functions prototypes for the
* USB definition firmware library.
*********************************************************************************
* 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_DEF_H
#define __USB_DEF_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v20x.h"
typedef enum _RECIPIENT_TYPE
{
DEVICE_RECIPIENT,
INTERFACE_RECIPIENT,
ENDPOINT_RECIPIENT,
OTHER_RECIPIENT
} RECIPIENT_TYPE;
typedef enum _STANDARD_REQUESTS
{
GET_STATUS = 0,
CLEAR_FEATURE,
RESERVED1,
SET_FEATURE,
RESERVED2,
SET_ADDRESS,
GET_DESCRIPTOR,
SET_DESCRIPTOR,
GET_CONFIGURATION,
SET_CONFIGURATION,
GET_INTERFACE,
SET_INTERFACE,
TOTAL_sREQUEST,
SYNCH_FRAME = 12
} STANDARD_REQUESTS;
/* Definition of "USBwValue" */
typedef enum _DESCRIPTOR_TYPE
{
DEVICE_DESCRIPTOR = 1,
CONFIG_DESCRIPTOR,
STRING_DESCRIPTOR,
INTERFACE_DESCRIPTOR,
ENDPOINT_DESCRIPTOR
} DESCRIPTOR_TYPE;
/* Feature selector of a SET_FEATURE or CLEAR_FEATURE */
typedef enum _FEATURE_SELECTOR
{
ENDPOINT_STALL,
DEVICE_REMOTE_WAKEUP
} FEATURE_SELECTOR;
/* Definition of "USBbmRequestType" */
#define REQUEST_TYPE 0x60
#define STANDARD_REQUEST 0x00
#define CLASS_REQUEST 0x20
#define VENDOR_REQUEST 0x40
#define RECIPIENT 0x1F
#ifdef __cplusplus
}
#endif
#endif /* __USB_DEF_H */
@@ -0,0 +1,42 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_init.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : This file contains all the functions prototypes for the
* USB Initialization firmware library.
*********************************************************************************
* 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_INIT_H
#define __USB_INIT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v20x.h"
void USB_Init(void);
extern uint8_t EPindex;
extern DEVICE_INFO* pInformation;
extern DEVICE_PROP* pProperty;
extern USER_STANDARD_REQUESTS *pUser_Standard_Requests;
extern uint16_t SaveState ;
extern uint16_t wInterrupt_Mask;
#ifdef __cplusplus
}
#endif
#endif /* __USB_INIT_H */
@@ -0,0 +1,25 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_int.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : This file contains all the functions prototypes for the
* USB Endpoint firmware library.
*********************************************************************************
* 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_INT_H
#define __USB_INT_H
void CTR_LP(void);
void CTR_HP(void);
#endif /* __USB_INT_H */
@@ -0,0 +1,30 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_lib.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Library configuration file for USB.
*********************************************************************************
* 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_LIB_H
#define __USB_LIB_H
#include "hw_config.h"
#include "usb_type.h"
#include "usb_regs.h"
#include "usb_def.h"
#include "usb_core.h"
#include "usb_init.h"
#include "usb_sil.h"
#include "usb_mem.h"
#include "usb_int.h"
//#include "ch32f20x_usb.h"
#endif /* __USB_LIB_H */
@@ -0,0 +1,36 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_mem.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : This file contains all the functions prototypes for the
* USB Initialization firmware library.
*********************************************************************************
* 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_MEM_H
#define __USB_MEM_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v20x.h"
void UserToPMABufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes);
#ifdef __cplusplus
}
#endif
#endif /*__USB_MEM_H*/
@@ -0,0 +1,675 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_regs.h
* Author : WCH
* Version : V1.0.1
* Date : 2022/12/28
* Description : This file contains all the functions prototypes for the
* USB cell registers firmware library.
*********************************************************************************
* 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_REGS_H
#define __USB_REGS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v20x.h"
typedef enum _EP_DBUF_DIR
{
EP_DBUF_ERR,
EP_DBUF_OUT,
EP_DBUF_IN
}EP_DBUF_DIR;
/* endpoint buffer number */
enum EP_BUF_NUM
{
EP_NOBUF,
EP_BUF0,
EP_BUF1
};
extern uint16_t Ep0RxBlks;
#define RegBase (0x40005C00L)
#define PMAAddr (0x40006000L)
/******************************************************************************/
/* General registers */
/******************************************************************************/
/* Control register */
#define CNTLR ((__IO unsigned *)(RegBase + 0x40))
/* Interrupt status register */
#define ISTR ((__IO unsigned *)(RegBase + 0x44))
/* Frame number register */
#define FNR ((__IO unsigned *)(RegBase + 0x48))
/* Device address register */
#define DADDR ((__IO unsigned *)(RegBase + 0x4C))
/* Buffer Table address register */
#define BTABLE ((__IO unsigned *)(RegBase + 0x50))
/******************************************************************************/
/* Endpoint registers */
/******************************************************************************/
#define EP0REG ((__IO unsigned *)(RegBase)) /* endpoint 0 register address */
/* Endpoint Addresses (w/direction) */
#define EP0_OUT ((uint8_t)0x00)
#define EP0_IN ((uint8_t)0x80)
#define EP1_OUT ((uint8_t)0x01)
#define EP1_IN ((uint8_t)0x81)
#define EP2_OUT ((uint8_t)0x02)
#define EP2_IN ((uint8_t)0x82)
#define EP3_OUT ((uint8_t)0x03)
#define EP3_IN ((uint8_t)0x83)
#define EP4_OUT ((uint8_t)0x04)
#define EP4_IN ((uint8_t)0x84)
#define EP5_OUT ((uint8_t)0x05)
#define EP5_IN ((uint8_t)0x85)
#define EP6_OUT ((uint8_t)0x06)
#define EP6_IN ((uint8_t)0x86)
#define EP7_OUT ((uint8_t)0x07)
#define EP7_IN ((uint8_t)0x87)
/* endpoints enumeration */
#define ENDP0 ((uint8_t)0)
#define ENDP1 ((uint8_t)1)
#define ENDP2 ((uint8_t)2)
#define ENDP3 ((uint8_t)3)
#define ENDP4 ((uint8_t)4)
#define ENDP5 ((uint8_t)5)
#define ENDP6 ((uint8_t)6)
#define ENDP7 ((uint8_t)7)
/******************************************************************************/
/* ISTR interrupt events */
/******************************************************************************/
#define ISTR_CTR (0x8000) /* Correct TRansfer (clear-only bit) */
#define ISTR_DOVR (0x4000) /* DMA OVeR/underrun (clear-only bit) */
#define ISTR_ERR (0x2000) /* ERRor (clear-only bit) */
#define ISTR_WKUP (0x1000) /* WaKe UP (clear-only bit) */
#define ISTR_SUSP (0x0800) /* SUSPend (clear-only bit) */
#define ISTR_RESET (0x0400) /* RESET (clear-only bit) */
#define ISTR_SOF (0x0200) /* Start Of Frame (clear-only bit) */
#define ISTR_ESOF (0x0100) /* Expected Start Of Frame (clear-only bit) */
#define ISTR_DIR (0x0010) /* DIRection of transaction (read-only bit) */
#define ISTR_EP_ID (0x000F) /* EndPoint IDentifier (read-only bit) */
#define CLR_CTR (~ISTR_CTR) /* clear Correct TRansfer bit */
#define CLR_DOVR (~ISTR_DOVR) /* clear DMA OVeR/underrun bit*/
#define CLR_ERR (~ISTR_ERR) /* clear ERRor bit */
#define CLR_WKUP (~ISTR_WKUP) /* clear WaKe UP bit */
#define CLR_SUSP (~ISTR_SUSP) /* clear SUSPend bit */
#define CLR_RESET (~ISTR_RESET) /* clear RESET bit */
#define CLR_SOF (~ISTR_SOF) /* clear Start Of Frame bit */
#define CLR_ESOF (~ISTR_ESOF) /* clear Expected Start Of Frame bit */
/******************************************************************************/
/* CNTR control register bits definitions */
/******************************************************************************/
#define CNTR_CTRM (0x8000) /* Correct TRansfer Mask */
#define CNTR_DOVRM (0x4000) /* DMA OVeR/underrun Mask */
#define CNTR_ERRM (0x2000) /* ERRor Mask */
#define CNTR_WKUPM (0x1000) /* WaKe UP Mask */
#define CNTR_SUSPM (0x0800) /* SUSPend Mask */
#define CNTR_RESETM (0x0400) /* RESET Mask */
#define CNTR_SOFM (0x0200) /* Start Of Frame Mask */
#define CNTR_ESOFM (0x0100) /* Expected Start Of Frame Mask */
#define CNTR_RESUME (0x0010) /* RESUME request */
#define CNTR_FSUSP (0x0008) /* Force SUSPend */
#define CNTR_LPMODE (0x0004) /* Low-power MODE */
#define CNTR_PDWN (0x0002) /* Power DoWN */
#define CNTR_FRES (0x0001) /* Force USB RESet */
/******************************************************************************/
/* FNR Frame Number Register bit definitions */
/******************************************************************************/
#define FNR_RXDP (0x8000) /* status of D+ data line */
#define FNR_RXDM (0x4000) /* status of D- data line */
#define FNR_LCK (0x2000) /* LoCKed */
#define FNR_LSOF (0x1800) /* Lost SOF */
#define FNR_FN (0x07FF) /* Frame Number */
/******************************************************************************/
/* DADDR Device ADDRess bit definitions */
/******************************************************************************/
#define DADDR_EF (0x80)
#define DADDR_ADD (0x7F)
/******************************************************************************/
/* Endpoint register */
/******************************************************************************/
/* bit positions */
#define EP_CTR_RX (0x8000) /* EndPoint Correct TRansfer RX */
#define EP_DTOG_RX (0x4000) /* EndPoint Data TOGGLE RX */
#define EPRX_STAT (0x3000) /* EndPoint RX STATus bit field */
#define EP_SETUP (0x0800) /* EndPoint SETUP */
#define EP_T_FIELD (0x0600) /* EndPoint TYPE */
#define EP_KIND (0x0100) /* EndPoint KIND */
#define EP_CTR_TX (0x0080) /* EndPoint Correct TRansfer TX */
#define EP_DTOG_TX (0x0040) /* EndPoint Data TOGGLE TX */
#define EPTX_STAT (0x0030) /* EndPoint TX STATus bit field */
#define EPADDR_FIELD (0x000F) /* EndPoint ADDRess FIELD */
/* EndPoint REGister MASK (no toggle fields) */
#define EPREG_MASK (EP_CTR_RX|EP_SETUP|EP_T_FIELD|EP_KIND|EP_CTR_TX|EPADDR_FIELD)
/* EP_TYPE[1:0] EndPoint TYPE */
#define EP_TYPE_MASK (0x0600) /* EndPoint TYPE Mask */
#define EP_BULK (0x0000) /* EndPoint BULK */
#define EP_CONTROL (0x0200) /* EndPoint CONTROL */
#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */
#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */
#define EP_T_MASK (~EP_T_FIELD & EPREG_MASK)
/* EP_KIND EndPoint KIND */
#define EPKIND_MASK (~EP_KIND & EPREG_MASK)
/* STAT_TX[1:0] STATus for TX transfer */
#define EP_TX_DIS (0x0000) /* EndPoint TX DISabled */
#define EP_TX_STALL (0x0010) /* EndPoint TX STALLed */
#define EP_TX_NAK (0x0020) /* EndPoint TX NAKed */
#define EP_TX_VALID (0x0030) /* EndPoint TX VALID */
#define EPTX_DTOG1 (0x0010) /* EndPoint TX Data TOGgle bit1 */
#define EPTX_DTOG2 (0x0020) /* EndPoint TX Data TOGgle bit2 */
#define EPTX_DTOGMASK (EPTX_STAT|EPREG_MASK)
/* STAT_RX[1:0] STATus for RX transfer */
#define EP_RX_DIS (0x0000) /* EndPoint RX DISabled */
#define EP_RX_STALL (0x1000) /* EndPoint RX STALLed */
#define EP_RX_NAK (0x2000) /* EndPoint RX NAKed */
#define EP_RX_VALID (0x3000) /* EndPoint RX VALID */
#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */
#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */
#define EPRX_DTOGMASK (EPRX_STAT|EPREG_MASK)
/* SetCNTR */
#define _SetCNTR(wRegValue) (*CNTLR = (uint16_t)wRegValue)
/* SetISTR */
#define _SetISTR(wRegValue) (*ISTR = (uint16_t)wRegValue)
/* SetDADDR */
#define _SetDADDR(wRegValue) (*DADDR = (uint16_t)wRegValue)
/* SetBTABLE */
#define _SetBTABLE(wRegValue)(*BTABLE = (uint16_t)(wRegValue & 0xFFF8))
/* GetCNTR */
#define _GetCNTR() ((uint16_t) *CNTLR)
/* GetISTR */
#define _GetISTR() ((uint16_t) *ISTR)
/* GetFNR */
#define _GetFNR() ((uint16_t) *FNR)
/* GetDADDR */
#define _GetDADDR() ((uint16_t) *DADDR)
/* GetBTABLE */
#define _GetBTABLE() ((uint16_t) *BTABLE)
/* SetENDPOINT */
#define _SetENDPOINT(bEpNum,wRegValue) (*(EP0REG + bEpNum)= \
(uint16_t)wRegValue)
/* GetENDPOINT */
#define _GetENDPOINT(bEpNum) ((uint16_t)(*(EP0REG + bEpNum)))
#define _SetEPType(bEpNum,wType) (_SetENDPOINT(bEpNum,\
((_GetENDPOINT(bEpNum) & EP_T_MASK) | wType )))
#define _GetEPType(bEpNum) (_GetENDPOINT(bEpNum) & EP_T_FIELD)
/*******************************************************************************
* Macro Name : SetEPTxStatus
* Description : sets the status for tx transfer (bits STAT_TX[1:0]).
* Input : bEpNum: Endpoint Number.
* wState: new state
* Return : None.
*******************************************************************************/
#define _SetEPTxStatus(bEpNum,wState) {\
register uint16_t _wRegVal; \
_wRegVal = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK;\
/* toggle first bit ? */ \
if((EPTX_DTOG1 & wState)!= 0) \
_wRegVal ^= EPTX_DTOG1; \
/* toggle second bit ? */ \
if((EPTX_DTOG2 & wState)!= 0) \
_wRegVal ^= EPTX_DTOG2; \
_SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \
while( ( _GetENDPOINT(bEpNum) & EPTX_STAT ) != wState ) \
{ \
_SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \
}; \
} /* _SetEPTxStatus */
/*******************************************************************************
* Macro Name : SetEPRxStatus
* Description : sets the status for rx transfer (bits STAT_TX[1:0])
* Input : bEpNum: Endpoint Number.
* wState: new state.
* Return : None.
*******************************************************************************/
#define _SetEPRxStatus(bEpNum,wState) {\
register uint16_t _wRegVal; \
\
_wRegVal = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK;\
/* toggle first bit ? */ \
if((EPRX_DTOG1 & wState)!= 0) \
_wRegVal ^= EPRX_DTOG1; \
/* toggle second bit ? */ \
if((EPRX_DTOG2 & wState)!= 0) \
_wRegVal ^= EPRX_DTOG2; \
_SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \
while( ( _GetENDPOINT(bEpNum) & EPRX_STAT ) != wState ) \
{ \
_SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \
} \
} /* _SetEPRxStatus */
/*******************************************************************************
* Macro Name : SetEPRxTxStatus
* Description : sets the status for rx & tx (bits STAT_TX[1:0] & STAT_RX[1:0])
* Input : bEpNum: Endpoint Number.
* wStaterx: new state.
* wStatetx: new state.
* Output : None.
* Return : None.
*******************************************************************************/
#define _SetEPRxTxStatus(bEpNum,wStaterx,wStatetx) {\
register uint32_t _wRegVal_T, _wRegVal_R; \
\
_wRegVal_T = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK; \
_wRegVal_R = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK; \
/* toggle first bit ? */ \
if((EPRX_DTOG1 & wStaterx)!= 0) \
_wRegVal_R ^= EPRX_DTOG1; \
/* toggle second bit ? */ \
if((EPRX_DTOG2 & wStaterx)!= 0) \
_wRegVal_R ^= EPRX_DTOG2; \
/* toggle first bit ? */ \
if((EPTX_DTOG1 & wStatetx)!= 0) \
_wRegVal_T ^= EPTX_DTOG1; \
/* toggle second bit ? */ \
if((EPTX_DTOG2 & wStatetx)!= 0) \
_wRegVal_T ^= EPTX_DTOG2; \
_SetENDPOINT(bEpNum, _wRegVal_T |_wRegVal_R | EP_CTR_RX | EP_CTR_TX); \
while( ( _GetENDPOINT(bEpNum) & EPTX_STAT ) != wStatetx ) \
{ \
_SetENDPOINT(bEpNum, _wRegVal_T | EP_CTR_RX | EP_CTR_TX); \
} \
while( ( _GetENDPOINT(bEpNum) & EPRX_STAT ) != wStaterx ) \
{ \
_SetENDPOINT(bEpNum, _wRegVal_R | EP_CTR_RX | EP_CTR_TX); \
} \
} /* _SetEPRxTxStatus */
/*******************************************************************************
* Macro Name : GetEPTxStatus / GetEPRxStatus
* Description : gets the status for tx/rx transfer (bits STAT_TX[1:0]
* /STAT_RX[1:0])
* Input : bEpNum: Endpoint Number.
* Return : status .
*******************************************************************************/
#define _GetEPTxStatus(bEpNum) ((uint16_t)_GetENDPOINT(bEpNum) & EPTX_STAT)
#define _GetEPRxStatus(bEpNum) ((uint16_t)_GetENDPOINT(bEpNum) & EPRX_STAT)
/*******************************************************************************
* Macro Name : SetEPTxValid / SetEPRxValid
* Description : sets directly the VALID tx/rx-status into the enpoint register
* Input : bEpNum: Endpoint Number.
* Return : None.
*******************************************************************************/
#define _SetEPTxValid(bEpNum) (_SetEPTxStatus(bEpNum, EP_TX_VALID))
#define _SetEPRxValid(bEpNum) (_SetEPRxStatus(bEpNum, EP_RX_VALID))
/*******************************************************************************
* Macro Name : GetTxStallStatus / GetRxStallStatus.
* Description : checks stall condition in an endpoint.
* Input : bEpNum: Endpoint Number.
* Return : TRUE = endpoint in stall condition.
*******************************************************************************/
#define _GetTxStallStatus(bEpNum) (_GetEPTxStatus(bEpNum) \
== EP_TX_STALL)
#define _GetRxStallStatus(bEpNum) (_GetEPRxStatus(bEpNum) \
== EP_RX_STALL)
/*******************************************************************************
* Macro Name : SetEP_KIND / ClearEP_KIND.
* Description : set & clear EP_KIND bit.
* Input : bEpNum: Endpoint Number.
* Return : None.
*******************************************************************************/
#define _SetEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \
(EP_CTR_RX|EP_CTR_TX|((_GetENDPOINT(bEpNum) | EP_KIND) & EPREG_MASK))))
#define _ClearEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \
(EP_CTR_RX|EP_CTR_TX|(_GetENDPOINT(bEpNum) & EPKIND_MASK))))
/*******************************************************************************
* Macro Name : Set_Status_Out / Clear_Status_Out.
* Description : Sets/clears directly STATUS_OUT bit in the endpoint register.
* Input : bEpNum: Endpoint Number.
* Return : None.
*******************************************************************************/
#define _Set_Status_Out(bEpNum) _SetEP_KIND(bEpNum)
#define _Clear_Status_Out(bEpNum) _ClearEP_KIND(bEpNum)
/*******************************************************************************
* Macro Name : SetEPDoubleBuff / ClearEPDoubleBuff.
* Description : Sets/clears directly EP_KIND bit in the endpoint register.
* Input : bEpNum: Endpoint Number.
* Return : None.
*******************************************************************************/
#define _SetEPDoubleBuff(bEpNum) _SetEP_KIND(bEpNum)
#define _ClearEPDoubleBuff(bEpNum) _ClearEP_KIND(bEpNum)
/*******************************************************************************
* Macro Name : ClearEP_CTR_RX / ClearEP_CTR_TX.
* Description : Clears bit CTR_RX / CTR_TX in the endpoint register.
* Input : bEpNum: Endpoint Number.
* Return : None.
*******************************************************************************/
#define _ClearEP_CTR_RX(bEpNum) (_SetENDPOINT(bEpNum,\
_GetENDPOINT(bEpNum) & 0x7FFF & EPREG_MASK))
#define _ClearEP_CTR_TX(bEpNum) (_SetENDPOINT(bEpNum,\
_GetENDPOINT(bEpNum) & 0xFF7F & EPREG_MASK))
/*******************************************************************************
* Macro Name : ToggleDTOG_RX / ToggleDTOG_TX .
* Description : Toggles DTOG_RX / DTOG_TX bit in the endpoint register.
* Input : bEpNum: Endpoint Number.
* Return : None.
*******************************************************************************/
#define _ToggleDTOG_RX(bEpNum) (_SetENDPOINT(bEpNum, \
EP_CTR_RX|EP_CTR_TX|EP_DTOG_RX | (_GetENDPOINT(bEpNum) & EPREG_MASK)))
#define _ToggleDTOG_TX(bEpNum) (_SetENDPOINT(bEpNum, \
EP_CTR_RX|EP_CTR_TX|EP_DTOG_TX | (_GetENDPOINT(bEpNum) & EPREG_MASK)))
/*******************************************************************************
* Macro Name : ClearDTOG_RX / ClearDTOG_TX.
* Description : Clears DTOG_RX / DTOG_TX bit in the endpoint register.
* Input : bEpNum: Endpoint Number.
* Return : None.
*******************************************************************************/
#define _ClearDTOG_RX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_RX) != 0)\
_ToggleDTOG_RX(bEpNum)
#define _ClearDTOG_TX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_TX) != 0)\
_ToggleDTOG_TX(bEpNum)
/*******************************************************************************
* Macro Name : SetEPAddress.
* Description : Sets address in an endpoint register.
* Input : bEpNum: Endpoint Number.
* bAddr: Address.
* Return : None.
*******************************************************************************/
#define _SetEPAddress(bEpNum,bAddr) _SetENDPOINT(bEpNum,\
EP_CTR_RX|EP_CTR_TX|(_GetENDPOINT(bEpNum) & EPREG_MASK) | bAddr)
/*******************************************************************************
* Macro Name : GetEPAddress.
* Description : Gets address in an endpoint register.
* Input : bEpNum: Endpoint Number.
* Return : None.
*******************************************************************************/
#define _GetEPAddress(bEpNum) ((uint8_t)(_GetENDPOINT(bEpNum) & EPADDR_FIELD))
#define _pEPTxAddr(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8 )*2 + PMAAddr))
#define _pEPTxCount(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+2)*2 + PMAAddr))
#define _pEPRxAddr(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+4)*2 + PMAAddr))
#define _pEPRxCount(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+6)*2 + PMAAddr))
/*******************************************************************************
* Macro Name : SetEPTxAddr / SetEPRxAddr.
* Description : sets address of the tx/rx buffer.
* Input : bEpNum: Endpoint Number.
* wAddr: address to be set (must be word aligned).
* Return : None.
*******************************************************************************/
#define _SetEPTxAddr(bEpNum,wAddr) (*_pEPTxAddr(bEpNum) = ((wAddr >> 1) << 1))
#define _SetEPRxAddr(bEpNum,wAddr) (*_pEPRxAddr(bEpNum) = ((wAddr >> 1) << 1))
/*******************************************************************************
* Macro Name : GetEPTxAddr / GetEPRxAddr.
* Description : Gets address of the tx/rx buffer.
* Input : bEpNum: Endpoint Number.
* Return : address of the buffer.
*******************************************************************************/
#define _GetEPTxAddr(bEpNum) ((uint16_t)*_pEPTxAddr(bEpNum))
#define _GetEPRxAddr(bEpNum) ((uint16_t)*_pEPRxAddr(bEpNum))
/*******************************************************************************
* Macro Name : SetEPCountRxReg.
* Description : Sets counter of rx buffer with no. of blocks.
* Input : pdwReg: pointer to counter.
* wCount: Counter.
* Return : None.
*******************************************************************************/
#define _BlocksOf32(dwReg,wCount,wNBlocks) {\
wNBlocks = wCount >> 5;\
if((wCount & 0x1f) == 0)\
wNBlocks--;\
*pdwReg = (uint32_t)((wNBlocks << 10) | 0x8000);\
}/* _BlocksOf32 */
#define _BlocksOf2(dwReg,wCount,wNBlocks) {\
wNBlocks = wCount >> 1;\
if((wCount & 0x1) != 0)\
wNBlocks++;\
*pdwReg = (uint32_t)(wNBlocks << 10);\
}/* _BlocksOf2 */
#define _SetEPCountRxReg(dwReg,wCount) {\
uint16_t wNBlocks;\
if(wCount > 62){_BlocksOf32(dwReg,wCount,wNBlocks);}\
else {_BlocksOf2(dwReg,wCount,wNBlocks);}\
}/* _SetEPCountRxReg */
#define _GetNumBlock(wCount,wValue) {\
uint16_t wNBlocks;\
if(wCount > 62){\
wNBlocks = wCount >> 5;\
if((wCount & 0x1f) == 0) wNBlocks--;\
wValue = (uint32_t)((wNBlocks << 10) | 0x8000);\
}\
else {wNBlocks = wCount >> 1;\
if((wCount & 0x1) != 0) wNBlocks++;\
wValue = (uint32_t)(wNBlocks << 10);\
}\
}
#define _SetEPRxDblBuf0Count(bEpNum,wCount) {\
uint32_t *pdwReg = _pEPTxCount(bEpNum); \
_SetEPCountRxReg(pdwReg, wCount);\
}
/*******************************************************************************
* Macro Name : SetEPTxCount / SetEPRxCount.
* Description : sets counter for the tx/rx buffer.
* Input : bEpNum: endpoint number.
* wCount: Counter value.
* Return : None.
*******************************************************************************/
#define _SetEPTxCount(bEpNum,wCount) (*_pEPTxCount(bEpNum) = wCount)
#define _SetEPRxCount(bEpNum,wCount) {\
uint32_t *pdwReg = _pEPRxCount(bEpNum); \
_SetEPCountRxReg(pdwReg, wCount);\
if (bEpNum == ENDP0) \
_GetNumBlock(Device_Property.MaxPacketSize,Ep0RxBlks);\
}
/*******************************************************************************
* Macro Name : GetEPTxCount / GetEPRxCount.
* Description : gets counter of the tx buffer.
* Input : bEpNum: endpoint number.
* Return : Counter value.
*******************************************************************************/
#define _GetEPTxCount(bEpNum)((uint16_t)(*_pEPTxCount(bEpNum)) & 0x3ff)
#define _GetEPRxCount(bEpNum)((uint16_t)(*_pEPRxCount(bEpNum)) & 0x3ff)
/*******************************************************************************
* Macro Name : SetEPDblBuf0Addr / SetEPDblBuf1Addr.
* Description : Sets buffer 0/1 address in a double buffer endpoint.
* Input : bEpNum: endpoint number.
* : wBuf0Addr: buffer 0 address.
* Output : None.
* Return : None.
*******************************************************************************/
#define _SetEPDblBuf0Addr(bEpNum,wBuf0Addr) {_SetEPTxAddr(bEpNum, wBuf0Addr);}
#define _SetEPDblBuf1Addr(bEpNum,wBuf1Addr) {_SetEPRxAddr(bEpNum, wBuf1Addr);}
/*******************************************************************************
* Macro Name : SetEPDblBuffAddr.
* Description : Sets addresses in a double buffer endpoint.
* Input : bEpNum: endpoint number.
* : wBuf0Addr: buffer 0 address.
* : wBuf1Addr = buffer 1 address.
* Return : None.
*******************************************************************************/
#define _SetEPDblBuffAddr(bEpNum,wBuf0Addr,wBuf1Addr) { \
_SetEPDblBuf0Addr(bEpNum, wBuf0Addr);\
_SetEPDblBuf1Addr(bEpNum, wBuf1Addr);\
} /* _SetEPDblBuffAddr */
/*******************************************************************************
* Macro Name : GetEPDblBuf0Addr / GetEPDblBuf1Addr.
* Description : Gets buffer 0/1 address of a double buffer endpoint.
* Input : bEpNum: endpoint number.
* Return : None.
*******************************************************************************/
#define _GetEPDblBuf0Addr(bEpNum) (_GetEPTxAddr(bEpNum))
#define _GetEPDblBuf1Addr(bEpNum) (_GetEPRxAddr(bEpNum))
/*******************************************************************************
* Macro Name : SetEPDblBuffCount / SetEPDblBuf0Count / SetEPDblBuf1Count.
* Description : Gets buffer 0/1 address of a double buffer endpoint.
* Input : bEpNum: endpoint number.
* : bDir: endpoint dir EP_DBUF_OUT = OUT
* EP_DBUF_IN = IN
* : wCount: Counter value
* Return : None.
*******************************************************************************/
#define _SetEPDblBuf0Count(bEpNum, bDir, wCount) { \
if(bDir == EP_DBUF_OUT)\
/* OUT endpoint */ \
{_SetEPRxDblBuf0Count(bEpNum,wCount);} \
else if(bDir == EP_DBUF_IN)\
/* IN endpoint */ \
*_pEPTxCount(bEpNum) = (uint32_t)wCount; \
} /* SetEPDblBuf0Count*/
#define _SetEPDblBuf1Count(bEpNum, bDir, wCount) { \
if(bDir == EP_DBUF_OUT)\
/* OUT endpoint */ \
{_SetEPRxCount(bEpNum,wCount);}\
else if(bDir == EP_DBUF_IN)\
/* IN endpoint */\
*_pEPRxCount(bEpNum) = (uint32_t)wCount; \
} /* SetEPDblBuf1Count */
#define _SetEPDblBuffCount(bEpNum, bDir, wCount) {\
_SetEPDblBuf0Count(bEpNum, bDir, wCount); \
_SetEPDblBuf1Count(bEpNum, bDir, wCount); \
} /* _SetEPDblBuffCount */
/*******************************************************************************
* Macro Name : GetEPDblBuf0Count / GetEPDblBuf1Count.
* Description : Gets buffer 0/1 rx/tx counter for double buffering.
* Input : bEpNum: endpoint number.
* Return : None.
*******************************************************************************/
#define _GetEPDblBuf0Count(bEpNum) (_GetEPTxCount(bEpNum))
#define _GetEPDblBuf1Count(bEpNum) (_GetEPRxCount(bEpNum))
extern __IO uint16_t wIstr; /* ISTR register last read value */
void SetCNTR(uint16_t /*wRegValue*/);
void SetISTR(uint16_t /*wRegValue*/);
void SetDADDR(uint16_t /*wRegValue*/);
void SetBTABLE(uint16_t /*wRegValue*/);
void SetBTABLE(uint16_t /*wRegValue*/);
uint16_t GetCNTR(void);
uint16_t GetISTR(void);
uint16_t GetFNR(void);
uint16_t GetDADDR(void);
uint16_t GetBTABLE(void);
void SetENDPOINT(uint8_t /*bEpNum*/, uint16_t /*wRegValue*/);
uint16_t GetENDPOINT(uint8_t /*bEpNum*/);
void SetEPType(uint8_t /*bEpNum*/, uint16_t /*wType*/);
uint16_t GetEPType(uint8_t /*bEpNum*/);
void SetEPTxStatus(uint8_t /*bEpNum*/, uint16_t /*wState*/);
void SetEPRxStatus(uint8_t /*bEpNum*/, uint16_t /*wState*/);
void SetDouBleBuffEPStall(uint8_t /*bEpNum*/, uint8_t bDir);
uint16_t GetEPTxStatus(uint8_t /*bEpNum*/);
uint16_t GetEPRxStatus(uint8_t /*bEpNum*/);
void SetEPTxValid(uint8_t /*bEpNum*/);
void SetEPRxValid(uint8_t /*bEpNum*/);
uint16_t GetTxStallStatus(uint8_t /*bEpNum*/);
uint16_t GetRxStallStatus(uint8_t /*bEpNum*/);
void SetEP_KIND(uint8_t /*bEpNum*/);
void ClearEP_KIND(uint8_t /*bEpNum*/);
void Set_Status_Out(uint8_t /*bEpNum*/);
void Clear_Status_Out(uint8_t /*bEpNum*/);
void SetEPDoubleBuff(uint8_t /*bEpNum*/);
void ClearEPDoubleBuff(uint8_t /*bEpNum*/);
void ClearEP_CTR_RX(uint8_t /*bEpNum*/);
void ClearEP_CTR_TX(uint8_t /*bEpNum*/);
void ToggleDTOG_RX(uint8_t /*bEpNum*/);
void ToggleDTOG_TX(uint8_t /*bEpNum*/);
void ClearDTOG_RX(uint8_t /*bEpNum*/);
void ClearDTOG_TX(uint8_t /*bEpNum*/);
void SetEPAddress(uint8_t /*bEpNum*/, uint8_t /*bAddr*/);
uint8_t GetEPAddress(uint8_t /*bEpNum*/);
void SetEPTxAddr(uint8_t /*bEpNum*/, uint16_t /*wAddr*/);
void SetEPRxAddr(uint8_t /*bEpNum*/, uint16_t /*wAddr*/);
uint16_t GetEPTxAddr(uint8_t /*bEpNum*/);
uint16_t GetEPRxAddr(uint8_t /*bEpNum*/);
void SetEPCountRxReg(uint32_t * /*pdwReg*/, uint16_t /*wCount*/);
void SetEPTxCount(uint8_t /*bEpNum*/, uint16_t /*wCount*/);
void SetEPRxCount(uint8_t /*bEpNum*/, uint16_t /*wCount*/);
uint16_t GetEPTxCount(uint8_t /*bEpNum*/);
uint16_t GetEPRxCount(uint8_t /*bEpNum*/);
void SetEPDblBuf0Addr(uint8_t /*bEpNum*/, uint16_t /*wBuf0Addr*/);
void SetEPDblBuf1Addr(uint8_t /*bEpNum*/, uint16_t /*wBuf1Addr*/);
void SetEPDblBuffAddr(uint8_t /*bEpNum*/, uint16_t /*wBuf0Addr*/, uint16_t /*wBuf1Addr*/);
uint16_t GetEPDblBuf0Addr(uint8_t /*bEpNum*/);
uint16_t GetEPDblBuf1Addr(uint8_t /*bEpNum*/);
void SetEPDblBuffCount(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/);
void SetEPDblBuf0Count(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/);
void SetEPDblBuf1Count(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/);
uint16_t GetEPDblBuf0Count(uint8_t /*bEpNum*/);
uint16_t GetEPDblBuf1Count(uint8_t /*bEpNum*/);
EP_DBUF_DIR GetEPDblBufDir(uint8_t /*bEpNum*/);
void FreeUserBuffer(uint8_t bEpNum/*bEpNum*/, uint8_t bDir);
uint16_t ToWord(uint8_t, uint8_t);
uint16_t ByteSwap(uint16_t);
#ifdef __cplusplus
}
#endif
#endif /* __USB_REGS_H */
@@ -0,0 +1,36 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_sil.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : This file contains all the functions prototypes for the
* USB Simplified Interface Layer firmware library.
*********************************************************************************
* 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_SIL_H
#define __USB_SIL_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v20x.h"
uint32_t USB_SIL_Init(void);
uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize);
uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer);
#ifdef __cplusplus
}
#endif
#endif /* __USB_SIL_H */
@@ -0,0 +1,33 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_type.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : This file contains all the functions prototypes for the
* USB types firmware library.
*********************************************************************************
* 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_TYPE_H
#define __USB_TYPE_H
#include "debug.h"
#include "usb_conf.h"
#ifndef NULL
#define NULL ((void *)0)
#endif
typedef enum
{
FALSE = 0, TRUE = !FALSE
}
bool;
#endif /* __USB_TYPE_H */
@@ -0,0 +1,954 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_core.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Standard protocol processing (USB v2.0)
*********************************************************************************
* 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 "usb_lib.h"
/* Global define */
#define ValBit(VAR,Place) (VAR & (1 << Place))
#define SetBit(VAR,Place) (VAR |= (1 << Place))
#define ClrBit(VAR,Place) (VAR &= ((1 << Place) ^ 255))
#define Send0LengthData() { _SetEPTxCount(ENDP0, 0); \
vSetEPTxStatus(EP_TX_VALID); \
}
#define vSetEPRxStatus(st) (SaveRState = st)
#define vSetEPTxStatus(st) (SaveTState = st)
#define USB_StatusIn() Send0LengthData()
#define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID)
#define StatusInfo0 StatusInfo.bw.bb1
#define StatusInfo1 StatusInfo.bw.bb0
uint16_t_uint8_t StatusInfo;
bool Data_Mul_MaxPacketSize = FALSE;
static void DataStageOut(void);
static void DataStageIn(void);
static void NoData_Setup0(void);
static void Data_Setup0(void);
/*********************************************************************
* @fn Standard_GetConfiguration
*
* @brief Return the current configuration variable address.
*
* @param Length - How many bytes are needed.
*
* @return Return 1 - if the request is invalid when "Length" is 0.
* Return "Buffer" if the "Length" is not 0.
*/
uint8_t *Standard_GetConfiguration(uint16_t Length)
{
if (Length == 0)
{
pInformation->Ctrl_Info.Usb_wLength = sizeof(pInformation->Current_Configuration);
return 0;
}
pUser_Standard_Requests->User_GetConfiguration();
return (uint8_t *)&pInformation->Current_Configuration;
}
/*********************************************************************
* @fn Standard_SetConfiguration
*
* @brief This routine is called to set the configuration value
* Then each class should configure device itself.
*
* @param None.
*
* @return Return USB_SUCCESS - if the request is performed.
* Return USB_UNSUPPORT - if the request is invalid.
*/
RESULT Standard_SetConfiguration(void)
{
if ((pInformation->USBwValue0 <=
Device_Table.Total_Configuration) && (pInformation->USBwValue1 == 0)
&& (pInformation->USBwIndex == 0))
{
pInformation->Current_Configuration = pInformation->USBwValue0;
pUser_Standard_Requests->User_SetConfiguration();
return USB_SUCCESS;
}
else
{
return USB_UNSUPPORT;
}
}
/*********************************************************************
* @fn Standard_GetInterface
*
* @brief Return the Alternate Setting of the current interface.
*
* @param Length - How many bytes are needed.
*
* @return Return 0 - if the request is invalid when "Length" is 0.
* Return "Buffer" if the "Length" is not 0.
*/
uint8_t *Standard_GetInterface(uint16_t Length)
{
if (Length == 0)
{
pInformation->Ctrl_Info.Usb_wLength = sizeof(pInformation->Current_AlternateSetting);
return 0;
}
pUser_Standard_Requests->User_GetInterface();
return (uint8_t *)&pInformation->Current_AlternateSetting;
}
/*********************************************************************
* @fn Standard_SetInterface
*
* @brief This routine is called to set the interface.
* Then each class should configure the interface them self.
*
* @param None
*
* @return Return USB_SUCCESS - if the request is performed.
* Return USB_UNSUPPORT - if the request is invalid.
*/
RESULT Standard_SetInterface(void)
{
RESULT Re;
Re = (*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, pInformation->USBwValue0);
if (pInformation->Current_Configuration != 0)
{
if ((Re != USB_SUCCESS) || (pInformation->USBwIndex1 != 0)
|| (pInformation->USBwValue1 != 0))
{
return USB_UNSUPPORT;
}
else if (Re == USB_SUCCESS)
{
pUser_Standard_Requests->User_SetInterface();
pInformation->Current_Interface = pInformation->USBwIndex0;
pInformation->Current_AlternateSetting = pInformation->USBwValue0;
return USB_SUCCESS;
}
}
return USB_UNSUPPORT;
}
/*********************************************************************
* @fn Standard_GetStatus
*
* @brief Copy the device request data to "StatusInfo buffer".
*
* @param Length - How many bytes are needed.
*
* @return Return 0 - if the request is at end of data block,
* or is invalid when "Length" is 0.
*/
uint8_t *Standard_GetStatus(uint16_t Length)
{
if (Length == 0)
{
pInformation->Ctrl_Info.Usb_wLength = 2;
return 0;
}
StatusInfo.w = 0;
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
{
uint8_t Feature = pInformation->Current_Feature;
if (ValBit(Feature, 5))
{
SetBit(StatusInfo0, 1);
}
else
{
ClrBit(StatusInfo0, 1);
}
if (ValBit(Feature, 6))
{
SetBit(StatusInfo0, 0);
}
else
{
ClrBit(StatusInfo0, 0);
}
}
else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
{
return (uint8_t *)&StatusInfo;
}
else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
{
uint8_t Related_Endpoint;
uint8_t wIndex0 = pInformation->USBwIndex0;
Related_Endpoint = (wIndex0 & 0x0f);
if (ValBit(wIndex0, 7))
{
if (_GetTxStallStatus(Related_Endpoint))
{
SetBit(StatusInfo0, 0);
}
}
else
{
if (_GetRxStallStatus(Related_Endpoint))
{
SetBit(StatusInfo0, 0);
}
}
}
else
{
return NULL;
}
pUser_Standard_Requests->User_GetStatus();
return (uint8_t *)&StatusInfo;
}
/*********************************************************************
* @fn Standard_ClearFeature
*
* @brief Clear or disable a specific feature.
*
* @return Return USB_SUCCESS - if the request is performed.
* Return USB_UNSUPPORT - if the request is invalid.
*/
RESULT Standard_ClearFeature(void)
{
uint32_t Type_Rec = Type_Recipient;
uint32_t Status;
if (Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT))
{
ClrBit(pInformation->Current_Feature, 5);
return USB_SUCCESS;
}
else if (Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
{
DEVICE* pDev;
uint32_t Related_Endpoint;
uint32_t wIndex0;
uint32_t rEP;
if ((pInformation->USBwValue != ENDPOINT_STALL)
|| (pInformation->USBwIndex1 != 0))
{
return USB_UNSUPPORT;
}
pDev = &Device_Table;
wIndex0 = pInformation->USBwIndex0;
rEP = wIndex0 & ~0x80;
Related_Endpoint = ENDP0 + rEP;
if (ValBit(pInformation->USBwIndex0, 7))
{
Status = _GetEPTxStatus(Related_Endpoint);
}
else
{
Status = _GetEPRxStatus(Related_Endpoint);
}
if ((rEP >= pDev->Total_Endpoint) || (Status == 0)
|| (pInformation->Current_Configuration == 0))
{
return USB_UNSUPPORT;
}
if (wIndex0 & 0x80)
{
if (_GetTxStallStatus(Related_Endpoint ))
{
ClearDTOG_TX(Related_Endpoint);
SetEPTxStatus(Related_Endpoint, EP_TX_VALID);
}
}
else
{
if (_GetRxStallStatus(Related_Endpoint))
{
if (Related_Endpoint == ENDP0)
{
SetEPRxCount(Related_Endpoint, Device_Property.MaxPacketSize);
_SetEPRxStatus(Related_Endpoint, EP_RX_VALID);
}
else
{
ClearDTOG_RX(Related_Endpoint);
_SetEPRxStatus(Related_Endpoint, EP_RX_VALID);
}
}
}
pUser_Standard_Requests->User_ClearFeature();
return USB_SUCCESS;
}
return USB_UNSUPPORT;
}
/*********************************************************************
* @fn Standard_SetEndPointFeature
*
* @brief Set or enable a specific feature of EndPoint
*
* @return Return USB_SUCCESS - if the request is performed.
* Return USB_UNSUPPORT - if the request is invalid.
*/
RESULT Standard_SetEndPointFeature(void)
{
uint32_t wIndex0;
uint32_t Related_Endpoint;
uint32_t rEP;
uint32_t Status;
wIndex0 = pInformation->USBwIndex0;
rEP = wIndex0 & ~0x80;
Related_Endpoint = ENDP0 + rEP;
if (ValBit(pInformation->USBwIndex0, 7))
{
Status = _GetEPTxStatus(Related_Endpoint);
}
else
{
Status = _GetEPRxStatus(Related_Endpoint);
}
if (Related_Endpoint >= Device_Table.Total_Endpoint
|| pInformation->USBwValue != 0 || Status == 0
|| pInformation->Current_Configuration == 0)
{
return USB_UNSUPPORT;
}
else
{
if (wIndex0 & 0x80)
{
_SetEPTxStatus(Related_Endpoint, EP_TX_STALL);
}
else
{
_SetEPRxStatus(Related_Endpoint, EP_RX_STALL);
}
}
pUser_Standard_Requests->User_SetEndPointFeature();
return USB_SUCCESS;
}
/*********************************************************************
* @fn Standard_SetDeviceFeature
*
* @brief Set or enable a specific feature of Device.
*
* @return Return USB_SUCCESS - if the request is performed.
* Return USB_UNSUPPORT - if the request is invalid.
*/
RESULT Standard_SetDeviceFeature(void)
{
SetBit(pInformation->Current_Feature, 5);
pUser_Standard_Requests->User_SetDeviceFeature();
return USB_SUCCESS;
}
/*********************************************************************
* @fn Standard_GetDescriptorData
*
* @brief This routine is used for the descriptors resident in Flash
* or RAM pDesc can be in either Flash or RAM
* The purpose of this routine is to have a versatile way to
* response descriptors request. It allows user to generate
* certain descriptors with software or read descriptors from
* external storage part by part.
*
* @param Length - Length of the data in this transfer.
* pDesc - A pointer points to descriptor struct.
* The structure gives the initial address of the descriptor and
* its original size.
*
* @return Address of a part of the descriptor pointed by the Usb_
* wOffset The buffer pointed by this address contains at least
* Length bytes.
*/
uint8_t *Standard_GetDescriptorData(uint16_t Length, ONE_DESCRIPTOR *pDesc)
{
uint32_t wOffset;
wOffset = pInformation->Ctrl_Info.Usb_wOffset;
if (Length == 0)
{
pInformation->Ctrl_Info.Usb_wLength = pDesc->Descriptor_Size - wOffset;
return 0;
}
return pDesc->Descriptor + wOffset;
}
/*********************************************************************
* @fn DataStageOut
*
* @brief Data stage of a Control Write Transfer.
*
* @return none
*/
void DataStageOut(void)
{
ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info;
uint32_t save_rLength;
save_rLength = pEPinfo->Usb_rLength;
if (pEPinfo->CopyData && save_rLength)
{
uint8_t *Buffer;
uint32_t Length;
Length = pEPinfo->PacketSize;
if (Length > save_rLength)
{
Length = save_rLength;
}
Buffer = (*pEPinfo->CopyData)(Length);
pEPinfo->Usb_rLength -= Length;
pEPinfo->Usb_rOffset += Length;
PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length);
}
if (pEPinfo->Usb_rLength != 0)
{
vSetEPRxStatus(EP_RX_VALID);
SetEPTxCount(ENDP0, 0);
vSetEPTxStatus(EP_TX_VALID);
}
if (pEPinfo->Usb_rLength >= pEPinfo->PacketSize)
{
pInformation->ControlState = OUT_DATA;
}
else
{
if (pEPinfo->Usb_rLength > 0)
{
pInformation->ControlState = LAST_OUT_DATA;
}
else if (pEPinfo->Usb_rLength == 0)
{
pInformation->ControlState = WAIT_STATUS_IN;
USB_StatusIn();
}
}
}
/*********************************************************************
* @fn DataStageIn
*
* @brief Data stage of a Control Read Transfer.
*
* @return none
*/
void DataStageIn(void)
{
ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info;
uint32_t save_wLength = pEPinfo->Usb_wLength;
uint32_t ControlState = pInformation->ControlState;
uint8_t *DataBuffer;
uint32_t Length;
if ((save_wLength == 0) && (ControlState == LAST_IN_DATA))
{
if(Data_Mul_MaxPacketSize == TRUE)
{
Send0LengthData();
ControlState = LAST_IN_DATA;
Data_Mul_MaxPacketSize = FALSE;
}
else
{
ControlState = WAIT_STATUS_OUT;
vSetEPTxStatus(EP_TX_STALL);
}
goto Expect_Status_Out;
}
Length = pEPinfo->PacketSize;
ControlState = (save_wLength <= Length) ? LAST_IN_DATA : IN_DATA;
if (Length > save_wLength)
{
Length = save_wLength;
}
DataBuffer = (*pEPinfo->CopyData)(Length);
UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length);
SetEPTxCount(ENDP0, Length);
pEPinfo->Usb_wLength -= Length;
pEPinfo->Usb_wOffset += Length;
vSetEPTxStatus(EP_TX_VALID);
USB_StatusOut();
Expect_Status_Out:
pInformation->ControlState = ControlState;
}
/*********************************************************************
* @fn NoData_Setup0
*
* @brief Proceed the processing of setup request without data stage.
*
* @return none
*/
void NoData_Setup0(void)
{
RESULT Result = USB_UNSUPPORT;
uint32_t RequestNo = pInformation->USBbRequest;
uint32_t ControlState;
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
{
if (RequestNo == SET_CONFIGURATION)
{
Result = Standard_SetConfiguration();
}
else if (RequestNo == SET_ADDRESS)
{
if ((pInformation->USBwValue0 > 127) || (pInformation->USBwValue1 != 0)
|| (pInformation->USBwIndex != 0)
|| (pInformation->Current_Configuration != 0))
{
ControlState = STALLED;
goto exit_NoData_Setup0;
}
else
{
Result = USB_SUCCESS;
}
}
else if (RequestNo == SET_FEATURE)
{
if ((pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP) \
&& (pInformation->USBwIndex == 0))
{
Result = Standard_SetDeviceFeature();
}
else
{
Result = USB_UNSUPPORT;
}
}
else if (RequestNo == CLEAR_FEATURE)
{
if (pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP
&& pInformation->USBwIndex == 0
&& ValBit(pInformation->Current_Feature, 5))
{
Result = Standard_ClearFeature();
}
else
{
Result = USB_UNSUPPORT;
}
}
}
else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
{
if (RequestNo == SET_INTERFACE)
{
Result = Standard_SetInterface();
}
}
else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
{
if (RequestNo == CLEAR_FEATURE)
{
Result = Standard_ClearFeature();
}
else if (RequestNo == SET_FEATURE)
{
Result = Standard_SetEndPointFeature();
}
}
else
{
Result = USB_UNSUPPORT;
}
if (Result != USB_SUCCESS)
{
Result = (*pProperty->Class_NoData_Setup)(RequestNo);
if (Result == USB_NOT_READY)
{
ControlState = PAUSE;
goto exit_NoData_Setup0;
}
}
if (Result != USB_SUCCESS)
{
ControlState = STALLED;
goto exit_NoData_Setup0;
}
ControlState = WAIT_STATUS_IN;
USB_StatusIn();
exit_NoData_Setup0:
pInformation->ControlState = ControlState;
return;
}
/*********************************************************************
* @fn Data_Setup0
*
* @brief Proceed the processing of setup request with data stage.
*
* @return none
*/
void Data_Setup0(void)
{
uint8_t *(*CopyRoutine)(uint16_t);
RESULT Result;
uint32_t Request_No = pInformation->USBbRequest;
uint32_t Related_Endpoint, Reserved;
uint32_t wOffset, Status;
CopyRoutine = NULL;
wOffset = 0;
if (Request_No == GET_DESCRIPTOR)
{
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
{
uint8_t wValue1 = pInformation->USBwValue1;
if (wValue1 == DEVICE_DESCRIPTOR)
{
CopyRoutine = pProperty->GetDeviceDescriptor;
}
else if (wValue1 == CONFIG_DESCRIPTOR)
{
CopyRoutine = pProperty->GetConfigDescriptor;
}
else if (wValue1 == STRING_DESCRIPTOR)
{
CopyRoutine = pProperty->GetStringDescriptor;
}
}
}
else if ((Request_No == GET_STATUS) && (pInformation->USBwValue == 0)
&& (pInformation->USBwLength == 0x0002)
&& (pInformation->USBwIndex1 == 0))
{
if ((Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
&& (pInformation->USBwIndex == 0))
{
CopyRoutine = Standard_GetStatus;
}
else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
{
if (((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS)
&& (pInformation->Current_Configuration != 0))
{
CopyRoutine = Standard_GetStatus;
}
}
else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
{
Related_Endpoint = (pInformation->USBwIndex0 & 0x0f);
Reserved = pInformation->USBwIndex0 & 0x70;
if (ValBit(pInformation->USBwIndex0, 7))
{
Status = _GetEPTxStatus(Related_Endpoint);
}
else
{
Status = _GetEPRxStatus(Related_Endpoint);
}
if ((Related_Endpoint < Device_Table.Total_Endpoint) && (Reserved == 0)
&& (Status != 0))
{
CopyRoutine = Standard_GetStatus;
}
}
}
else if (Request_No == GET_CONFIGURATION)
{
if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
{
CopyRoutine = Standard_GetConfiguration;
}
}
else if (Request_No == GET_INTERFACE)
{
if ((Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
&& (pInformation->Current_Configuration != 0) && (pInformation->USBwValue == 0)
&& (pInformation->USBwIndex1 == 0) && (pInformation->USBwLength == 0x0001)
&& ((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS))
{
CopyRoutine = Standard_GetInterface;
}
}
if (CopyRoutine)
{
pInformation->Ctrl_Info.Usb_wOffset = wOffset;
pInformation->Ctrl_Info.CopyData = CopyRoutine;
(*CopyRoutine)(0);
Result = USB_SUCCESS;
}
else
{
Result = (*pProperty->Class_Data_Setup)(pInformation->USBbRequest);
if (Result == USB_NOT_READY)
{
pInformation->ControlState = PAUSE;
return;
}
}
if (pInformation->Ctrl_Info.Usb_wLength == 0xFFFF)
{
pInformation->ControlState = PAUSE;
return;
}
if ((Result == USB_UNSUPPORT) || (pInformation->Ctrl_Info.Usb_wLength == 0))
{
pInformation->ControlState = STALLED;
return;
}
if (ValBit(pInformation->USBbmRequestType, 7))
{
__IO uint32_t wLength = pInformation->USBwLength;
if (pInformation->Ctrl_Info.Usb_wLength > wLength)
{
pInformation->Ctrl_Info.Usb_wLength = wLength;
}
else if (pInformation->Ctrl_Info.Usb_wLength < pInformation->USBwLength)
{
if (pInformation->Ctrl_Info.Usb_wLength < pProperty->MaxPacketSize)
{
Data_Mul_MaxPacketSize = FALSE;
}
else if ((pInformation->Ctrl_Info.Usb_wLength % pProperty->MaxPacketSize) == 0)
{
Data_Mul_MaxPacketSize = TRUE;
}
}
pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize;
DataStageIn();
}
else
{
pInformation->ControlState = OUT_DATA;
vSetEPRxStatus(EP_RX_VALID);
}
return;
}
/*********************************************************************
* @fn Setup0_Process
*
* @brief Get the device request data and dispatch to individual process.
*
* @return Post0_Process.
*/
uint8_t Setup0_Process(void)
{
union
{
uint8_t* b;
uint16_t* w;
} pBuf;
uint16_t offset = 1;
pBuf.b = PMAAddr + (uint8_t *)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */
if (pInformation->ControlState != PAUSE)
{
pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */
pInformation->USBbRequest = *pBuf.b++; /* bRequest */
pBuf.w += offset; /* word not accessed because of 32 bits addressing */
pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */
pBuf.w += offset; /* word not accessed because of 32 bits addressing */
pInformation->USBwIndex = ByteSwap(*pBuf.w++); /* wIndex */
pBuf.w += offset; /* word not accessed because of 32 bits addressing */
pInformation->USBwLength = *pBuf.w; /* wLength */
}
pInformation->ControlState = SETTING_UP;
if (pInformation->USBwLength == 0)
{
NoData_Setup0();
}
else
{
Data_Setup0();
}
return Post0_Process();
}
/*********************************************************************
* @fn In0_Process
*
* @brief Process the IN token on all default endpoint.
*
* @return none
*/
uint8_t In0_Process(void)
{
uint32_t ControlState = pInformation->ControlState;
if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA))
{
DataStageIn();
ControlState = pInformation->ControlState;
}
else if (ControlState == WAIT_STATUS_IN)
{
if ((pInformation->USBbRequest == SET_ADDRESS) &&
(Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)))
{
SetDeviceAddress(pInformation->USBwValue0);
pUser_Standard_Requests->User_SetDeviceAddress();
}
(*pProperty->Process_Status_IN)();
ControlState = STALLED;
}
else
{
ControlState = STALLED;
}
pInformation->ControlState = ControlState;
return Post0_Process();
}
/*********************************************************************
* @fn Out0_Process
*
* @brief Process the OUT token on all default endpoint.
*
* @return none
*/
uint8_t Out0_Process(void)
{
uint32_t ControlState = pInformation->ControlState;
if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA))
{
ControlState = STALLED;
}
else if ((ControlState == OUT_DATA) || (ControlState == LAST_OUT_DATA))
{
DataStageOut();
ControlState = pInformation->ControlState;
}
else if (ControlState == WAIT_STATUS_OUT)
{
(*pProperty->Process_Status_OUT)();
ControlState = STALLED;
}
else
{
ControlState = STALLED;
}
pInformation->ControlState = ControlState;
return Post0_Process();
}
/*********************************************************************
* @fn Post0_Process
*
* @brief Stall the Endpoint 0 in case of error.
*
* @return 0 - if the control State is in PAUSE
* 1 - if not.
*/
uint8_t Post0_Process(void)
{
SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
if (pInformation->ControlState == STALLED)
{
vSetEPRxStatus(EP_RX_STALL);
vSetEPTxStatus(EP_TX_STALL);
}
return (pInformation->ControlState == PAUSE);
}
/*********************************************************************
* @fn SetDeviceAddress
*
* @brief Set the device and all the used Endpoints addresses.
*
* @param Val - device address.
*
* @return none
*/
void SetDeviceAddress(uint8_t Val)
{
uint32_t i;
uint32_t nEP = Device_Table.Total_Endpoint;
for (i = 0; i < nEP; i++)
{
_SetEPAddress((uint8_t)i, (uint8_t)i);
}
_SetDADDR(Val | DADDR_EF);
}
/*********************************************************************
* @fn NOP_Process
*
* @brief No operation function.
*
* @return none
*/
void NOP_Process(void)
{
}
@@ -0,0 +1,42 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_init.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Initialization routines & global variables
*********************************************************************************
* 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 "usb_lib.h"
uint8_t EPindex;
DEVICE_INFO *pInformation;
DEVICE_PROP *pProperty;
uint16_t SaveState ;
uint16_t wInterrupt_Mask;
DEVICE_INFO Device_Info;
USER_STANDARD_REQUESTS *pUser_Standard_Requests;
/*******************************************************************************
* @fn USB_Init
*
* @brief USB system initialization
*
* @return None.
*
*/
void USB_Init(void)
{
pInformation = &Device_Info;
pInformation->ControlState = 2;
pProperty = &Device_Property;
pUser_Standard_Requests = &User_Standard_Requests;
pProperty->Init();
}
@@ -0,0 +1,133 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_int.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Endpoint CTR (Low and High) interrupt's 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 "usb_lib.h"
/* Private variables */
__IO uint16_t SaveRState;
__IO uint16_t SaveTState;
/* Extern variables */
extern void (*pEpInt_IN[7])(void); /* Handles IN interrupts */
extern void (*pEpInt_OUT[7])(void); /* Handles OUT interrupts */
/*******************************************************************************
* @fn CTR_LP.
*
* @brief Low priority Endpoint Correct Transfer interrupt's service
* routine.
*
* @return None.
*/
void CTR_LP(void)
{
__IO uint16_t wEPVal = 0;
while (((wIstr = _GetISTR()) & ISTR_CTR) != 0)
{
EPindex = (uint8_t)(wIstr & ISTR_EP_ID);
if (EPindex == 0)
{
SaveRState = _GetENDPOINT(ENDP0);
SaveTState = SaveRState & EPTX_STAT;
SaveRState &= EPRX_STAT;
_SetEPRxTxStatus(ENDP0,EP_RX_NAK,EP_TX_NAK);
if ((wIstr & ISTR_DIR) == 0)
{
_ClearEP_CTR_TX(ENDP0);
In0_Process();
_SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
return;
}
else
{
wEPVal = _GetENDPOINT(ENDP0);
if ((wEPVal &EP_SETUP) != 0)
{
_ClearEP_CTR_RX(ENDP0);
Setup0_Process();
_SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
return;
}
else if ((wEPVal & EP_CTR_RX) != 0)
{
_ClearEP_CTR_RX(ENDP0);
Out0_Process();
_SetEPRxTxStatus(ENDP0,SaveRState,SaveTState);
return;
}
}
}
else
{
wEPVal = _GetENDPOINT(EPindex);
if ((wEPVal & EP_CTR_RX) != 0)
{
_ClearEP_CTR_RX(EPindex);
(*pEpInt_OUT[EPindex-1])();
}
if ((wEPVal & EP_CTR_TX) != 0)
{
_ClearEP_CTR_TX(EPindex);
(*pEpInt_IN[EPindex-1])();
}
}
}
}
/*******************************************************************************
* @fn CTR_HP.
*
* @brief High Priority Endpoint Correct Transfer interrupt's service
* routine.
*
* @return None.
*/
void CTR_HP(void)
{
uint32_t wEPVal = 0;
while (((wIstr = _GetISTR()) & ISTR_CTR) != 0)
{
_SetISTR((uint16_t)CLR_CTR);
EPindex = (uint8_t)(wIstr & ISTR_EP_ID);
wEPVal = _GetENDPOINT(EPindex);
if ((wEPVal & EP_CTR_RX) != 0)
{
_ClearEP_CTR_RX(EPindex);
(*pEpInt_OUT[EPindex-1])();
}
else if ((wEPVal & EP_CTR_TX) != 0)
{
_ClearEP_CTR_TX(EPindex);
(*pEpInt_IN[EPindex-1])();
}
}
}
@@ -0,0 +1,74 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_mem.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Utility functions for memory transfers to/from PMA
*********************************************************************************
* 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 "usb_lib.h"
/*******************************************************************************
* @fn UserToPMABufferCopy
*
* @brief Copy a buffer from user memory area to packet memory area (PMA)
*
* @param pbUsrBuf: pointer to user memory area.
* wPMABufAddr: address into PMA.
* wNBytes: no. of bytes to be copied.
*
* @param None .
*/
void UserToPMABufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
{
uint32_t n = (wNBytes + 1) >> 1;
uint32_t i, temp1, temp2;
uint16_t *pdwVal;
pdwVal = (uint16_t *)(wPMABufAddr * 2 + PMAAddr);
for (i = n; i != 0; i--)
{
temp1 = (uint16_t) * pbUsrBuf;
pbUsrBuf++;
temp2 = temp1 | (uint16_t) * pbUsrBuf << 8;
*pdwVal++ = temp2;
pdwVal++;
pbUsrBuf++;
}
}
/*******************************************************************************
* @fn PMAToUserBufferCopy
*
* @brief Copy a buffer from user memory area to packet memory area (PMA)
*
* @param pbUsrBuf: pointer to user memory area.
* wPMABufAddr: address into PMA.
* wNBytes: no. of bytes to be copied.
*
* @param None.
*/
void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
{
uint32_t n = (wNBytes + 1) >> 1;
uint32_t i;
uint32_t *pdwVal;
pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr);
for (i = n; i != 0; i--)
{
*(uint16_t*)pbUsrBuf++ = *pdwVal++;
pbUsrBuf++;
}
}
@@ -0,0 +1,852 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_regs.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Interface functions to USB cell registers
*********************************************************************************
* 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 "usb_lib.h"
/*******************************************************************************
* @fn SetCNTR.
*
* @brief Set the CNTR register value.
*
* @param wRegValue: new register value.
*
* @return None.
*/
void SetCNTR(uint16_t wRegValue)
{
_SetCNTR(wRegValue);
}
/*******************************************************************************
* @fn GetCNTR.
*
* @brief returns the CNTR register value.
*
* @param None.
*
* @return CNTR register Value.
*/
uint16_t GetCNTR(void)
{
return(_GetCNTR());
}
/*******************************************************************************
* @fn SetISTR.
*
* @brief Set the ISTR register value.
*
* @param wRegValue: new register value.
*
* @return None.
*/
void SetISTR(uint16_t wRegValue)
{
_SetISTR(wRegValue);
}
/*******************************************************************************
* @fn GetISTR
*
* @brief Returns the ISTR register value.
*
* @param None.
*
* @return ISTR register Value
*/
uint16_t GetISTR(void)
{
return(_GetISTR());
}
/*******************************************************************************
* @fn GetFNR
*
* @brief Returns the FNR register value.
*
* @param None.
*
* @return FNR register Value
*/
uint16_t GetFNR(void)
{
return(_GetFNR());
}
/*******************************************************************************
* @fn SetDADDR
*
* @brief Set the DADDR register value.
*
* @param wRegValue: new register value.
*
* @return None.
*/
void SetDADDR(uint16_t wRegValue)
{
_SetDADDR(wRegValue);
}
/*******************************************************************************
* @fn GetDADDR
*
* @brief Returns the DADDR register value.
*
* @return DADDR register Value
*
*/
uint16_t GetDADDR(void)
{
return(_GetDADDR());
}
/*******************************************************************************
* @fn SetBTABLE
*
* @brief Set the BTABLE.
*
* @param wRegValue: New register value.
*
* @return None.
*/
void SetBTABLE(uint16_t wRegValue)
{
_SetBTABLE(wRegValue);
}
/*******************************************************************************
* @fn GetBTABLE.
*
* @param Returns the BTABLE register value.
*
* @return BTABLE address.
*/
uint16_t GetBTABLE(void)
{
return(_GetBTABLE());
}
/*******************************************************************************
* @fn SetENDPOINT
*
* @brief Set the Endpoint register value.
*
* @param bEpNum: Endpoint Number.
* wRegValue.
*
* @return None.
*/
void SetENDPOINT(uint8_t bEpNum, uint16_t wRegValue)
{
_SetENDPOINT(bEpNum, wRegValue);
}
/*******************************************************************************
* @fn GetENDPOINT
*
* @brief Return the Endpoint register value.
*
* @param bEpNum: Endpoint Number.
*
* @return Endpoint register value.
*/
uint16_t GetENDPOINT(uint8_t bEpNum)
{
return(_GetENDPOINT(bEpNum));
}
/*******************************************************************************
* @fn SetEPType
*
* @brief sets the type in the endpoint register.
*
* @param bEpNum: Endpoint Number.
* wType: type definition.
*
* @return None.
*/
void SetEPType(uint8_t bEpNum, uint16_t wType)
{
_SetEPType(bEpNum, wType);
}
/*******************************************************************************
* @fn GetEPType
*
* @brief Returns the endpoint type.
*
* @param bEpNum: Endpoint Number.
*
* @return Endpoint Type
*/
uint16_t GetEPType(uint8_t bEpNum)
{
return(_GetEPType(bEpNum));
}
/*******************************************************************************
* @fn SetEPTxStatus
*
* @brief Set the status of Tx endpoint.
*
* @param bEpNum: Endpoint Number.
* wState: new state.
*
* @return None.
*/
void SetEPTxStatus(uint8_t bEpNum, uint16_t wState)
{
_SetEPTxStatus(bEpNum, wState);
}
/*******************************************************************************
* @fn SetEPRxStatus
*
* @brief Set the status of Rx endpoint.
*
* @param bEpNum: Endpoint Number.
* wState: new state.
*
* @return None.
*/
void SetEPRxStatus(uint8_t bEpNum, uint16_t wState)
{
_SetEPRxStatus(bEpNum, wState);
}
/*******************************************************************************
* @fn SetDouBleBuffEPStall
*
* @brief sets the status for Double Buffer Endpoint to STALL
*
* @param bEpNum: Endpoint Number.
* bDir: Endpoint direction.
*
* @return None.
*/
void SetDouBleBuffEPStall(uint8_t bEpNum, uint8_t bDir)
{
uint16_t Endpoint_DTOG_Status;
Endpoint_DTOG_Status = GetENDPOINT(bEpNum);
if (bDir == EP_DBUF_OUT)
{
_SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPRX_DTOG1);
}
else if (bDir == EP_DBUF_IN)
{
_SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPTX_DTOG1);
}
}
/*******************************************************************************
* @fn GetEPTxStatus
*
* @brief Returns the endpoint Tx status.
*
* @param bEpNum: Endpoint Number.
*
* @return Endpoint TX Status
*/
uint16_t GetEPTxStatus(uint8_t bEpNum)
{
return(_GetEPTxStatus(bEpNum));
}
/*******************************************************************************
* @fn GetEPRxStatus
*
* @brief Returns the endpoint Rx status.
*
* @param bEpNum: Endpoint Number.
*
* @return Endpoint RX Status
*/
uint16_t GetEPRxStatus(uint8_t bEpNum)
{
return(_GetEPRxStatus(bEpNum));
}
/*******************************************************************************
* @fn SetEPTxValid
*
* @brief Valid the endpoint Tx Status.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void SetEPTxValid(uint8_t bEpNum)
{
_SetEPTxStatus(bEpNum, EP_TX_VALID);
}
/*******************************************************************************
* @fn SetEPRxValid
*
* @brief Valid the endpoint Rx Status.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void SetEPRxValid(uint8_t bEpNum)
{
_SetEPRxStatus(bEpNum, EP_RX_VALID);
}
/*******************************************************************************
* @fn SetEP_KIND
*
* @brief Clear the EP_KIND bit.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void SetEP_KIND(uint8_t bEpNum)
{
_SetEP_KIND(bEpNum);
}
/*******************************************************************************
* @fn ClearEP_KIND
*
* @brief set the EP_KIND bit.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void ClearEP_KIND(uint8_t bEpNum)
{
_ClearEP_KIND(bEpNum);
}
/*******************************************************************************
* @fn Clear_Status_Out
*
* @brief Clear the Status Out of the related Endpoint
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void Clear_Status_Out(uint8_t bEpNum)
{
_ClearEP_KIND(bEpNum);
}
/*******************************************************************************
* @fn Set_Status_Out
*
* @brief Set the Status Out of the related Endpoint
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void Set_Status_Out(uint8_t bEpNum)
{
_SetEP_KIND(bEpNum);
}
/*******************************************************************************
* @fn SetEPDoubleBuff
*
* @brief Enable the double buffer feature for the endpoint.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void SetEPDoubleBuff(uint8_t bEpNum)
{
_SetEP_KIND(bEpNum);
}
/*******************************************************************************
* @fn ClearEPDoubleBuff
*
* @brief Disable the double buffer feature for the endpoint.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void ClearEPDoubleBuff(uint8_t bEpNum)
{
_ClearEP_KIND(bEpNum);
}
/*******************************************************************************
* @fn GetTxStallStatus
*
* @brief Returns the Stall status of the Tx endpoint.
*
* @param bEpNum: Endpoint Number.
*
* @return Tx Stall status.
*/
uint16_t GetTxStallStatus(uint8_t bEpNum)
{
return(_GetTxStallStatus(bEpNum));
}
/*******************************************************************************
* @fn GetRxStallStatus
*
* @brief Returns the Stall status of the Rx endpoint.
*
* @param bEpNum: Endpoint Number.
*
* @return Rx Stall status.
*/
uint16_t GetRxStallStatus(uint8_t bEpNum)
{
return(_GetRxStallStatus(bEpNum));
}
/*******************************************************************************
* @fn ClearEP_CTR_RX
*
* @brief Clear the CTR_RX bit.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void ClearEP_CTR_RX(uint8_t bEpNum)
{
_ClearEP_CTR_RX(bEpNum);
}
/*******************************************************************************
* @fn ClearEP_CTR_TX
*
* @brief Clear the CTR_TX bit.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void ClearEP_CTR_TX(uint8_t bEpNum)
{
_ClearEP_CTR_TX(bEpNum);
}
/*******************************************************************************
* @fn ToggleDTOG_RX
*
* @brief Toggle the DTOG_RX bit.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void ToggleDTOG_RX(uint8_t bEpNum)
{
_ToggleDTOG_RX(bEpNum);
}
/*******************************************************************************
* @fn ToggleDTOG_TX
*
* @brief Toggle the DTOG_TX bit.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void ToggleDTOG_TX(uint8_t bEpNum)
{
_ToggleDTOG_TX(bEpNum);
}
/*******************************************************************************
* @fn ClearDTOG_RX.
*
* @brief Clear the DTOG_RX bit.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void ClearDTOG_RX(uint8_t bEpNum)
{
_ClearDTOG_RX(bEpNum);
}
/*******************************************************************************
* @fn ClearDTOG_TX.
*
* @brief Clear the DTOG_TX bit.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
void ClearDTOG_TX(uint8_t bEpNum)
{
_ClearDTOG_TX(bEpNum);
}
/*******************************************************************************
* @fn SetEPAddress
*
* @brief Set the endpoint address.
*
* @param bEpNum: Endpoint Number.
* bAddr: New endpoint address.
*
* @return None.
*/
void SetEPAddress(uint8_t bEpNum, uint8_t bAddr)
{
_SetEPAddress(bEpNum, bAddr);
}
/*******************************************************************************
* @fn GetEPAddress
*
* @brief Get the endpoint address.
*
* @param bEpNum: Endpoint Number.
*
* @return Endpoint address.
*/
uint8_t GetEPAddress(uint8_t bEpNum)
{
return(_GetEPAddress(bEpNum));
}
/*******************************************************************************
* @fn SetEPTxAddr
*
* @brief Set the endpoint Tx buffer address.
*
* @param bEpNum: Endpoint Number.
* wAddr: new address.
*
* @return None.
*/
void SetEPTxAddr(uint8_t bEpNum, uint16_t wAddr)
{
_SetEPTxAddr(bEpNum, wAddr);
}
/*******************************************************************************
* @fn SetEPRxAddr
*
* @brief Set the endpoint Rx buffer address.
*
* @param bEpNum: Endpoint Number.
* wAddr: new address.
*
* @return None.
*/
void SetEPRxAddr(uint8_t bEpNum, uint16_t wAddr)
{
_SetEPRxAddr(bEpNum, wAddr);
}
/*******************************************************************************
* @fn GetEPTxAddr
*
* @brief Returns the endpoint Tx buffer address.
*
* @param bEpNum: Endpoint Number.
*
* @return Rx buffer address.
*/
uint16_t GetEPTxAddr(uint8_t bEpNum)
{
return(_GetEPTxAddr(bEpNum));
}
/*******************************************************************************
* @fn GetEPRxAddr.
*
* @brief Returns the endpoint Rx buffer address.
*
* @param bEpNum: Endpoint Number.
*
* @returnRx buffer address.
*/
uint16_t GetEPRxAddr(uint8_t bEpNum)
{
return(_GetEPRxAddr(bEpNum));
}
/*******************************************************************************
* @fn SetEPTxCount.
*
* @brief Set the Tx count.
*
* @param bEpNum: Endpoint Number.
* wCount: new count value.
*
* @return None.
*/
void SetEPTxCount(uint8_t bEpNum, uint16_t wCount)
{
_SetEPTxCount(bEpNum, wCount);
}
/*******************************************************************************
* @fn SetEPCountRxReg.
*
* @brief Set the Count Rx Register value.
*
* @param *pdwReg: point to the register.
* wCount: the new register value.
*
* @return None.
*/
void SetEPCountRxReg(uint32_t *pdwReg, uint16_t wCount)
{
_SetEPCountRxReg(dwReg, wCount);
}
/*******************************************************************************
* @fn SetEPRxCount
*
* @brief Set the Rx count.
*
* @param bEpNum: Endpoint Number.
* wCount: the new count value.
*
* @return None.
*/
void SetEPRxCount(uint8_t bEpNum, uint16_t wCount)
{
_SetEPRxCount(bEpNum, wCount);
}
/*******************************************************************************
* @fn GetEPTxCount
*
* @brief Get the Tx count.
*
* @param bEpNum: Endpoint Number.
*
* @return Tx count value.
*/
uint16_t GetEPTxCount(uint8_t bEpNum)
{
return(_GetEPTxCount(bEpNum));
}
/*******************************************************************************
* @fn GetEPRxCount
*
* @brief Get the Rx count.
*
* @param bEpNum: Endpoint Number.
*
* @return Rx count value.
*/
uint16_t GetEPRxCount(uint8_t bEpNum)
{
return(_GetEPRxCount(bEpNum));
}
/*******************************************************************************
* @fn SetEPDblBuffAddr
*
* @brief Set the addresses of the buffer 0 and 1.
*
* @param bEpNum: Endpoint Number.
* wBuf0Addr: new address of buffer 0.
* wBuf1Addr: new address of buffer 1.
*
* @return None.
*/
void SetEPDblBuffAddr(uint8_t bEpNum, uint16_t wBuf0Addr, uint16_t wBuf1Addr)
{
_SetEPDblBuffAddr(bEpNum, wBuf0Addr, wBuf1Addr);
}
/*******************************************************************************
* @fn SetEPDblBuf0Addr
*
* @brief Set the Buffer 1 address.
*
* @param bEpNum: Endpoint Number
* wBuf0Addr: new address.
*
* @return None.
*/
void SetEPDblBuf0Addr(uint8_t bEpNum, uint16_t wBuf0Addr)
{
_SetEPDblBuf0Addr(bEpNum, wBuf0Addr);
}
/*******************************************************************************
* @fn SetEPDblBuf1Addr
*
* @brief Set the Buffer 1 address.
*
* @param bEpNum: Endpoint Number
* wBuf1Addr: new address.
*
* @return None.
*/
void SetEPDblBuf1Addr(uint8_t bEpNum, uint16_t wBuf1Addr)
{
_SetEPDblBuf1Addr(bEpNum, wBuf1Addr);
}
/*******************************************************************************
* @fn GetEPDblBuf0Addr
*
* @brief Returns the address of the Buffer 0.
*
* @param bEpNum: Endpoint Number.
*
* @return None.
*/
uint16_t GetEPDblBuf0Addr(uint8_t bEpNum)
{
return(_GetEPDblBuf0Addr(bEpNum));
}
/*******************************************************************************
* @fn GetEPDblBuf1Addr
*
* @brief Returns the address of the Buffer 1.
*
* @param bEpNum: Endpoint Number.
*
* @return Address of the Buffer 1.
*/
uint16_t GetEPDblBuf1Addr(uint8_t bEpNum)
{
return(_GetEPDblBuf1Addr(bEpNum));
}
/*******************************************************************************
* @fn SetEPDblBuffCount
*
* @brief Set the number of bytes for a double Buffer
* endpoint.
*
* @param bEpNum,bDir, wCount
*
* @return None.
*/
void SetEPDblBuffCount(uint8_t bEpNum, uint8_t bDir, uint16_t wCount)
{
_SetEPDblBuffCount(bEpNum, bDir, wCount);
}
/*******************************************************************************
* @fn SetEPDblBuf0Count
*
* @brief Set the number of bytes in the buffer 0 of a double Buffer
* endpoint.
*
* @param bEpNum, bDir, wCount
*
* @return None.
*/
void SetEPDblBuf0Count(uint8_t bEpNum, uint8_t bDir, uint16_t wCount)
{
_SetEPDblBuf0Count(bEpNum, bDir, wCount);
}
/*******************************************************************************
* @fn SetEPDblBuf1Count
*
* @brief Set the number of bytes in the buffer 0 of a double Buffer
* endpoint.
*
* @param bEpNum, bDir, wCount
*
* @return None.
*/
void SetEPDblBuf1Count(uint8_t bEpNum, uint8_t bDir, uint16_t wCount)
{
_SetEPDblBuf1Count(bEpNum, bDir, wCount);
}
/*******************************************************************************
* @fn GetEPDblBuf0Count
*
* @brief Returns the number of byte received in the buffer 0 of a double
* Buffer endpoint.
*
* @param bEpNum: Endpoint Number.
*
* @return Endpoint Buffer 0 count
*/
uint16_t GetEPDblBuf0Count(uint8_t bEpNum)
{
return(_GetEPDblBuf0Count(bEpNum));
}
/*******************************************************************************
* @fn GetEPDblBuf1Count
*
* @brief Returns the number of data received in the buffer 1 of a double
* Buffer endpoint.
*
* @param bEpNum: Endpoint Number.
*
* @return Endpoint Buffer 1 count.
*/
uint16_t GetEPDblBuf1Count(uint8_t bEpNum)
{
return(_GetEPDblBuf1Count(bEpNum));
}
/*******************************************************************************
* @fn GetEPDblBufDir
*
* @brief gets direction of the double buffered endpoint
*
* @param bEpNum: Endpoint Number.
*
* @return EP_DBUF_OUT, EP_DBUF_IN,
* EP_DBUF_ERR if the endpoint counter not yet programmed.
*/
EP_DBUF_DIR GetEPDblBufDir(uint8_t bEpNum)
{
if ((uint16_t)(*_pEPRxCount(bEpNum) & 0xFC00) != 0)
return(EP_DBUF_OUT);
else if (((uint16_t)(*_pEPTxCount(bEpNum)) & 0x03FF) != 0)
return(EP_DBUF_IN);
else
return(EP_DBUF_ERR);
}
/*******************************************************************************
* @fn FreeUserBuffer
*
* @brief free buffer used from the application realizing it to the line
toggles bit SW_BUF in the double buffered endpoint register
*
* @param bEpNum, bDir
*
* @return None.
*/
void FreeUserBuffer(uint8_t bEpNum, uint8_t bDir)
{
if (bDir == EP_DBUF_OUT)
{
_ToggleDTOG_TX(bEpNum);
}
else if (bDir == EP_DBUF_IN)
{
_ToggleDTOG_RX(bEpNum);
}
}
/*******************************************************************************
* @fn ToWord
*
* @brief merge two byte in a word.
*
* @param bh: byte high, bl: bytes low.
*
* @return resulted word.
*/
uint16_t ToWord(uint8_t bh, uint8_t bl)
{
uint16_t wRet;
wRet = (uint16_t)bl | ((uint16_t)bh << 8);
return(wRet);
}
/*******************************************************************************
* @fn ByteSwap
*
* @brief Swap two byte in a word.
*
* @param wSwW: word to Swap.
*
* @return resulted word.
*/
uint16_t ByteSwap(uint16_t wSwW)
{
uint8_t bTemp;
uint16_t wRet;
bTemp = (uint8_t)(wSwW & 0xff);
wRet = (wSwW >> 8) | ((uint16_t)bTemp << 8);
return(wRet);
}
@@ -0,0 +1,77 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : usb_sil.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/08/08
* Description : Simplified Interface Layer for Global Initialization and
* Endpoint Rea/Write operations.
*********************************************************************************
* 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 "usb_lib.h"
/*******************************************************************************
* @fn USB_SIL_Init
*
* @brief Initialize the USB Device IP and the Endpoint 0.
*
* @return Status.
*/
uint32_t USB_SIL_Init(void)
{
_SetISTR(0);
wInterrupt_Mask = IMR_MSK;
_SetCNTR(wInterrupt_Mask);
return 0;
}
/*******************************************************************************
* @fn USB_SIL_Write
*
* @brief Write a buffer of data to a selected endpoint.
*
* @param bEpAddr: The address of the non control endpoint.
* pBufferPointer: The pointer to the buffer of data to be written
* to the endpoint.
* wBufferSize: Number of data to be written (in bytes).
*
* @return Status.
*/
uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize)
{
UserToPMABufferCopy(pBufferPointer, GetEPTxAddr(bEpAddr & 0x7F), wBufferSize);
SetEPTxCount((bEpAddr & 0x7F), wBufferSize);
return 0;
}
/*******************************************************************************
* @fn USB_SIL_Read
*
* @brief Write a buffer of data to a selected endpoint.
*
* @param bEpAddr: The address of the non control endpoint.
* pBufferPointer: The pointer to which will be saved the
* received data buffer.
*
* @return Number of received data (in Bytes).
*/
uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer)
{
uint32_t DataLength = 0;
DataLength = GetEPRxCount(bEpAddr & 0x7F);
PMAToUserBufferCopy(pBufferPointer, GetEPRxAddr(bEpAddr & 0x7F), DataLength);
return DataLength;
}
@@ -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,53 @@
/********************************** (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")));
void SW_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)
{
}
}
/*********************************************************************
* @fn SW_Handler
*
* @brief This function handles Software exception.
*
* @return none
*/
void SW_Handler(void) {
__asm("li a6, 0x5000");
__asm("jr a6");
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,563 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_usbotg_device.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : This file provides all the USBOTG firmware 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.
*******************************************************************************/
#include "ch32v20x_usbotg_device.h"
#include "iap.h"
/* Global define */
/* OTH */
#define pMySetupReqPakHD ((PUSB_SETUP_REQ)EP0_DatabufHD)
#define RepDescSize 62
#define DevEP0SIZE 0x40
#define PID_OUT 0
#define PID_SOF 1
#define PID_IN 2
#define PID_SETUP 3
#define Version_Num 0x0100 //V0100
u8 EP2_Tx_Buffer[2];
/******************************************************************************/
/* Endpoint Buffer */
__attribute__ ((aligned(4))) UINT8 EP0_DatabufHD[64]; //ep0(64)
__attribute__ ((aligned(4))) UINT8 EP2_DatabufHD[64+64]; //ep2_out(64)+ep2_in(64)
PUINT8 pEP0_RAM_Addr; //ep0(64)
PUINT8 pEP2_RAM_Addr; //ep2_out(64)+ep2_in(64)
const UINT8 *pDescr;
volatile UINT16 USBHD_Dev_SetupReqLen = 0x00;
volatile UINT8 USBHD_Dev_Config = 0x00;
volatile UINT8 USBHD_Dev_Address = 0x00;
volatile UINT8 USBHD_Dev_SleepStatus = 0x00;
volatile UINT8 DevConfig;
volatile UINT8 SetupReqCode;
volatile UINT16 SetupReqLen;
/******************************************************************************/
/* Device Descriptor */
const UINT8 MyDevDescrHD[] = { 0x12, 0x01, 0x10, 0x01, 0xFF, 0x80, 0x55,
DevEP0SIZE, 0x48, 0x43, 0xe0, 0x55, //USB MODULE
(u8) Version_Num, (u8) (Version_Num >> 8),
0x00, 0x00, 0x00, 0x01 };
/* Configration Descriptor */
const UINT8 MyCfgDescrHD[] = { 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80,
0x32, 0x09, 0x04, 0x00, 0x00, 0x02, 0xFF, 0x80, 0x55, 0x00, 0x07, 0x05,
0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00 };
void USBHD_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
/*********************************************************************
* @fn USBOTG_FS_DeviceInit
*
* @brief Initializes USB device.
*
* @return none
*/
void USBDeviceInit( void )
{
USBOTG_FS->BASE_CTRL = 0x00;
USBOTG_FS->UEP2_3_MOD = USBHD_UEP2_RX_EN|USBHD_UEP2_TX_EN;
USBOTG_FS->UEP0_DMA = (UINT32)pEP0_RAM_Addr;
USBOTG_FS->UEP2_DMA = (UINT32)pEP2_RAM_Addr;
USBOTG_FS->UEP0_RX_CTRL = USBHD_UEP_R_RES_ACK;
USBOTG_FS->UEP1_RX_CTRL = USBHD_UEP_R_RES_NAK;
USBOTG_FS->UEP2_RX_CTRL = USBHD_UEP_R_RES_ACK;
USBOTG_FS->UEP3_RX_CTRL = USBHD_UEP_R_RES_NAK;
USBOTG_FS->UEP4_RX_CTRL = USBHD_UEP_R_RES_NAK;
USBOTG_FS->UEP5_RX_CTRL = USBHD_UEP_R_RES_NAK;
USBOTG_FS->UEP6_RX_CTRL = USBHD_UEP_R_RES_NAK;
USBOTG_FS->UEP7_RX_CTRL = USBHD_UEP_R_RES_NAK;
USBOTG_FS->UEP2_TX_LEN = 8;
USBOTG_FS->UEP0_TX_CTRL = USBHD_UEP_T_RES_NAK;
USBOTG_FS->UEP2_TX_CTRL = USBHD_UEP_T_RES_ACK|USBHD_UEP_AUTO_TOG;
USBOTG_FS->INT_FG = 0xFF;
USBOTG_FS->INT_EN = USBHD_UIE_SUSPEND | USBHD_UIE_BUS_RST | USBHD_UIE_TRANSFER;
USBOTG_FS->DEV_ADDR = 0x00;
USBOTG_FS->BASE_CTRL = USBHD_UC_DEV_PU_EN | USBHD_UC_INT_BUSY | USBHD_UC_DMA_EN;
USBOTG_FS->UDEV_CTRL = USBHD_UD_PD_DIS|USBHD_UD_PORT_EN;
}
/*********************************************************************
* @fn USBOTG_RCC_Init
*
* @brief Initializes the usbotg clock configuration.
*
* @return none
*/
void USBOTG_RCC_Init(void)
{
RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2);
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_OTG_FS, ENABLE );
}
/*********************************************************************
* @fn USBOTG_Init
*
* @brief Initializes the USBOTG full speed device.
*
* @return none
*/
void USBOTG_Init( void )
{
pEP0_RAM_Addr = EP0_DatabufHD;
pEP2_RAM_Addr = EP2_DatabufHD;
USBOTG_RCC_Init( );
Delay_Us(100);
USBDeviceInit( );
NVIC_EnableIRQ( USBHD_IRQn );
}
/*********************************************************************
* @fn USBHD_IRQHandler
*
* @brief This function handles OTG_FS exception.
*
* @return none
*/
void USBHD_IRQHandler( void )
{
UINT8 len, chtype;
UINT8 intflag, errflag = 0;
intflag = USBOTG_FS->INT_FG;
if( intflag & USBHD_UIF_TRANSFER )
{
switch ( USBOTG_FS->INT_ST & USBHD_UIS_TOKEN_MASK )
{
/* SETUP */
case USBHD_UIS_TOKEN_SETUP:
USBOTG_FS->UEP0_TX_CTRL = USBHD_UEP_T_TOG|USBHD_UEP_T_RES_NAK;
USBOTG_FS->UEP0_RX_CTRL = USBHD_UEP_R_TOG|USBHD_UEP_R_RES_ACK;
SetupReqLen = pSetupReqPakHD->wLength;
SetupReqCode = pSetupReqPakHD->bRequest;
chtype = pSetupReqPakHD->bRequestType;
len = 0;
errflag = 0;
if ( ( pSetupReqPakHD->bRequestType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )
{
if( pSetupReqPakHD->bRequestType & 0x40 )
{
switch( pSetupReqPakHD->bRequest )
{
default:
errflag = 0xFF;
break;
}
}
else if( pSetupReqPakHD->bRequestType & 0x20 )
{
switch( pSetupReqPakHD->bRequest )
{
case 0x01: //GetReport
break;
case 0x02: //GetIdle
break;
case 0x03: //GetProtocol
break;
case 0x09: //SetReport
break;
case 0x0A: //SetIdle
break;
case 0x0B: //SetProtocol
break;
default:
errflag = 0xFF;
break;
}
}
if( errflag != 0xFF )
{
if( SetupReqLen > len )
{
SetupReqLen = len;
}
len = ( USBHD_Dev_SetupReqLen >= DevEP0SIZE ) ? DevEP0SIZE : USBHD_Dev_SetupReqLen;
memcpy( EP0_DatabufHD, pDescr, len );
pDescr += len;
}
}
else
{
switch( SetupReqCode )
{
case USB_GET_DESCRIPTOR:
{
switch( ((pSetupReqPakHD->wValue)>>8) )
{
case USB_DESCR_TYP_DEVICE:
pDescr = MyDevDescrHD;
len = MyDevDescrHD[0];
break;
case USB_DESCR_TYP_CONFIG:
pDescr = MyCfgDescrHD;
len = MyCfgDescrHD[2];
break;
case USB_DESCR_TYP_STRING:
switch( (pSetupReqPakHD->wValue)&0xff )
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
default:
errflag = 0xFF;
break;
}
break;
case USB_DESCR_TYP_REPORT:
break;
case USB_DESCR_TYP_QUALIF:
break;
default :
errflag = 0xff;
break;
}
if( SetupReqLen>len ) SetupReqLen = len;
len = (SetupReqLen >= DevEP0SIZE) ? DevEP0SIZE : SetupReqLen;
memcpy( pEP0_DataBuf, pDescr, len );
pDescr += len;
}
break;
case USB_SET_ADDRESS:
SetupReqLen = (pSetupReqPakHD->wValue)&0xff;
break;
case USB_GET_CONFIGURATION:
pEP0_DataBuf[0] = DevConfig;
if ( SetupReqLen > 1 ) SetupReqLen = 1;
break;
case USB_SET_CONFIGURATION:
DevConfig = (pSetupReqPakHD->wValue)&0xff;
break;
case USB_CLEAR_FEATURE:
if ( ( pSetupReqPakHD->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
{
switch( (pSetupReqPakHD->wIndex)&0xff )
{
case 0x82:
USBOTG_FS->UEP2_TX_CTRL = (USBOTG_FS->UEP2_TX_CTRL & ~( USBHD_UEP_T_TOG|USBHD_UEP_T_RES_MASK )) | USBHD_UEP_T_RES_NAK;
break;
case 0x02:
USBOTG_FS->UEP2_RX_CTRL = (USBOTG_FS->UEP2_RX_CTRL & ~( USBHD_UEP_R_TOG|USBHD_UEP_R_RES_MASK )) | USBHD_UEP_R_RES_ACK;
break;
case 0x81:
USBOTG_FS->UEP1_TX_CTRL = (USBOTG_FS->UEP1_TX_CTRL & ~( USBHD_UEP_T_TOG|USBHD_UEP_T_RES_MASK )) | USBHD_UEP_T_RES_NAK;
break;
case 0x01:
USBOTG_FS->UEP1_RX_CTRL = (USBOTG_FS->UEP1_RX_CTRL & ~( USBHD_UEP_R_TOG|USBHD_UEP_R_RES_MASK )) | USBHD_UEP_R_RES_ACK;
break;
default:
errflag = 0xFF;
break;
}
}
else errflag = 0xFF;
break;
case USB_SET_FEATURE:
if( ( pMySetupReqPakHD->bRequestType & 0x1F ) == 0x00 )
{
if( pMySetupReqPakHD->wValue == 0x01 )
{
if( MyCfgDescrHD[ 7 ] & 0x20 )
{
USBHD_Dev_SleepStatus = 0x01;
}
else
{
errflag = 0xFF;
}
}
else
{
errflag = 0xFF;
}
}
else if( ( pMySetupReqPakHD->bRequestType & 0x1F ) == 0x02 )
{
if( pMySetupReqPakHD->wValue == 0x00 )
{
switch( ( pMySetupReqPakHD->wIndex ) & 0xff )
{
case 0x82:
USBOTG_FS->UEP2_TX_CTRL = ( USBOTG_FS->UEP2_TX_CTRL &= ~USBHD_UEP_T_RES_MASK ) | USBHD_UEP_T_RES_STALL;
break;
case 0x02:
USBOTG_FS->UEP2_RX_CTRL = ( USBOTG_FS->UEP2_RX_CTRL &= ~USBHD_UEP_R_RES_MASK ) | USBHD_UEP_R_RES_STALL;
break;
default:
errflag = 0xFF;
break;
}
}
else
{
errflag = 0xFF;
}
}
else
{
errflag = 0xFF;
}
break;
case USB_GET_INTERFACE:
pEP0_DataBuf[0] = 0x00;
if ( SetupReqLen > 1 ) SetupReqLen = 1;
break;
case USB_SET_INTERFACE:
EP0_DatabufHD[ 0 ] = 0x00;
if( USBHD_Dev_SetupReqLen > 1 )
{
USBHD_Dev_SetupReqLen = 1;
}
break;
case USB_GET_STATUS:
EP0_DatabufHD[ 0 ] = 0x00;
EP0_DatabufHD[ 1 ] = 0x00;
if( pMySetupReqPakHD->wIndex == 0x81 )
{
if( ( USBOTG_FS->UEP1_TX_CTRL & USBHD_UEP_T_RES_MASK ) == USBHD_UEP_T_RES_STALL )
{
EP0_DatabufHD[ 0 ] = 0x01;
}
}
else if( pMySetupReqPakHD->wIndex == 0x01 )
{
if( ( USBOTG_FS->UEP1_RX_CTRL & USBHD_UEP_R_RES_MASK ) == USBHD_UEP_R_RES_STALL )
{
EP0_DatabufHD[ 0 ] = 0x01;
}
}
else if( pMySetupReqPakHD->wIndex == 0x82 )
{
if( ( USBOTG_FS->UEP2_TX_CTRL & USBHD_UEP_T_RES_MASK ) == USBHD_UEP_T_RES_STALL )
{
EP0_DatabufHD[ 0 ] = 0x01;
}
}
else if( pMySetupReqPakHD->wIndex == 0x02 )
{
if( ( USBOTG_FS->UEP2_RX_CTRL & USBHD_UEP_R_RES_MASK ) == USBHD_UEP_R_RES_STALL )
{
EP0_DatabufHD[ 0 ] = 0x01;
}
}
if( USBHD_Dev_SetupReqLen > 2 )
{
USBHD_Dev_SetupReqLen = 2;
}
break;
default:
errflag = 0xff;
break;
}
}
if( errflag == 0xff)
{
USBOTG_FS->UEP0_TX_CTRL = USBHD_UEP_T_TOG|USBHD_UEP_T_RES_STALL;
USBOTG_FS->UEP0_RX_CTRL = USBHD_UEP_R_TOG|USBHD_UEP_R_RES_STALL;
}
else
{
if( chtype & 0x80 )
{
len = (SetupReqLen>DevEP0SIZE) ? DevEP0SIZE : SetupReqLen;
SetupReqLen -= len;
}
else len = 0;
USBOTG_FS->UEP0_TX_LEN = len;
USBOTG_FS->UEP0_TX_CTRL = USBHD_UEP_T_TOG|USBHD_UEP_T_RES_ACK;
USBOTG_FS->UEP0_RX_CTRL = USBHD_UEP_R_TOG|USBHD_UEP_R_RES_ACK;
}
break;
case USBHD_UIS_TOKEN_IN:
switch ( USBOTG_FS->INT_ST & ( USBHD_UIS_TOKEN_MASK | USBHD_UIS_ENDP_MASK ) )
{
case USBHD_UIS_TOKEN_IN:
switch( SetupReqCode )
{
case USB_GET_DESCRIPTOR:
len = SetupReqLen >= DevEP0SIZE ? DevEP0SIZE : SetupReqLen;
memcpy( pEP0_DataBuf, pDescr, len );
SetupReqLen -= len;
pDescr += len;
USBOTG_FS->UEP0_TX_LEN = len;
USBOTG_FS->UEP0_TX_CTRL ^= USBHD_UEP_T_TOG;
break;
case USB_SET_ADDRESS:
USBOTG_FS->DEV_ADDR = (USBOTG_FS->DEV_ADDR&USBHD_UDA_GP_BIT) | SetupReqLen;
USBOTG_FS->UEP0_TX_CTRL = USBHD_UEP_T_RES_NAK;
USBOTG_FS->UEP0_RX_CTRL = USBHD_UEP_R_RES_ACK;
break;
default:
USBOTG_FS->UEP0_TX_LEN = 0;
USBOTG_FS->UEP0_TX_CTRL = USBHD_UEP_T_RES_NAK;
USBOTG_FS->UEP0_RX_CTRL = USBHD_UEP_R_RES_ACK;
break;
}
break;
case USBHD_UIS_TOKEN_IN | 2:
USBOTG_FS->UEP2_TX_CTRL ^= USBHD_UEP_T_TOG;
USBOTG_FS->UEP2_TX_CTRL = (USBOTG_FS->UEP2_TX_CTRL & ~USBHD_UEP_T_RES_MASK) | USBHD_UEP_T_RES_NAK;
break;
default :
break;
}
break;
case USBHD_UIS_TOKEN_OUT:
switch ( USBOTG_FS->INT_ST & ( USBHD_UIS_TOKEN_MASK | USBHD_UIS_ENDP_MASK ) )
{
case USBHD_UIS_TOKEN_OUT:
len = USBOTG_FS->RX_LEN;
break;
case USBHD_UIS_TOKEN_OUT | 2:
if ( USBOTG_FS->INT_ST & USBHD_UIS_TOG_OK )
{
USBOTG_FS->UEP2_RX_CTRL ^= USBHD_UEP_R_TOG;
len = USBOTG_FS->RX_LEN;
DevEP2_OUT_Deal( len );
}
break;
}
break;
case USBHD_UIS_TOKEN_SOF:
break;
default :
break;
}
USBOTG_FS->INT_FG = USBHD_UIF_TRANSFER;
}
else if( intflag & USBHD_UIF_BUS_RST )
{
USBOTG_FS->DEV_ADDR = 0;
USBOTG_FS->UEP0_RX_CTRL = USBHD_UEP_R_RES_ACK;
USBOTG_FS->UEP2_RX_CTRL = USBHD_UEP_R_RES_ACK;
USBOTG_FS->UEP0_TX_CTRL = USBHD_UEP_T_RES_NAK;
USBOTG_FS->UEP2_TX_CTRL = USBHD_UEP_T_RES_NAK;
USBOTG_FS->INT_FG |= USBHD_UIF_BUS_RST;
}
else if( intflag & USBHD_UIF_SUSPEND )
{
if ( USBOTG_FS->MIS_ST & USBHD_UMS_SUSPEND ) {;}
else{;}
USBOTG_FS->INT_FG = USBHD_UIF_SUSPEND;
}
else
{
USBOTG_FS->INT_FG = intflag;
}
}
/*********************************************************************
* @fn DevEP2_IN_Deal
*
* @brief Device endpoint2 IN.
*
* @param l - IN length(<64B)
*
* @return none
*/
void DevEP2_IN_Deal( UINT8 l )
{
USBOTG_FS->UEP2_TX_LEN = l;
USBOTG_FS->UEP2_TX_CTRL = (USBOTG_FS->UEP2_TX_CTRL & ~USBHD_UEP_T_RES_MASK)| USBHD_UEP_T_RES_ACK;
}
/*********************************************************************
* @fn DevEP2_OUT_Deal
*
* @brief Deal device Endpoint 2 OUT.
*
* @param l - Data length.
*
* @return none
*/
void DevEP2_OUT_Deal( UINT8 l )
{
UINT8 s ,EP2_Tx_Cnt;
memcpy(EP2_Rx_Buffer, pEP2_OUT_DataBuf, l);
s = RecData_Deal();
if (s != ERR_End) {
EP2_Tx_Buffer[0] = 0x00;
if (s == ERR_ERROR)
{
pEP2_IN_DataBuf[1] = 0x01;
}
else
pEP2_IN_DataBuf[1] = 0x00;
EP2_Tx_Cnt = 2;
DevEP2_IN_Deal(EP2_Tx_Cnt);
}
}
@@ -0,0 +1,719 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_usbotg_device.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : This file provides all the USBOTG firmware 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.
*******************************************************************************/
#ifndef __CH32V20x_USBOTG_DEVICE_H_
#define __CH32V20x_USBOTG_DEVICE_H_
#include "debug.h"
#include "string.h"
#ifndef NULL
#define NULL 0
#endif
#ifndef VOID
#define VOID void
#endif
#ifndef CONST
#define CONST const
#endif
#ifndef BOOL
typedef unsigned char BOOL;
#endif
#ifndef BOOLEAN
typedef unsigned char BOOLEAN;
#endif
#ifndef CHAR
typedef char CHAR;
#endif
#ifndef INT8
typedef char INT8;
#endif
#ifndef INT16
typedef short INT16;
#endif
#ifndef INT32
typedef long INT32;
#endif
#ifndef UINT8
typedef unsigned char UINT8;
#endif
#ifndef UINT16
typedef unsigned short UINT16;
#endif
#ifndef UINT32
typedef unsigned long UINT32;
#endif
#ifndef UINT8V
typedef unsigned char volatile UINT8V;
#endif
#ifndef UINT16V
typedef unsigned short volatile UINT16V;
#endif
#ifndef UINT32V
typedef unsigned long volatile UINT32V;
#endif
#ifndef PVOID
typedef void *PVOID;
#endif
#ifndef PCHAR
typedef char *PCHAR;
#endif
#ifndef PCHAR
typedef const char *PCCHAR;
#endif
#ifndef PINT8
typedef char *PINT8;
#endif
#ifndef PINT16
typedef short *PINT16;
#endif
#ifndef PINT32
typedef long *PINT32;
#endif
#ifndef PUINT8
typedef unsigned char *PUINT8;
#endif
#ifndef PUINT16
typedef unsigned short *PUINT16;
#endif
#ifndef PUINT32
typedef unsigned long *PUINT32;
#endif
#ifndef PUINT8V
typedef volatile unsigned char *PUINT8V;
#endif
#ifndef PUINT16V
typedef volatile unsigned short *PUINT16V;
#endif
#ifndef PUINT32V
typedef volatile unsigned long *PUINT32V;
#endif
/* USB constant and structure define */
/* USB PID */
#ifndef USB_PID_SETUP
#define USB_PID_NULL 0x00 /* reserved PID */
#define USB_PID_SOF 0x05
#define USB_PID_SETUP 0x0D
#define USB_PID_IN 0x09
#define USB_PID_OUT 0x01
#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
/* 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 /* control IN, device to host */
#define USB_REQ_TYP_OUT 0x00 /* control OUT, host to device */
#define USB_REQ_TYP_READ 0x80 /* control read, device to host */
#define USB_REQ_TYP_WRITE 0x00 /* control write, host to device */
#define USB_REQ_TYP_MASK 0x60 /* bit mask of request type */
#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 /* bit mask of request recipient */
#define USB_REQ_RECIP_DEVICE 0x00
#define USB_REQ_RECIP_INTERF 0x01
#define USB_REQ_RECIP_ENDP 0x02
#define USB_REQ_RECIP_OTHER 0x03
#endif
/* USB request type for 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 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 endpoint type and attributes */
#ifndef USB_ENDP_TYPE_MASK
#define USB_ENDP_DIR_MASK 0x80
#define USB_ENDP_ADDR_MASK 0x0F
#define USB_ENDP_TYPE_MASK 0x03
#define USB_ENDP_TYPE_CTRL 0x00
#define USB_ENDP_TYPE_ISOCH 0x01
#define USB_ENDP_TYPE_BULK 0x02
#define USB_ENDP_TYPE_INTER 0x03
#endif
#ifndef USB_DEVICE_ADDR
#define USB_DEVICE_ADDR 0x02
#endif
#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
#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
#ifndef __PACKED
#define __PACKED __attribute__((packed))
#endif
typedef struct __PACKED _USB_SETUP_REQ {
UINT8 bRequestType;
UINT8 bRequest;
UINT16 wValue;
UINT16 wIndex;
UINT16 wLength;
} USB_SETUP_REQ, *PUSB_SETUP_REQ;
typedef struct __PACKED _USB_DEVICE_DESCR {
UINT8 bLength;
UINT8 bDescriptorType;
UINT16 bcdUSB;
UINT8 bDeviceClass;
UINT8 bDeviceSubClass;
UINT8 bDeviceProtocol;
UINT8 bMaxPacketSize0;
UINT16 idVendor;
UINT16 idProduct;
UINT16 bcdDevice;
UINT8 iManufacturer;
UINT8 iProduct;
UINT8 iSerialNumber;
UINT8 bNumConfigurations;
} USB_DEV_DESCR, *PUSB_DEV_DESCR;
typedef struct __PACKED _USB_CONFIG_DESCR {
UINT8 bLength;
UINT8 bDescriptorType;
UINT16 wTotalLength;
UINT8 bNumInterfaces;
UINT8 bConfigurationValue;
UINT8 iConfiguration;
UINT8 bmAttributes;
UINT8 MaxPower;
} USB_CFG_DESCR, *PUSB_CFG_DESCR;
typedef struct __PACKED _USB_INTERF_DESCR {
UINT8 bLength;
UINT8 bDescriptorType;
UINT8 bInterfaceNumber;
UINT8 bAlternateSetting;
UINT8 bNumEndpoints;
UINT8 bInterfaceClass;
UINT8 bInterfaceSubClass;
UINT8 bInterfaceProtocol;
UINT8 iInterface;
} USB_ITF_DESCR, *PUSB_ITF_DESCR;
typedef struct __PACKED _USB_ENDPOINT_DESCR {
UINT8 bLength;
UINT8 bDescriptorType;
UINT8 bEndpointAddress;
UINT8 bmAttributes;
UINT16 wMaxPacketSize;
UINT8 bInterval;
} USB_ENDP_DESCR, *PUSB_ENDP_DESCR;
typedef struct __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;
typedef struct __PACKED _USB_HUB_DESCR {
UINT8 bDescLength;
UINT8 bDescriptorType;
UINT8 bNbrPorts;
UINT8 wHubCharacteristicsL;
UINT8 wHubCharacteristicsH;
UINT8 bPwrOn2PwrGood;
UINT8 bHubContrCurrent;
UINT8 DeviceRemovable;
UINT8 PortPwrCtrlMask;
} USB_HUB_DESCR, *PUSB_HUB_DESCR;
typedef struct __PACKED _USB_HID_DESCR {
UINT8 bLength;
UINT8 bDescriptorType;
UINT16 bcdHID;
UINT8 bCountryCode;
UINT8 bNumDescriptors;
UINT8 bDescriptorTypeX;
UINT8 wDescriptorLengthL;
UINT8 wDescriptorLengthH;
} USB_HID_DESCR, *PUSB_HID_DESCR;
typedef struct __PACKED _UDISK_BOC_CBW {/* command of BulkOnly USB-FlashDisk */
UINT32 mCBW_Sig;
UINT32 mCBW_Tag;
UINT32 mCBW_DataLen; /* uppest byte of data length, always is 0 */
UINT8 mCBW_Flag; /* transfer direction and etc. */
UINT8 mCBW_LUN;
UINT8 mCBW_CB_Len; /* length of command block */
UINT8 mCBW_CB_Buf[16]; /* command block buffer */
} UDISK_BOC_CBW, *PXUDISK_BOC_CBW;
typedef struct __PACKED _UDISK_BOC_CSW {/* status of BulkOnly USB-FlashDisk */
UINT32 mCBW_Sig;
UINT32 mCBW_Tag;
UINT32 mCSW_Residue; /* return: remainder bytes */ /* uppest byte of remainder length, always is 0 */
UINT8 mCSW_Status; /* return: result status */
} UDISK_BOC_CSW, *PXUDISK_BOC_CSW;
#define USE_SYS_CLK 0
//#define USBHD_HOST 0
//#define USB_OTG 0
/******************************************************************************/
/* USBOTG_FS DEVICE USB_CONTROL */
/* BASE USB_CTRL */
#define USBHD_BASE_CTRL (USBOTG_FS->BASE_CTRL) // USB base control
#define USBHD_UC_HOST_MODE 0x80 // enable USB host mode: 0=device mode, 1=host mode
#define USBHD_UC_LOW_SPEED 0x40 // enable USB low speed: 0=12Mbps, 1=1.5Mbps
#define USBHD_UC_DEV_PU_EN 0x20 // USB device enable and internal pullup resistance enable
#define USBHD_UC_SYS_CTRL1 0x20 // USB system control high bit
#define USBHD_UC_SYS_CTRL0 0x10 // USB system control low bit
#define USBHD_UC_SYS_CTRL_MASK 0x30 // bit mask of USB system control
// UC_HOST_MODE & UC_SYS_CTRL1 & UC_SYS_CTRL0: USB system control
// 0 00: disable USB device and disable internal pullup resistance
// 0 01: enable USB device and disable internal pullup resistance, need external pullup resistance
// 0 1x: enable USB device and enable internal pullup resistance
// 1 00: enable USB host and normal status
// 1 01: enable USB host and force UDP/UDM output SE0 state
// 1 10: enable USB host and force UDP/UDM output J state
// 1 11: enable USB host and force UDP/UDM output resume or K state
#define USBHD_UC_INT_BUSY 0x08 // enable automatic responding busy for device mode or automatic pause for host mode during interrupt flag UIF_TRANSFER valid
#define USBHD_UC_RESET_SIE 0x04 // force reset USB SIE, need software clear
#define USBHD_UC_CLR_ALL 0x02 // force clear FIFO and count of USB
#define USBHD_UC_DMA_EN 0x01 // DMA enable and DMA interrupt enable for USB
/* DEVICE USB_CTRL */
#define USBHD_UDEV_CTRL (USBOTG_FS->UDEV_CTRL) // USB device physical prot control
#define USBHD_UD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
#define USBHD_UD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
#define USBHD_UD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
#define USBHD_UD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed
#define USBHD_UD_GP_BIT 0x02 // general purpose bit
#define USBHD_UD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable
/* USB INT EN */
#define USBHD_INT_EN (USBOTG_FS->INT_EN) // USB interrupt enable
#define USBHD_UIE_DEV_SOF 0x80 // enable interrupt for SOF received for USB device mode
#define USBHD_UIE_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode
#define USBHD_UIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow
#define USBHD_UIE_HST_SOF 0x08 // enable interrupt for host SOF timer action for USB host mode
#define USBHD_UIE_SUSPEND 0x04 // enable interrupt for USB suspend or resume event
#define USBHD_UIE_TRANSFER 0x02 // enable interrupt for USB transfer completion
#define USBHD_UIE_DETECT 0x01 // enable interrupt for USB device detected event for USB host mode
#define USBHD_UIE_BUS_RST 0x01 // enable interrupt for USB bus reset event for USB device mode
/* USB_DEV_ADDR */
#define USBHD_DEV_ADDR (USBOTG_FS->DEV_ADDR) // USB device address
#define USBHD_UDA_GP_BIT 0x80 // general purpose bit
#define USBHD_USB_ADDR_MASK 0x7F // bit mask for USB device address
/* USBOTG_FS DEVICE USB_STATUS */
/* USB_MIS_ST */
#define USBHD_MIS_ST (USBOTG_FS->MIS_ST) // USB miscellaneous status
#define USBHD_UMS_SOF_PRES 0x80 // RO, indicate host SOF timer presage status
#define USBHD_UMS_SOF_ACT 0x40 // RO, indicate host SOF timer action status for USB host
#define USBHD_UMS_SIE_FREE 0x20 // RO, indicate USB SIE free status
#define USBHD_UMS_R_FIFO_RDY 0x10 // RO, indicate USB receiving FIFO ready status (not empty)
#define USBHD_UMS_BUS_RESET 0x08 // RO, indicate USB bus reset status
#define USBHD_UMS_SUSPEND 0x04 // RO, indicate USB suspend status
#define USBHD_UMS_DM_LEVEL 0x02 // RO, indicate UDM level saved at device attached to USB host
#define USBHD_UMS_DEV_ATTACH 0x01 // RO, indicate device attached status on USB host
/* USB_INT_FG */
#define USBHD_INT_FG (USBOTG_FS->INT_FG) // USB interrupt flag
#define USBHD_U_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received
#define USBHD_U_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
#define USBHD_U_SIE_FREE 0x20 // RO, indicate USB SIE free status
#define USBHD_UIF_FIFO_OV 0x10 // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear
#define USBHD_UIF_HST_SOF 0x08 // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear
#define USBHD_UIF_SUSPEND 0x04 // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear
#define USBHD_UIF_TRANSFER 0x02 // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear
#define USBHD_UIF_DETECT 0x01 // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear
#define USBHD_UIF_BUS_RST 0x01 // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear
/* USB_INT_ST */
#define USBHD_INT_ST (USBOTG_FS->INT_ST) // USB interrupt flag
#define USBHD_UIS_IS_SETUP 0x80 // RO, indicate current USB transfer is setup received for USB device mode
#define USBHD_UIS_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received for USB device mode
#define USBHD_UIS_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
#define USBHD_UIS_TOKEN1 0x20 // RO, current token PID code bit 1 received for USB device mode
#define USBHD_UIS_TOKEN0 0x10 // RO, current token PID code bit 0 received for USB device mode
#define USBHD_UIS_TOKEN_MASK 0x30 // RO, bit mask of current token PID code received for USB device mode
#define USBHD_UIS_TOKEN_OUT 0x00
#define USBHD_UIS_TOKEN_SOF 0x10
#define USBHD_UIS_TOKEN_IN 0x20
#define USBHD_UIS_TOKEN_SETUP 0x30
// UIS_TOKEN1 & UIS_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 USBHD_UIS_ENDP_MASK 0x0F // RO, bit mask of current transfer endpoint number for USB device mode
/* USB_RX_LEN */
#define USBHD_RX_LEN (USBOTG_FS->Rx_Len) // USB receiving length
/* USB_BUF_MOD */
#define USBHD_UEP4_1_MOD (USBOTG_FS->UEP4_1_MOD) // endpoint 4/1 mode
#define USBHD_UEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT)
#define USBHD_UEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN)
#define USBHD_UEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1
// UEPn_RX_EN & UEPn_TX_EN & UEPn_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 USBHD_UEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT)
#define USBHD_UEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN)
// UEP4_RX_EN & UEP4_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 USBHD_UEP2_3_MOD (USBOTG_FS->UEP2_3_MOD) // endpoint 2/3 mode
#define USBHD_UEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT)
#define USBHD_UEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN)
#define USBHD_UEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3
#define USBHD_UEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT)
#define USBHD_UEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN)
#define USBHD_UEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2
#define USBHD_UEP5_6_MOD (USBOTG_FS->UEP5_6_MOD) // endpoint 5/6 mode
#define USBHD_UEP6_RX_EN 0x80 // enable USB endpoint 6 receiving (OUT)
#define USBHD_UEP6_TX_EN 0x40 // enable USB endpoint 6 transmittal (IN)
#define USBHD_UEP6_BUF_MOD 0x10 // buffer mode of USB endpoint 6
#define USBHD_UEP5_RX_EN 0x08 // enable USB endpoint 5 receiving (OUT)
#define USBHD_UEP5_TX_EN 0x04 // enable USB endpoint 5 transmittal (IN)
#define USBHD_UEP5_BUF_MOD 0x01 // buffer mode of USB endpoint 5
#define USBHD_UEP7_MOD (USBOTG_FS->UEP7_MOD) // endpoint 7 mode
#define USBHD_UEP7_RX_EN 0x08 // enable USB endpoint 7 receiving (OUT)
#define USBHD_UEP7_TX_EN 0x04 // enable USB endpoint 7 transmittal (IN)
#define USBHD_UEP7_BUF_MOD 0x01 // buffer mode of USB endpoint 7
/* USB_DMA */
#define USBHD_UEP0_DMA (USBOTG_FS->UEP0_DMA) // endpoint 0 DMA buffer address
//#define USBHD_UEP1_DMA (USBOTG_FS->UEP1_DMA) // endpoint 1 DMA buffer address
#define USBHD_UEP2_DMA (USBOTG_FS->UEP2_DMA) // endpoint 2 DMA buffer address
//#define USBHD_UEP3_DMA (USBOTG_FS->UEP3_DMA) // endpoint 3 DMA buffer address
//#define USBHD_UEP4_DMA (USBOTG_FS->UEP4_DMA) // endpoint 4 DMA buffer address
//#define USBHD_UEP5_DMA (USBOTG_FS->UEP5_DMA) // endpoint 5 DMA buffer address
//#define USBHD_UEP6_DMA (USBOTG_FS->UEP6_DMA) // endpoint 6 DMA buffer address
//#define USBHD_UEP7_DMA (USBOTG_FS->UEP7_DMA) // endpoint 7 DMA buffer address
/* USB_EP_CTRL */
#define USBHD_UEP0_T_LEN (USBOTG_FS->UEP0_TX_LEN) // endpoint 0 transmittal length
#define USBHD_UEP0_TX_CTRL (USBOTG_FS->UEP0_TX_CTRL) // endpoint 0 control
#define USBHD_UEP0_RX_CTRL (USBOTG_FS->UEP0_RX_CTRL) // endpoint 0 control
//#define USBHD_UEP1_T_LEN (USBOTG_FS->UEP1_TX_LEN) // endpoint 1 transmittal length
//#define USBHD_UEP1_TX_CTRL (USBOTG_FS->UEP1_TX_CTRL) // endpoint 1 control
//#define USBHD_UEP1_RX_CTRL (USBOTG_FS->UEP1_RX_CTRL) // endpoint 1 control
#define USBHD_UEP2_T_LEN (USBOTG_FS->UEP2_TX_LEN) // endpoint 2 transmittal length
#define USBHD_UEP2_TX_CTRL (USBOTG_FS->UEP2_TX_CTRL) // endpoint 2 control
#define USBHD_UEP2_RX_CTRL (USBOTG_FS->UEP2_RX_CTRL) // endpoint 2 control
//#define USBHD_UEP3_T_LEN (USBOTG_FS->UEP3_TX_LEN) // endpoint 3 transmittal length
//#define USBHD_UEP3_TX_CTRL (USBOTG_FS->UEP3_TX_CTRL) // endpoint 3 control
//#define USBHD_UEP3_RX_CTRL (USBOTG_FS->UEP3_RX_CTRL) // endpoint 3 control
//
//#define USBHD_UEP4_T_LEN (USBOTG_FS->UEP4_TX_LEN) // endpoint 4 transmittal length
//#define USBHD_UEP4_TX_CTRL (USBOTG_FS->UEP4_TX_CTRL) // endpoint 4 control
//#define USBHD_UEP4_RX_CTRL (USBOTG_FS->UEP4_RX_CTRL) // endpoint 4 control
//
//#define USBHD_UEP5_T_LEN (USBOTG_FS->UEP5_TX_LEN) // endpoint 5 transmittal length
//#define USBHD_UEP5_TX_CTRL (USBOTG_FS->UEP5_TX_CTRL) // endpoint 5 control
//#define USBHD_UEP5_RX_CTRL (USBOTG_FS->UEP5_RX_CTRL) // endpoint 5 control
//
//#define USBHD_UEP6_T_LEN (USBOTG_FS->UEP6_TX_LEN) // endpoint 6 transmittal length
//#define USBHD_UEP6_TX_CTRL (USBOTG_FS->UEP6_TX_CTRL) // endpoint 6 control
//#define USBHD_UEP6_RX_CTRL (USBOTG_FS->UEP6_RX_CTRL) // endpoint 6 control
//
//#define USBHD_UEP7_T_LEN (USBOTG_FS->UEP7_TX_LEN) // endpoint 7 transmittal length
//#define USBHD_UEP7_TX_CTRL (USBOTG_FS->UEP7_TX_CTRL) // endpoint 7 control
//#define USBHD_UEP7_RX_CTRL (USBOTG_FS->UEP7_RX_CTRL) // endpoint 7 control
#define USBHD_UEP_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
#define USBHD_UEP_R_TOG 0x04 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1
#define USBHD_UEP_T_TOG 0x04 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1
#define USBHD_UEP_R_RES1 0x02 // handshake response type high bit for USB endpoint X receiving (OUT)
#define USBHD_UEP_R_RES0 0x01 // handshake response type low bit for USB endpoint X receiving (OUT)
#define USBHD_UEP_R_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X receiving (OUT)
#define USBHD_UEP_R_RES_ACK 0x00
#define USBHD_UEP_R_RES_TOUT 0x01
#define USBHD_UEP_R_RES_NAK 0x02
#define USBHD_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)
#define USBHD_UEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmittal (IN)
#define USBHD_UEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmittal (IN)
#define USBHD_UEP_T_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN)
#define USBHD_UEP_T_RES_ACK 0x00
#define USBHD_UEP_T_RES_TOUT 0x01
#define USBHD_UEP_T_RES_NAK 0x02
#define USBHD_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: TALL (error)
#ifdef USBHD_HOST
/* USBOTG_FS HOST CONTROL&CFG */
/* HOST USB_CTRL */
#define USBHD_UHOST_CTRL (USBOTG_FS->UDEV_CTRL) // USB host physical prot control
#define USBHD_UH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
#define USBHD_UH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
#define USBHD_UH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
#define USBHD_UH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed
#define USBHD_UH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset
#define USBHD_UH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached
/* USB_INT_ST */
#define USBHD_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
/* USB_BUF_MOD */
#define USBHD_UH_EP_MOD USBHD_UEP2_3_MOD //host endpoint mode
#define USBHD__UH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal
#define USBHD__UH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint
// UH_EP_TX_EN & UH_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 USBHD_UH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving
#define USBHD_UH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint
// UH_EP_RX_EN & UH_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
/* USB_DMA */
#define USBHD_UH_RX_DMA USBHD_UEP2_DMA // host rx endpoint buffer high address
#define USBHD_UH_TX_DMA USBHD_UEP3_DMA // host tx endpoint buffer high address
/* USB_HOST_SETUP */
#define USBHD_UH_SETUP (*((PUINT16V)(0x50000036))) // host aux setup
#define USBHD_UH_PRE_PID_EN 0x0400 // USB host PRE PID enable for low speed device via hub
#define USBHD_UH_SOF_EN 0x04 // USB host automatic SOF enable
#define USBHD_UH_EP_PID USBHD_UEP2_T_LEN // host endpoint and PID
#define USBHD_UH_TOKEN_MASK 0xF0 // bit mask of token PID for USB host transfer
#define USBHD_UH_ENDP_MASK 0x0F // bit mask of endpoint number for USB host transfer
#define USBHD_UH_RX_CTRL USBHD_UEP2_RX_CTRL // host receiver endpoint control
#define USBHD_UH_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
#define USBHD_UH_R_TOG 0x04 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1
#define USBHD_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
#define USBHD_UH_RX_CTRL USBHD_UEP2_RX_CTRL // host receiver endpoint control
#define USBHD_UH_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
#define USBHD_UH_R_TOG 0x04 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1
#define USBHD_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
#define USBHD_UH_TX_LEN USBHD_UEP3_T_LEN // host transmittal endpoint transmittal length
#define USBHD_UH_TX_CTRL USBHD_UEP3_TX_CTRL // host transmittal endpoint control
#define USBHD_UH_T_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
#define USBHD_UH_T_TOG 0x04 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1
#define USBHD_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
#endif
#ifdef USB_OTG
#define USB_OTG_CR (USBOTG_FS->OTG_CR) // usb otg control
#define USB_OTG_CR_SESS 0x20
#define USB_OTG_CR_VBUS 0x10
#define USB_OTG_CR_OTG_EN 0x08
#define USB_OTG_CR_IDPU 0x04
#define USB_OTG_CR_CHARGEVBUS 0x02
#define USB_OTG_CR_DISCHARGEVBUS 0x01
#define USB_OTG_SR (USBOTG_FS->OTG_CR)
#define USB_OTG_SR_VBUS_VLD 0x01
#define USB_OTG_SR_SESS_VLD 0x02
#define USB_OTG_SR_SESS_END 0x04
#define USB_OTG_SR_ID_DIG 0x08
#endif
#ifndef USBHS_EXIST
#define USB_48M_CLK_SRC_MASK (1<<31)
#define USB_48M_CLK_SRC_SYS (0<<31)
#define USB_48M_CLK_SRC_PHY (1<<31)
#define USBHS_PLL_ALIVE (1<<30)
#define USBHS_PLL_CKREF_MASK (3<<28)
#define USBHS_PLL_CKREF_3M (0<<28)
#define USBHS_PLL_CKREF_4M (1<<28)
#define USBHS_PLL_CKREF_8M (2<<28)
#define USBHS_PLL_CKREF_5M (3<<28)
#define USBHS_PLL_SRC_MASK (1<<27)
#define USBHS_PLL_SRC_HSE (0<<27)
#define USBHS_PLL_SRC_HSI (1<<27)
#define USBHS_PLL_SRC_PRE_MASK (7<<24)
#define USBHS_PLL_SRC_PRE_DIV1 (0<<24)
#define USBHS_PLL_SRC_PRE_DIV2 (1<<24)
#define USBHS_PLL_SRC_PRE_DIV3 (2<<24)
#define USBHS_PLL_SRC_PRE_DIV4 (3<<24)
#define USBHS_PLL_SRC_PRE_DIV5 (4<<24)
#define USBHS_PLL_SRC_PRE_DIV6 (5<<24)
#define USBHS_PLL_SRC_PRE_DIV7 (6<<24)
#define DEF_USB_FS_EP_SIZE 64
#endif
#define RCC_USBFS_CLK_DIV_1 (0<<22)
#define RCC_USBFS_CLK_DIV_2 (1<<22)
#define RCC_USBFS_CLK_DIV_3 (2<<22)
#define RCC_USBFS_CLK_SRC (1<<31)
extern PUINT8 pEP0_RAM_Addr; //ep0(64)
extern PUINT8 pEP2_RAM_Addr; //ep2_out(64)+ep2_in(64)
extern volatile UINT8 USBHD_Endp1_Down_Flag;
#define pSetupReqPakHD ((PUSB_SETUP_REQ)pEP0_RAM_Addr)
#define pEP0_DataBuf (pEP0_RAM_Addr)
#define pEP2_OUT_DataBuf (pEP2_RAM_Addr)
#define pEP2_IN_DataBuf (pEP2_RAM_Addr+64)
#define EP2_GetINSta() (R8_UEP2_CTRL&UEP_T_RES_NAK)
extern void DevEP2_OUT_Deal( UINT8 l );
extern void DevEP2_IN_Deal( UINT8 l );
extern void USBDeviceInit( void );
extern void USBOTG_Init( void );
#endif
@@ -0,0 +1,32 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : iap.c
* Author : WCH
* Version : V1.0.0
* Date : 2020/12/16
* Description : CH32F103 fast program
*********************************************************************************
* 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 "flash.h"
#include "string.h"
u32 Verity_buf[32];
/*********************************************************************
* @fn CH32_IAP_Program
*
* @brief adr - the date address
* buf - the date buffer
*
* @return none
*/
void CH32_IAP_Program(u32 adr, u32* buf)
{
FLASH_ProgramPage_Fast(adr, buf);
}
@@ -0,0 +1,22 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : falsh.h
* Author : WCH
* Version : V1.0.0
* Date : 2020/12/16
* 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 __FLASH_H
#define __FLASH_H
#include "ch32v20x_it.h"
#include "stdio.h"
void CH32_IAP_Program(u32 adr, u32* buf);
#endif
@@ -0,0 +1,342 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : iap.c
* Author : WCH
* Version : V1.0.0
* Date : 2020/12/16
* Description : IAP
*********************************************************************************
* 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 "iap.h"
#include "string.h"
#include "flash.h"
#include "core_riscv.h"
#include "usb_istr.h"
#include "usb_lib.h"
/******************************************************************************/
#define FLASH_Base 0x08005000
#define USBD_DATA_SIZE 64
iapfun jump2app;
u32 Program_addr = FLASH_Base;
u32 Verity_addr = FLASH_Base;
u32 User_APP_Addr_offset = 0x5000;
u8 Verity_Star_flag = 0;
u8 Fast_Program_Buf[390];
u32 CodeLen = 0;
u8 End_Flag = 0;
u8 EP2_Rx_Buffer[USBD_DATA_SIZE];
#define isp_cmd_t ((isp_cmd *)EP2_Rx_Buffer)
/*********************************************************************
* @fn RecData_Deal
*
* @brief UART-USB deal date
*
* @return ERR_ERROR - ERROR
* ERR_SCUESS - SCUESS
* ERR_End - End
*/
u8 RecData_Deal(void)
{
u8 i, s, Lenth;
Lenth = isp_cmd_t->Len;
switch ( isp_cmd_t->Cmd) {
case CMD_IAP_ERASE:
FLASH_Unlock_Fast();
s = ERR_SCUESS;
break;
case CMD_IAP_PROM:
for (i = 0; i < Lenth; i++) {
Fast_Program_Buf[CodeLen + i] = isp_cmd_t->data[i];
}
CodeLen += Lenth;
if (CodeLen >= 256) {
FLASH_Unlock_Fast();
FLASH_ErasePage_Fast(Program_addr);
CH32_IAP_Program(Program_addr, (u32*) Fast_Program_Buf);
CodeLen -= 256;
for (i = 0; i < CodeLen; i++) {
Fast_Program_Buf[i] = Fast_Program_Buf[256 + i];
}
Program_addr += 0x100;
}
s = ERR_SCUESS;
break;
case CMD_IAP_VERIFY:
if (Verity_Star_flag == 0) {
Verity_Star_flag = 1;
for (i = 0; i < (256 - CodeLen); i++) {
Fast_Program_Buf[CodeLen + i] = 0xff;
}
FLASH_ErasePage_Fast(Program_addr);
CH32_IAP_Program(Program_addr, (u32*) Fast_Program_Buf);
CodeLen = 0;
}
s = ERR_SCUESS;
for (i = 0; i < Lenth; i++) {
if (isp_cmd_t->data[i] != *(u8*) (Verity_addr + i)) {
s = ERR_ERROR;
break;
}
}
Verity_addr += Lenth;
break;
case CMD_IAP_END:
Verity_Star_flag = 0;
End_Flag = 1;
Program_addr = FLASH_Base;
Verity_addr = FLASH_Base;
s = ERR_End;
break;
default:
s = ERR_ERROR;
break;
}
return s;
}
/*********************************************************************
* @fn EP2_RecData_Deal
*
* @brief EP2 out date deal
*
* @return none
*/
void EP2_IN_Tx_Deal(void)
{
UserToPMABufferCopy(EP2_Tx_Buffer, ENDP2_TXADDR, EP2_Tx_Cnt);
SetEPTxCount(ENDP2, EP2_Tx_Cnt);
SetEPTxValid(ENDP2);
}
/*********************************************************************
* @fn EP2_RecData_Deal
*
* @brief EP2 out date deal
*
* @return none
*/
void EP2_RecData_Deal(void)
{
u8 s;
if(EP2_OUT_Flag){
EP2_OUT_Flag = 0;
EP2_Rx_Cnt = USB_SIL_Read(EP2_OUT, EP2_Rx_Buffer);
s = RecData_Deal();
if(s!=ERR_End){
EP2_Tx_Buffer[0] = 0x00;
if(s==ERR_ERROR) EP2_Tx_Buffer[1] = 0x01; //err
else EP2_Tx_Buffer[1] = 0x00;
EP2_Tx_Cnt = 2;
EP2_IN_Tx_Deal();
}
SetEPRxStatus(ENDP2, EP_RX_VALID);
}
}
/*********************************************************************
* @fn GPIO_Cfg_init
*
* @brief GPIO init
*
* @return none
*/
void GPIO_Cfg_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/*********************************************************************
* @fn PA0_Check
*
* @brief Check PA0 state
*
* @return 1 - IAP
* 0 - APP
*/
u8 PA0_Check(void)
{
u8 i, cnt=0;
GPIO_Cfg_init();
for(i=0; i<10; i++){
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==0) cnt++;
Delay_Ms(5);
}
if(cnt>6) return 0;
else return 1;
}
/*********************************************************************
* @fn USART3_CFG
*
* @brief baudrate:UART3 baudrate
*
* @return none
*/
void USART3_CFG(u32 baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
USART_InitTypeDef USART_InitStructure = {0};
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART3, &USART_InitStructure);
USART_Cmd(USART3, ENABLE);
}
/*********************************************************************
* @fn UART3_SendMultiyData
*
* @brief Deal device Endpoint 3 OUT.
*
* @param l: Data length.
*
* @return none
*/
void UART3_SendMultiyData(u8* pbuf, u8 num)
{
u8 i = 0;
while(i<num)
{
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
USART_SendData(USART3, pbuf[i]);
i++;
}
}
/*********************************************************************
* @fn UART3_SendMultiyData
*
* @brief USART3 send date
*
* @param pbuf - Packet to be sent
* num - the number of date
*
* @return none
*/
void UART3_SendData(u8 data)
{
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
USART_SendData(USART3, data);
}
/*********************************************************************
* @fn Uart3_Rx
*
* @brief Uart3 receive date
*
* @return none
*/
u8 Uart3_Rx(void)
{
while( USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == RESET);
return USART_ReceiveData( USART3);
}
/*********************************************************************
* @fn UART_Rx_Deal
*
* @brief UART Rx data deal
*
* @return none
*/
void UART_Rx_Deal(void)
{
u8 i, s;
u8 Data_add = 0;
if (Uart3_Rx() == Uart_Sync_Head1)
{
if (Uart3_Rx() == Uart_Sync_Head2)
{
isp_cmd_t->Cmd = Uart3_Rx();
Data_add += isp_cmd_t->Cmd;
isp_cmd_t->Len = Uart3_Rx();
Data_add += isp_cmd_t->Len;
isp_cmd_t->Rev[0] = Uart3_Rx();
Data_add += isp_cmd_t->Rev[0];
isp_cmd_t->Rev[1] = Uart3_Rx();
Data_add += isp_cmd_t->Rev[1];
if ((isp_cmd_t->Cmd == CMD_IAP_PROM) || (isp_cmd_t->Cmd == CMD_IAP_VERIFY))
{
for (i = 0; i < isp_cmd_t->Len; i++) {
isp_cmd_t->data[i] = Uart3_Rx();
Data_add += isp_cmd_t->data[i];
}
}
if (Uart3_Rx() == Data_add)
{
s = RecData_Deal();
if (s != ERR_End)
{
UART3_SendData(0x00);
if (s == ERR_ERROR)
{
UART3_SendData(0x01);
}
else
{
UART3_SendData(0x00);
}
}
}
}
}
}
@@ -0,0 +1,68 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : iap.h
* Author : WCH
* Version : V1.0.0
* Date : 2020/12/16
* Description : IAP
*********************************************************************************
* 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 __IAP_H
#define __IAP_H
#include "ch32v20x.h"
#include "stdio.h"
#include "ch32v20x_usbotg_device.h"
#define USBD_DATA_SIZE 64
#define BUILD_UINT16(loByte, hiByte) ((UINT16)(((loByte) & 0x00FF) | (((hiByte) & 0x00FF) << 8)))
#define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3) \
((UINT32)((UINT32)((Byte0) & 0x00FF) \
+ ((((UINT32)Byte1) & 0x00FF) << 8) \
+ ((((UINT32)Byte2) & 0x00FF) << 16) \
+ ((((UINT32)Byte3) & 0x00FF) << 24)))
#define Uart_Sync_Head1 0x57
#define Uart_Sync_Head2 0xab
#define CMD_IAP_PROM 0x80
#define CMD_IAP_ERASE 0x81
#define CMD_IAP_VERIFY 0x82
#define CMD_IAP_END 0x83
#define ERR_SCUESS 0x00
#define ERR_ERROR 0x01
#define ERR_End 0x02
typedef struct __attribute__ ((aligned(4)))_ISP_CMD {
u8 Cmd;
u8 Len;
u8 Rev[2];
u8 data[60];
} isp_cmd;
typedef void (*iapfun)(void);
extern u32 Program_Verity_addr;
extern u32 User_APP_Addr_offset;
extern u8 EP2_IN_Flag;
extern u8 EP2_OUT_Flag;
extern u16 EP2_Rx_Cnt;
extern u8 EP2_Tx_Buffer[2];
extern u16 EP2_Tx_Cnt;
extern u8 EP2_Rx_Buffer[USBD_DATA_SIZE];
u8 RecData_Deal(void);
void GPIO_Cfg_init(void);
u8 PA0_Check(void);
void EP2_RecData_Deal(void);
void EP2_IN_Tx_Deal(void);
void USART3_CFG(u32 baudrate);
void UART_Rx_Deal(void);
#endif
@@ -0,0 +1,90 @@
/********************************** (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
IAP upgrade routine:
Support serial port and USB for FLASH burning
1. Use the IAP download tool to realize the download PA0 floating (default pull-up input)
2. After downloading the APP, connect PA0 to ground (low level input), and press
the reset button to run the APP program.
3. The routine needs to install the CH372 driver.
Note: FLASH operation keeps the frequency below 100Mhz, it is recommended that the main
frequency of IAP be below 100Mhz
*/
#include "debug.h"
#include "ch32v20x_usbotg_device.h"
#include "iap.h"
#include "usb_istr.h"
#include "usb_desc.h"
#include "usb_lib.h"
#include "hw_config.h"
#include "usb_pwr.h"
extern u8 End_Flag;
/*********************************************************************
* @fn IAP_2_APP
*
* @brief IAP_2_APP program.
*
* @return none
*/
void IAP_2_APP(void) {
USB_Port_Set(DISABLE, DISABLE);
USBOTG_H_FS->HOST_CTRL = 0x00;
USBOTG_FS->BASE_CTRL = 0x00;
USBOTG_FS->INT_EN = 0x00;
USBOTG_FS->UEP2_3_MOD = 0x00;
USBOTG_FS->BASE_CTRL |= (1 << 1) | (1 << 2);
Delay_Ms(50);
printf("jump APP\r\n");
Delay_Ms(10);
NVIC_EnableIRQ(Software_IRQn);
NVIC_SetPendingIRQ(Software_IRQn);
}
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void) {
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n", SystemCoreClock);
Set_USBConfig();
USB_Init();
USB_Port_Set(DISABLE, DISABLE);
Delay_Ms(700);
USB_Port_Set(ENABLE, ENABLE);
USB_Interrupts_Config();
USBOTG_Init();
USART3_CFG(57600);
while(1)
{
EP2_RecData_Deal();
if( USART_GetFlagStatus(USART3, USART_FLAG_RXNE) != RESET) {
UART_Rx_Deal();
}
if (End_Flag)
{
Delay_Ms(10);
IAP_2_APP();
while(1);
}
}
}
@@ -0,0 +1,819 @@
/********************************** (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_24MHz 24000000 */
//#define SYSCLK_FREQ_48MHz 48000000
/* #define SYSCLK_FREQ_56MHz 56000000 */
//#define SYSCLK_FREQ_72MHz 72000000
#define SYSCLK_FREQ_96MHz 96000000
//#define SYSCLK_FREQ_120MHz 120000000
//#define SYSCLK_FREQ_144MHz 144000000
/* Clock Definitions */
#ifdef SYSCLK_FREQ_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_24MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_96MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz; /* System Clock Frequency (Core Clock) */
#else /* HSI Selected as System Clock source */
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_24MHz
static void SetSysClockTo24(void);
#elif defined SYSCLK_FREQ_48MHz
static void SetSysClockTo48(void);
#elif defined SYSCLK_FREQ_56MHz
static void SetSysClockTo56(void);
#elif defined SYSCLK_FREQ_72MHz
static void SetSysClockTo72(void);
#elif defined SYSCLK_FREQ_96MHz
static void SetSysClockTo96(void);
#elif defined SYSCLK_FREQ_120MHz
static void SetSysClockTo120(void);
#elif defined SYSCLK_FREQ_144MHz
static void SetSysClockTo144(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_24MHz
SetSysClockTo24();
#elif defined SYSCLK_FREQ_48MHz
SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
#elif defined SYSCLK_FREQ_96MHz
SetSysClockTo96();
#elif defined SYSCLK_FREQ_120MHz
SetSysClockTo120();
#elif defined SYSCLK_FREQ_144MHz
SetSysClockTo144();
#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_24MHz
/*********************************************************************
* @fn SetSysClockTo24
*
* @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo24(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;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 3 = 24 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 3 = 24 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 3 = 24 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_PLLMULL3);
/* 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
/*********************************************************************
* @fn SetSysClockTo48
*
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo48(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
/*********************************************************************
* @fn SetSysClockTo56
*
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo56(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
/*********************************************************************
* @fn SetSysClockTo72
*
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo72(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
/*********************************************************************
* @fn SetSysClockTo96
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo96(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
/*********************************************************************
* @fn SetSysClockTo120
*
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo120(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
/*********************************************************************
* @fn SetSysClockTo144
*
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo144(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
*/
}
}
#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 */