From 8dc27fcbb690f5a27358b78782f7d217253b5235 Mon Sep 17 00:00:00 2001 From: Yunfeng Liu Date: Sun, 5 Jul 2015 17:58:52 -0400 Subject: [PATCH] initial commit --- .gitignore | 5 + README.md | 14 + build/IBDAP.ld | 188 +++++ build/IBDAP_lib.ld | 15 + build/IBDAP_mem.ld | 27 + build/Makefile | 52 ++ build/checksum | Bin 0 -> 12355 bytes build/objects.mk | 8 + build/sources.mk | 18 + build/src/subdir.mk | 58 ++ inc/DAP.h | 235 +++++++ inc/DAP_config.h | 474 +++++++++++++ inc/LPC11Uxx.h | 741 ++++++++++++++++++++ inc/app_usbd_cfg.h | 95 +++ inc/compiler.h | 19 + inc/core_cm0.h | 682 +++++++++++++++++++ inc/core_cmFunc.h | 636 +++++++++++++++++ inc/core_cmInstr.h | 688 +++++++++++++++++++ inc/error.h | 136 ++++ inc/lpc_types.h | 216 ++++++ inc/system_LPC11Uxx.h | 64 ++ inc/uart.h | 13 + inc/usb_driver.h | 53 ++ inc/usbd/usbd.h | 704 +++++++++++++++++++ inc/usbd/usbd_audio.h | 377 ++++++++++ inc/usbd/usbd_cdc.h | 249 +++++++ inc/usbd/usbd_cdcuser.h | 499 ++++++++++++++ inc/usbd/usbd_core.h | 585 ++++++++++++++++ inc/usbd/usbd_desc.h | 48 ++ inc/usbd/usbd_dfu.h | 120 ++++ inc/usbd/usbd_dfuuser.h | 270 ++++++++ inc/usbd/usbd_hid.h | 430 ++++++++++++ inc/usbd/usbd_hiduser.h | 421 ++++++++++++ inc/usbd/usbd_hw.h | 457 +++++++++++++ inc/usbd/usbd_msc.h | 119 ++++ inc/usbd/usbd_mscuser.h | 270 ++++++++ inc/usbd/usbd_rom_api.h | 92 +++ openocd-example.cfg | 8 + src/DAP.c | 1364 +++++++++++++++++++++++++++++++++++++ src/IBDAP.c | 251 +++++++ src/JTAG_DP.c | 358 ++++++++++ src/SW_DP.c | 236 +++++++ src/cr_startup_lpc11uxx.c | 348 ++++++++++ src/crp.c | 38 ++ src/system_LPC11Uxx.c | 495 ++++++++++++++ src/uart.c | 23 + src/usb_desc.c | 178 +++++ src/usb_driver.c | 187 +++++ 48 files changed, 12564 insertions(+) create mode 100644 .gitignore create mode 100644 build/IBDAP.ld create mode 100644 build/IBDAP_lib.ld create mode 100644 build/IBDAP_mem.ld create mode 100644 build/Makefile create mode 100755 build/checksum create mode 100644 build/objects.mk create mode 100644 build/sources.mk create mode 100644 build/src/subdir.mk create mode 100644 inc/DAP.h create mode 100644 inc/DAP_config.h create mode 100644 inc/LPC11Uxx.h create mode 100644 inc/app_usbd_cfg.h create mode 100644 inc/compiler.h create mode 100644 inc/core_cm0.h create mode 100644 inc/core_cmFunc.h create mode 100644 inc/core_cmInstr.h create mode 100644 inc/error.h create mode 100644 inc/lpc_types.h create mode 100644 inc/system_LPC11Uxx.h create mode 100644 inc/uart.h create mode 100644 inc/usb_driver.h create mode 100644 inc/usbd/usbd.h create mode 100644 inc/usbd/usbd_audio.h create mode 100644 inc/usbd/usbd_cdc.h create mode 100644 inc/usbd/usbd_cdcuser.h create mode 100644 inc/usbd/usbd_core.h create mode 100644 inc/usbd/usbd_desc.h create mode 100644 inc/usbd/usbd_dfu.h create mode 100644 inc/usbd/usbd_dfuuser.h create mode 100644 inc/usbd/usbd_hid.h create mode 100644 inc/usbd/usbd_hiduser.h create mode 100644 inc/usbd/usbd_hw.h create mode 100644 inc/usbd/usbd_msc.h create mode 100644 inc/usbd/usbd_mscuser.h create mode 100644 inc/usbd/usbd_rom_api.h create mode 100644 openocd-example.cfg create mode 100644 src/DAP.c create mode 100755 src/IBDAP.c create mode 100644 src/JTAG_DP.c create mode 100644 src/SW_DP.c create mode 100755 src/cr_startup_lpc11uxx.c create mode 100755 src/crp.c create mode 100644 src/system_LPC11Uxx.c create mode 100644 src/uart.c create mode 100644 src/usb_desc.c create mode 100644 src/usb_driver.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..76f0522 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.d +*.o +*.bin +*.map +*.axf diff --git a/README.md b/README.md index 1dd4916..8af13de 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,16 @@ # IBDAP-CMSIS-DAP Armstart's CMSIS-DAP firmware implementation in gcc and makefile. + +[http://www.armstart.com](http://www.armstart.com) + +[IBDAP](https://hackaday.io/project/6578-ibdap-affordable-cmsis-dap-jtagswd-debug-probe) is a fully CMSIS-DAP compatible debug adapter. It provides vendor independent debug interface between your PC over USB and target ARM device over JTAG/SWD pins. You can do debugging functions like stepping, breakpoints, watch points and firmware download etc. It's fully supported by Keil, OpenOCD, GNU GDB, IAR and other commonly used debugging tools. + +# Why IBDAP? + +Debug adapters are expensive, some could cost thousands of dollars, some may not be compatible among different vendors. Luckily, ARM standardized the debugging interface which is called CMSIS-DAP and released the firmware implementation on some processors, however, you still need a Keil MDK Professional edition software in order to build the firmware, even the open source one provided by mbed and the price for Keil Professional is intimidating. All these barriers has become the first issue that every inventor is facing, and we need a solution! +IBDAP's objective is to become an affordable open source & open hardware CMSIS-DAP JTAG/SWD debug probe implementation using gcc & makefile. Anyone can modify and embed a debug probe on its own device easily with everything under its control. + +Besides being functioning as a JTAG/SWD debug probe, IBDAP could also be used as a general development board. It has an ARM Cortex M0 processor running at 48Mhz and has peripherals like UART, I2C, SPI, USB. It can be used in many applications like USB audio devices, USB mouse/keyboards, USB mass storage devices, USB-TTL adapter device and many many more. Moreover, the 10-bit high precision ADC peripheral also makes IBDAP an ideal device for any sensor projects. + +![IBDAP pinmap](https://s3.amazonaws.com/armstart/Debug+Tools/IBDAP-LPC11U35/7.jpg) + diff --git a/build/IBDAP.ld b/build/IBDAP.ld new file mode 100644 index 0000000..dc8ac53 --- /dev/null +++ b/build/IBDAP.ld @@ -0,0 +1,188 @@ +/* + * GENERATED FILE - DO NOT EDIT + * (c) Code Red Technologies Ltd, 2008-13 + * (c) NXP Semiconductors 2013-2015 + * Generated linker script file for LPC11U35/501 + * Created from generic_c.ld (7.7.2 ()) + * By LPCXpresso v7.7.2 [Build 379] [2015-03-31] on Wed Jun 24 20:31:09 EDT 2015 + */ + + +INCLUDE "IBDAP_lib.ld" +INCLUDE "IBDAP_mem.ld" + +ENTRY(ResetISR) + +SECTIONS +{ + + /* MAIN TEXT SECTION */ + .text : ALIGN(4) + { + FILL(0xff) + __vectors_start__ = ABSOLUTE(.) ; + KEEP(*(.isr_vector)) + + /* Global Section Table */ + . = ALIGN(4) ; + __section_table_start = .; + __data_section_table = .; + LONG(LOADADDR(.data)); + LONG( ADDR(.data)); + LONG( SIZEOF(.data)); + LONG(LOADADDR(.data_RAM2)); + LONG( ADDR(.data_RAM2)); + LONG( SIZEOF(.data_RAM2)); + LONG(LOADADDR(.data_RAM3)); + LONG( ADDR(.data_RAM3)); + LONG( SIZEOF(.data_RAM3)); + __data_section_table_end = .; + __bss_section_table = .; + LONG( ADDR(.bss)); + LONG( SIZEOF(.bss)); + LONG( ADDR(.bss_RAM2)); + LONG( SIZEOF(.bss_RAM2)); + LONG( ADDR(.bss_RAM3)); + LONG( SIZEOF(.bss_RAM3)); + __bss_section_table_end = .; + __section_table_end = . ; + /* End of Global Section Table */ + + + *(.after_vectors*) + + } >MFlash64 + + .text : ALIGN(4) + { + *(.text*) + *(.rodata .rodata.* .constdata .constdata.*) + . = ALIGN(4); + + } > MFlash64 + + /* + * for exception handling/unwind - some Newlib functions (in common + * with C++ and STDC++) use this. + */ + .ARM.extab : ALIGN(4) + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > MFlash64 + __exidx_start = .; + + .ARM.exidx : ALIGN(4) + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > MFlash64 + __exidx_end = .; + + _etext = .; + + + /* DATA section for RamUsb2 */ + .data_RAM2 : ALIGN(4) + { + FILL(0xff) + PROVIDE(__start_data_RAM2 = .) ; + *(.ramfunc.$RAM2) + *(.ramfunc.$RamUsb2) + *(.data.$RAM2*) + *(.data.$RamUsb2*) + . = ALIGN(4) ; + PROVIDE(__end_data_RAM2 = .) ; + } > RamUsb2 AT>MFlash64 + + /* DATA section for SRAM1_2 */ + .data_RAM3 : ALIGN(4) + { + FILL(0xff) + PROVIDE(__start_data_RAM3 = .) ; + *(.ramfunc.$RAM3) + *(.ramfunc.$SRAM1_2) + *(.data.$RAM3*) + *(.data.$SRAM1_2*) + . = ALIGN(4) ; + PROVIDE(__end_data_RAM3 = .) ; + } > SRAM1_2 AT>MFlash64 + + /* MAIN DATA SECTION */ + + + .uninit_RESERVED : ALIGN(4) + { + KEEP(*(.bss.$RESERVED*)) + . = ALIGN(4) ; + _end_uninit_RESERVED = .; + } > RamLoc8 + + + /* Main DATA section (RamLoc8) */ + .data : ALIGN(4) + { + FILL(0xff) + _data = . ; + *(vtable) + *(.ramfunc*) + *(.data*) + . = ALIGN(4) ; + _edata = . ; + } > RamLoc8 AT>MFlash64 + + /* BSS section for RamUsb2 */ + .bss_RAM2 : ALIGN(4) + { + PROVIDE(__start_bss_RAM2 = .) ; + *(.bss.$RAM2*) + *(.bss.$RamUsb2*) + . = ALIGN(4) ; + PROVIDE(__end_bss_RAM2 = .) ; + } > RamUsb2 + /* BSS section for SRAM1_2 */ + .bss_RAM3 : ALIGN(4) + { + PROVIDE(__start_bss_RAM3 = .) ; + *(.bss.$RAM3*) + *(.bss.$SRAM1_2*) + . = ALIGN(4) ; + PROVIDE(__end_bss_RAM3 = .) ; + } > SRAM1_2 + + /* MAIN BSS SECTION */ + .bss : ALIGN(4) + { + _bss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4) ; + _ebss = .; + PROVIDE(end = .); + } > RamLoc8 + + /* NOINIT section for RamUsb2 */ + .noinit_RAM2 (NOLOAD) : ALIGN(4) + { + *(.noinit.$RAM2*) + *(.noinit.$RamUsb2*) + . = ALIGN(4) ; + } > RamUsb2 + /* NOINIT section for SRAM1_2 */ + .noinit_RAM3 (NOLOAD) : ALIGN(4) + { + *(.noinit.$RAM3*) + *(.noinit.$SRAM1_2*) + . = ALIGN(4) ; + } > SRAM1_2 + + /* DEFAULT NOINIT SECTION */ + .noinit (NOLOAD): ALIGN(4) + { + _noinit = .; + *(.noinit*) + . = ALIGN(4) ; + _end_noinit = .; + } > RamLoc8 + + PROVIDE(_pvHeapStart = DEFINED(__user_heap_base) ? __user_heap_base : .); + PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RamLoc8 - 0); +} diff --git a/build/IBDAP_lib.ld b/build/IBDAP_lib.ld new file mode 100644 index 0000000..682c593 --- /dev/null +++ b/build/IBDAP_lib.ld @@ -0,0 +1,15 @@ +/* + * GENERATED FILE - DO NOT EDIT + * (c) Code Red Technologies Ltd, 2008-13 + * (c) NXP Semiconductors 2013-2015 + * Generated linker script file for LPC11U35/501 + * Created from LibIncTemplate.ld (7.7.2 ()) + * By LPCXpresso v7.7.2 [Build 379] [2015-03-31] on Wed Jun 24 20:31:09 EDT 2015 + */ + + + GROUP( + libgcc.a + libc_nano.a + libm.a + ) diff --git a/build/IBDAP_mem.ld b/build/IBDAP_mem.ld new file mode 100644 index 0000000..f42bde3 --- /dev/null +++ b/build/IBDAP_mem.ld @@ -0,0 +1,27 @@ +/* + * GENERATED FILE - DO NOT EDIT + * (c) Code Red Technologies Ltd, 2008-2015 + * (c) NXP Semiconductors 2013-2015 + * Linker script memory definitions + * Created from LinkMemoryTemplate + * By LPCXpresso v7.7.2 [Build 379] [2015-03-31] on Wed Jun 24 20:31:09 EDT 2015) +*/ + +MEMORY +{ + /* Define each memory region */ + MFlash64 (rx) : ORIGIN = 0x0, LENGTH = 0x10000 /* 64K bytes */ + RamLoc8 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x2000 /* 8K bytes */ + RamUsb2 (rwx) : ORIGIN = 0x20004000, LENGTH = 0x800 /* 2K bytes */ + SRAM1_2 (rwx) : ORIGIN = 0x20000000, LENGTH = 0x800 /* 2K bytes */ + + +} + /* Define a symbol for the top of each memory region */ + __top_MFlash64 = 0x0 + 0x10000; + __top_RamLoc8 = 0x10000000 + 0x2000; + __top_RamUsb2 = 0x20004000 + 0x800; + __top_SRAM1_2 = 0x20000000 + 0x800; + + + diff --git a/build/Makefile b/build/Makefile new file mode 100644 index 0000000..14f907e --- /dev/null +++ b/build/Makefile @@ -0,0 +1,52 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +-include ../makefile.init + +RM := rm -rf + +# All Target +all: IBDAP.axf + +# All of the sources participating in the build are defined here +-include sources.mk +-include src/subdir.mk +-include subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables + + + +# Tool invocations +IBDAP.axf: $(OBJS) $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: MCU Linker' + arm-none-eabi-gcc -nostdlib -Xlinker -Map="IBDAP.map" -Xlinker --gc-sections -Xlinker --trace -mcpu=cortex-m0 -mthumb -T "IBDAP.ld" -o "IBDAP.axf" $(OBJS) $(USER_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + $(MAKE) --no-print-directory post-build + +# Other Targets +clean: + -$(RM) $(OBJS)$(C_DEPS)$(EXECUTABLES) IBDAP.axf IBDAP.bin IBDAP.map + -@echo ' ' + +post-build: + -@echo 'Performing post-build steps' + -arm-none-eabi-size "IBDAP.axf" ; arm-none-eabi-objcopy -v -O binary "IBDAP.axf" "IBDAP.bin" ; ./checksum -p LPC11U35_501 -d "IBDAP.bin" + -@echo ' ' + +.PHONY: all clean dependents +.SECONDARY: post-build + +-include ../makefile.targets diff --git a/build/checksum b/build/checksum new file mode 100755 index 0000000000000000000000000000000000000000..993df0ed6dee0dcc1557527e52344304973690f0 GIT binary patch literal 12355 zcmeHNe{fXCeczJ~b11?RAc~A-=NTWaWY8gj!2I%5APIwgfPy6(8^hzcd#88iba%OX z2a-cl=s|5+sFoevx~-F1V^5lTJh44a+)kZ##DIg{W?bxaGM>ca(8TT>5$(_fCp5vn zem=WzPp1oU)4%$U_Ga(9pZ$LKyWjopkGJpb{$W>elgHx`I#h^CLDc@oUSAt%{UXI_ z6NZ>28pVy`dT|Z1$ZItmb;%t#)xWdsodWf@a*g{}29ag!5a~PeZ@%}5zxrwYfnfcUZyC>bf8oS^oy`l#qb%!?zFJaoGconT zeWK}x;|(v|^^@^6KO1fs+_L{wWK9W_)4@OjE-VHEsqYt&()Z;u{7e}>UWUI^hEJB^ zx61Hem*H=f;iF~vjWRq~hX0)SWv`FEoFlFi4}!-3MB^Iq4d8PxX?&en0bGZ14kG<0 z&~F(h5?-=|owiDtW?z3YVP>3A+A&RG-g&^>VfDo_j+O3+hcX!}Ly>_2Gi9YS$wVj~ za|X==EmYI5G$7R%4x1UGR_2FY&0DrZZ6ua3vl%NQtbv##qREt%5E&<(2=}K*I+k#vFp>4Tt>_QM z5~5@0&J7#4n5}^o;*Q{!jUDE47^hP$^aeu(ewA)ydh+K%T8(v&9E%)R2IBW#+>c@D z6?vo?D7P0>kGnas*ldpQpSyXr5?6?iff+7hE?&U5py;X?eFJCDX3di1YX5_IjiTsl=Cw~rg?A-O{slv+3u)MJN3jVZa`aks?ufZa{pE-^h}?<8)Km>#kB5*rfJGd3G^z7`m?7+U{h z&(Oc+KDgN3v%`LA1XAPp``kVD=O6a^@|6(2G&&`?zCC=q7o97ze=z0)ea#2Y9hvar z|KzVLauc34?`Ccsk?U7(-196&3U$ZGmf~yPP3ONeg9<#k)81XXPmMUYh>>sqK8=F@ z+=cqFYRDcNcjo>b^N^Tz#_MNZ;q05IMqQb6Xw*=rzxqt4--l5nK)vWz0nwMSYUH2% zq)-^6&~R_{P>&zP2jU&_`ty&11u;tJ-$&Zj$N{T_tCg^iI=>BNEYu6ZH&0RYgNygx zgAo=1_W`J2%{!^<{0;aY1~_@HqOz-cSk$~K);HIj7_WJC9G3Rv4*7dT&C$PwXsHy6 z`}izjWj}gMRaTG6j*Vw$vkIyDA3mkfkKIB)`B)aZ@yrZAolBK78giS}tNKG% z%U6_^?N=$g4rL!ecg)OP_Bit={H3a%twv1~bEag~B8x46B_c;Bk-M(TSM&7v(eavN zZ=;c8G!-iE9HaMje=ef!ll_^8Y5CVNg+EQGdK5y>P>7bmc{dHS52$7tSVQQ-I#h^$ z=bXs@J0)r0vGJOt-&6H*N{RCvxWhgE?xC~jM-Tso5AWq*g9ZbohEA4oN6D4ChJya$ zAnSrCtcaEgAGRUO6RUcBga?` zY*;cppHgx*a4OIzn@3fPzVz$Kx$q9sxGs_ zzfofT<7%MvvILeY*KqD2*gL@?^v?Oqvb~?$gEMHkEB_|s$G9|M<{uh?i{PfV;oCWo zWPf7LA!jMX+pvb#yn2x-JWC{aSAhx%-cX=Yg0pIUIOJ~_KIC6IbjV*nQwbiFEjLCyn~)V_TlBLUAW9q{-lf8OC)lHU$r9y!&7WiNN3A;0dIg~G^dUX&ck z@xSTJ$wI}kg5z)f#c)?G9OJ{v2I3v=;-XYI@d~AK-|?*ZB>jHwbORc*`_yoQAJw8h z?uEv#;5{sNx!}xujj8BpZo*qQJ6wsZ?4_K12p47Z>{#rZp1ujwvl>3S4|^oOyKp}k z?Cw}0{{{v~makF&3bhin4!A7IaX}kF8$nk(olLJaSVwOr)Mu?V7H5oI%_$?5PKK>a zCYjz17~$W6-A359!uvDX{!OvCRdugzrLDD9%?FHF#yDW5_hC0()f^#;#4@RPXwZly zqRDiB$cZHrRi$MqbJB!geAVPxi&EjIq3>WleMI@+vXKC%Vn-i=zHS(t&}gR5I;A z3oTqs-MyJuqHoe|p?F^s?<#h`D`7M)ju;1%=}4xjN~HHK5gnlfHSwKjvXt~bTD7Gw zfzr^|GO&1{N^FSWO-h4%@ER789q4j}*pk2-8(z;0yf1O=9GDc*?J;h;-DoiysSgH} z=qL(+FDqkP@qWd|6?x#aET0mM5Nwa)?ah(JFs{_lf$^9J*H^CN=AG~Ghd(M5xNCR^ zG!FVP=p&#%#N%olbO9c9?}64MGI$>9-XT1PeAmb~*Xygj-bXy-8HkN2y8~2gxYoDv zSjBAWCy$ScJ>V??E#>jM$46f6@*V|#43P&hj4beHz)vGGP5+WU2mCi>a(8retTh^Y z_hl1Kc3Ci%2&I!oTL8c2*0!w7T^VR?l36Ro?;xy2MIbZSk1s8tPFhi0r*O1trBfn+ zj}%q_r>V_OsLw@xiELnBHiioTv4{u|*`bUr0+GQ4^eO736$f9TGWgas1(@KatvKaX zA{BQ;AeO)xalo+#@E-*LD~azMArY`_Gn&R{Cex0fq(&kTc9Q7~s#D~_Fqlw@Pefr< zmxLPp1*C4JXI}==;becmm2lwc-z{7ZG0qK+NqOG`fMZq%@)&MLWWQ2Q-pc^PKw1a+ zH5i~3QOiAodGrY6{8|W9%XK3C3wJJX{=EP>{Y{19lw;h6$T`S*IWOO%93tl_h?J=X zy$6wVlX9HL)c~BoI_TscWav4_`B#TZZb2T$Cj-kf?nmUDWt#JLJ>M^}zj$$LdO#^+kDgO+<8 z8PrEP9yohHtNdRs_uUdX9xPWwPV1noPQQ&b`-1x9eI>}9bMru?9NqZ?L|rfML0r6w zKI;5Yi5#CJmmt@PJRK;*m`Bw5+HuCvZU}J{c{&(w;y*!IKkegL_h|#qHKcVg+{Dj8 zsZWn3%I$P{B;+x|{Zbc*3=KC4aYX}A$}o_!Z*_R%7F_ed7`y=)t%z&`#}>ytZPQ_3 zsSy8MlA-l!ektX8M67PKsdYzTRWsKYg_T0CBMP&2wO%L;!w|SGD9j$k{K7m`m@Af= z=L*Yg`5af6tx(T*g}FOW^HX82Q0Pa@Lxt7In&v+2StB;~0(O z!GpVB_k;4@2z!#)20dFMUpj7BzkK2q>zgZ%KtBG2wr7rb47jxZzXUd1|Fiy=fpwrh zt~ZxZANP*rzXiGpcVd>f_7M9;j;m8erZ2TC{HyunyFBZyAmOpMyVi`7f05N6PS5fqDL{<-Z2p>5l(7 z74_m3VBTtCopUPYiE&_FjpDeZf6oHzKzn{%hCc#6?dq$=c=D92d6b`5hHnL43VW!N z^2^9Cv2R0}d`}s+fJ^I(1DD>794V9k3h+YRpB1ykH-UMKt^F|$%sXH_S7Li#2j+f+ z_RZyvESz>SPBt11gmFW$qi6dLGq~mM9$vFFJEx#KJ4#rQq}dlw?hD0Dxve!r*#Utq zYbtKxKrV1w%c_-v3^NuPAi52AA-OY-Wc&LEbv<3%I%PGRc5K+%WopD~bb7KDxrbJ@ zxCf|#a4IFt`-3axVPf}P;k#R4GjNut(M8er6G;v^TMl8HX zWWzjWHd|sbVcrqkzHvj)G`E;xoK~CIfv0iqTFl?RY17?ZJ!a2_jlnK@h$_ucIvpB> zXk==Jysj$D&il4)*t(@daBr_Je?m;&1Vs&|e1n);l`5ytG=oX@%m04=HJUQ*gTg&b z7p`8{Ra-NCqIepvYge~vc@MR{ee%w!u9oNY!kl_LR`WWNc)^33k`~G9v88&{71_z0 zR`;6hWKIij%;IWoX^y;lJDJfc-0J|WER!^CbQ#T315*!@qA%r}nYwyAsiQ^Tzb(x& zO}t~douO{=mU3ZNBCKxmmS)QyRyTl4v!!%@sx(X9`z_5dE%|15wM)wF?IpK>dH;Ay mIWx9u^{N0aE10RU>DbxC{=hy=G`C-IJdR7qxJWF=q4*!Aq)}J^ literal 0 HcmV?d00001 diff --git a/build/objects.mk b/build/objects.mk new file mode 100644 index 0000000..fc514e4 --- /dev/null +++ b/build/objects.mk @@ -0,0 +1,8 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +USER_OBJS := + +LIBS := + diff --git a/build/sources.mk b/build/sources.mk new file mode 100644 index 0000000..3712f5e --- /dev/null +++ b/build/sources.mk @@ -0,0 +1,18 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +O_SRCS := +C_SRCS := +S_SRCS := +S_UPPER_SRCS := +OBJ_SRCS := +ASM_SRCS := +OBJS := +C_DEPS := +EXECUTABLES := + +# Every subdirectory with source files must be described here +SUBDIRS := \ +src \ + diff --git a/build/src/subdir.mk b/build/src/subdir.mk new file mode 100644 index 0000000..de8d18a --- /dev/null +++ b/build/src/subdir.mk @@ -0,0 +1,58 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +../src/DAP.c \ +../src/IBDAP.c \ +../src/JTAG_DP.c \ +../src/SW_DP.c \ +../src/cr_startup_lpc11uxx.c \ +../src/crp.c \ +../src/system_LPC11Uxx.c \ +../src/uart.c \ +../src/usb_desc.c \ +../src/usb_driver.c + +OBJS += \ +./src/DAP.o \ +./src/IBDAP.o \ +./src/JTAG_DP.o \ +./src/SW_DP.o \ +./src/cr_startup_lpc11uxx.o \ +./src/crp.o \ +./src/system_LPC11Uxx.o \ +./src/uart.o \ +./src/usb_desc.o \ +./src/usb_driver.o + +C_DEPS += \ +./src/DAP.d \ +./src/IBDAP.d \ +./src/JTAG_DP.d \ +./src/SW_DP.d \ +./src/cr_startup_lpc11uxx.d \ +./src/crp.d \ +./src/system_LPC11Uxx.d \ +./src/uart.d \ +./src/usb_desc.d \ +./src/usb_driver.d + + +# Each subdirectory must supply rules for building sources it contributes +src/%.o: ../src/%.c + @echo 'Building file: $<' + @echo 'Invoking: MCU C Compiler' + arm-none-eabi-gcc -DNDEBUG -DCORE_M0 -D__USE_CMSIS -D__LPC11UXX__ -I"/home/yliu/projects/ib51822/IBDAP-FW/Firmware/IBDAP/inc" -I"/home/yliu/projects/ib51822/IBDAP-FW/Firmware/IBDAP/inc/usbd" -Os -g -Wall -c -fmessage-length=0 -fno-builtin -ffunction-sections -fdata-sections -mcpu=cortex-m0 -mthumb -v -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + +src/system_LPC11Uxx.o: ../src/system_LPC11Uxx.c + @echo 'Building file: $<' + @echo 'Invoking: MCU C Compiler' + arm-none-eabi-gcc -DNDEBUG -DCORE_M0 -D__USE_CMSIS -D__LPC11UXX__ -I"/home/yliu/projects/ib51822/IBDAP-FW/Firmware/IBDAP/inc" -I"/home/yliu/projects/ib51822/IBDAP-FW/Firmware/IBDAP/inc/usbd" -Os -g -Wall -c -fmessage-length=0 -fno-builtin -ffunction-sections -fdata-sections -mcpu=cortex-m0 -mthumb -v -MMD -MP -MF"$(@:%.o=%.d)" -MT"src/system_LPC11Uxx.d" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/inc/DAP.h b/inc/DAP.h new file mode 100644 index 0000000..8e67d32 --- /dev/null +++ b/inc/DAP.h @@ -0,0 +1,235 @@ +/****************************************************************************** + * @file DAP.h + * @brief CMSIS-DAP Definitions + * @version V1.00 + * @date 31. May 2012 + * + * @note + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#ifndef __DAP_H__ +#define __DAP_H__ + + +// DAP Command IDs +#define ID_DAP_Info 0x00 +#define ID_DAP_LED 0x01 +#define ID_DAP_Connect 0x02 +#define ID_DAP_Disconnect 0x03 +#define ID_DAP_TransferConfigure 0x04 +#define ID_DAP_Transfer 0x05 +#define ID_DAP_TransferBlock 0x06 +#define ID_DAP_TransferAbort 0x07 +#define ID_DAP_WriteABORT 0x08 +#define ID_DAP_Delay 0x09 +#define ID_DAP_ResetTarget 0x0A +#define ID_DAP_SWJ_Pins 0x10 +#define ID_DAP_SWJ_Clock 0x11 +#define ID_DAP_SWJ_Sequence 0x12 +#define ID_DAP_SWD_Configure 0x13 +#define ID_DAP_JTAG_Sequence 0x14 +#define ID_DAP_JTAG_Configure 0x15 +#define ID_DAP_JTAG_IDCODE 0x16 + +// DAP Vendor Command IDs +#define ID_DAP_Vendor0 0x80 +#define ID_DAP_Vendor1 0x81 +#define ID_DAP_Vendor2 0x82 +#define ID_DAP_Vendor3 0x83 +#define ID_DAP_Vendor4 0x84 +#define ID_DAP_Vendor5 0x85 +#define ID_DAP_Vendor6 0x86 +#define ID_DAP_Vendor7 0x87 +#define ID_DAP_Vendor8 0x88 +#define ID_DAP_Vendor9 0x89 +#define ID_DAP_Vendor10 0x8A +#define ID_DAP_Vendor11 0x8B +#define ID_DAP_Vendor12 0x8C +#define ID_DAP_Vendor13 0x8D +#define ID_DAP_Vendor14 0x8E +#define ID_DAP_Vendor15 0x8F +#define ID_DAP_Vendor16 0x90 +#define ID_DAP_Vendor17 0x91 +#define ID_DAP_Vendor18 0x92 +#define ID_DAP_Vendor19 0x93 +#define ID_DAP_Vendor20 0x94 +#define ID_DAP_Vendor21 0x95 +#define ID_DAP_Vendor22 0x96 +#define ID_DAP_Vendor23 0x97 +#define ID_DAP_Vendor24 0x98 +#define ID_DAP_Vendor25 0x99 +#define ID_DAP_Vendor26 0x9A +#define ID_DAP_Vendor27 0x9B +#define ID_DAP_Vendor28 0x9C +#define ID_DAP_Vendor29 0x9D +#define ID_DAP_Vendor30 0x9E +#define ID_DAP_Vendor31 0x9F + +#define ID_DAP_Invalid 0xFF + +// DAP Status Code +#define DAP_OK 0 +#define DAP_ERROR 0xFF + +// DAP ID +#define DAP_ID_VENDOR 1 +#define DAP_ID_PRODUCT 2 +#define DAP_ID_SER_NUM 3 +#define DAP_ID_FW_VER 4 +#define DAP_ID_DEVICE_VENDOR 5 +#define DAP_ID_DEVICE_NAME 6 +#define DAP_ID_CAPABILITIES 0xF0 +#define DAP_ID_PACKET_COUNT 0xFE +#define DAP_ID_PACKET_SIZE 0xFF + +// DAP LEDs +#define DAP_LED_DEBUGGER_CONNECTED 0 +#define DAP_LED_TARGET_RUNNING 1 + +// DAP Port +#define DAP_PORT_AUTODETECT 0 // Autodetect Port +#define DAP_PORT_DISABLED 0 // Port Disabled (I/O pins in High-Z) +#define DAP_PORT_SWD 1 // SWD Port (SWCLK, SWDIO) + nRESET +#define DAP_PORT_JTAG 2 // JTAG Port (TCK, TMS, TDI, TDO, nTRST) + nRESET + +// DAP SWJ Pins +#define DAP_SWJ_SWCLK_TCK 0 // SWCLK/TCK +#define DAP_SWJ_SWDIO_TMS 1 // SWDIO/TMS +#define DAP_SWJ_TDI 2 // TDI +#define DAP_SWJ_TDO 3 // TDO +#define DAP_SWJ_nTRST 5 // nTRST +#define DAP_SWJ_nRESET 7 // nRESET + +// DAP Transfer Request +#define DAP_TRANSFER_APnDP (1<<0) +#define DAP_TRANSFER_RnW (1<<1) +#define DAP_TRANSFER_A2 (1<<2) +#define DAP_TRANSFER_A3 (1<<3) +#define DAP_TRANSFER_MATCH_VALUE (1<<4) +#define DAP_TRANSFER_MATCH_MASK (1<<5) + +// DAP Transfer Response +#define DAP_TRANSFER_OK (1<<0) +#define DAP_TRANSFER_WAIT (1<<1) +#define DAP_TRANSFER_FAULT (1<<2) +#define DAP_TRANSFER_ERROR (1<<3) +#define DAP_TRANSFER_MISMATCH (1<<4) + + +// Debug Port Register Addresses +#define DP_IDCODE 0x00 // IDCODE Register (SW Read only) +#define DP_ABORT 0x00 // Abort Register (SW Write only) +#define DP_CTRL_STAT 0x04 // Control & Status +#define DP_WCR 0x04 // Wire Control Register (SW Only) +#define DP_SELECT 0x08 // Select Register (JTAG R/W & SW W) +#define DP_RESEND 0x08 // Resend (SW Read Only) +#define DP_RDBUFF 0x0C // Read Buffer (Read Only) + +// JTAG IR Codes +#define JTAG_ABORT 0x08 +#define JTAG_DPACC 0x0A +#define JTAG_APACC 0x0B +#define JTAG_IDCODE 0x0E +#define JTAG_BYPASS 0x0F + +// JTAG Sequence Info +#define JTAG_SEQUENCE_TCK 0x3F // TCK count +#define JTAG_SEQUENCE_TMS 0x40 // TMS value +#define JTAG_SEQUENCE_TDO 0x80 // TDO capture + + +#include +#include + +// DAP Data structure +typedef struct { + uint8_t debug_port; // Debug Port + uint8_t fast_clock; // Fast Clock Flag + uint32_t clock_delay; // Clock Delay + struct { // Transfer Configuration + uint8_t idle_cycles; // Idle cycles after transfer + uint16_t retry_count; // Number of retries after WAIT response + uint16_t match_retry; // Number of retries if read value does not match + uint32_t match_mask; // Match Mask + } transfer; +#if (DAP_SWD != 0) + struct { // SWD Configuration + uint8_t turnaround; // Turnaround period + uint8_t data_phase; // Always generate Data Phase + } swd_conf; +#endif +#if (DAP_JTAG != 0) + struct { // JTAG Device Chain + uint8_t count; // Number of devices + uint8_t index; // Device index (device at TDO has index 0) +#if (DAP_JTAG_DEV_CNT != 0) + uint8_t ir_length[DAP_JTAG_DEV_CNT]; // IR Length in bits + uint16_t ir_before[DAP_JTAG_DEV_CNT]; // Bits before IR + uint16_t ir_after [DAP_JTAG_DEV_CNT]; // Bits after IR +#endif + } jtag_dev; +#endif +} DAP_Data_t; + +extern DAP_Data_t DAP_Data; // DAP Data +extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag + + +// Functions +extern void SWJ_Sequence (uint32_t count, uint8_t *data); +extern void JTAG_Sequence (uint32_t info, uint8_t *tdi, uint8_t *tdo); +extern void JTAG_IR (uint32_t ir); +extern uint32_t JTAG_ReadIDCode (void); +extern void JTAG_WriteAbort (uint32_t data); +extern uint8_t JTAG_Transfer (uint32_t request, uint32_t *data); +extern uint8_t SWD_Transfer (uint32_t request, uint32_t *data); + +extern void Delayms (uint32_t delay); + +extern uint32_t DAP_ProcessVendorCommand (uint8_t *request, uint8_t *response); + +extern uint32_t DAP_ProcessCommand (uint8_t *request, uint8_t *response); +extern void DAP_Setup (void); + +// Configurable delay for clock generation +#ifndef DELAY_SLOW_CYCLES +#define DELAY_SLOW_CYCLES 3 // Number of cycles for one iteration +#endif +static __forceinline void PIN_DELAY_SLOW (uint32_t delay) { + int32_t count; + + count = delay; + while (--count); +} + +// Fixed delay for fast clock generation +#ifndef DELAY_FAST_CYCLES +#define DELAY_FAST_CYCLES 0 // Number of cycles: 0..3 +#endif +static __forceinline void PIN_DELAY_FAST (void) { +#if (DELAY_FAST_CYCLES >= 1) + __nop(); +#endif +#if (DELAY_FAST_CYCLES >= 2) + __nop(); +#endif +#if (DELAY_FAST_CYCLES >= 3) + __nop(); +#endif +} + + +#endif /* __DAP_H__ */ diff --git a/inc/DAP_config.h b/inc/DAP_config.h new file mode 100644 index 0000000..8a95b33 --- /dev/null +++ b/inc/DAP_config.h @@ -0,0 +1,474 @@ +/**************************************************************************//** + * @file DAP_config.h + * @brief IBDAP DAP config for LPC11U35 + * @version V0.1 + * @date 08. May 2015 + * + * @note + * Copyright (C) 2015 Armstart. All rights reserved. + * + * @par + * + * @par + * + ******************************************************************************/ + +#ifndef __DAP_CONFIG_H__ +#define __DAP_CONFIG_H__ + + +//************************************************************************************************** +/** +\defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information +\ingroup DAP_ConfigIO_gr +@{ +Provides definitions about: + - Definition of Cortex-M processor parameters used in CMSIS-DAP Debug Unit. + - Debug Unit communication packet size. + - Debug Access Port communication mode (JTAG or SWD). + - Optional information about a connected Target Device (for Evaluation Boards). +*/ + +#ifdef __USE_CMSIS +#include "LPC11Uxx.h" +#endif + +#include "compiler.h" + +/// Processor Clock of the Cortex-M MCU used in the Debug Unit. +/// This value is used to calculate the SWD/JTAG clock speed. +#define CPU_CLOCK 48000000 ///< Specifies the CPU Clock in Hz + +/// Number of processor cycles for I/O Port write operations. +/// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O +/// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors +/// requrie 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses +/// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be +/// requrired. +#define IO_PORT_WRITE_CYCLES 2 ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0 + +/// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port. +/// This information is returned by the command \ref DAP_Info as part of Capabilities. +#define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available + +/// Indicate that JTAG communication mode is available at the Debug Port. +/// This information is returned by the command \ref DAP_Info as part of Capabilities. +#define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available. + +/// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. +/// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. +#define DAP_JTAG_DEV_CNT 8 ///< Maximum number of JTAG devices on scan chain + +/// Default communication mode on the Debug Access Port. +/// Used for the command \ref DAP_Connect when Port Default mode is selected. +#define DAP_DEFAULT_PORT 1 ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG. + +/// Default communication speed on the Debug Access Port for SWD and JTAG mode. +/// Used to initialize the default SWD/JTAG clock frequency. +/// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. +#define DAP_DEFAULT_SWJ_CLOCK 5000000 ///< Default SWD/JTAG clock frequency in Hz. + +/// Maximum Package Size for Command and Response data. +/// This configuration settings is used to optimized the communication performance with the +/// debugger and depends on the USB peripheral. Change setting to 1024 for High-Speed USB. +#define DAP_PACKET_SIZE 64 ///< USB: 64 = Full-Speed, 1024 = High-Speed. + +/// Maximum Package Buffers for Command and Response data. +/// This configuration settings is used to optimized the communication performance with the +/// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the +/// setting can be reduced (valid range is 1 .. 255). Change setting to 4 for High-Speed USB. +#define DAP_PACKET_COUNT 8 ///< Buffers: 64 = Full-Speed, 4 = High-Speed. + + +/// Debug Unit is connected to fixed Target Device. +/// The Debug Unit may be part of an evaluation board and always connected to a fixed +/// known device. In this case a Device Vendor and Device Name string is stored which +/// may be used by the debugger or IDE to configure device parameters. +#define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown; + +#if TARGET_DEVICE_FIXED +#define TARGET_DEVICE_VENDOR "ARMSTART" ///< String indicating the Silicon Vendor +#define TARGET_DEVICE_NAME "IBDAP-LPC11U35 CMSIS-DAP" ///< String indicating the Target Device +#endif + +///@} + + +// Peripheral register bit masks (used for pin inits) +#define FUNC_0 0 +#define FUNC_1 1 +#define PULL_DOWN_ENABLED (1 << 3) +#define PULL_UP_ENABLED (2 << 3) +#define OPENDRAIN (1 << 10) + +// Debug Port I/O Pins +// For LPC11Uxx DAPs all SWD and JTAG pins are on GPIO port 0 +// Default is mbed HDK reference design with LPC11U35/501 +// SWCLK/TCK Pin PIO0_7 +#define PIN_SWCLK_IN_BIT 7 +#define PIN_SWCLK (1 << PIN_SWCLK_IN_BIT) +#define PIN_SWCLK_TCK_IOCON LPC_IOCON->PIO0_7 + +// SWDIO/TMS In/Out Pin PIO0_8 +#define PIN_SWDIO_IN_BIT 8 +#define PIN_SWDIO (1 << PIN_SWDIO_IN_BIT) +#define PIN_SWDIO_TMS_IOCON LPC_IOCON->PIO0_8 + +// nRESET Pin PIO0_2 +#define PIN_nRESET_IN_BIT 2 +#define PIN_nRESET (1 << PIN_nRESET_IN_BIT) +#define PIN_nRESET_IOCON LPC_IOCON->PIO0_2 + +#if (DAP_JTAG != 0) + +// TDI Pin PIO0_17 +#define PIN_TDI_IN_BIT 17 +#define PIN_TDI (1 << PIN_TDI_IN_BIT) +#define PIN_TDI_IOCON LPC_IOCON->PIO0_17 + +// SWO/TDO Pin PIO0_9 +#define PIN_TDO_IN_BIT 9 +#define PIN_TDO (1 << PIN_TDO_IN_BIT) +#define PIN_TDO_IOCON LPC_IOCON->PIO0_9 +#endif // (DAP_JTAG != 0) + +//************************************************************************************************** +/** +\defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access +\ingroup DAP_ConfigIO_gr +@{ + +Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode +and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug +interface of a device. The following I/O Pins are provided: + +JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode +---------------------------- | -------------------- | --------------------------------------------- +TCK: Test Clock | SWCLK: Clock | Output Push/Pull +TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) +TDI: Test Data Input | | Output Push/Pull +TDO: Test Data Output | | Input +nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor +nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor + + +DAP Hardware I/O Pin Access Functions +------------------------------------- +The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to +these I/O Pins. + +For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. +This functions are provided to achieve faster I/O that is possible with some advanced GPIO +peripherals that can independently write/read a single I/O pin without affecting any other pins +of the same I/O port. The following SWDIO I/O Pin functions are provided: + - \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware. + - \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware. + - \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed. + - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed. +*/ + + +// Configure DAP I/O pins ------------------------------ + +/** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. +Configures the DAP Hardware I/O pins for JTAG mode: + - TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level. + - TDO to input mode. +*/ +static __inline void PORT_JTAG_SETUP (void) { +#if (DAP_JTAG != 0) + LPC_GPIO->SET[0] = PIN_TDI; + LPC_GPIO->DIR[0] |= PIN_TDI; + LPC_GPIO->DIR[0] &= ~PIN_TDO; +#endif +} + +/** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. +Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: + - SWCLK, SWDIO, nRESET to output mode and set to default high level. + - TDI, TMS, nTRST to HighZ mode (pins are unused in SWD mode). +*/ +static __inline void PORT_SWD_SETUP (void) { + LPC_GPIO->SET[0] = PIN_SWCLK; + LPC_GPIO->SET[0] = PIN_SWDIO; +#if defined(CONF_OPENDRAIN) + // open drain logic + LPC_GPIO->DIR[0] &= ~PIN_nRESET; + LPC_GPIO->CLR[0] = PIN_nRESET; + LPC_GPIO->DIR[0] |= (PIN_SWCLK | PIN_SWDIO); +#else + LPC_GPIO->SET[0] = PIN_nRESET; + LPC_GPIO->DIR[0] |= (PIN_SWCLK | PIN_SWDIO | PIN_nRESET); +#endif +} + +/** Disable JTAG/SWD I/O Pins. +Disables the DAP Hardware I/O pins which configures: + - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. +*/ +static __inline void PORT_OFF (void) { + LPC_GPIO->CLR[0] = PIN_SWCLK; + LPC_GPIO->CLR[0] = PIN_SWDIO; +#if defined(CONF_OPENDRAIN) + // open drain logic + LPC_GPIO->DIR[0] &= ~PIN_nRESET; // reset not an output + LPC_GPIO->CLR[0] = PIN_nRESET; + LPC_GPIO->DIR[0] |= (PIN_SWCLK | PIN_SWDIO); +#else + LPC_GPIO->SET[0] = PIN_nRESET; + LPC_GPIO->DIR[0] |= (PIN_SWCLK | PIN_SWDIO | PIN_nRESET); +#endif +} + + +// SWCLK/TCK I/O pin ------------------------------------- + +/** SWCLK/TCK I/O pin: Get Input. +\return Current status of the SWCLK/TCK DAP hardware I/O pin. +*/ +static __forceinline uint32_t PIN_SWCLK_TCK_IN (void) { + return LPC_GPIO->B[PIN_SWCLK_IN_BIT] & 0x1; +} + +/** SWCLK/TCK I/O pin: Set Output to High. +Set the SWCLK/TCK DAP hardware I/O pin to high level. +*/ +static __forceinline void PIN_SWCLK_TCK_SET (void) { + LPC_GPIO->SET[0] = (PIN_SWCLK); +} + +/** SWCLK/TCK I/O pin: Set Output to Low. +Set the SWCLK/TCK DAP hardware I/O pin to low level. +*/ +static __forceinline void PIN_SWCLK_TCK_CLR (void) { + LPC_GPIO->CLR[0] = (PIN_SWCLK); +} + + +// SWDIO/TMS Pin I/O -------------------------------------- + +/** SWDIO/TMS I/O pin: Get Input. +\return Current status of the SWDIO/TMS DAP hardware I/O pin. +*/ +static __forceinline uint32_t PIN_SWDIO_TMS_IN (void) { + return LPC_GPIO->B[PIN_SWDIO_IN_BIT] & 0x1; +} + +/** SWDIO/TMS I/O pin: Set Output to High. +Set the SWDIO/TMS DAP hardware I/O pin to high level. +*/ +static __forceinline void PIN_SWDIO_TMS_SET (void) { + LPC_GPIO->SET[0] = (PIN_SWDIO); +} + +/** SWDIO/TMS I/O pin: Set Output to Low. +Set the SWDIO/TMS DAP hardware I/O pin to low level. +*/ +static __forceinline void PIN_SWDIO_TMS_CLR (void) { + LPC_GPIO->CLR[0] = (PIN_SWDIO); +} + +/** SWDIO I/O pin: Get Input (used in SWD mode only). +\return Current status of the SWDIO DAP hardware I/O pin. +*/ +static __forceinline uint32_t PIN_SWDIO_IN (void) { + return LPC_GPIO->B[PIN_SWDIO_IN_BIT] & 0x1; +} + +/** SWDIO I/O pin: Set Output (used in SWD mode only). +\param bit Output value for the SWDIO DAP hardware I/O pin. +*/ +static __forceinline void PIN_SWDIO_OUT (uint32_t bit){ + if (bit & 0x1) + LPC_GPIO->SET[0] = (PIN_SWDIO); + else + LPC_GPIO->CLR[0] = (PIN_SWDIO); +} + +/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only). +Configure the SWDIO DAP hardware I/O pin to output mode. This function is +called prior \ref PIN_SWDIO_OUT function calls. +*/ +static __forceinline void PIN_SWDIO_OUT_ENABLE (void) { + LPC_GPIO->DIR[0] |= (PIN_SWDIO); +} + +/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only). +Configure the SWDIO DAP hardware I/O pin to input mode. This function is +called prior \ref PIN_SWDIO_IN function calls. +*/ +static __forceinline void PIN_SWDIO_OUT_DISABLE (void) { + LPC_GPIO->DIR[0] &= ~(PIN_SWDIO); +} + + +// TDI Pin I/O --------------------------------------------- + +/** TDI I/O pin: Get Input. +\return Current status of the TDI DAP hardware I/O pin. +*/ +static __forceinline uint32_t PIN_TDI_IN (void) { +#if (DAP_JTAG != 0) + return LPC_GPIO->B[PIN_TDI_IN_BIT] & 0x1; +#else + return (0); // Not available +#endif +} + +/** TDI I/O pin: Set Output. +\param bit Output value for the TDI DAP hardware I/O pin. +*/ +static __forceinline void PIN_TDI_OUT (uint32_t bit) { +#if (DAP_JTAG != 0) + if (bit & 0x1) + LPC_GPIO->SET[0] = (PIN_TDI); + else + LPC_GPIO->CLR[0] = (PIN_TDI); +#else + ; // Not available +#endif +} + + +// TDO Pin I/O --------------------------------------------- + +/** TDO I/O pin: Get Input. +\return Current status of the TDO DAP hardware I/O pin. +*/ +static __forceinline uint32_t PIN_TDO_IN (void) { +#if (DAP_JTAG != 0) + return LPC_GPIO->B[PIN_TDO_IN_BIT] & 0x1; +#else + return (0); // Not available +#endif +} + + +// nTRST Pin I/O ------------------------------------------- + +/** nTRST I/O pin: Get Input. +\return Current status of the nTRST DAP hardware I/O pin. +*/ +static __forceinline uint32_t PIN_nTRST_IN (void) { + return (0); // Not available +} + +/** nTRST I/O pin: Set Output. +\param bit JTAG TRST Test Reset pin status: + - 0: issue a JTAG TRST Test Reset. + - 1: release JTAG TRST Test Reset. +*/ +static __forceinline void PIN_nTRST_OUT (uint32_t bit) { + ; // Not available +} + +// nRESET Pin I/O------------------------------------------ + +/** nRESET I/O pin: Get Input. +\return Current status of the nRESET DAP hardware I/O pin. +*/ +static __forceinline uint32_t PIN_nRESET_IN (void) { + return LPC_GPIO->B[PIN_nRESET_IN_BIT] & 0x1; +} + +/** nRESET I/O pin: Set Output. +\param bit target device hardware reset pin status: + - 0: issue a device hardware reset. + - 1: release device hardware reset. +*/ +static __forceinline void PIN_nRESET_OUT (uint32_t bit) { +#if defined(CONF_OPENDRAIN) + // open drain logic + if (bit) LPC_GPIO->DIR[0] &= ~PIN_nRESET; // input (pulled high external) + else LPC_GPIO->DIR[0] |= PIN_nRESET; // output (low) +#else + if (bit) + LPC_GPIO->SET[0] = (PIN_nRESET); + else + LPC_GPIO->CLR[0] = (PIN_nRESET); +#endif +} + +///@} + + +//************************************************************************************************** +/** +\defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs +\ingroup DAP_ConfigIO_gr +@{ + +CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit. + +It is recommended to provide the following LEDs for status indication: + - Connect LED: is active when the DAP hardware is connected to a debugger. + - Running LED: is active when the debugger has put the target device into running state. +*/ + +/** Debug Unit: Set status of Connected LED. +\param bit status of the Connect LED. + - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. + - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. +*/ +static __inline void LED_CONNECTED_OUT (uint32_t bit) { +} + +/** Debug Unit: Set status Target Running LED. +\param bit status of the Target Running LED. + - 1: Target Running LED ON: program execution in target started. + - 0: Target Running LED OFF: program execution in target stopped. +*/ +static __inline void LED_RUNNING_OUT (uint32_t bit) { + ; // Not available +} + +///@} + + +//************************************************************************************************** +/** +\defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization +\ingroup DAP_ConfigIO_gr +@{ + +CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP. +*/ + +/** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized). +This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the +Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set: + - I/O clock system enabled. + - all I/O pins: input buffer enabled, output pins are set to HighZ mode. + - for nTRST, nRESET a weak pull-up (if available) is enabled. + - LED output pins are enabled and LEDs are turned off. +*/ +static __inline void DAP_SETUP (void) { + // Configure I/O pins + PIN_SWCLK_TCK_IOCON = FUNC_0 | PULL_UP_ENABLED; // SWCLK/TCK + PIN_SWDIO_TMS_IOCON = FUNC_0 | PULL_UP_ENABLED; // SWDIO/TMS +#if !defined(CONF_OPENDRAIN) + PIN_nRESET_IOCON = FUNC_0 | PULL_UP_ENABLED; // nRESET +#else + PIN_nRESET_IOCON = FUNC_0 | OPENDRAIN; // nRESET +#endif +#if (DAP_JTAG != 0) + PIN_TDI_IOCON = FUNC_0 | PULL_UP_ENABLED; // TDI + PIN_TDO_IOCON = FUNC_0 | PULL_UP_ENABLED; // TDO +#endif +} + +/** Reset Target Device with custom specific I/O pin or command sequence. +This function allows the optional implementation of a device specific reset sequence. +It is called when the command \ref DAP_ResetTarget and is for example required +when a device needs a time-critical unlock sequence that enables the debug port. +\return 0 = no device specific reset sequence is implemented.\n + 1 = a device specific reset sequence is implemented. +*/ +static __inline uint32_t RESET_TARGET (void) { + return (0); // change to '1' when a device reset sequence is implemented +} + +///@} + + +#endif /* __DAP_CONFIG_H__ */ diff --git a/inc/LPC11Uxx.h b/inc/LPC11Uxx.h new file mode 100644 index 0000000..a558b39 --- /dev/null +++ b/inc/LPC11Uxx.h @@ -0,0 +1,741 @@ + +/****************************************************************************************************//** + * @file LPC11Uxx.h + * + * + * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File for + * default LPC11Uxx Device Series + * + * @version V0.1 + * @date 21. March 2011 + * + * @note Generated with SFDGen V2.6 Build 3j (beta) on Thursday, 17.03.2011 13:19:45 + * + * from CMSIS SVD File 'LPC11U1x_svd.xml' Version 0.1, + * created on Wednesday, 16.03.2011 20:30:42, last modified on Thursday, 17.03.2011 20:19:40 + * + *******************************************************************************************************/ + +// ################################################################################ +// Minor fix 8 April 2011 - changed LPC_CT32B1_BASE from 0x40014000 to 0x40018000 +// ################################################################################ + +/** @addtogroup NXP + * @{ + */ + +/** @addtogroup LPC11Uxx + * @{ + */ + +#ifndef __LPC11UXX_H__ +#define __LPC11UXX_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined ( __CC_ARM ) + #pragma anon_unions +#endif + + /* Interrupt Number Definition */ + +typedef enum { +// ------------------------- Cortex-M0 Processor Exceptions Numbers ----------------------------- + Reset_IRQn = -15, /*!< 1 Reset Vector, invoked on Power up and warm reset */ + NonMaskableInt_IRQn = -14, /*!< 2 Non maskable Interrupt, cannot be stopped or preempted */ + HardFault_IRQn = -13, /*!< 3 Hard Fault, all classes of Fault */ + SVCall_IRQn = -5, /*!< 11 System Service Call via SVC instruction */ + DebugMonitor_IRQn = -4, /*!< 12 Debug Monitor */ + PendSV_IRQn = -2, /*!< 14 Pendable request for system service */ + SysTick_IRQn = -1, /*!< 15 System Tick Timer */ +// --------------------------- LPC11Uxx Specific Interrupt Numbers ------------------------------ +FLEX_INT0_IRQn = 0, /*!< All I/O pins can be routed to below 8 interrupts. */ + FLEX_INT1_IRQn = 1, + FLEX_INT2_IRQn = 2, + FLEX_INT3_IRQn = 3, + FLEX_INT4_IRQn = 4, + FLEX_INT5_IRQn = 5, + FLEX_INT6_IRQn = 6, + FLEX_INT7_IRQn = 7, + GINT0_IRQn = 8, /*!< Grouped Interrupt 0 */ + GINT1_IRQn = 9, /*!< Grouped Interrupt 1 */ + Reserved0_IRQn = 10, /*!< Reserved Interrupt */ + Reserved1_IRQn = 11, + Reserved2_IRQn = 12, + Reserved3_IRQn = 13, + SSP1_IRQn = 14, /*!< SSP1 Interrupt */ + I2C_IRQn = 15, /*!< I2C Interrupt */ + TIMER_16_0_IRQn = 16, /*!< 16-bit Timer0 Interrupt */ + TIMER_16_1_IRQn = 17, /*!< 16-bit Timer1 Interrupt */ + TIMER_32_0_IRQn = 18, /*!< 32-bit Timer0 Interrupt */ + TIMER_32_1_IRQn = 19, /*!< 32-bit Timer1 Interrupt */ + SSP0_IRQn = 20, /*!< SSP0 Interrupt */ + UART_IRQn = 21, /*!< UART Interrupt */ + USB_IRQn = 22, /*!< USB IRQ Interrupt */ + USB_FIQn = 23, /*!< USB FIQ Interrupt */ + ADC_IRQn = 24, /*!< A/D Converter Interrupt */ + WDT_IRQn = 25, /*!< Watchdog timer Interrupt */ + BOD_IRQn = 26, /*!< Brown Out Detect(BOD) Interrupt */ + FMC_IRQn = 27, /*!< Flash Memory Controller Interrupt */ + Reserved4_IRQn = 28, /*!< Reserved Interrupt */ + Reserved5_IRQn = 29, /*!< Reserved Interrupt */ + USBWakeup_IRQn = 30, /*!< USB wakeup Interrupt */ + Reserved6_IRQn = 31, /*!< Reserved Interrupt */ +} IRQn_Type; + + +/** @addtogroup Configuration_of_CMSIS + * @{ + */ + +/* Processor and Core Peripheral Section */ /* Configuration of the Cortex-M0 Processor and Core Peripherals */ + +#define __MPU_PRESENT 0 /*!< MPU present or not */ +#define __NVIC_PRIO_BITS 3 /*!< Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +/** @} */ /* End of group Configuration_of_CMSIS */ + +#include "core_cm0.h" /*!< Cortex-M0 processor and core peripherals */ +#include "system_LPC11Uxx.h" /*!< LPC11Uxx System */ + +/** @addtogroup Device_Peripheral_Registers + * @{ + */ + + +// ------------------------------------------------------------------------------------------------ +// ----- I2C ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x I2C-bus controller Modification date=3/16/2011 Major revision=0 Minor revision=3 (I2C) + */ + +typedef struct { /*!< (@ 0x40000000) I2C Structure */ + __IO uint32_t CONSET; /*!< (@ 0x40000000) I2C Control Set Register */ + __I uint32_t STAT; /*!< (@ 0x40000004) I2C Status Register */ + __IO uint32_t DAT; /*!< (@ 0x40000008) I2C Data Register. */ + __IO uint32_t ADR0; /*!< (@ 0x4000000C) I2C Slave Address Register 0 */ + __IO uint32_t SCLH; /*!< (@ 0x40000010) SCH Duty Cycle Register High Half Word */ + __IO uint32_t SCLL; /*!< (@ 0x40000014) SCL Duty Cycle Register Low Half Word */ + __IO uint32_t CONCLR; /*!< (@ 0x40000018) I2C Control Clear Register*/ + __IO uint32_t MMCTRL; /*!< (@ 0x4000001C) Monitor mode control register*/ + __IO uint32_t ADR1; /*!< (@ 0x40000020) I2C Slave Address Register 1*/ + __IO uint32_t ADR2; /*!< (@ 0x40000024) I2C Slave Address Register 2*/ + __IO uint32_t ADR3; /*!< (@ 0x40000028) I2C Slave Address Register 3*/ + __I uint32_t DATA_BUFFER; /*!< (@ 0x4000002C) Data buffer register */ +union{ + __IO uint32_t MASK[4]; /*!< (@ 0x40000030) I2C Slave address mask register */ + struct{ + __IO uint32_t MASK0; + __IO uint32_t MASK1; + __IO uint32_t MASK2; + __IO uint32_t MASK3; + }; + }; +} LPC_I2C_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- WWDT ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x Windowed Watchdog Timer (WWDT) Modification date=3/16/2011 Major revision=0 Minor revision=3 (WWDT) + */ + +typedef struct { /*!< (@ 0x40004000) WWDT Structure */ + __IO uint32_t MOD; /*!< (@ 0x40004000) Watchdog mode register*/ + __IO uint32_t TC; /*!< (@ 0x40004004) Watchdog timer constant register */ + __IO uint32_t FEED; /*!< (@ 0x40004008) Watchdog feed sequence register */ + __I uint32_t TV; /*!< (@ 0x4000400C) Watchdog timer value register */ + __IO uint32_t CLKSEL; /*!< (@ 0x40004010) Watchdog clock select register. */ + __IO uint32_t WARNINT; /*!< (@ 0x40004014) Watchdog Warning Interrupt compare value. */ + __IO uint32_t WINDOW; /*!< (@ 0x40004018) Watchdog Window compare value. */ +} LPC_WWDT_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- USART ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x USART Modification date=3/16/2011 Major revision=0 Minor revision=3 (USART) + */ + +typedef struct { /*!< (@ 0x40008000) USART Structure */ + + union { + __IO uint32_t DLL; /*!< (@ 0x40008000) Divisor Latch LSB. Least significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider. (DLAB=1) */ + __O uint32_t THR; /*!< (@ 0x40008000) Transmit Holding Register. The next character to be transmitted is written here. (DLAB=0) */ + __I uint32_t RBR; /*!< (@ 0x40008000) Receiver Buffer Register. Contains the next received character to be read. (DLAB=0) */ + }; + + union { + __IO uint32_t IER; /*!< (@ 0x40008004) Interrupt Enable Register. Contains individual interrupt enable bits for the 7 potential USART interrupts. (DLAB=0) */ + __IO uint32_t DLM; /*!< (@ 0x40008004) Divisor Latch MSB. Most significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider. (DLAB=1) */ + }; + + union { + __O uint32_t FCR; /*!< (@ 0x40008008) FIFO Control Register. Controls USART FIFO usage and modes. */ + __I uint32_t IIR; /*!< (@ 0x40008008) Interrupt ID Register. Identifies which interrupt(s) are pending. */ + }; + __IO uint32_t LCR; /*!< (@ 0x4000800C) Line Control Register. Contains controls for frame formatting and break generation. */ + __IO uint32_t MCR; /*!< (@ 0x40008010) Modem Control Register. */ + __I uint32_t LSR; /*!< (@ 0x40008014) Line Status Register. Contains flags for transmit and receive status, including line errors. */ + __I uint32_t MSR; /*!< (@ 0x40008018) Modem Status Register. */ + __IO uint32_t SCR; /*!< (@ 0x4000801C) Scratch Pad Register. Eight-bit temporary storage for software. */ + __IO uint32_t ACR; /*!< (@ 0x40008020) Auto-baud Control Register. Contains controls for the auto-baud feature. */ + __IO uint32_t ICR; /*!< (@ 0x40008024) IrDA Control Register. Enables and configures the IrDA (remote control) mode. */ + __IO uint32_t FDR; /*!< (@ 0x40008028) Fractional Divider Register. Generates a clock input for the baud rate divider. */ + __IO uint32_t OSR; /*!< (@ 0x4000802C) Oversampling Register. Controls the degree of oversampling during each bit time. */ + __IO uint32_t TER; /*!< (@ 0x40008030) Transmit Enable Register. Turns off USART transmitter for use with software flow control. */ + __I uint32_t RESERVED0[3]; + __IO uint32_t HDEN; /*!< (@ 0x40008040) Half duplex enable register. */ + __I uint32_t RESERVED1; + __IO uint32_t SCICTRL; /*!< (@ 0x40008048) Smart Card Interface Control register. Enables and configures the Smart Card Interface feature. */ + __IO uint32_t RS485CTRL; /*!< (@ 0x4000804C) RS-485/EIA-485 Control. Contains controls to configure various aspects of RS-485/EIA-485 modes. */ + __IO uint32_t RS485ADRMATCH; /*!< (@ 0x40008050) RS-485/EIA-485 address match. Contains the address match value for RS-485/EIA-485 mode. */ + __IO uint32_t RS485DLY; /*!< (@ 0x40008054) RS-485/EIA-485 direction control delay. */ + __IO uint32_t SYNCCTRL; +} LPC_USART_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- Timer ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x 32-bitcounter/timers CT32B0/1 Modification date=3/16/2011 Major revision=0 Minor revision=3 + */ + +typedef struct { /*!< (@ 0x40014000) CT32B0 Structure */ + __IO uint32_t IR; /*!< (@ 0x40014000) Interrupt Register */ + __IO uint32_t TCR; /*!< (@ 0x40014004) Timer Control Register */ + __IO uint32_t TC; /*!< (@ 0x40014008) Timer Counter */ + __IO uint32_t PR; /*!< (@ 0x4001400C) Prescale Register */ + __IO uint32_t PC; /*!< (@ 0x40014010) Prescale Counter */ + __IO uint32_t MCR; /*!< (@ 0x40014014) Match Control Register */ + union { + __IO uint32_t MR[4]; /*!< (@ 0x40014018) Match Register */ + struct{ + __IO uint32_t MR0; /*!< (@ 0x40018018) Match Register. MR0 */ + __IO uint32_t MR1; /*!< (@ 0x4001801C) Match Register. MR1 */ + __IO uint32_t MR2; /*!< (@ 0x40018020) Match Register. MR2 */ + __IO uint32_t MR3; /*!< (@ 0x40018024) Match Register. MR3 */ + }; + }; + __IO uint32_t CCR; /*!< (@ 0x40014028) Capture Control Register */ + union{ + __I uint32_t CR[4]; /*!< (@ 0x4001402C) Capture Register */ + struct{ + __I uint32_t CR0; /*!< (@ 0x4001802C) Capture Register. CR 0 */ + __I uint32_t CR1; /*!< (@ 0x40018030) Capture Register. CR 1 */ + __I uint32_t CR2; /*!< (@ 0x40018034) Capture Register. CR 2 */ + __I uint32_t CR3; /*!< (@ 0x40018038) Capture Register. CR 3 */ + }; + }; +__IO uint32_t EMR; /*!< (@ 0x4001403C) External Match Register */ + __I uint32_t RESERVED0[12]; + __IO uint32_t CTCR; /*!< (@ 0x40014070) Count Control Register */ + __IO uint32_t PWMC; /*!< (@ 0x40014074) PWM Control Register */ +} LPC_CTxxBx_Type; + + + +// ------------------------------------------------------------------------------------------------ +// ----- ADC ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x ADC Modification date=3/16/2011 Major revision=0 Minor revision=3 (ADC) + */ + +typedef struct { /*!< (@ 0x4001C000) ADC Structure */ + __IO uint32_t CR; /*!< (@ 0x4001C000) A/D Control Register */ + __IO uint32_t GDR; /*!< (@ 0x4001C004) A/D Global Data Register */ + __I uint32_t RESERVED0[1]; + __IO uint32_t INTEN; /*!< (@ 0x4001C00C) A/D Interrupt Enable Register */ + union{ + __I uint32_t DR[8]; /*!< (@ 0x4001C010) A/D Channel Data Register*/ + struct{ + __IO uint32_t DR0; /*!< (@ 0x40020010) A/D Channel Data Register 0*/ + __IO uint32_t DR1; /*!< (@ 0x40020014) A/D Channel Data Register 1*/ + __IO uint32_t DR2; /*!< (@ 0x40020018) A/D Channel Data Register 2*/ + __IO uint32_t DR3; /*!< (@ 0x4002001C) A/D Channel Data Register 3*/ + __IO uint32_t DR4; /*!< (@ 0x40020020) A/D Channel Data Register 4*/ + __IO uint32_t DR5; /*!< (@ 0x40020024) A/D Channel Data Register 5*/ + __IO uint32_t DR6; /*!< (@ 0x40020028) A/D Channel Data Register 6*/ + __IO uint32_t DR7; /*!< (@ 0x4002002C) A/D Channel Data Register 7*/ + }; + }; + __I uint32_t STAT; /*!< (@ 0x4001C030) A/D Status Register. */ +} LPC_ADC_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- PMU ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x Power Management Unit (PMU) Modification date=3/16/2011 Major revision=0 Minor revision=3 (PMU) + */ + +typedef struct { /*!< (@ 0x40038000) PMU Structure */ + __IO uint32_t PCON; /*!< (@ 0x40038000) Power control register */ + union{ + __IO uint32_t GPREG[4]; /*!< (@ 0x40038004) General purpose register 0 */ + struct{ + __IO uint32_t GPREG0; /*!< (@ 0x40038004) General purpose register 0 */ + __IO uint32_t GPREG1; /*!< (@ 0x40038008) General purpose register 1 */ + __IO uint32_t GPREG2; /*!< (@ 0x4003800C) General purpose register 2 */ + __IO uint32_t GPREG3; /*!< (@ 0x40038010) General purpose register 3 */ + }; + }; +} LPC_PMU_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- FLASHCTRL ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x Flash programming firmware Modification date=3/17/2011 Major revision=0 Minor revision=3 (FLASHCTRL) + */ + +typedef struct { /*!< (@ 0x4003C000) FLASHCTRL Structure */ + __I uint32_t RESERVED0[4]; + __IO uint32_t FLASHCFG; /*!< (@ 0x4003C010) Flash memory access time configuration register */ + __I uint32_t RESERVED1[3]; + __IO uint32_t FMSSTART; /*!< (@ 0x4003C020) Signature start address register */ + __IO uint32_t FMSSTOP; /*!< (@ 0x4003C024) Signature stop-address register */ + __I uint32_t RESERVED2[1]; + __I uint32_t FMSW0; /*!< (@ 0x4003C02C) Word 0 [31:0] */ + __I uint32_t FMSW1; /*!< (@ 0x4003C030) Word 1 [63:32] */ + __I uint32_t FMSW2; /*!< (@ 0x4003C034) Word 2 [95:64] */ + __I uint32_t FMSW3; /*!< (@ 0x4003C038) Word 3 [127:96] */ + __I uint32_t RESERVED3[1001]; + __I uint32_t FMSTAT; /*!< (@ 0x4003CFE0) Signature generation status register */ + __I uint32_t RESERVED4[1]; + __IO uint32_t FMSTATCLR; /*!< (@ 0x4003CFE8) Signature generation status clear register */ +} LPC_FLASHCTRL_Type; + + +#define FLASHCFG_20MHZ_CPU 0 /*!< Flash accesses use 1 CPU clocks. Use for up to 20 MHz CPU clock*/ +#define FLASHCFG_40MHZ_CPU 1 /*!< Flash accesses use 2 CPU clocks. Use for up to 40 MHz CPU clock*/ +#define FLASHCFG_50MHZ_CPU 2 /*!< Flash accesses use 3 CPU clocks. Use for up to 50 MHz CPU clock*/ + + + +// ------------------------------------------------------------------------------------------------ +// ----- SSP0/1 ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x SSP/SPI Modification date=3/16/2011 Major revision=0 Minor revision=3 (SSP0) + */ + +typedef struct { /*!< (@ 0x40040000) SSP0 Structure */ + __IO uint32_t CR0; /*!< (@ 0x40040000) Control Register 0. Selects the serial clock rate, bus type, and data size. */ + __IO uint32_t CR1; /*!< (@ 0x40040004) Control Register 1. Selects master/slave and other modes. */ + __IO uint32_t DR; /*!< (@ 0x40040008) Data Register. Writes fill the transmit FIFO, and reads empty the receive FIFO. */ + __I uint32_t SR; /*!< (@ 0x4004000C) Status Register */ + __IO uint32_t CPSR; /*!< (@ 0x40040010) Clock Prescale Register */ + __IO uint32_t IMSC; /*!< (@ 0x40040014) Interrupt Mask Set and Clear Register */ + __I uint32_t RIS; /*!< (@ 0x40040018) Raw Interrupt Status Register */ + __I uint32_t MIS; /*!< (@ 0x4004001C) Masked Interrupt Status Register */ + __IO uint32_t ICR; /*!< (@ 0x40040020) SSPICR Interrupt Clear Register */ +} LPC_SSPx_Type; + + + +// ------------------------------------------------------------------------------------------------ +// ----- IOCONFIG ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x I/O configuration Modification date=3/16/2011 Major revision=0 Minor revision=3 (IOCONFIG) + */ + +typedef struct { /*!< (@ 0x40044000) IOCONFIG Structure */ + __IO uint32_t RESET_PIO0_0; /*!< (@ 0x40044000) I/O configuration for pin RESET/PIO0_0 */ + __IO uint32_t PIO0_1; /*!< (@ 0x40044004) I/O configuration for pin PIO0_1/CLKOUT/CT32B0_MAT2/USB_FTOGGLE */ + __IO uint32_t PIO0_2; /*!< (@ 0x40044008) I/O configuration for pin PIO0_2/SSEL0/CT16B0_CAP0 */ + __IO uint32_t PIO0_3; /*!< (@ 0x4004400C) I/O configuration for pin PIO0_3/USB_VBUS */ + __IO uint32_t PIO0_4; /*!< (@ 0x40044010) I/O configuration for pin PIO0_4/SCL */ + __IO uint32_t PIO0_5; /*!< (@ 0x40044014) I/O configuration for pin PIO0_5/SDA */ + __IO uint32_t PIO0_6; /*!< (@ 0x40044018) I/O configuration for pin PIO0_6/USB_CONNECT/SCK0 */ + __IO uint32_t PIO0_7; /*!< (@ 0x4004401C) I/O configuration for pin PIO0_7/CTS */ + __IO uint32_t PIO0_8; /*!< (@ 0x40044020) I/O configuration for pin PIO0_8/MISO0/CT16B0_MAT0 */ + __IO uint32_t PIO0_9; /*!< (@ 0x40044024) I/O configuration for pin PIO0_9/MOSI0/CT16B0_MAT1 */ + __IO uint32_t SWCLK_PIO0_10; /*!< (@ 0x40044028) I/O configuration for pin SWCLK/PIO0_10/ SCK0/CT16B0_MAT2 */ + __IO uint32_t TDI_PIO0_11; /*!< (@ 0x4004402C) I/O configuration for pin TDI/PIO0_11/AD0/CT32B0_MAT3 */ + __IO uint32_t TMS_PIO0_12; /*!< (@ 0x40044030) I/O configuration for pin TMS/PIO0_12/AD1/CT32B1_CAP0 */ + __IO uint32_t TDO_PIO0_13; /*!< (@ 0x40044034) I/O configuration for pin TDO/PIO0_13/AD2/CT32B1_MAT0 */ + __IO uint32_t TRST_PIO0_14; /*!< (@ 0x40044038) I/O configuration for pin TRST/PIO0_14/AD3/CT32B1_MAT1 */ + __IO uint32_t SWDIO_PIO0_15; /*!< (@ 0x4004403C) I/O configuration for pin SWDIO/PIO0_15/AD4/CT32B1_MAT2 */ + __IO uint32_t PIO0_16; /*!< (@ 0x40044040) I/O configuration for pin PIO0_16/AD5/CT32B1_MAT3/ WAKEUP */ + __IO uint32_t PIO0_17; /*!< (@ 0x40044044) I/O configuration for pin PIO0_17/RTS/CT32B0_CAP0/SCLK */ + __IO uint32_t PIO0_18; /*!< (@ 0x40044048) I/O configuration for pin PIO0_18/RXD/CT32B0_MAT0 */ + __IO uint32_t PIO0_19; /*!< (@ 0x4004404C) I/O configuration for pin PIO0_19/TXD/CT32B0_MAT1 */ + __IO uint32_t PIO0_20; /*!< (@ 0x40044050) I/O configuration for pin PIO0_20/CT16B1_CAP0 */ + __IO uint32_t PIO0_21; /*!< (@ 0x40044054) I/O configuration for pin PIO0_21/CT16B1_MAT0/MOSI1 */ + __IO uint32_t PIO0_22; /*!< (@ 0x40044058) I/O configuration for pin PIO0_22/AD6/CT16B1_MAT1/MISO1 */ + __IO uint32_t PIO0_23; /*!< (@ 0x4004405C) I/O configuration for pin PIO0_23/AD7 */ + __IO uint32_t PIO1_0; /*!< Offset: 0x060 */ + __IO uint32_t PIO1_1; + __IO uint32_t PIO1_2; + __IO uint32_t PIO1_3; + __IO uint32_t PIO1_4; /*!< Offset: 0x070 */ + __IO uint32_t PIO1_5; /*!< (@ 0x40044074) I/O configuration for pin PIO1_5/CT32B1_CAP1 */ + __IO uint32_t PIO1_6; + __IO uint32_t PIO1_7; + __IO uint32_t PIO1_8; /*!< Offset: 0x080 */ + __IO uint32_t PIO1_9; + __IO uint32_t PIO1_10; + __IO uint32_t PIO1_11; + __IO uint32_t PIO1_12; /*!< Offset: 0x090 */ + __IO uint32_t PIO1_13; /*!< (@ 0x40044094) I/O configuration for pin PIO1_13/DTR/CT16B0_MAT0/TXD */ + __IO uint32_t PIO1_14; /*!< (@ 0x40044098) I/O configuration for pin PIO1_14/DSR/CT16B0_MAT1/RXD */ + __IO uint32_t PIO1_15; /*!< (@ 0x4004409C) I/O configuration for pin PIO1_15/DCD/ CT16B0_MAT2/SCK1 */ + __IO uint32_t PIO1_16; /*!< (@ 0x400440A0) I/O configuration for pin PIO1_16/RI/CT16B0_CAP0 */ + __IO uint32_t PIO1_17; + __IO uint32_t PIO1_18; + __IO uint32_t PIO1_19; /*!< (@ 0x400440AC) I/O configuration for pin PIO1_19/DTR/SSEL1 */ + __IO uint32_t PIO1_20; /*!< (@ 0x400440B0) I/O configuration for pin PIO1_20/DSR/SCK1 */ + __IO uint32_t PIO1_21; /*!< (@ 0x400440B4) I/O configuration for pin PIO1_21/DCD/MISO1 */ + __IO uint32_t PIO1_22; /*!< (@ 0x400440B8) I/O configuration for pin PIO1_22/RI/MOSI1 */ + __IO uint32_t PIO1_23; /*!< (@ 0x400440BC) I/O configuration for pin PIO1_23/CT16B1_MAT1/SSEL1 */ + __IO uint32_t PIO1_24; /*!< (@ 0x400440C0) I/O configuration for pin PIO1_24/ CT32B0_MAT0 */ + __IO uint32_t PIO1_25; /*!< (@ 0x400440C4) I/O configuration for pin PIO1_25/CT32B0_MAT1 */ + __IO uint32_t PIO1_26; /*!< (@ 0x400440C8) I/O configuration for pin PIO1_26/CT32B0_MAT2/ RXD */ + __IO uint32_t PIO1_27; /*!< (@ 0x400440CC) I/O configuration for pin PIO1_27/CT32B0_MAT3/ TXD */ + __IO uint32_t PIO1_28; /*!< (@ 0x400440D0) I/O configuration for pin PIO1_28/CT32B0_CAP0/ SCLK */ + __IO uint32_t PIO1_29; /*!< (@ 0x400440D4) I/O configuration for pin PIO1_29/SCK0/ CT32B0_CAP1 */ + __IO uint32_t PIO1_30; + __IO uint32_t PIO1_31; /*!< (@ 0x400440DC) I/O configuration for pin PIO1_31 */ +} LPC_IOCON_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- SYSCON ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x System control block Modification date=3/16/2011 Major revision=0 Minor revision=3 (SYSCON) + */ + +typedef struct { //*!< (@ 0x40048000) SYSCON Structure + __IO uint32_t SYSMEMREMAP; /*!< System Memory remap register */ + __IO uint32_t PRESETCTRL; /*!< Peripheral reset Control register */ + __IO uint32_t SYSPLLCTRL; /*!< System PLL control register */ + __I uint32_t SYSPLLSTAT; /*!< System PLL status register */ + __IO uint32_t USBPLLCTRL; /*!< USB PLL control register, LPC11UXX only*/ + __I uint32_t USBPLLSTAT; /*!< USB PLL status register, LPC11UXX only */ + __I uint32_t RESERVED1[2]; + __IO uint32_t SYSOSCCTRL; /*!< System Oscillator control register */ + __IO uint32_t WDTOSCCTRL; /*!< Watchdog Oscillator control register */ + __IO uint32_t IRCCTRL; /*!< IRC control register, not on LPC11UXX and LPC11EXX */ + __IO uint32_t LFOSCCTRL; /*!< LF oscillator control, LPC11AXX only */ + __IO uint32_t SYSRSTSTAT; /*!< System Reset Status register */ + __I uint32_t RESERVED2[3]; + __IO uint32_t SYSPLLCLKSEL; /*!< System PLL clock source select register */ + __IO uint32_t SYSPLLCLKUEN; /*!< System PLL clock source update enable register*/ + __IO uint32_t USBPLLCLKSEL; /*!< USB PLL clock source select register, LPC11UXX only */ + __IO uint32_t USBPLLCLKUEN; /*!< USB PLL clock source update enable register, LPC11UXX only */ + __I uint32_t RESERVED3[8]; + __IO uint32_t MAINCLKSEL; /*!< Main clock source select register */ + __IO uint32_t MAINCLKUEN; /*!< Main clock source update enable register */ + __IO uint32_t SYSAHBCLKDIV; /*!< System Clock divider register */ + __I uint32_t RESERVED4; + __IO uint32_t SYSAHBCLKCTRL; /*!< System clock control register */ + __I uint32_t RESERVED5[4]; + __IO uint32_t SSP0CLKDIV; /*!< SSP0 clock divider register */ + __IO uint32_t USARTCLKDIV; /*!< UART clock divider register */ + __IO uint32_t SSP1CLKDIV; /*!< SSP1 clock divider register, not on CHIP_LPC110X, CHIP_LPC11XXLV */ + __I uint32_t RESERVED6[8]; + __IO uint32_t USBCLKSEL; /*!< USB clock source select register, LPC11UXX only */ + __IO uint32_t USBCLKUEN; /*!< USB clock source update enable register, LPC11UXX only */ + __IO uint32_t USBCLKDIV; /*!< USB clock source divider register, LPC11UXX only */ + __I uint32_t RESERVED7; + __IO uint32_t WDTCLKSEL; /*!< WDT clock source select register, some parts only */ + __IO uint32_t WDTCLKUEN; /*!< WDT clock source update enable register, some parts only */ + __IO uint32_t WDTCLKDIV; /*!< WDT clock divider register, some parts only */ + __I uint32_t RESERVED8; + __IO uint32_t CLKOUTSEL; /*!< Clock out source select register, not on LPC1102/04 */ + __IO uint32_t CLKOUTUEN; /*!< Clock out source update enable register, not on LPC1102/04 */ + __IO uint32_t CLKOUTDIV; /*!< Clock out divider register, not on LPC1102/04 */ + __I uint32_t RESERVED9[5]; + __I uint32_t PIOPORCAP[2];/*!< POR captured PIO status registers, index 1 on LPC1102/04 */ + __I uint32_t RESERVED10[18]; + __IO uint32_t BODCTRL; /*!< Brown Out Detect register */ + __IO uint32_t SYSTCKCAL; /*!< System tick counter calibration register */ + __I uint32_t RESERVED11[6]; + __IO uint32_t IRQLATENCY; /*!< IRQ delay register, on LPC11UXX and LPC11EXX only */ + __IO uint32_t NMISRC; /*!< NMI source control register,some parts only */ + __IO uint32_t PINTSEL[8]; /*!< GPIO pin interrupt select register 0-7, not on CHIP_LPC110X, CHIP_LPC11XXLV, CHIP_LPC11CXX */ + __IO uint32_t USBCLKCTRL; /*!< USB clock control register, LPC11UXX only */ + __I uint32_t USBCLKST; /*!< USB clock status register, LPC11UXX only */ + __I uint32_t RESERVED12[24]; + __IO uint32_t STARTAPRP0; /*!< Start loigc 0 interrupt wake up enable register 0, on CHIP_LPC110X, CHIP_LPC11XXLV, CHIP_LPC11CXX */ + __IO uint32_t STARTERP0; /*!< Start loigc signal enable register 0, not on LPC11AXX */ + __IO uint32_t STARTRSRP0CLR; /*!< Start loigc reset register 0, on CHIP_LPC110X, CHIP_LPC11XXLV, CHIP_LPC11CXX */ + __IO uint32_t STARTSRP0; /*!< Start loigc status register 0, on CHIP_LPC110X, CHIP_LPC11XXLV, CHIP_LPC11CXX */ + __I uint32_t RESERVED13; + __IO uint32_t STARTERP1; /*!< Start logic 1 interrupt wake up enable register 1, on LPC11UXX and LPC11EXX only */ + __I uint32_t RESERVED14[6]; + __IO uint32_t PDSLEEPCFG; /*!< Power down states in deep sleep mode register, not on LPC11AXX */ + __IO uint32_t PDWAKECFG; /*!< Power down states in wake up from deep sleep register, not on LPC11AXX */ + __IO uint32_t PDRUNCFG; /*!< Power configuration register*/ + __I uint32_t RESERVED15[110]; + __I uint32_t DEVICEID; /*!< Device ID register */ + /* + __IO uint32_t SYSMEMREMAP; //!< (@ 0x40048000) System memory remap + __IO uint32_t PRESETCTRL; //!< (@ 0x40048004) Peripheral reset control + __IO uint32_t SYSPLLCTRL; //!< (@ 0x40048008) System PLL control + __I uint32_t SYSPLLSTAT; //!< (@ 0x4004800C) System PLL status + __IO uint32_t USBPLLCTRL; //!< (@ 0x40048010) USB PLL control + __I uint32_t USBPLLSTAT; //!< (@ 0x40048014) USB PLL status + __I uint32_t RESERVED0[2]; + __IO uint32_t SYSOSCCTRL; //!< (@ 0x40048020) System oscillator control + __IO uint32_t WDTOSCCTRL; //!< (@ 0x40048024) Watchdog oscillator control + __I uint32_t RESERVED1[2]; + __IO uint32_t SYSRSTSTAT; //!< (@ 0x40048030) System reset status register + __I uint32_t RESERVED2[3]; + __IO uint32_t SYSPLLCLKSEL; //!< (@ 0x40048040) System PLL clock source select + __IO uint32_t SYSPLLCLKUEN; //!< (@ 0x40048044) System PLL clock source update enable + __IO uint32_t USBPLLCLKSEL; //!< (@ 0x40048048) USB PLL clock source select + __IO uint32_t USBPLLCLKUEN; //!< (@ 0x4004804C) USB PLL clock source update enable + __I uint32_t RESERVED3[8]; + __IO uint32_t MAINCLKSEL; //!< (@ 0x40048070) Main clock source select + __IO uint32_t MAINCLKUEN; //!< (@ 0x40048074) Main clock source update enable + __IO uint32_t SYSAHBCLKDIV; //!< (@ 0x40048078) System clock divider + __I uint32_t RESERVED4[1]; + __IO uint32_t SYSAHBCLKCTRL; //!< (@ 0x40048080) System clock control + __I uint32_t RESERVED5[4]; + __IO uint32_t SSP0CLKDIV; //!< (@ 0x40048094) SSP0 clock divider + __IO uint32_t UARTCLKDIV; //!< (@ 0x40048098) UART clock divider + __IO uint32_t SSP1CLKDIV; //!< (@ 0x4004809C) SSP1 clock divider + __I uint32_t RESERVED6[8]; + __IO uint32_t USBCLKSEL; //!< (@ 0x400480C0) USB clock source select + __IO uint32_t USBCLKUEN; //!< (@ 0x400480C4) USB clock source update enable + __IO uint32_t USBCLKDIV; //!< (@ 0x400480C8) USB clock source divider + __I uint32_t RESERVED7[5]; + __IO uint32_t CLKOUTSEL; //!< (@ 0x400480E0) CLKOUT clock source select + __IO uint32_t CLKOUTUEN; //!< (@ 0x400480E4) CLKOUT clock source update enable + __IO uint32_t CLKOUTDIV; //!< (@ 0x400480E8) CLKOUT clock divider + __I uint32_t RESERVED8[5]; + __I uint32_t PIOPORCAP0; //!< (@ 0x40048100) POR captured PIO status 0 + __I uint32_t PIOPORCAP1; //!< (@ 0x40048104) POR captured PIO status 1 + __I uint32_t RESERVED9[18]; + __IO uint32_t BODCTRL; //!< (@ 0x40048150) Brown-Out Detect + __IO uint32_t SYSTCKCAL; //!< (@ 0x40048154) System tick counter calibration + __I uint32_t RESERVED10[6]; + __IO uint32_t IRQLATENCY; //!< (@ 0x40048170) IQR delay + __IO uint32_t NMISRC; //!< (@ 0x40048174) NMI Source Control + __IO uint32_t PINTSEL[8]; //!< (@ 0x40048178) GPIO Pin Interrupt Select register 0 + __IO uint32_t USBCLKCTRL; //!< (@ 0x40048198) USB clock control + __I uint32_t USBCLKST; //!< (@ 0x4004819C) USB clock status + __I uint32_t RESERVED11[25]; + __IO uint32_t STARTERP0; //!< (@ 0x40048204) Start logic 0 interrupt wake-up enable register 0 + __I uint32_t RESERVED12[3]; + __IO uint32_t STARTERP1; //!< (@ 0x40048214) Start logic 1 interrupt wake-up enable register 1 + __I uint32_t RESERVED13[6]; + __IO uint32_t PDSLEEPCFG; //!< (@ 0x40048230) Power-down states in deep-sleep mode + __IO uint32_t PDAWAKECFG; //!< (@ 0x40048234) Power-down states for wake-up from deep-sleep + __IO uint32_t PDRUNCFG; //!< (@ 0x40048238) Power configuration register + __I uint32_t RESERVED14[110]; + __I uint32_t DEVICE_ID; //!< (@ 0x400483F4) Device ID + */ +} LPC_SYSCON_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- GPIO_PIN_INT ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x GPIO Modification date=3/17/2011 Major revision=0 Minor revision=3 (GPIO_PIN_INT) + */ + +typedef struct { /*!< (@ 0x4004C000) GPIO_PIN_INT Structure */ + __IO uint32_t ISEL; /*!< (@ 0x4004C000) Pin Interrupt Mode register */ + __IO uint32_t IENR; /*!< (@ 0x4004C004) Pin Interrupt Enable (Rising) register */ + __IO uint32_t SIENR; /*!< (@ 0x4004C008) Set Pin Interrupt Enable (Rising) register */ + __IO uint32_t CIENR; /*!< (@ 0x4004C00C) Clear Pin Interrupt Enable (Rising) register */ + __IO uint32_t IENF; /*!< (@ 0x4004C010) Pin Interrupt Enable Falling Edge / Active Level register */ + __IO uint32_t SIENF; /*!< (@ 0x4004C014) Set Pin Interrupt Enable Falling Edge / Active Level register */ + __IO uint32_t CIENF; /*!< (@ 0x4004C018) Clear Pin Interrupt Enable Falling Edge / Active Level address */ + __IO uint32_t RISE; /*!< (@ 0x4004C01C) Pin Interrupt Rising Edge register */ + __IO uint32_t FALL; /*!< (@ 0x4004C020) Pin Interrupt Falling Edge register */ + __IO uint32_t IST; /*!< (@ 0x4004C024) Pin Interrupt Status register */ +} LPC_GPIO_PIN_INT_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- GPIO_GROUP_INT0/1 ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x GPIO Modification date=3/17/2011 Major revision=0 Minor revision=3 (GPIO_GROUP_INT0) + */ + +typedef struct { /*!< (@ 0x4005C000) GPIO_GROUP_INT0 Structure */ + __IO uint32_t CTRL; /*!< (@ 0x4005C000) GPIO grouped interrupt control register */ + __I uint32_t RESERVED0[7]; + __IO uint32_t PORT_POL[2]; /*!< (@ 0x4005C020) GPIO grouped interrupt port 0 polarity register */ + __I uint32_t RESERVED1[6]; + __IO uint32_t PORT_ENA[2]; /*!< (@ 0x4005C040) GPIO grouped interrupt port 0/1 enable register */ +} LPC_GPIO_GROUP_INTx_Type; + + + +// ------------------------------------------------------------------------------------------------ +// ----- USB ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x USB2.0device controller Modification date=3/16/2011 Major revision=0 Minor revision=3 (USB) + */ + +typedef struct { /*!< (@ 0x40080000) USB Structure */ + __IO uint32_t DEVCMDSTAT; /*!< (@ 0x40080000) USB Device Command/Status register */ + __IO uint32_t INFO; /*!< (@ 0x40080004) USB Info register */ + __IO uint32_t EPLISTSTART; /*!< (@ 0x40080008) USB EP Command/Status List start address */ + __IO uint32_t DATABUFSTART; /*!< (@ 0x4008000C) USB Data buffer start address */ + __IO uint32_t LPM; /*!< (@ 0x40080010) Link Power Management register */ + __IO uint32_t EPSKIP; /*!< (@ 0x40080014) USB Endpoint skip */ + __IO uint32_t EPINUSE; /*!< (@ 0x40080018) USB Endpoint Buffer in use */ + __IO uint32_t EPBUFCFG; /*!< (@ 0x4008001C) USB Endpoint Buffer Configuration register */ + __IO uint32_t INTSTAT; /*!< (@ 0x40080020) USB interrupt status register */ + __IO uint32_t INTEN; /*!< (@ 0x40080024) USB interrupt enable register */ + __IO uint32_t INTSETSTAT; /*!< (@ 0x40080028) USB set interrupt status register */ + __IO uint32_t INTROUTING; /*!< (@ 0x4008002C) USB interrupt routing register */ + __I uint32_t RESERVED0[1]; + __I uint32_t EPTOGGLE; /*!< (@ 0x40080034) USB Endpoint toggle register */ +} LPC_USB_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- GPIO_PORT ----- +// ------------------------------------------------------------------------------------------------ + + +/** + * @brief Product name title=UM10462 Chapter title=LPC11U1x GPIO Modification date=3/17/2011 Major revision=0 Minor revision=3 (GPIO_PORT) + */ + +typedef struct { + union { + struct { + __IO uint8_t B0[32]; /*!< (@ 0x50000000) Byte pin registers port 0; pins PIO0_0 to PIO0_31 */ + __IO uint8_t B1[32]; /*!< (@ 0x50000020) Byte pin registers port 1 */ + }; + __IO uint8_t B[64]; /*!< (@ 0x50000000) Byte pin registers port 0/1 */ + }; + __I uint32_t RESERVED0[1008]; + union { + struct { + __IO uint32_t W0[32]; /*!< (@ 0x50001000) Word pin registers port 0 */ + __IO uint32_t W1[32]; /*!< (@ 0x50001080) Word pin registers port 1 */ + }; + __IO uint32_t W[64]; /*!< (@ 0x50001000) Word pin registers port 0/1 */ + }; + uint32_t RESERVED1[960]; + __IO uint32_t DIR[2]; /* 0x2000 */ + uint32_t RESERVED2[30]; + __IO uint32_t MASK[2]; /* 0x2080 */ + uint32_t RESERVED3[30]; + __IO uint32_t PIN[2]; /* 0x2100 */ + uint32_t RESERVED4[30]; + __IO uint32_t MPIN[2]; /* 0x2180 */ + uint32_t RESERVED5[30]; + __IO uint32_t SET[2]; /* 0x2200 */ + uint32_t RESERVED6[30]; + __O uint32_t CLR[2]; /* 0x2280 */ + uint32_t RESERVED7[30]; + __O uint32_t NOT[2]; /* 0x2300 */ +} LPC_GPIO_Type; + + +#if defined ( __CC_ARM ) + #pragma no_anon_unions +#endif + + +// ------------------------------------------------------------------------------------------------ +// ----- Peripheral memory map ----- +// ------------------------------------------------------------------------------------------------ + +#define LPC_I2C_BASE (0x40000000) +#define LPC_WWDT_BASE (0x40004000) +#define LPC_USART_BASE (0x40008000) +#define LPC_CT16B0_BASE (0x4000C000) +#define LPC_CT16B1_BASE (0x40010000) +#define LPC_CT32B0_BASE (0x40014000) +#define LPC_CT32B1_BASE (0x40018000) +#define LPC_ADC_BASE (0x4001C000) +#define LPC_PMU_BASE (0x40038000) +#define LPC_FLASHCTRL_BASE (0x4003C000) +#define LPC_SSP0_BASE (0x40040000) +#define LPC_SSP1_BASE (0x40058000) +#define LPC_IOCON_BASE (0x40044000) +#define LPC_SYSCON_BASE (0x40048000) +#define LPC_GPIO_PIN_INT_BASE (0x4004C000) +#define LPC_GPIO_GROUP_INT0_BASE (0x4005C000) +#define LPC_GPIO_GROUP_INT1_BASE (0x40060000) +#define LPC_USB_BASE (0x40080000) +#define LPC_GPIO_BASE (0x50000000) + + +// ------------------------------------------------------------------------------------------------ +// ----- Peripheral declaration ----- +// ------------------------------------------------------------------------------------------------ + +#define LPC_I2C ((LPC_I2C_Type *) LPC_I2C_BASE) +#define LPC_WWDT ((LPC_WWDT_Type *) LPC_WWDT_BASE) +#define LPC_USART ((LPC_USART_Type *) LPC_USART_BASE) +#define LPC_CT16B0 ((LPC_CTxxBx_Type *) LPC_CT16B0_BASE) +#define LPC_CT16B1 ((LPC_CTxxBx_Type *) LPC_CT16B1_BASE) +#define LPC_CT32B0 ((LPC_CTxxBx_Type *) LPC_CT32B0_BASE) +#define LPC_CT32B1 ((LPC_CTxxBx_Type *) LPC_CT32B1_BASE) +#define LPC_ADC ((LPC_ADC_Type *) LPC_ADC_BASE) +#define LPC_PMU ((LPC_PMU_Type *) LPC_PMU_BASE) +#define LPC_FLASHCTRL ((LPC_FLASHCTRL_Type *) LPC_FLASHCTRL_BASE) +#define LPC_SSP0 ((LPC_SSPx_Type *) LPC_SSP0_BASE) +#define LPC_SSP1 ((LPC_SSPx_Type *) LPC_SSP1_BASE) +#define LPC_IOCON ((LPC_IOCON_Type *) LPC_IOCON_BASE) +#define LPC_SYSCON ((LPC_SYSCON_Type *) LPC_SYSCON_BASE) +#define LPC_GPIO_PIN_INT ((LPC_GPIO_PIN_INT_Type *) LPC_GPIO_PIN_INT_BASE) +#define LPC_GPIO_GROUP_INT0 ((LPC_GPIO_GROUP_INTx_Type*) LPC_GPIO_GROUP_INT0_BASE) +#define LPC_GPIO_GROUP_INT1 ((LPC_GPIO_GROUP_INTx_Type*) LPC_GPIO_GROUP_INT1_BASE) +#define LPC_USB ((LPC_USB_Type *) LPC_USB_BASE) +#define LPC_GPIO ((LPC_GPIO_Type *) LPC_GPIO_BASE) + + +/** @} */ /* End of group Device_Peripheral_Registers */ +/** @} */ /* End of group (null) */ +/** @} */ /* End of group LPC11Uxx */ + +#ifdef __cplusplus +} +#endif + + +#endif // __LPC11UXX_H__ diff --git a/inc/app_usbd_cfg.h b/inc/app_usbd_cfg.h new file mode 100644 index 0000000..3bc0931 --- /dev/null +++ b/inc/app_usbd_cfg.h @@ -0,0 +1,95 @@ +/* + * @brief Configuration file needed for USB ROM stack based applications. + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ +#include "lpc_types.h" +#include "error.h" +#include "usbd_rom_api.h" + +#ifndef __APP_USB_CFG_H_ +#define __APP_USB_CFG_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @ingroup EXAMPLES_USBDROM_11UXX_HID_GENERIC + * @{ + */ + +/* HID In/Out Endpoint Address */ +#define HID_EP_IN 0x81 +#define HID_EP_OUT 0x01 + +/* The following manifest constants are used to define this memory area to be used + by USBD ROM stack. + */ +#define USB_STACK_MEM_BASE 0x20004000 +#define USB_STACK_MEM_SIZE 0x0800 + +/* Manifest constants used by USBD ROM stack. These values SHOULD NOT BE CHANGED + for advance features which require usage of USB_CORE_CTRL_T structure. + Since these are the values used for compiling USB stack. + */ +#define USB_MAX_IF_NUM 8 /*!< Max interface number used for building USBDL_Lib. DON'T CHANGE. */ +#define USB_MAX_EP_NUM 5 /*!< Max number of EP used for building USBD ROM. DON'T CHANGE. */ +#define USB_MAX_PACKET0 64 /*!< Max EP0 packet size used for building USBD ROM. DON'T CHANGE. */ +#define USB_FS_MAX_BULK_PACKET 64 /*!< MAXP for FS bulk EPs used for building USBD ROM. DON'T CHANGE. */ +#define USB_HS_MAX_BULK_PACKET 512 /*!< MAXP for HS bulk EPs used for building USBD ROM. DON'T CHANGE. */ +#define USB_DFU_XFER_SIZE 2048 /*!< Max DFU transfer size used for building USBD ROM. DON'T CHANGE. */ + +/* USB descriptor arrays defined *_desc.c file */ +extern const uint8_t USB_DeviceDescriptor[]; +extern uint8_t USB_FsConfigDescriptor[]; +extern const uint8_t USB_StringDescriptor[]; +extern const uint8_t USB_DeviceQualifier[]; + +// HID +extern const uint8_t HID_ReportDescriptor[]; +extern const uint8_t hid_report_size; + +/** + * @brief Find the address of interface descriptor for given class type. + * @param pDesc : Pointer to configuration descriptor in which the desired class + * interface descriptor to be found. + * @param intfClass : Interface class type to be searched. + * @return If found returns the address of requested interface else returns NULL. + */ +extern USB_INTERFACE_DESCRIPTOR *find_IntfDesc(const uint8_t *pDesc, uint32_t intfClass); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __APP_USB_CFG_H_ */ diff --git a/inc/compiler.h b/inc/compiler.h new file mode 100644 index 0000000..ed43a4b --- /dev/null +++ b/inc/compiler.h @@ -0,0 +1,19 @@ +/* + * compiler.h + * + * Created on: Jun 18, 2015 + * Author: yliu + */ + +#ifndef COMPILER_H_ +#define COMPILER_H_ + +#if defined ( __GNUC__ ) +#define __ALWAYS_INLINE __attribute__((always_inline)) +#define __forceinline __ALWAYS_INLINE +#define __weak __attribute__ ((weak)) +#endif + + + +#endif /* COMPILER_H_ */ diff --git a/inc/core_cm0.h b/inc/core_cm0.h new file mode 100644 index 0000000..1b6b54e --- /dev/null +++ b/inc/core_cm0.h @@ -0,0 +1,682 @@ +/**************************************************************************//** + * @file core_cm0.h + * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM0_H_GENERIC +#define __CORE_CM0_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex_M0 + @{ + */ + +/* CMSIS CM0 definitions */ +#define __CM0_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM0_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16) | \ + __CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ + +#endif /* __CORE_CM0_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0_H_DEPENDANT +#define __CORE_CM0_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0_REV + #define __CM0_REV 0x0000 + #warning "__CM0_REV not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex_M0 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31]; + __IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31]; + __IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31]; + __IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31]; + uint32_t RESERVED4[64]; + __IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + uint32_t RESERVED0; + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) + are only accessible over DAP and not via processor. Therefore + they are not covered by the Cortex-M0 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M0 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 ) +#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) ) +#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) ) + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); } + else { + NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); } +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */ + else { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#endif /* __CORE_CM0_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/inc/core_cmFunc.h b/inc/core_cmFunc.h new file mode 100644 index 0000000..139bc3c --- /dev/null +++ b/inc/core_cmFunc.h @@ -0,0 +1,636 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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 __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/inc/core_cmInstr.h b/inc/core_cmInstr.h new file mode 100644 index 0000000..8946c2c --- /dev/null +++ b/inc/core_cmInstr.h @@ -0,0 +1,688 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.20 + * @date 05. March 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM 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 COPYRIGHT HOLDERS AND 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 __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constrant "l" + * Otherwise, use general registers, specified by constrant "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + uint32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32 - op2)); +} + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/inc/error.h b/inc/error.h new file mode 100644 index 0000000..ea33032 --- /dev/null +++ b/inc/error.h @@ -0,0 +1,136 @@ +/* + * @brief Error code returned by Boot ROM drivers/library functions + * @ingroup Common + * + * This file contains unified error codes to be used across driver, + * middleware, applications, hal and demo software. + * + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __LPC_ERROR_H__ +#define __LPC_ERROR_H__ + +/** Error code returned by Boot ROM drivers/library functions +* +* Error codes are a 32-bit value with : +* - The 16 MSB contains the peripheral code number +* - The 16 LSB contains an error code number associated to that peripheral +* +*/ +typedef enum +{ + /**\b 0x00000000*/ LPC_OK=0, /**< enum value returned on Success */ + /**\b 0xFFFFFFFF*/ ERR_FAILED = -1, /**< enum value returned on general failure */ + /**\b 0xFFFFFFFE*/ ERR_TIME_OUT = -2, /**< enum value returned on general timeout */ + /**\b 0xFFFFFFFD*/ ERR_BUSY = -3, /**< enum value returned when resource is busy */ + + /* ISP related errors */ + ERR_ISP_BASE = 0x00000000, + /*0x00000001*/ ERR_ISP_INVALID_COMMAND = ERR_ISP_BASE + 1, + /*0x00000002*/ ERR_ISP_SRC_ADDR_ERROR, /* Source address not on word boundary */ + /*0x00000003*/ ERR_ISP_DST_ADDR_ERROR, /* Destination address not on word or 256 byte boundary */ + /*0x00000004*/ ERR_ISP_SRC_ADDR_NOT_MAPPED, + /*0x00000005*/ ERR_ISP_DST_ADDR_NOT_MAPPED, + /*0x00000006*/ ERR_ISP_COUNT_ERROR, /* Byte count is not multiple of 4 or is not a permitted value */ + /*0x00000007*/ ERR_ISP_INVALID_SECTOR, + /*0x00000008*/ ERR_ISP_SECTOR_NOT_BLANK, + /*0x00000009*/ ERR_ISP_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION, + /*0x0000000A*/ ERR_ISP_COMPARE_ERROR, + /*0x0000000B*/ ERR_ISP_BUSY, /* Flash programming hardware interface is busy */ + /*0x0000000C*/ ERR_ISP_PARAM_ERROR, /* Insufficient number of parameters */ + /*0x0000000D*/ ERR_ISP_ADDR_ERROR, /* Address not on word boundary */ + /*0x0000000E*/ ERR_ISP_ADDR_NOT_MAPPED, + /*0x0000000F*/ ERR_ISP_CMD_LOCKED, /* Command is locked */ + /*0x00000010*/ ERR_ISP_INVALID_CODE, /* Unlock code is invalid */ + /*0x00000011*/ ERR_ISP_INVALID_BAUD_RATE, + /*0x00000012*/ ERR_ISP_INVALID_STOP_BIT, + /*0x00000013*/ ERR_ISP_CODE_READ_PROTECTION_ENABLED, + + /* ROM API related errors */ + ERR_API_BASE = 0x00010000, + /**\b 0x00010001*/ ERR_API_INVALID_PARAMS = ERR_API_BASE + 1, /**< Invalid parameters*/ + /**\b 0x00010002*/ ERR_API_INVALID_PARAM1, /**< PARAM1 is invalid */ + /**\b 0x00010003*/ ERR_API_INVALID_PARAM2, /**< PARAM2 is invalid */ + /**\b 0x00010004*/ ERR_API_INVALID_PARAM3, /**< PARAM3 is invalid */ + /**\b 0x00010005*/ ERR_API_MOD_INIT, /**< API is called before module init */ + + /* SPIFI API related errors */ + ERR_SPIFI_BASE = 0x00020000, + /*0x00020001*/ ERR_SPIFI_DEVICE_ERROR =ERR_SPIFI_BASE+1, + /*0x00020002*/ ERR_SPIFI_INTERNAL_ERROR, + /*0x00020003*/ ERR_SPIFI_TIMEOUT, + /*0x00020004*/ ERR_SPIFI_OPERAND_ERROR, + /*0x00020005*/ ERR_SPIFI_STATUS_PROBLEM, + /*0x00020006*/ ERR_SPIFI_UNKNOWN_EXT, + /*0x00020007*/ ERR_SPIFI_UNKNOWN_ID, + /*0x00020008*/ ERR_SPIFI_UNKNOWN_TYPE, + /*0x00020009*/ ERR_SPIFI_UNKNOWN_MFG, + + /* Security API related errors */ + ERR_SEC_BASE = 0x00030000, + /*0x00030001*/ ERR_SEC_AES_WRONG_CMD=ERR_SEC_BASE+1, + /*0x00030002*/ ERR_SEC_AES_NOT_SUPPORTED, + /*0x00030003*/ ERR_SEC_AES_KEY_ALREADY_PROGRAMMED, + + + /* USB device stack related errors */ + ERR_USBD_BASE = 0x00040000, + /**\b 0x00040001*/ ERR_USBD_INVALID_REQ = ERR_USBD_BASE + 1, /**< invalid request */ + /**\b 0x00040002*/ ERR_USBD_UNHANDLED, /**< Callback did not process the event */ + /**\b 0x00040003*/ ERR_USBD_STALL, /**< Stall the endpoint on which the call back is called */ + /**\b 0x00040004*/ ERR_USBD_SEND_ZLP, /**< Send ZLP packet on the endpoint on which the call back is called */ + /**\b 0x00040005*/ ERR_USBD_SEND_DATA, /**< Send data packet on the endpoint on which the call back is called */ + /**\b 0x00040006*/ ERR_USBD_BAD_DESC, /**< Bad descriptor*/ + /**\b 0x00040007*/ ERR_USBD_BAD_CFG_DESC,/**< Bad config descriptor*/ + /**\b 0x00040008*/ ERR_USBD_BAD_INTF_DESC,/**< Bad interface descriptor*/ + /**\b 0x00040009*/ ERR_USBD_BAD_EP_DESC,/**< Bad endpoint descriptor*/ + /**\b 0x0004000a*/ ERR_USBD_BAD_MEM_BUF, /**< Bad alignment of buffer passed. */ + /**\b 0x0004000b*/ ERR_USBD_TOO_MANY_CLASS_HDLR, /**< Too many class handlers. */ + + /* CGU related errors */ + ERR_CGU_BASE = 0x00050000, + /*0x00050001*/ ERR_CGU_NOT_IMPL=ERR_CGU_BASE+1, + /*0x00050002*/ ERR_CGU_INVALID_PARAM, + /*0x00050003*/ ERR_CGU_INVALID_SLICE, + /*0x00050004*/ ERR_CGU_OUTPUT_GEN, + /*0x00050005*/ ERR_CGU_DIV_SRC, + /*0x00050006*/ ERR_CGU_DIV_VAL, + /*0x00050007*/ ERR_CGU_SRC + +} ErrorCode_t; + + +#ifndef offsetof +#define offsetof(s,m) (int)&(((s *)0)->m) +#endif + +#define COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;} + +#endif /* __LPC_ERROR_H__ */ diff --git a/inc/lpc_types.h b/inc/lpc_types.h new file mode 100644 index 0000000..772143e --- /dev/null +++ b/inc/lpc_types.h @@ -0,0 +1,216 @@ +/* + * @brief Common types used in LPC functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __LPC_TYPES_H_ +#define __LPC_TYPES_H_ + +#include +#include + +/** @defgroup LPC_Types CHIP: LPC Common Types + * @ingroup CHIP_Common + * @{ + */ + +/** @defgroup LPC_Types_Public_Types LPC Public Types + * @{ + */ + +/** + * @brief Boolean Type definition + */ +typedef enum {FALSE = 0, TRUE = !FALSE} Bool; + +/** + * @brief Boolean Type definition + */ +#if !defined(__cplusplus) +// typedef enum {false = 0, true = !false} bool; +#endif + +/** + * @brief Flag Status and Interrupt Flag Status type definition + */ +typedef enum {RESET = 0, SET = !RESET} FlagStatus, IntStatus, SetState; +#define PARAM_SETSTATE(State) ((State == RESET) || (State == SET)) + +/** + * @brief Functional State Definition + */ +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; +#define PARAM_FUNCTIONALSTATE(State) ((State == DISABLE) || (State == ENABLE)) + +/** + * @ Status type definition + */ +typedef enum {ERROR = 0, SUCCESS = !ERROR} Status; + +/** + * Read/Write transfer type mode (Block or non-block) + */ +typedef enum { + NONE_BLOCKING = 0, /**< None Blocking type */ + BLOCKING, /**< Blocking type */ +} TRANSFER_BLOCK_T; + +/** Pointer to Function returning Void (any number of parameters) */ +typedef void (*PFV)(); + +/** Pointer to Function returning int32_t (any number of parameters) */ +typedef int32_t (*PFI)(); + +/** + * @} + */ + +/** @defgroup LPC_Types_Public_Macros LPC Public Macros + * @{ + */ + +/* _BIT(n) sets the bit at position "n" + * _BIT(n) is intended to be used in "OR" and "AND" expressions: + * e.g., "(_BIT(3) | _BIT(7))". + */ +#undef _BIT +/* Set bit macro */ +#define _BIT(n) (1 << (n)) + +/* _SBF(f,v) sets the bit field starting at position "f" to value "v". + * _SBF(f,v) is intended to be used in "OR" and "AND" expressions: + * e.g., "((_SBF(5,7) | _SBF(12,0xF)) & 0xFFFF)" + */ +#undef _SBF +/* Set bit field macro */ +#define _SBF(f, v) ((v) << (f)) + +/* _BITMASK constructs a symbol with 'field_width' least significant + * bits set. + * e.g., _BITMASK(5) constructs '0x1F', _BITMASK(16) == 0xFFFF + * The symbol is intended to be used to limit the bit field width + * thusly: + * = (any_expression) & _BITMASK(x), where 0 < x <= 32. + * If "any_expression" results in a value that is larger than can be + * contained in 'x' bits, the bits above 'x - 1' are masked off. When + * used with the _SBF example above, the example would be written: + * a_reg = ((_SBF(5,7) | _SBF(12,0xF)) & _BITMASK(16)) + * This ensures that the value written to a_reg is no wider than + * 16 bits, and makes the code easier to read and understand. + */ +#undef _BITMASK +/* Bitmask creation macro */ +#define _BITMASK(field_width) ( _BIT(field_width) - 1) + +/* NULL pointer */ +#ifndef NULL +#define NULL ((void *) 0) +#endif + +/* Number of elements in an array */ +#define NELEMENTS(array) (sizeof(array) / sizeof(array[0])) + +/* Static data/function define */ +#define STATIC static +/* External data/function define */ +#define EXTERN extern + +#if !defined(MAX) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +#if !defined(MIN) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +/** + * @} + */ + +/* Old Type Definition compatibility */ +/** @addtogroup LPC_Types_Public_Types + * @{ + */ + +/** LPC type for character type */ +typedef char CHAR; + +/** LPC type for 8 bit unsigned value */ +typedef uint8_t UNS_8; + +/** LPC type for 8 bit signed value */ +typedef int8_t INT_8; + +/** LPC type for 16 bit unsigned value */ +typedef uint16_t UNS_16; + +/** LPC type for 16 bit signed value */ +typedef int16_t INT_16; + +/** LPC type for 32 bit unsigned value */ +typedef uint32_t UNS_32; + +/** LPC type for 32 bit signed value */ +typedef int32_t INT_32; + +/** LPC type for 64 bit signed value */ +typedef int64_t INT_64; + +/** LPC type for 64 bit unsigned value */ +typedef uint64_t UNS_64; + +#ifdef __CODE_RED +#define BOOL_32 bool +#define BOOL_16 bool +#define BOOL_8 bool +#else +/** 32 bit boolean type */ +typedef bool BOOL_32; + +/** 16 bit boolean type */ +typedef bool BOOL_16; + +/** 8 bit boolean type */ +typedef bool BOOL_8; +#endif + +#ifdef __CC_ARM +#define INLINE __inline +#else +#define INLINE inline +#endif + +/** + * @} + */ + +/** + * @} + */ + +#endif /* __LPC_TYPES_H_ */ diff --git a/inc/system_LPC11Uxx.h b/inc/system_LPC11Uxx.h new file mode 100644 index 0000000..e490d17 --- /dev/null +++ b/inc/system_LPC11Uxx.h @@ -0,0 +1,64 @@ +/**************************************************************************//** + * @file system_LPC11Uxx.h + * @brief CMSIS Cortex-M0 Device Peripheral Access Layer Header File + * for the NXP LPC11Uxx Device Series + * @version V1.10 + * @date 24. November 2010 + * + * @note + * Copyright (C) 2009-2010 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + + +#ifndef __SYSTEM_LPC11Uxx_H +#define __SYSTEM_LPC11Uxx_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + + +/** + * Initialize the system + * + * @param none + * @return none + * + * @brief Setup the microcontroller system. + * Initialize the System and update the SystemCoreClock variable. + */ +extern void SystemInit (void); + +/** + * Update SystemCoreClock variable + * + * @param none + * @return none + * + * @brief Updates the SystemCoreClock with current core Clock + * retrieved from cpu registers. + */ +extern void SystemCoreClockUpdate (void); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_LPC11Uxx_H */ diff --git a/inc/uart.h b/inc/uart.h new file mode 100644 index 0000000..2636467 --- /dev/null +++ b/inc/uart.h @@ -0,0 +1,13 @@ +/* + * uart.h + * + * Created on: Jun 26, 2015 + * Author: yliu + */ + +#ifndef UART_H_ +#define UART_H_ + + + +#endif /* UART_H_ */ diff --git a/inc/usb_driver.h b/inc/usb_driver.h new file mode 100644 index 0000000..5b13e51 --- /dev/null +++ b/inc/usb_driver.h @@ -0,0 +1,53 @@ +/* + * usb_driver.h + * + * Created on: Jun 18, 2015 + * Author: yliu + */ + +#ifndef USB_DRIVER_H_ +#define USB_DRIVER_H_ + + +#include "app_usbd_cfg.h" +#include "usbd_rom_api.h" + + +typedef struct { + const uint32_t usbdApiBase; /*!< USBD API function table base address */ + const uint32_t reserved0; /*!< Reserved */ + const uint32_t candApiBase; /*!< CAN API function table base address */ + const uint32_t pwrApiBase; /*!< Power API function table base address */ + const uint32_t reserved1; /*!< Reserved */ + const uint32_t reserved2; /*!< Reserved */ + const uint32_t reserved3; /*!< Reserved */ + const uint32_t reserved4; /*!< Reserved */ +} LPC_ROM_API_T; + + + +#define LPC_ROM_API_BASE_LOC 0x1FFF1FF8 +#define LPC_ROM_API (*((LPC_ROM_API_T * *) LPC_ROM_API_BASE_LOC)) + + +typedef ErrorCode_t (*HID_GetReport_Func_T)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length); +typedef ErrorCode_t (*HID_SetReport_Func_T)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length); +typedef ErrorCode_t (*HID_EpIn_Hdlr_Func_T) (USBD_HANDLE_T hUsb, void* data, uint32_t event); +typedef ErrorCode_t (*HID_EpOut_Hdlr_Func_T) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + +void init_usb_clock (); +void init_usb_power (); +int init_usb_driver (USBD_API_INIT_PARAM_T *usb_param); +int init_usb_hid (USBD_API_INIT_PARAM_T *usb_param, + HID_GetReport_Func_T getreport_fun, HID_SetReport_Func_T setreport_fun, + HID_EpIn_Hdlr_Func_T epin_hdlr_fun, HID_EpOut_Hdlr_Func_T epout_hdlr_fun, + uint8_t** report_saddr, int report_size); + +void connect_to_usb_bus (); +void disconnect_to_usb_bus (); + + +extern USBD_HANDLE_T g_usb_hnd; + + +#endif /* USB_DRIVER_H_ */ diff --git a/inc/usbd/usbd.h b/inc/usbd/usbd.h new file mode 100644 index 0000000..20faabd --- /dev/null +++ b/inc/usbd/usbd.h @@ -0,0 +1,704 @@ +/*********************************************************************** +* $Id:: mw_usbd.h 575 2012-11-20 01:35:56Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __USBD_H__ +#define __USBD_H__ + +/** \file + * \brief Common definitions and declarations for the USB stack. + * + * Common definitions and declarations for the USB stack. + * \addtogroup USBD_Core + * @{ + */ + +#include "lpc_types.h" + +#if defined(__GNUC__) +/* As per http://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax, +6.29 Attributes Syntax +"An attribute specifier list may appear as part of a struct, union or +enum specifier. It may go either immediately after the struct, union +or enum keyword, or after the closing brace. The former syntax is +preferred. Where attribute specifiers follow the closing brace, they +are considered to relate to the structure, union or enumerated type +defined, not to any enclosing declaration the type specifier appears +in, and the type defined is not complete until after the attribute +specifiers." +So use POST_PACK immediately after struct keyword +*/ +#define PRE_PACK +#define POST_PACK __attribute__((__packed__)) +#define ALIGNED(n) __attribute__((aligned (n))) + +#elif defined(__arm) +#define PRE_PACK __packed +#define POST_PACK +#define ALIGNED(n) __align(n) + +#elif defined(__ICCARM__) +#define PRE_PACK __packed +#define POST_PACK +#define PRAGMA_ALIGN_4096 _Pragma("data_alignment=4096") +#define PRAGMA_ALIGN_2048 _Pragma("data_alignment=2048") +#define PRAGMA_ALIGN_256 _Pragma("data_alignment=256") +#define PRAGMA_ALIGN_128 _Pragma("data_alignment=128") +#define PRAGMA_ALIGN_64 _Pragma("data_alignment=64") +#define PRAGMA_ALIGN_48 _Pragma("data_alignment=48") +#define PRAGMA_ALIGN_32 _Pragma("data_alignment=32") +#define PRAGMA_ALIGN_4 _Pragma("data_alignment=4") +#define ALIGNED(n) PRAGMA_ALIGN_##n + +#pragma diag_suppress=Pe021 +#endif + +/** Structure to pack lower and upper byte to form 16 bit word. */ +PRE_PACK struct POST_PACK _WB_T +{ + uint8_t L; /**< lower byte */ + uint8_t H; /**< upper byte */ +}; +/** Structure to pack lower and upper byte to form 16 bit word.*/ +typedef struct _WB_T WB_T; + +/** Union of \ref _WB_T struct and 16 bit word.*/ +PRE_PACK union POST_PACK __WORD_BYTE +{ + uint16_t W; /**< data member to do 16 bit access */ + WB_T WB; /**< data member to do 8 bit access */ +} ; +/** Union of \ref _WB_T struct and 16 bit word.*/ +typedef union __WORD_BYTE WORD_BYTE; + +/** bmRequestType.Dir defines + * @{ + */ +/** Request from host to device */ +#define REQUEST_HOST_TO_DEVICE 0 +/** Request from device to host */ +#define REQUEST_DEVICE_TO_HOST 1 +/** @} */ + +/** bmRequestType.Type defines + * @{ + */ +/** Standard Request */ +#define REQUEST_STANDARD 0 +/** Class Request */ +#define REQUEST_CLASS 1 +/** Vendor Request */ +#define REQUEST_VENDOR 2 +/** Reserved Request */ +#define REQUEST_RESERVED 3 +/** @} */ + +/** bmRequestType.Recipient defines + * @{ + */ +/** Request to device */ +#define REQUEST_TO_DEVICE 0 +/** Request to interface */ +#define REQUEST_TO_INTERFACE 1 +/** Request to endpoint */ +#define REQUEST_TO_ENDPOINT 2 +/** Request to other */ +#define REQUEST_TO_OTHER 3 +/** @} */ + +/** Structure to define 8 bit USB request.*/ +PRE_PACK struct POST_PACK _BM_T +{ + uint8_t Recipient : 5; /**< Recipient type. */ + uint8_t Type : 2; /**< Request type. */ + uint8_t Dir : 1; /**< Direction type. */ +}; +/** Structure to define 8 bit USB request.*/ +typedef struct _BM_T BM_T; + +/** Union of \ref _BM_T struct and 8 bit byte.*/ +PRE_PACK union POST_PACK _REQUEST_TYPE +{ + uint8_t B; /**< byte wide access memeber */ + BM_T BM; /**< bitfield structure access memeber */ +} ; +/** Union of \ref _BM_T struct and 8 bit byte.*/ +typedef union _REQUEST_TYPE REQUEST_TYPE; + +/** USB Standard Request Codes + * @{ + */ +/** GET_STATUS request */ +#define USB_REQUEST_GET_STATUS 0 +/** CLEAR_FEATURE request */ +#define USB_REQUEST_CLEAR_FEATURE 1 +/** SET_FEATURE request */ +#define USB_REQUEST_SET_FEATURE 3 +/** SET_ADDRESS request */ +#define USB_REQUEST_SET_ADDRESS 5 +/** GET_DESCRIPTOR request */ +#define USB_REQUEST_GET_DESCRIPTOR 6 +/** SET_DESCRIPTOR request */ +#define USB_REQUEST_SET_DESCRIPTOR 7 +/** GET_CONFIGURATION request */ +#define USB_REQUEST_GET_CONFIGURATION 8 +/** SET_CONFIGURATION request */ +#define USB_REQUEST_SET_CONFIGURATION 9 +/** GET_INTERFACE request */ +#define USB_REQUEST_GET_INTERFACE 10 +/** SET_INTERFACE request */ +#define USB_REQUEST_SET_INTERFACE 11 +/** SYNC_FRAME request */ +#define USB_REQUEST_SYNC_FRAME 12 +/** @} */ + +/** USB GET_STATUS Bit Values + * @{ + */ +/** SELF_POWERED status*/ +#define USB_GETSTATUS_SELF_POWERED 0x01 +/** REMOTE_WAKEUP capable status*/ +#define USB_GETSTATUS_REMOTE_WAKEUP 0x02 +/** ENDPOINT_STALL status*/ +#define USB_GETSTATUS_ENDPOINT_STALL 0x01 +/** @} */ + +/** USB Standard Feature selectors + * @{ + */ +/** ENDPOINT_STALL feature*/ +#define USB_FEATURE_ENDPOINT_STALL 0 +/** REMOTE_WAKEUP feature*/ +#define USB_FEATURE_REMOTE_WAKEUP 1 +/** TEST_MODE feature*/ +#define USB_FEATURE_TEST_MODE 2 +/** @} */ + +/** USB Default Control Pipe Setup Packet*/ +PRE_PACK struct POST_PACK _USB_SETUP_PACKET +{ + REQUEST_TYPE bmRequestType; /**< This bitmapped field identifies the characteristics + of the specific request. \sa _BM_T. + */ + uint8_t bRequest; /**< This field specifies the particular request. The + Type bits in the bmRequestType field modify the meaning + of this field. \sa USBD_REQUEST. + */ + WORD_BYTE wValue; /**< Used to pass a parameter to the device, specific + to the request. + */ + WORD_BYTE wIndex; /**< Used to pass a parameter to the device, specific + to the request. The wIndex field is often used in + requests to specify an endpoint or an interface. + */ + uint16_t wLength; /**< This field specifies the length of the data + transferred during the second phase of the control + transfer. + */ +} ; +/** USB Default Control Pipe Setup Packet*/ +typedef struct _USB_SETUP_PACKET USB_SETUP_PACKET; + + +/** USB Descriptor Types + * @{ + */ +/** Device descriptor type */ +#define USB_DEVICE_DESCRIPTOR_TYPE 1 +/** Configuration descriptor type */ +#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2 +/** String descriptor type */ +#define USB_STRING_DESCRIPTOR_TYPE 3 +/** Interface descriptor type */ +#define USB_INTERFACE_DESCRIPTOR_TYPE 4 +/** Endpoint descriptor type */ +#define USB_ENDPOINT_DESCRIPTOR_TYPE 5 +/** Device qualifier descriptor type */ +#define USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE 6 +/** Other speed configuration descriptor type */ +#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE 7 +/** Interface power descriptor type */ +#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 8 +/** OTG descriptor type */ +#define USB_OTG_DESCRIPTOR_TYPE 9 +/** Debug descriptor type */ +#define USB_DEBUG_DESCRIPTOR_TYPE 10 +/** Interface association descriptor type */ +#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE 11 +/** @} */ + +/** USB Device Classes + * @{ + */ +/** Reserved device class */ +#define USB_DEVICE_CLASS_RESERVED 0x00 +/** Audio device class */ +#define USB_DEVICE_CLASS_AUDIO 0x01 +/** Communications device class */ +#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02 +/** Human interface device class */ +#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 +/** monitor device class */ +#define USB_DEVICE_CLASS_MONITOR 0x04 +/** physical interface device class */ +#define USB_DEVICE_CLASS_PHYSICAL_INTERFACE 0x05 +/** power device class */ +#define USB_DEVICE_CLASS_POWER 0x06 +/** Printer device class */ +#define USB_DEVICE_CLASS_PRINTER 0x07 +/** Storage device class */ +#define USB_DEVICE_CLASS_STORAGE 0x08 +/** Hub device class */ +#define USB_DEVICE_CLASS_HUB 0x09 +/** miscellaneous device class */ +#define USB_DEVICE_CLASS_MISCELLANEOUS 0xEF +/** Application device class */ +#define USB_DEVICE_CLASS_APP 0xFE +/** Vendor specific device class */ +#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF +/** @} */ + +/** bmAttributes in Configuration Descriptor + * @{ + */ +/** Power field mask */ +#define USB_CONFIG_POWERED_MASK 0x40 +/** Bus powered */ +#define USB_CONFIG_BUS_POWERED 0x80 +/** Self powered */ +#define USB_CONFIG_SELF_POWERED 0xC0 +/** remote wakeup */ +#define USB_CONFIG_REMOTE_WAKEUP 0x20 +/** @} */ + +/** bMaxPower in Configuration Descriptor */ +#define USB_CONFIG_POWER_MA(mA) ((mA)/2) + +/** bEndpointAddress in Endpoint Descriptor + * @{ + */ +/** Endopint address mask */ +#define USB_ENDPOINT_DIRECTION_MASK 0x80 +/** Macro to convert OUT endopint number to endpoint address value. */ +#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00) +/** Macro to convert IN endopint number to endpoint address value. */ +#define USB_ENDPOINT_IN(addr) ((addr) | 0x80) +/** @} */ + +/** bmAttributes in Endpoint Descriptor + * @{ + */ +/** Endopint type mask */ +#define USB_ENDPOINT_TYPE_MASK 0x03 +/** Control Endopint type */ +#define USB_ENDPOINT_TYPE_CONTROL 0x00 +/** isochronous Endopint type */ +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01 +/** bulk Endopint type */ +#define USB_ENDPOINT_TYPE_BULK 0x02 +/** interrupt Endopint type */ +#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 +/** Endopint sync type mask */ +#define USB_ENDPOINT_SYNC_MASK 0x0C +/** no synchronization Endopint */ +#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION 0x00 +/** Asynchronous sync Endopint */ +#define USB_ENDPOINT_SYNC_ASYNCHRONOUS 0x04 +/** Adaptive sync Endopint */ +#define USB_ENDPOINT_SYNC_ADAPTIVE 0x08 +/** Synchronous sync Endopint */ +#define USB_ENDPOINT_SYNC_SYNCHRONOUS 0x0C +/** Endopint usage type mask */ +#define USB_ENDPOINT_USAGE_MASK 0x30 +/** Endopint data usage type */ +#define USB_ENDPOINT_USAGE_DATA 0x00 +/** Endopint feedback usage type */ +#define USB_ENDPOINT_USAGE_FEEDBACK 0x10 +/** Endopint implicit feedback usage type */ +#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK 0x20 +/** Endopint reserved usage type */ +#define USB_ENDPOINT_USAGE_RESERVED 0x30 +/** @} */ + +/** Control endopint EP0's maximum packet size in high-speed mode.*/ +#define USB_ENDPOINT_0_HS_MAXP 64 +/** Control endopint EP0's maximum packet size in low-speed mode.*/ +#define USB_ENDPOINT_0_LS_MAXP 8 +/** Bulk endopint's maximum packet size in high-speed mode.*/ +#define USB_ENDPOINT_BULK_HS_MAXP 512 + +/** USB Standard Device Descriptor */ +PRE_PACK struct POST_PACK _USB_DEVICE_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes. */ + uint8_t bDescriptorType; /**< DEVICE Descriptor Type. */ + uint16_t bcdUSB; /**< BUSB Specification Release Number in + Binary-Coded Decimal (i.e., 2.10 is 210H). + This field identifies the release of the USB + Specification with which the device and its + descriptors are compliant. + */ + uint8_t bDeviceClass; /**< Class code (assigned by the USB-IF). + If this field is reset to zero, each interface + within a configuration specifies its own + class information and the various + interfaces operate independently.\n + If this field is set to a value between 1 and + FEH, the device supports different class + specifications on different interfaces and + the interfaces may not operate + independently. This value identifies the + class definition used for the aggregate + interfaces. \n + If this field is set to FFH, the device class + is vendor-specific. + */ + uint8_t bDeviceSubClass; /**< Subclass code (assigned by the USB-IF). + These codes are qualified by the value of + the bDeviceClass field. \n + If the bDeviceClass field is reset to zero, + this field must also be reset to zero. \n + If the bDeviceClass field is not set to FFH, + all values are reserved for assignment by + the USB-IF. + */ + uint8_t bDeviceProtocol; /**< Protocol code (assigned by the USB-IF). + These codes are qualified by the value of + the bDeviceClass and the + bDeviceSubClass fields. If a device + supports class-specific protocols on a + device basis as opposed to an interface + basis, this code identifies the protocols + that the device uses as defined by the + specification of the device class. \n + If this field is reset to zero, the device + does not use class-specific protocols on a + device basis. However, it may use classspecific + protocols on an interface basis. \n + If this field is set to FFH, the device uses a + vendor-specific protocol on a device basis. + */ + uint8_t bMaxPacketSize0; /**< Maximum packet size for endpoint zero + (only 8, 16, 32, or 64 are valid). For HS devices + is fixed to 64. + */ + + uint16_t idVendor; /**< Vendor ID (assigned by the USB-IF). */ + uint16_t idProduct; /**< Product ID (assigned by the manufacturer). */ + uint16_t bcdDevice; /**< Device release number in binary-coded decimal. */ + uint8_t iManufacturer; /**< Index of string descriptor describing manufacturer. */ + uint8_t iProduct; /**< Index of string descriptor describing product. */ + uint8_t iSerialNumber; /**< Index of string descriptor describing the device’s + serial number. + */ + uint8_t bNumConfigurations; /**< Number of possible configurations. */ +} ; +/** USB Standard Device Descriptor */ +typedef struct _USB_DEVICE_DESCRIPTOR USB_DEVICE_DESCRIPTOR; + +/** USB 2.0 Device Qualifier Descriptor */ +PRE_PACK struct POST_PACK _USB_DEVICE_QUALIFIER_DESCRIPTOR +{ + uint8_t bLength; /**< Size of descriptor */ + uint8_t bDescriptorType; /**< Device Qualifier Type */ + uint16_t bcdUSB; /**< USB specification version number (e.g., 0200H for V2.00) */ + uint8_t bDeviceClass; /**< Class Code */ + uint8_t bDeviceSubClass; /**< SubClass Code */ + uint8_t bDeviceProtocol; /**< Protocol Code */ + uint8_t bMaxPacketSize0; /**< Maximum packet size for other speed */ + uint8_t bNumConfigurations; /**< Number of Other-speed Configurations */ + uint8_t bReserved; /**< Reserved for future use, must be zero */ +} ; +/** USB 2.0 Device Qualifier Descriptor */ +typedef struct _USB_DEVICE_QUALIFIER_DESCRIPTOR USB_DEVICE_QUALIFIER_DESCRIPTOR; + +/** USB Standard Configuration Descriptor */ +PRE_PACK struct POST_PACK _USB_CONFIGURATION_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes */ + uint8_t bDescriptorType; /**< CONFIGURATION Descriptor Type*/ + uint16_t wTotalLength; /**< Total length of data returned for this + configuration. Includes the combined length + of all descriptors (configuration, interface, + endpoint, and class- or vendor-specific) + returned for this configuration.*/ + uint8_t bNumInterfaces; /**< Number of interfaces supported by this configuration*/ + uint8_t bConfigurationValue; /**< Value to use as an argument to the + SetConfiguration() request to select this + configuration. */ + uint8_t iConfiguration; /**< Index of string descriptor describing this + configuration*/ + uint8_t bmAttributes; /**< Configuration characteristics \n + D7: Reserved (set to one)\n + D6: Self-powered \n + D5: Remote Wakeup \n + D4...0: Reserved (reset to zero) \n + D7 is reserved and must be set to one for + historical reasons. \n + A device configuration that uses power from + the bus and a local source reports a non-zero + value in bMaxPower to indicate the amount of + bus power required and sets D6. The actual + power source at runtime may be determined + using the GetStatus(DEVICE) request (see + USB 2.0 spec Section 9.4.5). \n + If a device configuration supports remote + wakeup, D5 is set to one.*/ + uint8_t bMaxPower; /**< Maximum power consumption of the USB + device from the bus in this specific + configuration when the device is fully + operational. Expressed in 2 mA units + (i.e., 50 = 100 mA). \n + Note: A device configuration reports whether + the configuration is bus-powered or selfpowered. + Device status reports whether the + device is currently self-powered. If a device is + disconnected from its external power source, it + updates device status to indicate that it is no + longer self-powered. \n + A device may not increase its power draw + from the bus, when it loses its external power + source, beyond the amount reported by its + configuration. \n + If a device can continue to operate when + disconnected from its external power source, it + continues to do so. If the device cannot + continue to operate, it fails operations it can + no longer support. The USB System Software + may determine the cause of the failure by + checking the status and noting the loss of the + device’s power source.*/ +} ; +/** USB Standard Configuration Descriptor */ +typedef struct _USB_CONFIGURATION_DESCRIPTOR USB_CONFIGURATION_DESCRIPTOR; + +/** USB Standard Interface Association Descriptor */ +PRE_PACK struct POST_PACK _USB_IAD_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes*/ + uint8_t bDescriptorType; /**< INTERFACE ASSOCIATION Descriptor Type*/ + uint8_t bFirstInterface; /**< Interface number of the first interface that is + associated with this function.*/ + uint8_t bInterfaceCount; /**< Number of contiguous interfaces that are + associated with this function. */ + uint8_t bFunctionClass; /**< Class code (assigned by USB-IF). \n + A value of zero is not allowed in this descriptor. + If this field is FFH, the function class is vendorspecific. + All other values are reserved for assignment by + the USB-IF.*/ + uint8_t bFunctionSubClass; /**< Subclass code (assigned by USB-IF). \n + If the bFunctionClass field is not set to FFH all + values are reserved for assignment by the USBIF.*/ + uint8_t bFunctionProtocol; /**< Protocol code (assigned by the USB). \n + These codes are qualified by the values of the + bFunctionClass and bFunctionSubClass fields.*/ + uint8_t iFunction; /**< Index of string descriptor describing this function.*/ +} ; +/** USB Standard Interface Association Descriptor */ +typedef struct _USB_IAD_DESCRIPTOR USB_IAD_DESCRIPTOR; + +/** USB Standard Interface Descriptor */ +PRE_PACK struct POST_PACK _USB_INTERFACE_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes*/ + uint8_t bDescriptorType; /**< INTERFACE Descriptor Type*/ + uint8_t bInterfaceNumber; /**< Number of this interface. Zero-based + value identifying the index in the array of + concurrent interfaces supported by this + configuration.*/ + uint8_t bAlternateSetting; /**< Value used to select this alternate setting + for the interface identified in the prior field*/ + uint8_t bNumEndpoints; /**< Number of endpoints used by this + interface (excluding endpoint zero). If this + value is zero, this interface only uses the + Default Control Pipe.*/ + uint8_t bInterfaceClass; /**< Class code (assigned by the USB-IF). \n + A value of zero is reserved for future + standardization. \n + If this field is set to FFH, the interface + class is vendor-specific. \n + All other values are reserved for + assignment by the USB-IF.*/ + uint8_t bInterfaceSubClass; /**< Subclass code (assigned by the USB-IF). \n + These codes are qualified by the value of + the bInterfaceClass field. \n + If the bInterfaceClass field is reset to zero, + this field must also be reset to zero. \n + If the bInterfaceClass field is not set to + FFH, all values are reserved for + assignment by the USB-IF.*/ + uint8_t bInterfaceProtocol; /**< Protocol code (assigned by the USB). \n + These codes are qualified by the value of + the bInterfaceClass and the + bInterfaceSubClass fields. If an interface + supports class-specific requests, this code + identifies the protocols that the device + uses as defined by the specification of the + device class. \n + If this field is reset to zero, the device + does not use a class-specific protocol on + this interface. \n + If this field is set to FFH, the device uses + a vendor-specific protocol for this + interface.*/ + uint8_t iInterface; /**< Index of string descriptor describing this interface*/ +} ; +/** USB Standard Interface Descriptor */ +typedef struct _USB_INTERFACE_DESCRIPTOR USB_INTERFACE_DESCRIPTOR; + +/** USB Standard Endpoint Descriptor */ +PRE_PACK struct POST_PACK _USB_ENDPOINT_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes*/ + uint8_t bDescriptorType; /**< ENDPOINT Descriptor Type*/ + uint8_t bEndpointAddress; /**< The address of the endpoint on the USB device + described by this descriptor. The address is + encoded as follows: \n + Bit 3...0: The endpoint number \n + Bit 6...4: Reserved, reset to zero \n + Bit 7: Direction, ignored for control endpoints + 0 = OUT endpoint + 1 = IN endpoint. \n \sa USBD_ENDPOINT_ADR_Type*/ + uint8_t bmAttributes; /**< This field describes the endpoint’s attributes when it is + configured using the bConfigurationValue. \n + Bits 1..0: Transfer Type + \li 00 = Control + \li 01 = Isochronous + \li 10 = Bulk + \li 11 = Interrupt \n + If not an isochronous endpoint, bits 5..2 are reserved + and must be set to zero. If isochronous, they are + defined as follows: \n + Bits 3..2: Synchronization Type + \li 00 = No Synchronization + \li 01 = Asynchronous + \li 10 = Adaptive + \li 11 = Synchronous \n + Bits 5..4: Usage Type + \li 00 = Data endpoint + \li 01 = Feedback endpoint + \li 10 = Implicit feedback Data endpoint + \li 11 = Reserved \n + Refer to Chapter 5 of USB 2.0 specification for more information. \n + All other bits are reserved and must be reset to zero. + Reserved bits must be ignored by the host. + \n \sa USBD_EP_ATTR_Type*/ + uint16_t wMaxPacketSize; /**< Maximum packet size this endpoint is capable of + sending or receiving when this configuration is + selected. \n + For isochronous endpoints, this value is used to + reserve the bus time in the schedule, required for the + per-(micro)frame data payloads. The pipe may, on an + ongoing basis, actually use less bandwidth than that + reserved. The device reports, if necessary, the actual + bandwidth used via its normal, non-USB defined + mechanisms. \n + For all endpoints, bits 10..0 specify the maximum + packet size (in bytes). \n + For high-speed isochronous and interrupt endpoints: \n + Bits 12..11 specify the number of additional transaction + opportunities per microframe: \n + \li 00 = None (1 transaction per microframe) + \li 01 = 1 additional (2 per microframe) + \li 10 = 2 additional (3 per microframe) + \li 11 = Reserved \n + Bits 15..13 are reserved and must be set to zero.*/ + uint8_t bInterval; /**< Interval for polling endpoint for data transfers. + Expressed in frames or microframes depending on the + device operating speed (i.e., either 1 millisecond or + 125 µs units). + \li For full-/high-speed isochronous endpoints, this value + must be in the range from 1 to 16. The bInterval value + is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a + bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). + \li For full-/low-speed interrupt endpoints, the value of + this field may be from 1 to 255. + \li For high-speed interrupt endpoints, the bInterval value + is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a + bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value + must be from 1 to 16. + \li For high-speed bulk/control OUT endpoints, the + bInterval must specify the maximum NAK rate of the + endpoint. A value of 0 indicates the endpoint never + NAKs. Other values indicate at most 1 NAK each + bInterval number of microframes. This value must be + in the range from 0 to 255. \n + Refer to Chapter 5 of USB 2.0 specification for more information. + */ +} ; +/** USB Standard Endpoint Descriptor */ +typedef struct _USB_ENDPOINT_DESCRIPTOR USB_ENDPOINT_DESCRIPTOR; + +/** USB String Descriptor */ +PRE_PACK struct POST_PACK _USB_STRING_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes*/ + uint8_t bDescriptorType; /**< STRING Descriptor Type*/ + uint16_t bString/*[]*/; /**< UNICODE encoded string */ +} ; +/** USB String Descriptor */ +typedef struct _USB_STRING_DESCRIPTOR USB_STRING_DESCRIPTOR; + +/** USB Common Descriptor */ +PRE_PACK struct POST_PACK _USB_COMMON_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes*/ + uint8_t bDescriptorType; /**< Descriptor Type*/ +} ; +/** USB Common Descriptor */ +typedef struct _USB_COMMON_DESCRIPTOR USB_COMMON_DESCRIPTOR; + +/** USB Other Speed Configuration */ +PRE_PACK struct POST_PACK _USB_OTHER_SPEED_CONFIGURATION +{ + uint8_t bLength; /**< Size of descriptor*/ + uint8_t bDescriptorType; /**< Other_speed_Configuration Type*/ + uint16_t wTotalLength; /**< Total length of data returned*/ + uint8_t bNumInterfaces; /**< Number of interfaces supported by this speed configuration*/ + uint8_t bConfigurationValue; /**< Value to use to select configuration*/ + uint8_t IConfiguration; /**< Index of string descriptor*/ + uint8_t bmAttributes; /**< Same as Configuration descriptor*/ + uint8_t bMaxPower; /**< Same as Configuration descriptor*/ +} ; +/** USB Other Speed Configuration */ +typedef struct _USB_OTHER_SPEED_CONFIGURATION USB_OTHER_SPEED_CONFIGURATION; + +/** \ingroup USBD_Core + * USB device stack/module handle. + */ +typedef void* USBD_HANDLE_T; + +#define WBVAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF) +#define B3VAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF),(((x) >> 16) & 0xFF) + +#define USB_DEVICE_DESC_SIZE (sizeof(USB_DEVICE_DESCRIPTOR)) +#define USB_CONFIGURATION_DESC_SIZE (sizeof(USB_CONFIGURATION_DESCRIPTOR)) +#define USB_INTERFACE_DESC_SIZE (sizeof(USB_INTERFACE_DESCRIPTOR)) +#define USB_INTERFACE_ASSOC_DESC_SIZE (sizeof(USB_IAD_DESCRIPTOR)) +#define USB_ENDPOINT_DESC_SIZE (sizeof(USB_ENDPOINT_DESCRIPTOR)) +#define USB_DEVICE_QUALI_SIZE (sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)) +#define USB_OTHER_SPEED_CONF_SIZE (sizeof(USB_OTHER_SPEED_CONFIGURATION)) + +/** @}*/ + +#endif /* __USBD_H__ */ diff --git a/inc/usbd/usbd_audio.h b/inc/usbd/usbd_audio.h new file mode 100644 index 0000000..4b8e885 --- /dev/null +++ b/inc/usbd/usbd_audio.h @@ -0,0 +1,377 @@ +/*********************************************************************** +* $Id:: mw_usbd_audio.h 165 2011-04-14 17:41:11Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Audio Device Class Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __AUDIO_H__ +#define __AUDIO_H__ + + +/* Audio Interface Subclass Codes */ +#define AUDIO_SUBCLASS_UNDEFINED 0x00 +#define AUDIO_SUBCLASS_AUDIOCONTROL 0x01 +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02 +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03 + +/* Audio Interface Protocol Codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00 + + +/* Audio Descriptor Types */ +#define AUDIO_UNDEFINED_DESCRIPTOR_TYPE 0x20 +#define AUDIO_DEVICE_DESCRIPTOR_TYPE 0x21 +#define AUDIO_CONFIGURATION_DESCRIPTOR_TYPE 0x22 +#define AUDIO_STRING_DESCRIPTOR_TYPE 0x23 +#define AUDIO_INTERFACE_DESCRIPTOR_TYPE 0x24 +#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE 0x25 + + +/* Audio Control Interface Descriptor Subtypes */ +#define AUDIO_CONTROL_UNDEFINED 0x00 +#define AUDIO_CONTROL_HEADER 0x01 +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02 +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03 +#define AUDIO_CONTROL_MIXER_UNIT 0x04 +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05 +#define AUDIO_CONTROL_FEATURE_UNIT 0x06 +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07 +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08 + +/* Audio Streaming Interface Descriptor Subtypes */ +#define AUDIO_STREAMING_UNDEFINED 0x00 +#define AUDIO_STREAMING_GENERAL 0x01 +#define AUDIO_STREAMING_FORMAT_TYPE 0x02 +#define AUDIO_STREAMING_FORMAT_SPECIFIC 0x03 + +/* Audio Endpoint Descriptor Subtypes */ +#define AUDIO_ENDPOINT_UNDEFINED 0x00 +#define AUDIO_ENDPOINT_GENERAL 0x01 + + +/* Audio Descriptor Sizes */ +#define AUDIO_CONTROL_INTERFACE_DESC_SZ(n) 0x08+n +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07 +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0C +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09 +#define AUDIO_MIXER_UNIT_DESC_SZ(p,n) 0x0A+p+n +#define AUDIO_SELECTOR_UNIT_DESC_SZ(p) 0x06+p +#define AUDIO_FEATURE_UNIT_DESC_SZ(ch,n) 0x07+(ch+1)*n +#define AUDIO_PROCESSING_UNIT_DESC_SZ(p,n,x) 0x0D+p+n+x +#define AUDIO_EXTENSION_UNIT_DESC_SZ(p,n) 0x0D+p+n +#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE 0x09 +#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE 0x07 + + +/* Audio Processing Unit Process Types */ +#define AUDIO_UNDEFINED_PROCESS 0x00 +#define AUDIO_UP_DOWN_MIX_PROCESS 0x01 +#define AUDIO_DOLBY_PROLOGIC_PROCESS 0x02 +#define AUDIO_3D_STEREO_PROCESS 0x03 +#define AUDIO_REVERBERATION_PROCESS 0x04 +#define AUDIO_CHORUS_PROCESS 0x05 +#define AUDIO_DYN_RANGE_COMP_PROCESS 0x06 + + +/* Audio Request Codes */ +#define AUDIO_REQUEST_UNDEFINED 0x00 +#define AUDIO_REQUEST_SET_CUR 0x01 +#define AUDIO_REQUEST_GET_CUR 0x81 +#define AUDIO_REQUEST_SET_MIN 0x02 +#define AUDIO_REQUEST_GET_MIN 0x82 +#define AUDIO_REQUEST_SET_MAX 0x03 +#define AUDIO_REQUEST_GET_MAX 0x83 +#define AUDIO_REQUEST_SET_RES 0x04 +#define AUDIO_REQUEST_GET_RES 0x84 +#define AUDIO_REQUEST_SET_MEM 0x05 +#define AUDIO_REQUEST_GET_MEM 0x85 +#define AUDIO_REQUEST_GET_STAT 0xFF + + +/* Audio Control Selector Codes */ +#define AUDIO_CONTROL_UNDEFINED 0x00 /* Common Selector */ + +/* Terminal Control Selectors */ +#define AUDIO_COPY_PROTECT_CONTROL 0x01 + +/* Feature Unit Control Selectors */ +#define AUDIO_MUTE_CONTROL 0x01 +#define AUDIO_VOLUME_CONTROL 0x02 +#define AUDIO_BASS_CONTROL 0x03 +#define AUDIO_MID_CONTROL 0x04 +#define AUDIO_TREBLE_CONTROL 0x05 +#define AUDIO_GRAPHIC_EQUALIZER_CONTROL 0x06 +#define AUDIO_AUTOMATIC_GAIN_CONTROL 0x07 +#define AUDIO_DELAY_CONTROL 0x08 +#define AUDIO_BASS_BOOST_CONTROL 0x09 +#define AUDIO_LOUDNESS_CONTROL 0x0A + +/* Processing Unit Control Selectors: */ +#define AUDIO_ENABLE_CONTROL 0x01 /* Common Selector */ +#define AUDIO_MODE_SELECT_CONTROL 0x02 /* Common Selector */ + +/* - Up/Down-mix Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +/* AUDIO_MODE_SELECT_CONTROL 0x02 Common Selector */ + +/* - Dolby Prologic Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +/* AUDIO_MODE_SELECT_CONTROL 0x02 Common Selector */ + +/* - 3D Stereo Extender Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +#define AUDIO_SPACIOUSNESS_CONTROL 0x02 + +/* - Reverberation Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +#define AUDIO_REVERB_LEVEL_CONTROL 0x02 +#define AUDIO_REVERB_TIME_CONTROL 0x03 +#define AUDIO_REVERB_FEEDBACK_CONTROL 0x04 + +/* - Chorus Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +#define AUDIO_CHORUS_LEVEL_CONTROL 0x02 +#define AUDIO_SHORUS_RATE_CONTROL 0x03 +#define AUDIO_CHORUS_DEPTH_CONTROL 0x04 + +/* - Dynamic Range Compressor Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +#define AUDIO_COMPRESSION_RATE_CONTROL 0x02 +#define AUDIO_MAX_AMPL_CONTROL 0x03 +#define AUDIO_THRESHOLD_CONTROL 0x04 +#define AUDIO_ATTACK_TIME_CONTROL 0x05 +#define AUDIO_RELEASE_TIME_CONTROL 0x06 + +/* Extension Unit Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ + +/* Endpoint Control Selectors */ +#define AUDIO_SAMPLING_FREQ_CONTROL 0x01 +#define AUDIO_PITCH_CONTROL 0x02 + + +/* Audio Format Specific Control Selectors */ + +/* MPEG Control Selectors */ +#define AUDIO_MPEG_CONTROL_UNDEFINED 0x00 +#define AUDIO_MPEG_DUAL_CHANNEL_CONTROL 0x01 +#define AUDIO_MPEG_SECOND_STEREO_CONTROL 0x02 +#define AUDIO_MPEG_MULTILINGUAL_CONTROL 0x03 +#define AUDIO_MPEG_DYN_RANGE_CONTROL 0x04 +#define AUDIO_MPEG_SCALING_CONTROL 0x05 +#define AUDIO_MPEG_HILO_SCALING_CONTROL 0x06 + +/* AC-3 Control Selectors */ +#define AUDIO_AC3_CONTROL_UNDEFINED 0x00 +#define AUDIO_AC3_MODE_CONTROL 0x01 +#define AUDIO_AC3_DYN_RANGE_CONTROL 0x02 +#define AUDIO_AC3_SCALING_CONTROL 0x03 +#define AUDIO_AC3_HILO_SCALING_CONTROL 0x04 + + +/* Audio Format Types */ +#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 +#define AUDIO_FORMAT_TYPE_I 0x01 +#define AUDIO_FORMAT_TYPE_II 0x02 +#define AUDIO_FORMAT_TYPE_III 0x03 + + +/* Audio Format Type Descriptor Sizes */ +#define AUDIO_FORMAT_TYPE_I_DESC_SZ(n) 0x08+(n*3) +#define AUDIO_FORMAT_TYPE_II_DESC_SZ(n) 0x09+(n*3) +#define AUDIO_FORMAT_TYPE_III_DESC_SZ(n) 0x08+(n*3) +#define AUDIO_FORMAT_MPEG_DESC_SIZE 0x09 +#define AUDIO_FORMAT_AC3_DESC_SIZE 0x0A + + +/* Audio Data Format Codes */ + +/* Audio Data Format Type I Codes */ +#define AUDIO_FORMAT_TYPE_I_UNDEFINED 0x0000 +#define AUDIO_FORMAT_PCM 0x0001 +#define AUDIO_FORMAT_PCM8 0x0002 +#define AUDIO_FORMAT_IEEE_FLOAT 0x0003 +#define AUDIO_FORMAT_ALAW 0x0004 +#define AUDIO_FORMAT_MULAW 0x0005 + +/* Audio Data Format Type II Codes */ +#define AUDIO_FORMAT_TYPE_II_UNDEFINED 0x1000 +#define AUDIO_FORMAT_MPEG 0x1001 +#define AUDIO_FORMAT_AC3 0x1002 + +/* Audio Data Format Type III Codes */ +#define AUDIO_FORMAT_TYPE_III_UNDEFINED 0x2000 +#define AUDIO_FORMAT_IEC1937_AC3 0x2001 +#define AUDIO_FORMAT_IEC1937_MPEG1_L1 0x2002 +#define AUDIO_FORMAT_IEC1937_MPEG1_L2_3 0x2003 +#define AUDIO_FORMAT_IEC1937_MPEG2_NOEXT 0x2003 +#define AUDIO_FORMAT_IEC1937_MPEG2_EXT 0x2004 +#define AUDIO_FORMAT_IEC1937_MPEG2_L1_LS 0x2005 +#define AUDIO_FORMAT_IEC1937_MPEG2_L2_3 0x2006 + + +/* Predefined Audio Channel Configuration Bits */ +#define AUDIO_CHANNEL_M 0x0000 /* Mono */ +#define AUDIO_CHANNEL_L 0x0001 /* Left Front */ +#define AUDIO_CHANNEL_R 0x0002 /* Right Front */ +#define AUDIO_CHANNEL_C 0x0004 /* Center Front */ +#define AUDIO_CHANNEL_LFE 0x0008 /* Low Freq. Enhance. */ +#define AUDIO_CHANNEL_LS 0x0010 /* Left Surround */ +#define AUDIO_CHANNEL_RS 0x0020 /* Right Surround */ +#define AUDIO_CHANNEL_LC 0x0040 /* Left of Center */ +#define AUDIO_CHANNEL_RC 0x0080 /* Right of Center */ +#define AUDIO_CHANNEL_S 0x0100 /* Surround */ +#define AUDIO_CHANNEL_SL 0x0200 /* Side Left */ +#define AUDIO_CHANNEL_SR 0x0400 /* Side Right */ +#define AUDIO_CHANNEL_T 0x0800 /* Top */ + + +/* Feature Unit Control Bits */ +#define AUDIO_CONTROL_MUTE 0x0001 +#define AUDIO_CONTROL_VOLUME 0x0002 +#define AUDIO_CONTROL_BASS 0x0004 +#define AUDIO_CONTROL_MID 0x0008 +#define AUDIO_CONTROL_TREBLE 0x0010 +#define AUDIO_CONTROL_GRAPHIC_EQUALIZER 0x0020 +#define AUDIO_CONTROL_AUTOMATIC_GAIN 0x0040 +#define AUDIO_CONTROL_DEALY 0x0080 +#define AUDIO_CONTROL_BASS_BOOST 0x0100 +#define AUDIO_CONTROL_LOUDNESS 0x0200 + +/* Processing Unit Control Bits: */ +#define AUDIO_CONTROL_ENABLE 0x0001 /* Common Bit */ +#define AUDIO_CONTROL_MODE_SELECT 0x0002 /* Common Bit */ + +/* - Up/Down-mix Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +/* AUDIO_CONTROL_MODE_SELECT 0x0002 Common Bit */ + +/* - Dolby Prologic Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +/* AUDIO_CONTROL_MODE_SELECT 0x0002 Common Bit */ + +/* - 3D Stereo Extender Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +#define AUDIO_CONTROL_SPACIOUSNESS 0x0002 + +/* - Reverberation Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +#define AUDIO_CONTROL_REVERB_TYPE 0x0002 +#define AUDIO_CONTROL_REVERB_LEVEL 0x0004 +#define AUDIO_CONTROL_REVERB_TIME 0x0008 +#define AUDIO_CONTROL_REVERB_FEEDBACK 0x0010 + +/* - Chorus Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +#define AUDIO_CONTROL_CHORUS_LEVEL 0x0002 +#define AUDIO_CONTROL_SHORUS_RATE 0x0004 +#define AUDIO_CONTROL_CHORUS_DEPTH 0x0008 + +/* - Dynamic Range Compressor Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +#define AUDIO_CONTROL_COMPRESSION_RATE 0x0002 +#define AUDIO_CONTROL_MAX_AMPL 0x0004 +#define AUDIO_CONTROL_THRESHOLD 0x0008 +#define AUDIO_CONTROL_ATTACK_TIME 0x0010 +#define AUDIO_CONTROL_RELEASE_TIME 0x0020 + +/* Extension Unit Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ + +/* Endpoint Control Bits */ +#define AUDIO_CONTROL_SAMPLING_FREQ 0x01 +#define AUDIO_CONTROL_PITCH 0x02 +#define AUDIO_MAX_PACKETS_ONLY 0x80 + + +/* Audio Terminal Types */ + +/* USB Terminal Types */ +#define AUDIO_TERMINAL_USB_UNDEFINED 0x0100 +#define AUDIO_TERMINAL_USB_STREAMING 0x0101 +#define AUDIO_TERMINAL_USB_VENDOR_SPECIFIC 0x01FF + +/* Input Terminal Types */ +#define AUDIO_TERMINAL_INPUT_UNDEFINED 0x0200 +#define AUDIO_TERMINAL_MICROPHONE 0x0201 +#define AUDIO_TERMINAL_DESKTOP_MICROPHONE 0x0202 +#define AUDIO_TERMINAL_PERSONAL_MICROPHONE 0x0203 +#define AUDIO_TERMINAL_OMNI_DIR_MICROPHONE 0x0204 +#define AUDIO_TERMINAL_MICROPHONE_ARRAY 0x0205 +#define AUDIO_TERMINAL_PROCESSING_MIC_ARRAY 0x0206 + +/* Output Terminal Types */ +#define AUDIO_TERMINAL_OUTPUT_UNDEFINED 0x0300 +#define AUDIO_TERMINAL_SPEAKER 0x0301 +#define AUDIO_TERMINAL_HEADPHONES 0x0302 +#define AUDIO_TERMINAL_HEAD_MOUNTED_AUDIO 0x0303 +#define AUDIO_TERMINAL_DESKTOP_SPEAKER 0x0304 +#define AUDIO_TERMINAL_ROOM_SPEAKER 0x0305 +#define AUDIO_TERMINAL_COMMUNICATION_SPEAKER 0x0306 +#define AUDIO_TERMINAL_LOW_FREQ_SPEAKER 0x0307 + +/* Bi-directional Terminal Types */ +#define AUDIO_TERMINAL_BIDIRECTIONAL_UNDEFINED 0x0400 +#define AUDIO_TERMINAL_HANDSET 0x0401 +#define AUDIO_TERMINAL_HEAD_MOUNTED_HANDSET 0x0402 +#define AUDIO_TERMINAL_SPEAKERPHONE 0x0403 +#define AUDIO_TERMINAL_SPEAKERPHONE_ECHOSUPRESS 0x0404 +#define AUDIO_TERMINAL_SPEAKERPHONE_ECHOCANCEL 0x0405 + +/* Telephony Terminal Types */ +#define AUDIO_TERMINAL_TELEPHONY_UNDEFINED 0x0500 +#define AUDIO_TERMINAL_PHONE_LINE 0x0501 +#define AUDIO_TERMINAL_TELEPHONE 0x0502 +#define AUDIO_TERMINAL_DOWN_LINE_PHONE 0x0503 + +/* External Terminal Types */ +#define AUDIO_TERMINAL_EXTERNAL_UNDEFINED 0x0600 +#define AUDIO_TERMINAL_ANALOG_CONNECTOR 0x0601 +#define AUDIO_TERMINAL_DIGITAL_AUDIO_INTERFACE 0x0602 +#define AUDIO_TERMINAL_LINE_CONNECTOR 0x0603 +#define AUDIO_TERMINAL_LEGACY_AUDIO_CONNECTOR 0x0604 +#define AUDIO_TERMINAL_SPDIF_INTERFACE 0x0605 +#define AUDIO_TERMINAL_1394_DA_STREAM 0x0606 +#define AUDIO_TERMINAL_1394_DA_STREAM_TRACK 0x0607 + +/* Embedded Function Terminal Types */ +#define AUDIO_TERMINAL_EMBEDDED_UNDEFINED 0x0700 +#define AUDIO_TERMINAL_CALIBRATION_NOISE 0x0701 +#define AUDIO_TERMINAL_EQUALIZATION_NOISE 0x0702 +#define AUDIO_TERMINAL_CD_PLAYER 0x0703 +#define AUDIO_TERMINAL_DAT 0x0704 +#define AUDIO_TERMINAL_DCC 0x0705 +#define AUDIO_TERMINAL_MINI_DISK 0x0706 +#define AUDIO_TERMINAL_ANALOG_TAPE 0x0707 +#define AUDIO_TERMINAL_PHONOGRAPH 0x0708 +#define AUDIO_TERMINAL_VCR_AUDIO 0x0709 +#define AUDIO_TERMINAL_VIDEO_DISC_AUDIO 0x070A +#define AUDIO_TERMINAL_DVD_AUDIO 0x070B +#define AUDIO_TERMINAL_TV_TUNER_AUDIO 0x070C +#define AUDIO_TERMINAL_SATELLITE_RECEIVER_AUDIO 0x070D +#define AUDIO_TERMINAL_CABLE_TUNER_AUDIO 0x070E +#define AUDIO_TERMINAL_DSS_AUDIO 0x070F +#define AUDIO_TERMINAL_RADIO_RECEIVER 0x0710 +#define AUDIO_TERMINAL_RADIO_TRANSMITTER 0x0711 +#define AUDIO_TERMINAL_MULTI_TRACK_RECORDER 0x0712 +#define AUDIO_TERMINAL_SYNTHESIZER 0x0713 + + +#endif /* __AUDIO_H__ */ diff --git a/inc/usbd/usbd_cdc.h b/inc/usbd/usbd_cdc.h new file mode 100644 index 0000000..010e941 --- /dev/null +++ b/inc/usbd/usbd_cdc.h @@ -0,0 +1,249 @@ +/*********************************************************************** +* $Id:: mw_usbd_cdc.h 165 2011-04-14 17:41:11Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Communication Device Class User module Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __CDC_H +#define __CDC_H + +#include "usbd.h" + +/*---------------------------------------------------------------------------- + * Definitions based on usbcdc11.pdf (www.usb.org) + *---------------------------------------------------------------------------*/ +/* Communication device class specification version 1.10 */ +#define CDC_V1_10 0x0110 + +/* Communication interface class code */ +/* (usbcdc11.pdf, 4.2, Table 15) */ +#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02 + +/* Communication interface class subclass codes */ +/* (usbcdc11.pdf, 4.3, Table 16) */ +#define CDC_DIRECT_LINE_CONTROL_MODEL 0x01 +#define CDC_ABSTRACT_CONTROL_MODEL 0x02 +#define CDC_TELEPHONE_CONTROL_MODEL 0x03 +#define CDC_MULTI_CHANNEL_CONTROL_MODEL 0x04 +#define CDC_CAPI_CONTROL_MODEL 0x05 +#define CDC_ETHERNET_NETWORKING_CONTROL_MODEL 0x06 +#define CDC_ATM_NETWORKING_CONTROL_MODEL 0x07 + +/* Communication interface class control protocol codes */ +/* (usbcdc11.pdf, 4.4, Table 17) */ +#define CDC_PROTOCOL_COMMON_AT_COMMANDS 0x01 + +/* Data interface class code */ +/* (usbcdc11.pdf, 4.5, Table 18) */ +#define CDC_DATA_INTERFACE_CLASS 0x0A + +/* Data interface class protocol codes */ +/* (usbcdc11.pdf, 4.7, Table 19) */ +#define CDC_PROTOCOL_ISDN_BRI 0x30 +#define CDC_PROTOCOL_HDLC 0x31 +#define CDC_PROTOCOL_TRANSPARENT 0x32 +#define CDC_PROTOCOL_Q921_MANAGEMENT 0x50 +#define CDC_PROTOCOL_Q921_DATA_LINK 0x51 +#define CDC_PROTOCOL_Q921_MULTIPLEXOR 0x52 +#define CDC_PROTOCOL_V42 0x90 +#define CDC_PROTOCOL_EURO_ISDN 0x91 +#define CDC_PROTOCOL_V24_RATE_ADAPTATION 0x92 +#define CDC_PROTOCOL_CAPI 0x93 +#define CDC_PROTOCOL_HOST_BASED_DRIVER 0xFD +#define CDC_PROTOCOL_DESCRIBED_IN_PUFD 0xFE + +/* Type values for bDescriptorType field of functional descriptors */ +/* (usbcdc11.pdf, 5.2.3, Table 24) */ +#define CDC_CS_INTERFACE 0x24 +#define CDC_CS_ENDPOINT 0x25 + +/* Type values for bDescriptorSubtype field of functional descriptors */ +/* (usbcdc11.pdf, 5.2.3, Table 25) */ +#define CDC_HEADER 0x00 +#define CDC_CALL_MANAGEMENT 0x01 +#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02 +#define CDC_DIRECT_LINE_MANAGEMENT 0x03 +#define CDC_TELEPHONE_RINGER 0x04 +#define CDC_REPORTING_CAPABILITIES 0x05 +#define CDC_UNION 0x06 +#define CDC_COUNTRY_SELECTION 0x07 +#define CDC_TELEPHONE_OPERATIONAL_MODES 0x08 +#define CDC_USB_TERMINAL 0x09 +#define CDC_NETWORK_CHANNEL 0x0A +#define CDC_PROTOCOL_UNIT 0x0B +#define CDC_EXTENSION_UNIT 0x0C +#define CDC_MULTI_CHANNEL_MANAGEMENT 0x0D +#define CDC_CAPI_CONTROL_MANAGEMENT 0x0E +#define CDC_ETHERNET_NETWORKING 0x0F +#define CDC_ATM_NETWORKING 0x10 + +/* CDC class-specific request codes */ +/* (usbcdc11.pdf, 6.2, Table 46) */ +/* see Table 45 for info about the specific requests. */ +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 +#define CDC_SET_COMM_FEATURE 0x02 +#define CDC_GET_COMM_FEATURE 0x03 +#define CDC_CLEAR_COMM_FEATURE 0x04 +#define CDC_SET_AUX_LINE_STATE 0x10 +#define CDC_SET_HOOK_STATE 0x11 +#define CDC_PULSE_SETUP 0x12 +#define CDC_SEND_PULSE 0x13 +#define CDC_SET_PULSE_TIME 0x14 +#define CDC_RING_AUX_JACK 0x15 +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 +#define CDC_SET_RINGER_PARMS 0x30 +#define CDC_GET_RINGER_PARMS 0x31 +#define CDC_SET_OPERATION_PARMS 0x32 +#define CDC_GET_OPERATION_PARMS 0x33 +#define CDC_SET_LINE_PARMS 0x34 +#define CDC_GET_LINE_PARMS 0x35 +#define CDC_DIAL_DIGITS 0x36 +#define CDC_SET_UNIT_PARAMETER 0x37 +#define CDC_GET_UNIT_PARAMETER 0x38 +#define CDC_CLEAR_UNIT_PARAMETER 0x39 +#define CDC_GET_PROFILE 0x3A +#define CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 +#define CDC_SET_ETHERNET_PMP_FILTER 0x41 +#define CDC_GET_ETHERNET_PMP_FILTER 0x42 +#define CDC_SET_ETHERNET_PACKET_FILTER 0x43 +#define CDC_GET_ETHERNET_STATISTIC 0x44 +#define CDC_SET_ATM_DATA_FORMAT 0x50 +#define CDC_GET_ATM_DEVICE_STATISTICS 0x51 +#define CDC_SET_ATM_DEFAULT_VC 0x52 +#define CDC_GET_ATM_VC_STATISTICS 0x53 + +/* Communication feature selector codes */ +/* (usbcdc11.pdf, 6.2.2..6.2.4, Table 47) */ +#define CDC_ABSTRACT_STATE 0x01 +#define CDC_COUNTRY_SETTING 0x02 + +/* Feature Status returned for ABSTRACT_STATE Selector */ +/* (usbcdc11.pdf, 6.2.3, Table 48) */ +#define CDC_IDLE_SETTING (1 << 0) +#define CDC_DATA_MULTPLEXED_STATE (1 << 1) + + +/* Control signal bitmap values for the SetControlLineState request */ +/* (usbcdc11.pdf, 6.2.14, Table 51) */ +#define CDC_DTE_PRESENT (1 << 0) +#define CDC_ACTIVATE_CARRIER (1 << 1) + +/* CDC class-specific notification codes */ +/* (usbcdc11.pdf, 6.3, Table 68) */ +/* see Table 67 for Info about class-specific notifications */ +#define CDC_NOTIFICATION_NETWORK_CONNECTION 0x00 +#define CDC_RESPONSE_AVAILABLE 0x01 +#define CDC_AUX_JACK_HOOK_STATE 0x08 +#define CDC_RING_DETECT 0x09 +#define CDC_NOTIFICATION_SERIAL_STATE 0x20 +#define CDC_CALL_STATE_CHANGE 0x28 +#define CDC_LINE_STATE_CHANGE 0x29 +#define CDC_CONNECTION_SPEED_CHANGE 0x2A + +/* UART state bitmap values (Serial state notification). */ +/* (usbcdc11.pdf, 6.3.5, Table 69) */ +#define CDC_SERIAL_STATE_OVERRUN (1 << 6) /* receive data overrun error has occurred */ +#define CDC_SERIAL_STATE_PARITY (1 << 5) /* parity error has occurred */ +#define CDC_SERIAL_STATE_FRAMING (1 << 4) /* framing error has occurred */ +#define CDC_SERIAL_STATE_RING (1 << 3) /* state of ring signal detection */ +#define CDC_SERIAL_STATE_BREAK (1 << 2) /* state of break detection */ +#define CDC_SERIAL_STATE_TX_CARRIER (1 << 1) /* state of transmission carrier */ +#define CDC_SERIAL_STATE_RX_CARRIER (1 << 0) /* state of receiver carrier */ + + +/*---------------------------------------------------------------------------- + * Structures based on usbcdc11.pdf (www.usb.org) + *---------------------------------------------------------------------------*/ + +/* Header functional descriptor */ +/* (usbcdc11.pdf, 5.2.3.1) */ +/* This header must precede any list of class-specific descriptors. */ +PRE_PACK struct POST_PACK _CDC_HEADER_DESCRIPTOR{ + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* Header functional descriptor subtype */ + uint16_t bcdCDC; /* USB CDC specification release version */ +}; +typedef struct _CDC_HEADER_DESCRIPTOR CDC_HEADER_DESCRIPTOR; + +/* Call management functional descriptor */ +/* (usbcdc11.pdf, 5.2.3.2) */ +/* Describes the processing of calls for the communication class interface. */ +PRE_PACK struct POST_PACK _CDC_CALL_MANAGEMENT_DESCRIPTOR { + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* call management functional descriptor subtype */ + uint8_t bmCapabilities; /* capabilities that this configuration supports */ + uint8_t bDataInterface; /* interface number of the data class interface used for call management (optional) */ +}; +typedef struct _CDC_CALL_MANAGEMENT_DESCRIPTOR CDC_CALL_MANAGEMENT_DESCRIPTOR; + +/* Abstract control management functional descriptor */ +/* (usbcdc11.pdf, 5.2.3.3) */ +/* Describes the command supported by the communication interface class with the Abstract Control Model subclass code. */ +PRE_PACK struct POST_PACK _CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR { + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* abstract control management functional descriptor subtype */ + uint8_t bmCapabilities; /* capabilities supported by this configuration */ +}; +typedef struct _CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR; + +/* Union functional descriptors */ +/* (usbcdc11.pdf, 5.2.3.8) */ +/* Describes the relationship between a group of interfaces that can be considered to form a functional unit. */ +PRE_PACK struct POST_PACK _CDC_UNION_DESCRIPTOR { + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* union functional descriptor subtype */ + uint8_t bMasterInterface; /* interface number designated as master */ +}; +typedef struct _CDC_UNION_DESCRIPTOR CDC_UNION_DESCRIPTOR; + +/* Union functional descriptors with one slave interface */ +/* (usbcdc11.pdf, 5.2.3.8) */ +PRE_PACK struct POST_PACK _CDC_UNION_1SLAVE_DESCRIPTOR { + CDC_UNION_DESCRIPTOR sUnion; /* Union functional descriptor */ + uint8_t bSlaveInterfaces[1]; /* Slave interface 0 */ +}; +typedef struct _CDC_UNION_1SLAVE_DESCRIPTOR CDC_UNION_1SLAVE_DESCRIPTOR; + +/* Line coding structure */ +/* Format of the data returned when a GetLineCoding request is received */ +/* (usbcdc11.pdf, 6.2.13) */ +PRE_PACK struct POST_PACK _CDC_LINE_CODING { + uint32_t dwDTERate; /* Data terminal rate in bits per second */ + uint8_t bCharFormat; /* Number of stop bits */ + uint8_t bParityType; /* Parity bit type */ + uint8_t bDataBits; /* Number of data bits */ +}; +typedef struct _CDC_LINE_CODING CDC_LINE_CODING; + +/* Notification header */ +/* Data sent on the notification endpoint must follow this header. */ +/* see USB_SETUP_PACKET in file usb.h */ +typedef USB_SETUP_PACKET CDC_NOTIFICATION_HEADER; + +#endif /* __CDC_H */ + diff --git a/inc/usbd/usbd_cdcuser.h b/inc/usbd/usbd_cdcuser.h new file mode 100644 index 0000000..4d1f440 --- /dev/null +++ b/inc/usbd/usbd_cdcuser.h @@ -0,0 +1,499 @@ +/*********************************************************************** +* $Id:: mw_usbd_cdcuser.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Communication Device Class User module Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __CDCUSER_H__ +#define __CDCUSER_H__ + +#include "error.h" +#include "usbd.h" +#include "usbd_cdc.h" + +/** \file + * \brief Communication Device Class (CDC) API structures and function prototypes. + * + * Definition of functions exported by ROM based CDC function driver. + * + */ + +/** \ingroup Group_USBD + * @defgroup USBD_CDC Communication Device Class (CDC) Function Driver + * \section Sec_CDCModDescription Module Description + * CDC Class Function Driver module. This module contains an internal implementation of the USB CDC Class. + * + * User applications can use this class driver instead of implementing the CDC-ACM class manually + * via the low-level USBD_HW and USBD_Core APIs. + * + * This module is designed to simplify the user code by exposing only the required interface needed to interface with + * Devices using the USB CDC-ACM Class. + */ + +/*---------------------------------------------------------------------------- + We need a buffer for incoming data on USB port because USB receives + much faster than UART transmits + *---------------------------------------------------------------------------*/ +/* Buffer masks */ +#define CDC_BUF_SIZE (128) /* Output buffer in bytes (power 2) */ + /* large enough for file transfer */ +#define CDC_BUF_MASK (CDC_BUF_SIZE-1ul) + +/** \brief Communication Device Class function driver initialization parameter data structure. + * \ingroup USBD_CDC + * + * \details This data structure is used to pass initialization parameters to the + * Communication Device Class function driver's init function. + * + */ +typedef struct USBD_CDC_INIT_PARAM +{ + /* memory allocation params */ + uint32_t mem_base; /**< Base memory location from where the stack can allocate + data and buffers. \note The memory address set in this field + should be accessible by USB DMA controller. Also this value + should be aligned on 4 byte boundary. + */ + uint32_t mem_size; /**< The size of memory buffer which stack can use. + \note The \em mem_size should be greater than the size + returned by USBD_CDC_API::GetMemSize() routine.*/ + /** Pointer to the control interface descriptor within the descriptor + * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T + * structure. The stack assumes both HS and FS use same BULK endpoints. + */ + uint8_t* cif_intf_desc; + /** Pointer to the data interface descriptor within the descriptor + * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T + * structure. The stack assumes both HS and FS use same BULK endpoints. + */ + uint8_t* dif_intf_desc; + + /* user defined functions */ + + /* required functions */ + /** + * Communication Interface Class specific get request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends CIC management element get requests. + * \note Applications implementing Abstract Control Model subclass can set this + * param to NULL. As the default driver parses ACM requests and calls the + * individual ACM call-back routines defined in this structure. For all other subclasses + * this routine should be provided by the application. + * \n + * The setup packet data (\em pSetup) is passed to the call-back so that application + * can extract the CIC request type and other associated data. By default the stack + * will assign \em pBuffer pointer to \em EP0Buff allocated at init. The application + * code can directly write data into this buffer as long as data is less than 64 byte. + * If more data has to be sent then application code should update \em pBuffer pointer + * and length accordingly. + * + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in, out] pBuffer Pointer to a pointer of data buffer containing request data. + * Pointer-to-pointer is used to implement zero-copy buffers. + * See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in, out] length Amount of data to be sent back to host. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CIC_GetRequest)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length); + + /** + * Communication Interface Class specific set request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a CIC management element requests. + * \note Applications implementing Abstract Control Model subclass can set this + * param to NULL. As the default driver parses ACM requests and calls the + * individual ACM call-back routines defined in this structure. For all other subclasses + * this routine should be provided by the application. + * \n + * The setup packet data (\em pSetup) is passed to the call-back so that application can + * extract the CIC request type and other associated data. If a set request has data associated, + * then this call-back is called twice. + * -# First when setup request is received, at this time application code could update + * \em pBuffer pointer to point to the intended destination. The length param is set to 0 + * so that application code knows this is first time. By default the stack will + * assign \em pBuffer pointer to \em EP0Buff allocated at init. Note, if data length is + * greater than 64 bytes and application code doesn't update \em pBuffer pointer the + * stack will send STALL condition to host. + * -# Second when the data is received from the host. This time the length param is set + * with number of data bytes received. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in, out] pBuffer Pointer to a pointer of data buffer containing request data. + * Pointer-to-pointer is used to implement zero-copy buffers. + * See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in] length Amount of data copied to destination buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CIC_SetRequest)( USBD_HANDLE_T hCdc, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length); + + /** + * Communication Device Class specific BULK IN endpoint handler. + * + * The application software should provide the BULK IN endpoint handler. + * Applications should transfer data depending on the communication protocol type set in descriptors. + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CDC_BulkIN_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + + /** + * Communication Device Class specific BULK OUT endpoint handler. + * + * The application software should provide the BULK OUT endpoint handler. + * Applications should transfer data depending on the communication protocol type set in descriptors. + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CDC_BulkOUT_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + + /** + * Abstract control model(ACM) subclass specific SEND_ENCAPSULATED_COMMAND request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a SEND_ENCAPSULATED_COMMAND set request. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] buffer Pointer to the command buffer. + * \param[in] len Length of the command buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*SendEncpsCmd) (USBD_HANDLE_T hCDC, uint8_t* buffer, uint16_t len); + + /** + * Abstract control model(ACM) subclass specific GET_ENCAPSULATED_RESPONSE request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a GET_ENCAPSULATED_RESPONSE request. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in, out] buffer Pointer to a pointer of data buffer containing response data. + * Pointer-to-pointer is used to implement zero-copy buffers. + * See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in, out] len Amount of data to be sent back to host. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*GetEncpsResp) (USBD_HANDLE_T hCDC, uint8_t** buffer, uint16_t* len); + + /** + * Abstract control model(ACM) subclass specific SET_COMM_FEATURE request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a SET_COMM_FEATURE set request. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] feature Communication feature type. See usbcdc11.pdf, section 6.2.4, Table 47. + * \param[in] buffer Pointer to the settings buffer for the specified communication feature. + * \param[in] len Length of the request buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*SetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t* buffer, uint16_t len); + + /** + * Abstract control model(ACM) subclass specific GET_COMM_FEATURE request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a GET_ENCAPSULATED_RESPONSE request. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] feature Communication feature type. See usbcdc11.pdf, section 6.2.4, Table 47. + * \param[in, out] buffer Pointer to a pointer of data buffer containing current settings + * for the communication feature. + * Pointer-to-pointer is used to implement zero-copy buffers. + * \param[in, out] len Amount of data to be sent back to host. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*GetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t** pBuffer, uint16_t* len); + + /** + * Abstract control model(ACM) subclass specific CLEAR_COMM_FEATURE request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a CLEAR_COMM_FEATURE request. In the call-back the application + * should Clears the settings for a particular communication feature. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] feature Communication feature type. See usbcdc11.pdf, section 6.2.4, Table 47. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*ClrCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature); + + /** + * Abstract control model(ACM) subclass specific SET_CONTROL_LINE_STATE request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a SET_CONTROL_LINE_STATE request. RS-232 signal used to tell the DCE + * device the DTE device is now present + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] state The state value uses bitmap values defined in usbcdc11.pdf, + * section 6.2.14, Table 51. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*SetCtrlLineState) (USBD_HANDLE_T hCDC, uint16_t state); + + /** + * Abstract control model(ACM) subclass specific SEND_BREAK request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a SEND_BREAK request. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] mstime Duration of Break signal in milliseconds. If mstime is FFFFh, then + * the application should send break until another SendBreak request is received + * with the wValue of 0000h. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*SendBreak) (USBD_HANDLE_T hCDC, uint16_t mstime); + + /** + * Abstract control model(ACM) subclass specific SET_LINE_CODING request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a SET_LINE_CODING request. The application should configure the device + * per DTE rate, stop-bits, parity, and number-of-character bits settings provided in + * command buffer. See usbcdc11.pdf, section 6.2.13, table 50 for detail of the command buffer. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] line_coding Pointer to the CDC_LINE_CODING command buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*SetLineCode) (USBD_HANDLE_T hCDC, CDC_LINE_CODING* line_coding); + + /** + * Optional Communication Device Class specific INTERRUPT IN endpoint handler. + * + * The application software should provide the INT IN endpoint handler. + * Applications should transfer data depending on the communication protocol type set in descriptors. + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CDC_InterruptEP_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + + /** + * Optional user override-able function to replace the default CDC class handler. + * + * The application software could override the default EP0 class handler with their + * own by providing the handler function address as this data member of the parameter + * structure. Application which like the default handler should set this data member + * to zero before calling the USBD_CDC_API::Init(). + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CDC_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + +} USBD_CDC_INIT_PARAM_T; + +/** \brief CDC class API functions structure. + * \ingroup USBD_CDC + * + * This module exposes functions which interact directly with USB device controller hardware. + * + */ +typedef struct USBD_CDC_API +{ + /** \fn uint32_t GetMemSize(USBD_CDC_INIT_PARAM_T* param) + * Function to determine the memory required by the CDC function driver module. + * + * This function is called by application layer before calling pUsbApi->CDC->Init(), to allocate memory used + * by CDC function driver module. The application should allocate the memory which is accessible by USB + * controller/DMA controller. + * \note Some memory areas are not accessible by all bus masters. + * + * \param[in] param Structure containing CDC function driver module initialization parameters. + * \return Returns the required memory size in bytes. + */ + uint32_t (*GetMemSize)(USBD_CDC_INIT_PARAM_T* param); + + /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_CDC_INIT_PARAM_T* param) + * Function to initialize CDC function driver module. + * + * This function is called by application layer to initialize CDC function driver module. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in, out] param Structure containing CDC function driver module initialization parameters. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte + * aligned or smaller than required. + * \retval ERR_API_INVALID_PARAM2 Either CDC_Write() or CDC_Read() or + * CDC_Verify() callbacks are not defined. + * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed. + * \retval ERR_USBD_BAD_EP_DESC Wrong endpoint descriptor is passed. + */ + ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_CDC_INIT_PARAM_T* param, USBD_HANDLE_T* phCDC); + + /** \fn ErrorCode_t SendNotification(USBD_HANDLE_T hCdc, uint8_t bNotification, uint16_t data) + * Function to send CDC class notifications to host. + * + * This function is called by application layer to send CDC class notifications to host. + * See usbcdc11.pdf, section 6.3, Table 67 for various notification types the CDC device can send. + * \note The current version of the driver only supports following notifications allowed by ACM subclass: + * CDC_NOTIFICATION_NETWORK_CONNECTION, CDC_RESPONSE_AVAILABLE, CDC_NOTIFICATION_SERIAL_STATE. + * \n + * For all other notifications application should construct the notification buffer appropriately + * and call hw->USB_WriteEP() for interrupt endpoint associated with the interface. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] bNotification Notification type allowed by ACM subclass. Should be CDC_NOTIFICATION_NETWORK_CONNECTION, + * CDC_RESPONSE_AVAILABLE or CDC_NOTIFICATION_SERIAL_STATE. For all other types ERR_API_INVALID_PARAM2 + * is returned. See usbcdc11.pdf, section 3.6.2.1, table 5. + * \param[in] data Data associated with notification. + * \n For CDC_NOTIFICATION_NETWORK_CONNECTION a non-zero data value is interpreted as connected state. + * \n For CDC_RESPONSE_AVAILABLE this parameter is ignored. + * \n For CDC_NOTIFICATION_SERIAL_STATE the data should use bitmap values defined in usbcdc11.pdf, + * section 6.3.5, Table 69. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_API_INVALID_PARAM2 If unsupported notification type is passed. + * + */ + ErrorCode_t (*SendNotification)(USBD_HANDLE_T hCdc, uint8_t bNotification, uint16_t data); + +} USBD_CDC_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes + *-----------------------------------------------------------------------------*/ +/** @cond ADVANCED_API */ + +typedef struct _CDC_CTRL_T +{ + USB_CORE_CTRL_T* pUsbCtrl; + /* notification buffer */ + uint8_t notice_buf[12]; + CDC_LINE_CODING line_coding; + uint8_t pad0; + + uint8_t cif_num; /* control interface number */ + uint8_t dif_num; /* data interface number */ + uint8_t epin_num; /* BULK IN endpoint number */ + uint8_t epout_num; /* BULK OUT endpoint number */ + uint8_t epint_num; /* Interrupt IN endpoint number */ + uint8_t pad[3]; + /* user defined functions */ + ErrorCode_t (*SendEncpsCmd) (USBD_HANDLE_T hCDC, uint8_t* buffer, uint16_t len); + ErrorCode_t (*GetEncpsResp) (USBD_HANDLE_T hCDC, uint8_t** buffer, uint16_t* len); + ErrorCode_t (*SetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t* buffer, uint16_t len); + ErrorCode_t (*GetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t** pBuffer, uint16_t* len); + ErrorCode_t (*ClrCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature); + ErrorCode_t (*SetCtrlLineState) (USBD_HANDLE_T hCDC, uint16_t state); + ErrorCode_t (*SendBreak) (USBD_HANDLE_T hCDC, uint16_t state); + ErrorCode_t (*SetLineCode) (USBD_HANDLE_T hCDC, CDC_LINE_CODING* line_coding); + + /* virtual functions */ + ErrorCode_t (*CIC_GetRequest)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length); + ErrorCode_t (*CIC_SetRequest)( USBD_HANDLE_T hCdc, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length); + +}USB_CDC_CTRL_T; + +/** @cond DIRECT_API */ +extern uint32_t mwCDC_GetMemSize(USBD_CDC_INIT_PARAM_T* param); +extern ErrorCode_t mwCDC_init(USBD_HANDLE_T hUsb, USBD_CDC_INIT_PARAM_T* param, USBD_HANDLE_T* phCDC); +extern ErrorCode_t mwCDC_SendNotification (USBD_HANDLE_T hCdc, uint8_t bNotification, uint16_t data); +/** @endcond */ + +/** @endcond */ + + + + + +#endif /* __CDCUSER_H__ */ diff --git a/inc/usbd/usbd_core.h b/inc/usbd/usbd_core.h new file mode 100644 index 0000000..5ff60ff --- /dev/null +++ b/inc/usbd/usbd_core.h @@ -0,0 +1,585 @@ +/*********************************************************************** +* $Id:: mw_usbd_core.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB core controller structure definitions and function prototypes. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __MW_USBD_CORE_H__ +#define __MW_USBD_CORE_H__ + +#include "error.h" +#include "usbd.h" +#include "app_usbd_cfg.h" + +/** \file + * \brief ROM API for USB device stack. + * + * Definition of functions exported by core layer of ROM based USB device stack. + * + */ + +/** \ingroup Group_USBD + * @defgroup USBD_Core USB Core Layer + * \section Sec_CoreModDescription Module Description + * The USB Core Layer implements the device abstraction defined in the Universal Serial Bus Specification, + * for applications to interact with the USB device interface on the device. The software in this layer responds to + * standard requests and returns standard descriptors. In current stack the Init() routine part of + * \ref USBD_HW_API_T structure initializes both hardware layer and core layer. + */ + + +/* function pointer types */ + +/** \ingroup USBD_Core + * \typedef USB_CB_T + * \brief USB device stack's event callback function type. + * + * The USB device stack exposes several event triggers through callback to application layer. The + * application layer can register methods to be called when such USB event happens. + * + * \param[in] hUsb Handle to the USB device stack. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx Other error conditions. + * + */ +typedef ErrorCode_t (*USB_CB_T) (USBD_HANDLE_T hUsb); + +/** \ingroup USBD_Core + * \typedef USB_PARAM_CB_T + * \brief USB device stack's event callback function type. + * + * The USB device stack exposes several event triggers through callback to application layer. The + * application layer can register methods to be called when such USB event happens. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] param1 Extra information related to the event. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ +typedef ErrorCode_t (*USB_PARAM_CB_T) (USBD_HANDLE_T hUsb, uint32_t param1); + +/** \ingroup USBD_Core + * \typedef USB_EP_HANDLER_T + * \brief USBD setup request and endpoint event handler type. + * + * The application layer should define the custom class's EP0 handler with function signature. + * The stack calls all the registered class handlers on any EP0 event before going through default + * handling of the event. This gives the class handlers to implement class specific request handlers + * and also to override the default stack handling for a particular event targeted to the interface. + * If an event is not handled by the callback the function should return ERR_USBD_UNHANDLED. For all + * other return codes the stack assumes that callback has taken care of the event and hence will not + * process the event any further and issues a STALL condition on EP0 indicating error to the host. + * \n + * For endpoint interrupt handler the return value is ignored by the stack. + * \n + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ +typedef ErrorCode_t (*USB_EP_HANDLER_T)(USBD_HANDLE_T hUsb, void* data, uint32_t event); + + +/** \ingroup USBD_Core + * \brief USB descriptors data structure. + * \ingroup USBD_Core + * + * \details This structure is used as part of USB device stack initialization + * parameter structure \ref USBD_API_INIT_PARAM_T. This structure contains + * pointers to various descriptor arrays needed by the stack. These descriptors + * are reported to USB host as part of enumerations process. + * + * \note All descriptor pointers assigned in this structure should be on 4 byte + * aligned address boundary. + */ +typedef struct _USB_CORE_DESCS_T +{ + uint8_t *device_desc; /**< Pointer to USB device descriptor */ + uint8_t *string_desc; /**< Pointer to array of USB string descriptors */ + uint8_t *full_speed_desc; /**< Pointer to USB device configuration descriptor + * when device is operating in full speed mode. + */ + uint8_t *high_speed_desc; /**< Pointer to USB device configuration descriptor + * when device is operating in high speed mode. For + * full-speed only implementation this pointer should + * be same as full_speed_desc. + */ + uint8_t *device_qualifier; /**< Pointer to USB device qualifier descriptor. For + * full-speed only implementation this pointer should + * be set to null (0). + */ +} USB_CORE_DESCS_T; + +/** \brief USB device stack initialization parameter data structure. + * \ingroup USBD_Core + * + * \details This data structure is used to pass initialization parameters to the + * USB device stack's init function. + * + */ +typedef struct USBD_API_INIT_PARAM +{ + uint32_t usb_reg_base; /**< USB device controller's base register address. */ + uint32_t mem_base; /**< Base memory location from where the stack can allocate + data and buffers. \note The memory address set in this field + should be accessible by USB DMA controller. Also this value + should be aligned on 2048 byte boundary. + */ + uint32_t mem_size; /**< The size of memory buffer which stack can use. + \note The \em mem_size should be greater than the size + returned by USBD_HW_API::GetMemSize() routine.*/ + uint8_t max_num_ep; /**< max number of endpoints supported by the USB device + controller instance (specified by \em usb_reg_base field) + to which this instance of stack is attached. + */ + uint8_t pad0[3]; + /* USB Device Events Callback Functions */ + /** Event for USB interface reset. This event fires when the USB host requests that the device + * reset its interface. This event fires after the control endpoint has been automatically + * configured by the library. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will prevent the device from enumerating correctly or operate properly. + * + */ + USB_CB_T USB_Reset_Event; + + /** Event for USB suspend. This event fires when the USB host suspends the device by halting its + * transmission of Start Of Frame pulses to the device. This is generally hooked in order to move + * the device over to a low power state until the host wakes up the device. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will cause other system issues. + */ + USB_CB_T USB_Suspend_Event; + + /** Event for USB wake up or resume. This event fires when a the USB device interface is suspended + * and the host wakes up the device by supplying Start Of Frame pulses. This is generally + * hooked to pull the user application out of a low power state and back into normal operating + * mode. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will cause other system issues. + * + */ + USB_CB_T USB_Resume_Event; + + /** Reserved parameter should be set to zero. */ + USB_CB_T reserved_sbz; + + /** Event for USB Start Of Frame detection, when enabled. This event fires at the start of each USB + * frame, once per millisecond in full-speed mode or once per 125 microseconds in high-speed mode, + * and is synchronized to the USB bus. + * + * This event is time-critical; it is run once per millisecond (full-speed mode) and thus long handlers + * will significantly degrade device performance. This event should only be enabled when needed to + * reduce device wake-ups. + * + * \note This event is not normally active - it must be manually enabled and disabled via the USB interrupt + * register. + * \n\n + */ + USB_CB_T USB_SOF_Event; + + /** Event for remote wake-up configuration, when enabled. This event fires when the USB host + * request the device to configure itself for remote wake-up capability. The USB host sends + * this request to device which report remote wake-up capable in their device descriptors, + * before going to low-power state. The application layer should implement this callback if + * they have any special on board circuit to trigger remote wake up event. Also application + * can use this callback to differentiate the following SUSPEND event is caused by cable plug-out + * or host SUSPEND request. The device can wake-up host only after receiving this callback and + * remote wake-up feature is enabled by host. To signal remote wake-up the device has to generate + * resume signaling on bus by calling usapi.hw->WakeUp() routine. + * + * \n\n + * \param[in] hUsb Handle to the USB device stack. + * \param[in] param1 When 0 - Clear the wake-up configuration, 1 - Enable the wake-up configuration. + * \return The call back should return \ref ErrorCode_t type to indicate success or error condition. + */ + USB_PARAM_CB_T USB_WakeUpCfg; + + /** Reserved parameter should be set to zero. */ + USB_PARAM_CB_T USB_Power_Event; + + /** Event for error condition. This event fires when USB device controller detect + * an error condition in the system. + * + * \n\n + * \param[in] hUsb Handle to the USB device stack. + * \param[in] param1 USB device interrupt status register. + * \return The call back should return \ref ErrorCode_t type to indicate success or error condition. + */ + USB_PARAM_CB_T USB_Error_Event; + + /* USB Core Events Callback Functions */ + /** Event for USB configuration number changed. This event fires when a the USB host changes the + * selected configuration number. On receiving configuration change request from host, the stack + * enables/configures the endpoints needed by the new configuration before calling this callback + * function. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will prevent the device from enumerating correctly or operate properly. + * + */ + USB_CB_T USB_Configure_Event; + + /** Event for USB interface setting changed. This event fires when a the USB host changes the + * interface setting to one of alternate interface settings. On receiving interface change + * request from host, the stack enables/configures the endpoints needed by the new alternate + * interface setting before calling this callback function. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will prevent the device from enumerating correctly or operate properly. + * + */ + USB_CB_T USB_Interface_Event; + + /** Event for USB feature changed. This event fires when a the USB host send set/clear feature + * request. The stack handles this request for USB_FEATURE_REMOTE_WAKEUP, USB_FEATURE_TEST_MODE + * and USB_FEATURE_ENDPOINT_STALL features only. On receiving feature request from host, the + * stack handle the request appropriately and then calls this callback function. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will prevent the device from enumerating correctly or operate properly. + * + */ + USB_CB_T USB_Feature_Event; + + /* cache and MMU translation functions */ + /** Reserved parameter for future use. should be set to zero. */ + uint32_t (* virt_to_phys)(void* vaddr); + /** Reserved parameter for future use. should be set to zero. */ + void (* cache_flush)(uint32_t* start_adr, uint32_t* end_adr); + +} USBD_API_INIT_PARAM_T; + + +/** \brief USBD stack Core API functions structure. + * \ingroup USBD_Core + * + * \details This module exposes functions which interact directly with USB device stack's core layer. + * The application layer uses this component when it has to implement custom class function driver or + * standard class function driver which is not part of the current USB device stack. + * The functions exposed by this interface are to register class specific EP0 handlers and corresponding + * utility functions to manipulate EP0 state machine of the stack. This interface also exposes + * function to register custom endpoint interrupt handler. + * + */ +typedef struct USBD_CORE_API +{ + /** \fn ErrorCode_t RegisterClassHandler(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data) + * Function to register class specific EP0 event handler with USB device stack. + * + * The application layer uses this function when it has to register the custom class's EP0 handler. + * The stack calls all the registered class handlers on any EP0 event before going through default + * handling of the event. This gives the class handlers to implement class specific request handlers + * and also to override the default stack handling for a particular event targeted to the interface. + * Check \ref USB_EP_HANDLER_T for more details on how the callback function should be implemented. Also + * application layer could use this function to register EP0 handler which responds to vendor specific + * requests. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] pfn Class specific EP0 handler function. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_TOO_MANY_CLASS_HDLR(0x0004000c) The number of class handlers registered is + greater than the number of handlers allowed by the stack. + * + */ + ErrorCode_t (*RegisterClassHandler)(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data); + + /** \fn ErrorCode_t RegisterEpHandler(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data) + * Function to register interrupt/event handler for the requested endpoint with USB device stack. + * + * The application layer uses this function to register the endpoint event handler. + * The stack calls all the registered endpoint handlers when + * - USB_EVT_OUT or USB_EVT_OUT_NAK events happen for OUT endpoint. + * - USB_EVT_IN or USB_EVT_IN_NAK events happen for IN endpoint. + * Check USB_EP_HANDLER_T for more details on how the callback function should be implemented. + * \note By default endpoint _NAK events are not enabled. Application should call \ref USBD_HW_API_T::EnableEvent + * for the corresponding endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] ep_index Endpoint index. Computed as + * - For OUT endpoints = 2 * endpoint number eg. for EP2_OUT it is 4. + * - For IN endopoints = (2 * endpoint number) + 1 eg. for EP2_IN it is 5. + * \param[in] pfn Endpoint event handler function. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_API_INVALID_PARAM2 ep_index is outside the boundary ( < 2 * USBD_API_INIT_PARAM_T::max_num_ep). + * + */ + ErrorCode_t (*RegisterEpHandler)(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data); + + /** \fn void SetupStage(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in setup state. + * + * This function is called by USB stack and the application layer to + * set the EP0 state machine in setup state. This function will read + * the setup packet received from USB host into stack's buffer. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*SetupStage )(USBD_HANDLE_T hUsb); + + /** \fn void DataInStage(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in data_in state. + * + * This function is called by USB stack and the application layer to + * set the EP0 state machine in data_in state. This function will write + * the data present in EP0Data buffer to EP0 FIFO for transmission to host. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*DataInStage)(USBD_HANDLE_T hUsb); + + /** \fn void DataOutStage(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in data_out state. + * + * This function is called by USB stack and the application layer to + * set the EP0 state machine in data_out state. This function will read + * the control data (EP0 out packets) received from USB host into EP0Data buffer. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*DataOutStage)(USBD_HANDLE_T hUsb); + + /** \fn void StatusInStage(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in status_in state. + * + * This function is called by USB stack and the application layer to + * set the EP0 state machine in status_in state. This function will send + * zero length IN packet on EP0 to host, indicating positive status. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*StatusInStage)(USBD_HANDLE_T hUsb); + /** \fn void StatusOutStage(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in status_out state. + * + * This function is called by USB stack and the application layer to + * set the EP0 state machine in status_out state. This function will read + * the zero length OUT packet received from USB host on EP0. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*StatusOutStage)(USBD_HANDLE_T hUsb); + + /** \fn void StallEp0(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in stall state. + * + * This function is called by USB stack and the application layer to + * generate STALL signaling on EP0 endpoint. This function will also + * reset the EP0Data buffer. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*StallEp0)(USBD_HANDLE_T hUsb); + +} USBD_CORE_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes + *-----------------------------------------------------------------------------*/ + + /** @cond ADVANCED_API */ + +/* forward declaration */ +struct _USB_CORE_CTRL_T; +typedef struct _USB_CORE_CTRL_T USB_CORE_CTRL_T; + +/* USB device Speed status defines */ +#define USB_FULL_SPEED 0 +#define USB_HIGH_SPEED 1 + +/* USB Endpoint Data Structure */ +typedef struct _USB_EP_DATA +{ + uint8_t *pData; + uint16_t Count; + uint16_t pad0; +} USB_EP_DATA; + + +/* USB core controller data structure */ +struct _USB_CORE_CTRL_T +{ + /* override-able function pointers ~ c++ style virtual functions*/ + USB_CB_T USB_EvtSetupHandler; + USB_CB_T USB_EvtOutHandler; + USB_PARAM_CB_T USB_ReqVendor; + USB_CB_T USB_ReqGetStatus; + USB_CB_T USB_ReqGetDescriptor; + USB_CB_T USB_ReqGetConfiguration; + USB_CB_T USB_ReqSetConfiguration; + USB_CB_T USB_ReqGetInterface; + USB_CB_T USB_ReqSetInterface; + USB_PARAM_CB_T USB_ReqSetClrFeature; + + /* USB Device Events Callback Functions */ + USB_CB_T USB_Reset_Event; + USB_CB_T USB_Suspend_Event; + USB_CB_T USB_Resume_Event; + USB_CB_T USB_SOF_Event; + USB_PARAM_CB_T USB_Power_Event; + USB_PARAM_CB_T USB_Error_Event; + USB_PARAM_CB_T USB_WakeUpCfg; + + /* USB Core Events Callback Functions */ + USB_CB_T USB_Configure_Event; + USB_CB_T USB_Interface_Event; + USB_CB_T USB_Feature_Event; + + /* cache and MMU translation functions */ + uint32_t (* virt_to_phys)(void* vaddr); + void (* cache_flush)(uint32_t* start_adr, uint32_t* end_adr); + + /* event handlers for endpoints. */ + USB_EP_HANDLER_T ep_event_hdlr[2 * USB_MAX_EP_NUM]; + void* ep_hdlr_data[2 * USB_MAX_EP_NUM]; + + /* USB class handlers */ + USB_EP_HANDLER_T ep0_hdlr_cb[USB_MAX_IF_NUM]; + void* ep0_cb_data[USB_MAX_IF_NUM]; + uint8_t num_ep0_hdlrs; + /* USB Core data Variables */ + uint8_t max_num_ep; /* max number of endpoints supported by the HW */ + uint8_t device_speed; + uint8_t num_interfaces; + uint8_t device_addr; + uint8_t config_value; + uint16_t device_status; + uint8_t *device_desc; + uint8_t *string_desc; + uint8_t *full_speed_desc; + uint8_t *high_speed_desc; + uint8_t *device_qualifier; + uint32_t ep_mask; + uint32_t ep_halt; + uint32_t ep_stall; + uint8_t alt_setting[USB_MAX_IF_NUM]; + /* HW driver data pointer */ + void* hw_data; + + /* USB Endpoint 0 Data Info */ + USB_EP_DATA EP0Data; + + /* USB Endpoint 0 Buffer */ + //ALIGNED(4) + uint8_t EP0Buf[64]; + + /* USB Setup Packet */ + //ALIGNED(4) + USB_SETUP_PACKET SetupPacket; + +}; + +/* USB Core Functions */ +extern void mwUSB_InitCore(USB_CORE_CTRL_T* pCtrl, USB_CORE_DESCS_T* pdescr, USBD_API_INIT_PARAM_T* param); +extern void mwUSB_ResetCore(USBD_HANDLE_T hUsb); + +/* inline functions */ +static INLINE void USB_SetSpeedMode(USB_CORE_CTRL_T* pCtrl, uint8_t mode) +{ + pCtrl->device_speed = mode; +} + +static INLINE bool USB_IsConfigured(USBD_HANDLE_T hUsb) +{ + USB_CORE_CTRL_T* pCtrl = (USB_CORE_CTRL_T*) hUsb; + return (bool) (pCtrl->config_value != 0); +} + +/** @cond DIRECT_API */ +/* midleware API */ +extern ErrorCode_t mwUSB_RegisterClassHandler(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data); +extern ErrorCode_t mwUSB_RegisterEpHandler(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data); +extern void mwUSB_SetupStage (USBD_HANDLE_T hUsb); +extern void mwUSB_DataInStage(USBD_HANDLE_T hUsb); +extern void mwUSB_DataOutStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StatusInStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StatusOutStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StallEp0(USBD_HANDLE_T hUsb); +extern ErrorCode_t mwUSB_RegisterClassHandler(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data); +extern ErrorCode_t mwUSB_RegisterEpHandler(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data); +extern void mwUSB_SetupStage (USBD_HANDLE_T hUsb); +extern void mwUSB_DataInStage(USBD_HANDLE_T hUsb); +extern void mwUSB_DataOutStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StatusInStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StatusOutStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StallEp0(USBD_HANDLE_T hUsb); +/** @endcond */ + +/** @endcond */ + +#endif /* __MW_USBD_CORE_H__ */ diff --git a/inc/usbd/usbd_desc.h b/inc/usbd/usbd_desc.h new file mode 100644 index 0000000..c03f942 --- /dev/null +++ b/inc/usbd/usbd_desc.h @@ -0,0 +1,48 @@ +/*********************************************************************** +* $Id:: mw_usbd_desc.h 165 2011-04-14 17:41:11Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Descriptors Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __USBDESC_H__ +#define __USBDESC_H__ + +#include "usbd.h" + +#define WBVAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF) +#define B3VAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF),(((x) >> 16) & 0xFF) + +#define USB_DEVICE_DESC_SIZE (sizeof(USB_DEVICE_DESCRIPTOR)) +#define USB_CONFIGUARTION_DESC_SIZE (sizeof(USB_CONFIGURATION_DESCRIPTOR)) +#define USB_INTERFACE_DESC_SIZE (sizeof(USB_INTERFACE_DESCRIPTOR)) +#define USB_ENDPOINT_DESC_SIZE (sizeof(USB_ENDPOINT_DESCRIPTOR)) +#define USB_DEVICE_QUALI_SIZE (sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)) +#define USB_OTHER_SPEED_CONF_SIZE (sizeof(USB_OTHER_SPEED_CONFIGURATION)) + +//#define HID_DESC_SIZE (sizeof(HID_DESCRIPTOR)) +//#define HID_REPORT_DESC_SIZE (sizeof(HID_ReportDescriptor)) + +extern const uint8_t HID_ReportDescriptor[]; +extern const uint16_t HID_ReportDescSize; +extern const uint16_t HID_DescOffset; + + +#endif /* __USBDESC_H__ */ diff --git a/inc/usbd/usbd_dfu.h b/inc/usbd/usbd_dfu.h new file mode 100644 index 0000000..52134eb --- /dev/null +++ b/inc/usbd/usbd_dfu.h @@ -0,0 +1,120 @@ +/*********************************************************************** +* $Id:: mw_usbd_dfu.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* Device Firmware Upgrade (DFU) module. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __MW_USBD_DFU_H__ +#define __MW_USBD_DFU_H__ + +#include "usbd.h" + +/** \file + * \brief Device Firmware Upgrade (DFU) class descriptors. + * + * Definition of DFU class descriptors and their bit defines. + * + */ + +/** + * If USB device is only DFU capable, DFU Interface number is always 0. + * if USB device is (DFU + Other Class (Audio/Mass Storage/HID), DFU + * Interface number should also be 0 in this implementation. + */ +#define USB_DFU_IF_NUM 0x0 + +#define USB_DFU_DESCRIPTOR_TYPE 0x21 +#define USB_DFU_DESCRIPTOR_SIZE 9 +#define USB_DFU_SUBCLASS 0x01 + +/* DFU class-specific requests (Section 3, DFU Rev 1.1) */ +#define USB_REQ_DFU_DETACH 0x00 +#define USB_REQ_DFU_DNLOAD 0x01 +#define USB_REQ_DFU_UPLOAD 0x02 +#define USB_REQ_DFU_GETSTATUS 0x03 +#define USB_REQ_DFU_CLRSTATUS 0x04 +#define USB_REQ_DFU_GETSTATE 0x05 +#define USB_REQ_DFU_ABORT 0x06 + +#define DFU_STATUS_OK 0x00 +#define DFU_STATUS_errTARGET 0x01 +#define DFU_STATUS_errFILE 0x02 +#define DFU_STATUS_errWRITE 0x03 +#define DFU_STATUS_errERASE 0x04 +#define DFU_STATUS_errCHECK_ERASED 0x05 +#define DFU_STATUS_errPROG 0x06 +#define DFU_STATUS_errVERIFY 0x07 +#define DFU_STATUS_errADDRESS 0x08 +#define DFU_STATUS_errNOTDONE 0x09 +#define DFU_STATUS_errFIRMWARE 0x0a +#define DFU_STATUS_errVENDOR 0x0b +#define DFU_STATUS_errUSBR 0x0c +#define DFU_STATUS_errPOR 0x0d +#define DFU_STATUS_errUNKNOWN 0x0e +#define DFU_STATUS_errSTALLEDPKT 0x0f + +enum dfu_state { + DFU_STATE_appIDLE = 0, + DFU_STATE_appDETACH = 1, + DFU_STATE_dfuIDLE = 2, + DFU_STATE_dfuDNLOAD_SYNC = 3, + DFU_STATE_dfuDNBUSY = 4, + DFU_STATE_dfuDNLOAD_IDLE = 5, + DFU_STATE_dfuMANIFEST_SYNC = 6, + DFU_STATE_dfuMANIFEST = 7, + DFU_STATE_dfuMANIFEST_WAIT_RST= 8, + DFU_STATE_dfuUPLOAD_IDLE = 9, + DFU_STATE_dfuERROR = 10 +}; + +#define DFU_EP0_NONE 0 +#define DFU_EP0_UNHANDLED 1 +#define DFU_EP0_STALL 2 +#define DFU_EP0_ZLP 3 +#define DFU_EP0_DATA 4 + +#define USB_DFU_CAN_DOWNLOAD (1 << 0) +#define USB_DFU_CAN_UPLOAD (1 << 1) +#define USB_DFU_MANIFEST_TOL (1 << 2) +#define USB_DFU_WILL_DETACH (1 << 3) + +PRE_PACK struct POST_PACK _USB_DFU_FUNC_DESCRIPTOR { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bmAttributes; + uint16_t wDetachTimeOut; + uint16_t wTransferSize; + uint16_t bcdDFUVersion; +}; +typedef struct _USB_DFU_FUNC_DESCRIPTOR USB_DFU_FUNC_DESCRIPTOR; + +PRE_PACK struct POST_PACK _DFU_STATUS { + uint8_t bStatus; + uint8_t bwPollTimeout[3]; + uint8_t bState; + uint8_t iString; +}; +typedef struct _DFU_STATUS DFU_STATUS_T; + +#define DFU_FUNC_DESC_SIZE sizeof(USB_DFU_FUNC_DESCRIPTOR) +#define DFU_GET_STATUS_SIZE 0x6 + + +#endif /* __MW_USBD_DFU_H__ */ diff --git a/inc/usbd/usbd_dfuuser.h b/inc/usbd/usbd_dfuuser.h new file mode 100644 index 0000000..61cd666 --- /dev/null +++ b/inc/usbd/usbd_dfuuser.h @@ -0,0 +1,270 @@ +/*********************************************************************** +* $Id:: mw_usbd_dfuuser.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* Device Firmware Upgrade Class Custom User Module Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __DFUUSER_H__ +#define __DFUUSER_H__ + +#include "usbd.h" +#include "usbd_dfu.h" +#include "usbd_core.h" + +/** \file + * \brief Device Firmware Upgrade (DFU) API structures and function prototypes. + * + * Definition of functions exported by ROM based DFU function driver. + * + */ + + +/** \ingroup Group_USBD + * @defgroup USBD_DFU Device Firmware Upgrade (DFU) Class Function Driver + * \section Sec_MSCModDescription Module Description + * DFU Class Function Driver module. This module contains an internal implementation of the USB DFU Class. + * User applications can use this class driver instead of implementing the DFU class manually + * via the low-level USBD_HW and USBD_Core APIs. + * + * This module is designed to simplify the user code by exposing only the required interface needed to interface with + * Devices using the USB DFU Class. + */ + +/** \brief USB descriptors data structure. + * \ingroup USBD_DFU + * + * \details This module exposes functions which interact directly with USB device stack's core layer. + * The application layer uses this component when it has to implement custom class function driver or + * standard class function driver which is not part of the current USB device stack. + * The functions exposed by this interface are to register class specific EP0 handlers and corresponding + * utility functions to manipulate EP0 state machine of the stack. This interface also exposes + * function to register custom endpoint interrupt handler. + * + */ +typedef struct USBD_DFU_INIT_PARAM +{ + /* memory allocation params */ + uint32_t mem_base; /**< Base memory location from where the stack can allocate + data and buffers. \note The memory address set in this field + should be accessible by USB DMA controller. Also this value + should be aligned on 4 byte boundary. + */ + uint32_t mem_size; /**< The size of memory buffer which stack can use. + \note The \em mem_size should be greater than the size + returned by USBD_DFU_API::GetMemSize() routine.*/ + /* DFU paramas */ + uint16_t wTransferSize; /**< DFU transfer block size in number of bytes. + This value should match the value set in DFU descriptor + provided as part of the descriptor array + (\em high_speed_desc) passed to Init() through + \ref USB_CORE_DESCS_T structure. */ + + uint16_t pad; + /** Pointer to the DFU interface descriptor within the descriptor + * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T + * structure. + */ + uint8_t* intf_desc; + /* user defined functions */ + /** + * DFU Write callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a write command. For application using zero-copy buffer scheme + * this function is called for the first time with \em length parameter set to 0. + * The application code should update the buffer pointer. + * + * \param[in] block_num Destination start address. + * \param[in, out] src Pointer to a pointer to the source of data. Pointer-to-pointer + * is used to implement zero-copy buffers. See \ref USBD_ZeroCopy + * for more details on zero-copy concept. + * \param[out] bwPollTimeout Pointer to a 3 byte buffer which the callback implementer + * should fill with the amount of minimum time, in milliseconds, + * that the host should wait before sending a subsequent + * DFU_GETSTATUS request. + * \param[in] length Number of bytes to be written. + * \return Returns DFU_STATUS_ values defined in mw_usbd_dfu.h. + * + */ + uint8_t (*DFU_Write)( uint32_t block_num, uint8_t** src, uint32_t length, uint8_t* bwPollTimeout); + + /** + * DFU Read callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a read command. + * + * \param[in] block_num Destination start address. + * \param[in, out] dst Pointer to a pointer to the source of data. Pointer-to-pointer + * is used to implement zero-copy buffers. See \ref USBD_ZeroCopy + * for more details on zero-copy concept. + * \param[in] length Amount of data copied to destination buffer. + * \return Returns + * - DFU_STATUS_ values defined in mw_usbd_dfu.h to return error conditions. + * - 0 if there is no more data to be read. Stack will send EOF frame and set + * DFU state-machine to dfuIdle state. + * - length of the data copied, should be greater than or equal to 16. If the data copied + * is less than DFU \em wTransferSize the stack will send EOF frame and + * goes to dfuIdle state. + * + */ + uint32_t (*DFU_Read)( uint32_t block_num, uint8_t** dst, uint32_t length); + + /** + * DFU done callback function. + * + * This function is provided by the application software. This function gets called + * after firmware download completes. + * + * \return Nothing. + * + */ + void (*DFU_Done)(void); + + /** + * DFU detach callback function. + * + * This function is provided by the application software. This function gets called + * after USB_REQ_DFU_DETACH is received. Applications which set USB_DFU_WILL_DETACH + * bit in DFU descriptor should define this function. As part of this function + * application can call Connect() routine to disconnect and then connect back with + * host. For application which rely on WinUSB based host application should use this + * feature since USB reset can be invoked only by kernel drivers on Windows host. + * By implementing this feature host doen't have to issue reset instead the device + * has to do it automatically by disconnect and connect procedure. + * + * \param[in] hUsb Handle DFU control structure. + * \return Nothing. + * + */ + void (*DFU_Detach)(USBD_HANDLE_T hUsb); + + /** + * Optional user override-able function to replace the default DFU class handler. + * + * The application software could override the default EP0 class handler with their + * own by providing the handler function address as this data member of the parameter + * structure. Application which like the default handler should set this data member + * to zero before calling the USBD_DFU_API::Init(). + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*DFU_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + +} USBD_DFU_INIT_PARAM_T; + + +/** \brief DFU class API functions structure. + * \ingroup USBD_DFU + * + * This module exposes functions which interact directly with USB device controller hardware. + * + */ +typedef struct USBD_DFU_API +{ + /** \fn uint32_t GetMemSize(USBD_DFU_INIT_PARAM_T* param) + * Function to determine the memory required by the DFU function driver module. + * + * This function is called by application layer before calling pUsbApi->dfu->Init(), to allocate memory used + * by DFU function driver module. The application should allocate the memory which is accessible by USB + * controller/DMA controller. + * \note Some memory areas are not accessible by all bus masters. + * + * \param[in] param Structure containing DFU function driver module initialization parameters. + * \return Returns the required memory size in bytes. + */ + uint32_t (*GetMemSize)(USBD_DFU_INIT_PARAM_T* param); + + /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_DFU_INIT_PARAM_T* param) + * Function to initialize DFU function driver module. + * + * This function is called by application layer to initialize DFU function driver module. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in, out] param Structure containing DFU function driver module initialization parameters. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte aligned or smaller than required. + * \retval ERR_API_INVALID_PARAM2 Either DFU_Write() or DFU_Done() or DFU_Read() call-backs are not defined. + * \retval ERR_USBD_BAD_DESC + * - USB_DFU_DESCRIPTOR_TYPE is not defined immediately after + * interface descriptor. + * - wTransferSize in descriptor doesn't match the value passed + * in param->wTransferSize. + * - DFU_Detach() is not defined while USB_DFU_WILL_DETACH is set + * in DFU descriptor. + * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed. + */ + ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_DFU_INIT_PARAM_T* param, uint32_t init_state); + +} USBD_DFU_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes + *-----------------------------------------------------------------------------*/ +/** @cond ADVANCED_API */ + +typedef struct _USBD_DFU_CTRL_T +{ + /*ALIGNED(4)*/ DFU_STATUS_T dfu_req_get_status; + uint16_t pad; + uint8_t dfu_state; + uint8_t dfu_status; + uint8_t download_done; + uint8_t if_num; /* interface number */ + + uint8_t* xfr_buf; + USB_DFU_FUNC_DESCRIPTOR* dfu_desc; + + USB_CORE_CTRL_T* pUsbCtrl; + /* user defined functions */ + /* return DFU_STATUS_ values defined in mw_usbd_dfu.h */ + uint8_t (*DFU_Write)( uint32_t block_num, uint8_t** src, uint32_t length, uint8_t* bwPollTimeout); + /* return + * DFU_STATUS_ : values defined in mw_usbd_dfu.h in case of errors + * 0 : If end of memory reached + * length : Amount of data copied to destination buffer + */ + uint32_t (*DFU_Read)( uint32_t block_num, uint8_t** dst, uint32_t length); + /* callback called after download is finished */ + void (*DFU_Done)(void); + /* callback called after USB_REQ_DFU_DETACH is recived */ + void (*DFU_Detach)(USBD_HANDLE_T hUsb); + +} USBD_DFU_CTRL_T; + +/** @cond DIRECT_API */ +uint32_t mwDFU_GetMemSize(USBD_DFU_INIT_PARAM_T* param); +extern ErrorCode_t mwDFU_init(USBD_HANDLE_T hUsb, USBD_DFU_INIT_PARAM_T* param, uint32_t init_state); +/** @endcond */ + +/** @endcond */ + +#endif /* __DFUUSER_H__ */ diff --git a/inc/usbd/usbd_hid.h b/inc/usbd/usbd_hid.h new file mode 100644 index 0000000..5d801ac --- /dev/null +++ b/inc/usbd/usbd_hid.h @@ -0,0 +1,430 @@ +/*********************************************************************** +* $Id: mw_usbd_hid.h.rca 1.2 Tue Nov 1 11:45:07 2011 nlv09221 Experimental $ +* +* Project: USB device ROM Stack +* +* Description: +* HID Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __HID_H__ +#define __HID_H__ + +#include "usbd.h" + +/** \file + * \brief Common definitions and declarations for the library USB HID Class driver. + * + * Common definitions and declarations for the library USB HID Class driver. + * \addtogroup USBD_HID + * @{ + */ + + +/** HID Subclass Codes + * @{ + */ +/** Descriptor Subclass value indicating that the device or interface does not implement a HID boot protocol. */ +#define HID_SUBCLASS_NONE 0x00 +/** Descriptor Subclass value indicating that the device or interface implements a HID boot protocol. */ +#define HID_SUBCLASS_BOOT 0x01 +/** @} */ + +/** HID Protocol Codes + * @{ + */ +/** Descriptor Protocol value indicating that the device or interface does not belong to a HID boot protocol. */ +#define HID_PROTOCOL_NONE 0x00 +/** Descriptor Protocol value indicating that the device or interface belongs to the Keyboard HID boot protocol. */ +#define HID_PROTOCOL_KEYBOARD 0x01 +/** Descriptor Protocol value indicating that the device or interface belongs to the Mouse HID boot protocol. */ +#define HID_PROTOCOL_MOUSE 0x02 +/** @} */ + + + +/** Descriptor Types + * @{ + */ +/** Descriptor header type value, to indicate a HID class HID descriptor. */ +#define HID_HID_DESCRIPTOR_TYPE 0x21 +/** Descriptor header type value, to indicate a HID class HID report descriptor. */ +#define HID_REPORT_DESCRIPTOR_TYPE 0x22 +/** Descriptor header type value, to indicate a HID class HID Physical descriptor. */ +#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 +/** @} */ + + +/** \brief HID class-specific HID Descriptor. + * + * Type define for the HID class-specific HID descriptor, to describe the HID device's specifications. Refer to the HID + * specification for details on the structure elements. + * + */ +PRE_PACK struct POST_PACK _HID_DESCRIPTOR { + uint8_t bLength; /**< Size of the descriptor, in bytes. */ + uint8_t bDescriptorType; /**< Type of HID descriptor. */ + uint16_t bcdHID; /**< BCD encoded version that the HID descriptor and device complies to. */ + uint8_t bCountryCode; /**< Country code of the localized device, or zero if universal. */ + uint8_t bNumDescriptors; /**< Total number of HID report descriptors for the interface. */ + + PRE_PACK struct POST_PACK _HID_DESCRIPTOR_LIST { + uint8_t bDescriptorType; /**< Type of HID report. */ + uint16_t wDescriptorLength; /**< Length of the associated HID report descriptor, in bytes. */ + } DescriptorList[1]; /**< Array of one or more descriptors */ +} ; +/** HID class-specific HID Descriptor. */ +typedef struct _HID_DESCRIPTOR HID_DESCRIPTOR; + +#define HID_DESC_SIZE sizeof(HID_DESCRIPTOR) + +/** HID Request Codes + * @{ + */ +#define HID_REQUEST_GET_REPORT 0x01 +#define HID_REQUEST_GET_IDLE 0x02 +#define HID_REQUEST_GET_PROTOCOL 0x03 +#define HID_REQUEST_SET_REPORT 0x09 +#define HID_REQUEST_SET_IDLE 0x0A +#define HID_REQUEST_SET_PROTOCOL 0x0B +/** @} */ + +/** HID Report Types + * @{ + */ +#define HID_REPORT_INPUT 0x01 +#define HID_REPORT_OUTPUT 0x02 +#define HID_REPORT_FEATURE 0x03 +/** @} */ + + +/** Usage Pages + * @{ + */ +#define HID_USAGE_PAGE_UNDEFINED 0x00 +#define HID_USAGE_PAGE_GENERIC 0x01 +#define HID_USAGE_PAGE_SIMULATION 0x02 +#define HID_USAGE_PAGE_VR 0x03 +#define HID_USAGE_PAGE_SPORT 0x04 +#define HID_USAGE_PAGE_GAME 0x05 +#define HID_USAGE_PAGE_DEV_CONTROLS 0x06 +#define HID_USAGE_PAGE_KEYBOARD 0x07 +#define HID_USAGE_PAGE_LED 0x08 +#define HID_USAGE_PAGE_BUTTON 0x09 +#define HID_USAGE_PAGE_ORDINAL 0x0A +#define HID_USAGE_PAGE_TELEPHONY 0x0B +#define HID_USAGE_PAGE_CONSUMER 0x0C +#define HID_USAGE_PAGE_DIGITIZER 0x0D +#define HID_USAGE_PAGE_UNICODE 0x10 +#define HID_USAGE_PAGE_ALPHANUMERIC 0x14 +/** @} */ + + +/** Generic Desktop Page (0x01) + * @{ + */ +#define HID_USAGE_GENERIC_POINTER 0x01 +#define HID_USAGE_GENERIC_MOUSE 0x02 +#define HID_USAGE_GENERIC_JOYSTICK 0x04 +#define HID_USAGE_GENERIC_GAMEPAD 0x05 +#define HID_USAGE_GENERIC_KEYBOARD 0x06 +#define HID_USAGE_GENERIC_KEYPAD 0x07 +#define HID_USAGE_GENERIC_X 0x30 +#define HID_USAGE_GENERIC_Y 0x31 +#define HID_USAGE_GENERIC_Z 0x32 +#define HID_USAGE_GENERIC_RX 0x33 +#define HID_USAGE_GENERIC_RY 0x34 +#define HID_USAGE_GENERIC_RZ 0x35 +#define HID_USAGE_GENERIC_SLIDER 0x36 +#define HID_USAGE_GENERIC_DIAL 0x37 +#define HID_USAGE_GENERIC_WHEEL 0x38 +#define HID_USAGE_GENERIC_HATSWITCH 0x39 +#define HID_USAGE_GENERIC_COUNTED_BUFFER 0x3A +#define HID_USAGE_GENERIC_BYTE_COUNT 0x3B +#define HID_USAGE_GENERIC_MOTION_WAKEUP 0x3C +#define HID_USAGE_GENERIC_VX 0x40 +#define HID_USAGE_GENERIC_VY 0x41 +#define HID_USAGE_GENERIC_VZ 0x42 +#define HID_USAGE_GENERIC_VBRX 0x43 +#define HID_USAGE_GENERIC_VBRY 0x44 +#define HID_USAGE_GENERIC_VBRZ 0x45 +#define HID_USAGE_GENERIC_VNO 0x46 +#define HID_USAGE_GENERIC_SYSTEM_CTL 0x80 +#define HID_USAGE_GENERIC_SYSCTL_POWER 0x81 +#define HID_USAGE_GENERIC_SYSCTL_SLEEP 0x82 +#define HID_USAGE_GENERIC_SYSCTL_WAKE 0x83 +#define HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU 0x84 +#define HID_USAGE_GENERIC_SYSCTL_MAIN_MENU 0x85 +#define HID_USAGE_GENERIC_SYSCTL_APP_MENU 0x86 +#define HID_USAGE_GENERIC_SYSCTL_HELP_MENU 0x87 +#define HID_USAGE_GENERIC_SYSCTL_MENU_EXIT 0x88 +#define HID_USAGE_GENERIC_SYSCTL_MENU_SELECT 0x89 +#define HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT 0x8A +#define HID_USAGE_GENERIC_SYSCTL_MENU_LEFT 0x8B +#define HID_USAGE_GENERIC_SYSCTL_MENU_UP 0x8C +#define HID_USAGE_GENERIC_SYSCTL_MENU_DOWN 0x8D +/** @} */ + +/** Simulation Controls Page (0x02) + * @{ + */ +#define HID_USAGE_SIMULATION_RUDDER 0xBA +#define HID_USAGE_SIMULATION_THROTTLE 0xBB +/** @} */ + +/* Virtual Reality Controls Page (0x03) */ +/* ... */ + +/* Sport Controls Page (0x04) */ +/* ... */ + +/* Game Controls Page (0x05) */ +/* ... */ + +/* Generic Device Controls Page (0x06) */ +/* ... */ + +/** Keyboard/Keypad Page (0x07) + * @{ + */ +/** Error "keys" */ +#define HID_USAGE_KEYBOARD_NOEVENT 0x00 +#define HID_USAGE_KEYBOARD_ROLLOVER 0x01 +#define HID_USAGE_KEYBOARD_POSTFAIL 0x02 +#define HID_USAGE_KEYBOARD_UNDEFINED 0x03 + +/** Letters */ +#define HID_USAGE_KEYBOARD_aA 0x04 +#define HID_USAGE_KEYBOARD_zZ 0x1D + +/** Numbers */ +#define HID_USAGE_KEYBOARD_ONE 0x1E +#define HID_USAGE_KEYBOARD_ZERO 0x27 + +#define HID_USAGE_KEYBOARD_RETURN 0x28 +#define HID_USAGE_KEYBOARD_ESCAPE 0x29 +#define HID_USAGE_KEYBOARD_DELETE 0x2A + +/** Funtion keys */ +#define HID_USAGE_KEYBOARD_F1 0x3A +#define HID_USAGE_KEYBOARD_F12 0x45 + +#define HID_USAGE_KEYBOARD_PRINT_SCREEN 0x46 + +/** Modifier Keys */ +#define HID_USAGE_KEYBOARD_LCTRL 0xE0 +#define HID_USAGE_KEYBOARD_LSHFT 0xE1 +#define HID_USAGE_KEYBOARD_LALT 0xE2 +#define HID_USAGE_KEYBOARD_LGUI 0xE3 +#define HID_USAGE_KEYBOARD_RCTRL 0xE4 +#define HID_USAGE_KEYBOARD_RSHFT 0xE5 +#define HID_USAGE_KEYBOARD_RALT 0xE6 +#define HID_USAGE_KEYBOARD_RGUI 0xE7 +#define HID_USAGE_KEYBOARD_SCROLL_LOCK 0x47 +#define HID_USAGE_KEYBOARD_NUM_LOCK 0x53 +#define HID_USAGE_KEYBOARD_CAPS_LOCK 0x39 +/** @} */ + +/* ... */ + +/** LED Page (0x08) + * @{ + */ +#define HID_USAGE_LED_NUM_LOCK 0x01 +#define HID_USAGE_LED_CAPS_LOCK 0x02 +#define HID_USAGE_LED_SCROLL_LOCK 0x03 +#define HID_USAGE_LED_COMPOSE 0x04 +#define HID_USAGE_LED_KANA 0x05 +#define HID_USAGE_LED_POWER 0x06 +#define HID_USAGE_LED_SHIFT 0x07 +#define HID_USAGE_LED_DO_NOT_DISTURB 0x08 +#define HID_USAGE_LED_MUTE 0x09 +#define HID_USAGE_LED_TONE_ENABLE 0x0A +#define HID_USAGE_LED_HIGH_CUT_FILTER 0x0B +#define HID_USAGE_LED_LOW_CUT_FILTER 0x0C +#define HID_USAGE_LED_EQUALIZER_ENABLE 0x0D +#define HID_USAGE_LED_SOUND_FIELD_ON 0x0E +#define HID_USAGE_LED_SURROUND_FIELD_ON 0x0F +#define HID_USAGE_LED_REPEAT 0x10 +#define HID_USAGE_LED_STEREO 0x11 +#define HID_USAGE_LED_SAMPLING_RATE_DETECT 0x12 +#define HID_USAGE_LED_SPINNING 0x13 +#define HID_USAGE_LED_CAV 0x14 +#define HID_USAGE_LED_CLV 0x15 +#define HID_USAGE_LED_RECORDING_FORMAT_DET 0x16 +#define HID_USAGE_LED_OFF_HOOK 0x17 +#define HID_USAGE_LED_RING 0x18 +#define HID_USAGE_LED_MESSAGE_WAITING 0x19 +#define HID_USAGE_LED_DATA_MODE 0x1A +#define HID_USAGE_LED_BATTERY_OPERATION 0x1B +#define HID_USAGE_LED_BATTERY_OK 0x1C +#define HID_USAGE_LED_BATTERY_LOW 0x1D +#define HID_USAGE_LED_SPEAKER 0x1E +#define HID_USAGE_LED_HEAD_SET 0x1F +#define HID_USAGE_LED_HOLD 0x20 +#define HID_USAGE_LED_MICROPHONE 0x21 +#define HID_USAGE_LED_COVERAGE 0x22 +#define HID_USAGE_LED_NIGHT_MODE 0x23 +#define HID_USAGE_LED_SEND_CALLS 0x24 +#define HID_USAGE_LED_CALL_PICKUP 0x25 +#define HID_USAGE_LED_CONFERENCE 0x26 +#define HID_USAGE_LED_STAND_BY 0x27 +#define HID_USAGE_LED_CAMERA_ON 0x28 +#define HID_USAGE_LED_CAMERA_OFF 0x29 +#define HID_USAGE_LED_ON_LINE 0x2A +#define HID_USAGE_LED_OFF_LINE 0x2B +#define HID_USAGE_LED_BUSY 0x2C +#define HID_USAGE_LED_READY 0x2D +#define HID_USAGE_LED_PAPER_OUT 0x2E +#define HID_USAGE_LED_PAPER_JAM 0x2F +#define HID_USAGE_LED_REMOTE 0x30 +#define HID_USAGE_LED_FORWARD 0x31 +#define HID_USAGE_LED_REVERSE 0x32 +#define HID_USAGE_LED_STOP 0x33 +#define HID_USAGE_LED_REWIND 0x34 +#define HID_USAGE_LED_FAST_FORWARD 0x35 +#define HID_USAGE_LED_PLAY 0x36 +#define HID_USAGE_LED_PAUSE 0x37 +#define HID_USAGE_LED_RECORD 0x38 +#define HID_USAGE_LED_ERROR 0x39 +#define HID_USAGE_LED_SELECTED_INDICATOR 0x3A +#define HID_USAGE_LED_IN_USE_INDICATOR 0x3B +#define HID_USAGE_LED_MULTI_MODE_INDICATOR 0x3C +#define HID_USAGE_LED_INDICATOR_ON 0x3D +#define HID_USAGE_LED_INDICATOR_FLASH 0x3E +#define HID_USAGE_LED_INDICATOR_SLOW_BLINK 0x3F +#define HID_USAGE_LED_INDICATOR_FAST_BLINK 0x40 +#define HID_USAGE_LED_INDICATOR_OFF 0x41 +#define HID_USAGE_LED_FLASH_ON_TIME 0x42 +#define HID_USAGE_LED_SLOW_BLINK_ON_TIME 0x43 +#define HID_USAGE_LED_SLOW_BLINK_OFF_TIME 0x44 +#define HID_USAGE_LED_FAST_BLINK_ON_TIME 0x45 +#define HID_USAGE_LED_FAST_BLINK_OFF_TIME 0x46 +#define HID_USAGE_LED_INDICATOR_COLOR 0x47 +#define HID_USAGE_LED_RED 0x48 +#define HID_USAGE_LED_GREEN 0x49 +#define HID_USAGE_LED_AMBER 0x4A +#define HID_USAGE_LED_GENERIC_INDICATOR 0x4B +/** @} */ + +/* Button Page (0x09) + */ +/* There is no need to label these usages. */ + +/* Ordinal Page (0x0A) + */ +/* There is no need to label these usages. */ + +/** Telephony Device Page (0x0B) + * @{ + */ +#define HID_USAGE_TELEPHONY_PHONE 0x01 +#define HID_USAGE_TELEPHONY_ANSWERING_MACHINE 0x02 +#define HID_USAGE_TELEPHONY_MESSAGE_CONTROLS 0x03 +#define HID_USAGE_TELEPHONY_HANDSET 0x04 +#define HID_USAGE_TELEPHONY_HEADSET 0x05 +#define HID_USAGE_TELEPHONY_KEYPAD 0x06 +#define HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON 0x07 +/** @} */ +/* ... */ + +/** Consumer Page (0x0C) + * @{ + */ +#define HID_USAGE_CONSUMER_CONTROL 0x01 +#define HID_USAGE_CONSUMER_FAST_FORWARD 0xB3 +#define HID_USAGE_CONSUMER_REWIND 0xB4 +#define HID_USAGE_CONSUMER_PLAY_PAUSE 0xCD +#define HID_USAGE_CONSUMER_VOLUME_INCREMENT 0xE9 +#define HID_USAGE_CONSUMER_VOLUME_DECREMENT 0xEA +/** @} */ +/* ... */ + +/* and others ... */ + + +/** HID Report Item Macros + * @{ + */ +/** Main Items */ +#define HID_Input(x) 0x81,x +#define HID_Output(x) 0x91,x +#define HID_Feature(x) 0xB1,x +#define HID_Collection(x) 0xA1,x +#define HID_EndCollection 0xC0 + +/** Data (Input, Output, Feature) */ +#define HID_Data 0<<0 +#define HID_Constant 1<<0 +#define HID_Array 0<<1 +#define HID_Variable 1<<1 +#define HID_Absolute 0<<2 +#define HID_Relative 1<<2 +#define HID_NoWrap 0<<3 +#define HID_Wrap 1<<3 +#define HID_Linear 0<<4 +#define HID_NonLinear 1<<4 +#define HID_PreferredState 0<<5 +#define HID_NoPreferred 1<<5 +#define HID_NoNullPosition 0<<6 +#define HID_NullState 1<<6 +#define HID_NonVolatile 0<<7 +#define HID_Volatile 1<<7 + +/** Collection Data */ +#define HID_Physical 0x00 +#define HID_Application 0x01 +#define HID_Logical 0x02 +#define HID_Report 0x03 +#define HID_NamedArray 0x04 +#define HID_UsageSwitch 0x05 +#define HID_UsageModifier 0x06 + +/** Global Items */ +#define HID_UsagePage(x) 0x05,x +#define HID_UsagePageVendor(x) 0x06,x,0xFF +#define HID_LogicalMin(x) 0x15,x +#define HID_LogicalMinS(x) 0x16,(x&0xFF),((x>>8)&0xFF) +#define HID_LogicalMinL(x) 0x17,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF) +#define HID_LogicalMax(x) 0x25,x +#define HID_LogicalMaxS(x) 0x26,(x&0xFF),((x>>8)&0xFF) +#define HID_LogicalMaxL(x) 0x27,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF) +#define HID_PhysicalMin(x) 0x35,x +#define HID_PhysicalMinS(x) 0x36,(x&0xFF),((x>>8)&0xFF) +#define HID_PhysicalMinL(x) 0x37,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF) +#define HID_PhysicalMax(x) 0x45,x +#define HID_PhysicalMaxS(x) 0x46,(x&0xFF),((x>>8)&0xFF) +#define HID_PhysicalMaxL(x) 0x47,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF) +#define HID_UnitExponent(x) 0x55,x +#define HID_Unit(x) 0x65,x +#define HID_UnitS(x) 0x66,(x&0xFF),((x>>8)&0xFF) +#define HID_UnitL(x) 0x67,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF) +#define HID_ReportSize(x) 0x75,x +#define HID_ReportID(x) 0x85,x +#define HID_ReportCount(x) 0x95,x +#define HID_Push 0xA0 +#define HID_Pop 0xB0 + +/** Local Items */ +#define HID_Usage(x) 0x09,x +#define HID_UsageMin(x) 0x19,x +#define HID_UsageMax(x) 0x29,x +/** @} */ + +/** @} */ + +#endif /* __HID_H__ */ diff --git a/inc/usbd/usbd_hiduser.h b/inc/usbd/usbd_hiduser.h new file mode 100644 index 0000000..c00ccac --- /dev/null +++ b/inc/usbd/usbd_hiduser.h @@ -0,0 +1,421 @@ +/*********************************************************************** +* $Id:: mw_usbd_hiduser.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* HID Custom User Module Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __HIDUSER_H__ +#define __HIDUSER_H__ + +#include "usbd.h" +#include "usbd_hid.h" +#include "usbd_core.h" + +/** \file + * \brief Human Interface Device (HID) API structures and function prototypes. + * + * Definition of functions exported by ROM based HID function driver. + * + */ + +/** \ingroup Group_USBD + * @defgroup USBD_HID HID Class Function Driver + * \section Sec_HIDModDescription Module Description + * HID Class Function Driver module. This module contains an internal implementation of the USB HID Class. + * User applications can use this class driver instead of implementing the HID class manually + * via the low-level HW and core APIs. + * + * This module is designed to simplify the user code by exposing only the required interface needed to interface with + * Devices using the USB HID Class. + */ + +/** \brief HID report descriptor data structure. + * \ingroup USBD_HID + * + * \details This structure is used as part of HID function driver initialization + * parameter structure \ref USBD_HID_INIT_PARAM. This structure contains + * details of a report type supported by the application. An application + * can support multiple report types as a single HID device. The application + * should define this report type data structure per report it supports and + * the array of report types to USBD_HID_API::init() through \ref USBD_HID_INIT_PARAM + * structure. + * + * \note All descriptor pointers assigned in this structure should be on 4 byte + * aligned address boundary. + * + */ +typedef struct _HID_REPORT_T { + uint16_t len; /**< Size of the report descriptor in bytes. */ + uint8_t idle_time; /**< This value is used by stack to respond to Set_Idle & + GET_Idle requests for the specified report ID. The value + of this field specified the rate at which duplicate reports + are generated for the specified Report ID. For example, a + device with two input reports could specify an idle rate of + 20 milliseconds for report ID 1 and 500 milliseconds for + report ID 2. + */ + uint8_t __pad; /**< Padding space. */ + uint8_t* desc; /**< Report descriptor. */ +} USB_HID_REPORT_T; + +/** \brief USB descriptors data structure. + * \ingroup USBD_HID + * + * \details This module exposes functions which interact directly with USB device stack's core layer. + * The application layer uses this component when it has to implement custom class function driver or + * standard class function driver which is not part of the current USB device stack. + * The functions exposed by this interface are to register class specific EP0 handlers and corresponding + * utility functions to manipulate EP0 state machine of the stack. This interface also exposes + * function to register custom endpoint interrupt handler. + * + */ +typedef struct USBD_HID_INIT_PARAM +{ + /* memory allocation params */ + uint32_t mem_base; /**< Base memory location from where the stack can allocate + data and buffers. \note The memory address set in this field + should be accessible by USB DMA controller. Also this value + should be aligned on 4 byte boundary. + */ + uint32_t mem_size; /**< The size of memory buffer which stack can use. + \note The \em mem_size should be greater than the size + returned by USBD_HID_API::GetMemSize() routine.*/ + /* HID paramas */ + uint8_t max_reports; /**< Number of HID reports supported by this instance + of HID class driver. + */ + uint8_t pad[3]; + uint8_t* intf_desc; /**< Pointer to the HID interface descriptor within the + descriptor array (\em high_speed_desc) passed to Init() + through \ref USB_CORE_DESCS_T structure. + */ + USB_HID_REPORT_T* report_data; /**< Pointer to an array of HID report descriptor + data structure (\ref USB_HID_REPORT_T). The number + of elements in the array should be same a \em max_reports + value. The stack uses this array to respond to + requests received for various HID report descriptor + information. \note This array should be of global scope. + */ + + /* user defined functions */ + /* required functions */ + /** + * HID get report callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a HID_REQUEST_GET_REPORT request. The setup packet data (\em pSetup) + * is passed to the callback so that application can extract the report ID, report + * type and other information need to generate the report. \note HID reports are sent + * via interrupt IN endpoint also. This function is called only when report request + * is received on control endpoint. Application should implement \em HID_EpIn_Hdlr to + * send reports to host via interrupt IN endpoint. + * + * + * \param[in] hHid Handle to HID function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in, out] pBuffer Pointer to a pointer of data buffer containing report data. + * Pointer-to-pointer is used to implement zero-copy buffers. + * See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in] length Amount of data copied to destination buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_GetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length); + + /** + * HID set report callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a HID_REQUEST_SET_REPORT request. The setup packet data (\em pSetup) + * is passed to the callback so that application can extract the report ID, report + * type and other information need to modify the report. An application might choose + * to ignore input Set_Report requests as meaningless. Alternatively these reports + * could be used to reset the origin of a control (that is, current position should + * report zero). + * + * \param[in] hHid Handle to HID function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in, out] pBuffer Pointer to a pointer of data buffer containing report data. + * Pointer-to-pointer is used to implement zero-copy buffers. + * See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in] length Amount of data copied to destination buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_SetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length); + + /* optional functions */ + + /** + * Optional callback function to handle HID_GetPhysDesc request. + * + * The application software could provide this callback HID_GetPhysDesc handler to + * handle get physical descriptor requests sent by the host. When host requests + * Physical Descriptor set 0, application should return a special descriptor + * identifying the number of descriptor sets and their sizes. A Get_Descriptor + * request with the Physical Index equal to 1 should return the first Physical + * Descriptor set. A device could possibly have alternate uses for its items. + * These can be enumerated by issuing subsequent Get_Descriptor requests while + * incrementing the Descriptor Index. A device should return the last descriptor + * set to requests with an index greater than the last number defined in the HID + * descriptor. + * \note Applications which don't have physical descriptor should set this data member + * to zero before calling the USBD_HID_API::Init(). + * \n + * + * \param[in] hHid Handle to HID function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in] pBuf Pointer to a pointer of data buffer containing physical descriptor + * data. If the physical descriptor is in USB accessible memory area + * application could just update the pointer or else it should copy + * the descriptor to the address pointed by this pointer. + * \param[in] length Amount of data copied to destination buffer or descriptor length. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_GetPhysDesc)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length); + + /** + * Optional callback function to handle HID_REQUEST_SET_IDLE request. + * + * The application software could provide this callback to handle HID_REQUEST_SET_IDLE + * requests sent by the host. This callback is provided to applications to adjust + * timers associated with various reports, which are sent to host over interrupt + * endpoint. The setup packet data (\em pSetup) is passed to the callback so that + * application can extract the report ID, report type and other information need + * to modify the report's idle time. + * \note Applications which don't send reports on Interrupt endpoint or don't + * have idle time between reports should set this data member to zero before + * calling the USBD_HID_API::Init(). + * \n + * + * \param[in] hHid Handle to HID function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in] idleTime Idle time to be set for the specified report. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_SetIdle)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t idleTime); + + /** + * Optional callback function to handle HID_REQUEST_SET_PROTOCOL request. + * + * The application software could provide this callback to handle HID_REQUEST_SET_PROTOCOL + * requests sent by the host. This callback is provided to applications to adjust + * modes of their code between boot mode and report mode. + * \note Applications which don't support protocol modes should set this data member + * to zero before calling the USBD_HID_API::Init(). + * \n + * + * \param[in] hHid Handle to HID function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in] protocol Protocol mode. + * 0 = Boot Protocol + * 1 = Report Protocol + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_SetProtocol)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t protocol); + + /** + * Optional Interrupt IN endpoint event handler. + * + * The application software could provide Interrupt IN endpoint event handler. + * Application which send reports to host on interrupt endpoint should provide + * an endpoint event handler through this data member. This data member is + * ignored if the interface descriptor \em intf_desc doesn't have any IN interrupt + * endpoint descriptor associated. + * \n + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Handle to HID function driver. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should return \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_EpIn_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + /** + * Optional Interrupt OUT endpoint event handler. + * + * The application software could provide Interrupt OUT endpoint event handler. + * Application which receives reports from host on interrupt endpoint should provide + * an endpoint event handler through this data member. This data member is + * ignored if the interface descriptor \em intf_desc doesn't have any OUT interrupt + * endpoint descriptor associated. + * \n + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Handle to HID function driver. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should return \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_EpOut_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + + /* user override-able function */ + /** + * Optional user override-able function to replace the default HID_GetReportDesc handler. + * + * The application software could override the default HID_GetReportDesc handler with their + * own by providing the handler function address as this data member of the parameter + * structure. Application which like the default handler should set this data member + * to zero before calling the USBD_HID_API::Init() and also provide report data array + * \em report_data field. + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_GetReportDesc)(USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length); + /** + * Optional user override-able function to replace the default HID class handler. + * + * The application software could override the default EP0 class handler with their + * own by providing the handler function address as this data member of the parameter + * structure. Application which like the default handler should set this data member + * to zero before calling the USBD_HID_API::Init(). + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + +} USBD_HID_INIT_PARAM_T; + +/** \brief HID class API functions structure. + * \ingroup USBD_HID + * + * This structure contains pointers to all the function exposed by HID function driver module. + * + */ +typedef struct USBD_HID_API +{ + /** \fn uint32_t GetMemSize(USBD_HID_INIT_PARAM_T* param) + * Function to determine the memory required by the HID function driver module. + * + * This function is called by application layer before calling pUsbApi->hid->Init(), to allocate memory used + * by HID function driver module. The application should allocate the memory which is accessible by USB + * controller/DMA controller. + * \note Some memory areas are not accessible by all bus masters. + * + * \param[in] param Structure containing HID function driver module initialization parameters. + * \return Returns the required memory size in bytes. + */ + uint32_t (*GetMemSize)(USBD_HID_INIT_PARAM_T* param); + + /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_HID_INIT_PARAM_T* param) + * Function to initialize HID function driver module. + * + * This function is called by application layer to initialize HID function driver + * module. On successful initialization the function returns a handle to HID + * function driver module in passed param structure. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in, out] param Structure containing HID function driver module + * initialization parameters. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte + * aligned or smaller than required. + * \retval ERR_API_INVALID_PARAM2 Either HID_GetReport() or HID_SetReport() + * callback are not defined. + * \retval ERR_USBD_BAD_DESC HID_HID_DESCRIPTOR_TYPE is not defined + * immediately after interface descriptor. + * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed. + * \retval ERR_USBD_BAD_EP_DESC Wrong endpoint descriptor is passed. + */ + ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_HID_INIT_PARAM_T* param); + +} USBD_HID_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes + *-----------------------------------------------------------------------------*/ +/** @cond ADVANCED_API */ + +typedef struct _HID_CTRL_T { + /* pointer to controller */ + USB_CORE_CTRL_T* pUsbCtrl; + /* descriptor pointers */ + uint8_t* hid_desc; + USB_HID_REPORT_T* report_data; + + uint8_t protocol; + uint8_t if_num; /* interface number */ + uint8_t epin_adr; /* IN interrupt endpoint */ + uint8_t epout_adr; /* OUT interrupt endpoint */ + + /* user defined functions */ + ErrorCode_t (*HID_GetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length); + ErrorCode_t (*HID_SetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length); + ErrorCode_t (*HID_GetPhysDesc)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length); + ErrorCode_t (*HID_SetIdle)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t idleTime); + ErrorCode_t (*HID_SetProtocol)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t protocol); + + /* virtual overridable functions */ + ErrorCode_t (*HID_GetReportDesc)(USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length); + +}USB_HID_CTRL_T; + +/** @cond DIRECT_API */ +extern uint32_t mwHID_GetMemSize(USBD_HID_INIT_PARAM_T* param); +extern ErrorCode_t mwHID_init(USBD_HANDLE_T hUsb, USBD_HID_INIT_PARAM_T* param); +/** @endcond */ + +/** @endcond */ + +#endif /* __HIDUSER_H__ */ diff --git a/inc/usbd/usbd_hw.h b/inc/usbd/usbd_hw.h new file mode 100644 index 0000000..b7e0f10 --- /dev/null +++ b/inc/usbd/usbd_hw.h @@ -0,0 +1,457 @@ +/*********************************************************************** +* $Id:: mw_usbd_hw.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Hardware Function prototypes. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __USBHW_H__ +#define __USBHW_H__ + +#include "error.h" +#include "usbd.h" +#include "usbd_core.h" + +/** \file + * \brief USB Hardware Function prototypes. + * + * Definition of functions exported by ROM based Device Controller Driver (DCD). + * + */ + +/** \ingroup Group_USBD + * @defgroup USBD_HW USB Device Controller Driver + * \section Sec_HWModDescription Module Description + * The Device Controller Driver Layer implements the routines to deal directly with the hardware. + */ + +/** \ingroup USBD_HW +* USB Endpoint/class handler Callback Events. +* +*/ +enum USBD_EVENT_T { + USB_EVT_SETUP =1, /**< 1 Setup Packet received */ + USB_EVT_OUT, /**< 2 OUT Packet received */ + USB_EVT_IN, /**< 3 IN Packet sent */ + USB_EVT_OUT_NAK, /**< 4 OUT Packet - Not Acknowledged */ + USB_EVT_IN_NAK, /**< 5 IN Packet - Not Acknowledged */ + USB_EVT_OUT_STALL, /**< 6 OUT Packet - Stalled */ + USB_EVT_IN_STALL, /**< 7 IN Packet - Stalled */ + USB_EVT_OUT_DMA_EOT, /**< 8 DMA OUT EP - End of Transfer */ + USB_EVT_IN_DMA_EOT, /**< 9 DMA IN EP - End of Transfer */ + USB_EVT_OUT_DMA_NDR, /**< 10 DMA OUT EP - New Descriptor Request */ + USB_EVT_IN_DMA_NDR, /**< 11 DMA IN EP - New Descriptor Request */ + USB_EVT_OUT_DMA_ERR, /**< 12 DMA OUT EP - Error */ + USB_EVT_IN_DMA_ERR, /**< 13 DMA IN EP - Error */ + USB_EVT_RESET, /**< 14 Reset event recieved */ + USB_EVT_SOF, /**< 15 Start of Frame event */ + USB_EVT_DEV_STATE, /**< 16 Device status events */ + USB_EVT_DEV_ERROR /**< 17 Device error events */ +}; + +/** + * \brief Hardware API functions structure. + * \ingroup USBD_HW + * + * This module exposes functions which interact directly with USB device controller hardware. + * + */ +typedef struct USBD_HW_API +{ + /** \fn uint32_t GetMemSize(USBD_API_INIT_PARAM_T* param) + * Function to determine the memory required by the USB device stack's DCD and core layers. + * + * This function is called by application layer before calling pUsbApi->hw->Init(), to allocate memory used + * by DCD and core layers. The application should allocate the memory which is accessible by USB + * controller/DMA controller. + * \note Some memory areas are not accessible by all bus masters. + * + * \param[in] param Structure containing USB device stack initialization parameters. + * \return Returns the required memory size in bytes. + */ + uint32_t (*GetMemSize)(USBD_API_INIT_PARAM_T* param); + + /** \fn ErrorCode_t Init(USBD_HANDLE_T* phUsb, USB_CORE_DESCS_T* pDesc, USBD_API_INIT_PARAM_T* param) + * Function to initialize USB device stack's DCD and core layers. + * + * This function is called by application layer to initialize USB hardware and core layers. + * On successful initialization the function returns a handle to USB device stack which should + * be passed to the rest of the functions. + * + * \param[in,out] phUsb Pointer to the USB device stack handle of type USBD_HANDLE_T. + * \param[in] pDesc Structure containing pointers to various descriptor arrays needed by the stack. + * These descriptors are reported to USB host as part of enumerations process. + * \param[in] param Structure containing USB device stack initialization parameters. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK(0) On success + * \retval ERR_USBD_BAD_MEM_BUF(0x0004000b) When insufficient memory buffer is passed or memory + * is not aligned on 2048 boundary. + */ + ErrorCode_t (*Init)(USBD_HANDLE_T* phUsb, USB_CORE_DESCS_T* pDesc, USBD_API_INIT_PARAM_T* param); + + /** \fn void Connect(USBD_HANDLE_T hUsb, uint32_t con) + * Function to make USB device visible/invisible on the USB bus. + * + * This function is called after the USB initialization. This function uses the soft connect + * feature to make the device visible on the USB bus. This function is called only after the + * application is ready to handle the USB data. The enumeration process is started by the + * host after the device detection. The driver handles the enumeration process according to + * the USB descriptors passed in the USB initialization function. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] con States whether to connect (1) or to disconnect (0). + * \return Nothing. + */ + void (*Connect)(USBD_HANDLE_T hUsb, uint32_t con); + + /** \fn void ISR(USBD_HANDLE_T hUsb) + * Function to USB device controller interrupt events. + * + * When the user application is active the interrupt handlers are mapped in the user flash + * space. The user application must provide an interrupt handler for the USB interrupt and + * call this function in the interrupt handler routine. The driver interrupt handler takes + * appropriate action according to the data received on the USB bus. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*ISR)(USBD_HANDLE_T hUsb); + + /** \fn void Reset(USBD_HANDLE_T hUsb) + * Function to Reset USB device stack and hardware controller. + * + * Reset USB device stack and hardware controller. Disables all endpoints except EP0. + * Clears all pending interrupts and resets endpoint transfer queues. + * This function is called internally by pUsbApi->hw->init() and from reset event. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*Reset)(USBD_HANDLE_T hUsb); + + /** \fn void ForceFullSpeed(USBD_HANDLE_T hUsb, uint32_t cfg) + * Function to force high speed USB device to operate in full speed mode. + * + * This function is useful for testing the behavior of current device when connected + * to a full speed only hosts. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] cfg When 1 - set force full-speed or + * 0 - clear force full-speed. + * \return Nothing. + */ + void (*ForceFullSpeed )(USBD_HANDLE_T hUsb, uint32_t cfg); + + /** \fn void WakeUpCfg(USBD_HANDLE_T hUsb, uint32_t cfg) + * Function to configure USB device controller to wake-up host on remote events. + * + * This function is called by application layer to configure the USB device controller + * to wakeup on remote events. It is recommended to call this function from users's + * USB_WakeUpCfg() callback routine registered with stack. + * \note User's USB_WakeUpCfg() is registered with stack by setting the USB_WakeUpCfg member + * of USBD_API_INIT_PARAM_T structure before calling pUsbApi->hw->Init() routine. + * Certain USB device controllers needed to keep some clocks always on to generate + * resume signaling through pUsbApi->hw->WakeUp(). This hook is provided to support + * such controllers. In most controllers cases this is an empty routine. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] cfg When 1 - Configure controller to wake on remote events or + * 0 - Configure controller not to wake on remote events. + * \return Nothing. + */ + void (*WakeUpCfg)(USBD_HANDLE_T hUsb, uint32_t cfg); + + /** \fn void SetAddress(USBD_HANDLE_T hUsb, uint32_t adr) + * Function to set USB address assigned by host in device controller hardware. + * + * This function is called automatically when USB_REQUEST_SET_ADDRESS request is received + * by the stack from USB host. + * This interface is provided to users to invoke this function in other scenarios which are not + * handle by current stack. In most user applications this function is not called directly. + * Also this function can be used by users who are selectively modifying the USB device stack's + * standard handlers through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] adr USB bus Address to which the device controller should respond. Usually + * assigned by the USB host. + * \return Nothing. + */ + void (*SetAddress)(USBD_HANDLE_T hUsb, uint32_t adr); + + /** \fn void Configure(USBD_HANDLE_T hUsb, uint32_t cfg) + * Function to configure device controller hardware with selected configuration. + * + * This function is called automatically when USB_REQUEST_SET_CONFIGURATION request is received + * by the stack from USB host. + * This interface is provided to users to invoke this function in other scenarios which are not + * handle by current stack. In most user applications this function is not called directly. + * Also this function can be used by users who are selectively modifying the USB device stack's + * standard handlers through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] cfg Configuration index. + * \return Nothing. + */ + void (*Configure)(USBD_HANDLE_T hUsb, uint32_t cfg); + + /** \fn void ConfigEP(USBD_HANDLE_T hUsb, USB_ENDPOINT_DESCRIPTOR *pEPD) + * Function to configure USB Endpoint according to descriptor. + * + * This function is called automatically when USB_REQUEST_SET_CONFIGURATION request is received + * by the stack from USB host. All the endpoints associated with the selected configuration + * are configured. + * This interface is provided to users to invoke this function in other scenarios which are not + * handle by current stack. In most user applications this function is not called directly. + * Also this function can be used by users who are selectively modifying the USB device stack's + * standard handlers through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] pEPD Endpoint descriptor structure defined in USB 2.0 specification. + * \return Nothing. + */ + void (*ConfigEP)(USBD_HANDLE_T hUsb, USB_ENDPOINT_DESCRIPTOR *pEPD); + + /** \fn void DirCtrlEP(USBD_HANDLE_T hUsb, uint32_t dir) + * Function to set direction for USB control endpoint EP0. + * + * This function is called automatically by the stack on need basis. + * This interface is provided to users to invoke this function in other scenarios which are not + * handle by current stack. In most user applications this function is not called directly. + * Also this function can be used by users who are selectively modifying the USB device stack's + * standard handlers through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] cfg When 1 - Set EP0 in IN transfer mode + * 0 - Set EP0 in OUT transfer mode + * \return Nothing. + */ + void (*DirCtrlEP)(USBD_HANDLE_T hUsb, uint32_t dir); + + /** \fn void EnableEP(USBD_HANDLE_T hUsb, uint32_t EPNum) + * Function to enable selected USB endpoint. + * + * This function enables interrupts on selected endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \return Nothing. + */ + void (*EnableEP)(USBD_HANDLE_T hUsb, uint32_t EPNum); + + /** \fn void DisableEP(USBD_HANDLE_T hUsb, uint32_t EPNum) + * Function to disable selected USB endpoint. + * + * This function disables interrupts on selected endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \return Nothing. + */ + void (*DisableEP)(USBD_HANDLE_T hUsb, uint32_t EPNum); + + /** \fn void ResetEP(USBD_HANDLE_T hUsb, uint32_t EPNum) + * Function to reset selected USB endpoint. + * + * This function flushes the endpoint buffers and resets data toggle logic. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \return Nothing. + */ + void (*ResetEP)(USBD_HANDLE_T hUsb, uint32_t EPNum); + + /** \fn void SetStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum) + * Function to STALL selected USB endpoint. + * + * Generates STALL signaling for requested endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \return Nothing. + */ + void (*SetStallEP)(USBD_HANDLE_T hUsb, uint32_t EPNum); + + /** \fn void ClrStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum) + * Function to clear STALL state for the requested endpoint. + * + * This function clears STALL state for the requested endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \return Nothing. + */ + void (*ClrStallEP)(USBD_HANDLE_T hUsb, uint32_t EPNum); + + /** \fn ErrorCode_t SetTestMode(USBD_HANDLE_T hUsb, uint8_t mode) + * Function to set high speed USB device controller in requested test mode. + * + * USB-IF requires the high speed device to be put in various test modes + * for electrical testing. This USB device stack calls this function whenever + * it receives USB_REQUEST_CLEAR_FEATURE request for USB_FEATURE_TEST_MODE. + * Users can put the device in test mode by directly calling this function. + * Returns ERR_USBD_INVALID_REQ when device controller is full-speed only. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] mode Test mode defined in USB 2.0 electrical testing specification. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK(0) - On success + * \retval ERR_USBD_INVALID_REQ(0x00040001) - Invalid test mode or + * Device controller is full-speed only. + */ + ErrorCode_t (*SetTestMode)(USBD_HANDLE_T hUsb, uint8_t mode); + + /** \fn uint32_t ReadEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData) + * Function to read data received on the requested endpoint. + * + * This function is called by USB stack and the application layer to read the data + * received on the requested endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \param[in,out] pData Pointer to the data buffer where data is to be copied. + * \return Returns the number of bytes copied to the buffer. + */ + uint32_t (*ReadEP)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData); + + /** \fn uint32_t ReadReqEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t len) + * Function to queue read request on the specified endpoint. + * + * This function is called by USB stack and the application layer to queue a read request + * on the specified endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \param[in,out] pData Pointer to the data buffer where data is to be copied. This buffer + * address should be accessible by USB DMA master. + * \param[in] len Length of the buffer passed. + * \return Returns the length of the requested buffer. + */ + uint32_t (*ReadReqEP)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t len); + + /** \fn uint32_t ReadSetupPkt(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t *pData) + * Function to read setup packet data received on the requested endpoint. + * + * This function is called by USB stack and the application layer to read setup packet data + * received on the requested endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP0_IN is represented by 0x80 number. + * \param[in,out] pData Pointer to the data buffer where data is to be copied. + * \return Returns the number of bytes copied to the buffer. + */ + uint32_t (*ReadSetupPkt)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t *pData); + + /** \fn uint32_t WriteEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t cnt) + * Function to write data to be sent on the requested endpoint. + * + * This function is called by USB stack and the application layer to send data + * on the requested endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \param[in] pData Pointer to the data buffer from where data is to be copied. + * \param[in] cnt Number of bytes to write. + * \return Returns the number of bytes written. + */ + uint32_t (*WriteEP)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t cnt); + + /** \fn void WakeUp(USBD_HANDLE_T hUsb) + * Function to generate resume signaling on bus for remote host wakeup. + * + * This function is called by application layer to remotely wakeup host controller + * when system is in suspend state. Application should indicate this remote wakeup + * capability by setting USB_CONFIG_REMOTE_WAKEUP in bmAttributes of Configuration + * Descriptor. Also this routine will generate resume signalling only if host + * enables USB_FEATURE_REMOTE_WAKEUP by sending SET_FEATURE request before suspending + * the bus. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*WakeUp)(USBD_HANDLE_T hUsb); + + /** \fn void EnableEvent(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t event_type, uint32_t enable) + * Function to enable/disable selected USB event. + * + * This function enables interrupts on selected endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number corresponding to the event. + * ie. An EP1_IN is represented by 0x81 number. For device events + * set this param to 0x0. + * \param[in] event_type Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \param[in] enable 1 - enable event, 0 - disable event. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK(0) - On success + * \retval ERR_USBD_INVALID_REQ(0x00040001) - Invalid event type. + */ + ErrorCode_t (*EnableEvent)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t event_type, uint32_t enable); + +} USBD_HW_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes used by stack internally + *-----------------------------------------------------------------------------*/ +/** @cond DIRECT_API */ + +/* Driver functions */ +uint32_t hwUSB_GetMemSize(USBD_API_INIT_PARAM_T* param); +ErrorCode_t hwUSB_Init(USBD_HANDLE_T* phUsb, USB_CORE_DESCS_T* pDesc, USBD_API_INIT_PARAM_T* param); +void hwUSB_Connect(USBD_HANDLE_T hUsb, uint32_t con); +void hwUSB_ISR(USBD_HANDLE_T hUsb); + +/* USB Hardware Functions */ +extern void hwUSB_Reset(USBD_HANDLE_T hUsb); +extern void hwUSB_ForceFullSpeed (USBD_HANDLE_T hUsb, uint32_t con); +extern void hwUSB_WakeUpCfg(USBD_HANDLE_T hUsb, uint32_t cfg); +extern void hwUSB_SetAddress(USBD_HANDLE_T hUsb, uint32_t adr); +extern void hwUSB_Configure(USBD_HANDLE_T hUsb, uint32_t cfg); +extern void hwUSB_ConfigEP(USBD_HANDLE_T hUsb, USB_ENDPOINT_DESCRIPTOR *pEPD); +extern void hwUSB_DirCtrlEP(USBD_HANDLE_T hUsb, uint32_t dir); +extern void hwUSB_EnableEP(USBD_HANDLE_T hUsb, uint32_t EPNum); +extern void hwUSB_DisableEP(USBD_HANDLE_T hUsb, uint32_t EPNum); +extern void hwUSB_ResetEP(USBD_HANDLE_T hUsb, uint32_t EPNum); +extern void hwUSB_SetStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum); +extern void hwUSB_ClrStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum); +extern ErrorCode_t hwUSB_SetTestMode(USBD_HANDLE_T hUsb, uint8_t mode); /* for FS only devices return ERR_USBD_INVALID_REQ */ +extern uint32_t hwUSB_ReadEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData); +extern uint32_t hwUSB_ReadReqEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t len); +extern uint32_t hwUSB_ReadSetupPkt(USBD_HANDLE_T hUsb, uint32_t, uint32_t *); +extern uint32_t hwUSB_WriteEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t cnt); + +/* generate resume signaling on the bus */ +extern void hwUSB_WakeUp(USBD_HANDLE_T hUsb); +extern ErrorCode_t hwUSB_EnableEvent(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t event_type, uint32_t enable); +/* TODO implement following routines +- function to program TD and queue them to ep Qh +*/ + +/** @endcond */ + + +#endif /* __USBHW_H__ */ diff --git a/inc/usbd/usbd_msc.h b/inc/usbd/usbd_msc.h new file mode 100644 index 0000000..d17e150 --- /dev/null +++ b/inc/usbd/usbd_msc.h @@ -0,0 +1,119 @@ +/*********************************************************************** +* $Id:: mw_usbd_msc.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* Mass Storage Class definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __MSC_H__ +#define __MSC_H__ + +#include "usbd.h" + +/** \file + * \brief Mass Storage class (MSC) descriptors. + * + * Definition of MSC class descriptors and their bit defines. + * + */ + +/* MSC Subclass Codes */ +#define MSC_SUBCLASS_RBC 0x01 +#define MSC_SUBCLASS_SFF8020I_MMC2 0x02 +#define MSC_SUBCLASS_QIC157 0x03 +#define MSC_SUBCLASS_UFI 0x04 +#define MSC_SUBCLASS_SFF8070I 0x05 +#define MSC_SUBCLASS_SCSI 0x06 + +/* MSC Protocol Codes */ +#define MSC_PROTOCOL_CBI_INT 0x00 +#define MSC_PROTOCOL_CBI_NOINT 0x01 +#define MSC_PROTOCOL_BULK_ONLY 0x50 + + +/* MSC Request Codes */ +#define MSC_REQUEST_RESET 0xFF +#define MSC_REQUEST_GET_MAX_LUN 0xFE + + +/* MSC Bulk-only Stage */ +#define MSC_BS_CBW 0 /* Command Block Wrapper */ +#define MSC_BS_DATA_OUT 1 /* Data Out Phase */ +#define MSC_BS_DATA_IN 2 /* Data In Phase */ +#define MSC_BS_DATA_IN_LAST 3 /* Data In Last Phase */ +#define MSC_BS_DATA_IN_LAST_STALL 4 /* Data In Last Phase with Stall */ +#define MSC_BS_CSW 5 /* Command Status Wrapper */ +#define MSC_BS_ERROR 6 /* Error */ + + +/* Bulk-only Command Block Wrapper */ +PRE_PACK struct POST_PACK _MSC_CBW +{ + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataLength; + uint8_t bmFlags; + uint8_t bLUN; + uint8_t bCBLength; + uint8_t CB[16]; +} ; +typedef struct _MSC_CBW MSC_CBW; + +/* Bulk-only Command Status Wrapper */ +PRE_PACK struct POST_PACK _MSC_CSW +{ + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataResidue; + uint8_t bStatus; +} ; +typedef struct _MSC_CSW MSC_CSW; + +#define MSC_CBW_Signature 0x43425355 +#define MSC_CSW_Signature 0x53425355 + + +/* CSW Status Definitions */ +#define CSW_CMD_PASSED 0x00 +#define CSW_CMD_FAILED 0x01 +#define CSW_PHASE_ERROR 0x02 + + +/* SCSI Commands */ +#define SCSI_TEST_UNIT_READY 0x00 +#define SCSI_REQUEST_SENSE 0x03 +#define SCSI_FORMAT_UNIT 0x04 +#define SCSI_INQUIRY 0x12 +#define SCSI_MODE_SELECT6 0x15 +#define SCSI_MODE_SENSE6 0x1A +#define SCSI_START_STOP_UNIT 0x1B +#define SCSI_MEDIA_REMOVAL 0x1E +#define SCSI_READ_FORMAT_CAPACITIES 0x23 +#define SCSI_READ_CAPACITY 0x25 +#define SCSI_READ10 0x28 +#define SCSI_WRITE10 0x2A +#define SCSI_VERIFY10 0x2F +#define SCSI_READ12 0xA8 +#define SCSI_WRITE12 0xAA +#define SCSI_MODE_SELECT10 0x55 +#define SCSI_MODE_SENSE10 0x5A + + +#endif /* __MSC_H__ */ diff --git a/inc/usbd/usbd_mscuser.h b/inc/usbd/usbd_mscuser.h new file mode 100644 index 0000000..1010707 --- /dev/null +++ b/inc/usbd/usbd_mscuser.h @@ -0,0 +1,270 @@ +/*********************************************************************** +* $Id:: mw_usbd_mscuser.h 577 2012-11-20 01:42:04Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* Mass Storage Class Custom User Module definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __MSCUSER_H__ +#define __MSCUSER_H__ + +#include "error.h" +#include "usbd.h" +#include "usbd_msc.h" +#include "usbd_core.h" +#include "app_usbd_cfg.h" + +/** \file + * \brief Mass Storage Class (MSC) API structures and function prototypes. + * + * Definition of functions exported by ROM based MSC function driver. + * + */ + +/** \ingroup Group_USBD + * @defgroup USBD_MSC Mass Storage Class (MSC) Function Driver + * \section Sec_MSCModDescription Module Description + * MSC Class Function Driver module. This module contains an internal implementation of the USB MSC Class. + * User applications can use this class driver instead of implementing the MSC class manually + * via the low-level USBD_HW and USBD_Core APIs. + * + * This module is designed to simplify the user code by exposing only the required interface needed to interface with + * Devices using the USB MSC Class. + */ + +/** \brief Mass Storage class function driver initialization parameter data structure. + * \ingroup USBD_MSC + * + * \details This data structure is used to pass initialization parameters to the + * Mass Storage class function driver's init function. + * + */ +typedef struct USBD_MSC_INIT_PARAM +{ + /* memory allocation params */ + uint32_t mem_base; /**< Base memory location from where the stack can allocate + data and buffers. \note The memory address set in this field + should be accessible by USB DMA controller. Also this value + should be aligned on 4 byte boundary. + */ + uint32_t mem_size; /**< The size of memory buffer which stack can use. + \note The \em mem_size should be greater than the size + returned by USBD_MSC_API::GetMemSize() routine.*/ + /* mass storage params */ + uint8_t* InquiryStr; /**< Pointer to the 28 character string. This string is + sent in response to the SCSI Inquiry command. \note The data + pointed by the pointer should be of global scope. + */ + uint32_t BlockCount; /**< Number of blocks present in the mass storage device */ + uint32_t BlockSize; /**< Block size in number of bytes */ + uint32_t MemorySize; /**< Memory size in number of bytes */ + /** Pointer to the interface descriptor within the descriptor + * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T + * structure. The stack assumes both HS and FS use same BULK endpoints. + */ + + uint8_t* intf_desc; + /* user defined functions */ + + /** + * MSC Write callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a write command. + * + * \param[in] offset Destination start address. + * \param[in, out] src Pointer to a pointer to the source of data. Pointer-to-pointer + * is used to implement zero-copy buffers. See \ref USBD_ZeroCopy + * for more details on zero-copy concept. + * \param[in] length Number of bytes to be written. + * \return Nothing. + * + */ + void (*MSC_Write)( uint32_t offset, uint8_t** src, uint32_t length, uint32_t high_offset); + /** + * MSC Read callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a read command. + * + * \param[in] offset Source start address. + * \param[in, out] dst Pointer to a pointer to the source of data. The MSC function drivers + * implemented in stack are written with zero-copy model. Meaning the stack doesn't make an + * extra copy of buffer before writing/reading data from USB hardware FIFO. Hence the + * parameter is pointer to a pointer containing address buffer (uint8_t** dst). + * So that the user application can update the buffer pointer instead of copying data to + * address pointed by the parameter. /note The updated buffer address should be accessible + * by USB DMA master. If user doesn't want to use zero-copy model, then the user should copy + * data to the address pointed by the passed buffer pointer parameter and shouldn't change + * the address value. See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in] length Number of bytes to be read. + * \return Nothing. + * + */ + void (*MSC_Read)( uint32_t offset, uint8_t** dst, uint32_t length, uint32_t high_offset); + /** + * MSC Verify callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a verify command. The callback function should compare the buffer + * with the destination memory at the requested offset and + * + * \param[in] offset Destination start address. + * \param[in] buf Buffer containing the data sent by the host. + * \param[in] length Number of bytes to verify. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK If data in the buffer matches the data at destination + * \retval ERR_FAILED At least one byte is different. + * + */ + ErrorCode_t (*MSC_Verify)( uint32_t offset, uint8_t buf[], uint32_t length, uint32_t high_offset); + /** + * Optional callback function to optimize MSC_Write buffer transfer. + * + * This function is provided by the application software. This function gets called + * when host sends SCSI_WRITE10/SCSI_WRITE12 command. The callback function should + * update the \em buff_adr pointer so that the stack transfers the data directly + * to the target buffer. /note The updated buffer address should be accessible + * by USB DMA master. If user doesn't want to use zero-copy model, then the user + * should not update the buffer pointer. See \ref USBD_ZeroCopy for more details + * on zero-copy concept. + * + * \param[in] offset Destination start address. + * \param[in,out] buf Buffer containing the data sent by the host. + * \param[in] length Number of bytes to write. + * \return Nothing. + * + */ + void (*MSC_GetWriteBuf)( uint32_t offset, uint8_t** buff_adr, uint32_t length, uint32_t high_offset); + + /** + * Optional user override-able function to replace the default MSC class handler. + * + * The application software could override the default EP0 class handler with their + * own by providing the handler function address as this data member of the parameter + * structure. Application which like the default handler should set this data member + * to zero before calling the USBD_MSC_API::Init(). + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*MSC_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + + uint64_t MemorySize64; + +} USBD_MSC_INIT_PARAM_T; + +/** \brief MSC class API functions structure. + * \ingroup USBD_MSC + * + * This module exposes functions which interact directly with USB device controller hardware. + * + */ +typedef struct USBD_MSC_API +{ + /** \fn uint32_t GetMemSize(USBD_MSC_INIT_PARAM_T* param) + * Function to determine the memory required by the MSC function driver module. + * + * This function is called by application layer before calling pUsbApi->msc->Init(), to allocate memory used + * by MSC function driver module. The application should allocate the memory which is accessible by USB + * controller/DMA controller. + * \note Some memory areas are not accessible by all bus masters. + * + * \param[in] param Structure containing MSC function driver module initialization parameters. + * \return Returns the required memory size in bytes. + */ + uint32_t (*GetMemSize)(USBD_MSC_INIT_PARAM_T* param); + + /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param) + * Function to initialize MSC function driver module. + * + * This function is called by application layer to initialize MSC function driver module. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in, out] param Structure containing MSC function driver module initialization parameters. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte + * aligned or smaller than required. + * \retval ERR_API_INVALID_PARAM2 Either MSC_Write() or MSC_Read() or + * MSC_Verify() callbacks are not defined. + * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed. + * \retval ERR_USBD_BAD_EP_DESC Wrong endpoint descriptor is passed. + */ + ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param); + +} USBD_MSC_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes + *-----------------------------------------------------------------------------*/ +/** @cond ADVANCED_API */ + +typedef struct _MSC_CTRL_T +{ + /* If it's a USB HS, the max packet is 512, if it's USB FS, + the max packet is 64. Use 512 for both HS and FS. */ + /*ALIGNED(4)*/ uint8_t BulkBuf[USB_HS_MAX_BULK_PACKET]; /* Bulk In/Out Buffer */ + /*ALIGNED(4)*/MSC_CBW CBW; /* Command Block Wrapper */ + /*ALIGNED(4)*/MSC_CSW CSW; /* Command Status Wrapper */ + + USB_CORE_CTRL_T* pUsbCtrl; + + uint64_t Offset; /* R/W Offset */ + uint32_t Length; /* R/W Length */ + uint32_t BulkLen; /* Bulk In/Out Length */ + uint8_t* rx_buf; + + uint8_t BulkStage; /* Bulk Stage */ + uint8_t if_num; /* interface number */ + uint8_t epin_num; /* BULK IN endpoint number */ + uint8_t epout_num; /* BULK OUT endpoint number */ + uint32_t MemOK; /* Memory OK */ + + uint8_t* InquiryStr; + uint32_t BlockCount; + uint32_t BlockSize; + uint64_t MemorySize; + /* user defined functions */ + void (*MSC_Write)( uint32_t offset, uint8_t** src, uint32_t length, uint32_t high_offset); + void (*MSC_Read)( uint32_t offset, uint8_t** dst, uint32_t length, uint32_t high_offset); + ErrorCode_t (*MSC_Verify)( uint32_t offset, uint8_t src[], uint32_t length, uint32_t high_offset); + /* optional call back for MSC_Write optimization */ + void (*MSC_GetWriteBuf)( uint32_t offset, uint8_t** buff_adr, uint32_t length, uint32_t high_offset); + + +}USB_MSC_CTRL_T; + +/** @cond DIRECT_API */ +extern uint32_t mwMSC_GetMemSize(USBD_MSC_INIT_PARAM_T* param); +extern ErrorCode_t mwMSC_init(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param); +/** @endcond */ + +/** @endcond */ + + +#endif /* __MSCUSER_H__ */ diff --git a/inc/usbd/usbd_rom_api.h b/inc/usbd/usbd_rom_api.h new file mode 100644 index 0000000..b00bb52 --- /dev/null +++ b/inc/usbd/usbd_rom_api.h @@ -0,0 +1,92 @@ +/*********************************************************************** +* $Id:: mw_usbd_rom_api.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* ROM API Module definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __MW_USBD_ROM_API_H +#define __MW_USBD_ROM_API_H +/** \file + * \brief ROM API for USB device stack. + * + * Definition of functions exported by ROM based USB device stack. + * + */ + +#include "error.h" +#include "usbd.h" +#include "usbd_hw.h" +#include "usbd_core.h" +#include "usbd_mscuser.h" +#include "usbd_dfuuser.h" +#include "usbd_hiduser.h" +#include "usbd_cdcuser.h" + +/** \brief Main USBD API functions structure. + * \ingroup Group_USBD + * + * This structure contains pointer to various USB Device stack's sub-module + * function tables. This structure is used as main entry point to access + * various methods (grouped in sub-modules) exposed by ROM based USB device + * stack. + * + */ +typedef struct USBD_API +{ + const USBD_HW_API_T* hw; /**< Pointer to function table which exposes functions + which interact directly with USB device stack's core + layer.*/ + const USBD_CORE_API_T* core; /**< Pointer to function table which exposes functions + which interact directly with USB device controller + hardware.*/ + const USBD_MSC_API_T* msc; /**< Pointer to function table which exposes functions + provided by MSC function driver module. + */ + const USBD_DFU_API_T* dfu; /**< Pointer to function table which exposes functions + provided by DFU function driver module. + */ + const USBD_HID_API_T* hid; /**< Pointer to function table which exposes functions + provided by HID function driver module. + */ + const USBD_CDC_API_T* cdc; /**< Pointer to function table which exposes functions + provided by CDC-ACM function driver module. + */ + const uint32_t* reserved6; /**< Reserved for future function driver module. + */ + const uint32_t version; /**< Version identifier of USB ROM stack. The version is + defined as 0x0CHDMhCC where each nibble represents version + number of the corresponding component. + CC - 7:0 - 8bit core version number + h - 11:8 - 4bit hardware interface version number + M - 15:12 - 4bit MSC class module version number + D - 19:16 - 4bit DFU class module version number + H - 23:20 - 4bit HID class module version number + C - 27:24 - 4bit CDC class module version number + H - 31:28 - 4bit reserved + */ + +} USBD_API_T; + +/* Applications using USBD ROM API should define this instance. The pointer should be assigned a value computed based on chip definitions. */ +extern const USBD_API_T* g_pUsbApi; +#define USBD_API g_pUsbApi + +#endif /*__MW_USBD_ROM_API_H*/ + diff --git a/openocd-example.cfg b/openocd-example.cfg new file mode 100644 index 0000000..f4a3721 --- /dev/null +++ b/openocd-example.cfg @@ -0,0 +1,8 @@ +interface cmsis-dap +source [find target/lpc11xx.cfg] +adapter_khz 1000 +reset_config srst_only +$_TARGETNAME configure -event gdb-attach { + echo "Halting target" + halt +} diff --git a/src/DAP.c b/src/DAP.c new file mode 100644 index 0000000..9d03041 --- /dev/null +++ b/src/DAP.c @@ -0,0 +1,1364 @@ +/****************************************************************************** + * @file DAP.c + * @brief CMSIS-DAP Commands + * @version V1.00 + * @date 31. May 2012 + * + * @note + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#include +#include "DAP_config.h" +#include "DAP.h" + + +#define DAP_FW_VER "1.0" // Firmware Version + + +#if (DAP_PACKET_SIZE < 64) +#error "Minimum Packet Size is 64" +#endif +#if (DAP_PACKET_SIZE > 32768) +#error "Maximum Packet Size is 32768" +#endif +#if (DAP_PACKET_COUNT < 1) +#error "Minimum Packet Count is 1" +#endif +#if (DAP_PACKET_COUNT > 255) +#error "Maximum Packet Count is 255" +#endif + + +// Clock Macros + +#define MAX_SWJ_CLOCK(delay_cycles) \ + (CPU_CLOCK/2 / (IO_PORT_WRITE_CYCLES + delay_cycles)) + +#define CLOCK_DELAY(swj_clock) \ + ((CPU_CLOCK/2 / swj_clock) - IO_PORT_WRITE_CYCLES) + + + DAP_Data_t DAP_Data; // DAP Data +volatile uint8_t DAP_TransferAbort; // Trasfer Abort Flag + + +#ifdef DAP_VENDOR +const char DAP_Vendor [] = DAP_VENDOR; +#endif +#ifdef DAP_PRODUCT +const char DAP_Product[] = DAP_PRODUCT; +#endif +#ifdef DAP_SER_NUM +const char DAP_SerNum [] = DAP_SER_NUM; +#endif +const char DAP_FW_Ver [] = DAP_FW_VER; + +#if TARGET_DEVICE_FIXED +const char TargetDeviceVendor [] = TARGET_DEVICE_VENDOR; +const char TargetDeviceName [] = TARGET_DEVICE_NAME; +#endif + + +// Get DAP Information +// id: info identifier +// info: pointer to info data +// return: number of bytes in info data +static uint8_t DAP_Info(uint8_t id, uint8_t *info) { + uint8_t length = 0; + + switch (id) { + case DAP_ID_VENDOR: +#ifdef DAP_VENDOR + memcpy(info, DAP_Vendor, sizeof(DAP_Vendor)); + length = sizeof(DAP_Vendor); +#endif + break; + case DAP_ID_PRODUCT: +#ifdef DAP_PRODUCT + memcpy(info, DAP_Product, sizeof(DAP_Product)); + length = sizeof(DAP_Product); +#endif + break; + case DAP_ID_SER_NUM: +#ifdef DAP_SER_NUM + memcpy(info, DAP_SerNum, sizeof(DAP_SerNum)); + length = sizeof(DAP_SerNum); +#endif + break; + case DAP_ID_FW_VER: + memcpy(info, DAP_FW_Ver, sizeof(DAP_FW_Ver)); + length = sizeof(DAP_FW_Ver); + break; + case DAP_ID_DEVICE_VENDOR: +#if TARGET_DEVICE_FIXED + memcpy(info, TargetDeviceVendor, sizeof(TargetDeviceVendor)); + length = sizeof(TargetDeviceVendor); +#endif + break; + case DAP_ID_DEVICE_NAME: +#if TARGET_DEVICE_FIXED + memcpy(info, TargetDeviceName, sizeof(TargetDeviceName)); + length = sizeof(TargetDeviceName); +#endif + break; + case DAP_ID_CAPABILITIES: + info[0] = ((DAP_SWD != 0) ? (1 << 0) : 0) | + ((DAP_JTAG != 0) ? (1 << 1) : 0); + length = 1; + break; + case DAP_ID_PACKET_SIZE: + info[0] = (uint8_t)(DAP_PACKET_SIZE >> 0); + info[1] = (uint8_t)(DAP_PACKET_SIZE >> 8); + length = 2; + break; + case DAP_ID_PACKET_COUNT: + info[0] = DAP_PACKET_COUNT; + length = 1; + break; + } + + return (length); +} + + +// Timer Functions + +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) + +// Start Timer +static __inline void TIMER_START (uint32_t usec) { + SysTick->VAL = 0; + SysTick->LOAD = usec * CPU_CLOCK/1000000; + SysTick->CTRL = (1 << SysTick_CTRL_ENABLE_Pos) | + (1 << SysTick_CTRL_CLKSOURCE_Pos); +} + +// Stop Timer +static __inline void TIMER_STOP (void) { + SysTick->CTRL = 0; +} + +// Check if Timer expired +static __inline uint32_t TIMER_EXPIRED (void) { + return ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) ? 1 : 0); +} + +#endif + + +// Delay for specified time +// delay: delay time in ms +void Delayms(uint32_t delay) { + delay *= (CPU_CLOCK/1000 + (DELAY_SLOW_CYCLES-1)) / DELAY_SLOW_CYCLES; + PIN_DELAY_SLOW(delay); +} + + +// Process Delay command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_Delay(uint8_t *request, uint8_t *response) { + uint32_t delay; + + delay = *(request+0) | (*(request+1) << 8); + delay *= (CPU_CLOCK/1000000 + (DELAY_SLOW_CYCLES-1)) / DELAY_SLOW_CYCLES; + + PIN_DELAY_SLOW(delay); + + *response = DAP_OK; + return (1); +} + + +// Process LED command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_LED(uint8_t *request, uint8_t *response) { + + switch (*request) { + case DAP_LED_DEBUGGER_CONNECTED: + LED_CONNECTED_OUT((*(request+1) & 1)); + break; + case DAP_LED_TARGET_RUNNING: + LED_RUNNING_OUT((*(request+1) & 1)); + break; + default: + *response = DAP_ERROR; + return (1); + } + + *response = DAP_OK; + return (1); +} + + +// Process Connect command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_Connect(uint8_t *request, uint8_t *response) { + uint32_t port; + + if (*request == DAP_PORT_AUTODETECT) { + port = DAP_DEFAULT_PORT; + } else { + port = *request; + } + + switch (port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + DAP_Data.debug_port = DAP_PORT_SWD; + PORT_SWD_SETUP(); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + DAP_Data.debug_port = DAP_PORT_JTAG; + PORT_JTAG_SETUP(); + break; +#endif + default: + *response = DAP_PORT_DISABLED; + return (1); + } + + *response = port; + return (1); +} + + +// Process Disconnect command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_Disconnect(uint8_t *response) { + + DAP_Data.debug_port = DAP_PORT_DISABLED; + PORT_OFF(); + + *response = DAP_OK; + return (1); +} + + +// Process Reset Target command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_ResetTarget(uint8_t *response) { + + *(response+1) = RESET_TARGET(); + *(response+0) = DAP_OK; + return (2); +} + + +// Process SWJ Pins command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) +static uint32_t DAP_SWJ_Pins(uint8_t *request, uint8_t *response) { + uint32_t value; + uint32_t select; + uint32_t wait; + + value = *(request+0); + select = *(request+1); + wait = (*(request+2) << 0) | + (*(request+3) << 8) | + (*(request+4) << 16) | + (*(request+5) << 24); + + if (select & (1 << DAP_SWJ_SWCLK_TCK)) { + if (value & (1 << DAP_SWJ_SWCLK_TCK)) { + PIN_SWCLK_TCK_SET(); + } else { + PIN_SWCLK_TCK_CLR(); + } + } + if (select & (1 << DAP_SWJ_SWDIO_TMS)) { + if (value & (1 << DAP_SWJ_SWDIO_TMS)) { + PIN_SWDIO_TMS_SET(); + } else { + PIN_SWDIO_TMS_CLR(); + } + } + if (select & (1 << DAP_SWJ_TDI)) { + PIN_TDI_OUT(value >> DAP_SWJ_TDI); + } + if (select & (1 << DAP_SWJ_nTRST)) { + PIN_nTRST_OUT(value >> DAP_SWJ_nTRST); + } + if (select & (1 << DAP_SWJ_nRESET)) { + PIN_nRESET_OUT(value >> DAP_SWJ_nRESET); + } + + if (wait) { + if (wait > 3000000) wait = 3000000; + TIMER_START(wait); + do { + if (select & (1 << DAP_SWJ_SWCLK_TCK)) { + if ((value >> DAP_SWJ_SWCLK_TCK) ^ PIN_SWCLK_TCK_IN()) continue; + } + if (select & (1 << DAP_SWJ_SWDIO_TMS)) { + if ((value >> DAP_SWJ_SWDIO_TMS) ^ PIN_SWDIO_TMS_IN()) continue; + } + if (select & (1 << DAP_SWJ_TDI)) { + if ((value >> DAP_SWJ_TDI) ^ PIN_TDI_IN()) continue; + } + if (select & (1 << DAP_SWJ_nTRST)) { + if ((value >> DAP_SWJ_nTRST) ^ PIN_nTRST_IN()) continue; + } + if (select & (1 << DAP_SWJ_nRESET)) { + if ((value >> DAP_SWJ_nRESET) ^ PIN_nRESET_IN()) continue; + } + break; + } while (!TIMER_EXPIRED()); + TIMER_STOP(); + } + + value = (PIN_SWCLK_TCK_IN() << DAP_SWJ_SWCLK_TCK) | + (PIN_SWDIO_TMS_IN() << DAP_SWJ_SWDIO_TMS) | + (PIN_TDI_IN() << DAP_SWJ_TDI) | + (PIN_TDO_IN() << DAP_SWJ_TDO) | + (PIN_nTRST_IN() << DAP_SWJ_nTRST) | + (PIN_nRESET_IN() << DAP_SWJ_nRESET); + + *response = (uint8_t)value; + return (1); +} +#endif + + +// Process SWJ Clock command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) +static uint32_t DAP_SWJ_Clock(uint8_t *request, uint8_t *response) { + uint32_t clock; + uint32_t delay; + + clock = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + + if (clock == 0) { + *response = DAP_ERROR; + return (1); + } + + if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) { + DAP_Data.fast_clock = 1; + DAP_Data.clock_delay = 1; + } else { + DAP_Data.fast_clock = 0; + + delay = (CPU_CLOCK/2 + (clock - 1)) / clock; + if (delay > IO_PORT_WRITE_CYCLES) { + delay -= IO_PORT_WRITE_CYCLES; + delay = (delay + (DELAY_SLOW_CYCLES - 1)) / DELAY_SLOW_CYCLES; + } else { + delay = 1; + } + + DAP_Data.clock_delay = delay; + } + + *response = DAP_OK; + return (1); +} +#endif + + +// Process SWJ Sequence command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) +static uint32_t DAP_SWJ_Sequence(uint8_t *request, uint8_t *response) { + uint32_t count; + + count = *request++; + if (count == 0) count = 256; + + SWJ_Sequence(count, request); + + *response = DAP_OK; + return (1); +} +#endif + + +// Process SWD Configure command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_SWD != 0) +static uint32_t DAP_SWD_Configure(uint8_t *request, uint8_t *response) { + uint8_t value; + + value = *request; + DAP_Data.swd_conf.turnaround = (value & 0x03) + 1; + DAP_Data.swd_conf.data_phase = (value & 0x04) ? 1 : 0; + + *response = DAP_OK; + + return (1); +} +#endif + + +// Process SWD Abort command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_SWD != 0) +static uint32_t DAP_SWD_Abort(uint8_t *request, uint8_t *response) { + uint32_t data; + + if (DAP_Data.debug_port != DAP_PORT_SWD) { + *response = DAP_ERROR; + return (1); + } + + // Load data (Ignore DAP index) + data = (*(request+1) << 0) | + (*(request+2) << 8) | + (*(request+3) << 16) | + (*(request+4) << 24); + + // Write Abort register + SWD_Transfer(DP_ABORT, &data); + *response = DAP_OK; + + return (1); +} +#endif + + +// Process JTAG Sequence command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_Sequence(uint8_t *request, uint8_t *response) { + uint32_t sequence_info; + uint32_t sequence_count; + uint32_t response_count; + uint32_t count; + + *response++ = DAP_OK; + response_count = 1; + + sequence_count = *request++; + while (sequence_count--) { + sequence_info = *request++; + JTAG_Sequence(sequence_info, request, response); + count = sequence_info & JTAG_SEQUENCE_TCK; + if (count == 0) count = 64; + count = (count + 7) / 8; + request += count; + if (sequence_info & JTAG_SEQUENCE_TDO) { + response += count; + response_count += count; + } + } + + return (response_count); +} +#endif + + +// Process JTAG Configure command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_Configure(uint8_t *request, uint8_t *response) { + uint32_t count; + uint32_t length; + uint32_t bits; + uint32_t n; + + count = *request++; + DAP_Data.jtag_dev.count = count; + + bits = 0; + for (n = 0; n < count; n++) { + length = *request++; + DAP_Data.jtag_dev.ir_length[n] = length; + DAP_Data.jtag_dev.ir_before[n] = bits; + bits += length; + } + for (n = 0; n < count; n++) { + bits -= DAP_Data.jtag_dev.ir_length[n]; + DAP_Data.jtag_dev.ir_after[n] = bits; + } + + *response = DAP_OK; + return (1); +} +#endif + + +// Process JTAG IDCODE command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_IDCode(uint8_t *request, uint8_t *response) { + uint32_t data; + + if (DAP_Data.debug_port != DAP_PORT_JTAG) { +err:*response = DAP_ERROR; + return (1); + } + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto err; + + // Select JTAG chain + JTAG_IR(JTAG_IDCODE); + + // Read IDCODE register + data = JTAG_ReadIDCode(); + + // Store Data + *(response+0) = DAP_OK; + *(response+1) = (uint8_t)(data >> 0); + *(response+2) = (uint8_t)(data >> 8); + *(response+3) = (uint8_t)(data >> 16); + *(response+4) = (uint8_t)(data >> 24); + + return (1+4); +} +#endif + + +// Process JTAG Abort command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_Abort(uint8_t *request, uint8_t *response) { + uint32_t data; + + if (DAP_Data.debug_port != DAP_PORT_JTAG) { +err:*response = DAP_ERROR; + return (1); + } + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto err; + + // Select JTAG chain + JTAG_IR(JTAG_ABORT); + + // Load data + data = (*(request+1) << 0) | + (*(request+2) << 8) | + (*(request+3) << 16) | + (*(request+4) << 24); + + // Write Abort register + JTAG_WriteAbort(data); + *response = DAP_OK; + + return (1); +} +#endif + + +// Process Transfer Configure command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_TransferConfigure(uint8_t *request, uint8_t *response) { + + DAP_Data.transfer.idle_cycles = *(request+0); + DAP_Data.transfer.retry_count = *(request+1) | (*(request+2) << 8); + DAP_Data.transfer.match_retry = *(request+3) | (*(request+4) << 8); + + *response = DAP_OK; + + return (1); +} + + +// Process SWD Transfer command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_SWD != 0) +static uint32_t DAP_SWD_Transfer(uint8_t *request, uint8_t *response) { + uint32_t request_count; + uint32_t request_value; + uint32_t response_count; + uint32_t response_value; + uint8_t *response_head; + uint32_t post_read; + uint32_t check_write; + uint32_t match_value; + uint32_t match_retry; + uint32_t retry; + uint32_t data; + + response_count = 0; + response_value = 0; + response_head = response; + response += 2; + + DAP_TransferAbort = 0; + + post_read = 0; + check_write = 0; + + request++; // Ignore DAP index + + request_count = *request++; + while (request_count--) { + request_value = *request++; + if (request_value & DAP_TRANSFER_RnW) { + // Read register + if (post_read) { + // Read was posted before + retry = DAP_Data.transfer.retry_count; + if ((request_value & (DAP_TRANSFER_APnDP | DAP_TRANSFER_MATCH_VALUE)) == DAP_TRANSFER_APnDP) { + // Read previous AP data and post next AP read + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } else { + // Read previous AP data + do { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + post_read = 0; + } + if (response_value != DAP_TRANSFER_OK) break; + // Store previous AP data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } + if (request_value & DAP_TRANSFER_MATCH_VALUE) { + // Read with value match + match_value = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + match_retry = DAP_Data.transfer.match_retry; + if (request_value & DAP_TRANSFER_APnDP) { + // Post AP read + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + } + do { + // Read register until its value matches or retry counter expires + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + } while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort); + if ((data & DAP_Data.transfer.match_mask) != match_value) { + response_value |= DAP_TRANSFER_MISMATCH; + } + if (response_value != DAP_TRANSFER_OK) break; + } else { + // Normal read + retry = DAP_Data.transfer.retry_count; + if (request_value & DAP_TRANSFER_APnDP) { + // Read AP register + if (post_read == 0) { + // Post AP read + do { + response_value = SWD_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + post_read = 1; + } + } else { + // Read DP register + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + // Store data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } + } + check_write = 0; + } else { + // Write register + if (post_read) { + // Read previous data + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + // Store previous data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + post_read = 0; + } + // Load data + data = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + if (request_value & DAP_TRANSFER_MATCH_MASK) { + // Write match mask + DAP_Data.transfer.match_mask = data; + response_value = DAP_TRANSFER_OK; + } else { + // Write DP/AP register + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + check_write = 1; + } + } + response_count++; + if (DAP_TransferAbort) break; + } + + if (response_value == DAP_TRANSFER_OK) { + if (post_read) { + // Read previous data + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) goto end; + // Store previous data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } else if (check_write) { + // Check last write + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + } + +end: + *(response_head+0) = (uint8_t)response_count; + *(response_head+1) = (uint8_t)response_value; + + return (response - response_head); +} +#endif + + +// Process JTAG Transfer command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_Transfer(uint8_t *request, uint8_t *response) { + uint32_t request_count; + uint32_t request_value; + uint32_t request_ir; + uint32_t response_count; + uint32_t response_value; + uint8_t *response_head; + uint32_t post_read; + uint32_t match_value; + uint32_t match_retry; + uint32_t retry; + uint32_t data; + uint32_t ir; + + response_count = 0; + response_value = 0; + response_head = response; + response += 2; + + DAP_TransferAbort = 0; + + ir = 0; + post_read = 0; + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request++; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto end; + + request_count = *request++; + while (request_count--) { + request_value = *request++; + request_ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC; + if (request_value & DAP_TRANSFER_RnW) { + // Read register + if (post_read) { + // Read was posted before + retry = DAP_Data.transfer.retry_count; + if ((ir == request_ir) && ((request_value & DAP_TRANSFER_MATCH_VALUE) == 0)) { + // Read previous data and post next read + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } else { + // Select JTAG chain + if (ir != JTAG_DPACC) { + ir = JTAG_DPACC; + JTAG_IR(ir); + } + // Read previous data + do { + response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + post_read = 0; + } + if (response_value != DAP_TRANSFER_OK) break; + // Store previous data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } + if (request_value & DAP_TRANSFER_MATCH_VALUE) { + // Read with value match + match_value = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + match_retry = DAP_Data.transfer.match_retry; + // Select JTAG chain + if (ir != request_ir) { + ir = request_ir; + JTAG_IR(ir); + } + // Post DP/AP read + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + do { + // Read register until its value matches or retry counter expires + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + } while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort); + if ((data & DAP_Data.transfer.match_mask) != match_value) { + response_value |= DAP_TRANSFER_MISMATCH; + } + if (response_value != DAP_TRANSFER_OK) break; + } else { + // Normal read + if (post_read == 0) { + // Select JTAG chain + if (ir != request_ir) { + ir = request_ir; + JTAG_IR(ir); + } + // Post DP/AP read + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + post_read = 1; + } + } + } else { + // Write register + if (post_read) { + // Select JTAG chain + if (ir != JTAG_DPACC) { + ir = JTAG_DPACC; + JTAG_IR(ir); + } + // Read previous data + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + // Store previous data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + post_read = 0; + } + // Load data + data = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + if (request_value & DAP_TRANSFER_MATCH_MASK) { + // Write match mask + DAP_Data.transfer.match_mask = data; + response_value = DAP_TRANSFER_OK; + } else { + // Select JTAG chain + if (ir != request_ir) { + ir = request_ir; + JTAG_IR(ir); + } + // Write DP/AP register + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + } + } + response_count++; + if (DAP_TransferAbort) break; + } + + if (response_value == DAP_TRANSFER_OK) { + // Select JTAG chain + if (ir != JTAG_DPACC) { + ir = JTAG_DPACC; + JTAG_IR(ir); + } + if (post_read) { + // Read previous data + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) goto end; + // Store previous data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } else { + // Check last write + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + } + +end: + *(response_head+0) = (uint8_t)response_count; + *(response_head+1) = (uint8_t)response_value; + + return (response - response_head); +} +#endif + + +// Process SWD Transfer Block command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_SWD != 0) +static uint32_t DAP_SWD_TransferBlock(uint8_t *request, uint8_t *response) { + uint32_t request_count; + uint32_t request_value; + uint32_t response_count; + uint32_t response_value; + uint8_t *response_head; + uint32_t retry; + uint32_t data; + + response_count = 0; + response_value = 0; + response_head = response; + response += 3; + + DAP_TransferAbort = 0; + + request++; // Ignore DAP index + + request_count = *request | (*(request+1) << 8); + request += 2; + if (request_count == 0) goto end; + + request_value = *request++; + if (request_value & DAP_TRANSFER_RnW) { + // Read register block + if (request_value & DAP_TRANSFER_APnDP) { + // Post AP read + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) goto end; + } + while (request_count--) { + // Read DP/AP register + if ((request_count == 0) && (request_value & DAP_TRANSFER_APnDP)) { + // Last AP read + request_value = DP_RDBUFF | DAP_TRANSFER_RnW; + } + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) goto end; + // Store data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + response_count++; + } + } else { + // Write register block + while (request_count--) { + // Load data + data = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + // Write DP/AP register + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) goto end; + response_count++; + } + // Check last write + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + +end: + *(response_head+0) = (uint8_t)(response_count >> 0); + *(response_head+1) = (uint8_t)(response_count >> 8); + *(response_head+2) = (uint8_t) response_value; + + return (response - response_head); +} +#endif + + +// Process JTAG Transfer Block command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_TransferBlock(uint8_t *request, uint8_t *response) { + uint32_t request_count; + uint32_t request_value; + uint32_t response_count; + uint32_t response_value; + uint8_t *response_head; + uint32_t retry; + uint32_t data; + uint32_t ir; + + response_count = 0; + response_value = 0; + response_head = response; + response += 3; + + DAP_TransferAbort = 0; + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request++; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto end; + + request_count = *request | (*(request+1) << 8); + request += 2; + if (request_count == 0) goto end; + + request_value = *request++; + + // Select JTAG chain + ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC; + JTAG_IR(ir); + + if (request_value & DAP_TRANSFER_RnW) { + // Post read + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) goto end; + // Read register block + while (request_count--) { + // Read DP/AP register + if (request_count == 0) { + // Last read + if (ir != JTAG_DPACC) { + JTAG_IR(JTAG_DPACC); + } + request_value = DP_RDBUFF | DAP_TRANSFER_RnW; + } + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) goto end; + // Store data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + response_count++; + } + } else { + // Write register block + while (request_count--) { + // Load data + data = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + // Write DP/AP register + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) goto end; + response_count++; + } + // Check last write + if (ir != JTAG_DPACC) { + JTAG_IR(JTAG_DPACC); + } + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + +end: + *(response_head+0) = (uint8_t)(response_count >> 0); + *(response_head+1) = (uint8_t)(response_count >> 8); + *(response_head+2) = (uint8_t) response_value; + + return (response - response_head); +} +#endif + + +// Process DAP Vendor command and prepare response +// Default function (can be overridden) +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +__weak uint32_t DAP_ProcessVendorCommand(uint8_t *request, uint8_t *response) { + *response = ID_DAP_Invalid; + return (1); +} + + +// Process DAP command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +uint32_t DAP_ProcessCommand(uint8_t *request, uint8_t *response) { + uint32_t num; + + if ((*request >= ID_DAP_Vendor0) && (*request <= ID_DAP_Vendor31)) { + return DAP_ProcessVendorCommand(request, response); + } + + *response++ = *request; + + switch (*request++) { + case ID_DAP_Info: + num = DAP_Info(*request, response+1); + *response = num; + return (2 + num); + case ID_DAP_LED: + num = DAP_LED(request, response); + break; + case ID_DAP_Connect: + num = DAP_Connect(request, response); + break; + case ID_DAP_Disconnect: + num = DAP_Disconnect(response); + break; + case ID_DAP_Delay: + num = DAP_Delay(request, response); + break; + case ID_DAP_ResetTarget: + num = DAP_ResetTarget(response); + break; + +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) + case ID_DAP_SWJ_Pins: + num = DAP_SWJ_Pins(request, response); + break; + case ID_DAP_SWJ_Clock: + num = DAP_SWJ_Clock(request, response); + break; + case ID_DAP_SWJ_Sequence: + num = DAP_SWJ_Sequence(request, response); + break; +#else + case ID_DAP_SWJ_Pins: + case ID_DAP_SWJ_Clock: + case ID_DAP_SWJ_Sequence: + *response = DAP_ERROR; + return (2); +#endif + +#if (DAP_SWD != 0) + case ID_DAP_SWD_Configure: + num = DAP_SWD_Configure(request, response); + break; +#else + case ID_DAP_SWD_Configure: + *response = DAP_ERROR; + return (2); +#endif + +#if (DAP_JTAG != 0) + case ID_DAP_JTAG_Sequence: + num = DAP_JTAG_Sequence(request, response); + break; + case ID_DAP_JTAG_Configure: + num = DAP_JTAG_Configure(request, response); + break; + case ID_DAP_JTAG_IDCODE: + num = DAP_JTAG_IDCode(request, response); + break; +#else + case ID_DAP_JTAG_Sequence: + case ID_DAP_JTAG_Configure: + case ID_DAP_JTAG_IDCODE: + *response = DAP_ERROR; + return (2); +#endif + + case ID_DAP_TransferConfigure: + num = DAP_TransferConfigure(request, response); + break; + + case ID_DAP_Transfer: + switch (DAP_Data.debug_port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + num = DAP_SWD_Transfer (request, response); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + num = DAP_JTAG_Transfer(request, response); + break; +#endif + default: + *(response+0) = 0; // Response count + *(response+1) = 0; // Response value + num = 2; + } + break; + + case ID_DAP_TransferBlock: + switch (DAP_Data.debug_port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + num = DAP_SWD_TransferBlock (request, response); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + num = DAP_JTAG_TransferBlock(request, response); + break; +#endif + default: + *(response+0) = 0; // Response count [7:0] + *(response+1) = 0; // Response count[15:8] + *(response+2) = 0; // Response value + num = 3; + } + break; + + case ID_DAP_WriteABORT: + switch (DAP_Data.debug_port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + num = DAP_SWD_Abort (request, response); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + num = DAP_JTAG_Abort(request, response); + break; +#endif + default: + *response = DAP_ERROR; + return (2); + } + break; + + default: + *(response-1) = ID_DAP_Invalid; + return (1); + } + + return (1 + num); +} + + +// Setup DAP +void DAP_Setup(void) { + + // Default settings (only non-zero values) +//DAP_Data.debug_port = 0; +//DAP_Data.fast_clock = 0; + DAP_Data.clock_delay = CLOCK_DELAY(DAP_DEFAULT_SWJ_CLOCK); +//DAP_Data.transfer.idle_cycles = 0; + DAP_Data.transfer.retry_count = 100; +//DAP_Data.transfer.match_retry = 0; +//DAP_Data.transfer.match_mask = 0x000000; +#if (DAP_SWD != 0) + DAP_Data.swd_conf.turnaround = 1; +//DAP_Data.swd_conf.data_phase = 0; +#endif +#if (DAP_JTAG != 0) +//DAP_Data.jtag_dev.count = 0; +#endif + + DAP_SETUP(); // Device specific setup +} diff --git a/src/IBDAP.c b/src/IBDAP.c new file mode 100755 index 0000000..62ad775 --- /dev/null +++ b/src/IBDAP.c @@ -0,0 +1,251 @@ +/* +=============================================================================== + Name : IBDAP.c + Author : $(author) + Version : + Copyright : $(copyright) + Description : main definition +=============================================================================== +*/ + +#ifdef __USE_CMSIS +#include "LPC11Uxx.h" +#endif + +#include "DAP_config.h" + +#include "DAP.h" + +#include "usb_driver.h" + + + +#define TICKRATE_100msec (10) +#define TICKRATE_10msec (100) +#define TICKRATE_1msec (1000) + +#define TICKRATE TICKRATE_1msec + +// Connected LED RED PIN 21: PIO0_11 +#define LED_ERROR_PORT 0 +#define LED_ERROR_BIT 11 +#define IOCON_ERROR_REG (LPC_IOCON->TDI_PIO0_11) + +void indicator_code (int code); + +void init_error_led () { + IOCON_ERROR_REG = 1 | 1 << 4 | 1 << 7; + LPC_GPIO->DIR[LED_ERROR_PORT] |= 1 << LED_ERROR_BIT; + LPC_GPIO->SET[LED_ERROR_PORT] = 1 << LED_ERROR_BIT; +} + +INLINE void LED_ERROR_ON () { + LPC_GPIO->CLR[LED_ERROR_PORT] = 1 << LED_ERROR_BIT; +} + +INLINE void LED_ERROR_OFF () { + LPC_GPIO->SET[LED_ERROR_PORT] = 1 << LED_ERROR_BIT; +} + + +static volatile uint32_t sys_time = 0; + + +void SysTick_Handler () { + sys_time++; +} + +void sleep_ms (int ms) { + + int e = sys_time * (1000/TICKRATE) + ms; + while ((sys_time * (1000/TICKRATE)) <= e) { + __WFI (); + } +} + +// HID callbacks and buffer + +typedef struct _IBDAP_HND_T { + volatile uint8_t usb_outs_end_idx; + volatile uint8_t usb_outs_start_idx; + uint8_t usb_outs[DAP_PACKET_COUNT][DAP_PACKET_SIZE]; + volatile uint8_t usb_ins_end_idx; + volatile uint8_t usb_ins_start_idx; + volatile uint8_t usb_ins_busy; + uint8_t usb_ins[DAP_PACKET_COUNT][DAP_PACKET_SIZE]; +}IBDAP_HND_T; + +IBDAP_HND_T* ibdap = 0; + + +ErrorCode_t DAP_GetReport_Callback( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length) { + return LPC_OK; +} + +ErrorCode_t DAP_SetReport_Callback( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length) { + return LPC_OK; +} + +ErrorCode_t DAP_EpInOut_Hdlr_Callback (USBD_HANDLE_T hUsb, void* data, uint32_t event) { + USB_HID_CTRL_T *pHidCtrl = (USB_HID_CTRL_T *) data; + switch (event) { + case USB_EVT_IN: + if (ibdap->usb_ins_start_idx == ibdap->usb_ins_end_idx) { + ibdap->usb_ins_busy = 0; + break; + } + USBD_API->hw->WriteEP(hUsb, pHidCtrl->epin_adr, ibdap->usb_ins[ibdap->usb_ins_start_idx], DAP_PACKET_SIZE); + ibdap->usb_ins_start_idx = (ibdap->usb_ins_start_idx+1) % DAP_PACKET_COUNT; + //LED_RUNNING_OUT (1); + //LED_CONNECTED_OUT (0); + break; + case USB_EVT_OUT: + USBD_API->hw->ReadEP(hUsb, pHidCtrl->epout_adr, ibdap->usb_outs[ibdap->usb_outs_end_idx]); + ibdap->usb_outs_end_idx = (ibdap->usb_outs_end_idx+1) % DAP_PACKET_COUNT; + //LED_CONNECTED_OUT (1); + //LED_RUNNING_OUT (0); + break; + } + return LPC_OK; +} + +void suspend () { + while (1) { + LED_ERROR_ON (); + sleep_ms (1000); + LED_ERROR_OFF (); + sleep_ms (1000); + } +} + +void error_code (int code) { + LED_ERROR_ON (); + while (1) { + if (code & 0x01 && !(code & 0x02 )) { // code == 1 + LED_CONNECTED_OUT (1); + LED_RUNNING_OUT (0); + sleep_ms (1000); + LED_CONNECTED_OUT (0); + } else if (!(code & 0x01) && (code & 0x02)) { // code == 2 + LED_CONNECTED_OUT (0); + LED_RUNNING_OUT (1); + sleep_ms (1000); + LED_RUNNING_OUT (0); + } else if ((code & 0x01) == 3) { + LED_CONNECTED_OUT (1); + LED_RUNNING_OUT (1); + sleep_ms (1000); + LED_CONNECTED_OUT (0); + LED_RUNNING_OUT (0); + } else { + LED_CONNECTED_OUT (1); + LED_RUNNING_OUT (0); + sleep_ms (1000); + LED_CONNECTED_OUT (0); + LED_RUNNING_OUT (1); + } + + sleep_ms (1000); + } +} + +void indicator_code (int code) { + LED_ERROR_OFF (); + while (1) { + if (code & 0x01 && !(code & 0x02 )) { // code == 1 + LED_CONNECTED_OUT (1); + LED_RUNNING_OUT (0); + sleep_ms (1000); + LED_CONNECTED_OUT (0); + } else if (!(code & 0x01) && (code & 0x02)) { // code == 2 + LED_CONNECTED_OUT (0); + LED_RUNNING_OUT (1); + sleep_ms (1000); + LED_RUNNING_OUT (0); + } else if ((code & 0x01) == 3) { + LED_CONNECTED_OUT (1); + LED_RUNNING_OUT (1); + sleep_ms (1000); + LED_CONNECTED_OUT (0); + LED_RUNNING_OUT (0); + } else { + LED_CONNECTED_OUT (1); + LED_RUNNING_OUT (0); + sleep_ms (1000); + LED_CONNECTED_OUT (0); + LED_RUNNING_OUT (1); + } + + sleep_ms (1000); + } +} +// TODO: insert other definitions and declarations here + +void device_boot() { + LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 6; // enable gpio clock +} + +int main(void) { + + device_boot(); + + USBD_API_INIT_PARAM_T usb_param; + + SysTick_Config(SystemCoreClock / TICKRATE); + + init_error_led (); + + DAP_Setup (); + + + init_usb_clock (); + init_usb_power (); + if (init_usb_driver (&usb_param)) { + // printf error; + // LED error; + suspend (); + return -1; + } + + if (init_usb_hid (&usb_param, + &DAP_GetReport_Callback, &DAP_SetReport_Callback, + &DAP_EpInOut_Hdlr_Callback, &DAP_EpInOut_Hdlr_Callback, + (uint8_t**)&ibdap, sizeof (IBDAP_HND_T))) { + // printf error; + // LED error; + error_code (1); + return -1; + } + + connect_to_usb_bus (); + //LED_ERROR_ON (); + while (1) { + /* + LED_ERROR_ON (); + sleep_ms (500); + LED_ERROR_OFF (); + sleep_ms (1000); + */ + if (ibdap->usb_outs_start_idx == ibdap->usb_outs_end_idx) { + //LED_ERROR_ON (); + __WFI (); + continue; + } else { + LED_CONNECTED_OUT (1); + } + //LED_ERROR_OFF (); + DAP_ProcessCommand (ibdap->usb_outs[ibdap->usb_outs_start_idx], ibdap->usb_ins[ibdap->usb_ins_end_idx]); + ibdap->usb_outs_start_idx = (ibdap->usb_outs_start_idx+1) % DAP_PACKET_COUNT; + ibdap->usb_ins_end_idx = (ibdap->usb_ins_end_idx+1) % DAP_PACKET_COUNT; + if (!ibdap->usb_ins_busy) { // kickstart + ibdap->usb_ins_busy = 1; + uint8_t idx = ibdap->usb_ins_start_idx; + ibdap->usb_ins_start_idx = (ibdap->usb_ins_start_idx+1) % DAP_PACKET_COUNT; + USBD_API->hw->WriteEP(g_usb_hnd, HID_EP_IN, ibdap->usb_ins[idx], DAP_PACKET_SIZE); + + //LED_RUNNING_OUT (1); + //LED_CONNECTED_OUT (0); + } + + } +} diff --git a/src/JTAG_DP.c b/src/JTAG_DP.c new file mode 100644 index 0000000..9d6692b --- /dev/null +++ b/src/JTAG_DP.c @@ -0,0 +1,358 @@ +/****************************************************************************** + * @file JTAG_DP.c + * @brief CMSIS-DAP JTAG DP I/O + * @version V1.00 + * @date 31. May 2012 + * + * @note + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#include "DAP_config.h" +#include "DAP.h" + + +// JTAG Macros + +#define PIN_TCK_SET PIN_SWCLK_TCK_SET +#define PIN_TCK_CLR PIN_SWCLK_TCK_CLR +#define PIN_TMS_SET PIN_SWDIO_TMS_SET +#define PIN_TMS_CLR PIN_SWDIO_TMS_CLR + +#define JTAG_CYCLE_TCK() \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define JTAG_CYCLE_TDI(tdi) \ + PIN_TDI_OUT(tdi); \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define JTAG_CYCLE_TDO(tdo) \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + tdo = PIN_TDO_IN(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define JTAG_CYCLE_TDIO(tdi,tdo) \ + PIN_TDI_OUT(tdi); \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + tdo = PIN_TDO_IN(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) + + +#if (DAP_JTAG != 0) + + +// Generate JTAG Sequence +// info: sequence information +// tdi: pointer to TDI generated data +// tdo: pointer to TDO captured data +// return: none +void JTAG_Sequence (uint32_t info, uint8_t *tdi, uint8_t *tdo) { + uint32_t i_val; + uint32_t o_val; + uint32_t bit; + uint32_t n, k; + + n = info & JTAG_SEQUENCE_TCK; + if (n == 0) n = 64; + + if (info & JTAG_SEQUENCE_TMS) { + PIN_TMS_SET(); + } else { + PIN_TMS_CLR(); + } + + while (n) { + i_val = *tdi++; + o_val = 0; + for (k = 8; k && n; k--, n--) { + JTAG_CYCLE_TDIO(i_val, bit); + i_val >>= 1; + o_val >>= 1; + o_val |= bit << 7; + } + o_val >>= k; + if (info & JTAG_SEQUENCE_TDO) { + *tdo++ = o_val; + } + } +} + + +// JTAG Set IR +// ir: IR value +// return: none +#define JTAG_IR_Function(speed) /**/ \ +void JTAG_IR_##speed (uint32_t ir) { \ + uint32_t n; \ + \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \ + JTAG_CYCLE_TCK(); /* Select-IR-Scan */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Capture-IR */ \ + JTAG_CYCLE_TCK(); /* Shift-IR */ \ + \ + PIN_TDI_OUT(1); \ + for (n = DAP_Data.jtag_dev.ir_before[DAP_Data.jtag_dev.index]; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass before data */ \ + } \ + for (n = DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index] - 1; n; n--) { \ + JTAG_CYCLE_TDI(ir); /* Set IR bits (except last) */ \ + ir >>= 1; \ + } \ + n = DAP_Data.jtag_dev.ir_after[DAP_Data.jtag_dev.index]; \ + if (n) { \ + JTAG_CYCLE_TDI(ir); /* Set last IR bit */ \ + PIN_TDI_OUT(1); \ + for (--n; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass after data */ \ + } \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Bypass & Exit1-IR */ \ + } else { \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TDI(ir); /* Set last IR bit & Exit1-IR */ \ + } \ + \ + JTAG_CYCLE_TCK(); /* Update-IR */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Idle */ \ + PIN_TDI_OUT(1); \ +} + + +// JTAG Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +#define JTAG_TransferFunction(speed) /**/ \ +uint8_t JTAG_Transfer##speed (uint32_t request, uint32_t *data) { \ + uint32_t ack; \ + uint32_t bit; \ + uint32_t val; \ + uint32_t n; \ + \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Capture-DR */ \ + JTAG_CYCLE_TCK(); /* Shift-DR */ \ + \ + for (n = DAP_Data.jtag_dev.index; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass before data */ \ + } \ + \ + JTAG_CYCLE_TDIO(request >> 1, bit); /* Set RnW, Get ACK.0 */ \ + ack = bit << 1; \ + JTAG_CYCLE_TDIO(request >> 2, bit); /* Set A2, Get ACK.1 */ \ + ack |= bit << 0; \ + JTAG_CYCLE_TDIO(request >> 3, bit); /* Set A3, Get ACK.2 */ \ + ack |= bit << 2; \ + \ + if (ack != DAP_TRANSFER_OK) { \ + /* Exit on error */ \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Exit1-DR */ \ + goto exit; \ + } \ + \ + if (request & DAP_TRANSFER_RnW) { \ + /* Read Transfer */ \ + val = 0; \ + for (n = 31; n; n--) { \ + JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ \ + val |= bit << 31; \ + val >>= 1; \ + } \ + n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1; \ + if (n) { \ + JTAG_CYCLE_TDO(bit); /* Get D31 */ \ + for (--n; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass after data */ \ + } \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \ + } else { \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ \ + } \ + val |= bit << 31; \ + if (data) *data = val; \ + } else { \ + /* Write Transfer */ \ + val = *data; \ + for (n = 31; n; n--) { \ + JTAG_CYCLE_TDI(val); /* Set D0..D30 */ \ + val >>= 1; \ + } \ + n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1; \ + if (n) { \ + JTAG_CYCLE_TDI(val); /* Set D31 */ \ + for (--n; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass after data */ \ + } \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \ + } else { \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TDI(val); /* Set D31 & Exit1-DR */ \ + } \ + } \ + \ +exit: \ + JTAG_CYCLE_TCK(); /* Update-DR */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Idle */ \ + PIN_TDI_OUT(1); \ + \ + /* Idle cycles */ \ + n = DAP_Data.transfer.idle_cycles; \ + while (n--) { \ + JTAG_CYCLE_TCK(); /* Idle */ \ + } \ + \ + return (ack); \ +} + + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_FAST() +JTAG_IR_Function(Fast); +JTAG_TransferFunction(Fast); + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) +JTAG_IR_Function(Slow); +JTAG_TransferFunction(Slow); + + +// JTAG Read IDCODE register +// return: value read +uint32_t JTAG_ReadIDCode (void) { + uint32_t bit; + uint32_t val; + uint32_t n; + + PIN_TMS_SET(); + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Capture-DR */ + JTAG_CYCLE_TCK(); /* Shift-DR */ + + for (n = DAP_Data.jtag_dev.index; n; n--) { + JTAG_CYCLE_TCK(); /* Bypass before data */ + } + + val = 0; + for (n = 31; n; n--) { + JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ + val |= bit << 31; + val >>= 1; + } + PIN_TMS_SET(); + JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ + val |= bit << 31; + + JTAG_CYCLE_TCK(); /* Update-DR */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Idle */ + + return (val); +} + + +// JTAG Write ABORT register +// data: value to write +// return: none +void JTAG_WriteAbort (uint32_t data) { + uint32_t n; + + PIN_TMS_SET(); + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Capture-DR */ + JTAG_CYCLE_TCK(); /* Shift-DR */ + + for (n = DAP_Data.jtag_dev.index; n; n--) { + JTAG_CYCLE_TCK(); /* Bypass before data */ + } + + PIN_TDI_OUT(0); + JTAG_CYCLE_TCK(); /* Set RnW=0 (Write) */ + JTAG_CYCLE_TCK(); /* Set A2=0 */ + JTAG_CYCLE_TCK(); /* Set A3=0 */ + + for (n = 31; n; n--) { + JTAG_CYCLE_TDI(data); /* Set D0..D30 */ + data >>= 1; + } + n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1; + if (n) { + JTAG_CYCLE_TDI(data); /* Set D31 */ + for (--n; n; n--) { + JTAG_CYCLE_TCK(); /* Bypass after data */ + } + PIN_TMS_SET(); + JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ + } else { + PIN_TMS_SET(); + JTAG_CYCLE_TDI(data); /* Set D31 & Exit1-DR */ + } + + JTAG_CYCLE_TCK(); /* Update-DR */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Idle */ + PIN_TDI_OUT(1); +} + + +// JTAG Set IR +// ir: IR value +// return: none +void JTAG_IR (uint32_t ir) { + if (DAP_Data.fast_clock) { + JTAG_IR_Fast(ir); + } else { + JTAG_IR_Slow(ir); + } +} + + +// JTAG Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +uint8_t JTAG_Transfer(uint32_t request, uint32_t *data) { + if (DAP_Data.fast_clock) { + return JTAG_TransferFast(request, data); + } else { + return JTAG_TransferSlow(request, data); + } +} + + +#endif /* (DAP_JTAG != 0) */ diff --git a/src/SW_DP.c b/src/SW_DP.c new file mode 100644 index 0000000..9dec094 --- /dev/null +++ b/src/SW_DP.c @@ -0,0 +1,236 @@ +/****************************************************************************** + * @file SW_DP.c + * @brief CMSIS-DAP SW DP I/O + * @version V1.00 + * @date 31. May 2012 + * + * @note + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#include "DAP_config.h" +#include "DAP.h" + + +// SW Macros + +#define PIN_SWCLK_SET PIN_SWCLK_TCK_SET +#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR + +#define SW_CLOCK_CYCLE() \ + PIN_SWCLK_CLR(); \ + PIN_DELAY(); \ + PIN_SWCLK_SET(); \ + PIN_DELAY() + +#define SW_WRITE_BIT(bit) \ + PIN_SWDIO_OUT(bit); \ + PIN_SWCLK_CLR(); \ + PIN_DELAY(); \ + PIN_SWCLK_SET(); \ + PIN_DELAY() + +#define SW_READ_BIT(bit) \ + PIN_SWCLK_CLR(); \ + PIN_DELAY(); \ + bit = PIN_SWDIO_IN(); \ + PIN_SWCLK_SET(); \ + PIN_DELAY() + +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) + + +// Generate SWJ Sequence +// count: sequence bit count +// data: pointer to sequence bit data +// return: none +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) +void SWJ_Sequence (uint32_t count, uint8_t *data) { + uint32_t val; + uint32_t n; + + val = 0; + n = 0; + while (count--) { + if (n == 0) { + val = *data++; + n = 8; + } + if (val & 1) { + PIN_SWDIO_TMS_SET(); + } else { + PIN_SWDIO_TMS_CLR(); + } + SW_CLOCK_CYCLE(); + val >>= 1; + n--; + } +} +#endif + + +#if (DAP_SWD != 0) + + +// SWD Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +#define SWD_TransferFunction(speed) /**/ \ +uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) { \ + uint32_t ack; \ + uint32_t bit; \ + uint32_t val; \ + uint32_t parity; \ + \ + uint32_t n; \ + \ + /* Packet Request */ \ + parity = 0; \ + SW_WRITE_BIT(1); /* Start Bit */ \ + bit = request >> 0; \ + SW_WRITE_BIT(bit); /* APnDP Bit */ \ + parity += bit; \ + bit = request >> 1; \ + SW_WRITE_BIT(bit); /* RnW Bit */ \ + parity += bit; \ + bit = request >> 2; \ + SW_WRITE_BIT(bit); /* A2 Bit */ \ + parity += bit; \ + bit = request >> 3; \ + SW_WRITE_BIT(bit); /* A3 Bit */ \ + parity += bit; \ + SW_WRITE_BIT(parity); /* Parity Bit */ \ + SW_WRITE_BIT(0); /* Stop Bit */ \ + SW_WRITE_BIT(1); /* Park Bit */ \ + \ + /* Turnaround */ \ + PIN_SWDIO_OUT_DISABLE(); \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + \ + /* Acknowledge response */ \ + SW_READ_BIT(bit); \ + ack = bit << 0; \ + SW_READ_BIT(bit); \ + ack |= bit << 1; \ + SW_READ_BIT(bit); \ + ack |= bit << 2; \ + \ + if (ack == DAP_TRANSFER_OK) { /* OK response */ \ + /* Data transfer */ \ + if (request & DAP_TRANSFER_RnW) { \ + /* Read data */ \ + val = 0; \ + parity = 0; \ + for (n = 32; n; n--) { \ + SW_READ_BIT(bit); /* Read RDATA[0:31] */ \ + parity += bit; \ + val >>= 1; \ + val |= bit << 31; \ + } \ + SW_READ_BIT(bit); /* Read Parity */ \ + if ((parity ^ bit) & 1) { \ + ack = DAP_TRANSFER_ERROR; \ + } \ + if (data) *data = val; \ + /* Turnaround */ \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + PIN_SWDIO_OUT_ENABLE(); \ + } else { \ + /* Turnaround */ \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + PIN_SWDIO_OUT_ENABLE(); \ + /* Write data */ \ + val = *data; \ + parity = 0; \ + for (n = 32; n; n--) { \ + SW_WRITE_BIT(val); /* Write WDATA[0:31] */ \ + parity += val; \ + val >>= 1; \ + } \ + SW_WRITE_BIT(parity); /* Write Parity Bit */ \ + } \ + /* Idle cycles */ \ + n = DAP_Data.transfer.idle_cycles; \ + if (n) { \ + PIN_SWDIO_OUT(0); \ + for (; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + } \ + PIN_SWDIO_OUT(1); \ + return (ack); \ + } \ + \ + if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { \ + /* WAIT or FAULT response */ \ + if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0)) { \ + for (n = 32+1; n; n--) { \ + SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ \ + } \ + } \ + /* Turnaround */ \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + PIN_SWDIO_OUT_ENABLE(); \ + if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0)) { \ + PIN_SWDIO_OUT(0); \ + for (n = 32+1; n; n--) { \ + SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ \ + } \ + } \ + PIN_SWDIO_OUT(1); \ + return (ack); \ + } \ + \ + /* Protocol error */ \ + for (n = DAP_Data.swd_conf.turnaround + 32 + 1; n; n--) { \ + SW_CLOCK_CYCLE(); /* Back off data phase */ \ + } \ + PIN_SWDIO_OUT(1); \ + return (ack); \ +} + + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_FAST() +SWD_TransferFunction(Fast); + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) +SWD_TransferFunction(Slow); + + +// SWD Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +uint8_t SWD_Transfer(uint32_t request, uint32_t *data) { + if (DAP_Data.fast_clock) { + return SWD_TransferFast(request, data); + } else { + return SWD_TransferSlow(request, data); + } +} + + +#endif /* (DAP_SWD != 0) */ diff --git a/src/cr_startup_lpc11uxx.c b/src/cr_startup_lpc11uxx.c new file mode 100755 index 0000000..ed97c98 --- /dev/null +++ b/src/cr_startup_lpc11uxx.c @@ -0,0 +1,348 @@ +//***************************************************************************** +// LPC11Uxx Microcontroller Startup code for use with LPCXpresso IDE +// +// Version : 141204 +//***************************************************************************** +// +// Copyright(C) NXP Semiconductors, 2013-2014 +// All rights reserved. +// +// Software that is described herein is for illustrative purposes only +// which provides customers with programming information regarding the +// LPC products. This software is supplied "AS IS" without any warranties of +// any kind, and NXP Semiconductors and its licensor disclaim any and +// all warranties, express or implied, including all implied warranties of +// merchantability, fitness for a particular purpose and non-infringement of +// intellectual property rights. NXP Semiconductors assumes no responsibility +// or liability for the use of the software, conveys no license or rights under any +// patent, copyright, mask work right, or any other intellectual property rights in +// or to any products. NXP Semiconductors reserves the right to make changes +// in the software without notification. NXP Semiconductors also makes no +// representation or warranty that such application will be suitable for the +// specified use without further testing or modification. +// +// Permission to use, copy, modify, and distribute this software and its +// documentation is hereby granted, under NXP Semiconductors' and its +// licensor's relevant copyrights in the software, without fee, provided that it +// is used in conjunction with NXP Semiconductors microcontrollers. This +// copyright, permission, and disclaimer notice must appear in all copies of +// this code. +//***************************************************************************** + +#if defined (__cplusplus) +#ifdef __REDLIB__ +#error Redlib does not support C++ +#else +//***************************************************************************** +// +// The entry point for the C++ library startup +// +//***************************************************************************** +extern "C" { + extern void __libc_init_array(void); +} +#endif +#endif + +#define WEAK __attribute__ ((weak)) +#define ALIAS(f) __attribute__ ((weak, alias (#f))) + +//***************************************************************************** +#if defined (__cplusplus) +extern "C" { +#endif + +//***************************************************************************** +#if defined (__USE_CMSIS) || defined (__USE_LPCOPEN) +// Declaration of external SystemInit function +extern void SystemInit(void); +#endif + +// Patch the AEABI integer divide functions to use MCU's romdivide library +#ifdef __USE_ROMDIVIDE +// Location in memory that holds the address of the ROM Driver table +#define PTR_ROM_DRIVER_TABLE ((unsigned int *)(0x1FFF1FF8)) +// Variables to store addresses of idiv and udiv functions within MCU ROM +unsigned int *pDivRom_idiv; +unsigned int *pDivRom_uidiv; +#endif + +//***************************************************************************** +// +// Forward declaration of the default handlers. These are aliased. +// When the application defines a handler (with the same name), this will +// automatically take precedence over these weak definitions +// +//***************************************************************************** + void ResetISR(void); +WEAK void NMI_Handler(void); +WEAK void HardFault_Handler(void); +WEAK void SVC_Handler(void); +WEAK void PendSV_Handler(void); +WEAK void SysTick_Handler(void); +WEAK void IntDefaultHandler(void); +//***************************************************************************** +// +// Forward declaration of the specific IRQ handlers. These are aliased +// to the IntDefaultHandler, which is a 'forever' loop. When the application +// defines a handler (with the same name), this will automatically take +// precedence over these weak definitions +// +//***************************************************************************** +void FLEX_INT0_IRQHandler (void) ALIAS(IntDefaultHandler); +void FLEX_INT1_IRQHandler (void) ALIAS(IntDefaultHandler); +void FLEX_INT2_IRQHandler (void) ALIAS(IntDefaultHandler); +void FLEX_INT3_IRQHandler (void) ALIAS(IntDefaultHandler); +void FLEX_INT4_IRQHandler (void) ALIAS(IntDefaultHandler); +void FLEX_INT5_IRQHandler (void) ALIAS(IntDefaultHandler); +void FLEX_INT6_IRQHandler (void) ALIAS(IntDefaultHandler); +void FLEX_INT7_IRQHandler (void) ALIAS(IntDefaultHandler); +void GINT0_IRQHandler (void) ALIAS(IntDefaultHandler); +void GINT1_IRQHandler (void) ALIAS(IntDefaultHandler); +void SSP1_IRQHandler (void) ALIAS(IntDefaultHandler); +void I2C_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER16_0_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER16_1_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER32_0_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER32_1_IRQHandler (void) ALIAS(IntDefaultHandler); +void SSP0_IRQHandler (void) ALIAS(IntDefaultHandler); +void UART_IRQHandler (void) ALIAS(IntDefaultHandler); +void USB_IRQHandler (void) ALIAS(IntDefaultHandler); +void USB_FIQHandler (void) ALIAS(IntDefaultHandler); +void ADC_IRQHandler (void) ALIAS(IntDefaultHandler); +void WDT_IRQHandler (void) ALIAS(IntDefaultHandler); +void BOD_IRQHandler (void) ALIAS(IntDefaultHandler); +void FMC_IRQHandler (void) ALIAS(IntDefaultHandler); +void USBWakeup_IRQHandler (void) ALIAS(IntDefaultHandler); + +//***************************************************************************** +// The entry point for the application. +// __main() is the entry point for redlib based applications +// main() is the entry point for newlib based applications +//***************************************************************************** +#if defined (__REDLIB__) +extern void __main(void); +#else +extern int main(void); +#endif +//***************************************************************************** +// +// External declaration for the pointer to the stack top from the Linker Script +// +//***************************************************************************** +extern void _vStackTop(void); + +//***************************************************************************** +#if defined (__cplusplus) +} // extern "C" +#endif +//***************************************************************************** +// +// The vector table. Note that the proper constructs must be placed on this to +// ensure that it ends up at physical address 0x0000.0000. +// +//***************************************************************************** +extern void (* const g_pfnVectors[])(void); +__attribute__ ((section(".isr_vector"))) +void (* const g_pfnVectors[])(void) = { + &_vStackTop, // The initial stack pointer + ResetISR, // The reset handler + NMI_Handler, // The NMI handler + HardFault_Handler, // The hard fault handler + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + SVC_Handler, // SVCall handler + 0, // Reserved + 0, // Reserved + PendSV_Handler, // The PendSV handler + SysTick_Handler, // The SysTick handler + + // LPC11U specific handlers + FLEX_INT0_IRQHandler, // 0 - GPIO pin interrupt 0 + FLEX_INT1_IRQHandler, // 1 - GPIO pin interrupt 1 + FLEX_INT2_IRQHandler, // 2 - GPIO pin interrupt 2 + FLEX_INT3_IRQHandler, // 3 - GPIO pin interrupt 3 + FLEX_INT4_IRQHandler, // 4 - GPIO pin interrupt 4 + FLEX_INT5_IRQHandler, // 5 - GPIO pin interrupt 5 + FLEX_INT6_IRQHandler, // 6 - GPIO pin interrupt 6 + FLEX_INT7_IRQHandler, // 7 - GPIO pin interrupt 7 + GINT0_IRQHandler, // 8 - GPIO GROUP0 interrupt + GINT1_IRQHandler, // 9 - GPIO GROUP1 interrupt + 0, // 10 - Reserved + 0, // 11 - Reserved + 0, // 12 - Reserved + 0, // 13 - Reserved + SSP1_IRQHandler, // 14 - SPI/SSP1 Interrupt + I2C_IRQHandler, // 15 - I2C0 + TIMER16_0_IRQHandler, // 16 - CT16B0 (16-bit Timer 0) + TIMER16_1_IRQHandler, // 17 - CT16B1 (16-bit Timer 1) + TIMER32_0_IRQHandler, // 18 - CT32B0 (32-bit Timer 0) + TIMER32_1_IRQHandler, // 19 - CT32B1 (32-bit Timer 1) + SSP0_IRQHandler, // 20 - SPI/SSP0 Interrupt + UART_IRQHandler, // 21 - UART0 + USB_IRQHandler, // 22 - USB IRQ + USB_FIQHandler, // 23 - USB FIQ + ADC_IRQHandler, // 24 - ADC (A/D Converter) + WDT_IRQHandler, // 25 - WDT (Watchdog Timer) + BOD_IRQHandler, // 26 - BOD (Brownout Detect) + FMC_IRQHandler, // 27 - IP2111 Flash Memory Controller + 0, // 28 - Reserved + 0, // 29 - Reserved + USBWakeup_IRQHandler, // 30 - USB wake-up interrupt + 0, // 31 - Reserved +}; + +//***************************************************************************** +// Functions to carry out the initialization of RW and BSS data sections. These +// are written as separate functions rather than being inlined within the +// ResetISR() function in order to cope with MCUs with multiple banks of +// memory. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void data_init(unsigned int romstart, unsigned int start, unsigned int len) { + unsigned int *pulDest = (unsigned int*) start; + unsigned int *pulSrc = (unsigned int*) romstart; + unsigned int loop; + for (loop = 0; loop < len; loop = loop + 4) + *pulDest++ = *pulSrc++; +} + +__attribute__ ((section(".after_vectors"))) +void bss_init(unsigned int start, unsigned int len) { + unsigned int *pulDest = (unsigned int*) start; + unsigned int loop; + for (loop = 0; loop < len; loop = loop + 4) + *pulDest++ = 0; +} + +//***************************************************************************** +// The following symbols are constructs generated by the linker, indicating +// the location of various points in the "Global Section Table". This table is +// created by the linker via the Code Red managed linker script mechanism. It +// contains the load address, execution address and length of each RW data +// section and the execution and length of each BSS (zero initialized) section. +//***************************************************************************** +extern unsigned int __data_section_table; +extern unsigned int __data_section_table_end; +extern unsigned int __bss_section_table; +extern unsigned int __bss_section_table_end; + +//***************************************************************************** +// Reset entry point for your code. +// Sets up a simple runtime environment and initializes the C/C++ +// library. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void +ResetISR(void) { + + + + // + // Copy the data sections from flash to SRAM. + // + unsigned int LoadAddr, ExeAddr, SectionLen; + unsigned int *SectionTableAddr; + + // Load base address of Global Section Table + SectionTableAddr = &__data_section_table; + + // Copy the data sections from flash to SRAM. + while (SectionTableAddr < &__data_section_table_end) { + LoadAddr = *SectionTableAddr++; + ExeAddr = *SectionTableAddr++; + SectionLen = *SectionTableAddr++; + data_init(LoadAddr, ExeAddr, SectionLen); + } + // At this point, SectionTableAddr = &__bss_section_table; + // Zero fill the bss segment + while (SectionTableAddr < &__bss_section_table_end) { + ExeAddr = *SectionTableAddr++; + SectionLen = *SectionTableAddr++; + bss_init(ExeAddr, SectionLen); + } + +#if defined (__USE_CMSIS) || defined (__USE_LPCOPEN) + SystemInit(); +#endif + +#if defined (__cplusplus) + // + // Call C++ library initialisation + // + __libc_init_array(); +#endif + +#if defined (__REDLIB__) + // Call the Redlib library, which in turn calls main() + __main() ; +#else + main(); +#endif + // + // main() shouldn't return, but if it does, we'll just enter an infinite loop + // + while (1) { + ; + } +} + +//***************************************************************************** +// Default exception handlers. Override the ones here by defining your own +// handler routines in your application code. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void NMI_Handler(void) +{ + while(1) + { + } +} +__attribute__ ((section(".after_vectors"))) +void HardFault_Handler(void) +{ + while(1) + { + } +} +__attribute__ ((section(".after_vectors"))) +void SVC_Handler(void) +{ + while(1) + { + } +} +__attribute__ ((section(".after_vectors"))) +void PendSV_Handler(void) +{ + while(1) + { + } +} +__attribute__ ((section(".after_vectors"))) +void SysTick_Handler(void) +{ + while(1) + { + } +} + +//***************************************************************************** +// +// Processor ends up here if an unexpected interrupt occurs or a specific +// handler is not present in the application code. +// +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void IntDefaultHandler(void) +{ + while(1) + { + } +} + diff --git a/src/crp.c b/src/crp.c new file mode 100755 index 0000000..fa9a0d5 --- /dev/null +++ b/src/crp.c @@ -0,0 +1,38 @@ +//***************************************************************************** +// crp.c +// +// Source file to create CRP word expected by LPCXpresso IDE linker +//***************************************************************************** +// +// Copyright(C) NXP Semiconductors, 2013 +// All rights reserved. +// +// Software that is described herein is for illustrative purposes only +// which provides customers with programming information regarding the +// LPC products. This software is supplied "AS IS" without any warranties of +// any kind, and NXP Semiconductors and its licensor disclaim any and +// all warranties, express or implied, including all implied warranties of +// merchantability, fitness for a particular purpose and non-infringement of +// intellectual property rights. NXP Semiconductors assumes no responsibility +// or liability for the use of the software, conveys no license or rights under any +// patent, copyright, mask work right, or any other intellectual property rights in +// or to any products. NXP Semiconductors reserves the right to make changes +// in the software without notification. NXP Semiconductors also makes no +// representation or warranty that such application will be suitable for the +// specified use without further testing or modification. +// +// Permission to use, copy, modify, and distribute this software and its +// documentation is hereby granted, under NXP Semiconductors' and its +// licensor's relevant copyrights in the software, without fee, provided that it +// is used in conjunction with NXP Semiconductors microcontrollers. This +// copyright, permission, and disclaimer notice must appear in all copies of +// this code. +//***************************************************************************** + +#if defined (__CODE_RED) +#include +// Variable to store CRP value in. Will be placed automatically +// by the linker when "Enable Code Read Protect" selected. +// See crp.h header for more information +__CRP const unsigned int CRP_WORD = CRP_NO_CRP ; +#endif diff --git a/src/system_LPC11Uxx.c b/src/system_LPC11Uxx.c new file mode 100644 index 0000000..7422b92 --- /dev/null +++ b/src/system_LPC11Uxx.c @@ -0,0 +1,495 @@ +/****************************************************************************** + * @file system_LPC11Uxx.c + * @purpose CMSIS Cortex-M3 Device Peripheral Access Layer Source File + * for the NXP LPC13xx Device Series + * @version V1.10 + * @date 24. November 2010 + * + * @note + * Copyright (C) 2009-2010 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + + +#include +#include "LPC11Uxx.h" + +/* +//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------ +*/ + +/*--------------------- Clock Configuration ---------------------------------- +// +// Clock Configuration +// System Oscillator Control Register (SYSOSCCTRL) +// BYPASS: System Oscillator Bypass Enable +// If enabled then PLL input (sys_osc_clk) is fed +// directly from XTALIN and XTALOUT pins. +// FREQRANGE: System Oscillator Frequency Range +// Determines frequency range for Low-power oscillator. +// <0=> 1 - 20 MHz +// <1=> 15 - 25 MHz +// +// +// Watchdog Oscillator Control Register (WDTOSCCTRL) +// DIVSEL: Select Divider for Fclkana +// wdt_osc_clk = Fclkana/ (2 � (1 + DIVSEL)) +// <0-31> +// FREQSEL: Select Watchdog Oscillator Analog Output Frequency (Fclkana) +// <0=> Undefined +// <1=> 0.5 MHz +// <2=> 0.8 MHz +// <3=> 1.1 MHz +// <4=> 1.4 MHz +// <5=> 1.6 MHz +// <6=> 1.8 MHz +// <7=> 2.0 MHz +// <8=> 2.2 MHz +// <9=> 2.4 MHz +// <10=> 2.6 MHz +// <11=> 2.7 MHz +// <12=> 2.9 MHz +// <13=> 3.1 MHz +// <14=> 3.2 MHz +// <15=> 3.4 MHz +// +// +// System PLL Control Register (SYSPLLCTRL) +// F_clkout = M * F_clkin = F_CCO / (2 * P) +// F_clkin must be in the range of 10 MHz to 25 MHz +// F_CCO must be in the range of 156 MHz to 320 MHz +// MSEL: Feedback Divider Selection +// M = MSEL + 1 +// <0-31> +// PSEL: Post Divider Selection +// <0=> P = 1 +// <1=> P = 2 +// <2=> P = 4 +// <3=> P = 8 +// +// +// System PLL Clock Source Select Register (SYSPLLCLKSEL) +// SEL: System PLL Clock Source +// <0=> IRC Oscillator +// <1=> System Oscillator +// <2=> Reserved +// <3=> Reserved +// +// +// Main Clock Source Select Register (MAINCLKSEL) +// SEL: Clock Source for Main Clock +// <0=> IRC Oscillator +// <1=> Input Clock to System PLL +// <2=> WDT Oscillator +// <3=> System PLL Clock Out +// +// +// System AHB Clock Divider Register (SYSAHBCLKDIV) +// DIV: System AHB Clock Divider +// Divides main clock to provide system clock to core, memories, and peripherals. +// 0 = is disabled +// <0-255> +// +// +// USB PLL Control Register (USBPLLCTRL) +// F_clkout = M * F_clkin = F_CCO / (2 * P) +// F_clkin must be in the range of 10 MHz to 25 MHz +// F_CCO must be in the range of 156 MHz to 320 MHz +// MSEL: Feedback Divider Selection +// M = MSEL + 1 +// <0-31> +// PSEL: Post Divider Selection +// <0=> P = 1 +// <1=> P = 2 +// <2=> P = 4 +// <3=> P = 8 +// +// +// USB PLL Clock Source Select Register (USBPLLCLKSEL) +// SEL: USB PLL Clock Source +// USB PLL clock source must be switched to System Oscillator for correct USB operation +// <0=> IRC Oscillator +// <1=> System Oscillator +// <2=> Reserved +// <3=> Reserved +// +// +// USB Clock Source Select Register (USBCLKSEL) +// SEL: System PLL Clock Source +// <0=> USB PLL out +// <1=> Main clock +// <2=> Reserved +// <3=> Reserved +// +// +// USB Clock Divider Register (USBCLKDIV) +// DIV: USB Clock Divider +// Divides USB clock to 48 MHz. +// 0 = is disabled +// <0-255> +// +// +*/ +#define CLOCK_SETUP 1 +#define SYSOSCCTRL_Val 0x00000000 // Reset: 0x000 +#define WDTOSCCTRL_Val 0x00000000 // Reset: 0x000 +#define SYSPLLCTRL_Val 0x00000023 // Reset: 0x000 +#define SYSPLLCLKSEL_Val 0x00000001 // Reset: 0x000 +#define MAINCLKSEL_Val 0x00000003 // Reset: 0x000 +#define SYSAHBCLKDIV_Val 0x00000001 // Reset: 0x001 +#define USBPLLCTRL_Val 0x00000023 // Reset: 0x000 +#define USBPLLCLKSEL_Val 0x00000001 // Reset: 0x000 +#define USBCLKSEL_Val 0x00000000 // Reset: 0x000 +#define USBCLKDIV_Val 0x00000000 // Reset: 0x001 + +#define PDRUNCFGUSEMASK 0x0000E800 +#define PDRUNCFGMASKTMP 0x000005FF + +/* +//-------- <<< end of configuration section >>> ------------------------------ +*/ + +/*---------------------------------------------------------------------------- + Check the register settings + *----------------------------------------------------------------------------*/ +#define CHECK_RANGE(val, min, max) ((val < min) || (val > max)) +#define CHECK_RSVD(val, mask) (val & mask) + +/* Clock Configuration -------------------------------------------------------*/ +#if (CHECK_RSVD((SYSOSCCTRL_Val), ~0x00000003)) + #error "SYSOSCCTRL: Invalid values of reserved bits!" +#endif + +#if (CHECK_RSVD((WDTOSCCTRL_Val), ~0x000001FF)) + #error "WDTOSCCTRL: Invalid values of reserved bits!" +#endif + +#if (CHECK_RANGE((SYSPLLCLKSEL_Val), 0, 2)) + #error "SYSPLLCLKSEL: Value out of range!" +#endif + +#if (CHECK_RSVD((SYSPLLCTRL_Val), ~0x000001FF)) + #error "SYSPLLCTRL: Invalid values of reserved bits!" +#endif + +#if (CHECK_RSVD((MAINCLKSEL_Val), ~0x00000003)) + #error "MAINCLKSEL: Invalid values of reserved bits!" +#endif + +#if (CHECK_RANGE((SYSAHBCLKDIV_Val), 0, 255)) + #error "SYSAHBCLKDIV: Value out of range!" +#endif + +#if (CHECK_RANGE((USBPLLCLKSEL_Val), 0, 1)) + #error "USBPLLCLKSEL: Value out of range!" +#endif + +#if (CHECK_RSVD((USBPLLCTRL_Val), ~0x000001FF)) + #error "USBPLLCTRL: Invalid values of reserved bits!" +#endif + +#if (CHECK_RANGE((USBCLKSEL_Val), 0, 1)) + #error "USBCLKSEL: Value out of range!" +#endif + +#if (CHECK_RANGE((USBCLKDIV_Val), 0, 255)) + #error "USBCLKDIV: Value out of range!" +#endif + + +/*---------------------------------------------------------------------------- + DEFINES + *----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ +#define __XTAL (12000000UL) /* Oscillator frequency */ +#define __SYS_OSC_CLK ( __XTAL) /* Main oscillator frequency */ +#define __IRC_OSC_CLK (12000000UL) /* Internal RC oscillator frequency */ + + +#define __FREQSEL ((WDTOSCCTRL_Val >> 5) & 0x0F) +#define __DIVSEL (((WDTOSCCTRL_Val & 0x1F) << 1) + 2) + +#if (CLOCK_SETUP) /* Clock Setup */ + #if (__FREQSEL == 0) + #define __WDT_OSC_CLK ( 0) /* undefined */ + #elif (__FREQSEL == 1) + #define __WDT_OSC_CLK ( 500000 / __DIVSEL) + #elif (__FREQSEL == 2) + #define __WDT_OSC_CLK ( 800000 / __DIVSEL) + #elif (__FREQSEL == 3) + #define __WDT_OSC_CLK (1100000 / __DIVSEL) + #elif (__FREQSEL == 4) + #define __WDT_OSC_CLK (1400000 / __DIVSEL) + #elif (__FREQSEL == 5) + #define __WDT_OSC_CLK (1600000 / __DIVSEL) + #elif (__FREQSEL == 6) + #define __WDT_OSC_CLK (1800000 / __DIVSEL) + #elif (__FREQSEL == 7) + #define __WDT_OSC_CLK (2000000 / __DIVSEL) + #elif (__FREQSEL == 8) + #define __WDT_OSC_CLK (2200000 / __DIVSEL) + #elif (__FREQSEL == 9) + #define __WDT_OSC_CLK (2400000 / __DIVSEL) + #elif (__FREQSEL == 10) + #define __WDT_OSC_CLK (2600000 / __DIVSEL) + #elif (__FREQSEL == 11) + #define __WDT_OSC_CLK (2700000 / __DIVSEL) + #elif (__FREQSEL == 12) + #define __WDT_OSC_CLK (2900000 / __DIVSEL) + #elif (__FREQSEL == 13) + #define __WDT_OSC_CLK (3100000 / __DIVSEL) + #elif (__FREQSEL == 14) + #define __WDT_OSC_CLK (3200000 / __DIVSEL) + #else + #define __WDT_OSC_CLK (3400000 / __DIVSEL) + #endif + + /* sys_pllclkin calculation */ + #if ((SYSPLLCLKSEL_Val & 0x03) == 0) + #define __SYS_PLLCLKIN (__IRC_OSC_CLK) + #elif ((SYSPLLCLKSEL_Val & 0x03) == 1) + #define __SYS_PLLCLKIN (__SYS_OSC_CLK) + #else + #define __SYS_PLLCLKIN (0) + #endif + + #define __SYS_PLLCLKOUT (__SYS_PLLCLKIN * ((SYSPLLCTRL_Val & 0x01F) + 1)) + + /* main clock calculation */ + #if ((MAINCLKSEL_Val & 0x03) == 0) + #define __MAIN_CLOCK (__IRC_OSC_CLK) + #elif ((MAINCLKSEL_Val & 0x03) == 1) + #define __MAIN_CLOCK (__SYS_PLLCLKIN) + #elif ((MAINCLKSEL_Val & 0x03) == 2) + #if (__FREQSEL == 0) + #error "MAINCLKSEL: WDT Oscillator selected but FREQSEL is undefined!" + #else + #define __MAIN_CLOCK (__WDT_OSC_CLK) + #endif + #elif ((MAINCLKSEL_Val & 0x03) == 3) + #define __MAIN_CLOCK (__SYS_PLLCLKOUT) + #else + #define __MAIN_CLOCK (0) + #endif + + #define __SYSTEM_CLOCK (__MAIN_CLOCK / SYSAHBCLKDIV_Val) + +#else + #define __SYSTEM_CLOCK (__IRC_OSC_CLK) +#endif // CLOCK_SETUP + + +/*---------------------------------------------------------------------------- + Clock Variable definitions + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = __SYSTEM_CLOCK;/*!< System Clock Frequency (Core Clock)*/ + + +/*---------------------------------------------------------------------------- + Clock functions + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */ +{ + uint32_t wdt_osc = 0; + + /* Determine clock frequency according to clock register values */ + switch ((LPC_SYSCON->WDTOSCCTRL >> 5) & 0x0F) { + case 0: wdt_osc = 0; break; + case 1: wdt_osc = 500000; break; + case 2: wdt_osc = 800000; break; + case 3: wdt_osc = 1100000; break; + case 4: wdt_osc = 1400000; break; + case 5: wdt_osc = 1600000; break; + case 6: wdt_osc = 1800000; break; + case 7: wdt_osc = 2000000; break; + case 8: wdt_osc = 2200000; break; + case 9: wdt_osc = 2400000; break; + case 10: wdt_osc = 2600000; break; + case 11: wdt_osc = 2700000; break; + case 12: wdt_osc = 2900000; break; + case 13: wdt_osc = 3100000; break; + case 14: wdt_osc = 3200000; break; + case 15: wdt_osc = 3400000; break; + } + wdt_osc /= ((LPC_SYSCON->WDTOSCCTRL & 0x1F) << 1) + 2; + + switch (LPC_SYSCON->MAINCLKSEL & 0x03) { + case 0: /* Internal RC oscillator */ + SystemCoreClock = __IRC_OSC_CLK; + break; + case 1: /* Input Clock to System PLL */ + switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) { + case 0: /* Internal RC oscillator */ + SystemCoreClock = __IRC_OSC_CLK; + break; + case 1: /* System oscillator */ + SystemCoreClock = __SYS_OSC_CLK; + break; + case 2: /* Reserved */ + case 3: /* Reserved */ + SystemCoreClock = 0; + break; + } + break; + case 2: /* WDT Oscillator */ + SystemCoreClock = wdt_osc; + break; + case 3: /* System PLL Clock Out */ + switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) { + case 0: /* Internal RC oscillator */ + if (LPC_SYSCON->SYSPLLCTRL & 0x180) { + SystemCoreClock = __IRC_OSC_CLK; + } else { + SystemCoreClock = __IRC_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1); + } + break; + case 1: /* System oscillator */ + if (LPC_SYSCON->SYSPLLCTRL & 0x180) { + SystemCoreClock = __SYS_OSC_CLK; + } else { + SystemCoreClock = __SYS_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1); + } + break; + case 2: /* Reserved */ + case 3: /* Reserved */ + SystemCoreClock = 0; + break; + } + break; + } + + SystemCoreClock /= LPC_SYSCON->SYSAHBCLKDIV; + +} + +__INLINE void SYSCTL_PowerDown(uint32_t powerdownmask) +{ + uint32_t pdrun; + + pdrun = LPC_SYSCON->PDRUNCFG & PDRUNCFGMASKTMP; + pdrun |= (powerdownmask & PDRUNCFGMASKTMP); + LPC_SYSCON->PDRUNCFG = (pdrun | PDRUNCFGUSEMASK); +} + +__INLINE void SYSCTL_PowerUp(uint32_t powerupmask) +{ + uint32_t pdrun; + + pdrun = LPC_SYSCON->PDRUNCFG & PDRUNCFGMASKTMP; + pdrun &= ~(powerupmask & PDRUNCFGMASKTMP); + + LPC_SYSCON->PDRUNCFG = (pdrun | PDRUNCFGUSEMASK); +} + +__STATIC_INLINE void FLASH_SetFLASHAccess(uint32_t clks) +{ + uint32_t tmp = LPC_FLASHCTRL->FLASHCFG & (~(0x3)); + + /* Don't alter upper bits */ + LPC_FLASHCTRL->FLASHCFG = tmp | clks; +} + +/** + * Initialize the system + * + * @param none + * @return none + * + * @brief Setup the microcontroller system. + * Initialize the System. + */ +void SystemInit (void) { + volatile uint32_t i; + +#if (CLOCK_SETUP) /* Clock Setup */ + +#if ((SYSPLLCLKSEL_Val & 0x03) == 1) + //LPC_SYSCON->PDRUNCFG &= ~(1 << 5); /* Power-up System Osc */ + SYSCTL_PowerUp ((1 << 5)); + //LPC_SYSCON->SYSOSCCTRL = SYSOSCCTRL_Val; + for (i = 0; i < 0x100; i++) __NOP(); +#endif + + LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_Val; /* Select PLL Input */ + LPC_SYSCON->SYSPLLCLKUEN = 0x00; /* Toggle Update Register */ + LPC_SYSCON->SYSPLLCLKUEN = 0x01; + //while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01)); /* Wait Until Updated */ + +#if ((MAINCLKSEL_Val & 0x03) == 3) /* Main Clock is PLL Out */ + SYSCTL_PowerDown (1 << 7); + LPC_SYSCON->SYSPLLCTRL = SYSPLLCTRL_Val; + //LPC_SYSCON->PDRUNCFG &= ~(1 << 7); /* Power-up SYSPLL */ + SYSCTL_PowerUp ((1 << 7)); + while (!(LPC_SYSCON->SYSPLLSTAT & 0x01)); /* Wait Until PLL Locked */ +#endif + +#if (((MAINCLKSEL_Val & 0x03) == 2) ) + SYSCTL_PowerDown (1 << 6); + LPC_SYSCON->WDTOSCCTRL = WDTOSCCTRL_Val; + //LPC_SYSCON->PDRUNCFG &= ~(1 << 6); /* Power-up WDT Clock */ + SYSCTL_PowerUp ((1 << 6)); + for (i = 0; i < 200; i++) __NOP(); +#endif + + LPC_SYSCON->SYSAHBCLKDIV = SYSAHBCLKDIV_Val; + + FLASH_SetFLASHAccess (FLASHCFG_50MHZ_CPU); + + LPC_SYSCON->MAINCLKSEL = MAINCLKSEL_Val; /* Select PLL Clock Output */ + LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle Update Register */ + LPC_SYSCON->MAINCLKUEN = 0x01; + //while (!(LPC_SYSCON->MAINCLKUEN & 0x01)); /* Wait Until Updated */ + +#if ((USBCLKSEL_Val & 0x003) == 0) /* USB clock is USB PLL out */ + //SYSCTL_PowerDown (1 << 8); + LPC_SYSCON->USBPLLCLKSEL = USBPLLCLKSEL_Val; /* Select PLL Input */ + LPC_SYSCON->USBPLLCLKUEN = 0x00; /* Toggle Update Register */ + LPC_SYSCON->USBPLLCLKUEN = 0x01; + //while (!(LPC_SYSCON->USBPLLCLKUEN & 0x01)); /* Wait Until Updated */ + LPC_SYSCON->USBPLLCTRL = USBPLLCTRL_Val; + SYSCTL_PowerUp (1 << 8); + while (!(LPC_SYSCON->USBPLLSTAT & 0x01)); /* Wait Until PLL Locked */ + //LPC_SYSCON->USBCLKSEL = 0x00; /* Select USB PLL */ + +#if ((USBCLKDIV_Val & 0x1FF) != 0) /* USB clock is used */ + SYSCTL_PowerDown (1 << 10); + LPC_SYSCON->USBCLKSEL = USBCLKSEL_Val; /* Select USB Clock */ + LPC_SYSCON->USBCLKDIV = USBCLKDIV_Val; /* Set USB clock divider */ + //LPC_SYSCON->PDRUNCFG &= ~(1 << 10); /* Power-up USB PHY */ + SYSCTL_PowerUp (1 << 10); +#endif + + + +#else /* USB clock is not used */ + LPC_SYSCON->PDRUNCFG |= (1 << 10); /* Power-down USB PHY */ + LPC_SYSCON->PDRUNCFG |= (1 << 8); /* Power-down USB PLL */ +#endif + +#endif + + /* System clock to the IOCON needs to be enabled or + most of the I/O related peripherals won't work. */ + LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16); + + LPC_IOCON->PIO0_3 = 1; // USB_VBUS + LPC_IOCON->PIO0_6 = 1; // USB_CONNECT + + LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 26; + +} diff --git a/src/uart.c b/src/uart.c new file mode 100644 index 0000000..d140382 --- /dev/null +++ b/src/uart.c @@ -0,0 +1,23 @@ +/* + * uart.c + * + * Created on: Jun 26, 2015 + * Author: yliu + */ + +#include "LPC11Uxx.h" + +void init_uart () { + /* + LPC_IOCON->PIO0_18 = 1; // PIO0_18 used for RXD + LPC_IOCON->PIO0_19 = 1; // PIO0_19 used for TXD + + // Setup UART for 115.2K8N1 + Chip_UART_Init(LPC_USART); + LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 12; + Chip_UART_SetBaud(LPC_USART, 115200); + Chip_UART_ConfigData(LPC_USART, (UART_LCR_WLEN8 | UART_LCR_SBS_1BIT)); + Chip_UART_SetupFIFOS(LPC_USART, (UART_FCR_FIFO_EN | UART_FCR_TRG_LEV2)); + Chip_UART_TXEnable(LPC_USART); + */ +} diff --git a/src/usb_desc.c b/src/usb_desc.c new file mode 100644 index 0000000..9c26d73 --- /dev/null +++ b/src/usb_desc.c @@ -0,0 +1,178 @@ +/* + * usb_desc.c + * + * Created on: Jun 18, 2015 + * Author: yliu + */ + +#include "compiler.h" +#include "app_usbd_cfg.h" +#include "DAP_config.h" + +ALIGNED(4) const uint8_t HID_ReportDescriptor[] = { + HID_UsagePageVendor(0x00), + HID_Usage(0x01), + HID_Collection(HID_Application), + HID_LogicalMin(0), /* value range: 0 - 0xFF */ + HID_LogicalMaxS(0xFF), + HID_ReportSize(8), /* 8 bits */ + HID_ReportCount(DAP_PACKET_SIZE), + HID_Usage(0x01), + HID_Input(HID_Data | HID_Variable | HID_Absolute), + HID_ReportCount(DAP_PACKET_SIZE), + HID_Usage(0x01), + HID_Output(HID_Data | HID_Variable | HID_Absolute), + HID_ReportCount(1), + HID_Usage(0x01), + HID_Feature(HID_Data | HID_Variable | HID_Absolute), + HID_EndCollection, +}; + +const uint8_t hid_report_size = sizeof (HID_ReportDescriptor); + + +/** + * USB Standard Device Descriptor + */ +ALIGNED(4) const uint8_t USB_DeviceDescriptor[] = { + USB_DEVICE_DESC_SIZE, /* bLength */ + USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */ + WBVAL(0x0200), /* bcdUSB 2.0 */ + 0x00, /* bDeviceClass */ + 0x00, /* bDeviceSubClass */ + 0x00, /* bDeviceProtocol */ + USB_MAX_PACKET0, /* bMaxPacketSize0 */ + WBVAL(0x1FC9), /* idVendor */ + WBVAL(0x0081), /* idProduct */ + WBVAL(0x0100), /* bcdDevice */ + 0x01, /* iManufacturer */ + 0x02, /* iProduct */ + 0x03, /* iSerialNumber */ + 0x01 /* bNumConfigurations */ +}; + +/** + * USB FSConfiguration Descriptor + * All Descriptors (Configuration, Interface, Endpoint, Class, Vendor) + */ +ALIGNED(4) uint8_t USB_FsConfigDescriptor[] = { + /* Configuration 1 */ + USB_CONFIGURATION_DESC_SIZE, /* bLength */ + USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */ + WBVAL( /* wTotalLength */ + USB_CONFIGURATION_DESC_SIZE + + USB_INTERFACE_DESC_SIZE + + HID_DESC_SIZE + + USB_ENDPOINT_DESC_SIZE + + USB_ENDPOINT_DESC_SIZE + ), + 0x01, /* bNumInterfaces */ + 0x01, /* bConfigurationValue */ + 0x00, /* iConfiguration */ + USB_CONFIG_SELF_POWERED, /* bmAttributes */ + USB_CONFIG_POWER_MA(100), /* bMaxPower */ + + /* Interface 0, Alternate Setting 0, HID Class */ + USB_INTERFACE_DESC_SIZE, /* bLength */ + USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ + 0x00, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x02, /* bNumEndpoints */ + USB_DEVICE_CLASS_HUMAN_INTERFACE, /* bInterfaceClass */ + HID_SUBCLASS_NONE, /* bInterfaceSubClass */ + HID_PROTOCOL_NONE, /* bInterfaceProtocol */ + 0x04, /* iInterface */ + /* HID Class Descriptor */ + /* HID_DESC_OFFSET = 0x0012 */ + HID_DESC_SIZE, /* bLength */ + HID_HID_DESCRIPTOR_TYPE, /* bDescriptorType */ + WBVAL(0x0111), /* bcdHID : 1.11*/ + 0x00, /* bCountryCode */ + 0x01, /* bNumDescriptors */ + HID_REPORT_DESCRIPTOR_TYPE, /* bDescriptorType */ + WBVAL(sizeof(HID_ReportDescriptor)), /* wDescriptorLength */ + /* Endpoint, HID Interrupt In */ + USB_ENDPOINT_DESC_SIZE, /* bLength */ + USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ + HID_EP_IN, /* bEndpointAddress */ + USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ + WBVAL(64), /* wMaxPacketSize */ + 0x01, /* 1ms */ /* bInterval */ + /* Endpoint, HID Interrupt Out */ + USB_ENDPOINT_DESC_SIZE, /* bLength */ + USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ + HID_EP_OUT, /* bEndpointAddress */ + USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ + WBVAL(64), /* wMaxPacketSize */ + 0x01, /* bInterval: 1ms */ + /* Terminator */ + 0 /* bLength */ +}; + +/** + * USB String Descriptor (optional) + */ +const uint8_t USB_StringDescriptor[] = { + /* Index 0x00: LANGID Codes */ + 0x04, /* bLength */ + USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ + WBVAL(0x0409), /* wLANGID : US English*/ + /* Index 0x01: Manufacturer */ + (8 * 2 + 2), /* bLength (8 Char + Type + lenght) */ + USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ + 'A', 0, + 'R', 0, + 'M', 0, + 'S', 0, + 'T', 0, + 'A', 0, + 'R', 0, + 'T', 0, + /* Index 0x02: Product */ + (24 * 2 + 2), /* bLength (24 Char + Type + lenght) */ + USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ + 'I', 0, + 'B', 0, + 'D', 0, + 'A', 0, + 'P', 0, + '-', 0, + 'L', 0, + 'P', 0, + 'C', 0, + '1', 0, + '1', 0, + 'U', 0, + '3', 0, + '5', 0, + ' ', 0, + 'C', 0, + 'M', 0, + 'S', 0, + 'I', 0, + 'S', 0, + '-', 0, + 'D', 0, + 'A', 0, + 'P', 0, + /* Index 0x03: Serial Number */ + (11 * 2 + 2), /* bLength (13 Char + Type + lenght) */ + USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ + 'I', 0, + 'B', 0, + 'D', 0, + 'A', 0, + 'P', 0, + '2', 0, + '0', 0, + '1', 0, + '5', 0, + '0', 0, + '7', 0, + /* Index 0x04: Interface 0, Alternate Setting 0 */ + (3 * 2 + 2), /* bLength (3 Char + Type + lenght) */ + USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */ + 'H', 0, + 'I', 0, + 'D', 0, +}; diff --git a/src/usb_driver.c b/src/usb_driver.c new file mode 100644 index 0000000..bdb3b41 --- /dev/null +++ b/src/usb_driver.c @@ -0,0 +1,187 @@ +/* + * usb_driver.c + * + * Created on: Jun 18, 2015 + * Author: yliu + */ + +#include +#include + +#ifdef __USE_CMSIS +#include "LPC11Uxx.h" +#endif + + +#include "usb_driver.h" + +#define PDRUNCFGUSEMASK 0x0000E800 +#define PDRUNCFGMASKTMP 0x000005FF + +USBD_HANDLE_T g_usb_hnd; +const USBD_API_T *g_pUsbApi; + + +/* Find the address of interface descriptor for given class type. */ +USB_INTERFACE_DESCRIPTOR *find_IntfDesc(const uint8_t *pDesc, uint32_t intfClass) +{ + USB_COMMON_DESCRIPTOR *pD; + USB_INTERFACE_DESCRIPTOR *pIntfDesc = 0; + uint32_t next_desc_adr; + + pD = (USB_COMMON_DESCRIPTOR *) pDesc; + next_desc_adr = (uint32_t) pDesc; + + while (pD->bLength) { + /* is it interface descriptor */ + if (pD->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) { + + pIntfDesc = (USB_INTERFACE_DESCRIPTOR *) pD; + /* did we find the right interface descriptor */ + if (pIntfDesc->bInterfaceClass == intfClass) { + break; + } + } + pIntfDesc = 0; + next_desc_adr = (uint32_t) pD + pD->bLength; + pD = (USB_COMMON_DESCRIPTOR *) next_desc_adr; + } + + return pIntfDesc; +} + + + + +void init_usb_clock () { + // no need to do this: LPC_SYSCON->PDRUNCFG &= ~(1 << 8); + // system_LPC11Uxx.c done that already. + // configure SYSAHBCLKCTRL + + // no need to do this: enabled in ResetISR() + //LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 26; // ram1 clock source enable + //LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 27; // usbram clock source enable + // conf usb main clock + LPC_SYSCON->USBCLKSEL = 0; + LPC_SYSCON->USBCLKUEN = 0; + LPC_SYSCON->USBCLKUEN = 1; + LPC_SYSCON->USBCLKDIV = 1; + + LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 14; // usb clock source + //LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 26; + LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 27; +} + +void init_usb_power () { + uint32_t pdrun; + pdrun = LPC_SYSCON->PDRUNCFG & PDRUNCFGMASKTMP; + pdrun &= ~((1 << 10) & PDRUNCFGMASKTMP); + LPC_SYSCON->PDRUNCFG = (pdrun | PDRUNCFGUSEMASK); +} + +void USB_IRQHandler(void) { + uint32_t *addr = (uint32_t *) LPC_USB->EPLISTSTART; + + /* WORKAROUND for artf32289 ROM driver BUG: + As part of USB specification the device should respond + with STALL condition for any unsupported setup packet. The host will send + new setup packet/request on seeing STALL condition for EP0 instead of sending + a clear STALL request. Current driver in ROM doesn't clear the STALL + condition on new setup packet which should be fixed. + */ + if ( LPC_USB->DEVCMDSTAT & (1 << 8) ) { /* if setup packet is received */ + addr[0] &= ~(1 << 29); /* clear EP0_OUT stall */ + addr[2] &= ~(1 << 29); /* clear EP0_IN stall */ + } + USBD_API->hw->ISR(g_usb_hnd); +} + +int init_usb_driver (USBD_API_INIT_PARAM_T *usb_param) { + USB_CORE_DESCS_T desc; + ErrorCode_t ret = LPC_OK; + + g_pUsbApi = (const USBD_API_T *) LPC_ROM_API->usbdApiBase; + memset((void *) usb_param, 0, sizeof(USBD_API_INIT_PARAM_T)); + usb_param->usb_reg_base = LPC_USB_BASE; + /* WORKAROUND for artf44835 ROM driver BUG: + Code clearing STALL bits in endpoint reset routine corrupts memory area + next to the endpoint control data. For example When EP0, EP1_IN, EP1_OUT, + EP2_IN are used we need to specify 3 here. But as a workaround for this + issue specify 4. So that extra EPs control structure acts as padding buffer + to avoid data corruption. Corruption of padding memory doesn’t affect the + stack/program behaviour. + */ + usb_param->max_num_ep = 2 + 1; + usb_param->mem_base = USB_STACK_MEM_BASE; + usb_param->mem_size = USB_STACK_MEM_SIZE; + + desc.device_desc = (uint8_t *) USB_DeviceDescriptor; + desc.string_desc = (uint8_t *) USB_StringDescriptor; + + desc.high_speed_desc = USB_FsConfigDescriptor; + desc.full_speed_desc = USB_FsConfigDescriptor; + desc.device_qualifier = 0; + + ret = USBD_API->hw->Init(&g_usb_hnd, &desc, usb_param); + if (ret != LPC_OK) return -1; + + usb_param->mem_base = USB_STACK_MEM_BASE + (USB_STACK_MEM_SIZE - usb_param->mem_size); + return 0; +} + + + +int init_usb_hid (USBD_API_INIT_PARAM_T *usb_param, + HID_GetReport_Func_T getreport_fun, HID_SetReport_Func_T setreport_fun, + HID_EpIn_Hdlr_Func_T epin_hdlr_fun, HID_EpOut_Hdlr_Func_T epout_hdlr_fun, + uint8_t** report_saddr, int report_size) { + USBD_HID_INIT_PARAM_T hid_param; + USB_HID_REPORT_T reports_data[1]; + ErrorCode_t ret = LPC_OK; + + memset((void *) &hid_param, 0, sizeof(USBD_HID_INIT_PARAM_T)); + hid_param.max_reports = 1; + + /* Init reports_data */ + reports_data[0].len = hid_report_size; + reports_data[0].idle_time = 0; + reports_data[0].desc = (uint8_t *) &HID_ReportDescriptor[0]; + + USB_INTERFACE_DESCRIPTOR *pIntfDesc = (USB_INTERFACE_DESCRIPTOR *) &USB_FsConfigDescriptor[sizeof(USB_CONFIGURATION_DESCRIPTOR)]; + + if ((pIntfDesc == 0) || (pIntfDesc->bInterfaceClass != USB_DEVICE_CLASS_HUMAN_INTERFACE)) { + return -1; + } + + hid_param.mem_base = usb_param->mem_base; + hid_param.mem_size = usb_param->mem_size; + hid_param.intf_desc = (uint8_t *) pIntfDesc; + /* user defined functions */ + hid_param.HID_GetReport = getreport_fun; + hid_param.HID_SetReport = setreport_fun; + hid_param.HID_EpIn_Hdlr = epin_hdlr_fun; + hid_param.HID_EpOut_Hdlr = epout_hdlr_fun; + hid_param.report_data = reports_data; + + ret = USBD_API->hid->init(g_usb_hnd, &hid_param); + if (ret != LPC_OK) return -2; + /* allocate USB accessable memory space for report data */ + *report_saddr = (uint8_t *) hid_param.mem_base; + memset (hid_param.mem_base, 0, report_size); + hid_param.mem_base += report_size; + hid_param.mem_size -= report_size; + /* update memory variables */ + usb_param->mem_base = hid_param.mem_base; + usb_param->mem_size = hid_param.mem_size; + return 0; +} + +void connect_to_usb_bus () { + NVIC_EnableIRQ (USB_IRQn); + USBD_API->hw->Connect (g_usb_hnd, 1); +} + +void disconnect_to_usb_bus () { + USBD_API->hw->Connect (g_usb_hnd, 0); + NVIC_DisableIRQ (USB_IRQn); +} -- 2.39.2