gd32vf103 jump to task success

This commit is contained in:
acevest
2019-09-21 22:29:55 +08:00
parent 86e6f923d7
commit 2d9580cf78
47 changed files with 1892 additions and 7939 deletions

2
.gitignore vendored
View File

@@ -20,7 +20,9 @@
*.dep
*.iex
*.map
*.swp
.DS_Store
board/**/build
board/*/MDK-ARM/DebugConfig/
board/*/obj/
board/*/MDK-ARM/Obj/

View File

@@ -1,146 +0,0 @@
#ifndef _RISCV_CSR_ENCODING_H
#define _RISCV_CSR_ENCODING_H
#define MSTATUS_UIE 0x00000001
#define MSTATUS_SIE 0x00000002
#define MSTATUS_HIE 0x00000004
#define MSTATUS_MIE 0x00000008
#define MSTATUS_UPIE 0x00000010
#define MSTATUS_SPIE 0x00000020
#define MSTATUS_HPIE 0x00000040
#define MSTATUS_MPIE 0x00000080
#define MSTATUS_SPP 0x00000100
#define MSTATUS_MPP 0x00001800
#define MSTATUS_FS 0x00006000
#define MSTATUS_XS 0x00018000
#define MSTATUS_MPRV 0x00020000
#define MSTATUS_PUM 0x00040000
#define MSTATUS_MXR 0x00080000
#define MSTATUS_VM 0x1F000000
#define MSTATUS32_SD 0x80000000
#define MSTATUS64_SD 0x8000000000000000
#define SSTATUS_UIE 0x00000001
#define SSTATUS_SIE 0x00000002
#define SSTATUS_UPIE 0x00000010
#define SSTATUS_SPIE 0x00000020
#define SSTATUS_SPP 0x00000100
#define SSTATUS_FS 0x00006000
#define SSTATUS_XS 0x00018000
#define SSTATUS_PUM 0x00040000
#define SSTATUS32_SD 0x80000000
#define SSTATUS64_SD 0x8000000000000000
#define DCSR_XDEBUGVER (3U<<30)
#define DCSR_NDRESET (1<<29)
#define DCSR_FULLRESET (1<<28)
#define DCSR_EBREAKM (1<<15)
#define DCSR_EBREAKH (1<<14)
#define DCSR_EBREAKS (1<<13)
#define DCSR_EBREAKU (1<<12)
#define DCSR_STOPCYCLE (1<<10)
#define DCSR_STOPTIME (1<<9)
#define DCSR_CAUSE (7<<6)
#define DCSR_DEBUGINT (1<<5)
#define DCSR_HALT (1<<3)
#define DCSR_STEP (1<<2)
#define DCSR_PRV (3<<0)
#define DCSR_CAUSE_NONE 0
#define DCSR_CAUSE_SWBP 1
#define DCSR_CAUSE_HWBP 2
#define DCSR_CAUSE_DEBUGINT 3
#define DCSR_CAUSE_STEP 4
#define DCSR_CAUSE_HALT 5
#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
#define MCONTROL_SELECT (1<<19)
#define MCONTROL_TIMING (1<<18)
#define MCONTROL_ACTION (0x3f<<12)
#define MCONTROL_CHAIN (1<<11)
#define MCONTROL_MATCH (0xf<<7)
#define MCONTROL_M (1<<6)
#define MCONTROL_H (1<<5)
#define MCONTROL_S (1<<4)
#define MCONTROL_U (1<<3)
#define MCONTROL_EXECUTE (1<<2)
#define MCONTROL_STORE (1<<1)
#define MCONTROL_LOAD (1<<0)
#define MCONTROL_TYPE_NONE 0
#define MCONTROL_TYPE_MATCH 2
#define MCONTROL_ACTION_DEBUG_EXCEPTION 0
#define MCONTROL_ACTION_DEBUG_MODE 1
#define MCONTROL_ACTION_TRACE_START 2
#define MCONTROL_ACTION_TRACE_STOP 3
#define MCONTROL_ACTION_TRACE_EMIT 4
#define MCONTROL_MATCH_EQUAL 0
#define MCONTROL_MATCH_NAPOT 1
#define MCONTROL_MATCH_GE 2
#define MCONTROL_MATCH_LT 3
#define MCONTROL_MATCH_MASK_LOW 4
#define MCONTROL_MATCH_MASK_HIGH 5
#define MIP_SSIP (1 << IRQ_S_SOFT)
#define MIP_HSIP (1 << IRQ_H_SOFT)
#define MIP_MSIP (1 << IRQ_M_SOFT)
#define MIP_STIP (1 << IRQ_S_TIMER)
#define MIP_HTIP (1 << IRQ_H_TIMER)
#define MIP_MTIP (1 << IRQ_M_TIMER)
#define MIP_SEIP (1 << IRQ_S_EXT)
#define MIP_HEIP (1 << IRQ_H_EXT)
#define MIP_MEIP (1 << IRQ_M_EXT)
#define MIE_SSIE MIP_SSIP
#define MIE_HSIE MIP_HSIP
#define MIE_MSIE MIP_MSIP
#define MIE_STIE MIP_STIP
#define MIE_HTIE MIP_HTIP
#define MIE_MTIE MIP_MTIP
#define MIE_SEIE MIP_SEIP
#define MIE_HEIE MIP_HEIP
#define MIE_MEIE MIP_MEIP
#define SIP_SSIP MIP_SSIP
#define SIP_STIP MIP_STIP
#define PRV_U 0
#define PRV_S 1
#define PRV_H 2
#define PRV_M 3
#define VM_MBARE 0
#define VM_MBB 1
#define VM_MBBID 2
#define VM_SV32 8
#define VM_SV39 9
#define VM_SV48 10
#define IRQ_S_SOFT 1
#define IRQ_H_SOFT 2
#define IRQ_M_SOFT 3
#define IRQ_S_TIMER 5
#define IRQ_H_TIMER 6
#define IRQ_M_TIMER 7
#define IRQ_S_EXT 9
#define IRQ_H_EXT 10
#define IRQ_M_EXT 11
#define IRQ_COP 12
#define IRQ_HOST 13
#define DEFAULT_RSTVEC 0x00001000
#define DEFAULT_NMIVEC 0x00001004
#define DEFAULT_MTVEC 0x00001010
#define CONFIG_STRING_ADDR 0x0000100C
#define EXT_IO_BASE 0x40000000
#define DRAM_BASE 0x80000000
#endif

View File

@@ -227,8 +227,10 @@ port_irq_context_switch:
.align 2
.global machine_trap_entry
machine_trap_entry:
.global trap_entry
.global irq_entry
trap_entry:
irq_entry:
SAVE_CONTEXT
csrr t0, mepc

View File

@@ -0,0 +1,47 @@
#ifndef INC_TOS_CONFIG_H_
#define INC_TOS_CONFIG_H_
#include "stddef.h"
#define TOS_CFG_TASK_PRIO_MAX 10u // <20><><EFBFBD><EFBFBD>TencentOS tinyĬ<79><C4AC>֧<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD>
#define TOS_CFG_ROUND_ROBIN_EN 0u // <20><><EFBFBD><EFBFBD>TencentOS tiny<6E><79><EFBFBD>ں<EFBFBD><DABA>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>Ƭ<EFBFBD><C6AC>ת
#define TOS_CFG_OBJECT_VERIFY 0u // <20><><EFBFBD><EFBFBD>TencentOS tiny<6E>Ƿ<EFBFBD>У<EFBFBD><D0A3>ָ<EFBFBD><D6B8><EFBFBD>Ϸ<EFBFBD>
#define TOS_CFG_EVENT_EN 1u // TencentOS tiny <20>¼<EFBFBD>ģ<EFBFBD><EFBFBD>ܺ<EFBFBD>
#define TOS_CFG_MMHEAP_EN 1u // <20><><EFBFBD><EFBFBD>TencentOS tiny<6E>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD>ڴ<EFBFBD>ģ<EFBFBD><C4A3>
#define TOS_CFG_MMHEAP_POOL_SIZE 8192 // <20><><EFBFBD><EFBFBD>TencentOS tiny<6E><79>̬<EFBFBD>ڴ<EFBFBD><DAB4>ش<EFBFBD>С
#define TOS_CFG_MUTEX_EN 1u // <20><><EFBFBD><EFBFBD>TencentOS tiny<6E>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>
#define TOS_CFG_QUEUE_EN 1u // <20><><EFBFBD><EFBFBD>TencentOS tiny<6E>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>
#define TOS_CFG_TIMER_EN 0u // <20><><EFBFBD><EFBFBD>TencentOS tiny<6E>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ģ<EFBFBD><C4A3>
#define TOS_CFG_SEM_EN 1u // <20><><EFBFBD><EFBFBD>TencentOS tiny<6E>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD><C5BA><EFBFBD>ģ<EFBFBD><C4A3>
#if (TOS_CFG_QUEUE_EN > 0u)
#define TOS_CFG_MSG_EN 1u
#else
#define TOS_CFG_MSG_EN 0u
#endif
#define TOS_CFG_MSG_POOL_SIZE 10u // <20><><EFBFBD><EFBFBD>TencentOS tiny<6E><79>Ϣ<EFBFBD><CFA2><EFBFBD>д<EFBFBD>С
#define TOS_CFG_IDLE_TASK_STK_SIZE 512u // <20><><EFBFBD><EFBFBD>TencentOS tiny<6E><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB>С
#define TOS_CFG_CPU_TICK_PER_SECOND 1000u // <20><><EFBFBD><EFBFBD>TencentOS tiny<6E><79>tickƵ<6B><C6B5>
#define TOS_CFG_CPU_CLOCK 108000000 // <20><><EFBFBD><EFBFBD>TencentOS tiny CPUƵ<55><C6B5>
#define TOS_CFG_TIMER_AS_PROC 1u // <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>TIMER<45><52><EFBFBD>óɺ<C3B3><C9BA><EFBFBD>ģʽ
#define TOS_CFG_VFS_EN 1u
#define TOS_CFG_MMBLK_EN 1u
#endif /* INC_TOS_CONFIG_H_ */

View File

@@ -0,0 +1,208 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.1626121275">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.1626121275" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<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.debug" cleanCommand="${cross_rm} -rf" description="" id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.1626121275" name="Debug" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug">
<folderInfo id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.1626121275." name="/" resourcePath="">
<toolChain id="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.debug.8330431" name="RISC-V Cross GCC" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.debug">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash.1202731164" name="Create flash image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting.1939916912" name="Create extended listing" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize.662073656" name="Print size" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.1313552818" name="Optimization Level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.none" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength.1404627735" name="Message length (-fmessage-length=0)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar.1267661089" name="'char' is signed (-fsigned-char)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections.1426360736" name="Function sections (-ffunction-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections.759847876" name="Data sections (-fdata-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level.668391469" name="Debug level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level.default" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format.1164967264" name="Debug format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name.1072740689" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name" value="GNU MCU RISC-V GCC" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix.1957750909" name="Prefix" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix" value="riscv-none-embed-" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c.1974277961" name="C compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c" value="gcc" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp.1904763105" name="C++ compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp" value="g++" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar.1687279771" name="Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar" value="ar" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy.990721007" name="Hex/Bin converter" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy" value="objcopy" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump.1007157873" name="Listing generator" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump" value="objdump" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size.2005273946" name="Size command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size" value="size" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make.817675941" name="Build command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make" value="make" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm.1016789776" name="Remove command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm" value="rm" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.id.631765752" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.id" value="512258282" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.base.1350567922" name="Architecture" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.base" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.arch.rv32i" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.multiply.1880868567" name="Multiply extension (RVM)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.multiply" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.atomic.456415389" name="Atomic extension (RVA)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.atomic" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.compressed.2087083466" name="Compressed extension (RVC)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.isa.compressed" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.abi.integer.520770065" name="Integer ABI" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.abi.integer" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.abi.integer.ilp32" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.codemodel.1599179399" name="Code model" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.codemodel" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.target.codemodel.low" valueType="enumerated"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform.1085168581" isAbstract="false" osList="all" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform"/>
<builder buildPath="${workspace_loc:/hello_world}/Debug" id="ilg.gnumcueclipse.managedbuild.cross.riscv.builder.1312339984" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.builder"/>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.933880407" name="GNU RISC-V Cross Assembler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor.525634082" name="Use preprocessor" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor" value="true" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.include.paths.334418871" 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:/hello_world/Application}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/hello_world/GD32VF103_Firmware_Library/RISCV/drivers}&quot;"/>
</option>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input.1565468565" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.578468153" 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.1686562117" name="Include paths (-I)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.include.paths" useByScannerDiscovery="true" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;Z:\workspace\TencentOS-tiny\board\GD32VF103C_START\TOS_CONFIG&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/hello_world/TencentOS_tiny/arch/risc-v/common/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/hello_world/TencentOS_tiny/arch/risc-v/rv32i/gcc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/hello_world/TencentOS_tiny/kernel/core/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/hello_world/TencentOS_tiny/kernel/hal/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/hello_world/TencentOS_tiny/kernel/pm/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/hello_world/GD32VF103_Firmware_Library/RISCV/drivers}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/hello_world/GD32VF103_Firmware_Library/GD32VF103_standard_peripheral/Include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/hello_world/GD32VF103_Firmware_Library/RISCV/stubs}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/hello_world/GD32VF103_Firmware_Library/GD32VF103_standard_peripheral}&quot;"/>
<listOptionValue builtIn="false" value="../."/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs.1188292994" name="Defined symbols (-D)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.compiler.defs" useByScannerDiscovery="true" valueType="definedSymbols">
<listOptionValue builtIn="false" value="GD32VF103C_START"/>
<listOptionValue builtIn="false" value="USE_STDPERIPH_DRIVER"/>
</option>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.750717644" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler.1930629688" 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.1064763742" 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.153022752" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.gcsections" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.usenewlibnano.769188653" 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.nostart.1138121561" 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 IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.scriptfile.134450266" 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}/GD32VF103_Firmware_Library/RISCV/env_Eclipse/GD32VF103xB.lds}&quot;"/>
</option>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.input.316705344" 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.42331133" 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.399385481" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.gcsections" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver.107126240" name="GNU RISC-V Cross Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver"/>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash.950120165" 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.125062338" 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.1032156266" name="Display source (--source|-S)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.source" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders.130399435" name="Display all headers (--all-headers|-x)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle.1410206102" name="Demangle names (--demangle|-C)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers.80630986" name="Display line numbers (--line-numbers|-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide.1257944666" name="Wide lines (--wide|-w)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.printsize.855604372" 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.545311739" name="Size format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.printsize.format"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
<cconfiguration id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.991040509">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.991040509" moduleId="org.eclipse.cdt.core.settings" name="Release">
<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.991040509" name="Release" optionalBuildProperties="" parent="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release">
<folderInfo id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.991040509." name="/" resourcePath="">
<toolChain id="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.release.475921123" name="RISC-V Cross GCC" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.toolchain.elf.release">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash.2095790256" name="Create flash image" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createflash" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting.496100242" name="Create extended listing" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.createlisting" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize.527839441" name="Print size" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.addtools.printsize" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.1036215044" name="Optimization Level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level" value="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.level.size" valueType="enumerated"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength.1566858053" name="Message length (-fmessage-length=0)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.messagelength" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar.313791122" name="'char' is signed (-fsigned-char)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.signedchar" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections.794704205" name="Function sections (-ffunction-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.functionsections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections.1897750591" name="Data sections (-fdata-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.optimization.datasections" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level.1176085190" name="Debug level" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.level"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format.1337198600" name="Debug format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.debugging.format"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name.2061911006" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.toolchain.name" value="GNU MCU RISC-V GCC" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix.1210955802" name="Prefix" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.prefix" value="riscv-none-embed-" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c.847078392" name="C compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.c" value="gcc" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp.1611409518" name="C++ compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.cpp" value="g++" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar.537190966" name="Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.ar" value="ar" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy.2075663864" name="Hex/Bin converter" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objcopy" value="objcopy" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump.718077138" name="Listing generator" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.objdump" value="objdump" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size.893508518" name="Size command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.size" value="size" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make.374071512" name="Build command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.make" value="make" valueType="string"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm.1639653064" name="Remove command" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.command.rm" value="rm" valueType="string"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform.1803353979" isAbstract="false" osList="all" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.targetPlatform"/>
<builder buildPath="${workspace_loc:/hello_world}/Release" id="ilg.gnumcueclipse.managedbuild.cross.riscv.builder.230771356" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.builder"/>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.1428729449" name="GNU RISC-V Cross Assembler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler">
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor.52580663" name="Use preprocessor" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.assembler.usepreprocessor" value="true" valueType="boolean"/>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input.1643948477" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.assembler.input"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.552753469" name="GNU RISC-V Cross C Compiler" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler">
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.2138673318" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.cpp.compiler.718172304" 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.1287109288" 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.1718779452" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.c.linker.gcsections" value="true" valueType="boolean"/>
<inputType id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.linker.input.1022093215" 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.240769017" 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.1440099990" name="Remove unused sections (-Xlinker --gc-sections)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.cpp.linker.gcsections" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver.1053336007" name="GNU RISC-V Cross Archiver" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.archiver"/>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.createflash.1841998771" 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.544284869" 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.1246759690" name="Display source (--source|-S)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.source" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders.776860234" name="Display all headers (--all-headers|-x)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.allheaders" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle.573544221" name="Demangle names (--demangle|-C)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.demangle" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers.112752514" name="Display line numbers (--line-numbers|-l)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.linenumbers" value="true" valueType="boolean"/>
<option id="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide.619039696" name="Wide lines (--wide|-w)" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.createlisting.wide" value="true" valueType="boolean"/>
</tool>
<tool id="ilg.gnumcueclipse.managedbuild.cross.riscv.tool.printsize.384827639" 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.1267897822" name="Size format" superClass="ilg.gnumcueclipse.managedbuild.cross.riscv.option.printsize.format"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="hello_world.ilg.gnumcueclipse.managedbuild.cross.riscv.target.elf.976385475" name="Executable" 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.1626121275;ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.1626121275.;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.578468153;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.750717644">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.991040509;ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.991040509.;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.552753469;ilg.gnumcueclipse.managedbuild.cross.riscv.tool.c.compiler.input.2138673318">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/hello_world"/>
</configuration>
<configuration configurationName="Release">
<resource resourceType="PROJECT" workspacePath="/hello_world"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
</cproject>

View File

@@ -0,0 +1 @@
/Debug/

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>hello_world</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<linkedResources>
<link>
<name>Application</name>
<type>2</type>
<locationURI>virtual:/virtual</locationURI>
</link>
<link>
<name>GD32VF103_Firmware_Library</name>
<type>2</type>
<location>Z:/workspace/TencentOS-tiny/platform/vendor_bsp/gd/GD32VF103_Firmware_Library</location>
</link>
<link>
<name>TencentOS_tiny</name>
<type>2</type>
<locationURI>virtual:/virtual</locationURI>
</link>
<link>
<name>Application/tos_config.h</name>
<type>1</type>
<location>Z:/workspace/TencentOS-tiny/board/GD32VF103C_START/TOS_CONFIG/tos_config.h</location>
</link>
<link>
<name>TencentOS_tiny/arch</name>
<type>2</type>
<locationURI>virtual:/virtual</locationURI>
</link>
<link>
<name>TencentOS_tiny/kernel</name>
<type>2</type>
<location>Z:/workspace/TencentOS-tiny/kernel</location>
</link>
<link>
<name>TencentOS_tiny/arch/risc-v</name>
<type>2</type>
<location>Z:/workspace/TencentOS-tiny/arch/risc-v</location>
</link>
</linkedResources>
</projectDescription>

View File

@@ -0,0 +1,2 @@
eclipse.preferences.version=1
install.folder=C\:\\ToolChain\\OpenOCD\\0.10.0-12-20190722-0746\\bin

View File

@@ -0,0 +1,2 @@
buildTools.path=C\:\\ToolChain\\Build Tools\\2.10-20180103-1919\\bin
eclipse.preferences.version=1

View File

@@ -0,0 +1,2 @@
eclipse.preferences.version=1
toolchain.path.512258282=C\:\\ToolChain\\RISC-V Embedded GCC\\8.2.0-2.2-20190521-0004\\bin

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.debug.1626121275" name="Debug">
<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="-431627395592245746" 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>
<configuration id="ilg.gnumcueclipse.managedbuild.cross.riscv.config.elf.release.991040509" name="Release">
<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="-428852719970927202" 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>

View File

@@ -1,8 +1,8 @@
/*!
\file usbh_transc.h
\brief USB host mode transactions header file
\file gd32vf103_libopt.h
\brief library optional for gd32vf103
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
\version 2019-6-5, V1.0.0, demo for GD32VF103
*/
/*
@@ -32,23 +32,30 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI
OF SUCH DAMAGE.
*/
#ifndef __USBH_TRANSC_H
#define __USBH_TRANSC_H
#ifndef GD32VF103_LIBOPT_H
#define GD32VF103_LIBOPT_H
#include "usb_conf.h"
#include "usbh_core.h"
/* send the setup packet to the USB device */
usbh_status usbh_ctlsetup_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num);
/* send a data packet to the USB device */
usbh_status usbh_data_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len);
/* receive a data packet from the USB device */
usbh_status usbh_data_recev (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len);
/* USB control transfer handler */
usbh_status usbh_ctl_handler (usb_core_driver *pudev, usbh_host *puhost);
#endif /* __USBH_TRANSC_H */
#include "gd32vf103_adc.h"
#include "gd32vf103_bkp.h"
#include "gd32vf103_can.h"
#include "gd32vf103_crc.h"
#include "gd32vf103_dac.h"
#include "gd32vf103_dma.h"
#include "gd32vf103_eclic.h"
#include "gd32vf103_exmc.h"
#include "gd32vf103_exti.h"
#include "gd32vf103_fmc.h"
#include "gd32vf103_gpio.h"
#include "gd32vf103_i2c.h"
#include "gd32vf103_fwdgt.h"
#include "gd32vf103_dbg.h"
#include "gd32vf103_pmu.h"
#include "gd32vf103_rcu.h"
#include "gd32vf103_rtc.h"
#include "gd32vf103_spi.h"
#include "gd32vf103_timer.h"
#include "gd32vf103_usart.h"
#include "gd32vf103_wwdgt.h"
#include "n200_func.h"
#endif /* GD32VF103_LIBOPT_H */

View File

@@ -0,0 +1,88 @@
#include "gd32vf103.h"
#include "tos.h"
void delay_1ms(uint32_t count)
{
uint64_t start_mtime, delta_mtime;
/* don't start measuruing until we see an mtime tick */
uint64_t tmp = get_timer_value();
do{
start_mtime = get_timer_value();
}while(start_mtime == tmp);
do{
delta_mtime = get_timer_value() - start_mtime;
}while(delta_mtime <(SystemCoreClock/4000.0 *count));
}
#define TASK_SIZE 512
k_task_t k_task_task1;
k_task_t k_task_task2;
uint8_t k_task1_stk[TASK_SIZE];
uint8_t k_task2_stk[TASK_SIZE];
int share = 123;
void task1(void *pdata)
{
int t1 = 0;
while(1)
{
t1++;
share++;
//k_tick_t delay = tos_millisec2tick(10);
gpio_bit_write(GPIOA, GPIO_PIN_7, (bit_status)(1-gpio_input_bit_get(GPIOA, GPIO_PIN_7)));
tos_task_delay(1000);
//tos_task_yield();
//osDelay(10);
//asm("wfi;");
}
}
void task2(void *pdata)
{
int t2 = 0;
while(1)
{
t2--;
share--;
//tos_task_delay(10);
tos_task_yield();
asm("wfi;");
}
}
void main(void) {
rcu_periph_clock_enable(RCU_GPIOA);
/* configure LED GPIO port */
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
gpio_bit_reset(GPIOA, GPIO_PIN_7);
tos_knl_init();
tos_task_create(&k_task_task1, "task1", task1, NULL, 3, k_task1_stk, TASK_SIZE, 0);
tos_task_create(&k_task_task2, "task2", task2, NULL, 3, k_task2_stk, TASK_SIZE, 0);
tos_knl_start();
int c = 0;
while(1)
{
c++;
asm("wfi;");
}
while(1){
/* insert 500 ms delay */
delay_1ms(1000);
/* toggle the LED */
gpio_bit_write(GPIOA, GPIO_PIN_7, (bit_status)(1-gpio_input_bit_get(GPIOA, GPIO_PIN_7)));
/* insert 500 ms delay */
delay_1ms(1000);
}
}

View File

@@ -0,0 +1,46 @@
adapter_khz 1000
reset_config srst_only
adapter_nsrst_assert_width 100
interface cmsis-dap
transport select jtag
autoexit true
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x1000563d
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 20480 -work-area-backup 0
# Work-area is a space in RAM used for flash programming
if { [info exists WORKAREASIZE] } {
set _WORKAREASIZE $WORKAREASIZE
} else {
set _WORKAREASIZE 0x5000
}
# Allow overriding the Flash bank size
if { [info exists FLASH_SIZE] } {
set _FLASH_SIZE $FLASH_SIZE
} else {
# autodetect size
set _FLASH_SIZE 0
}
# flash size will be probed
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME gd32vf103 0x08000000 0 0 0 $_TARGETNAME
#flash bank $_FLASHNAME stm32f103 0x08000000 0 0 0 $_TARGETNAME
riscv set_reset_timeout_sec 10
init
halt

View File

@@ -108,6 +108,7 @@ KERNEL_INC = \
-I $(TOP_DIR)/kernel/hal/include \
-I $(TOP_DIR)/arch/risc-v/common/include \
-I $(TOP_DIR)/arch/risc-v/rv32i/gcc \
-I $(TOP_DIR)/platform/vendor_bsp/gd/GD32VF103_Firmware_Library/RISCV/drivers \
-I $(TOP_DIR)/board/QEMU_Spike/TOS-CONFIG
C_INCLUDES += $(KERNEL_INC)
CMSIS_INC =

View File

@@ -9,7 +9,7 @@ _start:
csrc mstatus, MSTATUS_MIE
csrw mie, 0
la t0, machine_trap_entry
la t0, trap_entry
csrw mtvec, t0
la sp, _stack_top

View File

@@ -110,6 +110,8 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/demo/TencentOS_tiny/arch/risc-v/common/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/demo/TencentOS_tiny/arch/risc-v/rv32i/gcc}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/demo/Inc}&quot;"/>
</option>

View File

@@ -24,11 +24,6 @@
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<linkedResources>
<link>
<name>Inc</name>
<type>2</type>
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/Inc</locationURI>
</link>
<link>
<name>Src</name>
<type>2</type>

View File

@@ -11,7 +11,7 @@
<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="1359335743052093289" 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">
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="1344499799506608699" 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"/>

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@ _start:
csrc mstatus, MSTATUS_MIE
csrw mie, 0
la t0, machine_trap_entry
la t0, trap_entry
csrw mtvec, t0
la sp, _stack_top

View File

@@ -1,117 +0,0 @@
/*!
\file drv_usb_core.h
\brief USB core low level driver header file
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __DRV_USB_CORE_H
#define __DRV_USB_CORE_H
#include "drv_usb_regs.h"
#include "usb_ch9_std.h"
#define USB_FS_EP0_MAX_LEN 64U /* maximum packet size of EndPoint0 */
#define HC_MAX_PACKET_COUNT 140U /* maximum packet count */
#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) /* endpoint number */
#define EP_DIR(x) ((uint8_t)((x) >> 7)) /* endpoint direction */
enum _usb_eptype {
USB_EPTYPE_CTRL = 0U, /*!< control endpoint type */
USB_EPTYPE_ISOC = 1U, /*!< isochronous endpoint type */
USB_EPTYPE_BULK = 2U, /*!< bulk endpoint type */
USB_EPTYPE_INTR = 3U, /*!< interrupt endpoint type */
USB_EPTYPE_MASK = 3U, /*!< endpoint type mask */
};
typedef enum
{
USB_OTG_OK = 0, /*!< USB OTG status OK*/
USB_OTG_FAIL /*!< USB OTG status fail*/
} usb_otg_status;
typedef enum
{
USB_OK = 0, /*!< USB status OK*/
USB_FAIL /*!< USB status fail*/
} usb_status;
typedef enum
{
USB_USE_FIFO, /*!< USB use FIFO transfer mode */
USB_USE_DMA /*!< USB use DMA transfer mode */
} usb_transfer_mode;
typedef struct
{
uint8_t core_enum; /*!< USB core type */
uint8_t core_speed; /*!< USB core speed */
uint8_t num_pipe; /*!< USB host channel numbers */
uint8_t num_ep; /*!< USB device endpoint numbers */
uint8_t transfer_mode; /*!< USB transfer mode */
uint8_t phy_itf; /*!< USB core PHY interface */
uint8_t sof_enable; /*!< USB SOF output */
uint8_t low_power; /*!< USB low power */
} usb_core_basic;
/* function declarations */
/* config core capabilities */
usb_status usb_basic_init (usb_core_basic *usb_basic,
usb_core_regs *usb_regs,
usb_core_enum usb_core);
/*initializes the USB controller registers and prepares the core device mode or host mode operation*/
usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs);
/* read a packet from the Rx FIFO associated with the endpoint */
void *usb_rxfifo_read (usb_core_regs *core_regs, uint8_t *dest_buf, uint16_t byte_count);
/* write a packet into the Tx FIFO associated with the endpoint */
usb_status usb_txfifo_write (usb_core_regs *usb_regs,
uint8_t *src_buf,
uint8_t fifo_num,
uint16_t byte_count);
/* flush a Tx FIFO or all Tx FIFOs */
usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num);
/* flush the entire Rx FIFO */
usb_status usb_rxfifo_flush (usb_core_regs *usb_regs);
/* get the global interrupts */
static inline uint32_t usb_coreintr_get(usb_core_regs *usb_regs)
{
return usb_regs->gr->GINTEN & usb_regs->gr->GINTF;
}
#endif /* __DRV_USB_CORE_H */

View File

@@ -1,217 +0,0 @@
/*!
\file drv_usb_dev.h
\brief USB device low level driver header file
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __DRV_USB_DEV_H
#define __DRV_USB_DEV_H
#include "drv_usb_core.h"
enum usb_ctl_status {
USB_CTL_IDLE = 0U, /*!< USB control transfer idle state */
USB_CTL_DATA_IN, /*!< USB control transfer data in state */
USB_CTL_LAST_DATA_IN, /*!< USB control transfer last data in state */
USB_CTL_DATA_OUT, /*!< USB control transfer data out state */
USB_CTL_LAST_DATA_OUT, /*!< USB control transfer last data out state */
USB_CTL_STATUS_IN, /*!< USB control transfer status in state*/
USB_CTL_STATUS_OUT /*!< USB control transfer status out state */
};
#define EP_IN(x) ((uint8_t)(0x80U | (x))) /*!< device IN endpoint */
#define EP_OUT(x) ((uint8_t)(x)) /*!< device OUT endpoint */
/* USB descriptor */
typedef struct _usb_desc {
uint8_t *dev_desc; /*!< device descriptor */
uint8_t *config_desc; /*!< config descriptor */
uint8_t *bos_desc; /*!< BOS descriptor */
void* const *strings; /*!< string descriptor */
} usb_desc;
/* USB power management */
typedef struct _usb_pm {
uint8_t power_mode; /*!< power mode */
uint8_t power_low; /*!< power low */
uint8_t dev_remote_wakeup; /*!< remote wakeup */
uint8_t remote_wakeup_on; /*!< remote wakeup on */
} usb_pm;
/* USB control information */
typedef struct _usb_control {
usb_req req; /*!< USB standard device request */
uint8_t ctl_state; /*!< USB control transfer state */
uint8_t ctl_zlp; /*!< zero lenth package */
} usb_control;
typedef struct
{
struct {
uint8_t num: 4; /*!< the endpoint number.it can be from 0 to 6 */
uint8_t pad: 3; /*!< padding between number and direction */
uint8_t dir: 1; /*!< the endpoint direction */
} ep_addr;
uint8_t ep_type; /*!< USB endpoint type */
uint8_t ep_stall; /*!< USB endpoint stall status */
uint8_t frame_num; /*!< number of frame */
uint16_t max_len; /*!< Maximum packet lenth */
/* transaction level variables */
uint8_t *xfer_buf; /*!< transmit buffer */
uint32_t xfer_len; /*!< transmit buffer length */
uint32_t xfer_count; /*!< transmit buffer count */
uint32_t remain_len; /*!< remain packet lenth */
uint32_t dma_addr; /*!< DMA address */
} usb_transc;
typedef struct _usb_core_driver usb_dev;
typedef struct _usb_class_core
{
uint8_t command; /*!< device class request command */
uint8_t alter_set; /*!< alternative set */
uint8_t (*init) (usb_dev *udev, uint8_t config_index); /*!< initialize handler */
uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); /*!< de-initialize handler */
uint8_t (*req_proc) (usb_dev *udev, usb_req *req); /*!< device request handler */
uint8_t (*data_in) (usb_dev *udev, uint8_t ep_num); /*!< device data in handler */
uint8_t (*data_out) (usb_dev *udev, uint8_t ep_num); /*!< device data out handler */
uint8_t (*SOF) (usb_dev *udev); /*!< Start of frame handler */
uint8_t (*incomplete_isoc_in) (usb_dev *udev); /*!< Incomplete synchronization IN transfer handler */
uint8_t (*incomplete_isoc_out) (usb_dev *udev); /*!< Incomplete synchronization OUT transfer handler */
} usb_class_core;
typedef struct _usb_perp_dev
{
uint8_t config; /*!< configuration */
uint8_t dev_addr; /*!< device address */
__IO uint8_t cur_status; /*!< current status */
__IO uint8_t backup_status; /*!< backup status */
usb_transc transc_in[USBFS_MAX_TX_FIFOS]; /*!< endpoint IN transaction */
usb_transc transc_out[USBFS_MAX_TX_FIFOS]; /*!< endpoint OUT transaction */
usb_pm pm; /*!< power management */
usb_desc desc; /*!< USB descriptors */
usb_control control; /*!< USB control information */
usb_class_core *class_core; /*!< class driver */
} usb_perp_dev;
typedef struct _usb_core_driver
{
usb_core_basic bp; /*!< USB basic parameters */
usb_core_regs regs; /*!< USB registers */
usb_perp_dev dev; /*!< USB peripheral device */
} usb_core_driver;
/* function declarations */
/* initialize USB core registers for device mode */
usb_status usb_devcore_init (usb_core_driver *udev);
/* enable the USB device mode interrupts */
usb_status usb_devint_enable (usb_core_driver *udev);
/* active the usb transaction */
usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc);
/* deactive the usb transaction */
usb_status usb_transc_deactivate (usb_core_driver *udev, usb_transc *transc);
/* configure usb transaction to start IN transfer */
usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc);
/* configure usb transaction to start OUT transfer */
usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc);
/* set the usb transaction STALL status */
usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc);
/* clear the usb transaction STALL status */
usb_status usb_transc_clrstall (usb_core_driver *udev, usb_transc *transc);
/* read device all OUT endpoint interrupt register */
uint32_t usb_oepintnum_read (usb_core_driver *udev);
/* read device OUT endpoint interrupt flag register */
uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num);
/* read device all IN endpoint interrupt register */
uint32_t usb_iepintnum_read (usb_core_driver *udev);
/* read device IN endpoint interrupt flag register */
uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num);
/* config the USB device to be disconnected */
void usb_dev_disconnect (usb_core_driver *udev);
/* config the USB device to be connected */
void usb_dev_connect (usb_core_driver *udev);
/* set the USB device address */
void usb_devaddr_set (usb_core_driver *pudev, uint8_t dev_addr);
/* configures OUT endpoint 0 to receive SETUP packets */
void usb_ctlep_startout (usb_core_driver *udev);
/* active remote wakeup signalling */
void usb_rwkup_active (usb_core_driver *udev);
/* reset remote wakeup signalling */
void usb_rwkup_reset (usb_core_driver *udev);
/* set remote wakeup signalling */
void usb_rwkup_set (usb_core_driver *udev);
/* active USB core clock */
void usb_clock_active (usb_core_driver *udev);
/* usb device suspend */
void usb_dev_suspend (usb_core_driver *udev);
/* stop the device and clean up fifos */
void usb_dev_stop (usb_core_driver *udev);
#endif /* __DRV_USB_DEV_H */

View File

@@ -1,175 +0,0 @@
/*!
\file drv_usb_host.h
\brief USB host mode low level driver header file
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __DRV_USB_HOST_H
#define __DRV_USB_HOST_H
#include "drv_usb_regs.h"
#include "usb_ch9_std.h"
#include "drv_usb_core.h"
typedef enum _usb_pipe_status
{
PIPE_IDLE = 0U,
PIPE_XF,
PIPE_HALTED,
PIPE_NAK,
PIPE_NYET,
PIPE_STALL,
PIPE_TRACERR,
PIPE_BBERR,
PIPE_REQOVR,
PIPE_DTGERR,
} usb_pipe_staus;
typedef enum _usb_pipe_mode
{
PIPE_PERIOD = 0U,
PIPE_NON_PERIOD = 1U
} usb_pipe_mode;
typedef enum _usb_urb_state
{
URB_IDLE = 0U,
URB_DONE,
URB_NOTREADY,
URB_ERROR,
URB_STALL
} usb_urb_state;
typedef struct _usb_pipe
{
uint8_t in_used;
uint8_t dev_addr;
uint32_t dev_speed;
struct {
uint8_t num;
uint8_t dir;
uint8_t type;
uint16_t mps;
} ep;
uint8_t ping;
uint32_t DPID;
uint8_t *xfer_buf;
uint32_t xfer_len;
uint32_t xfer_count;
uint8_t data_toggle_in;
uint8_t data_toggle_out;
__IO uint32_t err_count;
__IO usb_pipe_staus pp_status;
__IO usb_urb_state urb_state;
} usb_pipe;
typedef struct _usb_host_drv
{
uint8_t rx_buf[512U];
__IO uint32_t connect_status;
__IO uint32_t port_enabled;
__IO uint32_t backup_xfercount[USBFS_MAX_TX_FIFOS];
usb_pipe pipe[USBFS_MAX_TX_FIFOS];
} usb_host_drv;
typedef struct _usb_core_driver
{
usb_core_basic bp;
usb_core_regs regs;
usb_host_drv host;
} usb_core_driver;
/* initializes USB core for host mode */
usb_status usb_host_init (usb_core_driver *pudev);
/* initialize host pipe */
usb_status usb_pipe_init (usb_core_driver *pudev, uint8_t pipe_num);
/* prepare host pipe for transferring packets */
usb_status usb_pipe_xfer (usb_core_driver *pudev, uint8_t pipe_num);
/* halt host pipe */
usb_status usb_pipe_halt (usb_core_driver *pudev, uint8_t pipe_num);
/* configure host pipe to do ping operation */
usb_status usb_pipe_ping (usb_core_driver *pudev, uint8_t pipe_num);
/* reset host port */
uint32_t usb_port_reset (usb_core_driver *pudev);
/* control the VBUS to power */
void usb_portvbus_switch (usb_core_driver *pudev, uint8_t state);
/* stop the USB host and clean up FIFO */
void usb_host_stop (usb_core_driver *pudev);
//__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *pudev)
uint32_t usb_frame_even (usb_core_driver *pudev);
//{
// return !(pudev->regs.hr->HFINFR & 0x01U);
//}
//__STATIC_INLINE void usb_phyclock_config (usb_core_driver *pudev, uint8_t clock)
void usb_phyclock_config (usb_core_driver *pudev, uint8_t clock) ;
//{
//pudev->regs.hr->HCTL &= ~HCTL_CLKSEL;
// pudev->regs.hr->HCTL |= clock;
//}
uint32_t usb_port_read (usb_core_driver *pudev);
//inline uint32_t usb_port_read (usb_core_driver *pudev)
//{
// return *pudev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC);
//}
uint32_t usb_curspeed_get (usb_core_driver *pudev);
//inline uint32_t usb_curspeed_get (usb_core_driver *pudev)
//{
// return *pudev->regs.HPCS & HPCS_PS;
//}
//__STATIC_INLINE uint32_t usb_curframe_get (usb_core_driver *pudev)
uint32_t usb_curframe_get (usb_core_driver *pudev);
//{
// return (pudev->regs.hr->HFINFR & 0xFFFFU);
//}
#endif /* __DRV_USB_HOST_H */

View File

@@ -1,62 +0,0 @@
/*!
\file drv_usb_hw.h
\brief usb hardware configuration header file
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __DRV_USB_HW_H
#define __DRV_USB_HW_H
#include "usb_conf.h"
/* configure USB clock */
void usb_rcu_config (void);
/* configure USB interrupt */
void usb_intr_config (void);
/* initializes delay unit using Timer2 */
void usb_timer_init (void);
/* delay in micro seconds */
void usb_udelay (const uint32_t usec);
/* delay in milli seconds */
void usb_mdelay (const uint32_t msec);
#ifdef USE_HOST_MODE
/* configure USB VBus */
void usb_vbus_config (void);
/* drive usb VBus */
void usb_vbus_drive (uint8_t State);
#endif /* USE_HOST_MODE */
#endif /* __DRV_USB_HW_H */

View File

@@ -1,666 +0,0 @@
/*!
\file drv_usb_regs.h
\brief USB cell registers definition and handle macros
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __DRV_USB_REGS_H
#define __DRV_USB_REGS_H
#include "usb_conf.h"
#define USBHS_REG_BASE 0x40040000L /*!< base address of USBHS registers */
#define USBFS_REG_BASE 0x50000000L /*!< base address of USBFS registers */
#define USBFS_MAX_TX_FIFOS 15 /*!< FIFO number */
#define USBFS_MAX_PACKET_SIZE 64U /*!< USBFS max packet size */
#define USBFS_MAX_CHANNEL_COUNT 8U /*!< USBFS host channel count */
#define USBFS_MAX_EP_COUNT 4U /*!< USBFS device endpoint count */
#define USBFS_MAX_FIFO_WORDLEN 320U /*!< USBFS max fifo size in words */
#define USBHS_MAX_PACKET_SIZE 512U /*!< USBHS max packet size */
#define USBHS_MAX_CHANNEL_COUNT 12U /*!< USBHS host channel count */
#define USBHS_MAX_EP_COUNT 6U /*!< USBHS device endpoint count */
#define USBHS_MAX_FIFO_WORDLEN 1280U /*!< USBHS max fifo size in words */
#define USB_DATA_FIFO_OFFSET 0x1000U /*!< USB data fifo offset */
#define USB_DATA_FIFO_SIZE 0x1000U /*!< USB data fifo size */
typedef enum
{
USB_CORE_ENUM_HS = 0, /*!< USB core type is HS */
USB_CORE_ENUM_FS = 1 /*!< USB core type is FS */
} usb_core_enum;
enum usb_reg_offset {
USB_REG_OFFSET_CORE = 0x0000U, /*!< global OTG control and status register */
USB_REG_OFFSET_DEV = 0x0800U, /*!< device mode control and status registers */
USB_REG_OFFSET_EP = 0x0020U,
USB_REG_OFFSET_EP_IN = 0x0900U, /*!< device IN endpoint 0 control register */
USB_REG_OFFSET_EP_OUT = 0x0B00U, /*!< device OUT endpoint 0 control register */
USB_REG_OFFSET_HOST = 0x0400U, /*!< host control register */
USB_REG_OFFSET_CH = 0x0020U,
USB_REG_OFFSET_PORT = 0x0440U, /*!< host port control and status register */
USB_REG_OFFSET_CH_INOUT = 0x0500U, /*!< Host channel-x control registers */
USB_REG_OFFSET_PWRCLKCTL = 0x0E00U, /*!< power and clock register */
};
typedef struct
{
__IO uint32_t GOTGCS; /*!< USB global OTG control and status register 000h */
__IO uint32_t GOTGINTF; /*!< USB global OTG interrupt flag register 004h */
__IO uint32_t GAHBCS; /*!< USB global AHB control and status register 008h */
__IO uint32_t GUSBCS; /*!< USB global USB control and status register 00Ch */
__IO uint32_t GRSTCTL; /*!< USB global reset control register 010h */
__IO uint32_t GINTF; /*!< USB global interrupt flag register 014h */
__IO uint32_t GINTEN; /*!< USB global interrupt enable register 018h */
__IO uint32_t GRSTATR; /*!< USB receive status debug read register 01Ch */
__IO uint32_t GRSTATP; /*!< USB receive status and pop register 020h */
__IO uint32_t GRFLEN; /*!< USB global receive FIFO length register 024h */
__IO uint32_t DIEP0TFLEN_HNPTFLEN; /*!< USB device IN endpoint 0/host non-periodic transmit FIFO length register 028h */
__IO uint32_t HNPTFQSTAT; /*!< USB host non-periodic FIFO/queue status register 02Ch */
uint32_t Reserved30[2]; /*!< Reserved 030h */
__IO uint32_t GCCFG; /*!< USB global core configuration register 038h */
__IO uint32_t CID; /*!< USB core ID register 03Ch */
uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */
__IO uint32_t HPTFLEN; /*!< USB host periodic transmit FIFO length register 100h */
__IO uint32_t DIEPTFLEN[15]; /*!< USB device IN endpoint transmit FIFO length register 104h */
} usb_gr;
typedef struct
{
__IO uint32_t HCTL; /*!< USB host control register 400h */
__IO uint32_t HFT; /*!< USB host frame interval register 404h */
__IO uint32_t HFINFR; /*!< USB host frame information remaining register 408h */
uint32_t Reserved40C; /*!< Reserved 40Ch */
__IO uint32_t HPTFQSTAT; /*!< USB host periodic transmit FIFO/queue status register 410h */
__IO uint32_t HACHINT; /*!< USB host all channels interrupt register 414h */
__IO uint32_t HACHINTEN; /*!< USB host all channels interrupt enable register 418h */
} usb_hr;
typedef struct
{
__IO uint32_t HCHCTL; /*!< USB host channel control register 500h */
__IO uint32_t HCHSTCTL; /*!< Reserved 504h */
__IO uint32_t HCHINTF; /*!< USB host channel interrupt flag register 508h */
__IO uint32_t HCHINTEN; /*!< USB host channel interrupt enable register 50Ch */
__IO uint32_t HCHLEN; /*!< USB host channel transfer length register 510h */
__IO uint32_t HCHDMAADDR; /*!< USB host channel-x DMA address register 514h*/
uint32_t Reserved[2];
} usb_pr;
typedef struct
{
__IO uint32_t DCFG; /*!< USB device configuration register 800h */
__IO uint32_t DCTL; /*!< USB device control register 804h */
__IO uint32_t DSTAT; /*!< USB device status register 808h */
uint32_t Reserved0C; /*!< Reserved 80Ch */
__IO uint32_t DIEPINTEN; /*!< USB device IN endpoint common interrupt enable register 810h */
__IO uint32_t DOEPINTEN; /*!< USB device OUT endpoint common interrupt enable register 814h */
__IO uint32_t DAEPINT; /*!< USB device all endpoints interrupt register 818h */
__IO uint32_t DAEPINTEN; /*!< USB device all endpoints interrupt enable register 81Ch */
uint32_t Reserved20; /*!< Reserved 820h */
uint32_t Reserved24; /*!< Reserved 824h */
__IO uint32_t DVBUSDT; /*!< USB device VBUS discharge time register 828h */
__IO uint32_t DVBUSPT; /*!< USB device VBUS pulsing time register 82Ch */
__IO uint32_t DTHRCTL; /*!< dev thr 830h */
__IO uint32_t DIEPFEINTEN; /*!< USB Device IN endpoint FIFO empty interrupt enable register 834h */
__IO uint32_t DEP1INT; /*!< USB device endpoint 1 interrupt register 838h */
__IO uint32_t DEP1INTEN; /*!< USB device endpoint 1 interrupt enable register 83Ch */
uint32_t Reserved40; /*!< Reserved 840h */
__IO uint32_t DIEP1INTEN; /*!< USB device IN endpoint-1 interrupt enable register 844h */
uint32_t Reserved48[15]; /*!< Reserved 848-880h */
__IO uint32_t DOEP1INTEN; /*!< USB device OUT endpoint-1 interrupt enable register 884h */
} usb_dr;
typedef struct
{
__IO uint32_t DIEPCTL; /*!< USB device IN endpoint control register 900h + (EpNum * 20h) + 00h */
uint32_t Reserved04; /*!< Reserved 900h + (EpNum * 20h) + 04h */
__IO uint32_t DIEPINTF; /*!< USB device IN endpoint interrupt flag register 900h + (EpNum * 20h) + 08h */
uint32_t Reserved0C; /*!< Reserved 900h + (EpNum * 20h) + 0Ch */
__IO uint32_t DIEPLEN; /*!< USB device IN endpoint transfer length register 900h + (EpNum * 20h) + 10h */
__IO uint32_t DIEPDMAADDR; /*!< Device IN endpoint-x DMA address register 900h + (EpNum * 20h) + 14h */
__IO uint32_t DIEPTFSTAT; /*!< USB device IN endpoint transmit FIFO status register 900h + (EpNum * 20h) + 18h */
} usb_erin;
typedef struct
{
__IO uint32_t DOEPCTL; /*!< USB device IN endpoint control register B00h + (EpNum * 20h) + 00h */
uint32_t Reserved04; /*!< Reserved B00h + (EpNum * 20h) + 04h */
__IO uint32_t DOEPINTF; /*!< USB device IN endpoint interrupt flag register B00h + (EpNum * 20h) + 08h */
uint32_t Reserved0C; /*!< Reserved B00h + (EpNum * 20h) + 0Ch */
__IO uint32_t DOEPLEN; /*!< USB device IN endpoint transfer length register B00h + (EpNum * 20h) + 10h */
__IO uint32_t DOEPDMAADDR; /*!< Device OUT endpoint-x DMA address register B00h + (EpNum * 20h) + 0Ch */
} usb_erout;
typedef struct _usb_regs
{
usb_gr *gr; /*!< USBFS global registers */
usb_dr *dr; /*!< Device control and status registers */
usb_hr *hr; /*!< Host control and status registers */
usb_erin *er_in[6]; /*!< USB device IN endpoint register */
usb_erout *er_out[6]; /*!< USB device OUT endpoint register */
usb_pr *pr[15]; /*!< USB Host channel-x control register */
__IO uint32_t *HPCS; /*!< USB host port control and status register */
__IO uint32_t *DFIFO[USBFS_MAX_TX_FIFOS];
__IO uint32_t *PWRCLKCTL; /*!< USB power and clock control register */
} usb_core_regs;
/* global OTG control and status register bits definitions */
#define GOTGCS_BSV BIT(19) /*!< B-Session Valid */
#define GOTGCS_ASV BIT(18) /*!< A-session valid */
#define GOTGCS_DI BIT(17) /*!< debounce interval */
#define GOTGCS_CIDPS BIT(16) /*!< id pin status */
#define GOTGCS_DHNPEN BIT(11) /*!< device HNP enable */
#define GOTGCS_HHNPEN BIT(10) /*!< host HNP enable */
#define GOTGCS_HNPREQ BIT(9) /*!< HNP request */
#define GOTGCS_HNPS BIT(8) /*!< HNP successes */
#define GOTGCS_SRPREQ BIT(1) /*!< SRP request */
#define GOTGCS_SRPS BIT(0) /*!< SRP successes */
/* global OTG interrupt flag register bits definitions */
#define GOTGINTF_DF BIT(19) /*!< debounce finish */
#define GOTGINTF_ADTO BIT(18) /*!< A-device timeout */
#define GOTGINTF_HNPDET BIT(17) /*!< host negotiation request detected */
#define GOTGINTF_HNPEND BIT(9) /*!< HNP end */
#define GOTGINTF_SRPEND BIT(8) /*!< SRP end */
#define GOTGINTF_SESEND BIT(2) /*!< session end */
/* global AHB control and status register bits definitions */
#define GAHBCS_PTXFTH BIT(8) /*!< periodic Tx FIFO threshold */
#define GAHBCS_TXFTH BIT(7) /*!< tx FIFO threshold */
#define GAHBCS_DMAEN BIT(5) /*!< DMA function Enable */
#define GAHBCS_BURST BITS(1, 4) /*!< the AHB burst type used by DMA */
#define GAHBCS_GINTEN BIT(0) /*!< global interrupt enable */
/* global USB control and status register bits definitions */
#define GUSBCS_FDM BIT(30) /*!< force device mode */
#define GUSBCS_FHM BIT(29) /*!< force host mode */
#define GUSBCS_ULPIEOI BIT(21) /*!< ULPI external over-current indicator */
#define GUSBCS_ULPIEVD BIT(20) /*!< ULPI external VBUS driver */
#define GUSBCS_UTT BITS(10, 13) /*!< USB turnaround time */
#define GUSBCS_HNPCEN BIT(9) /*!< HNP capability enable */
#define GUSBCS_SRPCEN BIT(8) /*!< SRP capability enable */
#define GUSBCS_EMBPHY BIT(6) /*!< embedded PHY selected */
#define GUSBCS_TOC BITS(0, 2) /*!< timeout calibration */
/* global reset control register bits definitions */
#define GRSTCTL_DMAIDL BIT(31) /*!< DMA idle state */
#define GRSTCTL_DMABSY BIT(30) /*!< DMA busy */
#define GRSTCTL_TXFNUM BITS(6, 10) /*!< tx FIFO number */
#define GRSTCTL_TXFF BIT(5) /*!< tx FIFO flush */
#define GRSTCTL_RXFF BIT(4) /*!< rx FIFO flush */
#define GRSTCTL_HFCRST BIT(2) /*!< host frame counter reset */
#define GRSTCTL_HCSRST BIT(1) /*!< HCLK soft reset */
#define GRSTCTL_CSRST BIT(0) /*!< core soft reset */
/* global interrupt flag register bits definitions */
#define GINTF_WKUPIF BIT(31) /*!< wakeup interrupt flag */
#define GINTF_SESIF BIT(30) /*!< session interrupt flag */
#define GINTF_DISCIF BIT(29) /*!< disconnect interrupt flag */
#define GINTF_IDPSC BIT(28) /*!< id pin status change */
#define GINTF_PTXFEIF BIT(26) /*!< periodic tx FIFO empty interrupt flag */
#define GINTF_HCIF BIT(25) /*!< host channels interrupt flag */
#define GINTF_HPIF BIT(24) /*!< host port interrupt flag */
#define GINTF_PXNCIF BIT(21) /*!< periodic transfer not complete interrupt flag */
#define GINTF_ISOONCIF BIT(21) /*!< isochronous OUT transfer not complete interrupt flag */
#define GINTF_ISOINCIF BIT(20) /*!< isochronous IN transfer not complete interrupt flag */
#define GINTF_OEPIF BIT(19) /*!< OUT endpoint interrupt flag */
#define GINTF_IEPIF BIT(18) /*!< IN endpoint interrupt flag */
#define GINTF_EOPFIF BIT(15) /*!< end of periodic frame interrupt flag */
#define GINTF_ISOOPDIF BIT(14) /*!< isochronous OUT packet dropped interrupt flag */
#define GINTF_ENUMFIF BIT(13) /*!< enumeration finished */
#define GINTF_RST BIT(12) /*!< USB reset */
#define GINTF_SP BIT(11) /*!< USB suspend */
#define GINTF_ESP BIT(10) /*!< early suspend */
#define GINTF_GONAK BIT(7) /*!< global OUT NAK effective */
#define GINTF_GNPINAK BIT(6) /*!< global IN non-periodic NAK effective */
#define GINTF_NPTXFEIF BIT(5) /*!< non-periodic tx FIFO empty interrupt flag */
#define GINTF_RXFNEIF BIT(4) /*!< rx FIFO non-empty interrupt flag */
#define GINTF_SOF BIT(3) /*!< start of frame */
#define GINTF_OTGIF BIT(2) /*!< OTG interrupt flag */
#define GINTF_MFIF BIT(1) /*!< mode fault interrupt flag */
#define GINTF_COPM BIT(0) /*!< current operation mode */
/* global interrupt enable register bits definitions */
#define GINTEN_WKUPIE BIT(31) /*!< wakeup interrupt enable */
#define GINTEN_SESIE BIT(30) /*!< session interrupt enable */
#define GINTEN_DISCIE BIT(29) /*!< disconnect interrupt enable */
#define GINTEN_IDPSCIE BIT(28) /*!< id pin status change interrupt enable */
#define GINTEN_PTXFEIE BIT(26) /*!< periodic tx FIFO empty interrupt enable */
#define GINTEN_HCIE BIT(25) /*!< host channels interrupt enable */
#define GINTEN_HPIE BIT(24) /*!< host port interrupt enable */
#define GINTEN_IPXIE BIT(21) /*!< periodic transfer not complete interrupt enable */
#define GINTEN_ISOONCIE BIT(21) /*!< isochronous OUT transfer not complete interrupt enable */
#define GINTEN_ISOINCIE BIT(20) /*!< isochronous IN transfer not complete interrupt enable */
#define GINTEN_OEPIE BIT(19) /*!< OUT endpoints interrupt enable */
#define GINTEN_IEPIE BIT(18) /*!< IN endpoints interrupt enable */
#define GINTEN_EOPFIE BIT(15) /*!< end of periodic frame interrupt enable */
#define GINTEN_ISOOPDIE BIT(14) /*!< isochronous OUT packet dropped interrupt enable */
#define GINTEN_ENUMFIE BIT(13) /*!< enumeration finish enable */
#define GINTEN_RSTIE BIT(12) /*!< USB reset interrupt enable */
#define GINTEN_SPIE BIT(11) /*!< USB suspend interrupt enable */
#define GINTEN_ESPIE BIT(10) /*!< early suspend interrupt enable */
#define GINTEN_GONAKIE BIT(7) /*!< global OUT NAK effective interrupt enable */
#define GINTEN_GNPINAKIE BIT(6) /*!< global non-periodic IN NAK effective interrupt enable */
#define GINTEN_NPTXFEIE BIT(5) /*!< non-periodic Tx FIFO empty interrupt enable */
#define GINTEN_RXFNEIE BIT(4) /*!< receive FIFO non-empty interrupt enable */
#define GINTEN_SOFIE BIT(3) /*!< start of frame interrupt enable */
#define GINTEN_OTGIE BIT(2) /*!< OTG interrupt enable */
#define GINTEN_MFIE BIT(1) /*!< mode fault interrupt enable */
/* global receive status read and pop register bits definitions */
#define GRSTATRP_RPCKST BITS(17, 20) /*!< received packet status */
#define GRSTATRP_DPID BITS(15, 16) /*!< data PID */
#define GRSTATRP_BCOUNT BITS(4, 14) /*!< byte count */
#define GRSTATRP_CNUM BITS(0, 3) /*!< channel number */
#define GRSTATRP_EPNUM BITS(0, 3) /*!< endpoint number */
/* global receive FIFO length register bits definitions */
#define GRFLEN_RXFD BITS(0, 15) /*!< rx FIFO depth */
/* host non-periodic transmit FIFO length register bits definitions */
#define HNPTFLEN_HNPTXFD BITS(16, 31) /*!< non-periodic Tx FIFO depth */
#define HNPTFLEN_HNPTXRSAR BITS(0, 15) /*!< non-periodic Tx RAM start address */
/**
* @brief USB IN endpoint 0 transmit FIFO length register bits definitions
*/
#define DIEP0TFLEN_IEP0TXFD BITS(16, 31) /*!< IN Endpoint 0 Tx FIFO depth */
#define DIEP0TFLEN_IEP0TXRSAR BITS(0, 15) /*!< IN Endpoint 0 TX RAM start address */
/* host non-periodic transmit FIFO/queue status register bits definitions */
#define HNPTFQSTAT_NPTXRQTOP BITS(24, 30) /*!< top entry of the non-periodic Tx request queue */
#define HNPTFQSTAT_NPTXRQS BITS(16, 23) /*!< non-periodic Tx request queue space */
#define HNPTFQSTAT_NPTXFS BITS(0, 15) /*!< non-periodic Tx FIFO space */
#define HNPTFQSTAT_CNUM BITS(27, 30) /*!< channel number*/
#define HNPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */
#define HNPTFQSTAT_TYPE BITS(25, 26) /*!< token type */
#define HNPTFQSTAT_TMF BIT(24) /*!< terminate flag */
/* global core configuration register bits definitions */
#define GCCFG_VBUSIG BIT(21) /*!< vbus ignored */
#define GCCFG_SOFOEN BIT(20) /*!< SOF output enable */
#define GCCFG_VBUSBCEN BIT(19) /*!< the VBUS B-device comparer enable */
#define GCCFG_VBUSACEN BIT(18) /*!< the VBUS A-device comparer enable */
#define GCCFG_PWRON BIT(16) /*!< power on */
/* core ID register bits definitions */
#define CID_CID BITS(0, 31) /*!< core ID */
/* host periodic transmit FIFO length register bits definitions */
#define HPTFLEN_HPTXFD BITS(16, 31) /*!< host periodic Tx FIFO depth */
#define HPTFLEN_HPTXFSAR BITS(0, 15) /*!< host periodic Tx RAM start address */
/* device IN endpoint transmit FIFO length register bits definitions */
#define DIEPTFLEN_IEPTXFD BITS(16, 31) /*!< IN endpoint Tx FIFO x depth */
#define DIEPTFLEN_IEPTXRSAR BITS(0, 15) /*!< IN endpoint FIFOx Tx x RAM start address */
/* host control register bits definitions */
#define HCTL_SPDFSLS BIT(2) /*!< speed limited to FS and LS */
#define HCTL_CLKSEL BITS(0, 1) /*!< clock select for USB clock */
/* host frame interval register bits definitions */
#define HFT_FRI BITS(0, 15) /*!< frame interval */
/* host frame information remaining register bits definitions */
#define HFINFR_FRT BITS(16, 31) /*!< frame remaining time */
#define HFINFR_FRNUM BITS(0, 15) /*!< frame number */
/* host periodic transmit FIFO/queue status register bits definitions */
#define HPTFQSTAT_PTXREQT BITS(24, 31) /*!< top entry of the periodic Tx request queue */
#define HPTFQSTAT_PTXREQS BITS(16, 23) /*!< periodic Tx request queue space */
#define HPTFQSTAT_PTXFS BITS(0, 15) /*!< periodic Tx FIFO space */
#define HPTFQSTAT_OEFRM BIT(31) /*!< odd/eveb frame */
#define HPTFQSTAT_CNUM BITS(27, 30) /*!< channel number */
#define HPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */
#define HPTFQSTAT_TYPE BITS(25, 26) /*!< token type */
#define HPTFQSTAT_TMF BIT(24) /*!< terminate flag */
#define TFQSTAT_TXFS BITS(0, 15)
#define TFQSTAT_CNUM BITS(27, 30)
/* host all channels interrupt register bits definitions */
#define HACHINT_HACHINT BITS(0, 11) /*!< host all channel interrupts */
/* host all channels interrupt enable register bits definitions */
#define HACHINTEN_CINTEN BITS(0, 11) /*!< channel interrupt enable */
/* host port control and status register bits definitions */
#define HPCS_PS BITS(17, 18) /*!< port speed */
#define HPCS_PP BIT(12) /*!< port power */
#define HPCS_PLST BITS(10, 11) /*!< port line status */
#define HPCS_PRST BIT(8) /*!< port reset */
#define HPCS_PSP BIT(7) /*!< port suspend */
#define HPCS_PREM BIT(6) /*!< port resume */
#define HPCS_PEDC BIT(3) /*!< port enable/disable change */
#define HPCS_PE BIT(2) /*!< port enable */
#define HPCS_PCD BIT(1) /*!< port connect detected */
#define HPCS_PCST BIT(0) /*!< port connect status */
/* host channel-x control register bits definitions */
#define HCHCTL_CEN BIT(31) /*!< channel enable */
#define HCHCTL_CDIS BIT(30) /*!< channel disable */
#define HCHCTL_ODDFRM BIT(29) /*!< odd frame */
#define HCHCTL_DAR BITS(22, 28) /*!< device address */
#define HCHCTL_MPC BITS(20, 21) /*!< multiple packet count */
#define HCHCTL_EPTYPE BITS(18, 19) /*!< endpoint type */
#define HCHCTL_LSD BIT(17) /*!< low-speed device */
#define HCHCTL_EPDIR BIT(15) /*!< endpoint direction */
#define HCHCTL_EPNUM BITS(11, 14) /*!< endpoint number */
#define HCHCTL_MPL BITS(0, 10) /*!< maximum packet length */
/* host channel-x split transaction register bits definitions */
#define HCHSTCTL_SPLEN BIT(31) /*!< enable high-speed split transaction */
#define HCHSTCTL_CSPLT BIT(16) /*!< complete-split enable */
#define HCHSTCTL_ISOPCE BITS(14, 15) /*!< isochronous OUT payload continuation encoding */
#define HCHSTCTL_HADDR BITS(7, 13) /*!< HUB address */
#define HCHSTCTL_PADDR BITS(0, 6) /*!< port address */
/* host channel-x interrupt flag register bits definitions */
#define HCHINTF_DTER BIT(10) /*!< data toggle error */
#define HCHINTF_REQOVR BIT(9) /*!< request queue overrun */
#define HCHINTF_BBER BIT(8) /*!< babble error */
#define HCHINTF_USBER BIT(7) /*!< USB bus Error */
#define HCHINTF_NYET BIT(6) /*!< NYET */
#define HCHINTF_ACK BIT(5) /*!< ACK */
#define HCHINTF_NAK BIT(4) /*!< NAK */
#define HCHINTF_STALL BIT(3) /*!< STALL */
#define HCHINTF_DMAER BIT(2) /*!< DMA error */
#define HCHINTF_CH BIT(1) /*!< channel halted */
#define HCHINTF_TF BIT(0) /*!< transfer finished */
/* host channel-x interrupt enable register bits definitions */
#define HCHINTEN_DTERIE BIT(10) /*!< data toggle error interrupt enable */
#define HCHINTEN_REQOVRIE BIT(9) /*!< request queue overrun interrupt enable */
#define HCHINTEN_BBERIE BIT(8) /*!< babble error interrupt enable */
#define HCHINTEN_USBERIE BIT(7) /*!< USB bus error interrupt enable */
#define HCHINTEN_NYETIE BIT(6) /*!< NYET interrupt enable */
#define HCHINTEN_ACKIE BIT(5) /*!< ACK interrupt enable */
#define HCHINTEN_NAKIE BIT(4) /*!< NAK interrupt enable */
#define HCHINTEN_STALLIE BIT(3) /*!< STALL interrupt enable */
#define HCHINTEN_DMAERIE BIT(2) /*!< DMA error interrupt enable */
#define HCHINTEN_CHIE BIT(1) /*!< channel halted interrupt enable */
#define HCHINTEN_TFIE BIT(0) /*!< transfer finished interrupt enable */
/* host channel-x transfer length register bits definitions */
#define HCHLEN_PING BIT(31) /*!< PING token request */
#define HCHLEN_DPID BITS(29, 30) /*!< data PID */
#define HCHLEN_PCNT BITS(19, 28) /*!< packet count */
#define HCHLEN_TLEN BITS(0, 18) /*!< transfer length */
/* host channel-x DMA address register bits definitions */
#define HCHDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */
#define PORT_SPEED(x) (((uint32_t)(x) << 17) & HPCS_PS) /*!< Port speed */
#define PORT_SPEED_HIGH PORT_SPEED(0) /*!< high speed */
#define PORT_SPEED_FULL PORT_SPEED(1) /*!< full speed */
#define PORT_SPEED_LOW PORT_SPEED(2) /*!< low speed */
#define PIPE_CTL_DAR(x) (((uint32_t)(x) << 22) & HCHCTL_DAR) /*!< device address */
#define PIPE_CTL_EPTYPE(x) (((uint32_t)(x) << 18) & HCHCTL_EPTYPE) /*!< endpoint type */
#define PIPE_CTL_EPNUM(x) (((uint32_t)(x) << 11) & HCHCTL_EPNUM) /*!< endpoint number */
#define PIPE_CTL_EPDIR(x) (((uint32_t)(x) << 15) & HCHCTL_EPDIR) /*!< endpoint direction */
#define PIPE_CTL_EPMPL(x) (((uint32_t)(x) << 0) & HCHCTL_MPL) /*!< maximum packet length */
#define PIPE_CTL_LSD(x) (((uint32_t)(x) << 17) & HCHCTL_LSD) /*!< low-Speed device */
#define PIPE_XFER_PCNT(x) (((uint32_t)(x) << 19) & HCHLEN_PCNT) /*!< packet count */
#define PIPE_XFER_DPID(x) (((uint32_t)(x) << 29) & HCHLEN_DPID) /*!< data PID */
#define PIPE_DPID_DATA0 PIPE_XFER_DPID(0) /*!< DATA0 */
#define PIPE_DPID_DATA1 PIPE_XFER_DPID(2) /*!< DATA1 */
#define PIPE_DPID_DATA2 PIPE_XFER_DPID(1) /*!< DATA2 */
#define PIPE_DPID_SETUP PIPE_XFER_DPID(3) /*!< MDATA (non-control)/SETUP (control) */
extern const uint32_t PIPE_DPID[];
/* device configuration registers bits definitions */
#define DCFG_EOPFT BITS(11, 12) /*!< end of periodic frame time */
#define DCFG_DAR BITS(4, 10) /*!< device address */
#define DCFG_NZLSOH BIT(2) /*!< non-zero-length status OUT handshake */
#define DCFG_DS BITS(0, 1) /*!< device speed */
/* device control registers bits definitions */
#define DCTL_POIF BIT(11) /*!< power-on initialization finished */
#define DCTL_CGONAK BIT(10) /*!< clear global OUT NAK */
#define DCTL_SGONAK BIT(9) /*!< set global OUT NAK */
#define DCTL_CGINAK BIT(8) /*!< clear global IN NAK */
#define DCTL_SGINAK BIT(7) /*!< set global IN NAK */
#define DCTL_GONS BIT(3) /*!< global OUT NAK status */
#define DCTL_GINS BIT(2) /*!< global IN NAK status */
#define DCTL_SD BIT(1) /*!< soft disconnect */
#define DCTL_RWKUP BIT(0) /*!< remote wakeup */
/* device status registers bits definitions */
#define DSTAT_FNRSOF BITS(8, 21) /*!< the frame number of the received SOF. */
#define DSTAT_ES BITS(1, 2) /*!< enumerated speed */
#define DSTAT_SPST BIT(0) /*!< suspend status */
/* device IN endpoint common interrupt enable registers bits definitions */
#define DIEPINTEN_NAKEN BIT(13) /*!< NAK handshake sent by USBHS interrupt enable bit */
#define DIEPINTEN_TXFEEN BIT(7) /*!< transmit FIFO empty interrupt enable bit */
#define DIEPINTEN_IEPNEEN BIT(6) /*!< IN endpoint NAK effective interrupt enable bit */
#define DIEPINTEN_EPTXFUDEN BIT(4) /*!< endpoint Tx FIFO underrun interrupt enable bit */
#define DIEPINTEN_CITOEN BIT(3) /*!< control In Timeout interrupt enable bit */
#define DIEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */
#define DIEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */
/* device OUT endpoint common interrupt enable registers bits definitions */
#define DOEPINTEN_NYETEN BIT(14) /*!< NYET handshake is sent interrupt enable bit */
#define DOEPINTEN_BTBSTPEN BIT(6) /*!< back-to-back SETUP packets interrupt enable bit */
#define DOEPINTEN_EPRXFOVREN BIT(4) /*!< endpoint Rx FIFO overrun interrupt enable bit */
#define DOEPINTEN_STPFEN BIT(3) /*!< SETUP phase finished interrupt enable bit */
#define DOEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */
#define DOEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */
/* device all endpoints interrupt registers bits definitions */
#define DAEPINT_OEPITB BITS(16, 21) /*!< device all OUT endpoint interrupt bits */
#define DAEPINT_IEPITB BITS(0, 5) /*!< device all IN endpoint interrupt bits */
/* device all endpoints interrupt enable registers bits definitions */
#define DAEPINTEN_OEPIE BITS(16, 21) /*!< OUT endpoint interrupt enable */
#define DAEPINTEN_IEPIE BITS(0, 3) /*!< IN endpoint interrupt enable */
/* device Vbus discharge time registers bits definitions */
#define DVBUSDT_DVBUSDT BITS(0, 15) /*!< device VBUS discharge time */
/* device Vbus pulsing time registers bits definitions */
#define DVBUSPT_DVBUSPT BITS(0, 11) /*!< device VBUS pulsing time */
/* device IN endpoint FIFO empty interrupt enable register bits definitions */
#define DIEPFEINTEN_IEPTXFEIE BITS(0, 5) /*!< IN endpoint Tx FIFO empty interrupt enable bits */
/* device endpoint 0 control register bits definitions */
#define DEP0CTL_EPEN BIT(31) /*!< endpoint enable */
#define DEP0CTL_EPD BIT(30) /*!< endpoint disable */
#define DEP0CTL_SNAK BIT(27) /*!< set NAK */
#define DEP0CTL_CNAK BIT(26) /*!< clear NAK */
#define DIEP0CTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */
#define DEP0CTL_STALL BIT(21) /*!< STALL handshake */
#define DOEP0CTL_SNOOP BIT(20) /*!< snoop mode */
#define DEP0CTL_EPTYPE BITS(18, 19) /*!< endpoint type */
#define DEP0CTL_NAKS BIT(17) /*!< NAK status */
#define DEP0CTL_EPACT BIT(15) /*!< endpoint active */
#define DEP0CTL_MPL BITS(0, 1) /*!< maximum packet length */
/* device endpoint x control register bits definitions */
#define DEPCTL_EPEN BIT(31) /*!< endpoint enable */
#define DEPCTL_EPD BIT(30) /*!< endpoint disable */
#define DEPCTL_SODDFRM BIT(29) /*!< set odd frame */
#define DEPCTL_SD1PID BIT(29) /*!< set DATA1 PID */
#define DEPCTL_SEVNFRM BIT(28) /*!< set even frame */
#define DEPCTL_SD0PID BIT(28) /*!< set DATA0 PID */
#define DEPCTL_SNAK BIT(27) /*!< set NAK */
#define DEPCTL_CNAK BIT(26) /*!< clear NAK */
#define DIEPCTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */
#define DEPCTL_STALL BIT(21) /*!< STALL handshake */
#define DOEPCTL_SNOOP BIT(20) /*!< snoop mode */
#define DEPCTL_EPTYPE BITS(18, 19) /*!< endpoint type */
#define DEPCTL_NAKS BIT(17) /*!< NAK status */
#define DEPCTL_EOFRM BIT(16) /*!< even/odd frame */
#define DEPCTL_DPID BIT(16) /*!< endpoint data PID */
#define DEPCTL_EPACT BIT(15) /*!< endpoint active */
#define DEPCTL_MPL BITS(0, 10) /*!< maximum packet length */
/* device IN endpoint-x interrupt flag register bits definitions */
#define DIEPINTF_NAK BIT(13) /*!< NAK handshake sent by USBHS */
#define DIEPINTF_TXFE BIT(7) /*!< transmit FIFO empty */
#define DIEPINTF_IEPNE BIT(6) /*!< IN endpoint NAK effective */
#define DIEPINTF_EPTXFUD BIT(4) /*!< endpoint Tx FIFO underrun */
#define DIEPINTF_CITO BIT(3) /*!< control In Timeout interrupt */
#define DIEPINTF_EPDIS BIT(1) /*!< endpoint disabled */
#define DIEPINTF_TF BIT(0) /*!< transfer finished */
/* device OUT endpoint-x interrupt flag register bits definitions */
#define DOEPINTF_NYET BIT(14) /*!< NYET handshake is sent */
#define DOEPINTF_BTBSTP BIT(6) /*!< back-to-back SETUP packets */
#define DOEPINTF_EPRXFOVR BIT(4) /*!< endpoint Rx FIFO overrun */
#define DOEPINTF_STPF BIT(3) /*!< SETUP phase finished */
#define DOEPINTF_EPDIS BIT(1) /*!< endpoint disabled */
#define DOEPINTF_TF BIT(0) /*!< transfer finished */
/* device IN endpoint 0 transfer length register bits definitions */
#define DIEP0LEN_PCNT BITS(19, 20) /*!< packet count */
#define DIEP0LEN_TLEN BITS(0, 6) /*!< transfer length */
/* device OUT endpoint 0 transfer length register bits definitions */
#define DOEP0LEN_STPCNT BITS(29, 30) /*!< SETUP packet count */
#define DOEP0LEN_PCNT BIT(19) /*!< packet count */
#define DOEP0LEN_TLEN BITS(0, 6) /*!< transfer length */
/* device OUT endpoint-x transfer length register bits definitions */
#define DOEPLEN_RXDPID BITS(29, 30) /*!< received data PID */
#define DOEPLEN_STPCNT BITS(29, 30) /*!< SETUP packet count */
#define DIEPLEN_MCNT BITS(29, 30) /*!< multi count */
#define DEPLEN_PCNT BITS(19, 28) /*!< packet count */
#define DEPLEN_TLEN BITS(0, 18) /*!< transfer length */
/* device IN endpoint-x DMA address register bits definitions */
#define DIEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */
/* device OUT endpoint-x DMA address register bits definitions */
#define DOEPDMAADDR_DMAADDR BITS(0, 31) /*!< DMA address */
/* device IN endpoint-x transmit FIFO status register bits definitions */
#define DIEPTFSTAT_IEPTFS BITS(0, 15) /*!< IN endpoint Tx FIFO space remaining */
/* USB power and clock registers bits definition */
#define PWRCLKCTL_SHCLK BIT(1) /*!< stop HCLK */
#define PWRCLKCTL_SUCLK BIT(0) /*!< stop the USB clock */
#define RSTAT_GOUT_NAK 1U /* global OUT NAK (triggers an interrupt) */
#define RSTAT_DATA_UPDT 2U /* OUT data packet received */
#define RSTAT_XFER_COMP 3U /* OUT transfer completed (triggers an interrupt) */
#define RSTAT_SETUP_COMP 4U /* SETUP transaction completed (triggers an interrupt) */
#define RSTAT_SETUP_UPDT 6U /* SETUP data packet received */
#define DSTAT_EM_HS_PHY_30MHZ_60MHZ 0U /* USB enumerate speed use high-speed PHY clock in 30MHz or 60MHz */
#define DSTAT_EM_FS_PHY_30MHZ_60MHZ 1U /* USB enumerate speed use full-speed PHY clock in 30MHz or 60MHz */
#define DSTAT_EM_LS_PHY_6MHZ 2U /* USB enumerate speed use low-speed PHY clock in 6MHz */
#define DSTAT_EM_FS_PHY_48MHZ 3U /* USB enumerate speed use full-speed PHY clock in 48MHz */
#define DPID_DATA0 0U /* device endpoint data PID is DATA0 */
#define DPID_DATA1 2U /* device endpoint data PID is DATA1 */
#define DPID_DATA2 1U /* device endpoint data PID is DATA2 */
#define DPID_MDATA 3U /* device endpoint data PID is MDATA */
#define GAHBCS_DMAINCR(regval) (GAHBCS_BURST & ((regval) << 1U)) /*!< AHB burst type used by DMA*/
#define DMA_INCR0 GAHBCS_DMAINCR(0U) /*!< single burst type used by DMA*/
#define DMA_INCR1 GAHBCS_DMAINCR(1U) /*!< 4-beat incrementing burst type used by DMA*/
#define DMA_INCR4 GAHBCS_DMAINCR(3U) /*!< 8-beat incrementing burst type used by DMA*/
#define DMA_INCR8 GAHBCS_DMAINCR(5U) /*!< 16-beat incrementing burst type used by DMA*/
#define DMA_INCR16 GAHBCS_DMAINCR(7U) /*!< 32-beat incrementing burst type used by DMA*/
#define DCFG_PFRI(regval) (DCFG_EOPFT & ((regval) << 11U)) /*!< end of periodic frame time configuration */
#define FRAME_INTERVAL_80 DCFG_PFRI(0U) /*!< 80% of the frame time */
#define FRAME_INTERVAL_85 DCFG_PFRI(1U) /*!< 85% of the frame time */
#define FRAME_INTERVAL_90 DCFG_PFRI(2U) /*!< 90% of the frame time */
#define FRAME_INTERVAL_95 DCFG_PFRI(3U) /*!< 95% of the frame time */
#define DCFG_DEVSPEED(regval) (DCFG_DS & ((regval) << 0U)) /*!< device speed configuration */
#define USB_SPEED_EXP_HIGH DCFG_DEVSPEED(0U) /*!< device external PHY high speed */
#define USB_SPEED_EXP_FULL DCFG_DEVSPEED(1U) /*!< device external PHY full speed */
#define USB_SPEED_INP_FULL DCFG_DEVSPEED(3U) /*!< device internal PHY full speed */
#define DEP0_MPL(regval) (DEP0CTL_MPL & ((regval) << 0U)) /*!< maximum packet length configuration */
#define EP0MPL_64 DEP0_MPL(0U) /*!< maximum packet length 64 bytes */
#define EP0MPL_32 DEP0_MPL(1U) /*!< maximum packet length 32 bytes */
#define EP0MPL_16 DEP0_MPL(2U) /*!< maximum packet length 16 bytes */
#define EP0MPL_8 DEP0_MPL(3U) /*!< maximum packet length 8 bytes */
#define DOEP0_TLEN(regval) (DOEP0LEN_TLEN & ((regval) << 0)) /*!< Transfer length */
#define DOEP0_PCNT(regval) (DOEP0LEN_PCNT & ((regval) << 19)) /*!< Packet count */
#define DOEP0_STPCNT(regval) (DOEP0LEN_STPCNT & ((regval) << 29)) /*!< SETUP packet count */
#define USB_ULPI_PHY 1 /*!< ULPI interface external PHY */
#define USB_EMBEDDED_PHY 2 /*!< Embedded PHY */
#define GRXSTS_PKTSTS_IN 2
#define GRXSTS_PKTSTS_IN_XFER_COMP 3
#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5
#define GRXSTS_PKTSTS_CH_HALTED 7
#define DEVICE_MODE 0 /*!< device mode */
#define HOST_MODE 1 /*!< host mode */
#define OTG_MODE 2 /*!< OTG mode */
#define HCTL_30_60MHZ 0 /*!< USB clock 30-60MHZ */
#define HCTL_48MHZ 1 /*!< USB clock 48MHZ */
#define HCTL_6MHZ 2 /*!< USB clock 6MHZ */
enum USB_SPEED {
USB_SPEED_UNKNOWN = 0, /*!< USB speed unknown */
USB_SPEED_LOW, /*!< USB speed low */
USB_SPEED_FULL, /*!< USB speed full */
USB_SPEED_HIGH /*!< USB speed high */
};
#define EP0_OUT ((uint8_t)0x00) /*!< endpoint out 0 */
#define EP0_IN ((uint8_t)0x80) /*!< endpoint in 0 */
#define EP1_OUT ((uint8_t)0x01) /*!< endpoint out 1 */
#define EP1_IN ((uint8_t)0x81) /*!< endpoint in 1 */
#define EP2_OUT ((uint8_t)0x02) /*!< endpoint out 2 */
#define EP2_IN ((uint8_t)0x82) /*!< endpoint in 2 */
#define EP3_OUT ((uint8_t)0x03) /*!< endpoint out 3 */
#define EP3_IN ((uint8_t)0x83) /*!< endpoint in 3 */
#endif /* __DRV_USB_REGS_H */

View File

@@ -1,52 +0,0 @@
/*!
\file drv_usbd_int.h
\brief USB device mode interrupt header file
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __DRV_USBD_INT_H
#define __DRV_USBD_INT_H
#include "drv_usb_core.h"
#include "drv_usb_dev.h"
/* USB device-mode interrupts global service routine handler */
void usbd_isr (usb_core_driver *udev);
#ifdef USB_HS_DEDICATED_EP1_ENABLED
uint32_t USBD_OTG_EP1IN_ISR_Handler (usb_core_driver *udev);
uint32_t USBD_OTG_EP1OUT_ISR_Handler (usb_core_driver *udev);
#endif
#endif /* __DRV_USBD_INT_H */

View File

@@ -1,49 +0,0 @@
/*!
\file drv_usbh_int.h.h
\brief USB host mode interrupt management header file
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __DRV_USBH_INT_H
#define __DRV_USBH_INT_H
#include "drv_usb_host.h"
typedef struct _usbh_int_cb
{
uint8_t (*SOF) (usb_core_driver *pudev);
} usbh_int_cb;
extern usbh_int_cb *usbh_int_fop;
uint32_t usbh_isr (usb_core_driver *pudev);
#endif /* __DRV_USBH_INT_H */

View File

@@ -1,237 +0,0 @@
/*!
\file usb_ch9_std.h
\brief USB 2.0 standard defines
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __USB_CH9_STD_H
#define __USB_CH9_STD_H
#include "usb_conf.h"
#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */
#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */
#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */
#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */
#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */
#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */
#define USB_SETUP_PACKET_LEN 0x08U /*!< USB setup packet length */
/* bit 7 of bmRequestType: data phase transfer direction */
#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */
#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */
#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */
/* bit 6..5 of bmRequestType: request type */
#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */
#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */
#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */
#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */
#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */
#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */
#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */
#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */
/* bit 4..0 of bmRequestType: recipient type */
enum _usb_recp_type {
USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */
USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */
USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */
USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */
};
/* bRequest value */
enum _usb_request {
USB_GET_STATUS = 0x0U, /*!< USB get status request */
USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */
USB_RESERVED2 = 0x2U,
USB_SET_FEATURE = 0x3U, /*!< USB set feature request */
USB_RESERVED4 = 0x4U,
USB_SET_ADDRESS = 0x5U, /*!< USB set address request */
USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */
USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */
USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */
USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */
USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */
USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */
USB_SYNCH_FRAME = 0xCU /*!< USB synchronize frame request */
};
/* descriptor types of USB specifications */
enum _usb_desctype {
USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */
USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */
USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */
USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */
USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */
USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualtfier descriptor type */
USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */
USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */
USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */
};
/* USB Endpoint Descriptor bmAttributes bit definitions */
/* bits 1..0 : transfer type */
enum _usbx_type {
USB_EP_ATTR_CTL = 0x0U, /*!< USB control transfer type */
USB_EP_ATTR_ISO = 0x1U, /*!< USB Isochronous transfer type */
USB_EP_ATTR_BULK = 0x2U, /*!< USB Bulk transfer type */
USB_EP_ATTR_INT = 0x3U /*!< USB Interrupt transfer type */
};
/* bits 3..2 : Sync type (only if ISOCHRONOUS) */
#define USB_EP_ATTR_NOSYNC 0x00 /* No Synchronization */
#define USB_EP_ATTR_ASYNC 0x04 /* Asynchronous */
#define USB_EP_ATTR_ADAPTIVE 0x08 /* Adaptive */
#define USB_EP_ATTR_SYNC 0x0C /* Synchronous */
#define USB_EP_ATTR_SYNCTYPE 0x0C /* Synchronous type */
/* bits 5..4 : usage type (only if ISOCHRONOUS) */
#define USB_EP_ATTR_DATA 0x00 /* Data endpoint */
#define USB_EP_ATTR_FEEDBACK 0x10 /* Feedback endpoint */
#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20 /* Implicit feedback Data endpoint */
#define USB_EP_ATTR_USAGETYPE 0x30 /* Usage type */
#define FEATURE_SELECTOR_EP 0x00 /* USB endpoint feature selector */
#define FEATURE_SELECTOR_DEV 0x01 /* USB device feature selector */
#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \
(uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U))
#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU))
#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U))
#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b))
#define USB_DEFAULT_CONFIG 0U
/* USB classes */
#define USB_CLASS_HID 0x03U /*!< USB HID class */
#define USB_CLASS_MSC 0x08U /*!< USB MSC class */
/* use the following values when USB host need to get descriptor */
#define USBH_DESC(x) (((x)<< 8U) & 0xFF00U)
/* as per usb specs 9.2.6.4 :standard request with data request timeout: 5sec
standard request with no data stage timeout : 50ms */
#define DATA_STAGE_TIMEOUT 5000U /*!< USB data stage timeout*/
#define NODATA_STAGE_TIMEOUT 50U /*!< USB no data stage timeout*/
#pragma pack(1)
/* USB standard device request structure */
typedef struct _usb_req {
uint8_t bmRequestType; /*!< type of request */
uint8_t bRequest; /*!< request of setup packet */
uint16_t wValue; /*!< value of setup packet */
uint16_t wIndex; /*!< index of setup packet */
uint16_t wLength; /*!< length of setup packet */
} usb_req;
/* USB setup packet define */
typedef union _usb_setup {
uint8_t data[8];
usb_req req;
} usb_setup;
/* USB descriptor defines */
typedef struct _usb_desc_header {
uint8_t bLength; /*!< size of the descriptor */
uint8_t bDescriptorType; /*!< type of the descriptor */
} usb_desc_header;
typedef struct _usb_desc_dev {
usb_desc_header header; /*!< descriptor header, including type and size */
uint16_t bcdUSB; /*!< BCD of the supported USB specification */
uint8_t bDeviceClass; /*!< USB device class */
uint8_t bDeviceSubClass; /*!< USB device subclass */
uint8_t bDeviceProtocol; /*!< USB device protocol */
uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */
uint16_t idVendor; /*!< vendor ID for the USB product */
uint16_t idProduct; /*!< unique product ID for the USB product */
uint16_t bcdDevice; /*!< product release (version) number */
uint8_t iManufacturer; /*!< string index for the manufacturer's name */
uint8_t iProduct; /*!< string index for the product name/details */
uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */
uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */
} usb_desc_dev;
typedef struct _usb_desc_config {
usb_desc_header header; /*!< descriptor header, including type and size */
uint16_t wTotalLength; /*!< size of the configuration descriptor header,and all sub descriptors inside the configuration */
uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */
uint8_t bConfigurationValue; /*!< configuration index of the current configuration */
uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */
uint8_t bmAttributes; /*!< configuration attributes */
uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */
} usb_desc_config;
typedef struct _usb_desc_itf {
usb_desc_header header; /*!< descriptor header, including type and size */
uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */
uint8_t bAlternateSetting; /*!< alternate setting for the interface number */
uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */
uint8_t bInterfaceClass; /*!< interface class ID */
uint8_t bInterfaceSubClass; /*!< interface subclass ID */
uint8_t bInterfaceProtocol; /*!< interface protocol ID */
uint8_t iInterface; /*!< index of the string descriptor describing the interface */
} usb_desc_itf;
typedef struct _usb_desc_ep {
usb_desc_header header; /*!< descriptor header, including type and size. */
uint8_t bEndpointAddress; /*!< logical address of the endpoint */
uint8_t bmAttributes; /*!< endpoint attributes */
uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */
uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */
#ifdef AUDIO_ENDPOINT
uint8_t bRefresh; /*!< reset to 0 */
uint8_t bSynchAddress; /*!< reset to 0 */
#endif
} usb_desc_ep;
typedef struct _usb_desc_LANGID {
usb_desc_header header; /*!< descriptor header, including type and size. */
uint16_t wLANGID; /*!< LANGID code */
} usb_desc_LANGID;
#pragma pack()
#endif /* __USB_CH9_STD_H */

View File

@@ -1,95 +0,0 @@
/*!
\file usbd_core.h
\brief USB device mode core functions protype
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __USBD_CORE_H
#define __USBD_CORE_H
#include "drv_usb_core.h"
#include "drv_usb_dev.h"
typedef enum
{
USBD_OK = 0, /*!< status OK */
USBD_BUSY, /*!< status busy */
USBD_FAIL, /*!< status fail */
} usbd_status;
enum _usbd_status {
USBD_DEFAULT = 1, /*!< default status */
USBD_ADDRESSED = 2, /*!< address send status */
USBD_CONFIGURED = 3, /*!< configured status */
USBD_SUSPENDED = 4 /*!< suspended status */
};
/* function declarations */
/* device connect */
void usbd_connect (usb_core_driver *udev);
/* device disconnect */
void usbd_disconnect (usb_core_driver *udev);
/* set USB device address */
void usbd_addr_set (usb_core_driver *udev, uint8_t addr);
/* initailizes the USB device-mode stack and load the class driver */
void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_class_core *class_core);
/* endpoint initialization */
uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc);
/* configure the endpoint when it is disabled */
uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr);
/* endpoint prepare to receive data */
uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t len);
/* endpoint prepare to transmit data */
uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t len);
/* set an endpoint to STALL status */
uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr);
/* clear endpoint STALLed status */
uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr);
/* flush the endpoint FIFOs */
uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr);
/* get the received data length */
uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num);
#endif /* __USBD_CORE_H */

View File

@@ -1,114 +0,0 @@
/*!
\file usbd_enum.h
\brief USB enumeration definitions
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __USBD_ENUM_H
#define __USBD_ENUM_H
#include "usbd_core.h"
#include "usbd_conf.h"
#include <wchar.h>
#ifndef NULL
#define NULL 0U
#endif
typedef enum _usb_reqsta {
REQ_SUPP = 0x0U, /* request support */
REQ_NOTSUPP = 0x1U /* request not support */
} usb_reqsta;
/* string descriptor index */
enum _str_index
{
STR_IDX_LANGID = 0x0U, /* language ID string index */
STR_IDX_MFC = 0x1U, /* manufacturer string index */
STR_IDX_PRODUCT = 0x2U, /* product string index */
STR_IDX_SERIAL = 0x3U, /* serial string index */
STR_IDX_CONFIG = 0x4U, /* configuration string index */
STR_IDX_ITF = 0x5U, /* interface string index */
STR_IDX_MAX = 0x6U /* string maximum index */
};
typedef enum _usb_pwrsta {
USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */
USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */
} usb_pwrsta;
typedef enum _usb_feature
{
USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */
USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */
USB_FEATURE_TEST_MODE = 0x2U /* USB has endpoint test mode feature */
} usb_feature;
#define ENG_LANGID 0x0409U /* english language ID */
#define CHN_LANGID 0x0804U /* chinese language ID */
/* USB device exported macros */
#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U))
#define WIDE_STRING(string) _WIDE_STRING(string)
#define _WIDE_STRING(string) L##string
#define USBD_STRING_DESC(string) \
(void *)&(const struct { \
uint8_t _len; \
uint8_t _type; \
wchar_t _data[sizeof(string)]; \
}) { \
sizeof(WIDE_STRING(string)) + 2U - 2U, \
USB_DESCTYPE_STR, \
WIDE_STRING(string) \
}
/* function declarations */
/* handle USB standard device request */
usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req);
/* handle USB device class request */
usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req);
/* handle USB vendor request */
usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req);
/* handle USB enumeration error */
void usbd_enum_error (usb_core_driver *udev, usb_req *req);
/* convert hex 32bits value into unicode char */
void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len);
#endif /* __USBD_ENUM_H */

View File

@@ -1,64 +0,0 @@
/*!
\file usbd_transc.h
\brief USB transaction core functions prototype
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __USBD_TRANSC_H
#define __USBD_TRANSC_H
#include "usbd_core.h"
/* function declarations */
/* USB send data in the control transaction */
usbd_status usbd_ctl_send (usb_core_driver *udev);
/* USB receive data in control transaction */
usbd_status usbd_ctl_recev (usb_core_driver *udev);
/* USB send control transaction status */
usbd_status usbd_ctl_status_send (usb_core_driver *udev);
/* USB control receive status */
usbd_status usbd_ctl_status_recev (usb_core_driver *udev);
/* USB setup stage processing */
uint8_t usbd_setup_transc (usb_core_driver *udev);
/* data out stage processing */
uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num)__attribute__((optimize("O0")));
/* data in stage processing */
uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num)__attribute__((optimize("O0")));
#endif /* __USBD_TRANSC_H */

View File

@@ -1,219 +0,0 @@
/*!
\file usbh_core.h
\brief USB host core state machine header file
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __USBH_CORE_H
#define __USBH_CORE_H
#include "usbh_conf.h"
#include "drv_usb_host.h"
#define MSC_CLASS 0x08U
#define HID_CLASS 0x03U
#define MSC_PROTOCOL 0x50U
#define CBI_PROTOCOL 0x01U
#define USBH_MAX_ERROR_COUNT 3U
#define USBH_DEV_ADDR_DEFAULT 0U
#define USBH_DEV_ADDR 1U
typedef enum
{
USBH_OK = 0U,
USBH_BUSY,
USBH_FAIL,
USBH_NOT_SUPPORTED,
USBH_UNRECOVERED_ERROR,
USBH_SPEED_UNKNOWN_ERROR,
USBH_APPLY_DEINIT
} usbh_status;
/* USB host global operation state */
typedef enum
{
HOST_DEFAULT = 0U,
HOST_DETECT_DEV_SPEED,
HOST_DEV_ATTACHED,
HOST_DEV_DETACHED,
HOST_ENUM,
HOST_CLASS_ENUM,
HOST_CLASS_HANDLER,
HOST_USER_INPUT,
HOST_SUSPENDED,
HOST_ERROR
} usb_host_state;
/* USB host enumeration state */
typedef enum
{
ENUM_DEFAULT = 0U,
ENUM_GET_DEV_DESC,
ENUM_SET_ADDR,
ENUM_GET_CFG_DESC,
ENUM_GET_CFG_DESC_SET,
ENUM_GET_STR_DESC,
ENUM_SET_CONFIGURATION,
ENUM_DEV_CONFIGURED
} usbh_enum_state;
/* USB host control transfer state */
typedef enum
{
CTL_IDLE = 0U,
CTL_SETUP,
CTL_DATA_IN,
CTL_DATA_OUT,
CTL_STATUS_IN,
CTL_STATUS_OUT,
CTL_ERROR,
CTL_FINISH
} usbh_ctl_state;
/* user action state */
typedef enum
{
USBH_USER_NO_RESP = 0U,
USBH_USER_RESP_OK = 1U,
} usbh_user_status;
/* control transfer information */
typedef struct _usbh_control
{
uint8_t pipe_in_num;
uint8_t pipe_out_num;
uint8_t max_len;
uint8_t error_count;
uint8_t *buf;
uint16_t ctl_len;
uint16_t timer;
usb_setup setup;
usbh_ctl_state ctl_state;
} usbh_control;
/* USB device property */
typedef struct
{
uint8_t addr;
uint32_t speed;
usb_desc_dev dev_desc;
usb_desc_config cfg_desc;
usb_desc_itf itf_desc[USBH_MAX_INTERFACES_NUM];
usb_desc_ep ep_desc[USBH_MAX_INTERFACES_NUM][USBH_MAX_EP_NUM];
} usb_dev_prop;
/**
* @brief Device class callbacks
*/
typedef struct
{
usbh_status (*class_init) (usb_core_driver *pudev, void *phost);
void (*class_deinit) (usb_core_driver *pudev, void *phost);
usbh_status (*class_requests) (usb_core_driver *pudev, void *phost);
usbh_status (*class_machine) (usb_core_driver *pudev, void *phost);
} usbh_class_cb;
/**
* @brief User callbacks
*/
typedef struct
{
void (*dev_init) (void);
void (*dev_deinit) (void);
void (*dev_attach) (void);
void (*dev_reset) (void);
void (*dev_detach) (void);
void (*dev_over_currented) (void);
void (*dev_speed_detected) (uint32_t dev_speed);
void (*dev_devdesc_assigned) (void *dev_desc);
void (*dev_address_set) (void);
void (*dev_cfgdesc_assigned) (usb_desc_config *cfg_desc,
usb_desc_itf *itf_desc,
usb_desc_ep *ep_desc);
void (*dev_mfc_str) (void *mfc_str);
void (*dev_prod_str) (void *prod_str);
void (*dev_seral_str) (void *serial_str);
void (*dev_enumerated) (void);
usbh_user_status (*dev_user_input) (void);
int (*dev_user_app) (void);
void (*dev_not_supported) (void);
void (*dev_error) (void);
} usbh_user_cb;
/**
* @brief Host information
*/
typedef struct
{
usb_host_state cur_state; /*!< host state machine value */
usb_host_state backup_state; /*!< backup of previous state machine value */
usbh_enum_state enum_state; /*!< enumeration state machine */
usbh_control control; /*!< USB host control state machine */
usb_dev_prop dev_prop; /*!< USB device properity */
usbh_class_cb *class_cb; /*!< USB class callback */
usbh_user_cb *usr_cb; /*!< USB user callback */
} usbh_host;
/* USB host stack initializations */
void usbh_init (usb_core_driver *pudev, usb_core_enum core, usbh_host *puhost);
/* de-initialize USB host */
usbh_status usbh_deinit (usb_core_driver *pudev, usbh_host *puhost);
/* USB host core main state machine process */
void usbh_core_task (usb_core_driver *pudev, usbh_host *puhost);
/* handle the error on USB host side */
void usbh_error_handler (usbh_host *puhost, usbh_status ErrType);
/* get USB URB state */
static inline usb_urb_state usbh_urbstate_get (usb_core_driver *pudev, uint8_t pp_num)
{
return pudev->host.pipe[pp_num].urb_state;
}
/* get USB transfer data count */
static inline uint32_t usbh_xfercount_get (usb_core_driver *pudev, uint8_t pp_num)
{
return pudev->host.backup_xfercount[pp_num];
}
#endif /* __USBH_CORE_H */

View File

@@ -1,78 +0,0 @@
/*!
\file usbh_enum.h
\brief USB host mode USB enumeration header file
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __USBH_ENUM_H
#define __USBH_ENUM_H
#include "usb_conf.h"
#include "usbh_core.h"
/* get the next descriptor header */
usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr);
/* configure USB control status parameters */
void usbh_ctlstate_config (usbh_host *puhost, uint8_t *buf, uint16_t len);
/* get device descriptor from the USB device */
usbh_status usbh_devdesc_get (usb_core_driver *pudev, usbh_host *puhost, uint8_t len);
/* get configuration descriptor from the USB device */
usbh_status usbh_cfgdesc_get (usb_core_driver *pudev, usbh_host *puhost, uint16_t len);
/* get string descriptor from the USB device */
usbh_status usbh_strdesc_get (usb_core_driver *pudev,
usbh_host *puhost,
uint8_t str_index,
uint8_t *buf,
uint16_t len);
/* set the configuration value to the connected device */
usbh_status usbh_setcfg (usb_core_driver *pudev, usbh_host *puhost, uint16_t config);
/* set the address to the connected device */
usbh_status usbh_setaddress (usb_core_driver *pudev, usbh_host *puhost, uint8_t dev_addr);
/* clear or disable a specific feature */
usbh_status usbh_clrfeature (usb_core_driver *pudev,
usbh_host *puhost,
uint8_t ep_num,
uint8_t pp_num);
/* set the interface value to the connected device */
usbh_status usbh_setinterface (usb_core_driver *pudev,
usbh_host *puhost,
uint8_t ep_num,
uint8_t alter_setting);
#endif /* __USBH_ENUM_H */

View File

@@ -1,70 +0,0 @@
/*!
\file usbh_pipe.h
\brief USB host mode pipe header file
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef __USBH_PIPE_H
#define __USBH_PIPE_H
#include "usbh_core.h"
#define HC_MAX 8U
#define HC_OK 0x0000U
#define HC_USED 0x8000U
#define HC_ERROR 0xFFFFU
#define HC_USED_MASK 0x7FFFU
/* allocate a new pipe */
uint8_t usbh_pipe_allocate (usb_core_driver *pudev, uint8_t ep_addr);
/* delete all USB host pipe */
uint8_t usbh_pipe_delete (usb_core_driver *pudev);
/* free a pipe */
uint8_t usbh_pipe_free (usb_core_driver *pudev, uint8_t pp_num);
/* create a pipe */
uint8_t usbh_pipe_create (usb_core_driver *pudev,
usb_dev_prop *udev,
uint8_t pp_num,
uint8_t ep_type,
uint16_t ep_mpl);
/* modify a pipe */
uint8_t usbh_pipe_update (usb_core_driver *pudev,
uint8_t pp_num,
uint8_t dev_addr,
uint32_t dev_speed,
uint16_t ep_mpl);
#endif /* __USBH_PIPE_H */

View File

@@ -1,319 +0,0 @@
/*!
\file drv_usb_core.c
\brief USB core driver which can operate in host and device mode
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "drv_usb_core.h"
#include "drv_usb_hw.h"
/*!
\brief config USB core to soft reset
\param[in] usb_regs: USB core registers
\param[out] none
\retval none
*/
static void usb_core_reset (usb_core_regs *usb_regs)
{
/* enable core soft reset */
usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST;
/* wait for the core to be soft reset */
while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST);
/* wait for addtional 3 PHY clocks */
usb_udelay(3);
}
/*!
\brief config USB core basic
\param[in] usb_basic: pointer to usb capabilities
\param[in] usb_regs: USB core registers
\param[in] usb_core: USB core
\param[out] none
\retval operation status
*/
usb_status usb_basic_init (usb_core_basic *usb_basic,
usb_core_regs *usb_regs,
usb_core_enum usb_core)
{
uint32_t i = 0, reg_base = 0;
/* config USB default transfer mode as FIFO mode */
usb_basic->transfer_mode = USB_USE_FIFO;
/* USB default speed is full-speed */
usb_basic->core_speed = USB_SPEED_FULL;
usb_basic->core_enum = usb_core;
switch (usb_core) {
case USB_CORE_ENUM_HS:
reg_base = USBHS_REG_BASE;
/* set the host channel numbers */
usb_basic->num_pipe = USBHS_MAX_CHANNEL_COUNT;
/* set the device endpoint numbers */
usb_basic->num_ep = USBHS_MAX_EP_COUNT;
#ifdef USB_ULPI_PHY_ENABLED
usb_basic->phy_itf = USB_ULPI_PHY;
#else
usb_basic->phy_itf = USB_EMBEDDED_PHY;
#endif /* USB_ULPI_PHY_ENABLED */
#ifdef USB_HS_INTERNAL_DMA_ENABLED
bp->transfer_mode = USB_USE_DMA;
#endif /* USB_HS_INTERNAL_DMA_ENABLED */
break;
case USB_CORE_ENUM_FS:
reg_base = USBFS_REG_BASE;
/* set the host channel numbers */
usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT;
/* set the device endpoint numbers */
usb_basic->num_ep = USBFS_MAX_EP_COUNT;
/* USBFS core use embedded physical layer */
usb_basic->phy_itf = USB_EMBEDDED_PHY;
break;
default:
return USB_FAIL;
}
usb_basic->sof_enable = USB_SOF_OUTPUT;
usb_basic->low_power = USB_LOW_POWER;
/* assign main registers address */
*usb_regs = (usb_core_regs) {
.gr = (usb_gr*) (reg_base + USB_REG_OFFSET_CORE),
.hr = (usb_hr*) (reg_base + USB_REG_OFFSET_HOST),
.dr = (usb_dr*) (reg_base + USB_REG_OFFSET_DEV),
.HPCS = (uint32_t*) (reg_base + USB_REG_OFFSET_PORT),
.PWRCLKCTL = (uint32_t*) (reg_base + USB_REG_OFFSET_PWRCLKCTL)
};
/* assign device endpoint registers address */
for (i = 0; i < usb_basic->num_ep; i++) {
usb_regs->er_in[i] = (usb_erin *) \
(reg_base + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP));
usb_regs->er_out[i] = (usb_erout *)\
(reg_base + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP));
}
/* assign host pipe registers address */
for (i = 0; i < usb_basic->num_pipe; i++) {
usb_regs->pr[i] = (usb_pr *) \
(reg_base + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH));
usb_regs->DFIFO[i] = (uint32_t *) \
(reg_base + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE));
}
return USB_OK;
}
/*!
\brief initializes the USB controller registers and
prepares the core device mode or host mode operation
\param[in] bp: usb capabilities
\param[in] core_regs: usb core registers
\param[out] none
\retval operation status
*/
usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs)
{
uint32_t reg_value = usb_regs->gr->GCCFG;
/* disable USB global interrupt */
usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN;
if (USB_ULPI_PHY == usb_basic.phy_itf) {
reg_value &= ~GCCFG_PWRON;
if (usb_basic.sof_enable) {
reg_value |= GCCFG_SOFOEN;
}
usb_regs->gr->GCCFG = GCCFG_SOFOEN;
/* init the ULPI interface */
usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI);
#ifdef USBHS_EXTERNAL_VBUS_ENABLED
/* use external VBUS driver */
usb_regs->gr->GUSBCS |= GUSBCS_ULPIEVD;
#else
/* use internal VBUS driver */
usb_regs->gr->GUSBCS &= ~GUSBCS_ULPIEVD;
#endif
/* soft reset the core */
usb_core_reset (usb_regs);
} else {
usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY;
/* soft reset the core */
usb_core_reset (usb_regs);
/* active the transceiver and enable vbus sensing */
reg_value = GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN;
#ifndef VBUS_SENSING_ENABLED
reg_value |= GCCFG_VBUSIG;
#endif /* VBUS_SENSING_ENABLED */
/* enable SOF output */
if (usb_basic.sof_enable) {
reg_value |= GCCFG_SOFOEN;
}
usb_regs->gr->GCCFG = reg_value;
usb_mdelay(20);
}
if (USB_USE_DMA == usb_basic.transfer_mode) {
usb_regs->gr->GAHBCS |= GAHBCS_DMAEN;
usb_regs->gr->GAHBCS &= ~GAHBCS_BURST;
usb_regs->gr->GAHBCS |= DMA_INCR8;
}
#ifdef USE_OTG_MODE
/* enable USB OTG features */
usb_regs->gr->GUSBCS |= GUSBCS_HNPCAP | GUSBCS_SRPCAP;
/* enable the USB wakeup and suspend interrupts */
usb_regs->gr->GINTF = 0xBFFFFFFFU;
usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | \
GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE;
#endif /* USE_OTG_MODE */
return USB_OK;
}
/*!
\brief write a packet into the Tx FIFO associated with the endpoint
\param[in] core_regs: usb core registers
\param[in] src_buf: pointer to source buffer
\param[in] fifo_num: FIFO number which is in (0..3)
\param[in] byte_count: packet byte count
\param[out] none
\retval operation status
*/
usb_status usb_txfifo_write (usb_core_regs *usb_regs,
uint8_t *src_buf,
uint8_t fifo_num,
uint16_t byte_count)
{
uint32_t word_count = (byte_count + 3U) / 4U;
__IO uint32_t *fifo = usb_regs->DFIFO[fifo_num];
while (word_count-- > 0) {
*fifo = *((__packed uint32_t *)src_buf);
src_buf += 4U;
}
return USB_OK;
}
/*!
\brief read a packet from the Rx FIFO associated with the endpoint
\param[in] core_regs: usb core registers
\param[in] dest_buf: pointer to destination buffer
\param[in] byte_count: packet byte count
\param[out] none
\retval void type pointer
*/
void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count)
{
uint32_t word_count = (byte_count + 3U) / 4U;
__IO uint32_t *fifo = usb_regs->DFIFO[0];
while (word_count-- > 0) {
*(__packed uint32_t *)dest_buf = *fifo;
dest_buf += 4U;
}
return ((void *)dest_buf);
}
/*!
\brief flush a Tx FIFO or all Tx FIFOs
\param[in] core_regs: pointer to usb core registers
\param[in] fifo_num: FIFO number which is in (0..3)
\param[out] none
\retval operation status
*/
usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num)
{
usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF;
/* wait for Tx FIFO flush bit is set */
while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF);
/* wait for 3 PHY clocks*/
usb_udelay(3);
return USB_OK;
}
/*!
\brief flush the entire Rx FIFO
\param[in] core_regs: pointer to usb core registers
\param[out] none
\retval operation status
*/
usb_status usb_rxfifo_flush (usb_core_regs *usb_regs)
{
usb_regs->gr->GRSTCTL = GRSTCTL_RXFF;
/* wait for Rx FIFO flush bit is set */
while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF);
/* wait for 3 PHY clocks */
usb_udelay(3);
return USB_OK;
}

View File

@@ -1,749 +0,0 @@
/*!
\file drv_usb_dev.c
\brief USB device mode low level driver
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "drv_usb_hw.h"
#include "drv_usb_core.h"
#include "drv_usb_dev.h"
/* endpoint 0 max packet length */
static const uint8_t EP0_MAXLEN[4] = {
[DSTAT_EM_HS_PHY_30MHZ_60MHZ] = EP0MPL_64,
[DSTAT_EM_FS_PHY_30MHZ_60MHZ] = EP0MPL_64,
[DSTAT_EM_FS_PHY_48MHZ] = EP0MPL_64,
[DSTAT_EM_LS_PHY_6MHZ] = EP0MPL_8
};
#ifdef USB_FS_CORE
/* USB endpoint Tx FIFO size */
static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_EP_COUNT] =
{
(uint16_t)TX0_FIFO_FS_SIZE,
(uint16_t)TX1_FIFO_FS_SIZE,
(uint16_t)TX2_FIFO_FS_SIZE,
(uint16_t)TX3_FIFO_FS_SIZE
};
#elif defined(USB_HS_CORE)
uint16_t USBHS_TX_FIFO_SIZE[USBHS_MAX_EP_COUNT] =
{
(uint16_t)TX0_FIFO_HS_SIZE,
(uint16_t)TX1_FIFO_HS_SIZE,
(uint16_t)TX2_FIFO_HS_SIZE,
(uint16_t)TX3_FIFO_HS_SIZE,
(uint16_t)TX4_FIFO_HS_SIZE,
(uint16_t)TX5_FIFO_HS_SIZE
};
#endif /* USBFS_CORE */
/*!
\brief initialize USB core registers for device mode
\param[in] udev: pointer to usb device
\param[out] none
\retval operation status
*/
usb_status usb_devcore_init (usb_core_driver *udev)
{
uint32_t i, ram_addr = 0;
/* force to peripheral mode */
udev->regs.gr->GUSBCS &= ~(GUSBCS_FDM | GUSBCS_FHM);
udev->regs.gr->GUSBCS |= GUSBCS_FDM;
// udev->regs.gr->GUSBCS &= ~(GUSBCS_FHM);
/* restart the Phy Clock (maybe don't need to...) */
*udev->regs.PWRCLKCTL = 0U;
/* config periodic frame interval to default value */
udev->regs.dr->DCFG &= ~DCFG_EOPFT;
udev->regs.dr->DCFG |= FRAME_INTERVAL_80;
udev->regs.dr->DCFG &= ~DCFG_DS;
#ifdef USB_FS_CORE
if (udev->bp.core_enum == USB_CORE_ENUM_FS) {
/* set full-speed PHY */
udev->regs.dr->DCFG |= USB_SPEED_INP_FULL;
/* set Rx FIFO size */
udev->regs.gr->GRFLEN = RX_FIFO_FS_SIZE;
/* set endpoint 0 Tx FIFO length and RAM address */
udev->regs.gr->DIEP0TFLEN_HNPTFLEN = ((uint32_t)TX0_FIFO_FS_SIZE << 16) | \
((uint32_t)RX_FIFO_FS_SIZE);
ram_addr = RX_FIFO_FS_SIZE;
/* set endpoint 1 to 3's Tx FIFO length and RAM address */
for (i = 1; i < USBFS_MAX_EP_COUNT; i++) {
ram_addr += USBFS_TX_FIFO_SIZE[i - 1];
udev->regs.gr->DIEPTFLEN[i - 1] = ((uint32_t)USBFS_TX_FIFO_SIZE[i] << 16U) | \
ram_addr;
}
}
#endif
#ifdef USB_HS_CORE
if (udev->bp.core == USB_CORE_HS) {
if (udev->bp.core_phy == USB_ULPI_PHY) {
udev->regs.dr->DCFG |= USB_SPEED_EXP_HIGH;
} else {/* set High speed phy in Full speed mode */
udev->regs.dr->DCFG |= USB_SPEED_EXP_FULL;
}
/* Set Rx FIFO size */
udev->regs.gr->GRFLEN &= ~GRFLEN_RXFD;
udev->regs.gr->GRFLEN |= RX_FIFO_HS_SIZE;
/* Set endpoint 0 Tx FIFO length and RAM address */
udev->regs.gr->DIEP0TFLEN_HNPTFLEN = ((uint32_t)TX0_FIFO_HS_SIZE << 16) | \
RX_FIFO_HS_SIZE;
ram_addr = RX_FIFO_HS_SIZE;
/* Set endpoint 1 to 3's Tx FIFO length and RAM address */
for (i = 1; i < USBHS_MAX_EP_COUNT; i++) {
ram_addr += USBHS_TX_FIFO_SIZE[i - 1];
udev->regs.gr->DIEPTFLEN[i - 1] = ((uint32_t)USBHS_TX_FIFO_SIZE[i] << 16) | \
ram_addr;
}
}
#endif
/* make sure all FIFOs are flushed */
/* flush all Tx FIFOs */
usb_txfifo_flush (&udev->regs, 0x10);
/* flush entire Rx FIFO */
usb_rxfifo_flush (&udev->regs);
/* clear all pending device interrupts */
udev->regs.dr->DIEPINTEN = 0U;
udev->regs.dr->DOEPINTEN = 0U;
udev->regs.dr->DAEPINT = 0xFFFFFFFFU;
udev->regs.dr->DAEPINTEN = 0U;
/* configure all IN/OUT endpoints */
for (i = 0; i < udev->bp.num_ep; i++) {
if (udev->regs.er_in[i]->DIEPCTL & DEPCTL_EPEN) {
udev->regs.er_in[i]->DIEPCTL |= DEPCTL_EPD | DEPCTL_SNAK;
} else {
udev->regs.er_in[i]->DIEPCTL = 0U;
}
/* set IN endpoint transfer length to 0 */
udev->regs.er_in[i]->DIEPLEN = 0U;
/* clear all pending IN endpoint interrupts */
udev->regs.er_in[i]->DIEPINTF = 0xFFU;
if (udev->regs.er_out[i]->DOEPCTL & DEPCTL_EPEN) {
udev->regs.er_out[i]->DOEPCTL |= DEPCTL_EPD | DEPCTL_SNAK;
} else {
udev->regs.er_out[i]->DOEPCTL = 0U;
}
/* set OUT endpoint transfer length to 0 */
udev->regs.er_out[i]->DOEPLEN = 0U;
/* clear all pending OUT endpoint interrupts */
udev->regs.er_out[i]->DOEPINTF = 0xFFU;
}
usb_devint_enable (udev);
return USB_OK;
}
/*!
\brief enable the USB device mode interrupts
\param[in] udev: pointer to usb device
\param[out] none
\retval operation status
*/
usb_status usb_devint_enable (usb_core_driver *udev)
{
/* clear any pending USB OTG interrupts */
udev->regs.gr->GOTGINTF = 0xFFFFFFFFU;
/* clear any pending interrupts */
udev->regs.gr->GINTF = 0xBFFFFFFFU;
/* enable the USB wakeup and suspend interrupts */
udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE;
/* enable device_mode-related interrupts */
if (USB_USE_FIFO == udev->bp.transfer_mode) {
udev->regs.gr->GINTEN |= GINTEN_RXFNEIE;
}
udev->regs.gr->GINTEN |= GINTEN_RSTIE | GINTEN_ENUMFIE | GINTEN_IEPIE |\
GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_MFIE;
#ifdef VBUS_SENSING_ENABLED
udev->regs.gr->GINTEN |= GINTEN_SESIE | GINTEN_OTGIE;
#endif /* VBUS_SENSING_ENABLED */
/* enable USB global interrupt */
udev->regs.gr->GAHBCS |= GAHBCS_GINTEN;
return USB_OK;
}
/*!
\brief config the USB device to be disconnected
\param[in] udev: pointer to usb device
\param[out] none
\retval operation status
*/
void usb_dev_disconnect (usb_core_driver *udev)
{
udev->regs.dr->DCTL |= DCTL_SD;
}
/*!
\brief config the USB device to be connected
\param[in] udev: pointer to usb device
\param[out] none
\retval operation status
*/
void usb_dev_connect (usb_core_driver *udev)
{
udev->regs.dr->DCTL &= ~DCTL_SD;
}
/*!
\brief set the USB device address
\param[in] udev: pointer to usb device
\param[in] dev_addr: device address for setting
\param[out] none
\retval operation status
*/
void usb_devaddr_set (usb_core_driver *udev, uint8_t dev_addr)
{
udev->regs.dr->DCFG &= ~DCFG_DAR;
udev->regs.dr->DCFG |= dev_addr << 4;
}
/*!
\brief active the usb transaction
\param[in] udev: pointer to usb device
\param[in] transc: the usb transaction
\param[out] none
\retval status
*/
usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc)
{
__IO uint32_t *reg_addr = NULL;
__IO uint32_t epinten = 0U;
/* get the endpoint number */
uint8_t ep_num = transc->ep_addr.num;
/* enable endpoint interrupt number */
if (transc->ep_addr.dir) {
reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL;
epinten = 1 << ep_num;
} else {
reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL;
epinten = 1 << (16 + ep_num);
}
/* if the endpoint is not active, need change the endpoint control register */
if (!(*reg_addr & DEPCTL_EPACT)) {
*reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM);
/* set endpoint maximum packet length */
if (0U == ep_num) {
*reg_addr |= EP0_MAXLEN[udev->regs.dr->DSTAT & DSTAT_ES];
} else {
*reg_addr |= transc->max_len;
}
/* activate endpoint */
*reg_addr |= (transc->ep_type << 18) | (ep_num << 22) | DEPCTL_SD0PID | DEPCTL_EPACT;
}
#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED
if ((ep_num == 1) && (udev->bp.core == USB_HS_CORE_ID)) {
udev->regs.dr->DEP1INTEN |= epinten;
}
else
#endif
{
/* enable the interrupts for this endpoint */
udev->regs.dr->DAEPINTEN |= epinten;
}
return USB_OK;
}
/*!
\brief deactive the usb transaction
\param[in] udev: pointer to usb device
\param[in] transc: the usb transaction
\param[out] none
\retval status
*/
usb_status usb_transc_deactivate(usb_core_driver *udev, usb_transc *transc)
{
uint32_t epinten = 0U;
uint8_t ep_num = transc->ep_addr.num;
/* disable endpoint interrupt number */
if (transc->ep_addr.dir) {
epinten = 1 << ep_num;
udev->regs.er_in[ep_num]->DIEPCTL &= ~DEPCTL_EPACT;
} else {
epinten = 1 << (ep_num + 16);
udev->regs.er_out[ep_num]->DOEPCTL &= ~DEPCTL_EPACT;
}
#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED
if ((ep_num == 1) && (udev->bp.core == USB_CORE_HS)) {
udev->regs.dr->DEP1INTEN &= ~epinten;
}
else
#endif
{
/* disable the interrupts for this endpoint */
udev->regs.dr->DAEPINTEN &= ~epinten;
}
return USB_OK;
}
/*!
\brief configure usb transaction to start IN transfer
\param[in] udev: pointer to usb device
\param[in] transc: the usb IN transaction
\param[out] none
\retval status
*/
usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc)
{
usb_status status = USB_OK;
uint8_t ep_num = transc->ep_addr.num;
__IO uint32_t epctl = udev->regs.er_in[ep_num]->DIEPCTL;
__IO uint32_t eplen = udev->regs.er_in[ep_num]->DIEPLEN;
eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT);
/* zero length packet or endpoint 0 */
if (0U == transc->xfer_len) {
/* set transfer packet count to 1 */
eplen |= 1 << 19;
} else {
/* set transfer packet count */
if (0U == ep_num) {
transc->xfer_len = USB_MIN(transc->xfer_len, transc->max_len);
eplen |= 1 << 19;
} else {
eplen |= ((transc->xfer_len - 1 + transc->max_len) / transc->max_len) << 19;
}
/* set endpoint transfer length */
eplen |= transc->xfer_len;
if (transc->ep_type == USB_EPTYPE_ISOC) {
eplen |= DIEPLEN_MCNT;
}
}
udev->regs.er_in[ep_num]->DIEPLEN = eplen;
if (USB_USE_DMA == udev->bp.transfer_mode) {
udev->regs.er_in[ep_num]->DIEPDMAADDR = transc->dma_addr;
}
if (transc->ep_type == USB_EPTYPE_ISOC) {
if (((udev->regs.dr->DSTAT & DSTAT_FNRSOF) >> 8) & 0x1) {
epctl |= DEPCTL_SD1PID;
} else {
epctl |= DEPCTL_SD0PID;
}
}
/* enable the endpoint and clear the NAK */
epctl |= DEPCTL_CNAK | DEPCTL_EPEN;
udev->regs.er_in[ep_num]->DIEPCTL = epctl;
if (transc->ep_type != USB_EPTYPE_ISOC) {
/* enable the Tx FIFO empty interrupt for this endpoint */
if (transc->xfer_len > 0) {
udev->regs.dr->DIEPFEINTEN |= 1 << ep_num;
}
} else {
usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, transc->xfer_len);
}
return status;
}
/*!
\brief configure usb transaction to start OUT transfer
\param[in] udev: pointer to usb device
\param[in] transc: the usb OUT transaction
\param[out] none
\retval status
*/
usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc)
{
usb_status status = USB_OK;
uint8_t ep_num = transc->ep_addr.num;
uint32_t epctl = udev->regs.er_out[ep_num]->DOEPCTL;
uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN;
eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT);
/* zero length packet or endpoint 0 */
if ((0U == transc->xfer_len) || (0U == ep_num)) {
/* set the transfer length to max packet size */
eplen |= transc->max_len;
/* set the transfer packet count to 1 */
eplen |= 1U << 19;
} else {
/* configure the transfer size and packet count as follows:
* pktcnt = N
* xfersize = N * maxpacket
*/
uint32_t packet_count = (transc->xfer_len + transc->max_len - 1) / transc->max_len;
eplen |= packet_count << 19;
eplen |= packet_count * transc->max_len;
}
udev->regs.er_out[ep_num]->DOEPLEN = eplen;
if (USB_USE_DMA == udev->bp.transfer_mode) {
udev->regs.er_out[ep_num]->DOEPDMAADDR = transc->dma_addr;
}
if (transc->ep_type == USB_EPTYPE_ISOC) {
if (transc->frame_num) {
epctl |= DEPCTL_SD1PID;
} else {
epctl |= DEPCTL_SD0PID;
}
}
/* enable the endpoint and clear the NAK */
epctl |= DEPCTL_EPEN | DEPCTL_CNAK;
udev->regs.er_out[ep_num]->DOEPCTL = epctl;
return status;
}
/*!
\brief set the usb transaction STALL status
\param[in] udev: pointer to usb device
\param[in] transc: the usb transaction
\param[out] none
\retval status
*/
usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc)
{
__IO uint32_t *reg_addr = NULL;
uint8_t ep_num = transc->ep_addr.num;
if (transc->ep_addr.dir) {
reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL);
/* set the endpoint disable bit */
if (*reg_addr & DEPCTL_EPEN) {
*reg_addr |= DEPCTL_EPD;
}
} else {
/* set the endpoint stall bit */
reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL);
}
/* set the endpoint stall bit */
*reg_addr |= DEPCTL_STALL;
return USB_OK;
}
/*!
\brief clear the usb transaction STALL status
\param[in] udev: pointer to usb device
\param[in] transc: the usb transaction
\param[out] none
\retval status
*/
usb_status usb_transc_clrstall(usb_core_driver *udev, usb_transc *transc)
{
__IO uint32_t *reg_addr = NULL;
uint8_t ep_num = transc->ep_addr.num;
if (transc->ep_addr.dir) {
reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL);
} else {
reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL);
}
/* clear the endpoint stall bits */
*reg_addr &= ~DEPCTL_STALL;
/* reset data PID of the periodic endpoints */
if ((transc->ep_type == USB_EPTYPE_INTR) || (transc->ep_type == USB_EPTYPE_BULK)) {
*reg_addr |= DEPCTL_SD0PID;
}
return USB_OK;
}
/*!
\brief read device all OUT endpoint interrupt register
\param[in] udev: pointer to usb device
\param[out] none
\retval none
*/
uint32_t usb_oepintnum_read (usb_core_driver *udev)
{
uint32_t value = udev->regs.dr->DAEPINT;
value &= udev->regs.dr->DAEPINTEN;
return (value & DAEPINT_OEPITB) >> 16;
}
/*!
\brief read device OUT endpoint interrupt flag register
\param[in] udev: pointer to usb device
\param[in] ep_num: endpoint number
\param[out] none
\retval none
*/
uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num)
{
uint32_t value = udev->regs.er_out[ep_num]->DOEPINTF;
value &= udev->regs.dr->DOEPINTEN;
return value;
}
/*!
\brief read device all IN endpoint interrupt register
\param[in] udev: pointer to usb device
\param[out] none
\retval none
*/
uint32_t usb_iepintnum_read (usb_core_driver *udev)
{
uint32_t value = udev->regs.dr->DAEPINT;
value &= udev->regs.dr->DAEPINTEN;
return value & DAEPINT_IEPITB;
}
/*!
\brief read device IN endpoint interrupt flag register
\param[in] udev: pointer to usb device
\param[in] ep_num: endpoint number
\param[out] none
\retval none
*/
uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num)
{
uint32_t value = 0U, fifoemptymask = 0U, commonintmask = 0U;
commonintmask = udev->regs.dr->DIEPINTEN;
fifoemptymask = udev->regs.dr->DIEPFEINTEN;
/* check FIFO empty interrupt enable bit */
commonintmask |= ((fifoemptymask >> ep_num) & 0x1U) << 7;
value = udev->regs.er_in[ep_num]->DIEPINTF & commonintmask;
return value;
}
/*!
\brief configures OUT endpoint 0 to receive SETUP packets
\param[in] udev: pointer to usb device
\param[out] none
\retval none
*/
void usb_ctlep_startout (usb_core_driver *udev)
{
/* set OUT endpoint 0 receive length to 24 bytes, 1 packet and 3 setup packets */
udev->regs.er_out[0]->DOEPLEN = DOEP0_TLEN(8U * 3U) | DOEP0_PCNT(1U) | DOEP0_STPCNT(3U);
if (USB_USE_DMA == udev->bp.transfer_mode) {
udev->regs.er_out[0]->DOEPDMAADDR = (uint32_t)&udev->dev.control.req;
/* endpoint enable */
udev->regs.er_out[0]->DOEPCTL |= DEPCTL_EPACT | DEPCTL_EPEN;
}
}
/*!
\brief set remote wakeup signalling
\param[in] udev: pointer to usb device
\param[out] none
\retval none
*/
void usb_rwkup_set (usb_core_driver *udev)
{
if (udev->dev.pm.dev_remote_wakeup) {
/* enable remote wakeup signaling */
udev->regs.dr->DCTL |= DCTL_RWKUP;
}
}
/*!
\brief reset remote wakeup signalling
\param[in] udev: pointer to usb device
\param[out] none
\retval none
*/
void usb_rwkup_reset (usb_core_driver *udev)
{
if (udev->dev.pm.dev_remote_wakeup) {
/* disable remote wakeup signaling */
udev->regs.dr->DCTL &= ~DCTL_RWKUP;
}
}
/*!
\brief active remote wakeup signalling
\param[in] udev: pointer to usb device
\param[out] none
\retval none
*/
void usb_rwkup_active (usb_core_driver *udev)
{
if (udev->dev.pm.dev_remote_wakeup) {
if (udev->regs.dr->DSTAT & DSTAT_SPST) {
if (udev->bp.low_power) {
/* ungate USB core clock */
*udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK);
}
/* active remote wakeup signaling */
udev->regs.dr->DCTL |= DCTL_RWKUP;
usb_mdelay(5);
udev->regs.dr->DCTL &= ~DCTL_RWKUP;
}
}
}
/*!
\brief active USB core clock
\param[in] udev: pointer to usb device
\param[out] none
\retval none
*/
void usb_clock_active (usb_core_driver *udev)
{
if (udev->bp.low_power) {
if (udev->regs.dr->DSTAT & DSTAT_SPST) {
/* un-gate USB Core clock */
*udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK);
}
}
}
/*!
\brief usb device suspend
\param[in] udev: pointer to usb device
\param[out] none
\retval none
*/
void usb_dev_suspend (usb_core_driver *udev)
{
__IO uint32_t devstat = udev->regs.dr->DSTAT;
if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) {
/* switch-off the USB clocks */
*udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK;
/* enter DEEP_SLEEP mode with LDO in low power mode */
pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD);
}
}
/*!
\brief stop the device and clean up fifos
\param[in] udev: pointer to usb device
\param[out] none
\retval none
*/
void usb_dev_stop (usb_core_driver *udev)
{
uint32_t i;
udev->dev.cur_status = 1;
/* clear all interrupt flag and enable bits */
for (i = 0; i < udev->bp.num_ep; i++) {
udev->regs.er_in[i]->DIEPINTF = 0xFFU;
udev->regs.er_out[i]->DOEPINTF = 0xFFU;
}
udev->regs.dr->DIEPINTEN = 0U;
udev->regs.dr->DOEPINTEN = 0U;
udev->regs.dr->DAEPINTEN = 0U;
udev->regs.dr->DAEPINT = 0xFFFFFFFFU;
/* flush the FIFO */
usb_rxfifo_flush (&udev->regs);
usb_txfifo_flush (&udev->regs, 0x10);
}

View File

@@ -1,514 +0,0 @@
/*!
\file drv_usb_host.c
\brief USB host mode low level driver
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "../Include/drv_usb_hw.h"
#include "../Include/drv_usb_core.h"
#include "../Include/drv_usb_host.h"
const uint32_t PIPE_DPID[] = {
PIPE_DPID_DATA0,
PIPE_DPID_DATA1
};
//__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *pudev)
uint32_t usb_frame_even (usb_core_driver *pudev)
{
return !(pudev->regs.hr->HFINFR & 0x01U);
}
//__STATIC_INLINE void usb_phyclock_config (usb_core_driver *pudev, uint8_t clock)
void usb_phyclock_config (usb_core_driver *pudev, uint8_t clock)
{
pudev->regs.hr->HCTL &= ~HCTL_CLKSEL;
pudev->regs.hr->HCTL |= clock;
}
//__STATIC_INLINE uint32_t usb_port_read (usb_core_driver *pudev)
uint32_t usb_port_read (usb_core_driver *pudev)
{
return *pudev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC);
}
//__STATIC_INLINE uint32_t usb_curspeed_get (usb_core_driver *pudev)
uint32_t usb_curspeed_get (usb_core_driver *pudev)
{
return *pudev->regs.HPCS & HPCS_PS;
}
uint32_t usb_curframe_get (usb_core_driver *pudev)
{
return (pudev->regs.hr->HFINFR & 0xFFFFU);
}
/*!
\brief initializes USB core for host mode
\param[in] pudev: pointer to selected usb host
\param[out] none
\retval operation status
*/
usb_status usb_host_init (usb_core_driver *pudev)
{
uint32_t i = 0, inten = 0U;
uint32_t nptxfifolen = 0U;
uint32_t ptxfifolen = 0U;
pudev->regs.gr->GUSBCS &= ~GUSBCS_FDM;
pudev->regs.gr->GUSBCS |= GUSBCS_FHM;
/* restart the PHY Clock */
*pudev->regs.PWRCLKCTL = 0U;
/* initialize host configuration register */
if (USB_ULPI_PHY == pudev->bp.phy_itf) {
usb_phyclock_config (pudev, HCTL_30_60MHZ);
} else {
usb_phyclock_config (pudev, HCTL_48MHZ);
}
usb_port_reset (pudev);
/* support FS/LS only */
pudev->regs.hr->HCTL &= ~HCTL_SPDFSLS;
/* configure data FIFOs size */
#ifdef USB_FS_CORE
if (USB_CORE_ENUM_FS == pudev->bp.core_enum) {
/* set Rx FIFO size */
pudev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE;
/* set non-periodic Tx FIFO size and address */
nptxfifolen |= USB_RX_FIFO_FS_SIZE;
nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U;
pudev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen;
/* set periodic Tx FIFO size and address */
ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_PFIFO_FS_SIZE;
ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U;
pudev->regs.gr->HPTFLEN = ptxfifolen;
}
#endif /* USB_FS_CORE */
#ifdef USB_HS_CORE
if (USB_CORE_HS == pudev->cfg.core) {
/* set Rx FIFO size */
pudev->regs.gr->GRFLEN = USBHS_RX_FIFO_SIZE;
/* set non-periodic Tx FIFO size and address */
nptxfifolen |= USBHS_RX_FIFO_SIZE;
nptxfifolen |= USBHS_HTX_NPFIFO_SIZE;
pudev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen;
/* set periodic Tx FIFO size and address */
ptxfifolen |= USBHS_RX_FIFO_SIZE + USBHS_HTX_PFIFO_SIZE;
ptxfifolen |= USBHS_HTX_PFIFO_SIZE;
pudev->regs.gr->HPTFLEN = ptxfifolen;
}
#endif
#ifdef USE_OTG_MODE
/* clear host set hnp enable in the usb_otg control register */
pudev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN;
#endif
/* disable all interrupts */
pudev->regs.gr->GINTEN = 0U;
/* clear any pending USB OTG interrupts */
pudev->regs.gr->GOTGINTF = 0xFFFFFFFFU;
/* enable the USB wakeup and suspend interrupts */
pudev->regs.gr->GINTF = 0xBFFFFFFFU;
/* make sure the FIFOs are flushed */
/* flush all Tx FIFOs in device or host mode */
usb_txfifo_flush (&pudev->regs, 0x10U);
/* flush the entire Rx FIFO */
usb_rxfifo_flush (&pudev->regs);
/* clear all pending host channel interrupts */
for (i = 0U; i < pudev->bp.num_pipe; i++) {
pudev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU;
pudev->regs.pr[i]->HCHINTEN = 0U;
}
#ifndef USE_OTG_MODE
usb_portvbus_switch (pudev, 1U);
#endif /* USE_OTG_MODE */
pudev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE;
/* enable host_mode-related interrupts */
if (USB_USE_FIFO == pudev->bp.transfer_mode) {
inten = GINTEN_RXFNEIE;
}
inten |= GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE;
pudev->regs.gr->GINTEN |= inten;
inten = GINTEN_DISCIE | GINTEN_SOFIE;
pudev->regs.gr->GINTEN &= ~inten;
pudev->regs.gr->GAHBCS |= GAHBCS_GINTEN;
return USB_OK;
}
/*!
\brief control the VBUS to power
\param[in] pudev: pointer to selected usb host
\param[in] state: VBUS state
\param[out] none
\retval none
*/
void usb_portvbus_switch (usb_core_driver *pudev, uint8_t state)
{
uint32_t port = 0U;
/* enable or disable the external charge pump */
usb_vbus_drive (state);
/* turn on the host port power. */
port = usb_port_read (pudev);
if (!(port & HPCS_PP) && (1U == state)) {
port |= HPCS_PP;
}
if ((port & HPCS_PP) && (0U == state)) {
port &= ~HPCS_PP;
}
*pudev->regs.HPCS = port;
usb_mdelay (200U);
}
/*!
\brief reset host port
\param[in] pudev: pointer to usb device
\param[out] none
\retval operation status
*/
uint32_t usb_port_reset (usb_core_driver *pudev)
{
__IO uint32_t port = usb_port_read (pudev);
*pudev->regs.HPCS = port | HPCS_PRST;
usb_mdelay (100U); /* see note */
*pudev->regs.HPCS = port & ~HPCS_PRST;
usb_mdelay (20U);
return 1;
}
/*!
\brief initialize host pipe
\param[in] pudev: pointer to usb device
\param[in] pipe_num: host pipe number which is in (0..7)
\param[out] none
\retval operation status
*/
usb_status usb_pipe_init (usb_core_driver *pudev, uint8_t pipe_num)
{
usb_status status = USB_OK;
__IO uint32_t pp_ctl = 0U;
__IO uint32_t pp_inten = HCHINTEN_TFIE;
usb_pipe *pp = &pudev->host.pipe[pipe_num];
/* clear old interrupt conditions for this host channel */
pudev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU;
if (USB_USE_DMA == pudev->bp.transfer_mode) {
pp_inten |= HCHINTEN_DMAERIE;
}
if (pp->ep.dir) {
pp_inten |= HCHINTEN_BBERIE;
}
/* enable channel interrupts required for this transfer */
switch (pp->ep.type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE \
| HCHINTEN_DTERIE | HCHINTEN_NAKIE;
if (!pp->ep.dir) {
pp_inten |= HCHINTEN_NYETIE;
if (pp->ping) {
pp_inten |= HCHINTEN_ACKIE;
}
}
break;
case USB_EPTYPE_INTR:
pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \
| HCHINTEN_NAKIE | HCHINTEN_REQOVRIE;
break;
case USB_EPTYPE_ISOC:
pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE;
if (pp->ep.dir) {
pp_inten |= HCHINTEN_USBERIE;
}
break;
default:
break;
}
pudev->regs.pr[pipe_num]->HCHINTEN = pp_inten;
/* enable the top level host channel interrupt */
pudev->regs.hr->HACHINTEN |= 1U << pipe_num;
/* make sure host channel interrupts are enabled */
pudev->regs.gr->GINTEN |= GINTEN_HCIE;
/* program the host channel control register */
pp_ctl |= PIPE_CTL_DAR(pp->dev_addr);
pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num);
pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir);
pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type);
pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW);
pp_ctl |= pp->ep.mps;
pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM;
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
return status;
}
/*!
\brief prepare host channel for transferring packets
\param[in] pudev: pointer to usb device
\param[in] pipe_num: host pipe number which is in (0..7)
\param[out] none
\retval operation status
*/
usb_status usb_pipe_xfer (usb_core_driver *pudev, uint8_t pipe_num)
{
usb_status status = USB_OK;
uint16_t dword_len = 0U;
uint16_t packet_count = 0U;
__IO uint32_t pp_ctl = 0U;
usb_pipe *pp = &pudev->host.pipe[pipe_num];
uint16_t max_packet_len = pp->ep.mps;
/* compute the expected number of packets associated to the transfer */
if (pp->xfer_len > 0U) {
packet_count = (pp->xfer_len + max_packet_len - 1U) / max_packet_len;
if (packet_count > HC_MAX_PACKET_COUNT) {
packet_count = HC_MAX_PACKET_COUNT;
pp->xfer_len = packet_count * max_packet_len;
}
} else {
packet_count = 1U;
}
if (pp->ep.dir) {
pp->xfer_len = packet_count * max_packet_len;
}
/* initialize the host channel transfer information */
pudev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count);
if (USB_USE_DMA == pudev->bp.transfer_mode) {
pudev->regs.pr[pipe_num]->HCHDMAADDR = (unsigned int)pp->xfer_buf;
}
pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL;
if (usb_frame_even(pudev)) {
pp_ctl |= HCHCTL_ODDFRM;
} else {
pp_ctl &= ~HCHCTL_ODDFRM;
}
/* set host channel enabled */
pp_ctl |= HCHCTL_CEN;
pp_ctl &= ~HCHCTL_CDIS;
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
if (USB_USE_FIFO == pudev->bp.transfer_mode) {
if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) {
switch (pp->ep.type) {
/* non-periodic transfer */
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
dword_len = (pp->xfer_len + 3U) / 4U;
/* check if there is enough space in fifo space */
if (dword_len > (pudev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) {
/* need to process data in nptxfempty interrupt */
pudev->regs.gr->GINTEN |= GINTEN_NPTXFEIE;
}
break;
/* periodic transfer */
case USB_EPTYPE_INTR:
case USB_EPTYPE_ISOC:
dword_len = (pp->xfer_len + 3U) / 4U;
/* check if there is enough space in fifo space */
if (dword_len > (pudev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) {
/* need to process data in ptxfempty interrupt */
pudev->regs.gr->GINTEN |= GINTEN_PTXFEIE;
}
break;
default:
break;
}
/* write packet into the tx fifo. */
usb_txfifo_write (&pudev->regs, pp->xfer_buf, pipe_num, pp->xfer_len);
}
}
return status;
}
/*!
\brief halt pipe
\param[in] pudev: pointer to usb device
\param[in] pipe_num: host pipe number which is in (0..7)
\param[out] none
\retval operation status
*/
usb_status usb_pipe_halt (usb_core_driver *pudev, uint8_t pipe_num)
{
__IO uint32_t pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL;
uint8_t ep_type = (pp_ctl & HCHCTL_EPTYPE) >> 18U;
pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS;
switch (ep_type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
if (0U == (pudev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) {
pp_ctl &= ~HCHCTL_CEN;
}
break;
case USB_EPTYPE_INTR:
case USB_EPTYPE_ISOC:
if (0U == (pudev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) {
pp_ctl &= ~HCHCTL_CEN;
}
break;
default:
break;
}
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
return USB_OK;
}
/*!
\brief configure host pipe to do ping operation
\param[in] pudev: pointer to usb device
\param[in] pipe_num: host pipe number which is in (0..7)
\param[out] none
\retval operation status
*/
usb_status usb_pipe_ping (usb_core_driver *pudev, uint8_t pipe_num)
{
uint32_t pp_ctl = 0U;
pudev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U));
pp_ctl = pudev->regs.pr[pipe_num]->HCHCTL;
pp_ctl |= HCHCTL_CEN;
pp_ctl &= ~HCHCTL_CDIS;
pudev->regs.pr[pipe_num]->HCHCTL = pp_ctl;
return USB_OK;
}
/*!
\brief stop the USB host and clean up FIFO
\param[in] none
\param[out] none
\retval none
*/
void usb_host_stop (usb_core_driver *pudev)
{
uint32_t i;
__IO uint32_t pp_ctl = 0U;
pudev->regs.hr->HACHINTEN = 0x0U;
pudev->regs.hr->HACHINT = 0xFFFFFFFFU;
/* flush out any leftover queued requests. */
for (i = 0U; i < pudev->bp.num_pipe; i++) {
pp_ctl = pudev->regs.pr[i]->HCHCTL;
pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR);
pp_ctl |= HCHCTL_CDIS;
pudev->regs.pr[i]->HCHCTL = pp_ctl;
}
/* flush the FIFO */
usb_rxfifo_flush (&pudev->regs);
usb_txfifo_flush (&pudev->regs, 0x10U);
}

View File

@@ -1,595 +0,0 @@
/*!
\file drv_usbd_int.c
\brief USB device mode interrupt routines
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "usbd_conf.h"
#include "drv_usbd_int.h"
#include "usbd_transc.h"
static uint32_t usbd_int_epout (usb_core_driver *udev);
static uint32_t usbd_int_epin (usb_core_driver *udev);
static uint32_t usbd_int_rxfifo (usb_core_driver *udev);
static uint32_t usbd_int_reset (usb_core_driver *udev);
static uint32_t usbd_int_enumfinish (usb_core_driver *udev);
static uint32_t usbd_int_suspend (usb_core_driver *udev);
static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num);
static const uint8_t USB_SPEED[4] = {
[DSTAT_EM_HS_PHY_30MHZ_60MHZ] = USB_SPEED_HIGH,
[DSTAT_EM_FS_PHY_30MHZ_60MHZ] = USB_SPEED_FULL,
[DSTAT_EM_FS_PHY_48MHZ] = USB_SPEED_FULL,
[DSTAT_EM_LS_PHY_6MHZ] = USB_SPEED_LOW
};
__IO uint8_t setupc_flag = 0U;
#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED
/*!
\brief USB dedicated OUT endpoint 1 interrupt service routine handler
\param[in] udev: pointer to usb device instance
\param[out] none
\retval operation status
*/
uint32_t USBD_OTG_EP1OUT_ISR_Handler (usb_core_driver *udev)
{
uint32_t oepintr = 0U;
uint32_t oeplen = 0U;
oepintr = udev->regs.er_out[1]->DOEPINTF;
oepintr &= udev->regs.dr->DOEP1INTEN;
/* Transfer complete */
if (oepintr & DOEPINTF_TF)
{
/* Clear the bit in DOEPINTn for this interrupt */
udev->regs.er_out[1]->DOEPINTF = DOEPINTF_TF;
if (USB_USE_DMA == udev->bp.transfer_mode)
{
oeplen = udev->regs.er_out[1]->DOEPLEN;
/* ToDo : handle more than one single MPS size packet */
udev->dev.transc_out[1].xfer_count = udev->dev.transc_out[1].usb_transc - \
oeplen & DEPLEN_TLEN;
}
/* RX COMPLETE */
USBD_DCD_INT_fops->DataOutStage(udev, 1);
}
return 1;
}
/*!
\brief USB dedicated IN endpoint 1 interrupt service routine handler
\param[in] udev: pointer to usb device instance
\param[out] none
\retval operation status
*/
uint32_t USBD_OTG_EP1IN_ISR_Handler (usb_core_driver *udev)
{
uint32_t inten, intr, emptyen;
inten = udev->regs.dr->DIEP1INTEN;
emptyen = udev->regs.dr->DIEPFEINTEN;
inten |= ((emptyen >> 1 ) & 0x1) << 7;
intr = udev->regs.er_in[1]->DIEPINTF & inten;
if (intr & DIEPINTF_TF)
{
udev->regs.dr->DIEPFEINTEN &= ~(0x1 << 1);
udev->regs.er_in[1]->DIEPINTF = DIEPINTF_TF;
/* TX COMPLETE */
USBD_DCD_INT_fops->DataInStage(udev, 1);
}
if (intr & DIEPINTF_TXFE)
{
DCD_WriteEmptyTxFifo(udev, 1);
udev->regs.er_in[1]->DIEPINTF = DIEPINTF_TXFE;
}
return 1;
}
#endif
/*!
\brief USB device-mode interrupts global service routine handler
\param[in] udev: pointer to usb device instance
\param[out] none
\retval none
*/
void usbd_isr (usb_core_driver *udev)
{
if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) {
uint32_t intr = udev->regs.gr->GINTF & udev->regs.gr->GINTEN;
/* there are no interrupts, avoid spurious interrupt */
if (!intr) {
return;
}
/* OUT endpoints interrupts */
if (intr & GINTF_OEPIF) {
usbd_int_epout (udev);
}
/* IN endpoints interrupts */
if (intr & GINTF_IEPIF) {
usbd_int_epin (udev);
}
/* suspend interrupt */
if (intr & GINTF_SP) {
usbd_int_suspend (udev);
}
/* wakeup interrupt */
if (intr & GINTF_WKUPIF) {
/* inform upper layer by the resume event */
udev->dev.cur_status = udev->dev.backup_status;
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_WKUPIF;
}
/* wakeup interrupt */
if (intr & GINTF_MFIF) {
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_MFIF;
}
/* start of frame interrupt */
if (intr & GINTF_SOF) {
if (udev->dev.class_core->SOF) {
udev->dev.class_core->SOF(udev);
}
if (0U != setupc_flag) {
setupc_flag ++;
if (setupc_flag >= 3U) {
usbd_setup_transc (udev);
setupc_flag = 0U;
}
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_SOF;
}
/* receive FIFO not empty interrupt */
if (intr & GINTF_RXFNEIF) {
usbd_int_rxfifo (udev);
}
/* USB reset interrupt */
if (intr & GINTF_RST) {
usbd_int_reset (udev);
}
/* enumeration has been done interrupt */
if (intr & GINTF_ENUMFIF) {
usbd_int_enumfinish (udev);
}
/* incomplete synchronization IN transfer interrupt*/
if (intr & GINTF_ISOINCIF) {
if (NULL != udev->dev.class_core->incomplete_isoc_in) {
udev->dev.class_core->incomplete_isoc_in(udev);
}
/* Clear interrupt */
udev->regs.gr->GINTF = GINTF_ISOINCIF;
}
/* incomplete synchronization OUT transfer interrupt*/
if (intr & GINTF_ISOONCIF) {
if (NULL != udev->dev.class_core->incomplete_isoc_out) {
udev->dev.class_core->incomplete_isoc_out(udev);
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_ISOONCIF;
}
#ifdef VBUS_SENSING_ENABLED
/* Session request interrupt */
if (intr & GINTF_SESIF) {
udev->regs.gr->GINTF = GINTF_SESIF;
}
/* OTG mode interrupt */
if (intr & GINTF_OTGIF) {
if(udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) {
}
/* Clear OTG interrupt */
udev->regs.gr->GINTF = GINTF_OTGIF;
}
#endif
}
}
/*!
\brief indicates that an OUT endpoint has a pending interrupt
\param[in] udev: pointer to usb device instance
\param[out] none
\retval operation status
*/
static uint32_t usbd_int_epout (usb_core_driver *udev)
{
uint32_t epintnum = 0U;
uint32_t ep_num = 0U;
for (epintnum = usb_oepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) {
if (epintnum & 0x1) {
__IO uint32_t oepintr = usb_oepintr_read (udev, ep_num);
/* transfer complete interrupt */
if (oepintr & DOEPINTF_TF) {
/* clear the bit in DOEPINTF for this interrupt */
udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF;
if (USB_USE_DMA == udev->bp.transfer_mode) {
__IO uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN;
udev->dev.transc_out[ep_num].xfer_count = udev->dev.transc_out[ep_num].max_len - \
eplen & DEPLEN_TLEN;
}
/* inform upper layer: data ready */
usbd_out_transc (udev, ep_num);
if (USB_USE_DMA == udev->bp.transfer_mode) {
if ((0U == ep_num) && (USB_CTL_STATUS_OUT == udev->dev.control.ctl_state)) {
usb_ctlep_startout (udev);
}
}
}
/* setup phase finished interrupt (control endpoints) */
if (oepintr & DOEPINTF_STPF) {
/* inform the upper layer that a setup packet is available */
if ((0U == ep_num) && (0U != setupc_flag)) {
usbd_setup_transc (udev);
setupc_flag = 0U;
udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF;
}
}
}
}
return 1;
}
/*!
\brief indicates that an IN endpoint has a pending interrupt
\param[in] udev: pointer to usb device instance
\param[out] none
\retval operation status
*/
static uint32_t usbd_int_epin (usb_core_driver *udev)
{
uint32_t epintnum = 0U;
uint32_t ep_num = 0U;
for (epintnum = usb_iepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) {
if (epintnum & 0x1U) {
__IO uint32_t iepintr = usb_iepintr_read (udev, ep_num);
if (iepintr & DIEPINTF_TF) {
udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF;
/* data transmittion is completed */
usbd_in_transc (udev, ep_num);
if (USB_USE_DMA == udev->bp.transfer_mode) {
if ((0U == ep_num) && (USB_CTL_STATUS_IN == udev->dev.control.ctl_state)) {
usb_ctlep_startout (udev);
}
}
}
if (iepintr & DIEPINTF_TXFE) {
usbd_emptytxfifo_write (udev, ep_num);
udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE;
}
}
}
return 1;
}
/*!
\brief handle the RX status queue level interrupt
\param[in] udev: pointer to usb device instance
\param[out] none
\retval operation status
*/
static uint32_t usbd_int_rxfifo (usb_core_driver *udev)
{
usb_transc *transc = NULL;
uint8_t data_PID = 0;
uint32_t bcount = 0;
__IO uint32_t devrxstat = 0;
/* disable the Rx status queue non-empty interrupt */
udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE;
/* get the status from the top of the FIFO */
devrxstat = udev->regs.gr->GRSTATP;
transc = &udev->dev.transc_out[devrxstat & GRSTATRP_EPNUM];
bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4;
data_PID = (devrxstat & GRSTATRP_DPID) >> 15;
switch ((devrxstat & GRSTATRP_RPCKST) >> 17) {
case RSTAT_GOUT_NAK:
break;
case RSTAT_DATA_UPDT:
if (bcount > 0) {
usb_rxfifo_read (&udev->regs, transc->xfer_buf, bcount);
transc->xfer_buf += bcount;
transc->xfer_count += bcount;
}
break;
case RSTAT_XFER_COMP:
/* trigger the OUT enpoint interrupt */
break;
case RSTAT_SETUP_COMP:
/* trigger the OUT enpoint interrupt */
break;
case RSTAT_SETUP_UPDT:
if ((transc->ep_addr.num == 0) && (bcount == 8) && (data_PID == DPID_DATA0)) {
/* copy the setup packet received in FIFO into the setup buffer in RAM */
usb_rxfifo_read (&udev->regs, (uint8_t *)&udev->dev.control.req, bcount);
transc->xfer_count += bcount;
setupc_flag = 1;
}
break;
default:
break;
}
/* enable the Rx status queue level interrupt */
udev->regs.gr->GINTEN |= GINTEN_RXFNEIE;
return 1;
}
/*!
\brief handle USB reset interrupt
\param[in] udev: pointer to usb device instance
\param[out] none
\retval status
*/
static uint32_t usbd_int_reset (usb_core_driver *udev)
{
uint32_t i;
/* clear the remote wakeup signaling */
udev->regs.dr->DCTL &= ~DCTL_RWKUP;
/* flush the Tx FIFO */
usb_txfifo_flush (&udev->regs, 0);
for (i = 0; i < udev->bp.num_ep; i++) {
udev->regs.er_in[i]->DIEPINTF = 0xFFU;
udev->regs.er_out[i]->DOEPINTF = 0xFFU;
}
/* clear all pending device endpoint interrupts */
udev->regs.dr->DAEPINT = 0xFFFFFFFFU;
/* enable endpoint 0 interrupts */
udev->regs.dr->DAEPINTEN = 1U | (1U << 16);
/* enable OUT endpoint interrupts */
udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN;
/* enable IN endpoint interrupts */
udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN;
/* reset device address */
udev->regs.dr->DCFG &= ~DCFG_DAR;
udev->dev.dev_addr = 0U;
/* configure endpoint 0 to receive SETUP packets */
usb_ctlep_startout (udev);
/* clear USB reset interrupt */
udev->regs.gr->GINTF = GINTF_RST;
udev->dev.transc_out[0] = (usb_transc) {
.ep_type = USB_EPTYPE_CTRL,
.max_len = USB_FS_EP0_MAX_LEN
};
usb_transc_active (udev, &udev->dev.transc_out[0]);
udev->dev.transc_in[0] = (usb_transc) {
.ep_addr = {
.dir = 1
},
.ep_type = USB_EPTYPE_CTRL,
.max_len = USB_FS_EP0_MAX_LEN
};
usb_transc_active (udev, &udev->dev.transc_in[0]);
/* upon reset call usr call back */
udev->dev.cur_status = USBD_DEFAULT;
return 1;
}
/*!
\brief handle USB speed enumeration finish interrupt
\param[in] udev: pointer to usb device instance
\param[out] none
\retval status
*/
static uint32_t usbd_int_enumfinish (usb_core_driver *udev)
{
uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U);
udev->regs.dr->DCTL &= ~DCTL_CGINAK;
udev->regs.dr->DCTL |= DCTL_CGINAK;
udev->regs.gr->GUSBCS &= ~GUSBCS_UTT;
/* set USB turn-around time based on device speed and PHY interface */
if (USB_SPEED[enum_speed] == USB_SPEED_HIGH) {
udev->bp.core_speed = USB_SPEED_HIGH;
udev->regs.gr->GUSBCS |= 0x09 << 10;
} else {
udev->bp.core_speed = USB_SPEED_FULL;
udev->regs.gr->GUSBCS |= 0x05 << 10;
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_ENUMFIF;
return 1;
}
/*!
\brief USB suspend interrupt handler
\param[in] udev: pointer to USB device instance
\param[out] none
\retval operation status
*/
static uint32_t usbd_int_suspend (usb_core_driver *udev)
{
__IO uint8_t low_power = udev->bp.low_power;
__IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST);
__IO uint8_t is_configured = (udev->dev.cur_status == USBD_CONFIGURED)? 1U : 0U;
udev->dev.backup_status = udev->dev.cur_status;
udev->dev.cur_status = USBD_SUSPENDED;
if (low_power && suspend && is_configured) {
/* switch-off the otg clocks */
*udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK;
/* enter DEEP_SLEEP mode with LDO in low power mode */
pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD);
}
/* clear interrupt */
udev->regs.gr->GINTF = GINTF_SP;
return 1U;
}
/*!
\brief check FIFO for the next packet to be loaded
\param[in] udev: pointer to usb device instance
\param[in] ep_num: endpoint identifier which is in (0..3)
\param[out] none
\retval status
*/
static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num)
{
usb_transc *transc = NULL;
uint32_t len = 0;
uint32_t word_count = 0;
transc = &udev->dev.transc_in[ep_num];
len = transc->xfer_len - transc->xfer_count;
/* get the data length to write */
if (len > transc->max_len) {
len = transc->max_len;
}
word_count = (len + 3) / 4;
while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) > word_count) && \
(transc->xfer_count < transc->xfer_len)) {
len = transc->xfer_len - transc->xfer_count;
if (len > transc->max_len) {
len = transc->max_len;
}
/* write FIFO in word(4bytes) */
word_count = (len + 3) / 4;
/* write the FIFO */
usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, len);
transc->xfer_buf += len;
transc->xfer_count += len;
if (transc->xfer_count == transc->xfer_len) {
/* disable the device endpoint FIFO empty interrupt */
udev->regs.dr->DIEPFEINTEN &= ~(0x01 << ep_num);
}
}
return 1;
}

View File

@@ -1,536 +0,0 @@
/*!
\file drv_usbh_int.c
\brief USB host mode interrupt handler file
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "../Include/drv_usb_core.h"
#include "../Include/drv_usb_host.h"
#include "../Include/drv_usbh_int.h"
#if defined (__GNUC__) /*!< GNU compiler */
#pragma GCC optimize ("O0")
#endif /* __GNUC__ */
static uint32_t usbh_int_port (usb_core_driver *pudev);
static uint32_t usbh_int_pipe (usb_core_driver *pudev);
static uint32_t usbh_int_pipe_in (usb_core_driver *pudev, uint32_t pp_num);
static uint32_t usbh_int_pipe_out (usb_core_driver *pudev, uint32_t pp_num);
static uint32_t usbh_int_rxfifonoempty (usb_core_driver *pudev);
static uint32_t usbh_int_txfifoempty (usb_core_driver *pudev, usb_pipe_mode pp_mode);
static inline void usb_pp_halt (usb_core_driver *pudev,
uint8_t pp_num,
uint32_t pp_int,
usb_pipe_staus pp_status)
{
pudev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE;
usb_pipe_halt(pudev, pp_num);
pudev->regs.pr[pp_num]->HCHINTF = pp_int;
pudev->host.pipe[pp_num].pp_status = pp_status;
}
/*!
\brief handle global host interrupt
\param[in] pudev: pointer to usb core instance
\param[out] none
\retval operation status
*/
uint32_t usbh_isr (usb_core_driver *pudev)
{
uint32_t Retval = 0U;
__IO uint32_t intr = 0U;
/* check if host mode */
if (HOST_MODE == (pudev->regs.gr->GINTF & GINTF_COPM)) {
intr = usb_coreintr_get(&pudev->regs);
if (!intr) {
return 0;
}
if (intr & GINTF_SOF) {
usbh_int_fop->SOF(pudev);
/* clear interrupt */
pudev->regs.gr->GINTF = GINTF_SOF;
}
if (intr & GINTF_RXFNEIF) {
Retval |= usbh_int_rxfifonoempty (pudev);
}
if (intr & GINTF_NPTXFEIF) {
Retval |= usbh_int_txfifoempty (pudev, PIPE_NON_PERIOD);
}
if (intr & GINTF_PTXFEIF) {
Retval |= usbh_int_txfifoempty (pudev, PIPE_PERIOD);
}
if (intr & GINTF_HCIF) {
Retval |= usbh_int_pipe (pudev);
}
if (intr & GINTF_HPIF) {
Retval |= usbh_int_port (pudev);
}
if (intr & GINTF_DISCIF) {
pudev->host.connect_status = 0U;
/* clear interrupt */
pudev->regs.gr->GINTF = GINTF_DISCIF;
}
if (intr & GINTF_ISOONCIF) {
pudev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS;
/* clear interrupt */
pudev->regs.gr->GINTF = GINTF_ISOONCIF;
}
}
return Retval;
}
/*!
\brief handle all host channels interrupt
\param[in] pudev: pointer to usb device instance
\param[out] none
\retval operation status
*/
static uint32_t usbh_int_pipe (usb_core_driver *pudev)
{
uint32_t pp_num = 0U;
uint32_t retval = 0U;
for (pp_num = 0U; pp_num < pudev->bp.num_pipe; pp_num++) {
if ((pudev->regs.hr->HACHINT & HACHINT_HACHINT) & (1U << pp_num)) {
if (pudev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) {
retval |= usbh_int_pipe_in (pudev, pp_num);
} else {
retval |= usbh_int_pipe_out (pudev, pp_num);
}
}
}
return retval;
}
/*!
\brief handle the TX FIFO empty interrupt
\param[in] pudev: pointer to usb device instance
\param[out] none
\retval operation status
*/
static uint32_t usbh_int_txfifoempty (usb_core_driver *pudev, usb_pipe_mode pp_mode)
{
uint8_t pp_num = 0U;
uint16_t word_count = 0U, len = 0U;
__IO uint32_t *txfiforeg = 0U, txfifostate = 0U;
if (PIPE_NON_PERIOD == pp_mode) {
txfiforeg = &pudev->regs.gr->HNPTFQSTAT;
} else if (PIPE_PERIOD == pp_mode) {
txfiforeg = &pudev->regs.hr->HPTFQSTAT;
} else {
return 0U;
}
txfifostate = *txfiforeg;
pp_num = (txfifostate & TFQSTAT_CNUM) >> 27U;
word_count = (pudev->host.pipe[pp_num].xfer_len + 3U) / 4U;
while (((txfifostate & TFQSTAT_TXFS) > word_count) && (0U != pudev->host.pipe[pp_num].xfer_len)) {
len = (txfifostate & TFQSTAT_TXFS) * 4U;
if (len > pudev->host.pipe[pp_num].xfer_len) {
/* last packet */
len = pudev->host.pipe[pp_num].xfer_len;
if (PIPE_NON_PERIOD == pp_mode) {
pudev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE;
} else {
pudev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE;
}
}
word_count = (pudev->host.pipe[pp_num].xfer_len + 3U) / 4U;
usb_txfifo_write (&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, pp_num, len);
pudev->host.pipe[pp_num].xfer_buf += len;
pudev->host.pipe[pp_num].xfer_len -= len;
pudev->host.pipe[pp_num].xfer_count += len;
txfifostate = *txfiforeg;
}
return 1;
}
/*!
\brief handle the host port interrupt
\param[in] pudev: pointer to usb device instance
\param[out] none
\retval operation status
*/
static uint32_t usbh_int_port (usb_core_driver *pudev)
{
uint32_t retval = 0U;
__IO uint32_t port_state = *pudev->regs.HPCS;
/* clear the interrupt bits in GINTSTS */
port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC);
/* port connect detected */
if (*pudev->regs.HPCS & HPCS_PCD) {
port_state |= HPCS_PCD;
pudev->host.connect_status = 1U;
retval |= 1U;
}
/* port enable changed */
if (*pudev->regs.HPCS & HPCS_PEDC) {
port_state |= HPCS_PEDC;
if (*pudev->regs.HPCS & HPCS_PE) {
uint32_t port_speed = usb_curspeed_get(pudev);
uint32_t clock_type = pudev->regs.hr->HCTL & HCTL_CLKSEL;
pudev->host.connect_status = 1U;
if (PORT_SPEED_LOW == port_speed) {
pudev->regs.hr->HFT = 6000U;
if (HCTL_6MHZ != clock_type) {
if (USB_EMBEDDED_PHY == pudev->bp.phy_itf) {
usb_phyclock_config (pudev, HCTL_6MHZ);
}
}
} else if (PORT_SPEED_FULL == port_speed) {
pudev->regs.hr->HFT = 48000U;
if (HCTL_48MHZ != clock_type) {
usb_phyclock_config (pudev, HCTL_48MHZ);
}
} else {
/* for high speed device and others */
}
pudev->host.port_enabled = 1U;
pudev->regs.gr->GINTEN |= GINTEN_DISCIE;
} else {
pudev->host.port_enabled = 0U;
}
}
/* clear port interrupts */
*pudev->regs.HPCS = port_state;
return retval;
}
/*!
\brief handle the OUT channel interrupt
\param[in] pudev: pointer to usb device instance
\param[in] pp_num: host channel number which is in (0..7)
\param[out] none
\retval operation status
*/
uint32_t usbh_int_pipe_out (usb_core_driver *pudev, uint32_t pp_num)
{
usb_pr *pp_reg = pudev->regs.pr[pp_num];
usb_pipe *pp = &pudev->host.pipe[pp_num];
uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN;
if (intr_pp & HCHINTF_ACK) {
pp_reg->HCHINTF = HCHINTF_ACK;
} else if (intr_pp & HCHINTF_STALL) {
usb_pp_halt (pudev, pp_num, HCHINTF_STALL, PIPE_STALL);
} else if (intr_pp & HCHINTF_DTER) {
usb_pp_halt (pudev, pp_num, HCHINTF_DTER, PIPE_DTGERR);
pp_reg->HCHINTF = HCHINTF_NAK;
} else if (intr_pp & HCHINTF_REQOVR) {
usb_pp_halt (pudev, pp_num, HCHINTF_REQOVR, PIPE_REQOVR);
} else if (intr_pp & HCHINTF_TF) {
pp->err_count = 0U;
usb_pp_halt (pudev, pp_num, HCHINTF_TF, PIPE_XF);
} else if (intr_pp & HCHINTF_NAK) {
pp->err_count = 0U;
usb_pp_halt (pudev, pp_num, HCHINTF_NAK, PIPE_NAK);
} else if (intr_pp & HCHINTF_USBER) {
pp->err_count++;
usb_pp_halt (pudev, pp_num, HCHINTF_USBER, PIPE_TRACERR);
} else if (intr_pp & HCHINTF_NYET) {
pp->err_count = 0U;
usb_pp_halt (pudev, pp_num, HCHINTF_NYET, PIPE_NYET);
} else if (intr_pp & HCHINTF_CH) {
pudev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE;
switch (pp->pp_status) {
case PIPE_XF:
pp->urb_state = URB_DONE;
if (USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) {
pp->data_toggle_out ^= 1U;
}
break;
case PIPE_NAK:
pp->urb_state = URB_NOTREADY;
break;
case PIPE_NYET:
if (1U == pudev->host.pipe[pp_num].ping) {
usb_pipe_ping (pudev, pp_num);
}
pp->urb_state = URB_NOTREADY;
break;
case PIPE_STALL:
pp->urb_state = URB_STALL;
break;
case PIPE_TRACERR:
if (3U == pp->err_count) {
pp->urb_state = URB_ERROR;
pp->err_count = 0U;
}
break;
default:
break;
}
pp_reg->HCHINTF = HCHINTF_CH;
}
return 1;
}
/*!
\brief handle the IN channel interrupt
\param[in] pudev: pointer to usb device instance
\param[in] pp_num: host channel number which is in (0..7)
\param[out] none
\retval operation status
*/
uint32_t usbh_int_pipe_in (usb_core_driver *pudev, uint32_t pp_num)
{
usb_pr *pp_reg = pudev->regs.pr[pp_num];
usb_pipe *pp = &pudev->host.pipe[pp_num];
__IO uint32_t intr_pp = pp_reg->HCHINTF & pp_reg->HCHINTEN;
uint8_t ep_type = (pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U;
if (intr_pp & HCHINTF_ACK) {
pp_reg->HCHINTF = HCHINTF_ACK;
} else if (intr_pp & HCHINTF_STALL) {
usb_pp_halt (pudev, pp_num, HCHINTF_STALL, PIPE_STALL);
pp_reg->HCHINTF = HCHINTF_NAK;
/* note: When there is a 'STALL', reset also nak,
else, the pudev->host.pp_status = HC_STALL
will be overwritten by 'NAK' in code below */
intr_pp &= ~HCHINTF_NAK;
} else if (intr_pp & HCHINTF_DTER) {
usb_pp_halt (pudev, pp_num, HCHINTF_DTER, PIPE_DTGERR);
pp_reg->HCHINTF = HCHINTF_NAK;
}
if (intr_pp & HCHINTF_REQOVR) {
usb_pp_halt (pudev, pp_num, HCHINTF_REQOVR, PIPE_REQOVR);
} else if (intr_pp & HCHINTF_TF) {
if (USB_USE_DMA == pudev->bp.transfer_mode) {
pudev->host.backup_xfercount[pp_num] = pp->xfer_len - pp_reg->HCHLEN & HCHLEN_TLEN;
}
pp->pp_status = PIPE_XF;
pp->err_count = 0U;
pp_reg->HCHINTF = HCHINTF_TF;
switch (ep_type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
usb_pp_halt (pudev, pp_num, HCHINTF_NAK, PIPE_XF);
pp->data_toggle_in ^= 1U;
break;
case USB_EPTYPE_INTR:
pp_reg->HCHCTL |= HCHCTL_ODDFRM;
pp->urb_state = URB_DONE;
break;
default:
break;
}
} else if (intr_pp & HCHINTF_CH) {
pp_reg->HCHINTEN &= ~HCHINTEN_CHIE;
switch (pp->pp_status) {
case PIPE_XF:
pp->urb_state = URB_DONE;
break;
case PIPE_STALL:
pp->urb_state = URB_STALL;
break;
case PIPE_TRACERR:
case PIPE_DTGERR:
pp->err_count = 0U;
pp->urb_state = URB_ERROR;
break;
default:
if(USB_EPTYPE_INTR == ep_type) {
pp->data_toggle_in ^= 1U;
}
break;
}
pp_reg->HCHINTF = HCHINTF_CH;
} else if (intr_pp & HCHINTF_BBER) {
pp->err_count++;
usb_pp_halt (pudev, pp_num, HCHINTF_BBER, PIPE_TRACERR);
} else if (intr_pp & HCHINTF_NAK) {
switch (ep_type) {
case USB_EPTYPE_CTRL:
case USB_EPTYPE_BULK:
/* re-activate the channel */
pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS;
break;
case USB_EPTYPE_INTR:
pp_reg->HCHINTEN |= HCHINTEN_CHIE;
usb_pipe_halt(pudev, pp_num);
break;
default:
break;
}
pp->pp_status = PIPE_NAK;
pp_reg->HCHINTF = HCHINTF_NAK;
}
return 1;
}
/*!
\brief handle the rx fifo non-empty interrupt
\param[in] pudev: pointer to usb device instance
\param[out] none
\retval operation status
*/
static uint32_t usbh_int_rxfifonoempty (usb_core_driver *pudev)
{
uint32_t count = 0U;
__IO uint8_t pp_num = 0U;
__IO uint32_t rx_stat = 0U;
/* disable the rx status queue level interrupt */
pudev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE;
rx_stat = pudev->regs.gr->GRSTATP;
pp_num = rx_stat & GRSTATRP_CNUM;
switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) {
case GRXSTS_PKTSTS_IN:
count = (rx_stat & GRSTATRP_BCOUNT) >> 4U;
/* read the data into the host buffer. */
if ((count > 0U) && (NULL != pudev->host.pipe[pp_num].xfer_buf)) {
usb_rxfifo_read (&pudev->regs, pudev->host.pipe[pp_num].xfer_buf, count);
/* manage multiple transfer packet */
pudev->host.pipe[pp_num].xfer_buf += count;
pudev->host.pipe[pp_num].xfer_count += count;
pudev->host.backup_xfercount[pp_num] = pudev->host.pipe[pp_num].xfer_count;
if (pudev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) {
/* re-activate the channel when more packets are expected */
__IO uint32_t pp_ctl = pudev->regs.pr[pp_num]->HCHCTL;
pp_ctl |= HCHCTL_CEN;
pp_ctl &= ~HCHCTL_CDIS;
pudev->regs.pr[pp_num]->HCHCTL = pp_ctl;
}
}
break;
case GRXSTS_PKTSTS_IN_XFER_COMP:
break;
case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
count = (rx_stat & GRSTATRP_BCOUNT) >> 4U;
while (count > 0U) {
rx_stat = pudev->regs.gr->GRSTATP;
count--;
}
break;
case GRXSTS_PKTSTS_CH_HALTED:
break;
default:
break;
}
/* enable the rx status queue level interrupt */
pudev->regs.gr->GINTEN |= GINTEN_RXFNEIE;
return 1;
}

View File

@@ -1,329 +0,0 @@
/*!
\file usbd_core.c
\brief USB device mode core functions
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "../Include/usbd_core.h"
#include "../Include/drv_usb_hw.h"
/* endpoint type */
const uint32_t ep_type[] = {
[USB_EP_ATTR_CTL] = USB_EPTYPE_CTRL,
[USB_EP_ATTR_BULK] = USB_EPTYPE_BULK,
[USB_EP_ATTR_INT] = USB_EPTYPE_INTR,
[USB_EP_ATTR_ISO] = USB_EPTYPE_ISOC
};
/*!
\brief initailizes the USB device-mode stack and load the class driver
\param[in] udev: pointer to USB core instance
\param[in] core: usb core type
\param[in] class_core: class driver
\param[out] none
\retval none
*/
void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_class_core *class_core)
{
/* device descriptor, class and user callbacks */
udev->dev.class_core = class_core;
/* configure USB capabilites */
usb_basic_init (&udev->bp, &udev->regs, core);
/* initailizes the USB core*/
usb_core_init (udev->bp, &udev->regs);
/* set device disconnect */
usbd_disconnect (udev);
/* initailizes device mode */
usb_devcore_init (udev);
/* set device connect */
usbd_connect (udev);
udev->dev.cur_status = USBD_DEFAULT;
}
/*!
\brief endpoint initialization
\param[in] udev: pointer to USB core instance
\param[in] ep_desc: pointer to endpoint descriptor
\param[out] none
\retval none
*/
uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc)
{
usb_transc *transc;
uint8_t ep_addr = ep_desc->bEndpointAddress;
uint8_t max_len = ep_desc->wMaxPacketSize;
/* set endpoint direction */
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
transc->ep_addr.dir = 1U;
} else {
transc = &udev->dev.transc_out[ep_addr];
transc->ep_addr.dir = 0U;
}
transc->ep_addr.num = EP_ID(ep_addr);
transc->max_len = max_len;
transc->ep_type = ep_type[ep_desc->bmAttributes & USB_EPTYPE_MASK];
/* active USB endpoint function */
usb_transc_active (udev, transc);
return 0;
}
/*!
\brief configure the endpoint when it is disabled
\param[in] udev: pointer to USB core instance
\param[in] ep_addr: endpoint address
in this parameter:
bit0..bit6: endpoint number (0..7)
bit7: endpoint direction which can be IN(1) or OUT(0)
\param[out] none
\retval none
*/
uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr)
{
usb_transc *transc;
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
} else {
transc = &udev->dev.transc_out[ep_addr];
}
/* deactive USB endpoint function */
usb_transc_deactivate (udev, transc);
return 0;
}
/*!
\brief endpoint prepare to receive data
\param[in] udev: pointer to usb core instance
\param[in] ep_addr: endpoint address
in this parameter:
bit0..bit6: endpoint number (0..7)
bit7: endpoint direction which can be IN(1) or OUT(0)
\param[in] pbuf: user buffer address pointer
\param[in] len: buffer length
\param[out] none
\retval none
*/
uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t len)
{
usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)];
/* setup the transfer */
transc->xfer_buf = pbuf;
transc->xfer_len = len;
transc->xfer_count = 0;
if (USB_USE_DMA == udev->bp.transfer_mode) {
transc->dma_addr = (uint32_t)pbuf;
}
/* start the transfer */
usb_transc_outxfer (udev, transc);
return 0;
}
/*!
\brief endpoint prepare to transmit data
\param[in] udev: pointer to USB core instance
\param[in] ep_addr: endpoint address
in this parameter:
bit0..bit6: endpoint number (0..7)
bit7: endpoint direction which can be IN(1) or OUT(0)
\param[in] pbuf: transmit buffer address pointer
\param[in] len: buffer length
\param[out] none
\retval none
*/
uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint16_t len)
{
usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)];
/* setup the transfer */
transc->xfer_buf = pbuf;
transc->xfer_len = len;
transc->xfer_count = 0;
if (USB_USE_DMA == udev->bp.transfer_mode) {
transc->dma_addr = (uint32_t)pbuf;
}
/* start the transfer */
usb_transc_inxfer (udev, transc);
return 0;
}
/*!
\brief set an endpoint to STALL status
\param[in] udev: pointer to USB core instance
\param[in] ep_addr: endpoint address
in this parameter:
bit0..bit6: endpoint number (0..7)
bit7: endpoint direction which can be IN(1) or OUT(0)
\param[out] none
\retval none
*/
uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr)
{
usb_transc *transc = NULL;
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
} else {
transc = &udev->dev.transc_out[ep_addr];
}
transc->ep_stall = 1;
usb_transc_stall (udev, transc);
return (0);
}
/*!
\brief clear endpoint STALLed status
\param[in] udev: pointer to usb core instance
\param[in] ep_addr: endpoint address
in this parameter:
bit0..bit6: endpoint number (0..7)
bit7: endpoint direction which can be IN(1) or OUT(0)
\param[out] none
\retval none
*/
uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr)
{
usb_transc *transc = NULL;
if (EP_DIR(ep_addr)) {
transc = &udev->dev.transc_in[EP_ID(ep_addr)];
} else {
transc = &udev->dev.transc_out[ep_addr];
}
transc->ep_stall = 0;
usb_transc_clrstall (udev, transc);
return (0);
}
/*!
\brief flush the endpoint FIFOs
\param[in] udev: pointer to usb core instance
\param[in] ep_addr: endpoint address
in this parameter:
bit0..bit6: endpoint number (0..7)
bit7: endpoint direction which can be IN(1) or OUT(0)
\param[out] none
\retval none
*/
uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr)
{
if (EP_DIR(ep_addr)) {
usb_txfifo_flush (&udev->regs, EP_ID(ep_addr));
} else {
usb_rxfifo_flush (&udev->regs);
}
return (0);
}
/*!
\brief set USB device address
\param[in] udev: pointer to USB core instance
\param[in] addr: device address to set
\param[out] none
\retval none
*/
void usbd_addr_set (usb_core_driver *udev, uint8_t addr)
{
usb_devaddr_set(udev, addr);
}
/*!
\brief get the received data length
\param[in] udev: pointer to USB device instance
\param[in] ep_num: endpoint number
\param[out] none
\retval USB device operation cur_status
*/
uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num)
{
return udev->dev.transc_out[ep_num].xfer_count;
}
/*!
\brief device connect
\param[in] udev: pointer to USB device instance
\param[out] none
\retval none
*/
void usbd_connect (usb_core_driver *udev)
{
#ifndef USE_OTG_MODE
/* connect device */
usb_dev_connect (udev);
usb_mdelay(3);
#endif /* USE_OTG_MODE */
}
/*!
\brief device disconnect
\param[in] udev: pointer to USB device instance
\param[out] none
\retval none
*/
void usbd_disconnect (usb_core_driver *udev)
{
#ifndef USE_OTG_MODE
/* disconnect device for 3ms */
usb_dev_disconnect (udev);
usb_mdelay(3);
#endif /* USE_OTG_MODE */
}

View File

@@ -1,696 +0,0 @@
/*!
\file usbd_enum.c
\brief USB enumeration function
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "../Include/usbd_enum.h"
#include "../Include/usb_ch9_std.h"
static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req);
static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req);
static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len);
static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len);
static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len);
static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len);
static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) =
{
[USB_GET_STATUS] = _usb_std_getstatus,
[USB_CLEAR_FEATURE] = _usb_std_clearfeature,
[USB_RESERVED2] = _usb_std_reserved,
[USB_SET_FEATURE] = _usb_std_setfeature,
[USB_RESERVED4] = _usb_std_reserved,
[USB_SET_ADDRESS] = _usb_std_setaddress,
[USB_GET_DESCRIPTOR] = _usb_std_getdescriptor,
[USB_SET_DESCRIPTOR] = _usb_std_setdescriptor,
[USB_GET_CONFIGURATION] = _usb_std_getconfiguration,
[USB_SET_CONFIGURATION] = _usb_std_setconfiguration,
[USB_GET_INTERFACE] = _usb_std_getinterface,
[USB_SET_INTERFACE] = _usb_std_setinterface,
[USB_SYNCH_FRAME] = _usb_std_synchframe,
};
/* get standard descriptor handler */
static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len) = {
[USB_DESCTYPE_DEV - 1] = _usb_dev_desc_get,
[USB_DESCTYPE_CONFIG - 1] = _usb_config_desc_get,
[USB_DESCTYPE_STR - 1] = _usb_str_desc_get
};
/*!
\brief handle USB standard device request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval USB device request status
*/
usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req)
{
return (*_std_dev_req[req->bRequest])(udev, req);
}
/*!
\brief handle USB device class request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device class request
\param[out] none
\retval USB device request status
*/
usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req)
{
if (USBD_CONFIGURED == udev->dev.cur_status) {
if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) {
/* call device class handle function */
return (usb_reqsta)udev->dev.class_core->req_proc(udev, req);
}
}
return REQ_NOTSUPP;
}
/*!
\brief handle USB vendor request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB vendor request
\param[out] none
\retval USB device request status
*/
usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req)
{
/* added by user... */
return REQ_SUPP;
}
/*!
\brief no operation, just for reserved
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB vendor request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req)
{
/* no operation... */
return REQ_NOTSUPP;
}
/*!
\brief get the device descriptor
\param[in] udev: pointer to USB device instance
\param[in] index: no use
\param[out] len: data length pointer
\retval descriptor buffer pointer
*/
static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len)
{
*len = udev->dev.desc.dev_desc[0];
return udev->dev.desc.dev_desc;
}
/*!
\brief get the configuration descriptor
\brief[in] udev: pointer to USB device instance
\brief[in] index: no use
\param[out] len: data length pointer
\retval descriptor buffer pointer
*/
static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len)
{
*len = udev->dev.desc.config_desc[2];
return udev->dev.desc.config_desc;
}
/*!
\brief get the BOS descriptor
\brief[in] udev: pointer to USB device instance
\brief[in] index: no use
\param[out] len: data length pointer
\retval descriptor buffer pointer
*/
static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len)
{
*len = udev->dev.desc.bos_desc[2];
return udev->dev.desc.bos_desc;
}
/*!
\brief get string descriptor
\param[in] udev: pointer to USB device instance
\param[in] index: string descriptor index
\param[out] len: pointer to string length
\retval descriptor buffer pointer
*/
static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len)
{
uint8_t *desc = udev->dev.desc.strings[index];
*len = desc[0];
return desc;
}
/*!
\brief handle Get_Status request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req)
{
uint8_t recp = BYTE_LOW(req->wIndex);
usb_transc *transc = &udev->dev.transc_in[0];
static uint8_t status[2] = {0};
switch(req->bmRequestType & USB_RECPTYPE_MASK) {
case USB_RECPTYPE_DEV:
if ((USBD_ADDRESSED == udev->dev.cur_status) || \
(USBD_CONFIGURED == udev->dev.cur_status)) {
if (udev->dev.pm.power_mode) {
status[0] = USB_STATUS_SELF_POWERED;
} else {
status[0] = 0U;
}
if (udev->dev.pm.dev_remote_wakeup) {
status[0] |= USB_STATUS_REMOTE_WAKEUP;
} else {
status[0] = 0U;
}
transc->xfer_buf = status;
transc->remain_len = 2U;
return REQ_SUPP;
}
break;
case USB_RECPTYPE_ITF:
if ((USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) {
transc->xfer_buf = status;
transc->remain_len = 2U;
return REQ_SUPP;
}
break;
case USB_RECPTYPE_EP:
if (USBD_CONFIGURED == udev->dev.cur_status) {
if (0x80U == (recp & 0x80U)) {
status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall;
} else {
status[0] = udev->dev.transc_out[recp].ep_stall;
}
transc->xfer_buf = status;
transc->remain_len = 2U;
return REQ_SUPP;
}
break;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
\brief handle USB Clear_Feature request
\param[in] udev: pointer to USB device instance
\param[in] req: USB device request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req)
{
uint8_t ep = 0;
switch(req->bmRequestType & USB_RECPTYPE_MASK)
{
case USB_RECPTYPE_DEV:
if ((USBD_ADDRESSED == udev->dev.cur_status) || \
(USBD_CONFIGURED == udev->dev.cur_status)) {
/* clear device remote wakeup feature */
if (USB_FEATURE_REMOTE_WAKEUP == req->wValue) {
udev->dev.pm.dev_remote_wakeup = 0U;
return REQ_SUPP;
}
}
break;
case USB_RECPTYPE_ITF:
break;
case USB_RECPTYPE_EP:
/* get endpoint address */
ep = BYTE_LOW(req->wIndex);
if (USBD_CONFIGURED == udev->dev.cur_status) {
/* clear endpoint halt feature */
if ((USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) {
usbd_ep_stall_clear (udev, ep);
udev->dev.class_core->req_proc (udev, req);
}
return REQ_SUPP;
}
break;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
\brief handle USB Set_Feature request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req)
{
uint8_t ep = 0;
switch(req->bmRequestType & USB_RECPTYPE_MASK)
{
case USB_RECPTYPE_DEV:
if ((USBD_ADDRESSED == udev->dev.cur_status) || \
(USBD_CONFIGURED == udev->dev.cur_status)) {
/* set device remote wakeup feature */
if (USB_FEATURE_REMOTE_WAKEUP == req->wValue) {
udev->dev.pm.dev_remote_wakeup = 1U;
}
return REQ_SUPP;
}
break;
case USB_RECPTYPE_ITF:
break;
case USB_RECPTYPE_EP:
/* get endpoint address */
ep = BYTE_LOW(req->wIndex);
if (USBD_CONFIGURED == udev->dev.cur_status) {
/* set endpoint halt feature */
if ((USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) {
usbd_ep_stall (udev, ep);
}
return REQ_SUPP;
}
break;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
\brief handle USB Set_Address request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req)
{
if ((0U == req->wIndex) && (0U == req->wLength)) {
udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU;
if (udev->dev.cur_status != USBD_CONFIGURED) {
usbd_addr_set (udev, udev->dev.dev_addr);
if (udev->dev.dev_addr) {
udev->dev.cur_status = USBD_ADDRESSED;
} else {
udev->dev.cur_status = USBD_DEFAULT;
}
return REQ_SUPP;
}
}
return REQ_NOTSUPP;
}
/*!
\brief handle USB Get_Descriptor request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req)
{
uint8_t desc_type = 0;
uint8_t desc_index = 0;
usb_transc *transc = &udev->dev.transc_in[0];
/* get device standard descriptor */
switch (req->bmRequestType & USB_RECPTYPE_MASK) {
case USB_RECPTYPE_DEV:
desc_type = BYTE_HIGH(req->wValue);
desc_index = BYTE_LOW(req->wValue);
switch (desc_type) {
case USB_DESCTYPE_DEV:
transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len));
if (64U == req->wLength) {
transc->remain_len = 8U;
}
break;
case USB_DESCTYPE_CONFIG:
transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len));
break;
case USB_DESCTYPE_STR:
if (desc_index < STR_IDX_MAX) {
transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len));
}
break;
case USB_DESCTYPE_ITF:
case USB_DESCTYPE_EP:
case USB_DESCTYPE_DEV_QUALIFIER:
case USB_DESCTYPE_OTHER_SPD_CONFIG:
case USB_DESCTYPE_ITF_POWER:
break;
case USB_DESCTYPE_BOS:
transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len));
break;
default:
break;
}
break;
case USB_RECPTYPE_ITF:
/* get device class special descriptor */
return (usb_reqsta)(udev->dev.class_core->req_proc(udev, req));
case USB_RECPTYPE_EP:
break;
default:
break;
}
if ((0U != transc->remain_len) && (0U != req->wLength)) {
if (transc->remain_len < req->wLength) {
if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) {
udev->dev.control.ctl_zlp = 1;
}
} else {
transc->remain_len = req->wLength;
}
return REQ_SUPP;
}
return REQ_NOTSUPP;
}
/*!
\brief handle USB Set_Descriptor request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req)
{
/* no handle... */
return REQ_SUPP;
}
/*!
\brief handle USB Get_Configuration request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req)
{
usb_transc *transc = &udev->dev.transc_in[0];
switch (udev->dev.cur_status) {
case USBD_ADDRESSED:
if (USB_DEFAULT_CONFIG == udev->dev.config) {
transc->xfer_buf = &(udev->dev.config);
transc->remain_len = 1U;
return REQ_SUPP;
}
break;
case USBD_CONFIGURED:
if (udev->dev.config != USB_DEFAULT_CONFIG) {
transc->xfer_buf = &(udev->dev.config);
transc->remain_len = 1U;
return REQ_SUPP;
}
break;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
\brief handle USB Set_Configuration request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req)
{
static uint8_t config;
config = (uint8_t)(req->wValue);
if (config <= USBD_CFG_MAX_NUM) {
switch (udev->dev.cur_status) {
case USBD_ADDRESSED:
if (config){
udev->dev.class_core->init(udev, config);
udev->dev.config = config;
udev->dev.cur_status = USBD_CONFIGURED;
}
return REQ_SUPP;
case USBD_CONFIGURED:
if (USB_DEFAULT_CONFIG == config) {
udev->dev.class_core->deinit(udev, config);
udev->dev.config = config;
udev->dev.cur_status = USBD_ADDRESSED;
} else if (config != udev->dev.config) {
/* clear old configuration */
udev->dev.class_core->deinit(udev, config);
/* set new configuration */
udev->dev.config = config;
udev->dev.class_core->init(udev, config);
}
return REQ_SUPP;
case USBD_DEFAULT:
break;
default:
break;
}
}
return REQ_NOTSUPP;
}
/*!
\brief handle USB Get_Interface request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req)
{
switch (udev->dev.cur_status) {
case USBD_DEFAULT:
break;
case USBD_ADDRESSED:
break;
case USBD_CONFIGURED:
if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) {
usb_transc *transc = &udev->dev.transc_in[0];
transc->xfer_buf = &(udev->dev.class_core->alter_set);
transc->remain_len = 1U;
return REQ_SUPP;
}
break;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
\brief handle USB Set_Interface request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req)
{
switch (udev->dev.cur_status) {
case USBD_DEFAULT:
break;
case USBD_ADDRESSED:
break;
case USBD_CONFIGURED:
if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) {
udev->dev.class_core->alter_set = req->wValue;
return REQ_SUPP;
}
break;
default:
break;
}
return REQ_NOTSUPP;
}
/*!
\brief handle USB SynchFrame request
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval USB device request status
*/
static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req)
{
/* no handle... */
return REQ_SUPP;
}
/*!
\brief handle USB enumeration error
\param[in] udev: pointer to USB device instance
\param[in] req: pointer to USB device request
\param[out] none
\retval none
*/
void usbd_enum_error (usb_core_driver *udev, usb_req *req)
{
usbd_ep_stall (udev, 0x80);
usbd_ep_stall (udev, 0x00);
usb_ctlep_startout(udev);
}
/*!
\brief convert hex 32bits value into unicode char
\param[in] value: hex 32bits value
\param[in] pbuf: buffer pointer to store unicode char
\param[in] len: value length
\param[out] none
\retval none
*/
void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len)
{
uint8_t index = 0;
for (index = 0; index < len; index++) {
if ((value >> 28) < 0x0A) {
pbuf[2 * index] = (value >> 28) + '0';
} else {
pbuf[2 * index] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * index + 1] = 0;
}
}

View File

@@ -1,254 +0,0 @@
/*!
\file usbd_transc.c
\brief USB transaction core functions
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "../Include/usbd_enum.h"
#include "../Include/usbd_transc.h"
/*!
\brief USB send data in the control transaction
\param[in] udev: pointer to USB device instance
\param[out] none
\retval USB device operation cur_status
*/
usbd_status usbd_ctl_send (usb_core_driver *udev)
{
usb_transc *transc = &udev->dev.transc_in[0];
usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len);
if (transc->remain_len > transc->max_len) {
udev->dev.control.ctl_state = USB_CTL_DATA_IN;
} else {
udev->dev.control.ctl_state = USB_CTL_LAST_DATA_IN;
}
return USBD_OK;
}
/*!
\brief USB receive data in control transaction
\param[in] udev: pointer to USB device instance
\param[out] none
\retval USB device operation cur_status
*/
usbd_status usbd_ctl_recev (usb_core_driver *udev)
{
usb_transc *transc = &udev->dev.transc_out[0];
usbd_ep_recev (udev, 0U, transc->xfer_buf, transc->remain_len);
if (transc->remain_len > transc->max_len) {
udev->dev.control.ctl_state = USB_CTL_DATA_OUT;
} else {
udev->dev.control.ctl_state = USB_CTL_LAST_DATA_OUT;
}
return USBD_OK;
}
/*!
\brief USB send control transaction status
\param[in] udev: pointer to USB device instance
\param[out] none
\retval USB device operation cur_status
*/
usbd_status usbd_ctl_status_send (usb_core_driver *udev)
{
udev->dev.control.ctl_state = USB_CTL_STATUS_IN;
usbd_ep_send (udev, 0U, NULL, 0U);
usb_ctlep_startout(udev);
return USBD_OK;
}
/*!
\brief USB control receive status
\param[in] udev: pointer to USB device instance
\param[out] none
\retval USB device operation cur_status
*/
usbd_status usbd_ctl_status_recev (usb_core_driver *udev)
{
udev->dev.control.ctl_state = USB_CTL_STATUS_OUT;
usbd_ep_recev (udev, 0, NULL, 0);
usb_ctlep_startout(udev);
return USBD_OK;
}
/*!
\brief USB setup stage processing
\param[in] udev: pointer to USB device instance
\param[out] none
\retval USB device operation cur_status
*/
uint8_t usbd_setup_transc (usb_core_driver *udev)
{
usb_reqsta reqstat = REQ_NOTSUPP;
usb_req req = udev->dev.control.req;
switch (req.bmRequestType & USB_REQTYPE_MASK) {
/* standard device request */
case USB_REQTYPE_STRD:
reqstat = usbd_standard_request (udev, &req);
break;
/* device class request */
case USB_REQTYPE_CLASS:
reqstat = usbd_class_request (udev, &req);
break;
/* vendor defined request */
case USB_REQTYPE_VENDOR:
reqstat = usbd_vendor_request (udev, &req);
break;
default:
break;
}
if (REQ_SUPP == reqstat) {
if (req.wLength == 0) {
usbd_ctl_status_send (udev);
} else {
if (req.bmRequestType & 0x80) {
usbd_ctl_send (udev);
} else {
usbd_ctl_recev (udev);
}
}
} else {
usbd_enum_error (udev, &req);
}
return USBD_OK;
}
/*!
\brief data out stage processing
\param[in] udev: pointer to USB device instance
\param[in] ep_num: endpoint identifier(0..7)
\param[out] none
\retval USB device operation cur_status
*/
uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num)
{
if (ep_num == 0) {
usb_transc *transc = &udev->dev.transc_out[0];
switch (udev->dev.control.ctl_state) {
case USB_CTL_DATA_OUT:
/* update transfer length */
transc->remain_len -= transc->max_len;
usbd_ctl_recev (udev);
break;
case USB_CTL_LAST_DATA_OUT:
if (udev->dev.cur_status == USBD_CONFIGURED) {
if (udev->dev.class_core->data_out != NULL) {
udev->dev.class_core->data_out (udev, 0U);
}
}
transc->remain_len = 0U;
usbd_ctl_status_send (udev);
break;
default:
break;
}
} else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == USBD_CONFIGURED)) {
udev->dev.class_core->data_out (udev, ep_num);
}
return USBD_OK;
}
/*!
\brief data in stage processing
\param[in] udev: pointer to USB device instance
\param[in] ep_num: endpoint identifier(0..7)
\param[out] none
\retval USB device operation cur_status
*/
uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num)
{
if (0U == ep_num) {
usb_transc *transc = &udev->dev.transc_in[0];
switch (udev->dev.control.ctl_state) {
case USB_CTL_DATA_IN:
/* update transfer length */
transc->remain_len -= transc->max_len;
usbd_ctl_send (udev);
break;
case USB_CTL_LAST_DATA_IN:
/* last packet is MPS multiple, so send ZLP packet */
if (udev->dev.control.ctl_zlp) {
usbd_ep_send (udev, 0U, NULL, 0U);
udev->dev.control.ctl_zlp = 0U;
} else {
if (udev->dev.cur_status == USBD_CONFIGURED) {
if (udev->dev.class_core->data_in != NULL) {
udev->dev.class_core->data_in (udev, 0U);
}
}
transc->remain_len = 0U;
usbd_ctl_status_recev (udev);
}
break;
default:
break;
}
} else {
if ((udev->dev.cur_status == USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) {
udev->dev.class_core->data_in (udev, ep_num);
}
}
return USBD_OK;
}

View File

@@ -1,441 +0,0 @@
/*!
\file usbh_core.c
\brief USB host core state machine driver
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "../Include/drv_usb_hw.h"
#include "../Include/usbh_pipe.h"
#include "../Include/usbh_enum.h"
#include "../Include/usbh_core.h"
#include "../Include/drv_usbh_int.h"
uint8_t usbh_sof (usb_core_driver *pudev);
usbh_int_cb usbh_int_op =
{
usbh_sof
};
usbh_int_cb *usbh_int_fop = &usbh_int_op;
static usbh_status usbh_enum_task (usb_core_driver *pudev, usbh_host *puhost);
/*!
\brief USB SOF callback function from the interrupt
\param[in] pudev: pointer to usb core instance
\param[out] none
\retval operation status
*/
uint8_t usbh_sof (usb_core_driver *pudev)
{
/* this callback could be used to implement a scheduler process */
return 0U;
}
/*!
\brief USB host stack initializations
\param[in] pudev: pointer to usb core instance
\param[in] core: USBFS core or USBHS core
\param[in] puhost: pointer to USB host
\param[out] none
\retval operation status
*/
void usbh_init (usb_core_driver *pudev, usb_core_enum core, usbh_host *puhost)
{
uint8_t i = 0U;
/* host de-initializations */
usbh_deinit(pudev, puhost);
pudev->host.connect_status = 0U;
for (i = 0U; i < USBFS_MAX_TX_FIFOS; i++) {
pudev->host.pipe[i].err_count = 0U;
pudev->host.pipe[i].pp_status = PIPE_IDLE;
pudev->host.backup_xfercount[i] = 0U;
}
pudev->host.pipe[0].ep.mps = 8U;
usb_basic_init (&pudev->bp, &pudev->regs, core);
#ifndef DUAL_ROLE_MODE_ENABLED
usb_core_init (pudev->bp, &pudev->regs);
usb_host_init (pudev);
#endif /* DUAL_ROLE_MODE_ENABLED */
/* upon init call usr call back */
puhost->usr_cb->dev_init();
}
/*!
\brief de-initialize USB host
\param[in] pudev: pointer to usb core instance
\param[in] puhost: pointer to USB host
\param[out] none
\retval operation status
*/
usbh_status usbh_deinit(usb_core_driver *pudev, usbh_host *puhost)
{
/* software init */
puhost->cur_state = HOST_DEFAULT;
puhost->backup_state = HOST_DEFAULT;
puhost->enum_state = ENUM_DEFAULT;
puhost->control.ctl_state = CTL_IDLE;
puhost->control.max_len = USB_FS_EP0_MAX_LEN;
puhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT;
puhost->dev_prop.speed = PORT_SPEED_FULL;
usbh_pipe_free(pudev, puhost->control.pipe_in_num);
usbh_pipe_free(pudev, puhost->control.pipe_out_num);
return USBH_OK;
}
/*!
\brief USB host core main state machine process
\param[in] pudev: pointer to usb core instance
\param[in] puhost: pointer to USB host
\param[out] none
\retval none
*/
void usbh_core_task (usb_core_driver *pudev, usbh_host *puhost)
{
volatile usbh_status status = USBH_FAIL;
/* check for host port events */
if (((0U == pudev->host.connect_status) || (0U == pudev->host.port_enabled)) && (HOST_DEFAULT != puhost->cur_state)) {
if (puhost->cur_state != HOST_DEV_DETACHED) {
puhost->cur_state = HOST_DEV_DETACHED;
}
}
switch (puhost->cur_state) {
case HOST_DEFAULT:
if (pudev->host.connect_status) {
puhost->cur_state = HOST_DETECT_DEV_SPEED;
usb_mdelay (100U);
// usb_mdelay (2U);
usb_port_reset (pudev);
puhost->usr_cb->dev_reset();
}
break;
case HOST_DETECT_DEV_SPEED:
if (pudev->host.port_enabled) {
puhost->cur_state = HOST_DEV_ATTACHED;
puhost->dev_prop.speed = usb_curspeed_get (pudev);
puhost->usr_cb->dev_speed_detected(puhost->dev_prop.speed);
usb_mdelay (50U);
}
break;
case HOST_DEV_ATTACHED:
puhost->usr_cb->dev_attach();
puhost->control.pipe_out_num = usbh_pipe_allocate(pudev, 0x00U);
puhost->control.pipe_in_num = usbh_pipe_allocate(pudev, 0x80U);
/* reset USB device */
usb_port_reset (pudev);
/* open IN control pipe */
usbh_pipe_create (pudev,
&puhost->dev_prop,
puhost->control.pipe_in_num,
USB_EPTYPE_CTRL,
puhost->control.max_len);
/* open OUT control pipe */
usbh_pipe_create (pudev,
&puhost->dev_prop,
puhost->control.pipe_out_num,
USB_EPTYPE_CTRL,
puhost->control.max_len);
puhost->cur_state = HOST_ENUM;
break;
case HOST_ENUM:
/* check for enumeration status */
if (USBH_OK == usbh_enum_task (pudev, puhost)) {
/* the function shall return USBH_OK when full enumeration is complete */
/* user callback for end of device basic enumeration */
puhost->usr_cb->dev_enumerated();
puhost->cur_state = HOST_USER_INPUT;
}
break;
case HOST_USER_INPUT:
/* the function should return user response true to move to class state */
if (USBH_USER_RESP_OK == puhost->usr_cb->dev_user_input()) {
if ((USBH_OK == puhost->class_cb->class_init(pudev, puhost))) {
puhost->cur_state = HOST_CLASS_ENUM;
}
}
break;
case HOST_CLASS_ENUM:
/* process class standard contol requests state machine */
status = puhost->class_cb->class_requests(pudev, puhost);
if (USBH_OK == status) {
puhost->cur_state = HOST_CLASS_HANDLER;
} else {
usbh_error_handler (puhost, status);
}
break;
case HOST_CLASS_HANDLER:
/* process class state machine */
status = puhost->class_cb->class_machine(pudev, puhost);
usbh_error_handler (puhost, status);
break;
case HOST_SUSPENDED:
break;
case HOST_ERROR:
/* re-initilaize host for new enumeration */
usbh_deinit (pudev, puhost);
puhost->usr_cb->dev_deinit();
puhost->class_cb->class_deinit(pudev, puhost);
break;
case HOST_DEV_DETACHED:
/* manage user disconnect operations*/
puhost->usr_cb->dev_detach();
/* re-initilaize host for new enumeration */
usbh_deinit(pudev, puhost);
puhost->usr_cb->dev_deinit();
puhost->class_cb->class_deinit(pudev, puhost);
usbh_pipe_delete(pudev);
puhost->cur_state = HOST_DEFAULT;
break;
default:
break;
}
}
/*!
\brief handle the error on USB host side
\param[in] puhost: pointer to USB host
\param[in] err_type: type of error or busy/OK state
\param[out] none
\retval none
*/
void usbh_error_handler (usbh_host *puhost, usbh_status err_type)
{
/* error unrecovered or not supported device speed */
if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) {
puhost->usr_cb->dev_error();
puhost->cur_state = HOST_ERROR;
} else if (USBH_APPLY_DEINIT == err_type) {
puhost->cur_state = HOST_ERROR;
/* user callback for initalization */
puhost->usr_cb->dev_init();
}
}
/*!
\brief handle the USB enumeration task
\param[in] pudev: pointer to selected USB device
\param[in] puhost: pointer to host
\param[out] none
\retval none
*/
static usbh_status usbh_enum_task (usb_core_driver *pudev, usbh_host *puhost)
{
uint8_t str_buf[64];
usbh_status status = USBH_BUSY;
static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U;
switch (puhost->enum_state) {
case ENUM_DEFAULT:
/* get device descriptor for only 1st 8 bytes : to get ep0 maxpacketsize */
if (USBH_OK == usbh_devdesc_get (pudev, puhost, 8U)) {
puhost->control.max_len = puhost->dev_prop.dev_desc.bMaxPacketSize0;
/* issue reset */
usb_port_reset (pudev);
/* modify control channels configuration for maximum packet size */
usbh_pipe_update (pudev,
puhost->control.pipe_out_num,
0U, 0U,
puhost->control.max_len);
usbh_pipe_update (pudev,
puhost->control.pipe_in_num,
0U, 0U,
puhost->control.max_len);
puhost->enum_state = ENUM_GET_DEV_DESC;
}
break;
case ENUM_GET_DEV_DESC:
/* get full device descriptor */
if (USBH_OK == usbh_devdesc_get (pudev, puhost, USB_DEV_DESC_LEN)) {
puhost->usr_cb->dev_devdesc_assigned(&puhost->dev_prop.dev_desc);
index_mfc_str = puhost->dev_prop.dev_desc.iManufacturer;
index_prod_str = puhost->dev_prop.dev_desc.iProduct;
index_serial_str = puhost->dev_prop.dev_desc.iSerialNumber;
puhost->enum_state = ENUM_SET_ADDR;
}
break;
case ENUM_SET_ADDR:
/* set address */
if (USBH_OK == usbh_setaddress (pudev, puhost, USBH_DEV_ADDR)) {
usb_mdelay (2);
puhost->dev_prop.addr = USBH_DEV_ADDR;
/* user callback for device address assigned */
puhost->usr_cb->dev_address_set();
/* modify control channels to update device address */
usbh_pipe_update (pudev,
puhost->control.pipe_in_num,
puhost->dev_prop.addr,
0U, 0U);
usbh_pipe_update (pudev,
puhost->control.pipe_out_num,
puhost->dev_prop.addr,
0U, 0U);
puhost->enum_state = ENUM_GET_CFG_DESC;
}
break;
case ENUM_GET_CFG_DESC:
/* get standard configuration descriptor */
if (USBH_OK == usbh_cfgdesc_get (pudev, puhost, USB_CFG_DESC_LEN)) {
puhost->enum_state = ENUM_GET_CFG_DESC_SET;
}
break;
case ENUM_GET_CFG_DESC_SET:
/* get full config descriptor (config, interface, endpoints) */
if (USBH_OK == usbh_cfgdesc_get (pudev, puhost, puhost->dev_prop.cfg_desc.wTotalLength)) {
/* user callback for configuration descriptors available */
puhost->usr_cb->dev_cfgdesc_assigned (&puhost->dev_prop.cfg_desc,
puhost->dev_prop.itf_desc,
puhost->dev_prop.ep_desc[0]);
puhost->enum_state = ENUM_GET_STR_DESC;
}
break;
case ENUM_GET_STR_DESC:
if (index_mfc_str) {
if (USBH_OK == usbh_strdesc_get (pudev,
puhost,
puhost->dev_prop.dev_desc.iManufacturer,
str_buf,
0xFFU)) {
/* user callback for manufacturing string */
puhost->usr_cb->dev_mfc_str(str_buf);
index_mfc_str = 0U;
}
} else {
if (index_prod_str) {
/* check that product string is available */
if (USBH_OK == usbh_strdesc_get (pudev,
puhost,
puhost->dev_prop.dev_desc.iProduct,
str_buf,
0xFFU)) {
puhost->usr_cb->dev_prod_str(str_buf);
index_prod_str = 0U;
}
} else {
if (index_serial_str) {
if (USBH_OK == usbh_strdesc_get (pudev,
puhost,
puhost->dev_prop.dev_desc.iSerialNumber,
str_buf,
0xFFU)) {
puhost->usr_cb->dev_seral_str(str_buf);
puhost->enum_state = ENUM_SET_CONFIGURATION;
index_serial_str = 0U;
}
} else {
puhost->enum_state = ENUM_SET_CONFIGURATION;
}
}
}
break;
case ENUM_SET_CONFIGURATION:
if (USBH_OK == usbh_setcfg (pudev,
puhost,
puhost->dev_prop.cfg_desc.bConfigurationValue)) {
puhost->enum_state = ENUM_DEV_CONFIGURED;
}
break;
case ENUM_DEV_CONFIGURED:
status = USBH_OK;
break;
default:
break;
}
return status;
}

View File

@@ -1,549 +0,0 @@
/*!
\file usbh_enum.c
\brief USB host mode enumberation driver
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "../Include/usbh_transc.h"
#include "../Include/usbh_enum.h"
static void usbh_devdesc_parse (usb_desc_dev *cfg_desc, uint8_t *buf, uint16_t len);
static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf);
static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf);
static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf);
static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf);
static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len);
/*!
\brief configure USB control status parameters
\param[in] puhost: pointer to usb host
\param[in] buf: control transfer data buffer pointer
\param[in] len: length of the data buffer
\param[out] none
\retval none
*/
void usbh_ctlstate_config (usbh_host *puhost, uint8_t *buf, uint16_t len)
{
/* prepare the transactions */
puhost->control.buf = buf;
puhost->control.ctl_len = len;
puhost->control.ctl_state = CTL_SETUP;
}
/*!
\brief get device descriptor from the USB device
\param[in] pudev: pointer to usb core instance
\param[in] puhost: pointer to usb host
\param[in] len: length of the descriptor
\param[out] none
\retval operation status
*/
usbh_status usbh_devdesc_get (usb_core_driver *pudev, usbh_host *puhost, uint8_t len)
{
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD,
.bRequest = USB_GET_DESCRIPTOR,
.wValue = USBH_DESC(USB_DESCTYPE_DEV),
.wIndex = 0U,
.wLength = len
};
usbh_ctlstate_config (puhost, pudev->host.rx_buf, len);
}
status = usbh_ctl_handler (pudev, puhost);
if (USBH_OK == status) {
/* commands successfully sent and response received */
usbh_devdesc_parse (&puhost->dev_prop.dev_desc, pudev->host.rx_buf, len);
}
return status;
}
/*!
\brief get configuration descriptor from the USB device
\param[in] pudev: pointer to usb core instance
\param[in] puhost: pointer to usb host
\param[in] len: length of the descriptor
\param[out] none
\retval operation status
*/
usbh_status usbh_cfgdesc_get (usb_core_driver *pudev, usbh_host *puhost, uint16_t len)
{
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD,
.bRequest = USB_GET_DESCRIPTOR,
.wValue = USBH_DESC(USB_DESCTYPE_CONFIG),
.wIndex = 0U,
.wLength = len
};
usbh_ctlstate_config (puhost, pudev->host.rx_buf, len);
}
status = usbh_ctl_handler (pudev, puhost);
if (USBH_OK == status) {
if (len <= USB_CFG_DESC_LEN) {
usbh_cfgdesc_parse (&puhost->dev_prop.cfg_desc, pudev->host.rx_buf);
} else {
usbh_cfgset_parse (&puhost->dev_prop, pudev->host.rx_buf);
}
}
return status;
}
/*!
\brief get string descriptor from the USB device
\param[in] pudev: pointer to usb core instance
\param[in] puhost: pointer to usb host
\param[in] str_index: index for the string descriptor
\param[in] buf: buffer pointer to the string descriptor
\param[in] len: length of the descriptor
\param[out] none
\retval operation status
*/
usbh_status usbh_strdesc_get (usb_core_driver *pudev,
usbh_host *puhost,
uint8_t str_index,
uint8_t *buf,
uint16_t len)
{
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD,
.bRequest = USB_GET_DESCRIPTOR,
.wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index,
.wIndex = 0x0409U,
.wLength = len
};
usbh_ctlstate_config (puhost, pudev->host.rx_buf, len);
}
status = usbh_ctl_handler (pudev, puhost);
if (USBH_OK == status) {
/* commands successfully sent and response received */
usbh_strdesc_parse (pudev->host.rx_buf, buf, len);
}
return status;
}
/*!
\brief set the address to the connected device
\param[in] pudev: pointer to usb core instance
\param[in] puhost: pointer to usb host
\param[in] dev_addr: device address to assign
\param[out] none
\retval operation status
*/
usbh_status usbh_setaddress (usb_core_driver *pudev, usbh_host *puhost, uint8_t dev_addr)
{
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD,
.bRequest = USB_SET_ADDRESS,
.wValue = (uint16_t)dev_addr,
.wIndex = 0U,
.wLength = 0U
};
usbh_ctlstate_config (puhost, NULL, 0U);
}
status = usbh_ctl_handler (pudev, puhost);
return status;
}
/*!
\brief set the configuration value to the connected device
\param[in] pudev: pointer to usb core instance
\param[in] puhost: pointer to usb host
\param[in] config_index: configuration value
\param[out] none
\retval operation status
*/
usbh_status usbh_setcfg (usb_core_driver *pudev, usbh_host *puhost, uint16_t config_index)
{
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD,
.bRequest = USB_SET_CONFIGURATION,
.wValue = config_index,
.wIndex = 0U,
.wLength = 0U
};
usbh_ctlstate_config (puhost, NULL, 0U);
}
status = usbh_ctl_handler (pudev, puhost);
return status;
}
/*!
\brief set the interface value to the connected device
\param[in] pudev: pointer to usb core instance
\param[in] puhost: pointer to usb host
\param[in] ep_num: endpoint number
\param[in] alter_setting: altnated setting value
\param[out] none
\retval operation status
*/
usbh_status usbh_setinterface (usb_core_driver *pudev,
usbh_host *puhost,
uint8_t ep_num,
uint8_t set)
{
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD,
.bRequest = USB_SET_INTERFACE,
.wValue = set,
.wIndex = ep_num,
.wLength = 0U
};
usbh_ctlstate_config (puhost, NULL, 0U);
}
status = usbh_ctl_handler (pudev, puhost);
return status;
}
/*!
\brief clear or disable a specific feature
\param[in] pudev: pointer to usb core instance
\param[in] puhost: pointer to usb host
\param[in] ep_addr: endpoint address
\param[in] pp_num: pipe number
\param[out] none
\retval operation status
*/
usbh_status usbh_clrfeature (usb_core_driver *pudev,
usbh_host *puhost,
uint8_t ep_addr,
uint8_t pp_num)
{
usbh_status status = USBH_BUSY;
usbh_control *usb_ctl = &puhost->control;
if (CTL_IDLE == usb_ctl->ctl_state) {
usb_ctl->setup.req = (usb_req) {
.bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD,
.bRequest = USB_CLEAR_FEATURE,
.wValue = FEATURE_SELECTOR_EP,
.wIndex = ep_addr,
.wLength = 0
};
if (EP_DIR(ep_addr)) {
pudev->host.pipe[pp_num].data_toggle_in = 0U;
} else {
pudev->host.pipe[pp_num].data_toggle_out = 0U;
}
usbh_ctlstate_config (puhost, NULL, 0U);
}
status = usbh_ctl_handler (pudev, puhost);
return status;
}
/*!
\brief parse the device descriptor
\param[in] dev_desc: pointer to usb device descriptor buffer
\param[in] buf: pointer to the source descriptor buffer
\param[in] len: length of the descriptor
\param[out] none
\retval operation status
*/
static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len)
{
*dev_desc = (usb_desc_dev) {
.header = {
.bLength = *(uint8_t *)(buf + 0U),
.bDescriptorType = *(uint8_t *)(buf + 1U)
},
.bcdUSB = BYTE_SWAP(buf + 2U),
.bDeviceClass = *(uint8_t *)(buf + 4U),
.bDeviceSubClass = *(uint8_t *)(buf + 5U),
.bDeviceProtocol = *(uint8_t *)(buf + 6U),
.bMaxPacketSize0 = *(uint8_t *)(buf + 7U)
};
if (len > 8U) {
/* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */
dev_desc->idVendor = BYTE_SWAP(buf + 8U);
dev_desc->idProduct = BYTE_SWAP(buf + 10U);
dev_desc->bcdDevice = BYTE_SWAP(buf + 12U);
dev_desc->iManufacturer = *(uint8_t *)(buf + 14U);
dev_desc->iProduct = *(uint8_t *)(buf + 15U);
dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U);
dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U);
}
}
/*!
\brief parse the configuration descriptor
\param[in] cfg_desc: pointer to usb configuration descriptor buffer
\param[in] buf: pointer to the source descriptor buffer
\param[out] none
\retval operation status
*/
static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf)
{
/* parse configuration descriptor */
*cfg_desc = (usb_desc_config) {
.header = {
.bLength = *(uint8_t *)(buf + 0U),
.bDescriptorType = *(uint8_t *)(buf + 1U),
},
.wTotalLength = BYTE_SWAP(buf + 2U),
.bNumInterfaces = *(uint8_t *)(buf + 4U),
.bConfigurationValue = *(uint8_t *)(buf + 5U),
.iConfiguration = *(uint8_t *)(buf + 6U),
.bmAttributes = *(uint8_t *)(buf + 7U),
.bMaxPower = *(uint8_t *)(buf + 8U)
};
}
/*!
\brief parse the configuration descriptor set
\param[in] udev: pointer to USB core instance
\param[in] buf: pointer to the source descriptor buffer
\param[out] none
\retval operation status
*/
static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf)
{
usb_desc_ep *ep = NULL;
usb_desc_itf *itf = NULL, itf_value;
usb_desc_header *pdesc = (usb_desc_header *)buf;
int8_t itf_index = 0U, ep_index = 0U;
uint16_t ptr;
uint8_t prev_itf = 0U;
uint16_t prev_ep_len = 0U;
/* parse configuration descriptor */
usbh_cfgdesc_parse (&udev->cfg_desc, buf);
ptr = USB_CFG_DESC_LEN;
if (udev->cfg_desc.bNumInterfaces > USBH_MAX_INTERFACES_NUM) {
return;
}
while (ptr < udev->cfg_desc.wTotalLength) {
pdesc = usbh_nextdesc_get ((uint8_t *)pdesc, &ptr);
if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) {
itf_index = *(((uint8_t *)pdesc) + 2U);
itf = &udev->itf_desc[itf_index];
if ((*((uint8_t *)pdesc + 3U)) < 3U) {
usbh_itfdesc_parse (&itf_value, (uint8_t *)pdesc);
/* parse endpoint descriptors relative to the current interface */
if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) {
return;
}
for (ep_index = 0; ep_index < itf_value.bNumEndpoints; ) {
pdesc = usbh_nextdesc_get ((void*)pdesc, &ptr);
if (pdesc->bDescriptorType == USB_DESCTYPE_EP) {
ep = &udev->ep_desc[itf_index][ep_index];
if (prev_itf != itf_index) {
prev_itf = itf_index;
usbh_itfdesc_parse (itf, (uint8_t *)&itf_value);
} else {
if (prev_ep_len > BYTE_SWAP((uint8_t *)pdesc + 4U)) {
break;
} else {
usbh_itfdesc_parse (itf, (uint8_t *)&itf_value);
}
}
usbh_epdesc_parse (ep, (uint8_t *)pdesc);
prev_ep_len = BYTE_SWAP((uint8_t *)pdesc + 4U);
ep_index++;
}
}
}
}
}
}
/*!
\brief parse the interface descriptor
\param[in] itf_desc: pointer to usb interface descriptor buffer
\param[in] buf: pointer to the source descriptor buffer
\param[out] none
\retval operation status
*/
static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf)
{
*itf_desc = (usb_desc_itf) {
.header = {
.bLength = *(uint8_t *)(buf + 0U),
.bDescriptorType = *(uint8_t *)(buf + 1U),
},
.bInterfaceNumber = *(uint8_t *)(buf + 2U),
.bAlternateSetting = *(uint8_t *)(buf + 3U),
.bNumEndpoints = *(uint8_t *)(buf + 4U),
.bInterfaceClass = *(uint8_t *)(buf + 5U),
.bInterfaceSubClass = *(uint8_t *)(buf + 6U),
.bInterfaceProtocol = *(uint8_t *)(buf + 7U),
.iInterface = *(uint8_t *)(buf + 8U)
};
}
/*!
\brief parse the endpoint descriptor
\param[in] ep_desc: pointer to usb endpoint descriptor buffer
\param[in] buf: pointer to the source descriptor buffer
\param[out] none
\retval operation status
*/
static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf)
{
*ep_desc = (usb_desc_ep) {
.header = {
.bLength = *(uint8_t *)(buf + 0U),
.bDescriptorType = *(uint8_t *)(buf + 1U)
},
.bEndpointAddress = *(uint8_t *)(buf + 2U),
.bmAttributes = *(uint8_t *)(buf + 3U),
.wMaxPacketSize = BYTE_SWAP(buf + 4U),
.bInterval = *(uint8_t *)(buf + 6U)
};
}
/*!
\brief parse the string descriptor
\param[in] psrc: source pointer containing the descriptor data
\param[in] pdest: destination address pointer
\param[in] len: length of the descriptor
\param[out] none
\retval operation status
*/
static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len)
{
uint16_t str_len = 0U, index = 0U;
/* the unicode string descriptor is not NULL-terminated. The string length is
* computed by substracting two from the value of the first byte of the descriptor.
*/
/* check which is lower size, the size of string or the length of bytes read from the device */
if (USB_DESCTYPE_STR == psrc[1]) {
/* make sure the descriptor is string type */
/* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */
str_len = USB_MIN(psrc[0] - 2U, len);
psrc += 2U; /* adjust the offset ignoring the string len and descriptor type */
for (index = 0U; index < str_len; index += 2U) {
/* copy only the string and ignore the unicode id, hence add the src */
*pdest = psrc[index];
pdest++;
}
*pdest = 0U; /* mark end of string */
}
}
/*!
\brief get the next descriptor header
\param[in] pbuf: pointer to buffer where the configuration descriptor set is available
\param[in] ptr: data popinter inside the configuration descriptor set
\param[out] none
\retval operation status
*/
usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr)
{
usb_desc_header *pnext;
*ptr += ((usb_desc_header *)pbuf)->bLength;
pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength);
return (pnext);
}

View File

@@ -1,174 +0,0 @@
/*!
\file usbh_pipe.c
\brief USB host mode pipe operation driver
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "../Include/usbh_pipe.h"
static uint16_t usbh_freepipe_get (usb_core_driver *pudev);
/*!
\brief create a pipe
\param[in] pudev: pointer to usb core instance
\param[in] pp_num: pipe number
\param[in] udev: USB device
\param[in] ep_type: endpoint type
\param[in] ep_mpl: endpoint max packet length
\param[out] none
\retval operation status
*/
uint8_t usbh_pipe_create (usb_core_driver *pudev,
usb_dev_prop *udev,
uint8_t pp_num,
uint8_t ep_type,
uint16_t ep_mpl)
{
usb_pipe *pp = &pudev->host.pipe[pp_num];
pp->dev_addr = udev->addr;
pp->dev_speed = udev->speed;
pp->ep.type = ep_type;
pp->ep.mps = ep_mpl;
pp->ping = udev->speed == PORT_SPEED_HIGH;
usb_pipe_init (pudev, pp_num);
return HC_OK;
}
/*!
\brief modify a pipe
\param[in] pudev: pointer to usb core instance
\param[in] pp_num: pipe number
\param[in] dev_addr: device address
\param[in] dev_speed: device speed
\param[in] ep_type: endpoint type
\param[in] ep_mpl: endpoint max packet length
\param[out] none
\retval operation status
*/
uint8_t usbh_pipe_update (usb_core_driver *pudev,
uint8_t pp_num,
uint8_t dev_addr,
uint32_t dev_speed,
uint16_t ep_mpl)
{
usb_pipe *pp = &pudev->host.pipe[pp_num];
if ((pp->dev_addr != dev_addr) && (dev_addr)) {
pp->dev_addr = dev_addr;
}
if ((pp->dev_speed != dev_speed) && (dev_speed)) {
pp->dev_speed = dev_speed;
}
if ((pp->ep.mps != ep_mpl) && (ep_mpl)) {
pp->ep.mps = ep_mpl;
}
usb_pipe_init (pudev, pp_num);
return HC_OK;
}
/*!
\brief allocate a new pipe
\param[in] pudev: pointer to usb core instance
\param[in] ep_addr: endpoint address
\param[out] none
\retval operation status
*/
uint8_t usbh_pipe_allocate (usb_core_driver *pudev, uint8_t ep_addr)
{
uint16_t pp_num = usbh_freepipe_get (pudev);
if (HC_ERROR != pp_num) {
pudev->host.pipe[pp_num].in_used = 1U;
pudev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr);
pudev->host.pipe[pp_num].ep.num = EP_ID(ep_addr);
}
return pp_num;
}
/*!
\brief free a pipe
\param[in] pudev: pointer to usb core instance
\param[in] pp_num: pipe number
\param[out] none
\retval operation status
*/
uint8_t usbh_pipe_free (usb_core_driver *pudev, uint8_t pp_num)
{
if (pp_num < HC_MAX) {
pudev->host.pipe[pp_num].in_used = 0U;
}
return USBH_OK;
}
/*!
\brief delete all USB host pipe
\param[in] pudev: pointer to usb core instance
\param[out] none
\retval operation status
*/
uint8_t usbh_pipe_delete (usb_core_driver *pudev)
{
uint8_t pp_num = 0U;
for (pp_num = 2U; pp_num < HC_MAX; pp_num++) {
pudev->host.pipe[pp_num] = (usb_pipe) {0};
}
return USBH_OK;
}
/*!
\brief get a free pipe number for allocation
\param[in] pudev: pointer to usb core instance
\param[out] none
\retval operation status
*/
static uint16_t usbh_freepipe_get (usb_core_driver *pudev)
{
uint8_t pp_num = 0U;
for (pp_num = 0U; pp_num < HC_MAX; pp_num++) {
if (pudev->host.pipe[pp_num].in_used == 0U) {
return pp_num;
}
}
return HC_ERROR;
}

View File

@@ -1,391 +0,0 @@
/*!
\file usbh_transc.c
\brief USB host mode transactions driver
\version 2019-6-5, V1.0.0, firmware for GD32 USBFS&USBHS
*/
/*
Copyright (c) 2019, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "../Include/drv_usb_hw.h"
#include "../Include/usbh_transc.h"
/*!
\brief prepare a pipe and start a transfer
\param[in] pudev: pointer to usb core instance
\param[in] pp_num: pipe number
\param[out] none
\retval operation status
*/
static uint32_t usbh_request_submit (usb_core_driver *pudev, uint8_t pp_num)
{
pudev->host.pipe[pp_num].urb_state = URB_IDLE;
pudev->host.pipe[pp_num].xfer_count = 0U;
return usb_pipe_xfer (pudev, pp_num);
}
/*!
\brief send the setup packet to the USB device
\param[in] pudev: pointer to usb core instance
\param[in] buf: data buffer which will be sent to USB device
\param[in] pp_num: pipe number
\param[out] none
\retval operation status
*/
usbh_status usbh_ctlsetup_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num)
{
usb_pipe *pp = &pudev->host.pipe[pp_num];
pp->DPID = PIPE_DPID_SETUP;
pp->xfer_buf = buf;
pp->xfer_len = USB_SETUP_PACKET_LEN;
return (usbh_status)usbh_request_submit (pudev, pp_num);
}
/*!
\brief send a data packet to the USB device
\param[in] pudev: pointer to usb core instance
\param[in] buf: data buffer which will be sent to USB device
\param[in] pp_num: pipe number
\param[in] len: length of the data to be sent
\param[out] none
\retval operation status
*/
usbh_status usbh_data_send (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len)
{
usb_pipe *pp = &pudev->host.pipe[pp_num];
pp->xfer_buf = buf;
pp->xfer_len = len;
switch (pp->ep.type) {
case USB_EPTYPE_CTRL:
if (0U == len) {
pp->data_toggle_out = 1U;
}
pp->DPID = PIPE_DPID[pp->data_toggle_out];
break;
case USB_EPTYPE_INTR:
pp->DPID = PIPE_DPID[pp->data_toggle_out];
pp->data_toggle_out ^= 1U;
break;
case USB_EPTYPE_BULK:
pp->DPID = PIPE_DPID[pp->data_toggle_out];
break;
case USB_EPTYPE_ISOC:
pp->DPID = PIPE_DPID[0];
break;
default:
break;
}
usbh_request_submit (pudev, pp_num);
return USBH_OK;
}
/*!
\brief receive a data packet from the USB device
\param[in] pudev: pointer to usb core instance
\param[in] buf: data buffer which will be received from USB device
\param[in] pp_num: pipe number
\param[in] len: length of the data to be received
\param[out] none
\retval operation status
*/
usbh_status usbh_data_recev (usb_core_driver *pudev, uint8_t *buf, uint8_t pp_num, uint16_t len)
{
usb_pipe *pp = &pudev->host.pipe[pp_num];
pp->xfer_buf = buf;
pp->xfer_len = len;
switch (pp->ep.type) {
case USB_EPTYPE_CTRL:
pp->DPID = PIPE_DPID[1];
break;
case USB_EPTYPE_INTR:
pp->DPID = PIPE_DPID[pp->data_toggle_in];
/* Toggle DATA PID */
pp->data_toggle_in ^= 1U;
break;
case USB_EPTYPE_BULK:
pp->DPID = PIPE_DPID[pp->data_toggle_in];
break;
case USB_EPTYPE_ISOC:
pp->DPID = PIPE_DPID[0];
break;
default:
break;
}
usbh_request_submit (pudev, pp_num);
return USBH_OK;
}
/*!
\brief wait for USB URB(USB request block) state
\param[in] pudev: pointer to USB core instance
\param[in] puhost: pointer to USB host
\param[in] pp_num: pipe number
\param[in] wait_time: wait time
\param[out] none
\retval USB URB state
*/
static usb_urb_state usbh_urb_wait (usb_core_driver *pudev, usbh_host *puhost, uint8_t pp_num, uint32_t wait_time)
{
usb_urb_state urb_status = URB_IDLE;
while (URB_DONE != (urb_status = usbh_urbstate_get(pudev, pp_num))) {
if (URB_NOTREADY == urb_status) {
break;
} else if (URB_STALL == urb_status) {
puhost->control.ctl_state = CTL_SETUP;
break;
} else if (URB_ERROR == urb_status) {
puhost->control.ctl_state = CTL_ERROR;
break;
} else if ((wait_time > 0U) && \
((usb_curframe_get(pudev)- puhost->control.timer) > wait_time)) {
/* timeout for in transfer */
puhost->control.ctl_state = CTL_ERROR;
break;
} else {
/* no operation, just wait */
}
}
return urb_status;
}
/*!
\brief USB setup transaction
\param[in] pudev: pointer to USB core instance
\param[in] puhost: pointer to USB host
\param[out] none
\retval none
*/
static void usbh_setup_transc (usb_core_driver *pudev, usbh_host *puhost)
{
usb_urb_state urb_status = URB_IDLE;
/* send a SETUP packet */
usbh_ctlsetup_send (pudev,
puhost->control.setup.data,
puhost->control.pipe_out_num);
urb_status = usbh_urb_wait (pudev, puhost, puhost->control.pipe_out_num, 0U);
if (URB_DONE == urb_status) {
uint8_t dir = (puhost->control.setup.req.bmRequestType & USB_TRX_MASK);
if (puhost->control.setup.req.wLength) {
if (USB_TRX_IN == dir) {
puhost->control.ctl_state = CTL_DATA_IN;
} else {
puhost->control.ctl_state = CTL_DATA_OUT;
}
} else {
if (USB_TRX_IN == dir) {
puhost->control.ctl_state = CTL_STATUS_OUT;
} else {
puhost->control.ctl_state = CTL_STATUS_IN;
}
}
/* set the delay timer to enable timeout for data stage completion */
puhost->control.timer = usb_curframe_get(pudev);
}
}
/*!
\brief USB data IN transaction
\param[in] pudev: pointer to USB core instance
\param[in] puhost: pointer to USB host
\param[out] none
\retval none
*/
static void usbh_data_in_transc (usb_core_driver *pudev, usbh_host *puhost)
{
usb_urb_state urb_status = URB_IDLE;
usbh_data_recev (pudev,
puhost->control.buf,
puhost->control.pipe_in_num,
puhost->control.ctl_len);
urb_status = usbh_urb_wait (pudev, puhost, puhost->control.pipe_in_num, DATA_STAGE_TIMEOUT);
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_STATUS_OUT;
puhost->control.timer = usb_curframe_get(pudev);
}
}
/*!
\brief USB data OUT transaction
\param[in] pudev: pointer to USB core instance
\param[in] puhost: pointer to USB host
\param[out] none
\retval none
*/
static void usbh_data_out_transc (usb_core_driver *pudev, usbh_host *puhost)
{
usb_urb_state urb_status = URB_IDLE;
pudev->host.pipe[puhost->control.pipe_out_num].data_toggle_out = 1U;
usbh_data_send (pudev,
puhost->control.buf,
puhost->control.pipe_out_num,
puhost->control.ctl_len);
urb_status = usbh_urb_wait (pudev, puhost, puhost->control.pipe_out_num, DATA_STAGE_TIMEOUT);
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_STATUS_IN;
puhost->control.timer = usb_curframe_get(pudev);
}
}
/*!
\brief USB status IN transaction
\param[in] pudev: pointer to USB core instance
\param[in] puhost: pointer to USB host
\param[out] none
\retval none
*/
static void usbh_status_in_transc (usb_core_driver *pudev, usbh_host *puhost)
{
uint8_t pp_num = puhost->control.pipe_in_num;
usb_urb_state urb_status = URB_IDLE;
usbh_data_recev (pudev, NULL, pp_num, 0U);
urb_status = usbh_urb_wait (pudev, puhost, pp_num, NODATA_STAGE_TIMEOUT);
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_FINISH;
}
}
/*!
\brief USB status OUT transaction
\param[in] pudev: pointer to USB core instance
\param[in] puhost: pointer to USB host
\param[out] none
\retval none
*/
static void usbh_status_out_transc (usb_core_driver *pudev, usbh_host *puhost)
{
uint8_t pp_num = puhost->control.pipe_out_num;
usb_urb_state urb_status = URB_IDLE;
pudev->host.pipe[pp_num].data_toggle_out ^= 1U;
usbh_data_send (pudev, NULL, pp_num, 0U);
urb_status = usbh_urb_wait (pudev, puhost, pp_num, NODATA_STAGE_TIMEOUT);
if (URB_DONE == urb_status) {
puhost->control.ctl_state = CTL_FINISH;
}
}
/*!
\brief USB control transfer handler
\param[in] pudev: pointer to USB core instance
\param[in] puhost: pointer to USB host
\param[out] none
\retval operation status
*/
usbh_status usbh_ctl_handler (usb_core_driver *pudev, usbh_host *puhost)
{
usbh_status status = USBH_BUSY;
switch (puhost->control.ctl_state) {
case CTL_SETUP:
usbh_setup_transc (pudev, puhost);
break;
case CTL_DATA_IN:
usbh_data_in_transc (pudev, puhost);
break;
case CTL_DATA_OUT:
usbh_data_out_transc (pudev, puhost);
break;
case CTL_STATUS_IN:
usbh_status_in_transc (pudev, puhost);
break;
case CTL_STATUS_OUT:
usbh_status_out_transc (pudev, puhost);
break;
case CTL_FINISH:
puhost->control.ctl_state = CTL_IDLE;
status = USBH_OK;
break;
case CTL_ERROR:
if (++puhost->control.error_count <= USBH_MAX_ERROR_COUNT) {
/* do the transmission again, starting from SETUP packet */
puhost->control.ctl_state = CTL_SETUP;
} else {
status = USBH_FAIL;
}
break;
default:
break;
}
return status;
}