From 357813f1714168746cf20b91ea6e11502003e5c5 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Oct 2013 11:27:25 +0700 Subject: [PATCH] implementing sw device stack --- demos/device/keyboard/main.c | 9 - demos/device/keyboard/tusb_config.h | 2 +- demos/host/host_os_none/.cproject | 8 +- tinyusb/class/hid_device.c | 14 +- tinyusb/common/errors.h | 1 + tinyusb/device/dcd.h | 42 +++- tinyusb/device/dcd_lpc175x_6x.c | 4 +- tinyusb/device/dcd_lpc43xx.c | 366 ++++++++++++++++++++++++++++ tinyusb/device/dcd_lpc43xx.h | 60 +++++ tinyusb/device/usbd.c | 127 +++++----- tinyusb/device/usbd_dcd.h | 1 - tinyusb/hal/hal_lpc43xx.c | 6 +- tinyusb/host/ehci/ehci.c | 3 +- tinyusb/tusb_option.h | 7 +- 14 files changed, 540 insertions(+), 110 deletions(-) create mode 100644 tinyusb/device/dcd_lpc43xx.c create mode 100644 tinyusb/device/dcd_lpc43xx.h diff --git a/demos/device/keyboard/main.c b/demos/device/keyboard/main.c index 6fa31e294..f15b80255 100644 --- a/demos/device/keyboard/main.c +++ b/demos/device/keyboard/main.c @@ -5,15 +5,6 @@ #include "boards/board.h" #include "tusb.h" -#if defined(__CODE_RED) - #include - #include - // Variable to store CRP value in. Will be placed automatically - // by the linker when "Enable Code Read Protect" selected. - // See crp.h header for more information - __CRP const unsigned int CRP_WORD = CRP_NO_CRP ; -#endif - void print_greeting(void); void led_blinking_task(void * p_para); diff --git a/demos/device/keyboard/tusb_config.h b/demos/device/keyboard/tusb_config.h index 64f95585f..7569680d8 100644 --- a/demos/device/keyboard/tusb_config.h +++ b/demos/device/keyboard/tusb_config.h @@ -81,7 +81,7 @@ //--------------------------------------------------------------------+ // DEVICE CONFIGURATION //--------------------------------------------------------------------+ -#define TUSB_CFG_DEVICE_USE_ROM_DRIVER 1 +#define TUSB_CFG_DEVICE_USE_ROM_DRIVER 0 //------------- descriptors -------------// #define TUSB_CFG_DEVICE_STRING_MANUFACTURER "tinyusb.org" diff --git a/demos/host/host_os_none/.cproject b/demos/host/host_os_none/.cproject index fc97d29c1..487101415 100644 --- a/demos/host/host_os_none/.cproject +++ b/demos/host/host_os_none/.cproject @@ -462,10 +462,7 @@ <?xml version="1.0" encoding="UTF-8"?> <TargetConfig> <Properties property_0="" property_2="LPC18x7_43x7_2x512_BootA.cfx" property_3="NXP" property_4="LPC4357" property_count="5" version="60000"/> -<infoList vendor="NXP"> -<info chip="LPC4357" flash_driver="LPC18x7_43x7_2x512_BootA.cfx" match_id="0x0" name="LPC4357" resetscript="LPC18LPC43InternalFLASHBootResetscript.scp" stub="crt_emu_lpc18_43_nxp"> -<chip> -<name>LPC4357</name> +<infoList vendor="NXP"><info chip="LPC4357" flash_driver="LPC18x7_43x7_2x512_BootA.cfx" match_id="0x0" name="LPC4357" resetscript="LPC18LPC43InternalFLASHBootResetscript.scp" stub="crt_emu_lpc18_43_nxp"><chip><name>LPC4357</name> <family>LPC43xx</family> <vendor>NXP (formerly Philips)</vendor> <reset board="None" core="Real" sys="Real"/> @@ -540,8 +537,7 @@ <peripheralInstance derived_from="SPI" determined="infoFile" id="SPI" location="0x40100000"/> <peripheralInstance derived_from="SGPIO" determined="infoFile" id="SGPIO" location="0x40101000"/> </chip> -<processor> -<name gcc_name="cortex-m4">Cortex-M4</name> +<processor><name gcc_name="cortex-m4">Cortex-M4</name> <family>Cortex-M</family> </processor> <link href="nxp_lpc43xx_peripheral.xme" show="embed" type="simple"/> diff --git a/tinyusb/class/hid_device.c b/tinyusb/class/hid_device.c index e2950b093..20061789f 100644 --- a/tinyusb/class/hid_device.c +++ b/tinyusb/class/hid_device.c @@ -56,6 +56,9 @@ typedef struct { tusb_hid_descriptor_hid_t const * p_hid_desc; uint8_t const * p_report_desc; // volatile tusb_interface_status_t status; + + endpoint_handle_t ept_handle; + uint8_t interface_number; }hidd_interface_t; #if TUSB_CFG_DEVICE_HID_KEYBOARD @@ -343,7 +346,7 @@ ErrorCode_t HID_EpOut_Hdlr (USBD_HANDLE_T hUsb, void* data, uint32_t event) return LPC_OK; } -#else // not use the rom driver +#elif 1 // not use the rom driver tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const * p_request) { @@ -356,8 +359,8 @@ tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const * if ( p_request->bRequest == TUSB_REQUEST_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) { - dcd_pipe_control_write(coreid, keyboard_intf.p_report_desc, - keyboard_intf.p_hid_desc->wReportLength); + dcd_pipe_control_xfer(coreid, TUSB_DIR_DEV_TO_HOST, + keyboard_intf.p_report_desc, keyboard_intf.p_hid_desc->wReportLength); }else { ASSERT_STATUS(TUSB_ERROR_FAILED); @@ -385,6 +388,8 @@ tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const * ASSERT_STATUS(TUSB_ERROR_NOT_SUPPORTED_YET); return TUSB_ERROR_NOT_SUPPORTED_YET; } + + dcd_pipe_control_xfer(coreid, TUSB_DIR_HOST_TO_DEV, NULL, 0); // treat all class request as non-data control }else { ASSERT_STATUS(TUSB_ERROR_FAILED); @@ -414,7 +419,8 @@ tusb_error_t hidd_init(uint8_t coreid, tusb_descriptor_interface_t const * p_int { #if TUSB_CFG_DEVICE_HID_KEYBOARD case HID_PROTOCOL_KEYBOARD: - ASSERT_STATUS( dcd_pipe_open(coreid, p_desc_endpoint) ); + keyboard_intf.ept_handle = dcd_pipe_open(coreid, p_desc_endpoint); + ASSERT( endpointhandle_is_valid(keyboard_intf.ept_handle), TUSB_ERROR_DCD_FAILED); break; #endif diff --git a/tinyusb/common/errors.h b/tinyusb/common/errors.h index 027f9bb2d..f5ce6a343 100644 --- a/tinyusb/common/errors.h +++ b/tinyusb/common/errors.h @@ -90,6 +90,7 @@ ENTRY(TUSB_ERROR_MSCH_UNKNOWN_SCSI_COMMAND )\ ENTRY(TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED )\ ENTRY(TUSB_ERROR_HUB_FEATURE_NOT_SUPPORTED )\ + ENTRY(TUSB_ERROR_DCD_FAILED )\ ENTRY(TUSB_ERROR_NOT_SUPPORTED_YET )\ ENTRY(TUSB_ERROR_FAILED )\ diff --git a/tinyusb/device/dcd.h b/tinyusb/device/dcd.h index 4d6c7c08a..0c648347e 100644 --- a/tinyusb/device/dcd.h +++ b/tinyusb/device/dcd.h @@ -51,18 +51,44 @@ extern "C" { #endif +typedef struct { + uint8_t coreid; + uint8_t xfer_type; // cannot be control as control uses separated API + uint8_t index; + uint8_t reserved; +} endpoint_handle_t; + +static inline bool endpointhandle_is_valid(endpoint_handle_t endpoint_handle) ATTR_CONST ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; +static inline bool endpointhandle_is_valid(endpoint_handle_t endpoint_handle) +{ + return endpoint_handle.xfer_type != TUSB_XFER_CONTROL; +} + +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.xfer_type == y.xfer_type) && (x.index == y.index); +} + tusb_error_t dcd_init(void) ATTR_WARN_UNUSED_RESULT; -tusb_error_t dcd_controller_reset(uint8_t coreid) ATTR_WARN_UNUSED_RESULT; -void dcd_controller_connect(uint8_t coreid); + void dcd_isr(uint8_t coreid); -tusb_error_t dcd_pipe_control_write(uint8_t coreid, void const * buffer, uint16_t length); -tusb_error_t dcd_pipe_control_read(uint8_t coreid, void * buffer, uint16_t length); +//------------- Controller API -------------// +tusb_error_t dcd_controller_reset(uint8_t coreid) ATTR_WARN_UNUSED_RESULT; +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, uint8_t config_num); -void dcd_pipe_control_write_zero_length(uint8_t coreid); -tusb_error_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc) ATTR_WARN_UNUSED_RESULT; -void dcd_device_set_address(uint8_t coreid, uint8_t dev_addr); -void dcd_device_set_configuration(uint8_t coreid, uint8_t config_num); +//------------- PIPE API -------------// +tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * buffer, uint16_t length); + +//tusb_error_t dcd_pipe_control_write(uint8_t coreid, void const * buffer, uint16_t length); +//tusb_error_t dcd_pipe_control_read(uint8_t coreid, void * buffer, uint16_t length); +//void dcd_pipe_control_write_zero_length(uint8_t coreid); + +endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc) ATTR_WARN_UNUSED_RESULT; #ifdef __cplusplus } diff --git a/tinyusb/device/dcd_lpc175x_6x.c b/tinyusb/device/dcd_lpc175x_6x.c index c6ab3990c..b231d62dc 100644 --- a/tinyusb/device/dcd_lpc175x_6x.c +++ b/tinyusb/device/dcd_lpc175x_6x.c @@ -225,12 +225,12 @@ void dcd_controller_connect(uint8_t coreid) sie_command_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); } -void dcd_device_set_address(uint8_t coreid, uint8_t dev_addr) +void dcd_controller_set_address(uint8_t coreid, uint8_t dev_addr) { sie_command_write(SIE_CMDCODE_SET_ADDRESS, 1, 0x80 | dev_addr); // 7th bit is : device_enable } -void dcd_device_set_configuration(uint8_t coreid, uint8_t config_num) +void dcd_controller_set_configuration(uint8_t coreid, uint8_t config_num) { (void) config_num; // supress compiler's warnings sie_command_write(SIE_CMDCODE_CONFIGURE_DEVICE, 1, 1); diff --git a/tinyusb/device/dcd_lpc43xx.c b/tinyusb/device/dcd_lpc43xx.c new file mode 100644 index 000000000..659bc7fff --- /dev/null +++ b/tinyusb/device/dcd_lpc43xx.c @@ -0,0 +1,366 @@ +/**************************************************************************/ +/*! + @file dcd_lpc43xx.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 && MCU == MCU_LPC43XX + +#define _TINY_USB_SOURCE_FILE_ +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "common/common.h" +#include "hal/hal.h" +#include "osal/osal.h" +#include "common/timeout_timer.h" + +#include "dcd.h" +#include "usbd_dcd.h" +#include "dcd_lpc43xx.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +#define DCD_QHD_MAX 12 +#define QTD_INVALID 0x01 +#define CONTROL_ENDOINT_SIZE 64 + +typedef struct { + // Word 0: Next QTD Pointer + uint32_t next; ///< Next link pointer This field contains the physical memory address of the next dTD to be processed + + // Word 1: qTQ Token + uint32_t : 3 ; + volatile uint32_t xact_err : 1 ; + uint32_t : 1 ; + volatile uint32_t buffer_err : 1 ; + volatile uint32_t halted : 1 ; + volatile uint32_t active : 1 ; + uint32_t : 2 ; + uint32_t mult_override : 2 ; ///< This field can be used for transmit ISOs to override the MULT field in the dQH. This field must be zero for all packet types that are not transmit-ISO. + uint32_t : 3 ; + uint32_t int_on_complete : 1 ; + volatile uint32_t total_bytes : 15 ; + uint32_t : 0 ; + + // Word 2-6: Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page + uint32_t buffer[5]; ///< buffer1 has frame_n for TODO Isochronous + + //------------- -------------// + uint32_t reserved; +} dcd_qtd_t; + +STATIC_ASSERT( sizeof(dcd_qtd_t) == 32, "size is not correct"); + +typedef struct { + // Word 0: Capabilities and Characteristics + uint32_t : 15 ; ///< Number of packets executed per transaction descriptor 00 - Execute N transactions as demonstrated by the USB variable length protocol where N is computed using Max_packet_length and the Total_bytes field in the dTD. 01 - Execute one transaction 10 - Execute two transactions 11 - Execute three transactions Remark: Non-isochronous endpoints must set MULT = 00. Remark: Isochronous endpoints must set MULT = 01, 10, or 11 as needed. + uint32_t int_on_setup : 1 ; ///< Interrupt on setup This bit is used on control type endpoints to indicate if USBINT is set in response to a setup being received. + uint32_t max_package_size : 11 ; ///< This directly corresponds to the maximum packet size of the associated endpoint (wMaxPacketSize) + uint32_t : 2 ; + uint32_t zero_length_termination : 1 ; ///< This bit is used for non-isochronous endpoints to indicate when a zero-length packet is received to terminate transfers in case the total transfer length is “multiple”. 0 - Enable zero-length packet to terminate transfers equal to a multiple of Max_packet_length (default). 1 - Disable zero-length packet on transfers that are equal in length to a multiple Max_packet_length. + uint32_t mult : 2 ; ///< + uint32_t : 0 ; + + // Word 1: Current qTD Pointer + volatile uint32_t qtd_addr; + + // Word 2-9: Transfer Overlay + volatile dcd_qtd_t qtd_overlay; + + // Word 10-11: Setup request (control OUT only) + volatile tusb_control_request_t setup_request; + + //--------------------------------------------------------------------+ + /// Due to the fact QHD is 64 bytes aligned but occupies only 48 bytes + /// thus there are 16 bytes padding free that we can make use of. + //--------------------------------------------------------------------+ + uint8_t reserved[16]; + +} ATTR_ALIGNED(64) dcd_qhd_t; + +STATIC_ASSERT( sizeof(dcd_qhd_t) == 64, "size is not correct"); + +typedef struct { + dcd_qhd_t qhd[DCD_QHD_MAX]; ///< Must be at 2K alignment + dcd_qtd_t qtd[DCD_QHD_MAX] ATTR_ALIGNED(32); + +}dcd_data_t; + +ATTR_ALIGNED(2048) dcd_data_t dcd_data; + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// USBD-DCD API +//--------------------------------------------------------------------+ +tusb_error_t dcd_controller_reset(uint8_t coreid) +{ + volatile uint32_t * p_reg_usbcmd; + + p_reg_usbcmd = (coreid ? &LPC_USB1->USBCMD_D : &LPC_USB0->USBCMD_D); +// NXP chip powered with non-host mode --> sts bit is not correctly reflected + (*p_reg_usbcmd) |= BIT_(1); // TODO refractor reset controller + +// timeout_timer_t timeout; +// timeout_set(&timeout, 2); // should not take longer the time to stop controller + while( ((*p_reg_usbcmd) & BIT_(1)) /*&& !timeout_expired(&timeout)*/) {} +// +// return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE; + return TUSB_ERROR_NONE; +} + +void dcd_controller_connect(uint8_t coreid) +{ + volatile uint32_t * p_reg_usbcmd = (coreid ? &LPC_USB1->USBCMD_D : &LPC_USB0->USBCMD_D); + + (*p_reg_usbcmd) |= BIT_(0); +} + +/*---------- ENDPTCTRL ----------*/ +enum { + ENDPTCTRL_MASK_STALL = BIT_(0), + ENDPTCTRL_MASK_TOGGLE_INHIBIT = BIT_(5), ///< used for test only + ENDPTCTRL_MASK_TOGGLE_RESET = BIT_(6), + ENDPTCTRL_MASK_ENABLE = BIT_(7) +}; + +/*---------- USBCMD ----------*/ +enum { + USBCMD_MASK_RUN_STOP = BIT_(0), + USBCMD_MASK_RESET = BIT_(1), + USBCMD_MASK_SETUP_TRIPWIRE = BIT_(13), + USBCMD_MASK_ADD_QTD_TRIPWIRE = BIT_(14) ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoint’s linked list. This bit is set and cleared by software during the process of adding a new dTD +}; +// Interrupt Threshold bit 23:16 + +/*---------- USBSTS, USBINTR ----------*/ +enum { + INT_MASK_USB = BIT_(0), + INT_MASK_ERROR = BIT_(1), + INT_MASK_PORT_CHANGE = BIT_(2), + INT_MASK_RESET = BIT_(6), + INT_MASK_SOF = BIT_(7), + INT_MASK_SUSPEND = BIT_(8), + INT_MASK_NAK = BIT_(16) +}; + +//--------------------------------------------------------------------+ +// CONTROLLER API +//--------------------------------------------------------------------+ +void dcd_controller_set_address(uint8_t coreid, uint8_t dev_addr) +{ + LPC_USB0->DEVICEADDR = (dev_addr << 25) | BIT_(24); +} + +void dcd_controller_set_configuration(uint8_t coreid, uint8_t config_num) +{ + +} + +void bus_reset(uint8_t coreid) +{ + +} + +tusb_error_t dcd_init(void) +{ + // TODO mutliple core id support + /* disable all EPs */ + LPC_USB0->ENDPTCTRL1 &= ~(ENDPTCTRL_MASK_ENABLE | (ENDPTCTRL_MASK_ENABLE << 16) ); + LPC_USB0->ENDPTCTRL2 &= ~(ENDPTCTRL_MASK_ENABLE | (ENDPTCTRL_MASK_ENABLE << 16) ); + LPC_USB0->ENDPTCTRL3 &= ~(ENDPTCTRL_MASK_ENABLE | (ENDPTCTRL_MASK_ENABLE << 16) ); + LPC_USB0->ENDPTCTRL4 &= ~(ENDPTCTRL_MASK_ENABLE | (ENDPTCTRL_MASK_ENABLE << 16) ); + LPC_USB0->ENDPTCTRL5 &= ~(ENDPTCTRL_MASK_ENABLE | (ENDPTCTRL_MASK_ENABLE << 16) ); + + /* Clear all pending interrupts */ + LPC_USB0->ENDPTNAK = LPC_USB0->ENDPTNAK; + LPC_USB0->ENDPTNAKEN = 0; + LPC_USB0->USBSTS_D = LPC_USB0->USBSTS_D; + LPC_USB0->ENDPTSETUPSTAT = LPC_USB0->ENDPTSETUPSTAT; + LPC_USB0->ENDPTCOMPLETE = LPC_USB0->ENDPTCOMPLETE; + +// while (LPC_USB0->ENDPTPRIME); /* Wait until all bits are 0 */ + LPC_USB0->ENDPTFLUSH = 0xFFFFFFFF; + while (LPC_USB0->ENDPTFLUSH); /* Wait until all bits are 0 */ + + /* Set the interrupt Threshold control interval to 0 */ + LPC_USB0->USBCMD_D &= ~0x00FF0000; + + /* Configure the Endpoint List Address */ /* make sure it in on 2K boundary !!! */ + LPC_USB0->ENDPOINTLISTADDR = (uint32_t) dcd_data.qhd; + + /* Enable interrupts: USB interrupt, error, port change, reset, suspend, NAK interrupt */ + LPC_USB0->USBINTR_D = INT_MASK_USB | INT_MASK_ERROR | INT_MASK_PORT_CHANGE | INT_MASK_RESET | INT_MASK_SUSPEND; // | INT_MASK_SOF| INT_MASK_NAK; + + //------------- Set up Control Endpoints (0 OUT, 1 IN)-------------// + dcd_data.qhd[0].zero_length_termination = dcd_data.qhd[1].zero_length_termination = 1; + dcd_data.qhd[0].max_package_size = dcd_data.qhd[1].max_package_size = CONTROL_ENDOINT_SIZE; + dcd_data.qhd[0].qtd_overlay.next = dcd_data.qhd[1].qtd_overlay.next = QTD_INVALID; + + dcd_data.qhd[0].int_on_setup = 1; // OUT only + + return TUSB_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// PIPE API +//--------------------------------------------------------------------+ +static inline uint8_t endpoint_to_pos(uint8_t logical_endpoint, tusb_direction_t dir) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint8_t endpoint_to_pos(uint8_t logical_endpoint, tusb_direction_t dir) +{ + return logical_endpoint + (dir == TUSB_DIR_HOST_TO_DEV ? 0 : 16); +} + +static inline uint8_t endpoint_log2phy(uint8_t logical_endpoint, tusb_direction_t dir) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint8_t endpoint_log2phy(uint8_t logical_endpoint, tusb_direction_t dir) +{ + return 2*logical_endpoint + (dir == TUSB_DIR_DEV_TO_HOST ? 1 : 0); +} + +static inline uint8_t endpoint_addr2phy(uint8_t endpoint_addr) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint8_t endpoint_addr2phy(uint8_t endpoint_addr) +{ + return 2*(endpoint_addr & 0x0F) + ((endpoint_addr & TUSB_DIR_DEV_TO_HOST_MASK) ? 1 : 0); +} + +static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) +{ + memclr_(p_qtd, sizeof(dcd_qtd_t)); + + p_qtd->next = QTD_INVALID; + p_qtd->active = 1; + p_qtd->total_bytes = total_bytes; + + if (data_ptr != NULL) + { + p_qtd->buffer[0] = (uint32_t) data_ptr; + for(uint8_t i=1; i<5; i++) + { + p_qtd->buffer[i] |= align4k( p_qtd->buffer[i-1] ) + 4096; + } + } +} + +tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * buffer, uint16_t length) +{ + uint8_t const endpoint_data = (dir == TUSB_DIR_DEV_TO_HOST) ? 1 : 0; // IN xfer --> data phase on Control IN, other Control OUT + + //------------- Data Phase -------------// + if (length) + { + dcd_qtd_t* p_data = &dcd_data.qtd[0]; + qtd_init(p_data, buffer, length); + dcd_data.qhd[endpoint_data].qtd_overlay.next = (uint32_t) p_data; + + LPC_USB0->ENDPTPRIME |= BIT_(endpoint_to_pos(0, dir)); + } + + //------------- Status Phase (other endpoint, opposite direction) -------------// + dcd_qtd_t* p_status = &dcd_data.qtd[1]; + qtd_init(p_status, NULL, 0); // zero length xfer + dcd_data.qhd[1 - endpoint_data].qtd_overlay.next = (uint32_t) p_status; + + LPC_USB0->ENDPTPRIME |= BIT_(endpoint_to_pos(0, 1-dir)); + + return TUSB_ERROR_NONE; +} + +endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc) +{ + // TODO USB1 only has 4 non-control enpoint (USB0 has 5) + endpoint_handle_t const null_handle = { .coreid = 0, .xfer_type = 0, .index = 0 }; + + if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) + return null_handle; // TODO not support ISO yet + + //------------- Prepare Queue Head -------------// + uint8_t ep_idx = endpoint_addr2phy(p_endpoint_desc->bEndpointAddress); + dcd_qhd_t * p_qhd = &dcd_data.qhd[ep_idx]; + + memclr_(p_qhd, sizeof(dcd_qhd_t)); + + p_qhd->zero_length_termination = 1; + p_qhd->max_package_size = p_endpoint_desc->wMaxPacketSize.size; + p_qhd->qtd_overlay.next = QTD_INVALID; + + //------------- Endpoint Control Register -------------// + volatile uint32_t * reg_control = (&LPC_USB0->ENDPTCTRL0) + (p_endpoint_desc->bEndpointAddress & 0x0f); + (*reg_control) = ((p_endpoint_desc->bmAttributes.xfer << 2) | ENDPTCTRL_MASK_ENABLE | ENDPTCTRL_MASK_TOGGLE_RESET) << ((p_endpoint_desc->bEndpointAddress & TUSB_DIR_DEV_TO_HOST_MASK) ? 16 : 0); + + return (endpoint_handle_t) { .coreid = coreid, .xfer_type = p_endpoint_desc->bmAttributes.xfer, .index = ep_idx }; +} + + +void dcd_isr(uint8_t coreid) +{ + uint32_t int_status = LPC_USB0->USBSTS_D; + int_status &= LPC_USB0->USBINTR_D; + + LPC_USB0->USBSTS_D = int_status; // Acknowledge handled interrupt + + if (int_status == 0) return; + + if (int_status & INT_MASK_RESET) + { +// dcd_init() + } + + if (int_status & INT_MASK_USB) + { + if (LPC_USB0->ENDPTSETUPSTAT) + { + LPC_USB0->ENDPTSETUPSTAT = 1; + usbd_setup_received_isr(coreid, &dcd_data.qhd[0].setup_request); + } + + if (LPC_USB0->ENDPTCOMPLETE) + { +// TransferCompleteISR(DeviceID); + } + } + + if (int_status & INT_MASK_SOF) { } + if (int_status & INT_MASK_SUSPEND) { } + if (int_status & INT_MASK_PORT_CHANGE) { } + if (int_status & INT_MASK_NAK) { } + if (int_status & INT_MASK_ERROR) ASSERT(false, VOID_RETURN); +} +#endif diff --git a/tinyusb/device/dcd_lpc43xx.h b/tinyusb/device/dcd_lpc43xx.h new file mode 100644 index 000000000..b8f5b1785 --- /dev/null +++ b/tinyusb/device/dcd_lpc43xx.h @@ -0,0 +1,60 @@ +/**************************************************************************/ +/*! + @file dcd_lpc43xx.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_DCD_LPC43XX_H_ +#define _TUSB_DCD_LPC43XX_H_ + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_DCD_LPC43XX_H_ */ + +/** @} */ \ No newline at end of file diff --git a/tinyusb/device/usbd.c b/tinyusb/device/usbd.c index 3d6687405..1092f4ce1 100644 --- a/tinyusb/device/usbd.c +++ b/tinyusb/device/usbd.c @@ -86,24 +86,20 @@ void usbd_bus_reset(uint32_t coreid) memclr_(usbd_devices, sizeof(usbd_device_info_t)*CONTROLLER_DEVICE_NUMBER); } -void std_get_descriptor(uint8_t coreid) +void std_get_descriptor(uint8_t coreid, tusb_control_request_t * p_request) { - tusb_std_descriptor_type_t const desc_type = usbd_devices[coreid].setup_packet.wValue >> 8; - uint8_t const desc_index = u16_low_u8( usbd_devices[coreid].setup_packet.wValue ); + tusb_std_descriptor_type_t const desc_type = p_request->wValue >> 8; + uint8_t const desc_index = u16_low_u8( p_request->wValue ); switch ( desc_type ) { case TUSB_DESC_TYPE_DEVICE: - dcd_pipe_control_write(coreid, &app_tusb_desc_device, sizeof(tusb_descriptor_device_t)); + dcd_pipe_control_xfer(coreid, TUSB_DIR_DEV_TO_HOST, &app_tusb_desc_device, + min16_of( p_request->wLength, sizeof(tusb_descriptor_device_t)) ); break; case TUSB_DESC_TYPE_CONFIGURATION: - { - uint16_t const requested_length = min16_of(usbd_devices[coreid].setup_packet.wLength, sizeof(app_tusb_desc_configuration)-1); - ASSERT(requested_length <= TUSB_CFG_DEVICE_CONTROL_PACKET_SIZE, (void)0 ); // multiple packets requires a task a-like - - dcd_pipe_control_write(coreid, &app_tusb_desc_configuration, - requested_length); - } + dcd_pipe_control_xfer(coreid, TUSB_DIR_DEV_TO_HOST, &app_tusb_desc_configuration, + min16_of( p_request->wLength, sizeof(app_tusb_desc_configuration)-1) ); break; case TUSB_DESC_TYPE_STRING: @@ -113,7 +109,7 @@ void std_get_descriptor(uint8_t coreid) { p_string += (*p_string); } - dcd_pipe_control_write(coreid, p_string, *p_string); + dcd_pipe_control_xfer(coreid, TUSB_DIR_DEV_TO_HOST, p_string, *p_string); } break; @@ -123,49 +119,44 @@ void std_get_descriptor(uint8_t coreid) } } -void usbd_setup_received(uint8_t coreid) +void usbd_setup_received_isr(uint8_t coreid, tusb_control_request_t * p_request) { usbd_device_info_t *p_device = &usbd_devices[coreid]; - - // check device configured TODO - if ( p_device->setup_packet.bmRequestType_bit.recipient == TUSB_REQUEST_RECIPIENT_INTERFACE) + switch(p_request->bmRequestType_bit.recipient) { - // TODO detect which class -// ASSERT( p_device->setup_packet.wIndex < USBD_MAX_INTERFACE, (void) 0); -// tusb_std_class_code_t const class_code = usbd_devices[coreid].interface2class[ p_device->setup_packet.wIndex ]; -// if ( usbd_class_drivers[class_code].control_request != NULL ) -// { -// usbd_class_drivers[class_code].control_request(coreid, &p_device->setup_packet); -// -// } - hidd_control_request(coreid, &p_device->setup_packet); - }else - { - switch ( p_device->setup_packet.bRequest ) - { - case TUSB_REQUEST_GET_DESCRIPTOR: - std_get_descriptor(coreid); - break; + //------------- Standard Control such as those in enumeration -------------// + case TUSB_REQUEST_RECIPIENT_DEVICE: + switch ( p_request->bRequest ) + { + case TUSB_REQUEST_GET_DESCRIPTOR: + std_get_descriptor(coreid, p_request); + break; - case TUSB_REQUEST_SET_ADDRESS: - p_device->address = (uint8_t) p_device->setup_packet.wValue; - dcd_device_set_address(coreid, p_device->address); - usbd_devices[coreid].state = TUSB_DEVICE_STATE_ADDRESSED; - break; + case TUSB_REQUEST_SET_ADDRESS: + p_device->address = (uint8_t) p_request->wValue; + dcd_controller_set_address(coreid, p_device->address); + usbd_devices[coreid].state = TUSB_DEVICE_STATE_ADDRESSED; - case TUSB_REQUEST_SET_CONFIGURATION: - dcd_device_set_configuration(coreid, (uint8_t) p_device->setup_packet.wValue); - usbd_devices[coreid].state = TUSB_DEVICE_STATE_CONFIGURED; - break; + dcd_pipe_control_xfer(coreid, TUSB_DIR_HOST_TO_DEV, NULL, 0); // zero length + break; - default: - return; - } - } + case TUSB_REQUEST_SET_CONFIGURATION: + dcd_controller_set_configuration(coreid, (uint8_t) p_request->wValue); + usbd_devices[coreid].state = TUSB_DEVICE_STATE_CONFIGURED; - if (p_device->setup_packet.bmRequestType_bit.direction == TUSB_DIR_HOST_TO_DEV) - { - dcd_pipe_control_write_zero_length(coreid); + dcd_pipe_control_xfer(coreid, TUSB_DIR_HOST_TO_DEV, NULL, 0); // zero length + break; + + default: ASSERT(false, VOID_RETURN); break; + } + break; + + //------------- Class/Interface Specific Reqequest -------------// + case TUSB_REQUEST_RECIPIENT_INTERFACE: + hidd_control_request(coreid, p_request); + break; + + default: ASSERT(false, VOID_RETURN); break; } } @@ -187,12 +178,6 @@ tusb_error_t usbd_init (void) ASSERT_STATUS( hidd_init(0, &app_tusb_desc_configuration.mouse_interface, &length) ); #endif - usbd_bus_reset(0); - - #ifndef _TEST_ - hal_interrupt_enable(0); // TODO USB1 - #endif - dcd_controller_connect(0); // TODO USB1 return TUSB_ERROR_NONE; @@ -211,23 +196,23 @@ tusb_error_t usbd_pipe_open(uint8_t coreid, tusb_descriptor_interface_t const * //--------------------------------------------------------------------+ // callback from DCD ISR //--------------------------------------------------------------------+ -void usbd_isr(uint8_t coreid, tusb_event_t event) -{ - switch(event) - { - case TUSB_EVENT_BUS_RESET: - usbd_bus_reset(coreid); - break; - - case TUSB_EVENT_SETUP_RECEIVED: - usbd_setup_received(coreid); - break; - - default: - ASSERT(false, (void) 0); - break; - } -} +//void usbd_isr(uint8_t coreid, tusb_event_t event) +//{ +// switch(event) +// { +// case TUSB_EVENT_BUS_RESET: +// usbd_bus_reset(coreid); +// break; +// +// case TUSB_EVENT_SETUP_RECEIVED: +// usbd_setup_received(coreid); +// break; +// +// default: +// ASSERT(false, (void) 0); +// break; +// } +//} //--------------------------------------------------------------------+ // HELPER diff --git a/tinyusb/device/usbd_dcd.h b/tinyusb/device/usbd_dcd.h index b824012e4..367d92384 100644 --- a/tinyusb/device/usbd_dcd.h +++ b/tinyusb/device/usbd_dcd.h @@ -60,7 +60,6 @@ typedef struct { volatile uint8_t state; uint8_t address; - tusb_control_request_t setup_packet; uint8_t interface2class[USBD_MAX_INTERFACE]; // determine interface number belongs to which class uint8_t endpoint_idx2class[USBD_MAX_ENDPOINT]; // determine endpoint index belongs to which class }usbd_device_info_t; diff --git a/tinyusb/hal/hal_lpc43xx.c b/tinyusb/hal/hal_lpc43xx.c index 2fe019d09..1ba5c4767 100644 --- a/tinyusb/hal/hal_lpc43xx.c +++ b/tinyusb/hal/hal_lpc43xx.c @@ -69,9 +69,9 @@ tusb_error_t hal_init(void) hcd_controller_reset(0); // TODO where to place prototype LPC_USB0->USBMODE_H = LPC43XX_USBMODE_HOST | (LPC43XX_USBMODE_VBUS_HIGH << 5); #else // TODO OTG -// dcd_controller_reset(0); -// LPC_USB0->USBMODE_D = LPC43XX_USBMODE_DEVICE; -// LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; + dcd_controller_reset(0); + LPC_USB0->USBMODE_D = LPC43XX_USBMODE_DEVICE; + LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; // LPC_USB0->PORTSC1_D |= (1<<24); // force full speed // dcd_controller_connect(0); #endif diff --git a/tinyusb/host/ehci/ehci.c b/tinyusb/host/ehci/ehci.c index 428c2636f..30c6665ec 100644 --- a/tinyusb/host/ehci/ehci.c +++ b/tinyusb/host/ehci/ehci.c @@ -768,8 +768,7 @@ void hcd_isr(uint8_t hostid) regs->usb_sts |= int_status; // Acknowledge handled interrupt - if (int_status == 0) - return; + if (int_status == 0) return; if (int_status & EHCI_INT_MASK_PORT_CHANGE) { diff --git a/tinyusb/tusb_option.h b/tinyusb/tusb_option.h index 6689cb6d1..a4b1fcd30 100644 --- a/tinyusb/tusb_option.h +++ b/tinyusb/tusb_option.h @@ -164,9 +164,10 @@ //--------------------------------------------------------------------+ #if MODE_DEVICE_SUPPORTED -#if defined(CAP_DEVICE_ROMDRIVER) && !TUSB_CFG_DEVICE_USE_ROM_DRIVER - #error only rom driver for these mcu are supported now -#endif +// TODO only support non rom driver +//#if defined(CAP_DEVICE_ROMDRIVER) && !TUSB_CFG_DEVICE_USE_ROM_DRIVER +// #error only rom driver for these mcu are supported now +//#endif #define DEVICE_CLASS_HID ( TUSB_CFG_DEVICE_HID_KEYBOARD + TUSB_CFG_DEVICE_HID_MOUSE + TUSB_CFG_DEVICE_HID_GENERIC )