complete dcd for lpc175x_6x

cdc device demo can work but there is hardfault with dma descriptor with fast typing
This commit is contained in:
hathach 2013-11-19 16:41:30 +07:00
parent 94854f805a
commit 2dafeee585
4 changed files with 260 additions and 90 deletions

View File

@ -46,7 +46,7 @@
// INCLUDE
//--------------------------------------------------------------------+
enum {
CDCD_APP_BUFFER_SIZE = 16
CDCD_APP_BUFFER_SIZE = 64
};
//--------------------------------------------------------------------+

View File

@ -44,25 +44,28 @@
//--------------------------------------------------------------------+
// Endpoints Address & Max Packet Size
//--------------------------------------------------------------------+
//------------- CDC -------------//
#define CDC_EDPT_NOTIFICATION_ADDR ENDPOINT_IN_LOGICAL_TO_PHYSICAL(2)
#define CDC_EDPT_NOTIFICATION_PACKETSIZE 64
#define EDPT_IN(x) (0x80 | x)
#define EDPT_OUT(x) (x)
#define CDC_EDPT_DATA_OUT ENDPOINT_OUT_LOGICAL_TO_PHYSICAL(3)
#define CDC_EDPT_DATA_IN ENDPOINT_IN_LOGICAL_TO_PHYSICAL(3)
#define CDC_EDPT_DATA_PACKETSIZE 64
//------------- CDC -------------//
#define CDC_EDPT_NOTIFICATION_ADDR EDPT_IN(1)
#define CDC_EDPT_NOTIFICATION_PACKETSIZE 64
#define CDC_EDPT_DATA_OUT EDPT_OUT(2)
#define CDC_EDPT_DATA_IN EDPT_IN(2)
#define CDC_EDPT_DATA_PACKETSIZE 64
//------------- HID Keyboard -------------//
#define HID_EDPT_KEYBOARD_ADDR ENDPOINT_IN_LOGICAL_TO_PHYSICAL(1)
#define HID_EDPT_KEYBOARD_ADDR EDPT_IN(3)
//------------- HID Mouse -------------//
#define HID_MOUSE_EP_IN ENDPOINT_IN_LOGICAL_TO_PHYSICAL(4)
#define HID_MOUSE_EP_IN EDPT_IN(4)
//------------- HID Generic -------------//
//------------- Mass Storage -------------//
#define MSC_EDPT_IN ENDPOINT_IN_LOGICAL_TO_PHYSICAL(3)
#define MSC_EDPT_OUT ENDPOINT_OUT_LOGICAL_TO_PHYSICAL(3)
#define MSC_EDPT_IN EDPT_IN(3)
#define MSC_EDPT_OUT EDPT_OUT(3)
//--------------------------------------------------------------------+

View File

@ -52,31 +52,28 @@
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
STATIC_ ATTR_ALIGNED(128) dcd_dma_descriptor_t* dcd_udca[32] TUSB_CFG_ATTR_USBRAM;
STATIC_ dcd_dma_descriptor_t dcd_dd[DCD_MAX_DD];
#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];
uint8_t ddat[DCD_QHD_MAX]; ///< DMA Descriptor Allocation Table. A fixed DD will be allocated for a UDCA pointer up on endpoint open
uint8_t class_code[DCD_QHD_MAX];
}dcd_data_t;
STATIC_ dcd_data_t dcd_data TUSB_CFG_ATTR_USBRAM;
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
static void bus_reset(void);
static inline void endpoint_set_max_packet_size(uint8_t endpoint_idx, uint16_t max_packet_size) ATTR_ALWAYS_INLINE;
static inline void endpoint_set_max_packet_size(uint8_t endpoint_idx, uint16_t max_packet_size)
{
LPC_USB->USBReEp |= BIT_(endpoint_idx);
LPC_USB->USBEpInd = endpoint_idx; // select index before setting packet size
LPC_USB->USBMaxPSize = max_packet_size;
#ifndef _TEST_
if( endpoint_idx > 2) // endpoint control is always realized
{
while ((LPC_USB->USBDevIntSt & DEV_INT_ENDPOINT_REALIZED_MASK) == 0) {} // TODO can be omitted, or move to set max packet size
LPC_USB->USBDevIntClr = DEV_INT_ENDPOINT_REALIZED_MASK;
}
#endif
}
//--------------------------------------------------------------------+
// 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)
{
@ -110,22 +107,44 @@ static inline uint32_t sie_read (uint8_t cmd_code, uint8_t data_len)
return LPC_USB->USBCmdData;
}
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_
if( ep_id > 2) // endpoint control is always realized
{
while ((LPC_USB->USBDevIntSt & DEV_INT_ENDPOINT_REALIZED_MASK) == 0) {} // TODO can be omitted, or move to set max packet size
LPC_USB->USBDevIntClr = DEV_INT_ENDPOINT_REALIZED_MASK;
}
#endif
}
static inline dcd_dma_descriptor_t* qhd_get_fixed_dd(uint8_t ep_id) ATTR_PURE ATTR_ALWAYS_INLINE;
static inline dcd_dma_descriptor_t* qhd_get_fixed_dd(uint8_t ep_id)
{
return &dcd_data.dd[ dcd_data.ddat[ep_id] ];
}
static tusb_error_t pipe_control_write(void const * buffer, uint16_t length);
static tusb_error_t pipe_control_read(void * buffer, uint16_t length);
//--------------------------------------------------------------------+
// IMPLEMENTATION
//--------------------------------------------------------------------+
void endpoint_control_isr(uint8_t coreid)
void endpoint_control_isr(void)
{
(void) coreid; // suppress compiler warning
uint32_t const endpoint_int_status = LPC_USB->USBEpIntSt & LPC_USB->USBEpIntEn;
//------------- control OUT -------------//
if (endpoint_int_status & BIT_(0))
{
uint32_t const endpoint_status = sie_read(SIE_CMDCODE_ENDPOINT_SELECT+0, 1);
if (endpoint_status & SIE_ENDPOINT_STATUS_SETUP_RECEIVED_MASK)
if (endpoint_status & SIE_SELECT_ENDPOINT_SETUP_RECEIVED_MASK)
{
tusb_control_request_t control_request;
@ -137,7 +156,6 @@ void endpoint_control_isr(uint8_t coreid)
}else
{
// Current not support any out control with data yet
// pipe_control_read(0,..
}
sie_write(SIE_CMDCODE_ENDPOINT_SELECT+0, 0, 0);
sie_write(SIE_CMDCODE_BUFFER_CLEAR , 0, 0);
@ -146,10 +164,16 @@ void endpoint_control_isr(uint8_t coreid)
//------------- control IN -------------//
if (endpoint_int_status & BIT_(1))
{
(void) endpoint_int_status;
endpoint_handle_t edpt_hdl =
{
.index = 1 //BIT_TEST_(int_status, 1) ? 1 : 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
LPC_USB->USBEpIntClr = endpoint_int_status; // acknowledge interrupt TODO cannot immediately acknowledge setup packet
}
void dcd_isr(uint8_t coreid)
@ -173,20 +197,59 @@ void dcd_isr(uint8_t coreid)
}
}
//------------- slave mode, control endpoint -------------//
//------------- Control Endpoint (Slave Mode) -------------//
if (device_int_status & DEV_INT_ENDPOINT_SLOW_MASK)
{
// only occur on control endpoint, all other use DMA
endpoint_control_isr(coreid);
endpoint_control_isr();
}
if (device_int_status & DEV_INT_ERROR_MASK)
//------------- 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
for(uint8_t ep_id = 2; ep_id < DCD_QHD_MAX; ep_id++ )
{
if ( BIT_TEST_(eot_int, ep_id) )
{
dcd_dma_descriptor_t* p_dd;
dcd_dma_descriptor_t* const p_fixed_dd = qhd_get_fixed_dd(ep_id);
p_fixed_dd->buffer_length = 0; // buffer length is used to determined if fixed dd is queued in pipe xfer function
// Maximum is 2 QTD are queued in an endpoint
if (p_fixed_dd->is_next_valid)
{
p_dd = (dcd_dma_descriptor_t*) p_fixed_dd->next;
p_dd->used = 0; // free non-fixed dd
}else
{
p_dd = p_fixed_dd;
}
endpoint_handle_t edpt_hdl =
{
.coreid = 0,
.index = ep_id,
.class_code = dcd_data.class_code[ep_id]
};
tusb_event_t event = (p_dd->status == DD_STATUS_NORMAL || p_dd->status == DD_STATUS_DATA_UNDERUN) ? TUSB_EVENT_XFER_COMPLETE : TUSB_EVENT_XFER_ERROR;
usbd_xfer_isr(edpt_hdl, event, p_dd->present_count); // only number of bytes in the IOC qtd
}
}
}
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);
}
}
//--------------------------------------------------------------------+
@ -200,32 +263,28 @@ static void bus_reset(void)
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
endpoint_set_max_packet_size(0, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE);
endpoint_set_max_packet_size(1, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE);
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);
for (uint8_t index = 0; index < DCD_MAX_DD; index++)
{
dcd_udca[index] = dcd_dd + index;
}
LPC_USB->USBUDCAH = (uint32_t) dcd_udca;
LPC_USB->USBDMAIntEn = (DMA_INT_END_OF_XFER_MASK | DMA_INT_NEW_DD_REQUEST_MASK | DMA_INT_ERROR_MASK );
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 );
// clear all stall on control endpoint IN & OUT if any
sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS , 1, 0);
@ -252,10 +311,10 @@ void dcd_controller_set_configuration(uint8_t coreid)
}
//--------------------------------------------------------------------+
// PIPE API
// PIPE CONTROL HELPER
//--------------------------------------------------------------------+
static inline uint16_t length_unit_byte2dword(uint16_t length_in_bytes) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint16_t length_unit_byte2dword(uint16_t length_in_bytes)
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
}
@ -267,7 +326,7 @@ static tusb_error_t pipe_control_write(void const * buffer, uint16_t length)
LPC_USB->USBCtrl = SLAVE_CONTROL_WRITE_ENABLE_MASK; // logical endpoint = 0
LPC_USB->USBTxPLen = length;
for (uint16_t count = 0; count < length_unit_byte2dword(length); count++)
for (uint16_t count = 0; count < length_byte2dword(length); count++)
{
LPC_USB->USBTxData = *((uint32_t *)buffer); // NOTE: cortex M3 have no problem with alignment
buffer += 4;
@ -288,7 +347,7 @@ static tusb_error_t pipe_control_read(void * buffer, uint16_t length)
uint16_t actual_length = min16_of(length, (uint16_t) (LPC_USB->USBRxPLen & SLAVE_RXPLEN_PACKET_LENGTH_MASK) );
uint32_t *p_read_data = (uint32_t*) buffer;
for( uint16_t count=0; count < length_unit_byte2dword(actual_length); count++)
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) )
@ -298,18 +357,12 @@ static tusb_error_t pipe_control_read(void * buffer, uint16_t length)
return TUSB_ERROR_NONE;
}
static inline uint8_t endpoint_address_to_physical_index(uint8_t ep_address) ATTR_ALWAYS_INLINE ATTR_CONST;
static inline uint8_t endpoint_address_to_physical_index(uint8_t ep_address)
{
return (ep_address << 1) + (ep_address & 0x80 ? 1 : 0 );
}
//--------------------------------------------------------------------+
// CONTROL PIPE API
//--------------------------------------------------------------------+
void dcd_pipe_control_stall(uint8_t coreid)
{
ASSERT(false, VOID_RETURN);
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, void * p_buffer, uint16_t length)
@ -327,6 +380,27 @@ tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void *
return TUSB_ERROR_NONE;
}
//--------------------------------------------------------------------+
// 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);
}
// retval UINT8_MAX: invalid
static inline uint8_t dd_find_free(void) ATTR_PURE ATTR_ALWAYS_INLINE;
static inline uint8_t dd_find_free(void)
{
for(uint8_t i=0; i<DCD_QTD_MAX; i++)
{
if (dcd_data.dd[i].used == 0) return i;
}
return UINT8_MAX;
}
//--------------------------------------------------------------------+
// BULK/INTERRUPT/ISO PIPE API
//--------------------------------------------------------------------+
@ -334,38 +408,127 @@ endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const
{
(void) coreid;
return (endpoint_handle_t) { 0 };
endpoint_handle_t const null_handle = { 0 };
uint8_t phy_ep = endpoint_address_to_physical_index( p_endpoint_desc->bEndpointAddress );
// 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 -------------//
endpoint_set_max_packet_size(phy_ep, p_endpoint_desc->wMaxPacketSize.size);
edpt_set_max_packet_size(ep_id, p_endpoint_desc->wMaxPacketSize.size);
//------------- DMA set up -------------//
memclr_(dcd_dd + phy_ep, sizeof(dcd_dma_descriptor_t));
dcd_dd[phy_ep].is_isochronous = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) ? 1 : 0;
dcd_dd[phy_ep].max_packet_size = p_endpoint_desc->wMaxPacketSize.size;
dcd_dd[phy_ep].is_retired = 1; // dd is not active at first
//------------- fixed DD prepare -------------//
uint8_t const dd_idx = dd_find_free();
ASSERT(dd_idx != UINT8_MAX, null_handle);
LPC_USB->USBEpDMAEn = BIT_(phy_ep);
dcd_data.ddat[ep_id] = dd_idx; // fixed this DD to UDCA for this endpoint
dcd_data.class_code[ep_id] = class_code;
sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS+phy_ep, 1, 0); // clear all endpoint status
dcd_dma_descriptor_t* const p_dd = &dcd_data.dd[dd_idx];
memclr_(p_dd, sizeof(dcd_dma_descriptor_t));
p_dd->used = 1;
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)
{
ASSERT(false, false);
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;
}
tusb_error_t dcd_pipe_queue_xfer(endpoint_handle_t edpt_hdl, void * buffer, uint16_t total_bytes)
{ // NOTE for sure the qhd has no dds
ASSERT( !dcd_pipe_is_busy(edpt_hdl), TUSB_ERROR_INTERFACE_IS_BUSY); // endpoint must not in transferring
dcd_dma_descriptor_t* const p_dd = qhd_get_fixed_dd(edpt_hdl.index); // always queue with the fixed DD
dd_xfer_init(p_dd, buffer, total_bytes);
// p_dd->int_on_complete = 0;
p_dd->is_retired = 1;
return TUSB_ERROR_NONE;
}
tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, void * buffer, uint16_t total_bytes, bool int_on_complete)
{
ASSERT_STATUS(TUSB_ERROR_FAILED);
ASSERT( !dcd_pipe_is_busy(edpt_hdl), TUSB_ERROR_INTERFACE_IS_BUSY); // endpoint must not in transferring
dcd_dma_descriptor_t* const p_fixed_dd = qhd_get_fixed_dd(edpt_hdl.index);
if ( p_fixed_dd->buffer_length )
{ // fixed DD is already queued a xfer
//------------- setup new dd -------------//
uint8_t dd_idx = dd_find_free();
ASSERT( dd_idx != UINT8_MAX, TUSB_ERROR_DCD_NOT_ENOUGH_QTD);
dcd_dma_descriptor_t* const p_dd = &dcd_data.dd[ dd_idx ];
memclr_(p_dd, sizeof(dcd_dma_descriptor_t));
dd_xfer_init(p_dd, buffer, total_bytes);
p_dd->used = 1;
p_dd->max_packet_size = p_fixed_dd->max_packet_size;
p_dd->is_isochronous = p_fixed_dd->is_isochronous;
// p_dd->int_on_complete = int_on_complete;
//------------- hook to fixed dd -------------//
p_fixed_dd->next = (uint32_t) p_dd;
p_fixed_dd->is_next_valid = 1;
} else
{ // fixed DD is free
dd_xfer_init(p_fixed_dd, buffer, total_bytes);
// p_fixed_dd->int_on_complete = int_on_complete;
}
p_fixed_dd->is_retired = 0;
dcd_data.udca[edpt_hdl.index] = p_fixed_dd;
LPC_USB->USBEpDMAEn = BIT_(edpt_hdl.index);
if ( edpt_hdl.index % 2 )
{ // endpoint IN
LPC_USB->USBDMARSet = BIT_(edpt_hdl.index);
}
return TUSB_ERROR_NONE;
}

View File

@ -61,13 +61,13 @@ typedef struct
//------------- Word 1 -------------//
uint16_t mode : 2; // either 00 normal or 01 ATLE(auto length extraction)
uint16_t is_next_valid : 1;
uint16_t : 1;
uint16_t used : 1; ///< make use of reserved bit
uint16_t is_isochronous : 1; // is an iso endpoint
uint16_t max_packet_size : 11;
volatile uint16_t buffer_length;
//------------- Word 2 -------------//
volatile uint32_t buffer_start_addr;
volatile uint32_t buffer_addr;
//------------- Word 3 -------------//
volatile uint16_t is_retired : 1; // initialized to zero
@ -77,18 +77,15 @@ typedef struct
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;
// uint16_t int_on_complete : 1; ///< make use of reserved bit
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
} ATTR_ALIGNED(4) dcd_dma_descriptor_t;
#define DCD_MAX_DD 32 // TODO scale with configure
STATIC_ASSERT( sizeof(dcd_dma_descriptor_t) == 16, "size is not correct"); // TODO not support ISO for now
//typedef struct {
// dcd_dma_descriptor_t dd[DCD_MAX_DD];
//
//}dcd_data_t;
//--------------------------------------------------------------------+
// Register Interface
@ -178,17 +175,24 @@ enum {
SIE_DEV_STATUS_RESET_MASK = BIT_(4)
};
//------------- SIE Endpoint Status -------------//
//------------- SIE Select Endpoint Command -------------//
enum {
SIE_ENDPOINT_STATUS_FULL_EMPTY_MASK = BIT_(0), // 0: empty, 1 full. IN endpoint checks empty, OUT endpoint check full
SIE_ENDPOINT_STATUS_STALL_MASK = BIT_(1),
SIE_ENDPOINT_STATUS_SETUP_RECEIVED_MASK = BIT_(2), // clear by SIE_CMDCODE_ENDPOINT_SELECT_CLEAR_INTERRUPT
SIE_ENDPOINT_STATUS_PACKET_OVERWRITTEN_MASK = BIT_(3), // previous packet is overwritten by a SETUP packet
SIE_ENDPOINT_STATUS_NAK_MASK = BIT_(4), // last packet response is NAK (auto clear by an ACK)
SIE_ENDPOINT_STATUS_BUFFER1_FULL_MASK = BIT_(5),
SIE_ENDPOINT_STATUS_BUFFER2_FULL_MASK = BIT_(6)
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)
};
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;
//------------- DMA Descriptor Status -------------//
enum {
DD_STATUS_NOT_SERVICED = 0,