mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-30 04:20:26 +00:00
implementing sw device stack
This commit is contained in:
parent
d925026089
commit
357813f171
@ -5,15 +5,6 @@
|
||||
#include "boards/board.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#if defined(__CODE_RED)
|
||||
#include <cr_section_macros.h>
|
||||
#include <NXP/crp.h>
|
||||
// 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);
|
||||
|
@ -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"
|
||||
|
@ -462,10 +462,7 @@
|
||||
<projectStorage><?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"/>
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 )\
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
366
tinyusb/device/dcd_lpc43xx.c
Normal file
366
tinyusb/device/dcd_lpc43xx.c
Normal file
@ -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
|
60
tinyusb/device/dcd_lpc43xx.h
Normal file
60
tinyusb/device/dcd_lpc43xx.h
Normal file
@ -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_ */
|
||||
|
||||
/** @} */
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 )
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user