diff --git a/demos/bsp/lpc13uxx/CMSISv2p10_LPC13Uxx/inc/LPC13Uxx.h b/demos/bsp/lpc13uxx/CMSISv2p10_LPC13Uxx/inc/LPC13Uxx.h index 220c0f889..966033540 100644 --- a/demos/bsp/lpc13uxx/CMSISv2p10_LPC13Uxx/inc/LPC13Uxx.h +++ b/demos/bsp/lpc13uxx/CMSISv2p10_LPC13Uxx/inc/LPC13Uxx.h @@ -1,760 +1,760 @@ - -/****************************************************************************************************//** - * @file LPC13Uxx.h - * - * - * - * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File for - * default LPC13Uxx Device Series - * - * @version V0.1 - * @date 18. Jan 2012 - * - * @note Generated with SFDGen V2.6 Build 4f on Tuesday, 17.01.2012 13:39:52 - * - * from CMSIS SVD File 'LPC13uxx_svd_v0.1.xml' Version 0.1, - * created on Thurs, 01.19.2012 15:13:15, last modified on Thurs, 01.19.2012 15:53:09 - * - *******************************************************************************************************/ - -/** @addtogroup NXP - * @{ - */ - -/** @addtogroup LPC13Uxx - * @{ - */ - -#ifndef __LPC13UXX_H__ -#define __LPC13UXX_H__ - -#ifdef __cplusplus -extern "C" { -#endif - - -#if defined ( __CC_ARM ) - #pragma anon_unions -#endif - - /* Interrupt Number Definition */ - -typedef enum { -// ------------------------- Cortex-M3 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 */ - MemoryManagement_IRQn = -12, /*!< 4 Memory Management, MPU mismatch, including Access Violation and No Match */ - BusFault_IRQn = -11, /*!< 5 Bus Fault, Pre-Fetch-, Memory Access Fault, other address/memory related Fault */ - UsageFault_IRQn = -10, /*!< 6 Usage Fault, i.e. Undef Instruction, Illegal State Transition */ - 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 */ -// ---------------------------- LPC13Uxx Specific Interrupt Numbers -------------------------------- - PIN_INT0_IRQn = 0, /*!< 0 PIN_INT0 */ - PIN_INT1_IRQn = 1, /*!< 1 PIN_INT1 */ - PIN_INT2_IRQn = 2, /*!< 2 PIN_INT2 */ - PIN_INT3_IRQn = 3, /*!< 3 PIN_INT3 */ - PIN_INT4_IRQn = 4, /*!< 4 PIN_INT4 */ - PIN_INT5_IRQn = 5, /*!< 5 PIN_INT5 */ - PIN_INT6_IRQn = 6, /*!< 6 PIN_INT6 */ - PIN_INT7_IRQn = 7, /*!< 7 PIN_INT7 */ - GINT0_IRQn = 8, /*!< 8 GINT0 */ - GINT1_IRQn = 9, /*!< 9 GINT1 */ - Reserved0_IRQn = 10, /*!< 10 Reserved Interrupt */ - Reserved1_IRQn = 11, /*!< 11 Reserved Interrupt */ - RIT_IRQn = 12, /*!< 12 Repetitive Interrupt Timer */ - Reserved2_IRQn = 13, /*!< 13 Reserved Interrupt */ - SSP1_IRQn = 14, /*!< 14 SSP1 */ - I2C_IRQn = 15, /*!< 15 I2C */ - CT16B0_IRQn = 16, /*!< 16 CT16B0 */ - CT16B1_IRQn = 17, /*!< 17 CT16B1 */ - CT32B0_IRQn = 18, /*!< 18 CT32B0 */ - CT32B1_IRQn = 19, /*!< 19 CT32B1 */ - SSP0_IRQn = 20, /*!< 20 SSP0 */ - USART_IRQn = 21, /*!< 21 USART */ - USB_IRQ_IRQn = 22, /*!< 22 USB_IRQ */ - USB_FIQ_IRQn = 23, /*!< 23 USB_FIQ */ - ADC_IRQn = 24, /*!< 24 ADC */ - WDT_IRQn = 25, /*!< 25 WDT */ - BOD_IRQn = 26, /*!< 26 BOD */ - FMC_IRQn = 27, /*!< 27 FMC */ - Reserved3_IRQn = 28, /*!< 28 Reserved Interrupt */ - Reserved4_IRQn = 29, /*!< 29 Reserved Interrupt */ - USBWAKEUP_IRQn = 30, /*!< 30 USBWAKEUP */ - Reserved5_IRQn = 31, /*!< 31 Reserved Interrupt */ -} IRQn_Type; - - -/** @addtogroup Configuration_of_CMSIS - * @{ - */ - -/* Processor and Core Peripheral Section */ /* Configuration of the Cortex-M3 Processor and Core Peripherals */ - -#define __CM3_REV 0x0000 /*!< Cortex-M3 Core Revision */ -#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 /*!< Cortex-M3 processor and core peripherals */ -#include "system_LPC13Uxx.h" /*!< LPC13Uxx System */ - -/** @addtogroup Device_Peripheral_Registers - * @{ - */ - - -// ------------------------------------------------------------------------------------------------ -// ----- I2C ----- -// ------------------------------------------------------------------------------------------------ - - - -typedef struct { /*!< (@ 0x40000000) I2C Structure */ - __IO uint32_t CONSET; /*!< (@ 0x40000000) I2C Control Set Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is set. Writing a zero has no effect on the corresponding bit in the I2C control register. */ - __I uint32_t STAT; /*!< (@ 0x40000004) I2C Status Register. During I2C operation, this register provides detailed status codes that allow software to determine the next action needed. */ - __IO uint32_t DAT; /*!< (@ 0x40000008) I2C Data Register. During master or slave transmit mode, data to be transmitted is written to this register. During master or slave receive mode, data that has been received may be read from this register. */ - __IO uint32_t ADR0; /*!< (@ 0x4000000C) I2C Slave Address Register 0. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ - __IO uint32_t SCLH; /*!< (@ 0x40000010) SCH Duty Cycle Register High Half Word. Determines the high time of the I2C clock. */ - __IO uint32_t SCLL; /*!< (@ 0x40000014) SCL Duty Cycle Register Low Half Word. Determines the low time of the I2C clock. I2nSCLL and I2nSCLH together determine the clock frequency generated by an I2C master and certain times used in slave mode. */ - __O uint32_t CONCLR; /*!< (@ 0x40000018) I2C Control Clear Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is cleared. Writing a zero has no effect on the corresponding bit in the I2C control register. */ - __IO uint32_t MMCTRL; /*!< (@ 0x4000001C) Monitor mode control register. */ - union{ - __IO uint32_t ADR[3]; /*!< (@ 0x40000020) I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ - struct{ - __IO uint32_t ADR1; - __IO uint32_t ADR2; - __IO uint32_t ADR3; - }; - }; - __I uint32_t DATA_BUFFER; /*!< (@ 0x4000002C) Data buffer register. The contents of the 8 MSBs of the I2DAT shift register will be transferred to the DATA_BUFFER automatically after every nine bits (8 bits of data plus ACK or NACK) has been received on the bus. */ - union{ - __IO uint32_t MASK[4]; /*!< (@ 0x40000030) I2C Slave address mask register. This mask register is associated with I2ADR0 to determine an address match. The mask register has no effect when comparing to the General Call address (0000000). */ - struct{ - __IO uint32_t MASK0; - __IO uint32_t MASK1; - __IO uint32_t MASK2; - __IO uint32_t MASK3; - }; - }; -} LPC_I2C_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- WWDT ----- -// ------------------------------------------------------------------------------------------------ - - -typedef struct { /*!< (@ 0x40004000) WWDT Structure */ - __IO uint32_t MOD; /*!< (@ 0x40004000) Watchdog mode register. This register contains the basic mode and status of the Watchdog Timer. */ - __IO uint32_t TC; /*!< (@ 0x40004004) Watchdog timer constant register. This 24-bit register determines the time-out value. */ - __O uint32_t FEED; /*!< (@ 0x40004008) Watchdog feed sequence register. Writing 0xAA followed by 0x55 to this register reloads the Watchdog timer with the value contained in WDTC. */ - __I uint32_t TV; /*!< (@ 0x4000400C) Watchdog timer value register. This 24-bit register reads out the current value of the Watchdog timer. */ - __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 ----- -// ------------------------------------------------------------------------------------------------ - - -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; /*!< (@ 0x40008058) Synchronous mode control register. */ -} LPC_USART_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- CT16B0 ----- -// ------------------------------------------------------------------------------------------------ - -typedef struct { /*!< (@ 0x4000C000) CT16B0 Structure */ - __IO uint32_t IR; /*!< (@ 0x4000C000) Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */ - __IO uint32_t TCR; /*!< (@ 0x4000C004) Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */ - __IO uint32_t TC; /*!< (@ 0x4000C008) Timer Counter. The 16-bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */ - __IO uint32_t PR; /*!< (@ 0x4000C00C) Prescale Register. When the Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */ - __IO uint32_t PC; /*!< (@ 0x4000C010) Prescale Counter. The 16-bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */ - __IO uint32_t MCR; /*!< (@ 0x4000C014) Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */ - union { - __IO uint32_t MR[4]; /*!< (@ 0x4000C018) Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */ - struct{ - __IO uint32_t MR0; /*!< (@ 0x4000C018) Match Register. MR0 */ - __IO uint32_t MR1; /*!< (@ 0x4000C01C) Match Register. MR1 */ - __IO uint32_t MR2; /*!< (@ 0x4000C020) Match Register. MR2 */ - __IO uint32_t MR3; /*!< (@ 0x4000C024) Match Register. MR3 */ - }; - }; - __IO uint32_t CCR; /*!< (@ 0x4000C028) Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */ - union{ - __I uint32_t CR[4]; /*!< (@ 0x4000C02C) Capture Register. CR is loaded with the value of TC when there is an event on the CT16B0_CAP input. */ - struct{ - __I uint32_t CR0; /*!< (@ 0x4000C02C) Capture Register. CR 0 */ - __I uint32_t CR1; /*!< (@ 0x4000C030) Capture Register. CR 1 */ - __I uint32_t CR2; /*!< (@ 0x4000C034) Capture Register. CR 2 */ - __I uint32_t CR3; /*!< (@ 0x4000C038) Capture Register. CR 3 */ - }; - }; - __IO uint32_t EMR; /*!< (@ 0x4000C03C) External Match Register. The EMR controls the match function and the external match pins */ - __I uint32_t RESERVED0[12]; - __IO uint32_t CTCR; /*!< (@ 0x4000C070) Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */ - __IO uint32_t PWMC; /*!< (@ 0x4000C074) PWM Control Register. The PWMCON enables PWM mode for the external match pins CT16B0_MAT[1:0] and CT16B1_MAT[1:0]. */ -} LPC_CT16B0_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- CT16B1 ----- -// ------------------------------------------------------------------------------------------------ - -typedef struct { /*!< (@ 0x40010000) CT16B1 Structure */ - __IO uint32_t IR; /*!< (@ 0x40010000) Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */ - __IO uint32_t TCR; /*!< (@ 0x40010004) Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */ - __IO uint32_t TC; /*!< (@ 0x40010008) Timer Counter. The 16-bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */ - __IO uint32_t PR; /*!< (@ 0x4001000C) Prescale Register. When the Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */ - __IO uint32_t PC; /*!< (@ 0x40010010) Prescale Counter. The 16-bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */ - __IO uint32_t MCR; /*!< (@ 0x40010014) Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */ - union { - __IO uint32_t MR[4]; /*!< (@ 0x40010018) Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */ - struct{ - __IO uint32_t MR0; /*!< (@ 0x40010018) Match Register. MR0 */ - __IO uint32_t MR1; /*!< (@ 0x4001001C) Match Register. MR1 */ - __IO uint32_t MR2; /*!< (@ 0x40010020) Match Register. MR2 */ - __IO uint32_t MR3; /*!< (@ 0x40010024) Match Register. MR3 */ - }; - }; - __IO uint32_t CCR; /*!< (@ 0x40010028) Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */ - union{ - __I uint32_t CR[4]; /*!< (@ 0x4001002C) Capture Register. CR is loaded with the value of TC when there is an event on the CT16B0_CAP input. */ - struct{ - __I uint32_t CR0; /*!< (@ 0x4001002C) Capture Register. CR 0 */ - __I uint32_t CR1; /*!< (@ 0x40010030) Capture Register. CR 1 */ - __I uint32_t CR2; /*!< (@ 0x40010034) Capture Register. CR 2 */ - __I uint32_t CR3; /*!< (@ 0x40010038) Capture Register. CR 3 */ - }; - }; - __IO uint32_t EMR; /*!< (@ 0x4001003C) External Match Register. The EMR controls the match function and the external match pins */ - __I uint32_t RESERVED0[12]; - __IO uint32_t CTCR; /*!< (@ 0x40010070) Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */ - __IO uint32_t PWMC; /*!< (@ 0x40010074) PWM Control Register. The PWMCON enables PWM mode for the external match pins CT16B0_MAT[1:0] and CT16B1_MAT[1:0]. */ -} LPC_CT16B1_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- CT32B0 ----- -// ------------------------------------------------------------------------------------------------ -typedef struct { /*!< (@ 0x40014000) CT32B0 Structure */ - __IO uint32_t IR; /*!< (@ 0x40014000) Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */ - __IO uint32_t TCR; /*!< (@ 0x40014004) Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */ - __IO uint32_t TC; /*!< (@ 0x40014008) Timer Counter. The 32-bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */ - __IO uint32_t PR; /*!< (@ 0x4001400C) Prescale Register. When the Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */ - __IO uint32_t PC; /*!< (@ 0x40014010) Prescale Counter. The 32-bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */ - __IO uint32_t MCR; /*!< (@ 0x40014014) Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */ - union { - __IO uint32_t MR[4]; /*!< (@ 0x40014018) Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */ - struct{ - __IO uint32_t MR0; /*!< (@ 0x40014018) Match Register. MR0 */ - __IO uint32_t MR1; /*!< (@ 0x4001401C) Match Register. MR1 */ - __IO uint32_t MR2; /*!< (@ 0x40014020) Match Register. MR2 */ - __IO uint32_t MR3; /*!< (@ 0x40014024) Match Register. MR3 */ - }; - }; - __IO uint32_t CCR; /*!< (@ 0x40014028) Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */ - union{ - __I uint32_t CR[4]; /*!< (@ 0x4001402C) Capture Register. CR is loaded with the value of TC when there is an event on the CT32B_CAP0 input. */ - struct{ - __I uint32_t CR0; /*!< (@ 0x4001402C) Capture Register. CR 0 */ - __I uint32_t CR1; /*!< (@ 0x40014030) Capture Register. CR 1 */ - __I uint32_t CR2; /*!< (@ 0x40014034) Capture Register. CR 2 */ - __I uint32_t CR3; /*!< (@ 0x40014038) Capture Register. CR 3 */ - }; - }; - __IO uint32_t EMR; /*!< (@ 0x4001403C) External Match Register. The EMR controls the match function and the external match pins CT32Bn_MAT[3:0]. */ - __I uint32_t RESERVED0[12]; - __IO uint32_t CTCR; /*!< (@ 0x40014070) Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */ - __IO uint32_t PWMC; /*!< (@ 0x40014074) PWM Control Register. The PWMCON enables PWM mode for the external match pins CT32Bn_MAT[3:0]. */ -} LPC_CT32B0_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- CT32B1 ----- -// ------------------------------------------------------------------------------------------------ -typedef struct { /*!< (@ 0x40018000) CT32B1 Structure */ - __IO uint32_t IR; /*!< (@ 0x40018000) Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */ - __IO uint32_t TCR; /*!< (@ 0x40018004) Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */ - __IO uint32_t TC; /*!< (@ 0x40018008) Timer Counter. The 32-bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */ - __IO uint32_t PR; /*!< (@ 0x4001800C) Prescale Register. When the Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */ - __IO uint32_t PC; /*!< (@ 0x40018010) Prescale Counter. The 32-bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */ - __IO uint32_t MCR; /*!< (@ 0x40018014) Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */ - union { - __IO uint32_t MR[4]; /*!< (@ 0x40018018) Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */ - 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; /*!< (@ 0x40018028) Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */ - union{ - __I uint32_t CR[4]; /*!< (@ 0x4001802C) Capture Register. CR is loaded with the value of TC when there is an event on the CT32B_CAP0 input. */ - 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; /*!< (@ 0x4001803C) External Match Register. The EMR controls the match function and the external match pins CT32Bn_MAT[3:0]. */ - __I uint32_t RESERVED0[12]; - __IO uint32_t CTCR; /*!< (@ 0x40018070) Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */ - __IO uint32_t PWMC; /*!< (@ 0x40018074) PWM Control Register. The PWMCON enables PWM mode for the external match pins CT32Bn_MAT[3:0]. */ -} LPC_CT32B1_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- ADC ----- -// ------------------------------------------------------------------------------------------------ -typedef struct { /*!< (@ 0x4001C000) ADC Structure */ - __IO uint32_t CR; /*!< (@ 0x4001C000) A/D Control Register. The CR register must be written to select the operating mode before A/D conversion can occur. */ - __IO uint32_t GDR; /*!< (@ 0x4001C004) A/D Global Data Register. Contains the result of the most recent A/D conversion. */ - __I uint32_t RESERVED0[1]; - __IO uint32_t INTEN; /*!< (@ 0x4001C00C) A/D Interrupt Enable Register. This register contains enable bits that allow the DONE flag of each A/D channel to be included or excluded from contributing to the generation of an A/D interrupt. */ - union{ - __I uint32_t DR[8]; /*!< (@ 0x4001C010) A/D Channel Data Register*/ - struct{ - __I uint32_t DR0; /*!< (@ 0x4001C010) A/D Channel Data Register 0*/ - __I uint32_t DR1; /*!< (@ 0x4001C014) A/D Channel Data Register 1*/ - __I uint32_t DR2; /*!< (@ 0x4001C018) A/D Channel Data Register 2*/ - __I uint32_t DR3; /*!< (@ 0x4001C01C) A/D Channel Data Register 3*/ - __I uint32_t DR4; /*!< (@ 0x4001C020) A/D Channel Data Register 4*/ - __I uint32_t DR5; /*!< (@ 0x4001C024) A/D Channel Data Register 5*/ - __I uint32_t DR6; /*!< (@ 0x4001C028) A/D Channel Data Register 6*/ - __I uint32_t DR7; /*!< (@ 0x4001C02C) A/D Channel Data Register 7*/ - }; - }; - __I uint32_t STAT; /*!< (@ 0x4001C030) A/D Status Register. This register contains DONE and OVERRUN flags for all of the A/D channels, as well as the A/D interrupt flag. */ -} LPC_ADC_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- 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 */ - }; - }; - __IO uint32_t GPREG4; /*!< (@ 0x40038014) General purpose register 4 */ -} LPC_PMU_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- 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]; - __O uint32_t FMSTATCLR; /*!< (@ 0x4003CFE8) Signature generation status clear register */ -} LPC_FLASHCTRL_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- 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 */ - __O uint32_t ICR; /*!< (@ 0x40040020) SSPICR Interrupt Clear Register */ -} LPC_SSP0_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- IOCON ----- -// ------------------------------------------------------------------------------------------------ -typedef struct { /*!< (@ 0x40044000) IOCON 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/SWO */ - __IO uint32_t PIO0_9; /*!< (@ 0x40044024) I/O configuration for pin PIO0_9/MOSI0/CT16B0_MAT1/TRACECLK */ - __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; /*!< (@ 0x40044060) I/O configuration for pin PIO1_0/CT32B1_MAT0 */ - __IO uint32_t PIO1_1; /*!< (@ 0x40044064) I/O configuration for pin PIO1_1/CT32B1_MAT1 */ - __IO uint32_t PIO1_2; /*!< (@ 0x40044068) I/O configuration for pin PIO1_2/CT32B1_MAT2 */ - __IO uint32_t PIO1_3; /*!< (@ 0x4004406C) I/O configuration for pin PIO1_3/CT32B1_MAT3 */ - __IO uint32_t PIO1_4; /*!< (@ 0x40044070) I/O configuration for pin PIO1_4/CT32B1_CAP0 */ - __IO uint32_t PIO1_5; /*!< (@ 0x40044074) I/O configuration for pin PIO1_5/CT32B1_CAP1 */ - __IO uint32_t PIO1_6; /*!< (@ 0x40044078) I/O configuration for pin PIO1_6 */ - __IO uint32_t PIO1_7; /*!< (@ 0x4004407C) I/O configuration for pin PIO1_7 */ - __IO uint32_t PIO1_8; /*!< (@ 0x40044080) I/O configuration for pin PIO1_8 */ - __IO uint32_t PIO1_9; /*!< (@ 0x40044084) I/O configuration for pin PIO1_9 */ - __IO uint32_t PIO1_10; /*!< (@ 0x40044088) I/O configuration for pin PIO1_10 */ - __IO uint32_t PIO1_11; /*!< (@ 0x4004408C) I/O configuration for pin PIO1_11 */ - __IO uint32_t PIO1_12; /*!< (@ 0x40044090) I/O configuration for pin PIO1_12 */ - __IO uint32_t PIO1_13; /*!< (@ 0x40044094) I/O configuration for PIO1_13/DTR/CT16B0_MAT0/TXD */ - __IO uint32_t PIO1_14; /*!< (@ 0x40044098) I/O configuration for 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; /*!< (@ 0x400440A4) I/O configuration for PIO1_17/CT16B0_CAP1/RXD */ - __IO uint32_t PIO1_18; /*!< (@ 0x400440A8) I/O configuration for PIO1_18/CT16B1_CAP1/TXD */ - __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; /*!< (@ 0x400440D8) I/O configuration for pin PIO1_30 */ - __IO uint32_t PIO1_31; /*!< (@ 0x400440DC) I/O configuration for pin PIO1_31 */ -} LPC_IOCON_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- SYSCON ----- -// ------------------------------------------------------------------------------------------------ - -typedef struct { /*!< (@ 0x40048000) SYSCON Structure */ - __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 */ - __I uint32_t RESERVED3; - __IO uint32_t USBPLLCLKSEL; /*!< (@ 0x40048048) USB PLL clock source select */ - __I uint32_t RESERVED4[9]; - __IO uint32_t MAINCLKSEL; /*!< (@ 0x40048070) Main clock source select */ - __I uint32_t RESERVED5; - __IO uint32_t SYSAHBCLKDIV; /*!< (@ 0x40048078) System clock divider */ - __I uint32_t RESERVED6; - __IO uint32_t SYSAHBCLKCTRL; /*!< (@ 0x40048080) System clock control */ - __I uint32_t RESERVED7[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 RESERVED8[3]; - __IO uint32_t TRACECLKDIV; /*!< (@ 0x400480AC) ARM trace clock divider */ - __IO uint32_t SYSTICKCLKDIV; /*!< (@ 0x400480B0) SYSTICK clock divder */ - __I uint32_t RESERVED9[3]; - __IO uint32_t USBCLKSEL; /*!< (@ 0x400480C0) USB clock source select */ - __I uint32_t RESERVED10; - __IO uint32_t USBCLKDIV; /*!< (@ 0x400480C8) USB clock source divider */ - __I uint32_t RESERVED11[5]; - __IO uint32_t CLKOUTSEL; /*!< (@ 0x400480E0) CLKOUT clock source select */ - __I uint32_t RESERVED12; - __IO uint32_t CLKOUTDIV; /*!< (@ 0x400480E8) CLKOUT clock divider */ - __I uint32_t RESERVED13[5]; - __I uint32_t PIOPORCAP0; /*!< (@ 0x40048100) POR captured PIO status 0 */ - __I uint32_t PIOPORCAP1; /*!< (@ 0x40048104) POR captured PIO status 1 */ - __I uint32_t RESERVED14[18]; - __IO uint32_t BODCTRL; /*!< (@ 0x40048150) Brown-Out Detect */ - __IO uint32_t SYSTCKCAL; /*!< (@ 0x40048154) System tick counter calibration */ - __I uint32_t RESERVED15[6]; - __IO uint32_t IRQLATENCY; /*!< (@ 0x40048170) IQR delay. Allows trade-off between interrupt latency and determinism. */ - __IO uint32_t NMISRC; /*!< (@ 0x40048174) NMI Source Control */ - __IO uint32_t PINSEL[8]; /*!< (@ 0x40048178) GPIO Pin Interrupt Select register */ - __IO uint32_t USBCLKCTRL; /*!< (@ 0x40048198) USB clock control */ - __I uint32_t USBCLKST; /*!< (@ 0x4004819C) USB clock status */ - __I uint32_t RESERVED16[25]; - __IO uint32_t STARTERP0; /*!< (@ 0x40048204) Start logic 0 interrupt wake-up enable register 0 */ - __I uint32_t RESERVED17[3]; - __IO uint32_t STARTERP1; /*!< (@ 0x40048214) Start logic 1 interrupt wake-up enable register 1 */ - __I uint32_t RESERVED18[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 RESERVED19[111]; - __I uint32_t DEVICE_ID; /*!< (@ 0x400483F8) Device ID */ -} LPC_SYSCON_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- 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 */ - __O uint32_t SIENR; /*!< (@ 0x4004C008) Set Pin Interrupt Enable (Rising) register */ - __O uint32_t CIENR; /*!< (@ 0x4004C00C) Clear Pin Interrupt Enable (Rising) register */ - __IO uint32_t IENF; /*!< (@ 0x4004C010) Pin Interrupt Enable Falling Edge / Active Level register */ - __O uint32_t SIENF; /*!< (@ 0x4004C014) Set Pin Interrupt Enable Falling Edge / Active Level register */ - __O 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; - - -// ------------------------------------------------------------------------------------------------ -// ----- SSP1 ----- -// ------------------------------------------------------------------------------------------------ -typedef struct { /*!< (@ 0x40058000) SSP1 Structure */ - __IO uint32_t CR0; /*!< (@ 0x40058000) Control Register 0. Selects the serial clock rate, bus type, and data size. */ - __IO uint32_t CR1; /*!< (@ 0x40058004) Control Register 1. Selects master/slave and other modes. */ - __IO uint32_t DR; /*!< (@ 0x40058008) Data Register. Writes fill the transmit FIFO, and reads empty the receive FIFO. */ - __I uint32_t SR; /*!< (@ 0x4005800C) Status Register */ - __IO uint32_t CPSR; /*!< (@ 0x40058010) Clock Prescale Register */ - __IO uint32_t IMSC; /*!< (@ 0x40058014) Interrupt Mask Set and Clear Register */ - __I uint32_t RIS; /*!< (@ 0x40058018) Raw Interrupt Status Register */ - __I uint32_t MIS; /*!< (@ 0x4005801C) Masked Interrupt Status Register */ - __O uint32_t ICR; /*!< (@ 0x40058020) SSPICR Interrupt Clear Register */ -} LPC_SSP1_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- 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_INT0_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- GPIO_GROUP_INT1 ----- -// ------------------------------------------------------------------------------------------------ - -typedef struct { /*!< (@ 0x40060000) GPIO_GROUP_INT1 Structure */ - __IO uint32_t CTRL; /*!< (@ 0x40060000) GPIO grouped interrupt control register */ - __I uint32_t RESERVED0[7]; - __IO uint32_t PORT_POL[2]; /*!< (@ 0x40060020) GPIO grouped interrupt port 0 polarity register */ - __I uint32_t RESERVED1[6]; - __IO uint32_t PORT_ENA[2]; /*!< (@ 0x40060040) GPIO grouped interrupt port 0/1 enable register */ -} LPC_GPIO_GROUP_INT1_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- Repetitive Interrupt Timer (RIT) ----- -// ------------------------------------------------------------------------------------------------ - -typedef struct { /*!< (@ 0x40064000) RITIMER Structure */ - __IO uint32_t COMPVAL; /*!< (@ 0x40064000) RITIMER compare register */ - __IO uint32_t MASK; /*!< (@ 0x40064004) RITIMER mask register */ - __IO uint32_t CTRL; /*!< (@ 0x40064008) RITIMER control register */ - __IO uint32_t COUNTER; /*!< (@ 0x4006400C) RITIMER counter register */ - __IO uint32_t COMPVAL_H; /*!< (@ 0x40064010) RITIMER compare upper register */ - __IO uint32_t MASK_H; /*!< (@ 0x40064014) RITIMER mask upper register */ - __I uint32_t RESERVED0[1]; - __IO uint32_t COUNTER_H; /*!< (@ 0x4006401C) RITIMER counter upper register */ -} LPC_RITIMER_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- USB ----- -// ------------------------------------------------------------------------------------------------ -typedef struct { /*!< (@ 0x40020000) USB Structure */ - __IO uint32_t DEVCMDSTAT; /*!< (@ 0x40020000) USB Device Command/Status register */ - __IO uint32_t INFO; /*!< (@ 0x40020004) USB Info register */ - __IO uint32_t EPLISTSTART; /*!< (@ 0x40020008) USB EP Command/Status List start address */ - __IO uint32_t DATABUFSTART; /*!< (@ 0x4002000C) USB Data buffer start address */ - __IO uint32_t LPM; /*!< (@ 0x40020010) Link Power Management register */ - __IO uint32_t EPSKIP; /*!< (@ 0x40020014) USB Endpoint skip */ - __IO uint32_t EPINUSE; /*!< (@ 0x40020018) USB Endpoint Buffer in use */ - __IO uint32_t EPBUFCFG; /*!< (@ 0x4002001C) USB Endpoint Buffer Configuration register */ - __IO uint32_t INTSTAT; /*!< (@ 0x40020020) USB interrupt status register */ - __IO uint32_t INTEN; /*!< (@ 0x40020024) USB interrupt enable register */ - __IO uint32_t INTSETSTAT; /*!< (@ 0x40020028) USB set interrupt status register */ - __IO uint32_t INTROUTING; /*!< (@ 0x4002002C) USB interrupt routing register */ - __I uint32_t RESERVED0[1]; - __I uint32_t EPTOGGLE; /*!< (@ 0x40020034) USB Endpoint toggle register */ -} LPC_USB_Type; - - -// ------------------------------------------------------------------------------------------------ -// ----- GPIO_PORT ----- -// ------------------------------------------------------------------------------------------------ - -typedef struct { /*!< (@ 0x50000000) GPIO_PORT Structure */ - 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 */ - }; - __I uint32_t RESERVED1[960]; - __IO uint32_t DIR[2]; /*!< (@ 0x50002000) Direction registers port 0/1 */ - __I uint32_t RESERVED2[30]; - __IO uint32_t MASK[2]; /*!< (@ 0x50002080) Mask register port 0/1 */ - __I uint32_t RESERVED3[30]; - __IO uint32_t PIN[2]; /*!< (@ 0x50002100) Portpin register port 0 */ - __I uint32_t RESERVED4[30]; - __IO uint32_t MPIN[2]; /*!< (@ 0x50002180) Masked port register port 0/1 */ - __I uint32_t RESERVED5[30]; - __IO uint32_t SET[2]; /*!< (@ 0x50002200) Write: Set register for port 0/1 Read: output bits for port 0/1 */ - __I uint32_t RESERVED6[30]; - __O uint32_t CLR[2]; /*!< (@ 0x50002280) Clear port 0/1 */ - __I uint32_t RESERVED7[30]; - __O uint32_t NOT[2]; /*!< (@ 0x50002300) Toggle port 0/1 */ -} 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_IOCON_BASE (0x40044000) -#define LPC_SYSCON_BASE (0x40048000) -#define LPC_GPIO_PIN_INT_BASE (0x4004C000) -#define LPC_SSP1_BASE (0x40058000) -#define LPC_GPIO_GROUP_INT0_BASE (0x4005C000) -#define LPC_GPIO_GROUP_INT1_BASE (0x40060000) -#define LPC_RITIMER_BASE (0x40064000) -#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_CT16B0_Type *) LPC_CT16B0_BASE) -#define LPC_CT16B1 ((LPC_CT16B1_Type *) LPC_CT16B1_BASE) -#define LPC_CT32B0 ((LPC_CT32B0_Type *) LPC_CT32B0_BASE) -#define LPC_CT32B1 ((LPC_CT32B1_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_SSP0_Type *) LPC_SSP0_BASE) -#define LPC_SSP1 ((LPC_SSP1_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_INT0_Type*) LPC_GPIO_GROUP_INT0_BASE) -#define LPC_GPIO_GROUP_INT1 ((LPC_GPIO_GROUP_INT1_Type*) LPC_GPIO_GROUP_INT1_BASE) -#define LPC_RITIMER ((LPC_RITIMER_Type *) LPC_RITIMER_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 h1usf */ - -#ifdef __cplusplus -} -#endif - - -#endif // __LPC13UXX_H__ + +/****************************************************************************************************//** + * @file LPC13Uxx.h + * + * + * + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File for + * default LPC13Uxx Device Series + * + * @version V0.1 + * @date 18. Jan 2012 + * + * @note Generated with SFDGen V2.6 Build 4f on Tuesday, 17.01.2012 13:39:52 + * + * from CMSIS SVD File 'LPC13uxx_svd_v0.1.xml' Version 0.1, + * created on Thurs, 01.19.2012 15:13:15, last modified on Thurs, 01.19.2012 15:53:09 + * + *******************************************************************************************************/ + +/** @addtogroup NXP + * @{ + */ + +/** @addtogroup LPC13Uxx + * @{ + */ + +#ifndef __LPC13UXX_H__ +#define __LPC13UXX_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined ( __CC_ARM ) + #pragma anon_unions +#endif + + /* Interrupt Number Definition */ + +typedef enum { +// ------------------------- Cortex-M3 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 */ + MemoryManagement_IRQn = -12, /*!< 4 Memory Management, MPU mismatch, including Access Violation and No Match */ + BusFault_IRQn = -11, /*!< 5 Bus Fault, Pre-Fetch-, Memory Access Fault, other address/memory related Fault */ + UsageFault_IRQn = -10, /*!< 6 Usage Fault, i.e. Undef Instruction, Illegal State Transition */ + 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 */ +// ---------------------------- LPC13Uxx Specific Interrupt Numbers -------------------------------- + PIN_INT0_IRQn = 0, /*!< 0 PIN_INT0 */ + PIN_INT1_IRQn = 1, /*!< 1 PIN_INT1 */ + PIN_INT2_IRQn = 2, /*!< 2 PIN_INT2 */ + PIN_INT3_IRQn = 3, /*!< 3 PIN_INT3 */ + PIN_INT4_IRQn = 4, /*!< 4 PIN_INT4 */ + PIN_INT5_IRQn = 5, /*!< 5 PIN_INT5 */ + PIN_INT6_IRQn = 6, /*!< 6 PIN_INT6 */ + PIN_INT7_IRQn = 7, /*!< 7 PIN_INT7 */ + GINT0_IRQn = 8, /*!< 8 GINT0 */ + GINT1_IRQn = 9, /*!< 9 GINT1 */ + Reserved0_IRQn = 10, /*!< 10 Reserved Interrupt */ + Reserved1_IRQn = 11, /*!< 11 Reserved Interrupt */ + RIT_IRQn = 12, /*!< 12 Repetitive Interrupt Timer */ + Reserved2_IRQn = 13, /*!< 13 Reserved Interrupt */ + SSP1_IRQn = 14, /*!< 14 SSP1 */ + I2C_IRQn = 15, /*!< 15 I2C */ + CT16B0_IRQn = 16, /*!< 16 CT16B0 */ + CT16B1_IRQn = 17, /*!< 17 CT16B1 */ + CT32B0_IRQn = 18, /*!< 18 CT32B0 */ + CT32B1_IRQn = 19, /*!< 19 CT32B1 */ + SSP0_IRQn = 20, /*!< 20 SSP0 */ + USART_IRQn = 21, /*!< 21 USART */ + USB_IRQ_IRQn = 22, /*!< 22 USB_IRQ */ + USB_FIQ_IRQn = 23, /*!< 23 USB_FIQ */ + ADC_IRQn = 24, /*!< 24 ADC */ + WDT_IRQn = 25, /*!< 25 WDT */ + BOD_IRQn = 26, /*!< 26 BOD */ + FMC_IRQn = 27, /*!< 27 FMC */ + Reserved3_IRQn = 28, /*!< 28 Reserved Interrupt */ + Reserved4_IRQn = 29, /*!< 29 Reserved Interrupt */ + USBWAKEUP_IRQn = 30, /*!< 30 USBWAKEUP */ + Reserved5_IRQn = 31, /*!< 31 Reserved Interrupt */ +} IRQn_Type; + + +/** @addtogroup Configuration_of_CMSIS + * @{ + */ + +/* Processor and Core Peripheral Section */ /* Configuration of the Cortex-M3 Processor and Core Peripherals */ + +#define __CM3_REV 0x0000 /*!< Cortex-M3 Core Revision */ +#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 /*!< Cortex-M3 processor and core peripherals */ +#include "system_LPC13Uxx.h" /*!< LPC13Uxx System */ + +/** @addtogroup Device_Peripheral_Registers + * @{ + */ + + +// ------------------------------------------------------------------------------------------------ +// ----- I2C ----- +// ------------------------------------------------------------------------------------------------ + + + +typedef struct { /*!< (@ 0x40000000) I2C Structure */ + __IO uint32_t CONSET; /*!< (@ 0x40000000) I2C Control Set Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is set. Writing a zero has no effect on the corresponding bit in the I2C control register. */ + __I uint32_t STAT; /*!< (@ 0x40000004) I2C Status Register. During I2C operation, this register provides detailed status codes that allow software to determine the next action needed. */ + __IO uint32_t DAT; /*!< (@ 0x40000008) I2C Data Register. During master or slave transmit mode, data to be transmitted is written to this register. During master or slave receive mode, data that has been received may be read from this register. */ + __IO uint32_t ADR0; /*!< (@ 0x4000000C) I2C Slave Address Register 0. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ + __IO uint32_t SCLH; /*!< (@ 0x40000010) SCH Duty Cycle Register High Half Word. Determines the high time of the I2C clock. */ + __IO uint32_t SCLL; /*!< (@ 0x40000014) SCL Duty Cycle Register Low Half Word. Determines the low time of the I2C clock. I2nSCLL and I2nSCLH together determine the clock frequency generated by an I2C master and certain times used in slave mode. */ + __O uint32_t CONCLR; /*!< (@ 0x40000018) I2C Control Clear Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is cleared. Writing a zero has no effect on the corresponding bit in the I2C control register. */ + __IO uint32_t MMCTRL; /*!< (@ 0x4000001C) Monitor mode control register. */ + union{ + __IO uint32_t ADR[3]; /*!< (@ 0x40000020) I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ + struct{ + __IO uint32_t ADR1; + __IO uint32_t ADR2; + __IO uint32_t ADR3; + }; + }; + __I uint32_t DATA_BUFFER; /*!< (@ 0x4000002C) Data buffer register. The contents of the 8 MSBs of the I2DAT shift register will be transferred to the DATA_BUFFER automatically after every nine bits (8 bits of data plus ACK or NACK) has been received on the bus. */ + union{ + __IO uint32_t MASK[4]; /*!< (@ 0x40000030) I2C Slave address mask register. This mask register is associated with I2ADR0 to determine an address match. The mask register has no effect when comparing to the General Call address (0000000). */ + struct{ + __IO uint32_t MASK0; + __IO uint32_t MASK1; + __IO uint32_t MASK2; + __IO uint32_t MASK3; + }; + }; +} LPC_I2C_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- WWDT ----- +// ------------------------------------------------------------------------------------------------ + + +typedef struct { /*!< (@ 0x40004000) WWDT Structure */ + __IO uint32_t MOD; /*!< (@ 0x40004000) Watchdog mode register. This register contains the basic mode and status of the Watchdog Timer. */ + __IO uint32_t TC; /*!< (@ 0x40004004) Watchdog timer constant register. This 24-bit register determines the time-out value. */ + __O uint32_t FEED; /*!< (@ 0x40004008) Watchdog feed sequence register. Writing 0xAA followed by 0x55 to this register reloads the Watchdog timer with the value contained in WDTC. */ + __I uint32_t TV; /*!< (@ 0x4000400C) Watchdog timer value register. This 24-bit register reads out the current value of the Watchdog timer. */ + __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 ----- +// ------------------------------------------------------------------------------------------------ + + +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; /*!< (@ 0x40008058) Synchronous mode control register. */ +} LPC_USART_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- CT16B0 ----- +// ------------------------------------------------------------------------------------------------ + +typedef struct { /*!< (@ 0x4000C000) CT16B0 Structure */ + __IO uint32_t IR; /*!< (@ 0x4000C000) Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */ + __IO uint32_t TCR; /*!< (@ 0x4000C004) Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */ + __IO uint32_t TC; /*!< (@ 0x4000C008) Timer Counter. The 16-bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */ + __IO uint32_t PR; /*!< (@ 0x4000C00C) Prescale Register. When the Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */ + __IO uint32_t PC; /*!< (@ 0x4000C010) Prescale Counter. The 16-bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */ + __IO uint32_t MCR; /*!< (@ 0x4000C014) Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */ + union { + __IO uint32_t MR[4]; /*!< (@ 0x4000C018) Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */ + struct{ + __IO uint32_t MR0; /*!< (@ 0x4000C018) Match Register. MR0 */ + __IO uint32_t MR1; /*!< (@ 0x4000C01C) Match Register. MR1 */ + __IO uint32_t MR2; /*!< (@ 0x4000C020) Match Register. MR2 */ + __IO uint32_t MR3; /*!< (@ 0x4000C024) Match Register. MR3 */ + }; + }; + __IO uint32_t CCR; /*!< (@ 0x4000C028) Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */ + union{ + __I uint32_t CR[4]; /*!< (@ 0x4000C02C) Capture Register. CR is loaded with the value of TC when there is an event on the CT16B0_CAP input. */ + struct{ + __I uint32_t CR0; /*!< (@ 0x4000C02C) Capture Register. CR 0 */ + __I uint32_t CR1; /*!< (@ 0x4000C030) Capture Register. CR 1 */ + __I uint32_t CR2; /*!< (@ 0x4000C034) Capture Register. CR 2 */ + __I uint32_t CR3; /*!< (@ 0x4000C038) Capture Register. CR 3 */ + }; + }; + __IO uint32_t EMR; /*!< (@ 0x4000C03C) External Match Register. The EMR controls the match function and the external match pins */ + __I uint32_t RESERVED0[12]; + __IO uint32_t CTCR; /*!< (@ 0x4000C070) Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */ + __IO uint32_t PWMC; /*!< (@ 0x4000C074) PWM Control Register. The PWMCON enables PWM mode for the external match pins CT16B0_MAT[1:0] and CT16B1_MAT[1:0]. */ +} LPC_CT16B0_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- CT16B1 ----- +// ------------------------------------------------------------------------------------------------ + +typedef struct { /*!< (@ 0x40010000) CT16B1 Structure */ + __IO uint32_t IR; /*!< (@ 0x40010000) Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */ + __IO uint32_t TCR; /*!< (@ 0x40010004) Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */ + __IO uint32_t TC; /*!< (@ 0x40010008) Timer Counter. The 16-bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */ + __IO uint32_t PR; /*!< (@ 0x4001000C) Prescale Register. When the Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */ + __IO uint32_t PC; /*!< (@ 0x40010010) Prescale Counter. The 16-bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */ + __IO uint32_t MCR; /*!< (@ 0x40010014) Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */ + union { + __IO uint32_t MR[4]; /*!< (@ 0x40010018) Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */ + struct{ + __IO uint32_t MR0; /*!< (@ 0x40010018) Match Register. MR0 */ + __IO uint32_t MR1; /*!< (@ 0x4001001C) Match Register. MR1 */ + __IO uint32_t MR2; /*!< (@ 0x40010020) Match Register. MR2 */ + __IO uint32_t MR3; /*!< (@ 0x40010024) Match Register. MR3 */ + }; + }; + __IO uint32_t CCR; /*!< (@ 0x40010028) Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */ + union{ + __I uint32_t CR[4]; /*!< (@ 0x4001002C) Capture Register. CR is loaded with the value of TC when there is an event on the CT16B0_CAP input. */ + struct{ + __I uint32_t CR0; /*!< (@ 0x4001002C) Capture Register. CR 0 */ + __I uint32_t CR1; /*!< (@ 0x40010030) Capture Register. CR 1 */ + __I uint32_t CR2; /*!< (@ 0x40010034) Capture Register. CR 2 */ + __I uint32_t CR3; /*!< (@ 0x40010038) Capture Register. CR 3 */ + }; + }; + __IO uint32_t EMR; /*!< (@ 0x4001003C) External Match Register. The EMR controls the match function and the external match pins */ + __I uint32_t RESERVED0[12]; + __IO uint32_t CTCR; /*!< (@ 0x40010070) Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */ + __IO uint32_t PWMC; /*!< (@ 0x40010074) PWM Control Register. The PWMCON enables PWM mode for the external match pins CT16B0_MAT[1:0] and CT16B1_MAT[1:0]. */ +} LPC_CT16B1_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- CT32B0 ----- +// ------------------------------------------------------------------------------------------------ +typedef struct { /*!< (@ 0x40014000) CT32B0 Structure */ + __IO uint32_t IR; /*!< (@ 0x40014000) Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */ + __IO uint32_t TCR; /*!< (@ 0x40014004) Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */ + __IO uint32_t TC; /*!< (@ 0x40014008) Timer Counter. The 32-bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */ + __IO uint32_t PR; /*!< (@ 0x4001400C) Prescale Register. When the Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */ + __IO uint32_t PC; /*!< (@ 0x40014010) Prescale Counter. The 32-bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */ + __IO uint32_t MCR; /*!< (@ 0x40014014) Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */ + union { + __IO uint32_t MR[4]; /*!< (@ 0x40014018) Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */ + struct{ + __IO uint32_t MR0; /*!< (@ 0x40014018) Match Register. MR0 */ + __IO uint32_t MR1; /*!< (@ 0x4001401C) Match Register. MR1 */ + __IO uint32_t MR2; /*!< (@ 0x40014020) Match Register. MR2 */ + __IO uint32_t MR3; /*!< (@ 0x40014024) Match Register. MR3 */ + }; + }; + __IO uint32_t CCR; /*!< (@ 0x40014028) Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */ + union{ + __I uint32_t CR[4]; /*!< (@ 0x4001402C) Capture Register. CR is loaded with the value of TC when there is an event on the CT32B_CAP0 input. */ + struct{ + __I uint32_t CR0; /*!< (@ 0x4001402C) Capture Register. CR 0 */ + __I uint32_t CR1; /*!< (@ 0x40014030) Capture Register. CR 1 */ + __I uint32_t CR2; /*!< (@ 0x40014034) Capture Register. CR 2 */ + __I uint32_t CR3; /*!< (@ 0x40014038) Capture Register. CR 3 */ + }; + }; + __IO uint32_t EMR; /*!< (@ 0x4001403C) External Match Register. The EMR controls the match function and the external match pins CT32Bn_MAT[3:0]. */ + __I uint32_t RESERVED0[12]; + __IO uint32_t CTCR; /*!< (@ 0x40014070) Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */ + __IO uint32_t PWMC; /*!< (@ 0x40014074) PWM Control Register. The PWMCON enables PWM mode for the external match pins CT32Bn_MAT[3:0]. */ +} LPC_CT32B0_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- CT32B1 ----- +// ------------------------------------------------------------------------------------------------ +typedef struct { /*!< (@ 0x40018000) CT32B1 Structure */ + __IO uint32_t IR; /*!< (@ 0x40018000) Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */ + __IO uint32_t TCR; /*!< (@ 0x40018004) Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */ + __IO uint32_t TC; /*!< (@ 0x40018008) Timer Counter. The 32-bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */ + __IO uint32_t PR; /*!< (@ 0x4001800C) Prescale Register. When the Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */ + __IO uint32_t PC; /*!< (@ 0x40018010) Prescale Counter. The 32-bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */ + __IO uint32_t MCR; /*!< (@ 0x40018014) Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */ + union { + __IO uint32_t MR[4]; /*!< (@ 0x40018018) Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */ + 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; /*!< (@ 0x40018028) Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */ + union{ + __I uint32_t CR[4]; /*!< (@ 0x4001802C) Capture Register. CR is loaded with the value of TC when there is an event on the CT32B_CAP0 input. */ + 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; /*!< (@ 0x4001803C) External Match Register. The EMR controls the match function and the external match pins CT32Bn_MAT[3:0]. */ + __I uint32_t RESERVED0[12]; + __IO uint32_t CTCR; /*!< (@ 0x40018070) Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */ + __IO uint32_t PWMC; /*!< (@ 0x40018074) PWM Control Register. The PWMCON enables PWM mode for the external match pins CT32Bn_MAT[3:0]. */ +} LPC_CT32B1_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- ADC ----- +// ------------------------------------------------------------------------------------------------ +typedef struct { /*!< (@ 0x4001C000) ADC Structure */ + __IO uint32_t CR; /*!< (@ 0x4001C000) A/D Control Register. The CR register must be written to select the operating mode before A/D conversion can occur. */ + __IO uint32_t GDR; /*!< (@ 0x4001C004) A/D Global Data Register. Contains the result of the most recent A/D conversion. */ + __I uint32_t RESERVED0[1]; + __IO uint32_t INTEN; /*!< (@ 0x4001C00C) A/D Interrupt Enable Register. This register contains enable bits that allow the DONE flag of each A/D channel to be included or excluded from contributing to the generation of an A/D interrupt. */ + union{ + __I uint32_t DR[8]; /*!< (@ 0x4001C010) A/D Channel Data Register*/ + struct{ + __I uint32_t DR0; /*!< (@ 0x4001C010) A/D Channel Data Register 0*/ + __I uint32_t DR1; /*!< (@ 0x4001C014) A/D Channel Data Register 1*/ + __I uint32_t DR2; /*!< (@ 0x4001C018) A/D Channel Data Register 2*/ + __I uint32_t DR3; /*!< (@ 0x4001C01C) A/D Channel Data Register 3*/ + __I uint32_t DR4; /*!< (@ 0x4001C020) A/D Channel Data Register 4*/ + __I uint32_t DR5; /*!< (@ 0x4001C024) A/D Channel Data Register 5*/ + __I uint32_t DR6; /*!< (@ 0x4001C028) A/D Channel Data Register 6*/ + __I uint32_t DR7; /*!< (@ 0x4001C02C) A/D Channel Data Register 7*/ + }; + }; + __I uint32_t STAT; /*!< (@ 0x4001C030) A/D Status Register. This register contains DONE and OVERRUN flags for all of the A/D channels, as well as the A/D interrupt flag. */ +} LPC_ADC_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- 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 */ + }; + }; + __IO uint32_t GPREG4; /*!< (@ 0x40038014) General purpose register 4 */ +} LPC_PMU_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- 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]; + __O uint32_t FMSTATCLR; /*!< (@ 0x4003CFE8) Signature generation status clear register */ +} LPC_FLASHCTRL_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- 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 */ + __O uint32_t ICR; /*!< (@ 0x40040020) SSPICR Interrupt Clear Register */ +} LPC_SSP0_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- IOCON ----- +// ------------------------------------------------------------------------------------------------ +typedef struct { /*!< (@ 0x40044000) IOCON 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/SWO */ + __IO uint32_t PIO0_9; /*!< (@ 0x40044024) I/O configuration for pin PIO0_9/MOSI0/CT16B0_MAT1/TRACECLK */ + __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; /*!< (@ 0x40044060) I/O configuration for pin PIO1_0/CT32B1_MAT0 */ + __IO uint32_t PIO1_1; /*!< (@ 0x40044064) I/O configuration for pin PIO1_1/CT32B1_MAT1 */ + __IO uint32_t PIO1_2; /*!< (@ 0x40044068) I/O configuration for pin PIO1_2/CT32B1_MAT2 */ + __IO uint32_t PIO1_3; /*!< (@ 0x4004406C) I/O configuration for pin PIO1_3/CT32B1_MAT3 */ + __IO uint32_t PIO1_4; /*!< (@ 0x40044070) I/O configuration for pin PIO1_4/CT32B1_CAP0 */ + __IO uint32_t PIO1_5; /*!< (@ 0x40044074) I/O configuration for pin PIO1_5/CT32B1_CAP1 */ + __IO uint32_t PIO1_6; /*!< (@ 0x40044078) I/O configuration for pin PIO1_6 */ + __IO uint32_t PIO1_7; /*!< (@ 0x4004407C) I/O configuration for pin PIO1_7 */ + __IO uint32_t PIO1_8; /*!< (@ 0x40044080) I/O configuration for pin PIO1_8 */ + __IO uint32_t PIO1_9; /*!< (@ 0x40044084) I/O configuration for pin PIO1_9 */ + __IO uint32_t PIO1_10; /*!< (@ 0x40044088) I/O configuration for pin PIO1_10 */ + __IO uint32_t PIO1_11; /*!< (@ 0x4004408C) I/O configuration for pin PIO1_11 */ + __IO uint32_t PIO1_12; /*!< (@ 0x40044090) I/O configuration for pin PIO1_12 */ + __IO uint32_t PIO1_13; /*!< (@ 0x40044094) I/O configuration for PIO1_13/DTR/CT16B0_MAT0/TXD */ + __IO uint32_t PIO1_14; /*!< (@ 0x40044098) I/O configuration for 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; /*!< (@ 0x400440A4) I/O configuration for PIO1_17/CT16B0_CAP1/RXD */ + __IO uint32_t PIO1_18; /*!< (@ 0x400440A8) I/O configuration for PIO1_18/CT16B1_CAP1/TXD */ + __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; /*!< (@ 0x400440D8) I/O configuration for pin PIO1_30 */ + __IO uint32_t PIO1_31; /*!< (@ 0x400440DC) I/O configuration for pin PIO1_31 */ +} LPC_IOCON_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- SYSCON ----- +// ------------------------------------------------------------------------------------------------ + +typedef struct { /*!< (@ 0x40048000) SYSCON Structure */ + __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 */ + __I uint32_t RESERVED3; + __IO uint32_t USBPLLCLKSEL; /*!< (@ 0x40048048) USB PLL clock source select */ + __I uint32_t RESERVED4[9]; + __IO uint32_t MAINCLKSEL; /*!< (@ 0x40048070) Main clock source select */ + __I uint32_t RESERVED5; + __IO uint32_t SYSAHBCLKDIV; /*!< (@ 0x40048078) System clock divider */ + __I uint32_t RESERVED6; + __IO uint32_t SYSAHBCLKCTRL; /*!< (@ 0x40048080) System clock control */ + __I uint32_t RESERVED7[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 RESERVED8[3]; + __IO uint32_t TRACECLKDIV; /*!< (@ 0x400480AC) ARM trace clock divider */ + __IO uint32_t SYSTICKCLKDIV; /*!< (@ 0x400480B0) SYSTICK clock divder */ + __I uint32_t RESERVED9[3]; + __IO uint32_t USBCLKSEL; /*!< (@ 0x400480C0) USB clock source select */ + __I uint32_t RESERVED10; + __IO uint32_t USBCLKDIV; /*!< (@ 0x400480C8) USB clock source divider */ + __I uint32_t RESERVED11[5]; + __IO uint32_t CLKOUTSEL; /*!< (@ 0x400480E0) CLKOUT clock source select */ + __I uint32_t RESERVED12; + __IO uint32_t CLKOUTDIV; /*!< (@ 0x400480E8) CLKOUT clock divider */ + __I uint32_t RESERVED13[5]; + __I uint32_t PIOPORCAP0; /*!< (@ 0x40048100) POR captured PIO status 0 */ + __I uint32_t PIOPORCAP1; /*!< (@ 0x40048104) POR captured PIO status 1 */ + __I uint32_t RESERVED14[18]; + __IO uint32_t BODCTRL; /*!< (@ 0x40048150) Brown-Out Detect */ + __IO uint32_t SYSTCKCAL; /*!< (@ 0x40048154) System tick counter calibration */ + __I uint32_t RESERVED15[6]; + __IO uint32_t IRQLATENCY; /*!< (@ 0x40048170) IQR delay. Allows trade-off between interrupt latency and determinism. */ + __IO uint32_t NMISRC; /*!< (@ 0x40048174) NMI Source Control */ + __IO uint32_t PINSEL[8]; /*!< (@ 0x40048178) GPIO Pin Interrupt Select register */ + __IO uint32_t USBCLKCTRL; /*!< (@ 0x40048198) USB clock control */ + __I uint32_t USBCLKST; /*!< (@ 0x4004819C) USB clock status */ + __I uint32_t RESERVED16[25]; + __IO uint32_t STARTERP0; /*!< (@ 0x40048204) Start logic 0 interrupt wake-up enable register 0 */ + __I uint32_t RESERVED17[3]; + __IO uint32_t STARTERP1; /*!< (@ 0x40048214) Start logic 1 interrupt wake-up enable register 1 */ + __I uint32_t RESERVED18[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 RESERVED19[111]; + __I uint32_t DEVICE_ID; /*!< (@ 0x400483F8) Device ID */ +} LPC_SYSCON_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- 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 */ + __O uint32_t SIENR; /*!< (@ 0x4004C008) Set Pin Interrupt Enable (Rising) register */ + __O uint32_t CIENR; /*!< (@ 0x4004C00C) Clear Pin Interrupt Enable (Rising) register */ + __IO uint32_t IENF; /*!< (@ 0x4004C010) Pin Interrupt Enable Falling Edge / Active Level register */ + __O uint32_t SIENF; /*!< (@ 0x4004C014) Set Pin Interrupt Enable Falling Edge / Active Level register */ + __O 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; + + +// ------------------------------------------------------------------------------------------------ +// ----- SSP1 ----- +// ------------------------------------------------------------------------------------------------ +typedef struct { /*!< (@ 0x40058000) SSP1 Structure */ + __IO uint32_t CR0; /*!< (@ 0x40058000) Control Register 0. Selects the serial clock rate, bus type, and data size. */ + __IO uint32_t CR1; /*!< (@ 0x40058004) Control Register 1. Selects master/slave and other modes. */ + __IO uint32_t DR; /*!< (@ 0x40058008) Data Register. Writes fill the transmit FIFO, and reads empty the receive FIFO. */ + __I uint32_t SR; /*!< (@ 0x4005800C) Status Register */ + __IO uint32_t CPSR; /*!< (@ 0x40058010) Clock Prescale Register */ + __IO uint32_t IMSC; /*!< (@ 0x40058014) Interrupt Mask Set and Clear Register */ + __I uint32_t RIS; /*!< (@ 0x40058018) Raw Interrupt Status Register */ + __I uint32_t MIS; /*!< (@ 0x4005801C) Masked Interrupt Status Register */ + __O uint32_t ICR; /*!< (@ 0x40058020) SSPICR Interrupt Clear Register */ +} LPC_SSP1_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- 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_INT0_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- GPIO_GROUP_INT1 ----- +// ------------------------------------------------------------------------------------------------ + +typedef struct { /*!< (@ 0x40060000) GPIO_GROUP_INT1 Structure */ + __IO uint32_t CTRL; /*!< (@ 0x40060000) GPIO grouped interrupt control register */ + __I uint32_t RESERVED0[7]; + __IO uint32_t PORT_POL[2]; /*!< (@ 0x40060020) GPIO grouped interrupt port 0 polarity register */ + __I uint32_t RESERVED1[6]; + __IO uint32_t PORT_ENA[2]; /*!< (@ 0x40060040) GPIO grouped interrupt port 0/1 enable register */ +} LPC_GPIO_GROUP_INT1_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- Repetitive Interrupt Timer (RIT) ----- +// ------------------------------------------------------------------------------------------------ + +typedef struct { /*!< (@ 0x40064000) RITIMER Structure */ + __IO uint32_t COMPVAL; /*!< (@ 0x40064000) RITIMER compare register */ + __IO uint32_t MASK; /*!< (@ 0x40064004) RITIMER mask register */ + __IO uint32_t CTRL; /*!< (@ 0x40064008) RITIMER control register */ + __IO uint32_t COUNTER; /*!< (@ 0x4006400C) RITIMER counter register */ + __IO uint32_t COMPVAL_H; /*!< (@ 0x40064010) RITIMER compare upper register */ + __IO uint32_t MASK_H; /*!< (@ 0x40064014) RITIMER mask upper register */ + __I uint32_t RESERVED0[1]; + __IO uint32_t COUNTER_H; /*!< (@ 0x4006401C) RITIMER counter upper register */ +} LPC_RITIMER_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- USB ----- +// ------------------------------------------------------------------------------------------------ +typedef struct { /*!< (@ 0x40020000) USB Structure */ + __IO uint32_t DEVCMDSTAT; /*!< (@ 0x40020000) USB Device Command/Status register */ + __IO uint32_t INFO; /*!< (@ 0x40020004) USB Info register */ + __IO uint32_t EPLISTSTART; /*!< (@ 0x40020008) USB EP Command/Status List start address */ + __IO uint32_t DATABUFSTART; /*!< (@ 0x4002000C) USB Data buffer start address */ + __IO uint32_t LPM; /*!< (@ 0x40020010) Link Power Management register */ + __IO uint32_t EPSKIP; /*!< (@ 0x40020014) USB Endpoint skip */ + __IO uint32_t EPINUSE; /*!< (@ 0x40020018) USB Endpoint Buffer in use */ + __IO uint32_t EPBUFCFG; /*!< (@ 0x4002001C) USB Endpoint Buffer Configuration register */ + __IO uint32_t INTSTAT; /*!< (@ 0x40020020) USB interrupt status register */ + __IO uint32_t INTEN; /*!< (@ 0x40020024) USB interrupt enable register */ + __IO uint32_t INTSETSTAT; /*!< (@ 0x40020028) USB set interrupt status register */ + __IO uint32_t INTROUTING; /*!< (@ 0x4002002C) USB interrupt routing register */ + __I uint32_t RESERVED0[1]; + __I uint32_t EPTOGGLE; /*!< (@ 0x40020034) USB Endpoint toggle register */ +} LPC_USB_Type; + + +// ------------------------------------------------------------------------------------------------ +// ----- GPIO_PORT ----- +// ------------------------------------------------------------------------------------------------ + +typedef struct { /*!< (@ 0x50000000) GPIO_PORT Structure */ + 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 */ + }; + __I uint32_t RESERVED1[960]; + __IO uint32_t DIR[2]; /*!< (@ 0x50002000) Direction registers port 0/1 */ + __I uint32_t RESERVED2[30]; + __IO uint32_t MASK[2]; /*!< (@ 0x50002080) Mask register port 0/1 */ + __I uint32_t RESERVED3[30]; + __IO uint32_t PIN[2]; /*!< (@ 0x50002100) Portpin register port 0 */ + __I uint32_t RESERVED4[30]; + __IO uint32_t MPIN[2]; /*!< (@ 0x50002180) Masked port register port 0/1 */ + __I uint32_t RESERVED5[30]; + __IO uint32_t SET[2]; /*!< (@ 0x50002200) Write: Set register for port 0/1 Read: output bits for port 0/1 */ + __I uint32_t RESERVED6[30]; + __O uint32_t CLR[2]; /*!< (@ 0x50002280) Clear port 0/1 */ + __I uint32_t RESERVED7[30]; + __O uint32_t NOT[2]; /*!< (@ 0x50002300) Toggle port 0/1 */ +} 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_IOCON_BASE (0x40044000) +#define LPC_SYSCON_BASE (0x40048000) +#define LPC_GPIO_PIN_INT_BASE (0x4004C000) +#define LPC_SSP1_BASE (0x40058000) +#define LPC_GPIO_GROUP_INT0_BASE (0x4005C000) +#define LPC_GPIO_GROUP_INT1_BASE (0x40060000) +#define LPC_RITIMER_BASE (0x40064000) +#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_CT16B0_Type *) LPC_CT16B0_BASE) +#define LPC_CT16B1 ((LPC_CT16B1_Type *) LPC_CT16B1_BASE) +#define LPC_CT32B0 ((LPC_CT32B0_Type *) LPC_CT32B0_BASE) +#define LPC_CT32B1 ((LPC_CT32B1_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_SSP0_Type *) LPC_SSP0_BASE) +#define LPC_SSP1 ((LPC_SSP1_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_INT0_Type*) LPC_GPIO_GROUP_INT0_BASE) +#define LPC_GPIO_GROUP_INT1 ((LPC_GPIO_GROUP_INT1_Type*) LPC_GPIO_GROUP_INT1_BASE) +#define LPC_RITIMER ((LPC_RITIMER_Type *) LPC_RITIMER_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 h1usf */ + +#ifdef __cplusplus +} +#endif + + +#endif // __LPC13UXX_H__ diff --git a/demos/device/src/main.c b/demos/device/src/main.c index a69a710f1..914c97217 100644 --- a/demos/device/src/main.c +++ b/demos/device/src/main.c @@ -1,163 +1,163 @@ -/**************************************************************************/ -/*! - @file main.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include -#include -#include - -#include "boards/board.h" -#include "tusb.h" - -#include "mscd_app.h" -#include "keyboardd_app.h" -#include "moused_app.h" -#include "cdcd_app.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para); -OSAL_TASK_DEF(led_blinking_task, 128, LED_BLINKING_APP_TASK_PRIO); - -void print_greeting(void); - -#if TUSB_CFG_OS == TUSB_OS_NONE -// like a real RTOS, this function is a main loop invoking each task in application and never return -void os_none_start_scheduler(void) -{ - while (1) - { - tusb_task_runner(); - led_blinking_task(NULL); - - keyboardd_app_task(NULL); - moused_app_task(NULL); - cdcd_serial_app_task(NULL); - } -} -#endif - -int main(void) -{ - board_init(); - print_greeting(); - - tusb_init(); - - //------------- application task init -------------// - (void) osal_task_create( OSAL_TASK_REF(led_blinking_task) ); - - msc_dev_app_init(); - keyboardd_app_init(); - moused_app_init(); - cdcd_serial_app_init(); - - //------------- start OS scheduler (never return) -------------// -#if TUSB_CFG_OS == TUSB_OS_FREERTOS - vTaskStartScheduler(); -#elif TUSB_CFG_OS == TUSB_OS_NONE - os_none_start_scheduler(); -#elif TUSB_CFG_OS == TUSB_OS_CMSIS_RTX - while(1) - { - osDelay(osWaitForever); // CMSIS RTX osKernelStart already started, main() is a task - } -#else - #error need to start RTOS schduler -#endif - - while(1) { } // should not reach here - - return 0; -} - -//--------------------------------------------------------------------+ -// BLINKING TASK -//--------------------------------------------------------------------+ -static uint32_t led_blink_interval_ms = 1000; // default is 1 seconda -void led_blinking_set_interval(uint32_t ms) -{ - led_blink_interval_ms = ms; -} - -OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para) -{ - OSAL_TASK_LOOP_BEGIN - - static uint32_t led_on_mask = 0; - - osal_task_delay(led_blink_interval_ms); - - board_leds(led_on_mask, 1 - led_on_mask); - led_on_mask = 1 - led_on_mask; // toggle - - uint32_t btn_mask = board_buttons(); - for(uint8_t i=0; i<32; i++) - { - if ( BIT_TEST_(btn_mask, i) ) printf("button %d is pressed\n", i); - } - - OSAL_TASK_LOOP_END -} - -//--------------------------------------------------------------------+ -// HELPER FUNCTION -//--------------------------------------------------------------------+ -void print_greeting(void) -{ - printf("\n\ ---------------------------------------------------------------------\n\ -- Device Demo (a tinyusb example)\n\ -- if you find any bugs or get any questions, feel free to file an\n\ -- issue at https://github.com/hathach/tinyusb\n\ ---------------------------------------------------------------------\n\n" - ); - - puts("This demo supports the following classes"); - if (TUSB_CFG_DEVICE_HID_MOUSE ) puts(" - HID Mouse"); - if (TUSB_CFG_DEVICE_HID_KEYBOARD ) puts(" - HID Keyboard"); - if (TUSB_CFG_DEVICE_MSC ) puts(" - Mass Storage"); - if (TUSB_CFG_DEVICE_CDC ) puts(" - Communication Device Class"); -} +/**************************************************************************/ +/*! + @file main.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include +#include +#include + +#include "boards/board.h" +#include "tusb.h" + +#include "mscd_app.h" +#include "keyboardd_app.h" +#include "moused_app.h" +#include "cdcd_app.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para); +OSAL_TASK_DEF(led_blinking_task, 128, LED_BLINKING_APP_TASK_PRIO); + +void print_greeting(void); + +#if TUSB_CFG_OS == TUSB_OS_NONE +// like a real RTOS, this function is a main loop invoking each task in application and never return +void os_none_start_scheduler(void) +{ + while (1) + { + tusb_task_runner(); + led_blinking_task(NULL); + + keyboardd_app_task(NULL); + moused_app_task(NULL); + cdcd_serial_app_task(NULL); + } +} +#endif + +int main(void) +{ + board_init(); + print_greeting(); + + tusb_init(); + + //------------- application task init -------------// + (void) osal_task_create( OSAL_TASK_REF(led_blinking_task) ); + + msc_dev_app_init(); + keyboardd_app_init(); + moused_app_init(); + cdcd_serial_app_init(); + + //------------- start OS scheduler (never return) -------------// +#if TUSB_CFG_OS == TUSB_OS_FREERTOS + vTaskStartScheduler(); +#elif TUSB_CFG_OS == TUSB_OS_NONE + os_none_start_scheduler(); +#elif TUSB_CFG_OS == TUSB_OS_CMSIS_RTX + while(1) + { + osDelay(osWaitForever); // CMSIS RTX osKernelStart already started, main() is a task + } +#else + #error need to start RTOS schduler +#endif + + while(1) { } // should not reach here + + return 0; +} + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +static uint32_t led_blink_interval_ms = 1000; // default is 1 seconda +void led_blinking_set_interval(uint32_t ms) +{ + led_blink_interval_ms = ms; +} + +OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para) +{ + OSAL_TASK_LOOP_BEGIN + + static uint32_t led_on_mask = 0; + + osal_task_delay(led_blink_interval_ms); + + board_leds(led_on_mask, 1 - led_on_mask); + led_on_mask = 1 - led_on_mask; // toggle + + uint32_t btn_mask = board_buttons(); + for(uint8_t i=0; i<32; i++) + { + if ( BIT_TEST_(btn_mask, i) ) printf("button %d is pressed\n", i); + } + + OSAL_TASK_LOOP_END +} + +//--------------------------------------------------------------------+ +// HELPER FUNCTION +//--------------------------------------------------------------------+ +void print_greeting(void) +{ + printf("\n\ +--------------------------------------------------------------------\n\ +- Device Demo (a tinyusb example)\n\ +- if you find any bugs or get any questions, feel free to file an\n\ +- issue at https://github.com/hathach/tinyusb\n\ +--------------------------------------------------------------------\n\n" + ); + + puts("This demo supports the following classes"); + if (TUSB_CFG_DEVICE_HID_MOUSE ) puts(" - HID Mouse"); + if (TUSB_CFG_DEVICE_HID_KEYBOARD ) puts(" - HID Keyboard"); + if (TUSB_CFG_DEVICE_MSC ) puts(" - Mass Storage"); + if (TUSB_CFG_DEVICE_CDC ) puts(" - Communication Device Class"); +} diff --git a/tinyusb/class/msc_device.c b/tinyusb/class/msc_device.c index 997145499..2196a0164 100644 --- a/tinyusb/class/msc_device.c +++ b/tinyusb/class/msc_device.c @@ -52,17 +52,15 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ typedef struct { - uint8_t interface_number; - endpoint_handle_t edpt_in, edpt_out; - - // must be in USB ram - ATTR_USB_MIN_ALIGNMENT uint8_t max_lun; // can STALL for one LUN - ATTR_USB_MIN_ALIGNMENT msc_cmd_block_wrapper_t cbw; ATTR_USB_MIN_ALIGNMENT msc_cmd_status_wrapper_t csw; + ATTR_USB_MIN_ALIGNMENT uint8_t max_lun; // can STALL for one LUN + + uint8_t interface_number; + endpoint_handle_t edpt_in, edpt_out; }mscd_interface_t; -TUSB_CFG_ATTR_USBRAM STATIC_VAR mscd_interface_t mscd_data; +ATTR_USB_MIN_ALIGNMENT TUSB_CFG_ATTR_USBRAM STATIC_VAR mscd_interface_t mscd_data; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ diff --git a/tinyusb/class/msc_host.c b/tinyusb/class/msc_host.c index dcb3fff6f..1380b1e03 100644 --- a/tinyusb/class/msc_host.c +++ b/tinyusb/class/msc_host.c @@ -1,429 +1,429 @@ -/**************************************************************************/ -/*! - @file msc_host.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -#include "tusb_option.h" - -#if MODE_HOST_SUPPORTED & TUSB_CFG_HOST_MSC - -#define _TINY_USB_SOURCE_FILE_ - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "common/common.h" -#include "msc_host.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -TUSB_CFG_ATTR_USBRAM STATIC_VAR msch_interface_t msch_data[TUSB_CFG_HOST_DEVICE_MAX]; - - -//------------- Initalization Data -------------// -OSAL_SEM_DEF(msch_semaphore); -static osal_semaphore_handle_t msch_sem_hdl; - -// buffer used to read scsi information when mounted, largest response data currently is inquiry -TUSB_CFG_ATTR_USBRAM ATTR_ALIGNED(4) STATIC_VAR uint8_t msch_buffer[sizeof(scsi_inquiry_data_t)]; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// PUBLIC API -//--------------------------------------------------------------------+ -bool tusbh_msc_is_mounted(uint8_t dev_addr) -{ - return tusbh_device_is_configured(dev_addr) && // is configured can be omitted - msch_data[dev_addr-1].is_initialized; -} - -bool tusbh_msc_is_busy(uint8_t dev_addr) -{ - return msch_data[dev_addr-1].is_initialized && - hcd_pipe_is_busy(msch_data[dev_addr-1].bulk_in); -} - -uint8_t const* tusbh_msc_get_vendor_name(uint8_t dev_addr) -{ - return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].vendor_id : NULL; -} - -uint8_t const* tusbh_msc_get_product_name(uint8_t dev_addr) -{ - return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].product_id : NULL; -} - -tusb_error_t tusbh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size) -{ - if ( !msch_data[dev_addr-1].is_initialized ) return TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED; - ASSERT(p_last_lba != NULL && p_block_size != NULL, TUSB_ERROR_INVALID_PARA); - - (*p_last_lba) = msch_data[dev_addr-1].last_lba; - (*p_block_size) = (uint32_t) msch_data[dev_addr-1].block_size; - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// PUBLIC API: SCSI COMMAND -//--------------------------------------------------------------------+ -static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun) ATTR_ALWAYS_INLINE; -static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun) -{ - p_cbw->signature = MSC_CBW_SIGNATURE; - p_cbw->tag = 0xCAFECAFE; - p_cbw->lun = lun; -} - -static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer) ATTR_WARN_UNUSED_RESULT; -static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer) -{ - if ( NULL != p_buffer) - { // there is data phase - if (p_msch->cbw.dir & TUSB_DIR_DEV_TO_HOST_MASK) - { - ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) ); - ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_in , p_buffer, p_msch->cbw.xfer_bytes) ); - }else - { - ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t)) ); - ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out , p_buffer, p_msch->cbw.xfer_bytes, false) ); - } - } - - ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , (uint8_t*) &p_msch->csw, sizeof(msc_cmd_status_wrapper_t), true) ); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) -{ - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - p_msch->cbw.xfer_bytes = sizeof(scsi_inquiry_data_t); - p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t); - - //------------- SCSI command -------------// - scsi_inquiry_t cmd_inquiry = - { - .cmd_code = SCSI_CMD_INQUIRY, - .alloc_length = sizeof(scsi_inquiry_data_t) - }; - - memcpy(p_msch->cbw.command, &cmd_inquiry, p_msch->cbw.cmd_len); - - ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) ); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_msc_read_capacity10(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) -{ - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - p_msch->cbw.xfer_bytes = sizeof(scsi_read_capacity10_data_t); - p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_read_capacity10_t); - - //------------- SCSI command -------------// - scsi_read_capacity10_t cmd_read_capacity10 = - { - .cmd_code = SCSI_CMD_READ_CAPACITY_10, - .lba = 0, - .partial_medium_indicator = 0 - }; - - memcpy(p_msch->cbw.command, &cmd_read_capacity10, p_msch->cbw.cmd_len); - - ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) ); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) -{ - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - p_msch->cbw.xfer_bytes = 18; - p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_request_sense_t); - - //------------- SCSI command -------------// - scsi_request_sense_t cmd_request_sense = - { - .cmd_code = SCSI_CMD_REQUEST_SENSE, - .alloc_length = 18 - }; - - memcpy(p_msch->cbw.command, &cmd_request_sense, p_msch->cbw.cmd_len); - - ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) ); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, msc_cmd_status_wrapper_t * p_csw) -{ - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - - p_msch->cbw.xfer_bytes = 0; // Number of bytes - p_msch->cbw.dir = TUSB_DIR_HOST_TO_DEV; - p_msch->cbw.cmd_len = sizeof(scsi_test_unit_ready_t); - - //------------- SCSI command -------------// - scsi_test_unit_ready_t cmd_test_unit_ready = - { - .cmd_code = SCSI_CMD_TEST_UNIT_READY, - .lun = lun // according to wiki - }; - - memcpy(p_msch->cbw.command, &cmd_test_unit_ready, p_msch->cbw.cmd_len); - - // TODO MSCH refractor test uinit ready - ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) ); - ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , (uint8_t*) p_csw, sizeof(msc_cmd_status_wrapper_t), true) ); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) -{ - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - - p_msch->cbw.xfer_bytes = p_msch->block_size*block_count; // Number of bytes - p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_read10_t); - - //------------- SCSI command -------------// - scsi_read10_t cmd_read10 = - { - .cmd_code = SCSI_CMD_READ_10, - .lba = __n2be(lba), - .block_count = u16_le2be(block_count) - }; - - memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len); - - ASSERT_STATUS ( msch_command_xfer(p_msch, p_buffer)); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count) -{ - msch_interface_t* p_msch = &msch_data[dev_addr-1]; - - //------------- Command Block Wrapper -------------// - msc_cbw_add_signature(&p_msch->cbw, lun); - - p_msch->cbw.xfer_bytes = p_msch->block_size*block_count; // Number of bytes - p_msch->cbw.dir = TUSB_DIR_HOST_TO_DEV; - p_msch->cbw.cmd_len = sizeof(scsi_write10_t); - - //------------- SCSI command -------------// - scsi_write10_t cmd_write10 = - { - .cmd_code = SCSI_CMD_WRITE_10, - .lba = __n2be(lba), - .block_count = u16_le2be(block_count) - }; - - memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len); - - ASSERT_STATUS ( msch_command_xfer(p_msch, (void*) p_buffer)); - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// CLASS-USBH API (don't require to verify parameters) -//--------------------------------------------------------------------+ -void msch_init(void) -{ - memclr_(msch_data, sizeof(msch_interface_t)*TUSB_CFG_HOST_DEVICE_MAX); - msch_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(msch_semaphore) ); -} - -tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) -{ - tusb_error_t error; - - OSAL_SUBTASK_BEGIN - - if (! ( MSC_SUBCLASS_SCSI == p_interface_desc->bInterfaceSubClass && - MSC_PROTOCOL_BOT == p_interface_desc->bInterfaceProtocol ) ) - { - return TUSB_ERROR_MSC_UNSUPPORTED_PROTOCOL; - } - - //------------- Open Data Pipe -------------// - tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc ); - for(uint32_t i=0; i<2; i++) - { - SUBTASK_ASSERT(TUSB_DESC_TYPE_ENDPOINT == p_endpoint->bDescriptorType); - SUBTASK_ASSERT(TUSB_XFER_BULK == p_endpoint->bmAttributes.xfer); - - pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_DEV_TO_HOST_MASK ) ? - &msch_data[dev_addr-1].bulk_in : &msch_data[dev_addr-1].bulk_out; - - (*p_pipe_hdl) = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_MSC); - SUBTASK_ASSERT( pipehandle_is_valid(*p_pipe_hdl) ); - - p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_endpoint ); - } - - msch_data[dev_addr-1].interface_number = p_interface_desc->bInterfaceNumber; - (*p_length) += sizeof(tusb_descriptor_interface_t) + 2*sizeof(tusb_descriptor_endpoint_t); - - - //------------- Get Max Lun -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE), - MSC_REQUEST_GET_MAX_LUN, 0, msch_data[dev_addr-1].interface_number, - 1, msch_buffer ), - error - ); - - SUBTASK_ASSERT( TUSB_ERROR_NONE == error /* && TODO STALL means zero */); - msch_data[dev_addr-1].max_lun = msch_buffer[0]; - -#if 0 - //------------- Reset -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE), - MSC_REQUEST_RESET, 0, msch_data[dev_addr-1].interface_number, - 0, NULL ), - error - ); -#endif - - enum { SCSI_XFER_TIMEOUT = 2000 }; - //------------- SCSI Inquiry -------------// - tusbh_msc_inquiry(dev_addr, 0, msch_buffer); - osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); - SUBTASK_ASSERT_STATUS(error); - - memcpy(msch_data[dev_addr-1].vendor_id , ((scsi_inquiry_data_t*) msch_buffer)->vendor_id , 8); - memcpy(msch_data[dev_addr-1].product_id, ((scsi_inquiry_data_t*) msch_buffer)->product_id, 16); - - //------------- SCSI Read Capacity 10 -------------// - tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); - osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); - SUBTASK_ASSERT_STATUS(error); - - // NOTE: my toshiba thumb-drive stall the first Read Capacity and require the sequence - // Read Capacity --> Stalled --> Clear Stall --> Request Sense --> Read Capacity (2) to work - if ( hcd_pipe_is_stalled(msch_data[dev_addr-1].bulk_in) ) - { // clear stall TODO abstract clear stall function - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_STANDARD, TUSB_REQUEST_RECIPIENT_ENDPOINT), - TUSB_REQUEST_CLEAR_FEATURE, 0, hcd_pipe_get_endpoint_addr(msch_data[dev_addr-1].bulk_in), - 0, NULL ), - error - ); - SUBTASK_ASSERT_STATUS(error); - - hcd_pipe_clear_stall(msch_data[dev_addr-1].bulk_in); - osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); // wait for SCSI status - SUBTASK_ASSERT_STATUS(error); - - //------------- SCSI Request Sense -------------// - tusbh_msc_request_sense(dev_addr, 0, msch_buffer); - osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); - SUBTASK_ASSERT_STATUS(error); - - //------------- Re-read SCSI Read Capactity -------------// - tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); - osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); - SUBTASK_ASSERT_STATUS(error); - } - - msch_data[dev_addr-1].last_lba = __be2n( ((scsi_read_capacity10_data_t*)msch_buffer)->last_lba ); - msch_data[dev_addr-1].block_size = (uint16_t) __be2n( ((scsi_read_capacity10_data_t*)msch_buffer)->block_size ); - - msch_data[dev_addr-1].is_initialized = true; - tusbh_msc_mounted_cb(dev_addr); - - OSAL_SUBTASK_END -} - -void msch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) -{ - if ( pipehandle_is_equal(pipe_hdl, msch_data[pipe_hdl.dev_addr-1].bulk_in) ) - { - if (msch_data[pipe_hdl.dev_addr-1].is_initialized) - { - tusbh_msc_isr(pipe_hdl.dev_addr, event, xferred_bytes); - }else - { // still initializing under open subtask - osal_semaphore_post(msch_sem_hdl); - } - } -} - -void msch_close(uint8_t dev_addr) -{ - (void) hcd_pipe_close(msch_data[dev_addr-1].bulk_in); - (void) hcd_pipe_close(msch_data[dev_addr-1].bulk_out); - - memclr_(&msch_data[dev_addr-1], sizeof(msch_interface_t)); - osal_semaphore_reset(msch_sem_hdl); - - tusbh_msc_unmounted_cb(dev_addr); // invoke Application Callback -} - -//--------------------------------------------------------------------+ -// INTERNAL & HELPER -//--------------------------------------------------------------------+ - - -#endif +/**************************************************************************/ +/*! + @file msc_host.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +#include "tusb_option.h" + +#if MODE_HOST_SUPPORTED & TUSB_CFG_HOST_MSC + +#define _TINY_USB_SOURCE_FILE_ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "common/common.h" +#include "msc_host.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +TUSB_CFG_ATTR_USBRAM STATIC_VAR msch_interface_t msch_data[TUSB_CFG_HOST_DEVICE_MAX]; + + +//------------- Initalization Data -------------// +OSAL_SEM_DEF(msch_semaphore); +static osal_semaphore_handle_t msch_sem_hdl; + +// buffer used to read scsi information when mounted, largest response data currently is inquiry +TUSB_CFG_ATTR_USBRAM ATTR_ALIGNED(4) STATIC_VAR uint8_t msch_buffer[sizeof(scsi_inquiry_data_t)]; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// PUBLIC API +//--------------------------------------------------------------------+ +bool tusbh_msc_is_mounted(uint8_t dev_addr) +{ + return tusbh_device_is_configured(dev_addr) && // is configured can be omitted + msch_data[dev_addr-1].is_initialized; +} + +bool tusbh_msc_is_busy(uint8_t dev_addr) +{ + return msch_data[dev_addr-1].is_initialized && + hcd_pipe_is_busy(msch_data[dev_addr-1].bulk_in); +} + +uint8_t const* tusbh_msc_get_vendor_name(uint8_t dev_addr) +{ + return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].vendor_id : NULL; +} + +uint8_t const* tusbh_msc_get_product_name(uint8_t dev_addr) +{ + return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].product_id : NULL; +} + +tusb_error_t tusbh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size) +{ + if ( !msch_data[dev_addr-1].is_initialized ) return TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED; + ASSERT(p_last_lba != NULL && p_block_size != NULL, TUSB_ERROR_INVALID_PARA); + + (*p_last_lba) = msch_data[dev_addr-1].last_lba; + (*p_block_size) = (uint32_t) msch_data[dev_addr-1].block_size; + + return TUSB_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// PUBLIC API: SCSI COMMAND +//--------------------------------------------------------------------+ +static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun) ATTR_ALWAYS_INLINE; +static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun) +{ + p_cbw->signature = MSC_CBW_SIGNATURE; + p_cbw->tag = 0xCAFECAFE; + p_cbw->lun = lun; +} + +static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer) ATTR_WARN_UNUSED_RESULT; +static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer) +{ + if ( NULL != p_buffer) + { // there is data phase + if (p_msch->cbw.dir & TUSB_DIR_DEV_TO_HOST_MASK) + { + ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) ); + ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_in , p_buffer, p_msch->cbw.xfer_bytes) ); + }else + { + ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t)) ); + ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out , p_buffer, p_msch->cbw.xfer_bytes, false) ); + } + } + + ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , (uint8_t*) &p_msch->csw, sizeof(msc_cmd_status_wrapper_t), true) ); + + return TUSB_ERROR_NONE; +} + +tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) +{ + msch_interface_t* p_msch = &msch_data[dev_addr-1]; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&p_msch->cbw, lun); + p_msch->cbw.xfer_bytes = sizeof(scsi_inquiry_data_t); + p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK; + p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t); + + //------------- SCSI command -------------// + scsi_inquiry_t cmd_inquiry = + { + .cmd_code = SCSI_CMD_INQUIRY, + .alloc_length = sizeof(scsi_inquiry_data_t) + }; + + memcpy(p_msch->cbw.command, &cmd_inquiry, p_msch->cbw.cmd_len); + + ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) ); + + return TUSB_ERROR_NONE; +} + +tusb_error_t tusbh_msc_read_capacity10(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) +{ + msch_interface_t* p_msch = &msch_data[dev_addr-1]; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&p_msch->cbw, lun); + p_msch->cbw.xfer_bytes = sizeof(scsi_read_capacity10_data_t); + p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK; + p_msch->cbw.cmd_len = sizeof(scsi_read_capacity10_t); + + //------------- SCSI command -------------// + scsi_read_capacity10_t cmd_read_capacity10 = + { + .cmd_code = SCSI_CMD_READ_CAPACITY_10, + .lba = 0, + .partial_medium_indicator = 0 + }; + + memcpy(p_msch->cbw.command, &cmd_read_capacity10, p_msch->cbw.cmd_len); + + ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) ); + + return TUSB_ERROR_NONE; +} + +tusb_error_t tusbh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) +{ + msch_interface_t* p_msch = &msch_data[dev_addr-1]; + + //------------- Command Block Wrapper -------------// + p_msch->cbw.xfer_bytes = 18; + p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK; + p_msch->cbw.cmd_len = sizeof(scsi_request_sense_t); + + //------------- SCSI command -------------// + scsi_request_sense_t cmd_request_sense = + { + .cmd_code = SCSI_CMD_REQUEST_SENSE, + .alloc_length = 18 + }; + + memcpy(p_msch->cbw.command, &cmd_request_sense, p_msch->cbw.cmd_len); + + ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) ); + + return TUSB_ERROR_NONE; +} + +tusb_error_t tusbh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, msc_cmd_status_wrapper_t * p_csw) +{ + msch_interface_t* p_msch = &msch_data[dev_addr-1]; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&p_msch->cbw, lun); + + p_msch->cbw.xfer_bytes = 0; // Number of bytes + p_msch->cbw.dir = TUSB_DIR_HOST_TO_DEV; + p_msch->cbw.cmd_len = sizeof(scsi_test_unit_ready_t); + + //------------- SCSI command -------------// + scsi_test_unit_ready_t cmd_test_unit_ready = + { + .cmd_code = SCSI_CMD_TEST_UNIT_READY, + .lun = lun // according to wiki + }; + + memcpy(p_msch->cbw.command, &cmd_test_unit_ready, p_msch->cbw.cmd_len); + + // TODO MSCH refractor test uinit ready + ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) ); + ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , (uint8_t*) p_csw, sizeof(msc_cmd_status_wrapper_t), true) ); + + return TUSB_ERROR_NONE; +} + +tusb_error_t tusbh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) +{ + msch_interface_t* p_msch = &msch_data[dev_addr-1]; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&p_msch->cbw, lun); + + p_msch->cbw.xfer_bytes = p_msch->block_size*block_count; // Number of bytes + p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK; + p_msch->cbw.cmd_len = sizeof(scsi_read10_t); + + //------------- SCSI command -------------// + scsi_read10_t cmd_read10 = + { + .cmd_code = SCSI_CMD_READ_10, + .lba = __n2be(lba), + .block_count = u16_le2be(block_count) + }; + + memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len); + + ASSERT_STATUS ( msch_command_xfer(p_msch, p_buffer)); + + return TUSB_ERROR_NONE; +} + +tusb_error_t tusbh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count) +{ + msch_interface_t* p_msch = &msch_data[dev_addr-1]; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&p_msch->cbw, lun); + + p_msch->cbw.xfer_bytes = p_msch->block_size*block_count; // Number of bytes + p_msch->cbw.dir = TUSB_DIR_HOST_TO_DEV; + p_msch->cbw.cmd_len = sizeof(scsi_write10_t); + + //------------- SCSI command -------------// + scsi_write10_t cmd_write10 = + { + .cmd_code = SCSI_CMD_WRITE_10, + .lba = __n2be(lba), + .block_count = u16_le2be(block_count) + }; + + memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len); + + ASSERT_STATUS ( msch_command_xfer(p_msch, (void*) p_buffer)); + + return TUSB_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// CLASS-USBH API (don't require to verify parameters) +//--------------------------------------------------------------------+ +void msch_init(void) +{ + memclr_(msch_data, sizeof(msch_interface_t)*TUSB_CFG_HOST_DEVICE_MAX); + msch_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(msch_semaphore) ); +} + +tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) +{ + tusb_error_t error; + + OSAL_SUBTASK_BEGIN + + if (! ( MSC_SUBCLASS_SCSI == p_interface_desc->bInterfaceSubClass && + MSC_PROTOCOL_BOT == p_interface_desc->bInterfaceProtocol ) ) + { + return TUSB_ERROR_MSC_UNSUPPORTED_PROTOCOL; + } + + //------------- Open Data Pipe -------------// + tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc ); + for(uint32_t i=0; i<2; i++) + { + SUBTASK_ASSERT(TUSB_DESC_TYPE_ENDPOINT == p_endpoint->bDescriptorType); + SUBTASK_ASSERT(TUSB_XFER_BULK == p_endpoint->bmAttributes.xfer); + + pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_DEV_TO_HOST_MASK ) ? + &msch_data[dev_addr-1].bulk_in : &msch_data[dev_addr-1].bulk_out; + + (*p_pipe_hdl) = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_MSC); + SUBTASK_ASSERT( pipehandle_is_valid(*p_pipe_hdl) ); + + p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_endpoint ); + } + + msch_data[dev_addr-1].interface_number = p_interface_desc->bInterfaceNumber; + (*p_length) += sizeof(tusb_descriptor_interface_t) + 2*sizeof(tusb_descriptor_endpoint_t); + + + //------------- Get Max Lun -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE), + MSC_REQUEST_GET_MAX_LUN, 0, msch_data[dev_addr-1].interface_number, + 1, msch_buffer ), + error + ); + + SUBTASK_ASSERT( TUSB_ERROR_NONE == error /* && TODO STALL means zero */); + msch_data[dev_addr-1].max_lun = msch_buffer[0]; + +#if 0 + //------------- Reset -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE), + MSC_REQUEST_RESET, 0, msch_data[dev_addr-1].interface_number, + 0, NULL ), + error + ); +#endif + + enum { SCSI_XFER_TIMEOUT = 2000 }; + //------------- SCSI Inquiry -------------// + tusbh_msc_inquiry(dev_addr, 0, msch_buffer); + osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); + SUBTASK_ASSERT_STATUS(error); + + memcpy(msch_data[dev_addr-1].vendor_id , ((scsi_inquiry_data_t*) msch_buffer)->vendor_id , 8); + memcpy(msch_data[dev_addr-1].product_id, ((scsi_inquiry_data_t*) msch_buffer)->product_id, 16); + + //------------- SCSI Read Capacity 10 -------------// + tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); + osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); + SUBTASK_ASSERT_STATUS(error); + + // NOTE: my toshiba thumb-drive stall the first Read Capacity and require the sequence + // Read Capacity --> Stalled --> Clear Stall --> Request Sense --> Read Capacity (2) to work + if ( hcd_pipe_is_stalled(msch_data[dev_addr-1].bulk_in) ) + { // clear stall TODO abstract clear stall function + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_STANDARD, TUSB_REQUEST_RECIPIENT_ENDPOINT), + TUSB_REQUEST_CLEAR_FEATURE, 0, hcd_pipe_get_endpoint_addr(msch_data[dev_addr-1].bulk_in), + 0, NULL ), + error + ); + SUBTASK_ASSERT_STATUS(error); + + hcd_pipe_clear_stall(msch_data[dev_addr-1].bulk_in); + osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); // wait for SCSI status + SUBTASK_ASSERT_STATUS(error); + + //------------- SCSI Request Sense -------------// + tusbh_msc_request_sense(dev_addr, 0, msch_buffer); + osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); + SUBTASK_ASSERT_STATUS(error); + + //------------- Re-read SCSI Read Capactity -------------// + tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); + osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); + SUBTASK_ASSERT_STATUS(error); + } + + msch_data[dev_addr-1].last_lba = __be2n( ((scsi_read_capacity10_data_t*)msch_buffer)->last_lba ); + msch_data[dev_addr-1].block_size = (uint16_t) __be2n( ((scsi_read_capacity10_data_t*)msch_buffer)->block_size ); + + msch_data[dev_addr-1].is_initialized = true; + tusbh_msc_mounted_cb(dev_addr); + + OSAL_SUBTASK_END +} + +void msch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) +{ + if ( pipehandle_is_equal(pipe_hdl, msch_data[pipe_hdl.dev_addr-1].bulk_in) ) + { + if (msch_data[pipe_hdl.dev_addr-1].is_initialized) + { + tusbh_msc_isr(pipe_hdl.dev_addr, event, xferred_bytes); + }else + { // still initializing under open subtask + osal_semaphore_post(msch_sem_hdl); + } + } +} + +void msch_close(uint8_t dev_addr) +{ + (void) hcd_pipe_close(msch_data[dev_addr-1].bulk_in); + (void) hcd_pipe_close(msch_data[dev_addr-1].bulk_out); + + memclr_(&msch_data[dev_addr-1], sizeof(msch_interface_t)); + osal_semaphore_reset(msch_sem_hdl); + + tusbh_msc_unmounted_cb(dev_addr); // invoke Application Callback +} + +//--------------------------------------------------------------------+ +// INTERNAL & HELPER +//--------------------------------------------------------------------+ + + +#endif diff --git a/tinyusb/common/fifo.c b/tinyusb/common/fifo.c index c6b6dc449..aa5970622 100644 --- a/tinyusb/common/fifo.c +++ b/tinyusb/common/fifo.c @@ -1,188 +1,188 @@ -/**************************************************************************/ -/*! - @file fifo.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ -#include -#include "fifo.h" - -static inline void mutex_lock (fifo_t* f) ATTR_ALWAYS_INLINE; -static inline void mutex_unlock (fifo_t* f) ATTR_ALWAYS_INLINE; -static inline bool is_fifo_initalized(fifo_t* f) ATTR_ALWAYS_INLINE; - - -/**************************************************************************/ -/*! - @brief Read one byte out of the RX buffer. - - This function will return the byte located at the array index of the - read pointer, and then increment the read pointer index. If the read - pointer exceeds the maximum buffer size, it will roll over to zero. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] data - Pointer to the place holder for data read from the buffer - - @returns TRUE if the queue is not empty -*/ -/**************************************************************************/ -bool fifo_read(fifo_t* f, void * p_buffer) -{ - if( !is_fifo_initalized(f) || fifo_is_empty(f) ) - { - return false; - } - - mutex_lock(f); - - memcpy(p_buffer, - f->buffer + (f->rd_idx * f->item_size), - f->item_size); - f->rd_idx = (f->rd_idx + 1) % f->depth; - f->count--; - - mutex_unlock(f); - - return true; -} - -/**************************************************************************/ -/*! - @brief Write one byte into the RX buffer. - - This function will write one byte into the array index specified by - the write pointer and increment the write index. If the write index - exceeds the max buffer size, then it will roll over to zero. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] data - The byte to add to the FIFO - - @returns TRUE if the data was written to the FIFO (overwrittable - FIFO will always return TRUE) -*/ -/**************************************************************************/ -bool fifo_write(fifo_t* f, void const * p_data) -{ - if ( !is_fifo_initalized(f) || (fifo_is_full(f) && !f->overwritable) ) - { - return false; - } - - mutex_lock(f); - - memcpy( f->buffer + (f->wr_idx * f->item_size), - p_data, - f->item_size); - - f->wr_idx = (f->wr_idx + 1) % f->depth; - - if (fifo_is_full(f)) - { - f->rd_idx = f->wr_idx; // keep the full state (rd == wr && len = size) - }else - { - f->count++; - } - - mutex_unlock(f); - - return true; -} - -/**************************************************************************/ -/*! - @brief Clear the fifo read and write pointers and set length to zero - - @param[in] f - Pointer to the FIFO buffer to manipulate -*/ -/**************************************************************************/ -void fifo_clear(fifo_t *f) -{ - mutex_lock(f); - - f->rd_idx = f->wr_idx = f->count = 0; - - mutex_unlock(f); -} - -//--------------------------------------------------------------------+ -// HELPER FUNCTIONS -//--------------------------------------------------------------------+ - -/**************************************************************************/ -/*! - @brief Disables the IRQ specified in the FIFO's 'irq' field - to prevent reads/write issues with interrupts - - @param[in] f - Pointer to the FIFO that should be protected -*/ -/**************************************************************************/ -static inline void mutex_lock (fifo_t* f) -{ -// if (f->irq > 0) -// { -// #if !defined (_TEST_) -// NVIC_DisableIRQ(f->irq); -// #endif -// } -} - -/**************************************************************************/ -/*! - @brief Re-enables the IRQ specified in the FIFO's 'irq' field - - @param[in] f - Pointer to the FIFO that should be protected -*/ -/**************************************************************************/ -static inline void mutex_unlock (fifo_t* f) -{ -// if (f->irq > 0) -// { -// #if !defined (_TEST_) -// NVIC_EnableIRQ(f->irq); -// #endif -// } -} - -static inline bool is_fifo_initalized(fifo_t* f) -{ - return !( f->buffer == NULL || f->depth == 0 || f->item_size == 0); -} +/**************************************************************************/ +/*! + @file fifo.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ +#include +#include "fifo.h" + +static inline void mutex_lock (fifo_t* f) ATTR_ALWAYS_INLINE; +static inline void mutex_unlock (fifo_t* f) ATTR_ALWAYS_INLINE; +static inline bool is_fifo_initalized(fifo_t* f) ATTR_ALWAYS_INLINE; + + +/**************************************************************************/ +/*! + @brief Read one byte out of the RX buffer. + + This function will return the byte located at the array index of the + read pointer, and then increment the read pointer index. If the read + pointer exceeds the maximum buffer size, it will roll over to zero. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] data + Pointer to the place holder for data read from the buffer + + @returns TRUE if the queue is not empty +*/ +/**************************************************************************/ +bool fifo_read(fifo_t* f, void * p_buffer) +{ + if( !is_fifo_initalized(f) || fifo_is_empty(f) ) + { + return false; + } + + mutex_lock(f); + + memcpy(p_buffer, + f->buffer + (f->rd_idx * f->item_size), + f->item_size); + f->rd_idx = (f->rd_idx + 1) % f->depth; + f->count--; + + mutex_unlock(f); + + return true; +} + +/**************************************************************************/ +/*! + @brief Write one byte into the RX buffer. + + This function will write one byte into the array index specified by + the write pointer and increment the write index. If the write index + exceeds the max buffer size, then it will roll over to zero. + + @param[in] f + Pointer to the FIFO buffer to manipulate + @param[in] data + The byte to add to the FIFO + + @returns TRUE if the data was written to the FIFO (overwrittable + FIFO will always return TRUE) +*/ +/**************************************************************************/ +bool fifo_write(fifo_t* f, void const * p_data) +{ + if ( !is_fifo_initalized(f) || (fifo_is_full(f) && !f->overwritable) ) + { + return false; + } + + mutex_lock(f); + + memcpy( f->buffer + (f->wr_idx * f->item_size), + p_data, + f->item_size); + + f->wr_idx = (f->wr_idx + 1) % f->depth; + + if (fifo_is_full(f)) + { + f->rd_idx = f->wr_idx; // keep the full state (rd == wr && len = size) + }else + { + f->count++; + } + + mutex_unlock(f); + + return true; +} + +/**************************************************************************/ +/*! + @brief Clear the fifo read and write pointers and set length to zero + + @param[in] f + Pointer to the FIFO buffer to manipulate +*/ +/**************************************************************************/ +void fifo_clear(fifo_t *f) +{ + mutex_lock(f); + + f->rd_idx = f->wr_idx = f->count = 0; + + mutex_unlock(f); +} + +//--------------------------------------------------------------------+ +// HELPER FUNCTIONS +//--------------------------------------------------------------------+ + +/**************************************************************************/ +/*! + @brief Disables the IRQ specified in the FIFO's 'irq' field + to prevent reads/write issues with interrupts + + @param[in] f + Pointer to the FIFO that should be protected +*/ +/**************************************************************************/ +static inline void mutex_lock (fifo_t* f) +{ +// if (f->irq > 0) +// { +// #if !defined (_TEST_) +// NVIC_DisableIRQ(f->irq); +// #endif +// } +} + +/**************************************************************************/ +/*! + @brief Re-enables the IRQ specified in the FIFO's 'irq' field + + @param[in] f + Pointer to the FIFO that should be protected +*/ +/**************************************************************************/ +static inline void mutex_unlock (fifo_t* f) +{ +// if (f->irq > 0) +// { +// #if !defined (_TEST_) +// NVIC_EnableIRQ(f->irq); +// #endif +// } +} + +static inline bool is_fifo_initalized(fifo_t* f) +{ + return !( f->buffer == NULL || f->depth == 0 || f->item_size == 0); +} diff --git a/tinyusb/common/fifo.h b/tinyusb/common/fifo.h index 4a518ca0c..98a8fbcd2 100644 --- a/tinyusb/common/fifo.h +++ b/tinyusb/common/fifo.h @@ -1,104 +1,104 @@ -/**************************************************************************/ -/*! - @file fifo.h - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -/** \ingroup Group_Common - * - * @{ - */ - -#ifndef _TUSB_FIFO_H_ -#define _TUSB_FIFO_H_ - -#include "common/common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/** \struct fifo_t - * \brief Simple Circular FIFO - */ -typedef struct -{ - uint8_t* const buffer ; ///< buffer pointer - uint16_t const depth ; ///< max items - uint16_t const item_size ; ///< size of each item - volatile uint16_t count ; ///< number of items in queue - volatile uint16_t wr_idx ; ///< write pointer - volatile uint16_t rd_idx ; ///< read pointer - bool overwritable ; - // IRQn_Type irq; -} fifo_t; - -#define FIFO_DEF(name, ff_depth, type, is_overwritable) /*, irq_mutex)*/ \ - uint8_t name##_buffer[ff_depth*sizeof(type)];\ - fifo_t name = {\ - .buffer = name##_buffer,\ - .depth = ff_depth,\ - .item_size = sizeof(type),\ - .overwritable = is_overwritable,\ - /*.irq = irq_mutex*/\ - } - -bool fifo_write(fifo_t* f, void const * p_data); -bool fifo_read(fifo_t* f, void * p_buffer); -void fifo_clear(fifo_t *f); - -static inline bool fifo_is_empty(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE; -static inline bool fifo_is_empty(fifo_t* f) -{ - return (f->count == 0); -} - -static inline bool fifo_is_full(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE; -static inline bool fifo_is_full(fifo_t* f) -{ - return (f->count == f->depth); -} - -static inline uint16_t fifo_get_length(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE; -static inline uint16_t fifo_get_length(fifo_t* f) -{ - return f->count; -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_FIFO_H_ */ +/**************************************************************************/ +/*! + @file fifo.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup Group_Common + * + * @{ + */ + +#ifndef _TUSB_FIFO_H_ +#define _TUSB_FIFO_H_ + +#include "common/common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/** \struct fifo_t + * \brief Simple Circular FIFO + */ +typedef struct +{ + uint8_t* const buffer ; ///< buffer pointer + uint16_t const depth ; ///< max items + uint16_t const item_size ; ///< size of each item + volatile uint16_t count ; ///< number of items in queue + volatile uint16_t wr_idx ; ///< write pointer + volatile uint16_t rd_idx ; ///< read pointer + bool overwritable ; + // IRQn_Type irq; +} fifo_t; + +#define FIFO_DEF(name, ff_depth, type, is_overwritable) /*, irq_mutex)*/ \ + uint8_t name##_buffer[ff_depth*sizeof(type)];\ + fifo_t name = {\ + .buffer = name##_buffer,\ + .depth = ff_depth,\ + .item_size = sizeof(type),\ + .overwritable = is_overwritable,\ + /*.irq = irq_mutex*/\ + } + +bool fifo_write(fifo_t* f, void const * p_data); +bool fifo_read(fifo_t* f, void * p_buffer); +void fifo_clear(fifo_t *f); + +static inline bool fifo_is_empty(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE; +static inline bool fifo_is_empty(fifo_t* f) +{ + return (f->count == 0); +} + +static inline bool fifo_is_full(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE; +static inline bool fifo_is_full(fifo_t* f) +{ + return (f->count == f->depth); +} + +static inline uint16_t fifo_get_length(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE; +static inline uint16_t fifo_get_length(fifo_t* f) +{ + return f->count; +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_FIFO_H_ */ diff --git a/tinyusb/device/dcd.h b/tinyusb/device/dcd.h index 95eef8fce..3df43e30d 100644 --- a/tinyusb/device/dcd.h +++ b/tinyusb/device/dcd.h @@ -1,103 +1,103 @@ -/**************************************************************************/ -/*! - @file dcd.h - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -/** \addtogroup Port Port - * @{ - * \defgroup Port_DCD Device Controller Driver (DCD) - * @{ - */ - -#ifndef _TUSB_DCD_H_ -#define _TUSB_DCD_H_ - -#include "common/common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -typedef struct { - uint8_t coreid; - uint8_t reserved; // TODO redundant, cannot be control as control uses separated API - uint8_t index; - uint8_t class_code; -} endpoint_handle_t; - -static inline bool endpointhandle_is_valid(endpoint_handle_t edpt_hdl) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; -static inline bool endpointhandle_is_valid(endpoint_handle_t edpt_hdl) -{ - return (edpt_hdl.class_code != 0); -} - -static inline bool endpointhandle_is_equal(endpoint_handle_t x, endpoint_handle_t y) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; -static inline bool endpointhandle_is_equal(endpoint_handle_t x, endpoint_handle_t y) -{ - return (x.coreid == y.coreid) && (x.index == y.index) && (x.class_code == y.class_code); -} - -tusb_error_t dcd_init(void) ATTR_WARN_UNUSED_RESULT; - -void dcd_isr(uint8_t coreid); - -//------------- Controller API -------------// -void dcd_controller_connect (uint8_t coreid); -void dcd_controller_disconnect (uint8_t coreid); -void dcd_controller_set_address (uint8_t coreid, uint8_t dev_addr); -void dcd_controller_set_configuration (uint8_t coreid); - -//------------- PIPE API -------------// -tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, uint8_t * p_buffer, uint16_t length, bool int_on_complete); -void dcd_pipe_control_stall(uint8_t coreid); - -endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT; -tusb_error_t dcd_pipe_queue_xfer(endpoint_handle_t edpt_hdl, uint8_t * buffer, uint16_t total_bytes) ATTR_WARN_UNUSED_RESULT; // only queue, not transferring yet -tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, uint8_t * buffer, uint16_t total_bytes, bool int_on_complete) ATTR_WARN_UNUSED_RESULT; -tusb_error_t dcd_pipe_stall(endpoint_handle_t edpt_hdl) ATTR_WARN_UNUSED_RESULT; -bool dcd_pipe_is_busy(endpoint_handle_t edpt_hdl) ATTR_WARN_UNUSED_RESULT ; - -// TODO coreid + endpoint address are part of endpoint handle, not endpoint handle, data toggle also need to be reset -tusb_error_t dcd_pipe_clear_stall(uint8_t coreid, uint8_t edpt_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_DCD_H_ */ - -/// @} -/// @} +/**************************************************************************/ +/*! + @file dcd.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \addtogroup Port Port + * @{ + * \defgroup Port_DCD Device Controller Driver (DCD) + * @{ + */ + +#ifndef _TUSB_DCD_H_ +#define _TUSB_DCD_H_ + +#include "common/common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct { + uint8_t coreid; + uint8_t reserved; // TODO redundant, cannot be control as control uses separated API + uint8_t index; + uint8_t class_code; +} endpoint_handle_t; + +static inline bool endpointhandle_is_valid(endpoint_handle_t edpt_hdl) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; +static inline bool endpointhandle_is_valid(endpoint_handle_t edpt_hdl) +{ + return (edpt_hdl.class_code != 0); +} + +static inline bool endpointhandle_is_equal(endpoint_handle_t x, endpoint_handle_t y) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; +static inline bool endpointhandle_is_equal(endpoint_handle_t x, endpoint_handle_t y) +{ + return (x.coreid == y.coreid) && (x.index == y.index) && (x.class_code == y.class_code); +} + +tusb_error_t dcd_init(void) ATTR_WARN_UNUSED_RESULT; + +void dcd_isr(uint8_t coreid); + +//------------- Controller API -------------// +void dcd_controller_connect (uint8_t coreid); +void dcd_controller_disconnect (uint8_t coreid); +void dcd_controller_set_address (uint8_t coreid, uint8_t dev_addr); +void dcd_controller_set_configuration (uint8_t coreid); + +//------------- PIPE API -------------// +tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, uint8_t * p_buffer, uint16_t length, bool int_on_complete); +void dcd_pipe_control_stall(uint8_t coreid); + +endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT; +tusb_error_t dcd_pipe_queue_xfer(endpoint_handle_t edpt_hdl, uint8_t * buffer, uint16_t total_bytes) ATTR_WARN_UNUSED_RESULT; // only queue, not transferring yet +tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, uint8_t * buffer, uint16_t total_bytes, bool int_on_complete) ATTR_WARN_UNUSED_RESULT; +tusb_error_t dcd_pipe_stall(endpoint_handle_t edpt_hdl) ATTR_WARN_UNUSED_RESULT; +bool dcd_pipe_is_busy(endpoint_handle_t edpt_hdl) ATTR_WARN_UNUSED_RESULT ; + +// TODO coreid + endpoint address are part of endpoint handle, not endpoint handle, data toggle also need to be reset +tusb_error_t dcd_pipe_clear_stall(uint8_t coreid, uint8_t edpt_addr); + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DCD_H_ */ + +/// @} +/// @} diff --git a/tinyusb/device/dcd_lpc175x_6x.c b/tinyusb/device/dcd_lpc175x_6x.c index df6c49154..5a799b24c 100644 --- a/tinyusb/device/dcd_lpc175x_6x.c +++ b/tinyusb/device/dcd_lpc175x_6x.c @@ -1,527 +1,527 @@ -/**************************************************************************/ -/*! - @file dcd_lpc175x_6x.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -#include "tusb_option.h" - -#if MODE_DEVICE_SUPPORTED && (TUSB_CFG_MCU == MCU_LPC175X_6X) - -#define _TINY_USB_SOURCE_FILE_ -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "dcd.h" -#include "dcd_lpc175x_6x.h" -#include "usbd_dcd.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -#define DCD_QHD_MAX 32 -#define DCD_QTD_MAX 32 // TODO scale with configure - -typedef struct { - volatile ATTR_ALIGNED(128) dcd_dma_descriptor_t* udca[DCD_QHD_MAX]; - dcd_dma_descriptor_t dd[DCD_QTD_MAX][2]; // each endpoints can have up to 2 DD queued at a time TODO 0-1 are not used, offset to reduce memory - - uint8_t class_code[DCD_QHD_MAX]; - - struct { - uint8_t* p_data; - uint16_t remaining_bytes; - uint8_t int_on_complete; - }control_dma; - -}dcd_data_t; - -TUSB_CFG_ATTR_USBRAM STATIC_ dcd_data_t dcd_data; - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static void bus_reset(void); -static tusb_error_t pipe_control_read(void * buffer, uint16_t length); -static tusb_error_t pipe_control_write(void const * buffer, uint16_t length); -static tusb_error_t pipe_control_xfer(uint8_t ep_id, uint8_t* p_buffer, uint16_t length); - -//--------------------------------------------------------------------+ -// PIPE HELPER -//--------------------------------------------------------------------+ -static inline uint8_t edpt_addr2phy(uint8_t endpoint_addr) ATTR_CONST ATTR_ALWAYS_INLINE; -static inline uint8_t edpt_addr2phy(uint8_t endpoint_addr) -{ - return 2*(endpoint_addr & 0x0F) + ((endpoint_addr & TUSB_DIR_DEV_TO_HOST_MASK) ? 1 : 0); -} - -static inline void edpt_set_max_packet_size(uint8_t ep_id, uint16_t max_packet_size) ATTR_ALWAYS_INLINE; -static inline void edpt_set_max_packet_size(uint8_t ep_id, uint16_t max_packet_size) -{ // follows example in 11.10.4.2 - LPC_USB->USBReEp |= BIT_(ep_id); - LPC_USB->USBEpInd = ep_id; // select index before setting packet size - LPC_USB->USBMaxPSize = max_packet_size; - -#ifndef _TEST_ - while ((LPC_USB->USBDevIntSt & DEV_INT_ENDPOINT_REALIZED_MASK) == 0) {} // TODO can be omitted - LPC_USB->USBDevIntClr = DEV_INT_ENDPOINT_REALIZED_MASK; -#endif - -} - -//--------------------------------------------------------------------+ -// USBD-DCD API -//--------------------------------------------------------------------+ -static void bus_reset(void) -{ - // step 7 : slave mode set up - LPC_USB->USBEpIntClr = 0xFFFFFFFF; // clear all pending interrupt - LPC_USB->USBDevIntClr = 0xFFFFFFFF; // clear all pending interrupt - LPC_USB->USBEpIntEn = (uint32_t) BIN8(11); // control endpoint cannot use DMA, non-control all use DMA - LPC_USB->USBEpIntPri = 0; // same priority for all endpoint - - // step 8 : DMA set up - LPC_USB->USBEpDMADis = 0xFFFFFFFF; // firstly disable all dma - LPC_USB->USBDMARClr = 0xFFFFFFFF; // clear all pending interrupt - LPC_USB->USBEoTIntClr = 0xFFFFFFFF; - LPC_USB->USBNDDRIntClr = 0xFFFFFFFF; - LPC_USB->USBSysErrIntClr = 0xFFFFFFFF; - - memclr_(&dcd_data, sizeof(dcd_data_t)); -} - -tusb_error_t dcd_init(void) -{ - //------------- user manual 11.13 usb device controller initialization -------------// LPC_USB->USBEpInd = 0; - // step 6 : set up control endpoint - edpt_set_max_packet_size(0, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE); - edpt_set_max_packet_size(1, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE); - - bus_reset(); - - LPC_USB->USBDevIntEn = (DEV_INT_DEVICE_STATUS_MASK | DEV_INT_ENDPOINT_SLOW_MASK | DEV_INT_ERROR_MASK); - LPC_USB->USBUDCAH = (uint32_t) dcd_data.udca; - LPC_USB->USBDMAIntEn = (DMA_INT_END_OF_XFER_MASK | DMA_INT_ERROR_MASK ); - - sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); // connect - - return TUSB_ERROR_NONE; -} - -static void endpoint_non_control_isr(uint32_t eot_int) -{ - for(uint8_t ep_id = 2; ep_id < DCD_QHD_MAX; ep_id++ ) - { - if ( BIT_TEST_(eot_int, ep_id) ) - { - dcd_dma_descriptor_t* const p_first_dd = &dcd_data.dd[ep_id][0]; - dcd_dma_descriptor_t* const p_last_dd = dcd_data.dd[ep_id] + (p_first_dd->is_next_valid ? 1 : 0); // Maximum is 2 QTD are queued in an endpoint - - // only handle when Controller already finished the last DD - if ( dcd_data.udca[ep_id] == p_last_dd ) - { - dcd_data.udca[ep_id] = p_first_dd; // UDCA currently points to the last DD, change to the fixed DD - p_first_dd->buffer_length = 0; // buffer length is used to determined if first dd is queued in pipe xfer function - - if ( p_last_dd->int_on_complete ) - { - endpoint_handle_t edpt_hdl = - { - .coreid = 0, - .index = ep_id, - .class_code = dcd_data.class_code[ep_id] - }; - tusb_event_t event = (p_last_dd->status == DD_STATUS_NORMAL || p_last_dd->status == DD_STATUS_DATA_UNDERUN) ? TUSB_EVENT_XFER_COMPLETE : TUSB_EVENT_XFER_ERROR; - - usbd_xfer_isr(edpt_hdl, event, p_last_dd->present_count); // report only xferred bytes in the IOC qtd - } - } - } - } -} - -static void endpoint_control_isr(void) -{ - uint32_t const endpoint_int_status = LPC_USB->USBEpIntSt & LPC_USB->USBEpIntEn; -// LPC_USB->USBEpIntClr = endpoint_int_status; // acknowledge interrupt TODO cannot immediately acknowledge setup packet - - //------------- Setup Recieved-------------// - if ( (endpoint_int_status & BIT_(0)) && - (sie_read(SIE_CMDCODE_ENDPOINT_SELECT+0, 1) & SIE_SELECT_ENDPOINT_SETUP_RECEIVED_MASK) ) - { - (void) sie_read(SIE_CMDCODE_ENDPOINT_SELECT_CLEAR_INTERRUPT+0, 1); // clear setup bit - - tusb_control_request_t control_request; - pipe_control_read(&control_request, 8); // TODO read before clear setup above - usbd_setup_received_isr(0, &control_request); - } - else if (endpoint_int_status & 0x03) - { - uint8_t const ep_id = ( endpoint_int_status & BIT_(0) ) ? 0 : 1; - - if ( dcd_data.control_dma.remaining_bytes > 0 ) - { // there are still data to transfer - pipe_control_xfer(ep_id, dcd_data.control_dma.p_data, dcd_data.control_dma.remaining_bytes); - } - else - { - dcd_data.control_dma.remaining_bytes = 0; - - if ( BIT_TEST_(dcd_data.control_dma.int_on_complete, ep_id) ) - { - endpoint_handle_t edpt_hdl = { .coreid = 0, .class_code = 0 }; - dcd_data.control_dma.int_on_complete = 0; - - // FIXME xferred_byte for control xfer is not needed now !!! - usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, 0); - } - } - } - - LPC_USB->USBEpIntClr = endpoint_int_status; // acknowledge interrupt TODO cannot immediately acknowledge setup packet -} - -void dcd_isr(uint8_t coreid) -{ - (void) coreid; - uint32_t const device_int_status = LPC_USB->USBDevIntSt & LPC_USB->USBDevIntEn; - LPC_USB->USBDevIntClr = device_int_status;// Acknowledge handled interrupt - - //------------- usb bus event -------------// - if (device_int_status & DEV_INT_DEVICE_STATUS_MASK) - { - uint8_t const dev_status_reg = sie_read(SIE_CMDCODE_DEVICE_STATUS, 1); - if (dev_status_reg & SIE_DEV_STATUS_RESET_MASK) - { - bus_reset(); - usbd_dcd_bus_event_isr(0, USBD_BUS_EVENT_RESET); - } - - if (dev_status_reg & SIE_DEV_STATUS_CONNECT_CHANGE_MASK) - { // device is disconnected, require using VBUS (P1_30) - usbd_dcd_bus_event_isr(0, USBD_BUS_EVENT_UNPLUGGED); - } - - if (dev_status_reg & SIE_DEV_STATUS_SUSPEND_CHANGE_MASK) - { - if (dev_status_reg & SIE_DEV_STATUS_SUSPEND_MASK) - { - usbd_dcd_bus_event_isr(0, USBD_BUS_EVENT_SUSPENDED); - } -// else -// { -// usbd_dcd_bus_event_isr(0, USBD_BUS_EVENT_RESUME); -// } - } - } - - //------------- Control Endpoint (Slave Mode) -------------// - if (device_int_status & DEV_INT_ENDPOINT_SLOW_MASK) - { - endpoint_control_isr(); - } - - //------------- Non-Control Endpoint (DMA Mode) -------------// - uint32_t dma_int_status = LPC_USB->USBDMAIntSt & LPC_USB->USBDMAIntEn; - - if (dma_int_status & DMA_INT_END_OF_XFER_MASK) - { - uint32_t eot_int = LPC_USB->USBEoTIntSt; - LPC_USB->USBEoTIntClr = eot_int; // acknowledge interrupt source - - endpoint_non_control_isr(eot_int); - } - - if (device_int_status & DEV_INT_ERROR_MASK || dma_int_status & DMA_INT_ERROR_MASK) - { - uint32_t error_status = sie_read(SIE_CMDCODE_READ_ERROR_STATUS, 1); - (void) error_status; -// ASSERT(false, (void) 0); - } -} - -//--------------------------------------------------------------------+ -// USBD API - CONTROLLER -//--------------------------------------------------------------------+ -void dcd_controller_connect(uint8_t coreid) -{ - (void) coreid; - sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); -} - -void dcd_controller_set_address(uint8_t coreid, uint8_t dev_addr) -{ - (void) coreid; - sie_write(SIE_CMDCODE_SET_ADDRESS, 1, 0x80 | dev_addr); // 7th bit is : device_enable -} - -void dcd_controller_set_configuration(uint8_t coreid) -{ - (void) coreid; - sie_write(SIE_CMDCODE_CONFIGURE_DEVICE, 1, 1); -} - -//--------------------------------------------------------------------+ -// PIPE CONTROL HELPER -//--------------------------------------------------------------------+ -static inline uint16_t length_byte2dword(uint16_t length_in_bytes) ATTR_ALWAYS_INLINE ATTR_CONST; -static inline uint16_t length_byte2dword(uint16_t length_in_bytes) -{ - return (length_in_bytes + 3) / 4; // length_in_dword -} - -static tusb_error_t pipe_control_xfer(uint8_t ep_id, uint8_t* p_buffer, uint16_t length) -{ - uint16_t const packet_len = min16_of(length, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE); - - if (ep_id) - { - ASSERT_STATUS ( pipe_control_write(p_buffer, packet_len) ); - }else - { - ASSERT_STATUS ( pipe_control_read(p_buffer, packet_len) ); - } - - dcd_data.control_dma.remaining_bytes -= packet_len; - dcd_data.control_dma.p_data += packet_len; - - return TUSB_ERROR_NONE; -} - -static tusb_error_t pipe_control_write(void const * buffer, uint16_t length) -{ - uint32_t const * p_write_data = (uint32_t const *) buffer; - - LPC_USB->USBCtrl = USBCTRL_WRITE_ENABLE_MASK; // logical endpoint = 0 - LPC_USB->USBTxPLen = length; - - for (uint16_t count = 0; count < length_byte2dword(length); count++) - { - LPC_USB->USBTxData = *p_write_data; // NOTE: cortex M3 have no problem with alignment - p_write_data++; - } - - LPC_USB->USBCtrl = 0; - - // select control IN & validate the endpoint - sie_write(SIE_CMDCODE_ENDPOINT_SELECT+1, 0, 0); - sie_write(SIE_CMDCODE_BUFFER_VALIDATE , 0, 0); - - return TUSB_ERROR_NONE; -} - -static tusb_error_t pipe_control_read(void * buffer, uint16_t length) -{ - LPC_USB->USBCtrl = USBCTRL_READ_ENABLE_MASK; // logical endpoint = 0 - while ((LPC_USB->USBRxPLen & USBRXPLEN_PACKET_READY_MASK) == 0) {} // TODO blocking, should have timeout - - uint16_t actual_length = min16_of(length, (uint16_t) (LPC_USB->USBRxPLen & USBRXPLEN_PACKET_LENGTH_MASK) ); - uint32_t *p_read_data = (uint32_t*) buffer; - for( uint16_t count=0; count < length_byte2dword(actual_length); count++) - { - *p_read_data = LPC_USB->USBRxData; - p_read_data++; // increase by 4 ( sizeof(uint32_t) ) - } - - LPC_USB->USBCtrl = 0; - - // select control OUT & clear the endpoint - sie_write(SIE_CMDCODE_ENDPOINT_SELECT+0, 0, 0); - sie_write(SIE_CMDCODE_BUFFER_CLEAR , 0, 0); - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// CONTROL PIPE API -//--------------------------------------------------------------------+ -void dcd_pipe_control_stall(uint8_t coreid) -{ - sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS+0, 1, SIE_SET_ENDPOINT_STALLED_MASK | SIE_SET_ENDPOINT_CONDITION_STALLED_MASK); -} - -tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, uint8_t * p_buffer, uint16_t length, bool int_on_complete) -{ - (void) coreid; - - ASSERT( !(length != 0 && p_buffer == NULL), TUSB_ERROR_INVALID_PARA); - - // determine Endpoint where Data & Status phase occurred (IN or OUT) - uint8_t const ep_data = (dir == TUSB_DIR_DEV_TO_HOST) ? 1 : 0; - uint8_t const ep_status = 1 - ep_data; - - dcd_data.control_dma.int_on_complete = int_on_complete ? BIT_(ep_status) : 0; - - //------------- Data Phase -------------// - if ( length ) - { - dcd_data.control_dma.p_data = (uint8_t*) p_buffer; - dcd_data.control_dma.remaining_bytes = length; - - // lpc17xx already received the first DATA OUT packet by now - ASSERT_STATUS ( pipe_control_xfer(ep_data, p_buffer, length) ); - } - - //------------- Status Phase (opposite direct to Data) -------------// - if (dir == TUSB_DIR_HOST_TO_DEV) - { // only write for CONTROL OUT, CONTROL IN data will be retrieved in dcd_isr // TODO ???? - ASSERT_STATUS ( pipe_control_write(NULL, 0) ); - } - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// BULK/INTERRUPT/ISO PIPE API -//--------------------------------------------------------------------+ -endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code) -{ - (void) coreid; - - endpoint_handle_t const null_handle = { 0 }; - - // TODO refractor to universal pipe open validation function - if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) return null_handle; // TODO not support ISO yet - ASSERT (p_endpoint_desc->wMaxPacketSize.size <= 64, null_handle); // TODO ISO can be 1023, but ISO not supported now - - uint8_t ep_id = edpt_addr2phy( p_endpoint_desc->bEndpointAddress ); - - //------------- Realize Endpoint with Max Packet Size -------------// - edpt_set_max_packet_size(ep_id, p_endpoint_desc->wMaxPacketSize.size); - dcd_data.class_code[ep_id] = class_code; - - //------------- first DD prepare -------------// - dcd_dma_descriptor_t* const p_dd = &dcd_data.dd[ep_id][0]; - memclr_(p_dd, sizeof(dcd_dma_descriptor_t)); - - p_dd->is_isochronous = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; - p_dd->max_packet_size = p_endpoint_desc->wMaxPacketSize.size; - p_dd->is_retired = 1; // inactive at first - - dcd_data.udca[ ep_id ] = p_dd; // hook to UDCA - - sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS+ep_id, 1, 0); // clear all endpoint status - - return (endpoint_handle_t) - { - .coreid = 0, - .index = ep_id, - .class_code = class_code - }; -} - -bool dcd_pipe_is_busy(endpoint_handle_t edpt_hdl) -{ - return (dcd_data.udca[edpt_hdl.index] != NULL && !dcd_data.udca[edpt_hdl.index]->is_retired); -} - -tusb_error_t dcd_pipe_stall(endpoint_handle_t edpt_hdl) -{ - sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS+edpt_hdl.index, 1, SIE_SET_ENDPOINT_STALLED_MASK); - return TUSB_ERROR_NONE; -} - -tusb_error_t dcd_pipe_clear_stall(uint8_t coreid, uint8_t edpt_addr) -{ - uint8_t ep_id = edpt_addr2phy(edpt_addr); - - sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS+ep_id, 1, 0); - - return TUSB_ERROR_FAILED; -} - -void dd_xfer_init(dcd_dma_descriptor_t* p_dd, void* buffer, uint16_t total_bytes) -{ - p_dd->next = 0; - p_dd->is_next_valid = 0; - p_dd->buffer_addr = (uint32_t) buffer; - p_dd->buffer_length = total_bytes; - p_dd->status = DD_STATUS_NOT_SERVICED; - p_dd->iso_last_packet_valid = 0; - p_dd->present_count = 0; -} - -tusb_error_t dcd_pipe_queue_xfer(endpoint_handle_t edpt_hdl, uint8_t * buffer, uint16_t total_bytes) -{ // NOTE for sure the qhd has no dds - dcd_dma_descriptor_t* const p_fixed_dd = &dcd_data.dd[edpt_hdl.index][0]; // always queue with the fixed DD - - dd_xfer_init(p_fixed_dd, buffer, total_bytes); - p_fixed_dd->is_retired = 1; - p_fixed_dd->int_on_complete = 0; - - return TUSB_ERROR_NONE; -} - -tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, uint8_t* buffer, uint16_t total_bytes, bool int_on_complete) -{ - dcd_dma_descriptor_t* const p_first_dd = &dcd_data.dd[edpt_hdl.index][0]; - - //------------- fixed DD is already queued a xfer -------------// - if ( p_first_dd->buffer_length ) - { - // setup new dd - dcd_dma_descriptor_t* const p_dd = &dcd_data.dd[ edpt_hdl.index ][1]; - memclr_(p_dd, sizeof(dcd_dma_descriptor_t)); - - dd_xfer_init(p_dd, buffer, total_bytes); - - p_dd->max_packet_size = p_first_dd->max_packet_size; - p_dd->is_isochronous = p_first_dd->is_isochronous; - p_dd->int_on_complete = int_on_complete; - - // hook to fixed dd - p_first_dd->next = (uint32_t) p_dd; - p_first_dd->is_next_valid = 1; - } - //------------- fixed DD is free -------------// - else - { - dd_xfer_init(p_first_dd, buffer, total_bytes); - p_first_dd->int_on_complete = int_on_complete; - } - - p_first_dd->is_retired = 0; // activate xfer - dcd_data.udca[edpt_hdl.index] = p_first_dd; - LPC_USB->USBEpDMAEn = BIT_(edpt_hdl.index); - - if ( edpt_hdl.index % 2 ) - { // endpoint IN need to actively raise DMA request - LPC_USB->USBDMARSet = BIT_(edpt_hdl.index); - } - - return TUSB_ERROR_NONE; -} - -#endif +/**************************************************************************/ +/*! + @file dcd_lpc175x_6x.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +#include "tusb_option.h" + +#if MODE_DEVICE_SUPPORTED && (TUSB_CFG_MCU == MCU_LPC175X_6X) + +#define _TINY_USB_SOURCE_FILE_ +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "dcd.h" +#include "dcd_lpc175x_6x.h" +#include "usbd_dcd.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +#define DCD_QHD_MAX 32 +#define DCD_QTD_MAX 32 // TODO scale with configure + +typedef struct { + volatile ATTR_ALIGNED(128) dcd_dma_descriptor_t* udca[DCD_QHD_MAX]; + dcd_dma_descriptor_t dd[DCD_QTD_MAX][2]; // each endpoints can have up to 2 DD queued at a time TODO 0-1 are not used, offset to reduce memory + + uint8_t class_code[DCD_QHD_MAX]; + + struct { + uint8_t* p_data; + uint16_t remaining_bytes; + uint8_t int_on_complete; + }control_dma; + +}dcd_data_t; + +TUSB_CFG_ATTR_USBRAM STATIC_ dcd_data_t dcd_data; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +static void bus_reset(void); +static tusb_error_t pipe_control_read(void * buffer, uint16_t length); +static tusb_error_t pipe_control_write(void const * buffer, uint16_t length); +static tusb_error_t pipe_control_xfer(uint8_t ep_id, uint8_t* p_buffer, uint16_t length); + +//--------------------------------------------------------------------+ +// PIPE HELPER +//--------------------------------------------------------------------+ +static inline uint8_t edpt_addr2phy(uint8_t endpoint_addr) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint8_t edpt_addr2phy(uint8_t endpoint_addr) +{ + return 2*(endpoint_addr & 0x0F) + ((endpoint_addr & TUSB_DIR_DEV_TO_HOST_MASK) ? 1 : 0); +} + +static inline void edpt_set_max_packet_size(uint8_t ep_id, uint16_t max_packet_size) ATTR_ALWAYS_INLINE; +static inline void edpt_set_max_packet_size(uint8_t ep_id, uint16_t max_packet_size) +{ // follows example in 11.10.4.2 + LPC_USB->USBReEp |= BIT_(ep_id); + LPC_USB->USBEpInd = ep_id; // select index before setting packet size + LPC_USB->USBMaxPSize = max_packet_size; + +#ifndef _TEST_ + while ((LPC_USB->USBDevIntSt & DEV_INT_ENDPOINT_REALIZED_MASK) == 0) {} // TODO can be omitted + LPC_USB->USBDevIntClr = DEV_INT_ENDPOINT_REALIZED_MASK; +#endif + +} + +//--------------------------------------------------------------------+ +// USBD-DCD API +//--------------------------------------------------------------------+ +static void bus_reset(void) +{ + // step 7 : slave mode set up + LPC_USB->USBEpIntClr = 0xFFFFFFFF; // clear all pending interrupt + LPC_USB->USBDevIntClr = 0xFFFFFFFF; // clear all pending interrupt + LPC_USB->USBEpIntEn = (uint32_t) BIN8(11); // control endpoint cannot use DMA, non-control all use DMA + LPC_USB->USBEpIntPri = 0; // same priority for all endpoint + + // step 8 : DMA set up + LPC_USB->USBEpDMADis = 0xFFFFFFFF; // firstly disable all dma + LPC_USB->USBDMARClr = 0xFFFFFFFF; // clear all pending interrupt + LPC_USB->USBEoTIntClr = 0xFFFFFFFF; + LPC_USB->USBNDDRIntClr = 0xFFFFFFFF; + LPC_USB->USBSysErrIntClr = 0xFFFFFFFF; + + memclr_(&dcd_data, sizeof(dcd_data_t)); +} + +tusb_error_t dcd_init(void) +{ + //------------- user manual 11.13 usb device controller initialization -------------// LPC_USB->USBEpInd = 0; + // step 6 : set up control endpoint + edpt_set_max_packet_size(0, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE); + edpt_set_max_packet_size(1, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE); + + bus_reset(); + + LPC_USB->USBDevIntEn = (DEV_INT_DEVICE_STATUS_MASK | DEV_INT_ENDPOINT_SLOW_MASK | DEV_INT_ERROR_MASK); + LPC_USB->USBUDCAH = (uint32_t) dcd_data.udca; + LPC_USB->USBDMAIntEn = (DMA_INT_END_OF_XFER_MASK | DMA_INT_ERROR_MASK ); + + sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); // connect + + return TUSB_ERROR_NONE; +} + +static void endpoint_non_control_isr(uint32_t eot_int) +{ + for(uint8_t ep_id = 2; ep_id < DCD_QHD_MAX; ep_id++ ) + { + if ( BIT_TEST_(eot_int, ep_id) ) + { + dcd_dma_descriptor_t* const p_first_dd = &dcd_data.dd[ep_id][0]; + dcd_dma_descriptor_t* const p_last_dd = dcd_data.dd[ep_id] + (p_first_dd->is_next_valid ? 1 : 0); // Maximum is 2 QTD are queued in an endpoint + + // only handle when Controller already finished the last DD + if ( dcd_data.udca[ep_id] == p_last_dd ) + { + dcd_data.udca[ep_id] = p_first_dd; // UDCA currently points to the last DD, change to the fixed DD + p_first_dd->buffer_length = 0; // buffer length is used to determined if first dd is queued in pipe xfer function + + if ( p_last_dd->int_on_complete ) + { + endpoint_handle_t edpt_hdl = + { + .coreid = 0, + .index = ep_id, + .class_code = dcd_data.class_code[ep_id] + }; + tusb_event_t event = (p_last_dd->status == DD_STATUS_NORMAL || p_last_dd->status == DD_STATUS_DATA_UNDERUN) ? TUSB_EVENT_XFER_COMPLETE : TUSB_EVENT_XFER_ERROR; + + usbd_xfer_isr(edpt_hdl, event, p_last_dd->present_count); // report only xferred bytes in the IOC qtd + } + } + } + } +} + +static void endpoint_control_isr(void) +{ + uint32_t const endpoint_int_status = LPC_USB->USBEpIntSt & LPC_USB->USBEpIntEn; +// LPC_USB->USBEpIntClr = endpoint_int_status; // acknowledge interrupt TODO cannot immediately acknowledge setup packet + + //------------- Setup Recieved-------------// + if ( (endpoint_int_status & BIT_(0)) && + (sie_read(SIE_CMDCODE_ENDPOINT_SELECT+0, 1) & SIE_SELECT_ENDPOINT_SETUP_RECEIVED_MASK) ) + { + (void) sie_read(SIE_CMDCODE_ENDPOINT_SELECT_CLEAR_INTERRUPT+0, 1); // clear setup bit + + tusb_control_request_t control_request; + pipe_control_read(&control_request, 8); // TODO read before clear setup above + usbd_setup_received_isr(0, &control_request); + } + else if (endpoint_int_status & 0x03) + { + uint8_t const ep_id = ( endpoint_int_status & BIT_(0) ) ? 0 : 1; + + if ( dcd_data.control_dma.remaining_bytes > 0 ) + { // there are still data to transfer + pipe_control_xfer(ep_id, dcd_data.control_dma.p_data, dcd_data.control_dma.remaining_bytes); + } + else + { + dcd_data.control_dma.remaining_bytes = 0; + + if ( BIT_TEST_(dcd_data.control_dma.int_on_complete, ep_id) ) + { + endpoint_handle_t edpt_hdl = { .coreid = 0, .class_code = 0 }; + dcd_data.control_dma.int_on_complete = 0; + + // FIXME xferred_byte for control xfer is not needed now !!! + usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, 0); + } + } + } + + LPC_USB->USBEpIntClr = endpoint_int_status; // acknowledge interrupt TODO cannot immediately acknowledge setup packet +} + +void dcd_isr(uint8_t coreid) +{ + (void) coreid; + uint32_t const device_int_status = LPC_USB->USBDevIntSt & LPC_USB->USBDevIntEn; + LPC_USB->USBDevIntClr = device_int_status;// Acknowledge handled interrupt + + //------------- usb bus event -------------// + if (device_int_status & DEV_INT_DEVICE_STATUS_MASK) + { + uint8_t const dev_status_reg = sie_read(SIE_CMDCODE_DEVICE_STATUS, 1); + if (dev_status_reg & SIE_DEV_STATUS_RESET_MASK) + { + bus_reset(); + usbd_dcd_bus_event_isr(0, USBD_BUS_EVENT_RESET); + } + + if (dev_status_reg & SIE_DEV_STATUS_CONNECT_CHANGE_MASK) + { // device is disconnected, require using VBUS (P1_30) + usbd_dcd_bus_event_isr(0, USBD_BUS_EVENT_UNPLUGGED); + } + + if (dev_status_reg & SIE_DEV_STATUS_SUSPEND_CHANGE_MASK) + { + if (dev_status_reg & SIE_DEV_STATUS_SUSPEND_MASK) + { + usbd_dcd_bus_event_isr(0, USBD_BUS_EVENT_SUSPENDED); + } +// else +// { +// usbd_dcd_bus_event_isr(0, USBD_BUS_EVENT_RESUME); +// } + } + } + + //------------- Control Endpoint (Slave Mode) -------------// + if (device_int_status & DEV_INT_ENDPOINT_SLOW_MASK) + { + endpoint_control_isr(); + } + + //------------- Non-Control Endpoint (DMA Mode) -------------// + uint32_t dma_int_status = LPC_USB->USBDMAIntSt & LPC_USB->USBDMAIntEn; + + if (dma_int_status & DMA_INT_END_OF_XFER_MASK) + { + uint32_t eot_int = LPC_USB->USBEoTIntSt; + LPC_USB->USBEoTIntClr = eot_int; // acknowledge interrupt source + + endpoint_non_control_isr(eot_int); + } + + if (device_int_status & DEV_INT_ERROR_MASK || dma_int_status & DMA_INT_ERROR_MASK) + { + uint32_t error_status = sie_read(SIE_CMDCODE_READ_ERROR_STATUS, 1); + (void) error_status; +// ASSERT(false, (void) 0); + } +} + +//--------------------------------------------------------------------+ +// USBD API - CONTROLLER +//--------------------------------------------------------------------+ +void dcd_controller_connect(uint8_t coreid) +{ + (void) coreid; + sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); +} + +void dcd_controller_set_address(uint8_t coreid, uint8_t dev_addr) +{ + (void) coreid; + sie_write(SIE_CMDCODE_SET_ADDRESS, 1, 0x80 | dev_addr); // 7th bit is : device_enable +} + +void dcd_controller_set_configuration(uint8_t coreid) +{ + (void) coreid; + sie_write(SIE_CMDCODE_CONFIGURE_DEVICE, 1, 1); +} + +//--------------------------------------------------------------------+ +// PIPE CONTROL HELPER +//--------------------------------------------------------------------+ +static inline uint16_t length_byte2dword(uint16_t length_in_bytes) ATTR_ALWAYS_INLINE ATTR_CONST; +static inline uint16_t length_byte2dword(uint16_t length_in_bytes) +{ + return (length_in_bytes + 3) / 4; // length_in_dword +} + +static tusb_error_t pipe_control_xfer(uint8_t ep_id, uint8_t* p_buffer, uint16_t length) +{ + uint16_t const packet_len = min16_of(length, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE); + + if (ep_id) + { + ASSERT_STATUS ( pipe_control_write(p_buffer, packet_len) ); + }else + { + ASSERT_STATUS ( pipe_control_read(p_buffer, packet_len) ); + } + + dcd_data.control_dma.remaining_bytes -= packet_len; + dcd_data.control_dma.p_data += packet_len; + + return TUSB_ERROR_NONE; +} + +static tusb_error_t pipe_control_write(void const * buffer, uint16_t length) +{ + uint32_t const * p_write_data = (uint32_t const *) buffer; + + LPC_USB->USBCtrl = USBCTRL_WRITE_ENABLE_MASK; // logical endpoint = 0 + LPC_USB->USBTxPLen = length; + + for (uint16_t count = 0; count < length_byte2dword(length); count++) + { + LPC_USB->USBTxData = *p_write_data; // NOTE: cortex M3 have no problem with alignment + p_write_data++; + } + + LPC_USB->USBCtrl = 0; + + // select control IN & validate the endpoint + sie_write(SIE_CMDCODE_ENDPOINT_SELECT+1, 0, 0); + sie_write(SIE_CMDCODE_BUFFER_VALIDATE , 0, 0); + + return TUSB_ERROR_NONE; +} + +static tusb_error_t pipe_control_read(void * buffer, uint16_t length) +{ + LPC_USB->USBCtrl = USBCTRL_READ_ENABLE_MASK; // logical endpoint = 0 + while ((LPC_USB->USBRxPLen & USBRXPLEN_PACKET_READY_MASK) == 0) {} // TODO blocking, should have timeout + + uint16_t actual_length = min16_of(length, (uint16_t) (LPC_USB->USBRxPLen & USBRXPLEN_PACKET_LENGTH_MASK) ); + uint32_t *p_read_data = (uint32_t*) buffer; + for( uint16_t count=0; count < length_byte2dword(actual_length); count++) + { + *p_read_data = LPC_USB->USBRxData; + p_read_data++; // increase by 4 ( sizeof(uint32_t) ) + } + + LPC_USB->USBCtrl = 0; + + // select control OUT & clear the endpoint + sie_write(SIE_CMDCODE_ENDPOINT_SELECT+0, 0, 0); + sie_write(SIE_CMDCODE_BUFFER_CLEAR , 0, 0); + + return TUSB_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// CONTROL PIPE API +//--------------------------------------------------------------------+ +void dcd_pipe_control_stall(uint8_t coreid) +{ + sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS+0, 1, SIE_SET_ENDPOINT_STALLED_MASK | SIE_SET_ENDPOINT_CONDITION_STALLED_MASK); +} + +tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, uint8_t * p_buffer, uint16_t length, bool int_on_complete) +{ + (void) coreid; + + ASSERT( !(length != 0 && p_buffer == NULL), TUSB_ERROR_INVALID_PARA); + + // determine Endpoint where Data & Status phase occurred (IN or OUT) + uint8_t const ep_data = (dir == TUSB_DIR_DEV_TO_HOST) ? 1 : 0; + uint8_t const ep_status = 1 - ep_data; + + dcd_data.control_dma.int_on_complete = int_on_complete ? BIT_(ep_status) : 0; + + //------------- Data Phase -------------// + if ( length ) + { + dcd_data.control_dma.p_data = (uint8_t*) p_buffer; + dcd_data.control_dma.remaining_bytes = length; + + // lpc17xx already received the first DATA OUT packet by now + ASSERT_STATUS ( pipe_control_xfer(ep_data, p_buffer, length) ); + } + + //------------- Status Phase (opposite direct to Data) -------------// + if (dir == TUSB_DIR_HOST_TO_DEV) + { // only write for CONTROL OUT, CONTROL IN data will be retrieved in dcd_isr // TODO ???? + ASSERT_STATUS ( pipe_control_write(NULL, 0) ); + } + + return TUSB_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// BULK/INTERRUPT/ISO PIPE API +//--------------------------------------------------------------------+ +endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code) +{ + (void) coreid; + + endpoint_handle_t const null_handle = { 0 }; + + // TODO refractor to universal pipe open validation function + if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) return null_handle; // TODO not support ISO yet + ASSERT (p_endpoint_desc->wMaxPacketSize.size <= 64, null_handle); // TODO ISO can be 1023, but ISO not supported now + + uint8_t ep_id = edpt_addr2phy( p_endpoint_desc->bEndpointAddress ); + + //------------- Realize Endpoint with Max Packet Size -------------// + edpt_set_max_packet_size(ep_id, p_endpoint_desc->wMaxPacketSize.size); + dcd_data.class_code[ep_id] = class_code; + + //------------- first DD prepare -------------// + dcd_dma_descriptor_t* const p_dd = &dcd_data.dd[ep_id][0]; + memclr_(p_dd, sizeof(dcd_dma_descriptor_t)); + + p_dd->is_isochronous = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; + p_dd->max_packet_size = p_endpoint_desc->wMaxPacketSize.size; + p_dd->is_retired = 1; // inactive at first + + dcd_data.udca[ ep_id ] = p_dd; // hook to UDCA + + sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS+ep_id, 1, 0); // clear all endpoint status + + return (endpoint_handle_t) + { + .coreid = 0, + .index = ep_id, + .class_code = class_code + }; +} + +bool dcd_pipe_is_busy(endpoint_handle_t edpt_hdl) +{ + return (dcd_data.udca[edpt_hdl.index] != NULL && !dcd_data.udca[edpt_hdl.index]->is_retired); +} + +tusb_error_t dcd_pipe_stall(endpoint_handle_t edpt_hdl) +{ + sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS+edpt_hdl.index, 1, SIE_SET_ENDPOINT_STALLED_MASK); + return TUSB_ERROR_NONE; +} + +tusb_error_t dcd_pipe_clear_stall(uint8_t coreid, uint8_t edpt_addr) +{ + uint8_t ep_id = edpt_addr2phy(edpt_addr); + + sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS+ep_id, 1, 0); + + return TUSB_ERROR_FAILED; +} + +void dd_xfer_init(dcd_dma_descriptor_t* p_dd, void* buffer, uint16_t total_bytes) +{ + p_dd->next = 0; + p_dd->is_next_valid = 0; + p_dd->buffer_addr = (uint32_t) buffer; + p_dd->buffer_length = total_bytes; + p_dd->status = DD_STATUS_NOT_SERVICED; + p_dd->iso_last_packet_valid = 0; + p_dd->present_count = 0; +} + +tusb_error_t dcd_pipe_queue_xfer(endpoint_handle_t edpt_hdl, uint8_t * buffer, uint16_t total_bytes) +{ // NOTE for sure the qhd has no dds + dcd_dma_descriptor_t* const p_fixed_dd = &dcd_data.dd[edpt_hdl.index][0]; // always queue with the fixed DD + + dd_xfer_init(p_fixed_dd, buffer, total_bytes); + p_fixed_dd->is_retired = 1; + p_fixed_dd->int_on_complete = 0; + + return TUSB_ERROR_NONE; +} + +tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, uint8_t* buffer, uint16_t total_bytes, bool int_on_complete) +{ + dcd_dma_descriptor_t* const p_first_dd = &dcd_data.dd[edpt_hdl.index][0]; + + //------------- fixed DD is already queued a xfer -------------// + if ( p_first_dd->buffer_length ) + { + // setup new dd + dcd_dma_descriptor_t* const p_dd = &dcd_data.dd[ edpt_hdl.index ][1]; + memclr_(p_dd, sizeof(dcd_dma_descriptor_t)); + + dd_xfer_init(p_dd, buffer, total_bytes); + + p_dd->max_packet_size = p_first_dd->max_packet_size; + p_dd->is_isochronous = p_first_dd->is_isochronous; + p_dd->int_on_complete = int_on_complete; + + // hook to fixed dd + p_first_dd->next = (uint32_t) p_dd; + p_first_dd->is_next_valid = 1; + } + //------------- fixed DD is free -------------// + else + { + dd_xfer_init(p_first_dd, buffer, total_bytes); + p_first_dd->int_on_complete = int_on_complete; + } + + p_first_dd->is_retired = 0; // activate xfer + dcd_data.udca[edpt_hdl.index] = p_first_dd; + LPC_USB->USBEpDMAEn = BIT_(edpt_hdl.index); + + if ( edpt_hdl.index % 2 ) + { // endpoint IN need to actively raise DMA request + LPC_USB->USBDMARSet = BIT_(edpt_hdl.index); + } + + return TUSB_ERROR_NONE; +} + +#endif diff --git a/tinyusb/hal/hal_lpc11uxx.c b/tinyusb/hal/hal_lpc11uxx.c index d1ee35e2c..8a8232904 100644 --- a/tinyusb/hal/hal_lpc11uxx.c +++ b/tinyusb/hal/hal_lpc11uxx.c @@ -1,69 +1,69 @@ -/**************************************************************************/ -/*! - @file hal_lpc11uxx.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -#include "common/common.h" -#include "hal.h" - -#if TUSB_CFG_MCU == MCU_LPC11UXX - -tusb_error_t hal_init(void) -{ - // TODO remove magic number - /* Enable AHB clock to the USB block and USB RAM. */ - LPC_SYSCON->SYSAHBCLKCTRL |= ((0x1<<14) | (0x1<<27)); - LPC_SYSCON->PDRUNCFG &= ~( BIT_(8) | BIT_(10) ); // enable USB PLL & USB transceiver - - /* Pull-down is needed, or internally, VBUS will be floating. This is to - address the wrong status in VBUSDebouncing bit in CmdStatus register. */ - // set PIO0_3 as USB_VBUS - LPC_IOCON->PIO0_3 &= ~0x1F; - LPC_IOCON->PIO0_3 |= (0x01<<0) | (1 << 3); /* Secondary function VBUS */ - - // set PIO0_6 as usb connect - LPC_IOCON->PIO0_6 &= ~0x07; - LPC_IOCON->PIO0_6 |= (0x01<<0); /* Secondary function SoftConn */ - - return TUSB_ERROR_NONE; -} - -void USB_IRQHandler(void) -{ - tusb_isr(0); -} - -#endif +/**************************************************************************/ +/*! + @file hal_lpc11uxx.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +#include "common/common.h" +#include "hal.h" + +#if TUSB_CFG_MCU == MCU_LPC11UXX + +tusb_error_t hal_init(void) +{ + // TODO remove magic number + /* Enable AHB clock to the USB block and USB RAM. */ + LPC_SYSCON->SYSAHBCLKCTRL |= ((0x1<<14) | (0x1<<27)); + LPC_SYSCON->PDRUNCFG &= ~( BIT_(8) | BIT_(10) ); // enable USB PLL & USB transceiver + + /* Pull-down is needed, or internally, VBUS will be floating. This is to + address the wrong status in VBUSDebouncing bit in CmdStatus register. */ + // set PIO0_3 as USB_VBUS + LPC_IOCON->PIO0_3 &= ~0x1F; + LPC_IOCON->PIO0_3 |= (0x01<<0) | (1 << 3); /* Secondary function VBUS */ + + // set PIO0_6 as usb connect + LPC_IOCON->PIO0_6 &= ~0x07; + LPC_IOCON->PIO0_6 |= (0x01<<0); /* Secondary function SoftConn */ + + return TUSB_ERROR_NONE; +} + +void USB_IRQHandler(void) +{ + tusb_isr(0); +} + +#endif diff --git a/tinyusb/hal/hal_lpc13uxx.c b/tinyusb/hal/hal_lpc13uxx.c index 706f5004c..9f3361d35 100644 --- a/tinyusb/hal/hal_lpc13uxx.c +++ b/tinyusb/hal/hal_lpc13uxx.c @@ -1,68 +1,68 @@ -/**************************************************************************/ -/*! - @file hal_lpc13uxx.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -#include "common/common.h" -#include "hal.h" - -#if TUSB_CFG_MCU == MCU_LPC13UXX - -tusb_error_t hal_init(void) -{ - // TODO remove magic number - LPC_SYSCON->SYSAHBCLKCTRL |= ((0x1<<14) | (0x1<<27)); /* Enable AHB clock to the USB block and USB RAM. */ - LPC_SYSCON->PDRUNCFG &= ~( BIT_(8) | BIT_(10) ); // enable USB PLL & USB transceiver - - /* Pull-down is needed, or internally, VBUS will be floating. This is to - address the wrong status in VBUSDebouncing bit in CmdStatus register. */ - // set PIO0_3 as USB_VBUS - LPC_IOCON->PIO0_3 &= ~0x1F; - LPC_IOCON->PIO0_3 |= (0x01<<0) | (1 << 3); /* Secondary function VBUS */ - - // set PIO0_6 as usb connect - LPC_IOCON->PIO0_6 &= ~0x07; - LPC_IOCON->PIO0_6 |= (0x01<<0); /* Secondary function SoftConn */ - - return TUSB_ERROR_NONE; -} - -void USB_IRQHandler(void) -{ - tusb_isr(0); -} - -#endif +/**************************************************************************/ +/*! + @file hal_lpc13uxx.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +#include "common/common.h" +#include "hal.h" + +#if TUSB_CFG_MCU == MCU_LPC13UXX + +tusb_error_t hal_init(void) +{ + // TODO remove magic number + LPC_SYSCON->SYSAHBCLKCTRL |= ((0x1<<14) | (0x1<<27)); /* Enable AHB clock to the USB block and USB RAM. */ + LPC_SYSCON->PDRUNCFG &= ~( BIT_(8) | BIT_(10) ); // enable USB PLL & USB transceiver + + /* Pull-down is needed, or internally, VBUS will be floating. This is to + address the wrong status in VBUSDebouncing bit in CmdStatus register. */ + // set PIO0_3 as USB_VBUS + LPC_IOCON->PIO0_3 &= ~0x1F; + LPC_IOCON->PIO0_3 |= (0x01<<0) | (1 << 3); /* Secondary function VBUS */ + + // set PIO0_6 as usb connect + LPC_IOCON->PIO0_6 &= ~0x07; + LPC_IOCON->PIO0_6 |= (0x01<<0); /* Secondary function SoftConn */ + + return TUSB_ERROR_NONE; +} + +void USB_IRQHandler(void) +{ + tusb_isr(0); +} + +#endif diff --git a/tinyusb/hal/hal_lpc175x_6x.c b/tinyusb/hal/hal_lpc175x_6x.c index d36d58376..c3753a8fa 100644 --- a/tinyusb/hal/hal_lpc175x_6x.c +++ b/tinyusb/hal/hal_lpc175x_6x.c @@ -1,99 +1,99 @@ -/**************************************************************************/ -/*! - @file hal_lpc175x_6x.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -#include "tusb_option.h" - -#if TUSB_CFG_MCU == MCU_LPC175X_6X - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "common/common.h" -#include "hal.h" - -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ -tusb_error_t hal_init(void) -{ - enum { - USBCLK_DEVCIE = 0x12, // AHB + Device - USBCLK_HOST = 0x19 // AHB + Host + OTG (!) - }; - - LPC_SC->PCONP |= CLKPWR_PCONP_PCUSB; // enable USB Peripherals - - //------------- user manual 11.13 usb device controller initialization -------------// - PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 0, .Pinnum = 29, .Funcnum = 1} ); // P0.29 as D+ - PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 0, .Pinnum = 30, .Funcnum = 1} ); // P0.30 as D- - -#if MODE_HOST_SUPPORTED - PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 1, .Pinnum = 22, .Funcnum = 2} ); // P1.22 as USB_PWRD - PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 1, .Pinnum = 19, .Funcnum = 2} ); // P1.19 as USB_PPWR - - LPC_USB->USBClkCtrl = USBCLK_HOST; - while ((LPC_USB->USBClkSt & USBCLK_HOST) != USBCLK_HOST); - LPC_USB->OTGStCtrl = 0x3; -#endif - -#if MODE_DEVICE_SUPPORTED - LPC_PINCON->PINSEL4 = bit_set_range(LPC_PINCON->PINSEL4, 18, 19, BIN8(01)); // P2_9 as USB Connect - - // P1_30 as VBUS, ignore if it is already in VBUS mode - if ( !(!BIT_TEST_(LPC_PINCON->PINSEL3, 28) && BIT_TEST_(LPC_PINCON->PINSEL3, 29)) ) - { - // some board like lpcxpresso1769 does not connect VBUS signal to pin P1_30, this allow those board to overwrite - // by always pulling P1_30 to high - PINSEL_ConfigPin( &(PINSEL_CFG_Type) { - .Portnum = 1, .Pinnum = 30, - .Funcnum = 2, .Pinmode = PINSEL_PINMODE_PULLDOWN} ); - } - - LPC_USB->USBClkCtrl = USBCLK_DEVCIE; - while ((LPC_USB->USBClkSt & USBCLK_DEVCIE) != USBCLK_DEVCIE); -#endif - - return TUSB_ERROR_NONE; -} - -void USB_IRQHandler(void) -{ - tusb_isr(0); -} - -#endif +/**************************************************************************/ +/*! + @file hal_lpc175x_6x.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +#include "tusb_option.h" + +#if TUSB_CFG_MCU == MCU_LPC175X_6X + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "common/common.h" +#include "hal.h" + +//--------------------------------------------------------------------+ +// IMPLEMENTATION +//--------------------------------------------------------------------+ +tusb_error_t hal_init(void) +{ + enum { + USBCLK_DEVCIE = 0x12, // AHB + Device + USBCLK_HOST = 0x19 // AHB + Host + OTG (!) + }; + + LPC_SC->PCONP |= CLKPWR_PCONP_PCUSB; // enable USB Peripherals + + //------------- user manual 11.13 usb device controller initialization -------------// + PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 0, .Pinnum = 29, .Funcnum = 1} ); // P0.29 as D+ + PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 0, .Pinnum = 30, .Funcnum = 1} ); // P0.30 as D- + +#if MODE_HOST_SUPPORTED + PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 1, .Pinnum = 22, .Funcnum = 2} ); // P1.22 as USB_PWRD + PINSEL_ConfigPin( &(PINSEL_CFG_Type) { .Portnum = 1, .Pinnum = 19, .Funcnum = 2} ); // P1.19 as USB_PPWR + + LPC_USB->USBClkCtrl = USBCLK_HOST; + while ((LPC_USB->USBClkSt & USBCLK_HOST) != USBCLK_HOST); + LPC_USB->OTGStCtrl = 0x3; +#endif + +#if MODE_DEVICE_SUPPORTED + LPC_PINCON->PINSEL4 = bit_set_range(LPC_PINCON->PINSEL4, 18, 19, BIN8(01)); // P2_9 as USB Connect + + // P1_30 as VBUS, ignore if it is already in VBUS mode + if ( !(!BIT_TEST_(LPC_PINCON->PINSEL3, 28) && BIT_TEST_(LPC_PINCON->PINSEL3, 29)) ) + { + // some board like lpcxpresso1769 does not connect VBUS signal to pin P1_30, this allow those board to overwrite + // by always pulling P1_30 to high + PINSEL_ConfigPin( &(PINSEL_CFG_Type) { + .Portnum = 1, .Pinnum = 30, + .Funcnum = 2, .Pinmode = PINSEL_PINMODE_PULLDOWN} ); + } + + LPC_USB->USBClkCtrl = USBCLK_DEVCIE; + while ((LPC_USB->USBClkSt & USBCLK_DEVCIE) != USBCLK_DEVCIE); +#endif + + return TUSB_ERROR_NONE; +} + +void USB_IRQHandler(void) +{ + tusb_isr(0); +} + +#endif diff --git a/tinyusb/host/hcd.c b/tinyusb/host/hcd.c index b9e2b1a0a..092ca96da 100644 --- a/tinyusb/host/hcd.c +++ b/tinyusb/host/hcd.c @@ -1,44 +1,44 @@ -/**************************************************************************/ -/*! - @file hcd.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -#include "hcd.h" - -#if MODE_HOST_SUPPORTED - - -#endif +/**************************************************************************/ +/*! + @file hcd.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +#include "hcd.h" + +#if MODE_HOST_SUPPORTED + + +#endif diff --git a/tinyusb/host/hcd.h b/tinyusb/host/hcd.h index 952dc5fe2..c148ccb88 100644 --- a/tinyusb/host/hcd.h +++ b/tinyusb/host/hcd.h @@ -1,122 +1,122 @@ -/**************************************************************************/ -/*! - @file hcd.h - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -/** \addtogroup Port Port - * @{ - * \defgroup Port_HCD Host Controller Driver (HCD) - * @{ - */ - -#ifndef _TUSB_HCD_H_ -#define _TUSB_HCD_H_ - -#include "common/common.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct { - uint8_t dev_addr; - uint8_t xfer_type; - uint8_t index; - uint8_t reserved; -} pipe_handle_t; - -static inline bool pipehandle_is_valid(pipe_handle_t pipe_hdl) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; -static inline bool pipehandle_is_valid(pipe_handle_t pipe_hdl) -{ - return pipe_hdl.dev_addr > 0; -} - -static inline bool pipehandle_is_equal(pipe_handle_t x, pipe_handle_t y) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; -static inline bool pipehandle_is_equal(pipe_handle_t x, pipe_handle_t y) -{ - return (x.dev_addr == y.dev_addr) && (x.xfer_type == y.xfer_type) && (x.index == y.index); -} - -//--------------------------------------------------------------------+ -// USBH-HCD API -//--------------------------------------------------------------------+ -tusb_error_t hcd_init(void) ATTR_WARN_UNUSED_RESULT; -void hcd_isr(uint8_t hostid); - -//--------------------------------------------------------------------+ -// PIPE API -//--------------------------------------------------------------------+ -// TODO control xfer should be used via usbh layer -tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) ATTR_WARN_UNUSED_RESULT; -tusb_error_t hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[]) ATTR_WARN_UNUSED_RESULT; -tusb_error_t hcd_pipe_control_close(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT; - -pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const * endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT; -tusb_error_t hcd_pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes) ATTR_WARN_UNUSED_RESULT; // only queue, not transferring yet -tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) ATTR_WARN_UNUSED_RESULT; -tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl) /*ATTR_WARN_UNUSED_RESULT*/; - -bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl) ATTR_PURE; -bool hcd_pipe_is_error(pipe_handle_t pipe_hdl) ATTR_PURE; -bool hcd_pipe_is_stalled(pipe_handle_t pipe_hdl) ATTR_PURE; // stalled also counted as error - -uint8_t hcd_pipe_get_endpoint_addr(pipe_handle_t pipe_hdl) ATTR_PURE; -tusb_error_t hcd_pipe_clear_stall(pipe_handle_t pipe_hdl); - -#if 0 -tusb_error_t hcd_pipe_cancel()ATTR_WARN_UNUSED_RESULT; -#endif - -//--------------------------------------------------------------------+ -// PORT API -//--------------------------------------------------------------------+ -/// return the current connect status of roothub port -bool hcd_port_connect_status(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible -void hcd_port_reset(uint8_t hostid); -tusb_speed_t hcd_port_speed_get(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible -void hcd_port_unplug(uint8_t hostid); // called by usbh to instruct hcd that it can execute unplug procedure - -#ifdef __cplusplus - } -#endif - - #endif /* _TUSB_HCD_H_ */ - -/// @} -/// @} +/**************************************************************************/ +/*! + @file hcd.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \addtogroup Port Port + * @{ + * \defgroup Port_HCD Host Controller Driver (HCD) + * @{ + */ + +#ifndef _TUSB_HCD_H_ +#define _TUSB_HCD_H_ + +#include "common/common.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct { + uint8_t dev_addr; + uint8_t xfer_type; + uint8_t index; + uint8_t reserved; +} pipe_handle_t; + +static inline bool pipehandle_is_valid(pipe_handle_t pipe_hdl) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; +static inline bool pipehandle_is_valid(pipe_handle_t pipe_hdl) +{ + return pipe_hdl.dev_addr > 0; +} + +static inline bool pipehandle_is_equal(pipe_handle_t x, pipe_handle_t y) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; +static inline bool pipehandle_is_equal(pipe_handle_t x, pipe_handle_t y) +{ + return (x.dev_addr == y.dev_addr) && (x.xfer_type == y.xfer_type) && (x.index == y.index); +} + +//--------------------------------------------------------------------+ +// USBH-HCD API +//--------------------------------------------------------------------+ +tusb_error_t hcd_init(void) ATTR_WARN_UNUSED_RESULT; +void hcd_isr(uint8_t hostid); + +//--------------------------------------------------------------------+ +// PIPE API +//--------------------------------------------------------------------+ +// TODO control xfer should be used via usbh layer +tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) ATTR_WARN_UNUSED_RESULT; +tusb_error_t hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[]) ATTR_WARN_UNUSED_RESULT; +tusb_error_t hcd_pipe_control_close(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT; + +pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const * endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT; +tusb_error_t hcd_pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes) ATTR_WARN_UNUSED_RESULT; // only queue, not transferring yet +tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) ATTR_WARN_UNUSED_RESULT; +tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl) /*ATTR_WARN_UNUSED_RESULT*/; + +bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl) ATTR_PURE; +bool hcd_pipe_is_error(pipe_handle_t pipe_hdl) ATTR_PURE; +bool hcd_pipe_is_stalled(pipe_handle_t pipe_hdl) ATTR_PURE; // stalled also counted as error + +uint8_t hcd_pipe_get_endpoint_addr(pipe_handle_t pipe_hdl) ATTR_PURE; +tusb_error_t hcd_pipe_clear_stall(pipe_handle_t pipe_hdl); + +#if 0 +tusb_error_t hcd_pipe_cancel()ATTR_WARN_UNUSED_RESULT; +#endif + +//--------------------------------------------------------------------+ +// PORT API +//--------------------------------------------------------------------+ +/// return the current connect status of roothub port +bool hcd_port_connect_status(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible +void hcd_port_reset(uint8_t hostid); +tusb_speed_t hcd_port_speed_get(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible +void hcd_port_unplug(uint8_t hostid); // called by usbh to instruct hcd that it can execute unplug procedure + +#ifdef __cplusplus + } +#endif + + #endif /* _TUSB_HCD_H_ */ + +/// @} +/// @} diff --git a/tinyusb/host/hub.c b/tinyusb/host/hub.c index e87ce62f0..823b3930b 100644 --- a/tinyusb/host/hub.c +++ b/tinyusb/host/hub.c @@ -1,233 +1,233 @@ -/**************************************************************************/ -/*! - @file hub.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -#include "tusb_option.h" - -#if (MODE_HOST_SUPPORTED && TUSB_CFG_HOST_HUB) - -#define _TINY_USB_SOURCE_FILE_ - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "hub.h" -#include "usbh_hub.h" - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -typedef struct { - pipe_handle_t pipe_status; - uint8_t interface_number; - uint8_t port_number; - uint8_t status_change; // data from status change interrupt endpoint -}usbh_hub_t; - -TUSB_CFG_ATTR_USBRAM usbh_hub_t hub_data[TUSB_CFG_HOST_DEVICE_MAX]; -TUSB_CFG_ATTR_USBRAM uint8_t hub_enum_buffer[sizeof(descriptor_hub_desc_t)]; - -//OSAL_SEM_DEF(hub_enum_semaphore); -//static osal_semaphore_handle_t hub_enum_sem_hdl; - -//--------------------------------------------------------------------+ -// HUB -//--------------------------------------------------------------------+ -tusb_error_t hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t feature) -{ - tusb_error_t error; - - OSAL_SUBTASK_BEGIN - - SUBTASK_ASSERT(HUB_FEATURE_PORT_CONNECTION_CHANGE <= feature && - feature <= HUB_FEATURE_PORT_RESET_CHANGE); - - //------------- Clear Port Feature request -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), - HUB_REQUEST_CLEAR_FEATURE, feature, hub_port, - 0, NULL ), - error - ); - SUBTASK_ASSERT_STATUS( error ); - - //------------- Get Port Status to check if feature is cleared -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), - HUB_REQUEST_GET_STATUS, 0, hub_port, - 4, hub_enum_buffer ), - error - ); - SUBTASK_ASSERT_STATUS( error ); - - //------------- Check if feature is cleared -------------// - hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer; - SUBTASK_ASSERT( !BIT_TEST_(p_port_status->status_change.value, feature-16) ); - - OSAL_SUBTASK_END -} - -tusb_error_t hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port) -{ - tusb_error_t error; - - OSAL_SUBTASK_BEGIN - - //------------- Set Port Reset -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), - HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_RESET, hub_port, - 0, NULL ), - error - ); - SUBTASK_ASSERT_STATUS( error ); - - osal_task_delay(50); // TODO Hub wait for Status Endpoint on Reset Change - - //------------- Get Port Status to check if port is enabled, powered and reset_change -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), - HUB_REQUEST_GET_STATUS, 0, hub_port, - 4, hub_enum_buffer ), - error - ); - SUBTASK_ASSERT_STATUS( error ); - - hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer; - SUBTASK_ASSERT ( p_port_status->status_change.reset && p_port_status->status_current.connect_status && - p_port_status->status_current.port_power && p_port_status->status_current.port_enable); - - OSAL_SUBTASK_END -} - -// can only get the speed RIGHT AFTER hub_port_reset_subtask call -tusb_speed_t hub_port_get_speed(void) -{ - hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer; - return (p_port_status->status_current.high_speed_device_attached) ? TUSB_SPEED_HIGH : - (p_port_status->status_current.low_speed_device_attached ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; -} - -//--------------------------------------------------------------------+ -// CLASS-USBH API (don't require to verify parameters) -//--------------------------------------------------------------------+ -void hub_init(void) -{ - memclr_(hub_data, TUSB_CFG_HOST_DEVICE_MAX*sizeof(usbh_hub_t)); -// hub_enum_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(hub_enum_semaphore) ); -} - -tusb_error_t hub_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) -{ - tusb_error_t error; - - OSAL_SUBTASK_BEGIN - - // not support multiple TT yet - if ( p_interface_desc->bInterfaceProtocol > 1 ) return TUSB_ERROR_HUB_FEATURE_NOT_SUPPORTED; - - //------------- Open Interrupt Status Pipe -------------// - tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc ); - SUBTASK_ASSERT(TUSB_DESC_TYPE_ENDPOINT == p_endpoint->bDescriptorType); - SUBTASK_ASSERT(TUSB_XFER_INTERRUPT == p_endpoint->bmAttributes.xfer); - - hub_data[dev_addr-1].pipe_status = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_HUB); - SUBTASK_ASSERT( pipehandle_is_valid(hub_data[dev_addr-1].pipe_status) ); - hub_data[dev_addr-1].interface_number = p_interface_desc->bInterfaceNumber; - - (*p_length) = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_descriptor_endpoint_t); - - //------------- Get Hub Descriptor -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_DEVICE), - HUB_REQUEST_GET_DESCRIPTOR, 0, 0, - sizeof(descriptor_hub_desc_t), hub_enum_buffer ), - error - ); - SUBTASK_ASSERT_STATUS(error); - - // only care about this field in hub descriptor - hub_data[dev_addr-1].port_number = ((descriptor_hub_desc_t*) hub_enum_buffer)->bNbrPorts; - - //------------- Set Port_Power on all ports -------------// - static uint8_t i; - for(i=1; i <= hub_data[dev_addr-1].port_number; i++) - { - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), - HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_POWER, i, - 0, NULL ), - error - ); - } - - //------------- Queue the initial Status endpoint transfer -------------// - SUBTASK_ASSERT_STATUS ( hcd_pipe_xfer(hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true) ); - - OSAL_SUBTASK_END -} - -void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) -{ - usbh_hub_t * p_hub = &hub_data[pipe_hdl.dev_addr-1]; - - for (uint8_t port=1; port <= p_hub->port_number; port++) - { // TODO HUB ignore bit0 hub_status_change - if ( BIT_TEST_(p_hub->status_change, port) ) - { - usbh_hub_port_plugged_isr(pipe_hdl.dev_addr, port); - } - } - - // NOTE: next status transfer is queued by usbh.c after handling this request -} - -void hub_close(uint8_t dev_addr) -{ - (void) hcd_pipe_close(hub_data[dev_addr-1].pipe_status); - memclr_(&hub_data[dev_addr-1], sizeof(usbh_hub_t)); - -// osal_semaphore_reset(hub_enum_sem_hdl); -} - -tusb_error_t hub_status_pipe_queue(uint8_t dev_addr) -{ - return hcd_pipe_xfer(hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true); -} - - -#endif +/**************************************************************************/ +/*! + @file hub.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +#include "tusb_option.h" + +#if (MODE_HOST_SUPPORTED && TUSB_CFG_HOST_HUB) + +#define _TINY_USB_SOURCE_FILE_ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "hub.h" +#include "usbh_hub.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +typedef struct { + pipe_handle_t pipe_status; + uint8_t interface_number; + uint8_t port_number; + uint8_t status_change; // data from status change interrupt endpoint +}usbh_hub_t; + +TUSB_CFG_ATTR_USBRAM usbh_hub_t hub_data[TUSB_CFG_HOST_DEVICE_MAX]; +TUSB_CFG_ATTR_USBRAM uint8_t hub_enum_buffer[sizeof(descriptor_hub_desc_t)]; + +//OSAL_SEM_DEF(hub_enum_semaphore); +//static osal_semaphore_handle_t hub_enum_sem_hdl; + +//--------------------------------------------------------------------+ +// HUB +//--------------------------------------------------------------------+ +tusb_error_t hub_port_clear_feature_subtask(uint8_t hub_addr, uint8_t hub_port, uint8_t feature) +{ + tusb_error_t error; + + OSAL_SUBTASK_BEGIN + + SUBTASK_ASSERT(HUB_FEATURE_PORT_CONNECTION_CHANGE <= feature && + feature <= HUB_FEATURE_PORT_RESET_CHANGE); + + //------------- Clear Port Feature request -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), + HUB_REQUEST_CLEAR_FEATURE, feature, hub_port, + 0, NULL ), + error + ); + SUBTASK_ASSERT_STATUS( error ); + + //------------- Get Port Status to check if feature is cleared -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), + HUB_REQUEST_GET_STATUS, 0, hub_port, + 4, hub_enum_buffer ), + error + ); + SUBTASK_ASSERT_STATUS( error ); + + //------------- Check if feature is cleared -------------// + hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer; + SUBTASK_ASSERT( !BIT_TEST_(p_port_status->status_change.value, feature-16) ); + + OSAL_SUBTASK_END +} + +tusb_error_t hub_port_reset_subtask(uint8_t hub_addr, uint8_t hub_port) +{ + tusb_error_t error; + + OSAL_SUBTASK_BEGIN + + //------------- Set Port Reset -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), + HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_RESET, hub_port, + 0, NULL ), + error + ); + SUBTASK_ASSERT_STATUS( error ); + + osal_task_delay(50); // TODO Hub wait for Status Endpoint on Reset Change + + //------------- Get Port Status to check if port is enabled, powered and reset_change -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), + HUB_REQUEST_GET_STATUS, 0, hub_port, + 4, hub_enum_buffer ), + error + ); + SUBTASK_ASSERT_STATUS( error ); + + hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer; + SUBTASK_ASSERT ( p_port_status->status_change.reset && p_port_status->status_current.connect_status && + p_port_status->status_current.port_power && p_port_status->status_current.port_enable); + + OSAL_SUBTASK_END +} + +// can only get the speed RIGHT AFTER hub_port_reset_subtask call +tusb_speed_t hub_port_get_speed(void) +{ + hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer; + return (p_port_status->status_current.high_speed_device_attached) ? TUSB_SPEED_HIGH : + (p_port_status->status_current.low_speed_device_attached ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; +} + +//--------------------------------------------------------------------+ +// CLASS-USBH API (don't require to verify parameters) +//--------------------------------------------------------------------+ +void hub_init(void) +{ + memclr_(hub_data, TUSB_CFG_HOST_DEVICE_MAX*sizeof(usbh_hub_t)); +// hub_enum_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(hub_enum_semaphore) ); +} + +tusb_error_t hub_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) +{ + tusb_error_t error; + + OSAL_SUBTASK_BEGIN + + // not support multiple TT yet + if ( p_interface_desc->bInterfaceProtocol > 1 ) return TUSB_ERROR_HUB_FEATURE_NOT_SUPPORTED; + + //------------- Open Interrupt Status Pipe -------------// + tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc ); + SUBTASK_ASSERT(TUSB_DESC_TYPE_ENDPOINT == p_endpoint->bDescriptorType); + SUBTASK_ASSERT(TUSB_XFER_INTERRUPT == p_endpoint->bmAttributes.xfer); + + hub_data[dev_addr-1].pipe_status = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_HUB); + SUBTASK_ASSERT( pipehandle_is_valid(hub_data[dev_addr-1].pipe_status) ); + hub_data[dev_addr-1].interface_number = p_interface_desc->bInterfaceNumber; + + (*p_length) = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_descriptor_endpoint_t); + + //------------- Get Hub Descriptor -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_DEVICE), + HUB_REQUEST_GET_DESCRIPTOR, 0, 0, + sizeof(descriptor_hub_desc_t), hub_enum_buffer ), + error + ); + SUBTASK_ASSERT_STATUS(error); + + // only care about this field in hub descriptor + hub_data[dev_addr-1].port_number = ((descriptor_hub_desc_t*) hub_enum_buffer)->bNbrPorts; + + //------------- Set Port_Power on all ports -------------// + static uint8_t i; + for(i=1; i <= hub_data[dev_addr-1].port_number; i++) + { + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), + HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_POWER, i, + 0, NULL ), + error + ); + } + + //------------- Queue the initial Status endpoint transfer -------------// + SUBTASK_ASSERT_STATUS ( hcd_pipe_xfer(hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true) ); + + OSAL_SUBTASK_END +} + +void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes) +{ + usbh_hub_t * p_hub = &hub_data[pipe_hdl.dev_addr-1]; + + for (uint8_t port=1; port <= p_hub->port_number; port++) + { // TODO HUB ignore bit0 hub_status_change + if ( BIT_TEST_(p_hub->status_change, port) ) + { + usbh_hub_port_plugged_isr(pipe_hdl.dev_addr, port); + } + } + + // NOTE: next status transfer is queued by usbh.c after handling this request +} + +void hub_close(uint8_t dev_addr) +{ + (void) hcd_pipe_close(hub_data[dev_addr-1].pipe_status); + memclr_(&hub_data[dev_addr-1], sizeof(usbh_hub_t)); + +// osal_semaphore_reset(hub_enum_sem_hdl); +} + +tusb_error_t hub_status_pipe_queue(uint8_t dev_addr) +{ + return hcd_pipe_xfer(hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true); +} + + +#endif diff --git a/tinyusb/osal/osal_common.h b/tinyusb/osal/osal_common.h index 6135e3ce8..6347abaea 100644 --- a/tinyusb/osal/osal_common.h +++ b/tinyusb/osal/osal_common.h @@ -1,75 +1,75 @@ -/**************************************************************************/ -/*! - @file osal_common.h - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -/** \ingroup TBD - * \defgroup TBD - * \brief TBD - * - * @{ - */ - -#ifndef _TUSB_OSAL_COMMON_H_ -#define _TUSB_OSAL_COMMON_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#include "common/common.h" - -enum -{ - OSAL_TIMEOUT_NOTIMEOUT = 0, // for use within ISR, return immediately - OSAL_TIMEOUT_NORMAL = 10*5, // default is 10 msec, FIXME CMSIS-RTX easily timeout with 10 msec - OSAL_TIMEOUT_WAIT_FOREVER = 0x0EEEEEEE -}; - -// TODO refractor/remove this function and/or TUSB_CFG_OS_TICKS_PER_SECOND if using an RTOS -static inline uint32_t osal_tick_from_msec(uint32_t msec) ATTR_CONST ATTR_ALWAYS_INLINE; -static inline uint32_t osal_tick_from_msec(uint32_t msec) -{ - return (msec * TUSB_CFG_OS_TICKS_PER_SECOND)/1000; -} - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_OSAL_COMMON_H_ */ - -/** @} */ +/**************************************************************************/ +/*! + @file osal_common.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders 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 ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +/** \ingroup TBD + * \defgroup TBD + * \brief TBD + * + * @{ + */ + +#ifndef _TUSB_OSAL_COMMON_H_ +#define _TUSB_OSAL_COMMON_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "common/common.h" + +enum +{ + OSAL_TIMEOUT_NOTIMEOUT = 0, // for use within ISR, return immediately + OSAL_TIMEOUT_NORMAL = 10*5, // default is 10 msec, FIXME CMSIS-RTX easily timeout with 10 msec + OSAL_TIMEOUT_WAIT_FOREVER = 0x0EEEEEEE +}; + +// TODO refractor/remove this function and/or TUSB_CFG_OS_TICKS_PER_SECOND if using an RTOS +static inline uint32_t osal_tick_from_msec(uint32_t msec) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint32_t osal_tick_from_msec(uint32_t msec) +{ + return (msec * TUSB_CFG_OS_TICKS_PER_SECOND)/1000; +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_OSAL_COMMON_H_ */ + +/** @} */