2013-05-25 11:03:40 +02:00
/**************************************************************************/
/*!
2013-05-28 10:24:27 +02:00
@ file dcd_lpc175x_6x . h
2013-05-25 11:03:40 +02:00
@ 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 .
*/
/**************************************************************************/
2013-11-22 09:16:24 +01:00
/** \ingroup Port_DCD
* @ {
* \ defgroup LPC175x_6x
2013-05-25 11:03:40 +02:00
* @ {
*/
2013-11-22 09:16:24 +01:00
2013-05-28 10:24:27 +02:00
# ifndef _TUSB_DCD_LPC175X_6X_H_
# define _TUSB_DCD_LPC175X_6X_H_
2013-05-25 11:03:40 +02:00
2013-06-05 06:23:41 +02:00
# include "common/common.h"
2013-05-25 11:03:40 +02:00
# ifdef __cplusplus
extern " C " {
# endif
2013-11-22 09:16:24 +01:00
typedef struct ATTR_ALIGNED ( 4 )
2013-06-05 06:23:41 +02:00
{
//------------- Word 0 -------------//
uint32_t next ;
//------------- Word 1 -------------//
2013-06-12 16:06:43 +02:00
uint16_t mode : 2 ; // either 00 normal or 01 ATLE(auto length extraction)
2013-06-05 06:23:41 +02:00
uint16_t is_next_valid : 1 ;
2014-03-10 05:18:50 +01:00
uint16_t int_on_complete : 1 ; ///< make use of reserved bit
2013-06-05 06:23:41 +02:00
uint16_t is_isochronous : 1 ; // is an iso endpoint
uint16_t max_packet_size : 11 ;
volatile uint16_t buffer_length ;
//------------- Word 2 -------------//
2013-11-19 10:41:30 +01:00
volatile uint32_t buffer_addr ;
2013-06-05 06:23:41 +02:00
//------------- Word 3 -------------//
volatile uint16_t is_retired : 1 ; // initialized to zero
volatile uint16_t status : 4 ;
volatile uint16_t iso_last_packet_valid : 1 ;
volatile uint16_t atle_is_lsb_extracted : 1 ; // used in ATLE mode
volatile uint16_t atle_is_msb_extracted : 1 ; // used in ATLE mode
volatile uint16_t atle_message_length_position : 6 ; // used in ATLE mode
uint16_t : 2 ;
volatile uint16_t present_count ; // The number of bytes transferred by the DMA engine. The DMA engine updates this field after completing each packet transfer.
//------------- Word 4 -------------//
// uint32_t iso_packet_size_addr; // iso only, can be omitted for non-iso
2013-11-22 09:16:24 +01:00
} dcd_dma_descriptor_t ;
2013-06-05 06:23:41 +02:00
2013-11-19 10:41:30 +01:00
STATIC_ASSERT ( sizeof ( dcd_dma_descriptor_t ) = = 16 , " size is not correct " ) ; // TODO not support ISO for now
2013-06-05 06:23:41 +02:00
2013-06-07 21:50:10 +02:00
//--------------------------------------------------------------------+
// Register Interface
//--------------------------------------------------------------------+
//------------- USB Interrupt USBIntSt -------------//
//enum {
// DCD_USB_REQ_LOW_PRIO_MASK = BIT_(0),
// DCD_USB_REQ_HIGH_PRIO_MASK = BIT_(1),
// DCD_USB_REQ_DMA_MASK = BIT_(2),
// DCD_USB_REQ_NEED_CLOCK_MASK = BIT_(8),
// DCD_USB_REQ_ENABLE_MASK = BIT_(31)
//};
//------------- Device Interrupt USBDevInt -------------//
enum {
DEV_INT_FRAME_MASK = BIT_ ( 0 ) ,
DEV_INT_ENDPOINT_FAST_MASK = BIT_ ( 1 ) ,
DEV_INT_ENDPOINT_SLOW_MASK = BIT_ ( 2 ) ,
DEV_INT_DEVICE_STATUS_MASK = BIT_ ( 3 ) ,
DEV_INT_COMMAND_CODE_EMPTY_MASK = BIT_ ( 4 ) ,
DEV_INT_COMMAND_DATA_FULL_MASK = BIT_ ( 5 ) ,
DEV_INT_RX_ENDPOINT_PACKET_MASK = BIT_ ( 6 ) ,
DEV_INT_TX_ENDPOINT_PACKET_MASK = BIT_ ( 7 ) ,
DEV_INT_ENDPOINT_REALIZED_MASK = BIT_ ( 8 ) ,
2013-11-20 06:21:29 +01:00
DEV_INT_ERROR_MASK = BIT_ ( 9 )
2013-06-07 21:50:10 +02:00
} ;
//------------- DMA Interrupt USBDMAInt-------------//
enum {
DMA_INT_END_OF_XFER_MASK = BIT_ ( 0 ) ,
DMA_INT_NEW_DD_REQUEST_MASK = BIT_ ( 1 ) ,
DMA_INT_ERROR_MASK = BIT_ ( 2 )
} ;
//------------- USBCtrl -------------//
enum {
2013-11-20 06:52:07 +01:00
USBCTRL_READ_ENABLE_MASK = BIT_ ( 0 ) ,
USBCTRL_WRITE_ENABLE_MASK = BIT_ ( 1 ) ,
2013-06-07 21:50:10 +02:00
} ;
//------------- USBRxPLen -------------//
enum {
2013-11-20 06:52:07 +01:00
USBRXPLEN_PACKET_LENGTH_MASK = ( BIT_ ( 10 ) - 1 ) ,
USBRXPLEN_DATA_VALID_MASK = BIT_ ( 10 ) ,
USBRXPLEN_PACKET_READY_MASK = BIT_ ( 11 ) ,
2013-06-07 21:50:10 +02:00
} ;
//------------- SIE Command Code -------------//
2013-11-18 11:29:12 +01:00
typedef enum {
2013-06-07 21:50:10 +02:00
SIE_CMDPHASE_WRITE = 1 ,
SIE_CMDPHASE_READ = 2 ,
SIE_CMDPHASE_COMMAND = 5
2013-11-18 11:29:12 +01:00
} sie_cmdphase_t ;
2013-06-07 21:50:10 +02:00
enum {
// device commands
SIE_CMDCODE_SET_ADDRESS = 0xd0 ,
SIE_CMDCODE_CONFIGURE_DEVICE = 0xd8 ,
SIE_CMDCODE_SET_MODE = 0xf3 ,
SIE_CMDCODE_READ_FRAME_NUMBER = 0xf5 ,
SIE_CMDCODE_READ_TEST_REGISTER = 0xfd ,
SIE_CMDCODE_DEVICE_STATUS = 0xfe ,
SIE_CMDCODE_GET_ERROR = 0xff ,
SIE_CMDCODE_READ_ERROR_STATUS = 0xfb ,
// endpoint commands
SIE_CMDCODE_ENDPOINT_SELECT = 0x00 , // + endpoint index
SIE_CMDCODE_ENDPOINT_SELECT_CLEAR_INTERRUPT = 0x40 , // + endpoint index, should use USBEpIntClr instead
SIE_CMDCODE_ENDPOINT_SET_STATUS = 0x40 , // + endpoint index
SIE_CMDCODE_BUFFER_CLEAR = 0xf2 ,
SIE_CMDCODE_BUFFER_VALIDATE = 0xfa
} ;
//------------- SIE Device Status (get/set from SIE_CMDCODE_DEVICE_STATUS) -------------//
enum {
2013-11-21 06:47:55 +01:00
SIE_DEV_STATUS_CONNECT_STATUS_MASK = BIT_ ( 0 ) ,
2013-06-07 21:50:10 +02:00
SIE_DEV_STATUS_CONNECT_CHANGE_MASK = BIT_ ( 1 ) ,
SIE_DEV_STATUS_SUSPEND_MASK = BIT_ ( 2 ) ,
SIE_DEV_STATUS_SUSPEND_CHANGE_MASK = BIT_ ( 3 ) ,
SIE_DEV_STATUS_RESET_MASK = BIT_ ( 4 )
} ;
2013-11-19 10:41:30 +01:00
//------------- SIE Select Endpoint Command -------------//
2013-06-07 21:50:10 +02:00
enum {
2013-11-19 10:41:30 +01:00
SIE_SELECT_ENDPOINT_FULL_EMPTY_MASK = BIT_ ( 0 ) , // 0: empty, 1 full. IN endpoint checks empty, OUT endpoint check full
SIE_SELECT_ENDPOINT_STALL_MASK = BIT_ ( 1 ) ,
SIE_SELECT_ENDPOINT_SETUP_RECEIVED_MASK = BIT_ ( 2 ) , // clear by SIE_CMDCODE_ENDPOINT_SELECT_CLEAR_INTERRUPT
SIE_SELECT_ENDPOINT_PACKET_OVERWRITTEN_MASK = BIT_ ( 3 ) , // previous packet is overwritten by a SETUP packet
SIE_SELECT_ENDPOINT_NAK_MASK = BIT_ ( 4 ) , // last packet response is NAK (auto clear by an ACK)
SIE_SELECT_ENDPOINT_BUFFER1_FULL_MASK = BIT_ ( 5 ) ,
SIE_SELECT_ENDPOINT_BUFFER2_FULL_MASK = BIT_ ( 6 )
2013-06-07 21:50:10 +02:00
} ;
2013-11-19 10:41:30 +01:00
typedef enum {
SIE_SET_ENDPOINT_STALLED_MASK = BIT_ ( 0 ) ,
SIE_SET_ENDPOINT_DISABLED_MASK = BIT_ ( 5 ) ,
SIE_SET_ENDPOINT_RATE_FEEDBACK_MASK = BIT_ ( 6 ) ,
SIE_SET_ENDPOINT_CONDITION_STALLED_MASK = BIT_ ( 7 ) ,
} sie_endpoint_set_status_mask_t ;
2013-06-12 16:06:43 +02:00
//------------- DMA Descriptor Status -------------//
enum {
DD_STATUS_NOT_SERVICED = 0 ,
DD_STATUS_BEING_SERVICED ,
DD_STATUS_NORMAL ,
DD_STATUS_DATA_UNDERUN , // short packet
DD_STATUS_DATA_OVERRUN ,
DD_STATUS_SYSTEM_ERROR
} ;
2013-11-21 06:47:55 +01:00
//--------------------------------------------------------------------+
// SIE Command
//--------------------------------------------------------------------+
static inline void sie_cmd_code ( sie_cmdphase_t phase , uint8_t code_data ) ATTR_ALWAYS_INLINE ;
static inline void sie_cmd_code ( sie_cmdphase_t phase , uint8_t code_data )
{
LPC_USB - > USBDevIntClr = ( DEV_INT_COMMAND_CODE_EMPTY_MASK | DEV_INT_COMMAND_DATA_FULL_MASK ) ;
LPC_USB - > USBCmdCode = ( phase < < 8 ) | ( code_data < < 16 ) ;
uint32_t const wait_flag = ( phase = = SIE_CMDPHASE_READ ) ? DEV_INT_COMMAND_DATA_FULL_MASK : DEV_INT_COMMAND_CODE_EMPTY_MASK ;
# ifndef _TEST_
while ( ( LPC_USB - > USBDevIntSt & wait_flag ) = = 0 ) ; // TODO blocking forever potential
# endif
LPC_USB - > USBDevIntClr = wait_flag ;
}
static inline void sie_write ( uint8_t cmd_code , uint8_t data_len , uint8_t data ) ATTR_ALWAYS_INLINE ;
static inline void sie_write ( uint8_t cmd_code , uint8_t data_len , uint8_t data )
{
sie_cmd_code ( SIE_CMDPHASE_COMMAND , cmd_code ) ;
if ( data_len )
{
sie_cmd_code ( SIE_CMDPHASE_WRITE , data ) ;
}
}
static inline uint32_t sie_read ( uint8_t cmd_code , uint8_t data_len ) ATTR_ALWAYS_INLINE ;
static inline uint32_t sie_read ( uint8_t cmd_code , uint8_t data_len )
{
// TODO multiple read
sie_cmd_code ( SIE_CMDPHASE_COMMAND , cmd_code ) ;
sie_cmd_code ( SIE_CMDPHASE_READ , cmd_code ) ;
return LPC_USB - > USBCmdData ;
}
2013-05-25 11:03:40 +02:00
# ifdef __cplusplus
}
# endif
2013-05-28 10:24:27 +02:00
# endif /* _TUSB_DCD_LPC175X_6X_H_ */
2013-05-25 11:03:40 +02:00
/** @} */
2013-11-22 09:16:24 +01:00
/** @} */