summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/class/cdc/cdc_device.c7
-rw-r--r--src/class/hid/hid_device.c9
-rw-r--r--src/class/msc/msc.h4
-rw-r--r--src/class/msc/msc_device.c83
-rw-r--r--src/class/msc/msc_device.h43
-rw-r--r--src/device/dcd.h27
-rw-r--r--src/device/usbd.c82
-rw-r--r--src/device/usbd_pvt.h15
-rw-r--r--src/osal/osal_freertos.h1
-rw-r--r--src/osal/osal_none.h103
-rw-r--r--src/portable/microchip/samd21/dcd.c341
-rw-r--r--src/portable/microchip/samd21/hal.c82
-rw-r--r--src/portable/microchip/samd51/dcd.c360
-rw-r--r--src/portable/microchip/samd51/hal.c88
-rw-r--r--src/portable/nordic/nrf5x/dcd_nrf5x.c10
-rw-r--r--src/tusb_option.h2
16 files changed, 1050 insertions, 207 deletions
diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c
index a6f1f1fbb..f3d4622f8 100644
--- a/src/class/cdc/cdc_device.c
+++ b/src/class/cdc/cdc_device.c
@@ -289,8 +289,6 @@ tusb_error_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface
tusb_error_t cdcd_control_request_st(uint8_t rhport, tusb_control_request_t const * p_request)
{
- OSAL_SUBTASK_BEGIN
-
//------------- Class Specific Request -------------//
if (p_request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
@@ -301,7 +299,7 @@ tusb_error_t cdcd_control_request_st(uint8_t rhport, tusb_control_request_t cons
if ( (CDC_REQUEST_GET_LINE_CODING == p_request->bRequest) || (CDC_REQUEST_SET_LINE_CODING == p_request->bRequest) )
{
uint16_t len = tu_min16(sizeof(cdc_line_coding_t), p_request->wLength);
- usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, &p_cdc->line_coding, len);
+ usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, (uint8_t*) &p_cdc->line_coding, len);
// Invoke callback
if (CDC_REQUEST_SET_LINE_CODING == p_request->bRequest)
@@ -327,8 +325,7 @@ tusb_error_t cdcd_control_request_st(uint8_t rhport, tusb_control_request_t cons
{
dcd_control_stall(rhport); // stall unsupported request
}
-
- OSAL_SUBTASK_END
+ return TUSB_ERROR_NONE;
}
tusb_error_t cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes)
diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c
index d8696f137..3e74950e6 100644
--- a/src/class/hid/hid_device.c
+++ b/src/class/hid/hid_device.c
@@ -407,8 +407,6 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons
hidd_interface_t* p_hid = get_interface_by_itfnum( (uint8_t) p_request->wIndex );
TU_ASSERT(p_hid, TUSB_ERROR_FAILED);
- OSAL_SUBTASK_BEGIN
-
//------------- STD Request -------------//
if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD)
{
@@ -419,7 +417,7 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons
if (p_request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT)
{
// use device control buffer
- STASK_ASSERT ( p_hid->desc_len <= CFG_TUD_CTRL_BUFSIZE );
+ TU_ASSERT ( p_hid->desc_len <= CFG_TUD_CTRL_BUFSIZE );
memcpy(_usbd_ctrl_buf, p_hid->desc_report, p_hid->desc_len);
usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, _usbd_ctrl_buf, p_hid->desc_len);
@@ -447,7 +445,7 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons
xferlen = p_request->wLength;
}
- STASK_ASSERT( xferlen > 0 );
+ TU_ASSERT( xferlen > 0 );
usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, p_hid->report_buf, xferlen);
}
else if ( HID_REQ_CONTROL_SET_REPORT == p_request->bRequest )
@@ -492,8 +490,7 @@ tusb_error_t hidd_control_request_st(uint8_t rhport, tusb_control_request_t cons
{
dcd_control_stall(rhport);
}
-
- OSAL_SUBTASK_END
+ return TUSB_ERROR_NONE;
}
tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes)
diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h
index 59df6bed6..a0abc2501 100644
--- a/src/class/msc/msc.h
+++ b/src/class/msc/msc.h
@@ -279,11 +279,13 @@ typedef struct ATTR_PACKED
TU_VERIFY_STATIC( sizeof(scsi_mode_sense6_t) == 6, "size is not correct");
+// This is only a Mode parameter header(6).
typedef struct ATTR_PACKED
{
uint8_t data_len;
uint8_t medium_type;
- uint8_t device_specific_para;
+ bool write_protected : 1;
+ uint8_t reserved : 7;
uint8_t block_descriptor_len;
} scsi_mode_sense6_resp_t;
diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c
index 5a047b016..aa9ebbbc9 100644
--- a/src/class/msc/msc_device.c
+++ b/src/class/msc/msc_device.c
@@ -59,31 +59,7 @@ enum
MSC_STAGE_STATUS
};
-typedef struct {
- CFG_TUSB_MEM_ALIGN msc_cbw_t cbw;
-
-//#if defined (__ICCARM__) && (CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13UXX)
-// uint8_t padding1[64-sizeof(msc_cbw_t)]; // IAR cannot align struct's member
-//#endif
-
- CFG_TUSB_MEM_ALIGN msc_csw_t csw;
-
- uint8_t itf_num;
- uint8_t ep_in;
- uint8_t ep_out;
-
- // Bulk Only Transfer (BOT) Protocol
- uint8_t stage;
- uint32_t total_len;
- uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage
-
- // Sense Response Data
- uint8_t sense_key;
- uint8_t add_sense_code;
- uint8_t add_sense_qualifier;
-}mscd_interface_t;
-
-CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static mscd_interface_t _mscd_itf;
+CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN mscd_interface_t _mscd_itf;
CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_BUFSIZE];
//--------------------------------------------------------------------+
@@ -172,8 +148,6 @@ tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_desc_itf,
tusb_error_t mscd_control_request_st(uint8_t rhport, tusb_control_request_t const * p_request)
{
- OSAL_SUBTASK_BEGIN
-
TU_ASSERT(p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS, TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT);
if(MSC_REQ_RESET == p_request->bRequest)
@@ -189,9 +163,18 @@ tusb_error_t mscd_control_request_st(uint8_t rhport, tusb_control_request_t cons
{
dcd_control_stall(rhport); // stall unsupported request
}
+ return TUSB_ERROR_NONE;
+}
- OSAL_SUBTASK_END
+// For backwards compatibility we support static block counts.
+#if defined(CFG_TUD_MSC_BLOCK_NUM) && defined(CFG_TUD_MSC_BLOCK_SZ)
+ATTR_WEAK bool tud_lun_capacity_cb(uint8_t lun, uint32_t* last_valid_sector, uint16_t* block_size) {
+ (void) lun;
+ *last_valid_sector = CFG_TUD_MSC_BLOCK_NUM-1;
+ *block_size = CFG_TUD_MSC_BLOCK_SZ;
+ return true;
}
+#endif
// return length of response (copied to buffer), -1 if it is not an built-in commands
int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t bufsize)
@@ -202,11 +185,13 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
{
case SCSI_CMD_READ_CAPACITY_10:
{
- scsi_read_capacity10_resp_t read_capa10 =
- {
- .last_lba = ENDIAN_BE(CFG_TUD_MSC_BLOCK_NUM-1), // read capacity
- .block_size = ENDIAN_BE(CFG_TUD_MSC_BLOCK_SZ)
- };
+ scsi_read_capacity10_resp_t read_capa10;
+
+ uint32_t last_valid_sector;
+ uint16_t block_size;
+ tud_lun_capacity_cb(p_cbw->lun, &last_valid_sector, &block_size);
+ read_capa10.last_lba = ENDIAN_BE(last_valid_sector); // read capacity
+ read_capa10.block_size = ENDIAN_BE(block_size);
ret = sizeof(read_capa10);
memcpy(buffer, &read_capa10, ret);
@@ -218,11 +203,17 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
scsi_read_format_capacity_data_t read_fmt_capa =
{
.list_length = 8,
- .block_num = ENDIAN_BE(CFG_TUD_MSC_BLOCK_NUM), // write capacity
+ .block_num = 0,
.descriptor_type = 2, // formatted media
- .block_size_u16 = ENDIAN_BE16(CFG_TUD_MSC_BLOCK_SZ)
+ .block_size_u16 = 0
};
+ uint32_t last_valid_sector;
+ uint16_t block_size;
+ tud_lun_capacity_cb(p_cbw->lun, &last_valid_sector, &block_size);
+ read_fmt_capa.block_num = ENDIAN_BE(last_valid_sector+1);
+ read_fmt_capa.block_size_u16 = ENDIAN_BE16(block_size);
+
ret = sizeof(read_fmt_capa);
memcpy(buffer, &read_fmt_capa, ret);
}
@@ -251,13 +242,21 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
case SCSI_CMD_MODE_SENSE_6:
{
- scsi_mode_sense6_resp_t const mode_resp = {
- .data_len = 3,
- .medium_type = 0,
- .device_specific_para = 0,
- .block_descriptor_len = 0 // no block descriptor are included
+ scsi_mode_sense6_resp_t mode_resp =
+ {
+ .data_len = 3,
+ .medium_type = 0,
+ .write_protected = false,
+ .reserved = 0,
+ .block_descriptor_len = 0 // no block descriptor are included
};
+ bool writable = true;
+ if (tud_msc_is_writable_cb) {
+ writable = tud_msc_is_writable_cb(p_cbw->lun);
+ }
+ mode_resp.write_protected = !writable;
+
ret = sizeof(mode_resp);
memcpy(buffer, &mode_resp, ret);
}
@@ -291,7 +290,7 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
return ret;
}
-tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes)
+tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, uint8_t event, uint32_t xferred_bytes)
{
mscd_interface_t* p_msc = &_mscd_itf;
msc_cbw_t const * p_cbw = &p_msc->cbw;
@@ -425,7 +424,7 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u
}else
{
// Application consume less than what we got (including zero)
- if ( nbytes < xferred_bytes )
+ if ( nbytes < (int32_t) xferred_bytes )
{
if ( nbytes > 0 )
{
diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h
index 8403dfed9..92ab4dde0 100644
--- a/src/class/msc/msc_device.h
+++ b/src/class/msc/msc_device.h
@@ -55,14 +55,6 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct");
#error MSC Device: Incorrect setting of MAX LUN
#endif
-#ifndef CFG_TUD_MSC_BLOCK_NUM
- #error CFG_TUD_MSC_BLOCK_NUM must be defined
-#endif
-
-#ifndef CFG_TUD_MSC_BLOCK_SZ
- #error CFG_TUD_MSC_BLOCK_SZ must be defined
-#endif
-
#ifndef CFG_TUD_MSC_BUFSIZE
#error CFG_TUD_MSC_BUFSIZE must be defined, value of CFG_TUD_MSC_BLOCK_SZ should work well, the more the better
#endif
@@ -89,6 +81,32 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct");
extern "C" {
#endif
+typedef struct {
+ CFG_TUSB_MEM_ALIGN msc_cbw_t cbw;
+
+//#if defined (__ICCARM__) && (CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13UXX)
+// uint8_t padding1[64-sizeof(msc_cbw_t)]; // IAR cannot align struct's member
+//#endif
+
+ CFG_TUSB_MEM_ALIGN msc_csw_t csw;
+
+ uint8_t itf_num;
+ uint8_t ep_in;
+ uint8_t ep_out;
+
+ // Bulk Only Transfer (BOT) Protocol
+ uint8_t stage;
+ uint32_t total_len;
+ uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage
+
+ // Sense Response Data
+ uint8_t sense_key;
+ uint8_t add_sense_code;
+ uint8_t add_sense_qualifier;
+}mscd_interface_t;
+
+extern mscd_interface_t _mscd_itf;
+
/** \addtogroup ClassDriver_MSC
* @{
* \defgroup MSC_Device Device
@@ -138,7 +156,7 @@ int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buf
* \retval negative Indicate error writing disk I/O. Tinyusb will \b STALL the corresponding
* endpoint and return failed status in command status wrapper phase.
*/
-int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize);
+int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize);
/**
* Callback invoked when received an SCSI command not in built-in list below.
@@ -164,6 +182,12 @@ ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun);
ATTR_WEAK void tud_msc_write10_complete_cb(uint8_t lun);
ATTR_WEAK void tud_msc_scsi_complete_cb(uint8_t lun, uint8_t const scsi_cmd[16]);
+// Hook to make a mass storage device read-only.
+ATTR_WEAK bool tud_msc_is_writable_cb(uint8_t lun);
+
+// Override for dynamic LUN sizes.
+ATTR_WEAK bool tud_lun_capacity_cb(uint8_t lun, uint32_t* last_valid_sector, uint16_t* block_size);
+
/** @} */
/** @} */
@@ -185,4 +209,3 @@ void mscd_reset(uint8_t rhport);
#endif
#endif /* _TUSB_MSC_DEVICE_H_ */
-
diff --git a/src/device/dcd.h b/src/device/dcd.h
index 87837df20..c1715a5b7 100644
--- a/src/device/dcd.h
+++ b/src/device/dcd.h
@@ -113,32 +113,13 @@ void dcd_disconnect (uint8_t rhport) ATTR_WEAK;
void dcd_event_handler(dcd_event_t const * event, bool in_isr);
// helper to send bus signal event
-static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr)
-{
- dcd_event_t event = { .rhport = 0, .event_id = eid, };
- dcd_event_handler(&event, in_isr);
-}
+void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr);
// helper to send setup received
-static inline void dcd_event_setup_recieved(uint8_t rhport, uint8_t const * setup, bool in_isr)
-{
- dcd_event_t event = { .rhport = 0, .event_id = DCD_EVENT_SETUP_RECEIVED };
- memcpy(&event.setup_received, setup, 8);
-
- dcd_event_handler(&event, true);
-}
+void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr);
// helper to send transfer complete event
-static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
-{
- dcd_event_t event = { .rhport = 0, .event_id = DCD_EVENT_XFER_COMPLETE };
-
- event.xfer_complete.ep_addr = ep_addr;
- event.xfer_complete.len = xferred_bytes;
- event.xfer_complete.result = result;
-
- dcd_event_handler(&event, in_isr);
-}
+void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr);
/*------------------------------------------------------------------*/
@@ -167,7 +148,7 @@ static inline bool dcd_control_status(uint8_t rhport, uint8_t dir)
static inline void dcd_control_stall(uint8_t rhport)
{
- dcd_edpt_stall(rhport, 0);
+ dcd_edpt_stall(rhport, 0 | TUSB_DIR_IN_MASK);
}
#ifdef __cplusplus
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 1c2fa5d5d..8155b585f 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -239,25 +239,25 @@ void usbd_task( void* param)
OSAL_TASK_END
}
+extern uint32_t setup_count;
+
static tusb_error_t usbd_main_st(void)
{
- static dcd_event_t event;
-
- OSAL_SUBTASK_BEGIN
-
+ dcd_event_t event;
+ tusb_error_t err = TUSB_ERROR_NONE;
// Loop until there is no more events in the queue
- while (1)
+ while (_usbd_q->count > 0)
{
- uint32_t err;
-
- err = TUSB_ERROR_NONE;
tu_memclr(&event, sizeof(dcd_event_t));
- osal_queue_receive(_usbd_q, &event, OSAL_TIMEOUT_WAIT_FOREVER, &err);
+ err = osal_queue_receive(_usbd_q, &event);
+ if (err != TUSB_ERROR_NONE) {
+ break;
+ }
if ( DCD_EVENT_SETUP_RECEIVED == event.event_id )
{
- STASK_INVOKE( proc_control_request_st(event.rhport, &event.setup_received), err );
+ proc_control_request_st(event.rhport, &event.setup_received);
}
else if (DCD_EVENT_XFER_COMPLETE == event.event_id)
{
@@ -267,7 +267,7 @@ static tusb_error_t usbd_main_st(void)
if (drv_id < USBD_CLASS_DRIVER_COUNT)
{
- usbd_class_drivers[drv_id].xfer_cb( event.rhport, ep_addr, (tusb_event_t) event.xfer_complete.result, event.xfer_complete.len);
+ usbd_class_drivers[drv_id].xfer_cb( event.rhport, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
}
}
else if (DCD_EVENT_BUS_RESET == event.event_id)
@@ -304,7 +304,7 @@ static tusb_error_t usbd_main_st(void)
}
}
- OSAL_SUBTASK_END
+ return err;
}
//--------------------------------------------------------------------+
@@ -312,10 +312,7 @@ static tusb_error_t usbd_main_st(void)
//--------------------------------------------------------------------+
static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request_t const * const p_request)
{
- OSAL_SUBTASK_BEGIN
-
- ATTR_UNUSED tusb_error_t error;
- error = TUSB_ERROR_NONE;
+ tusb_error_t error = TUSB_ERROR_NONE;
//------------- Standard Request e.g in enumeration -------------//
if( TUSB_REQ_RCPT_DEVICE == p_request->bmRequestType_bit.recipient &&
@@ -326,9 +323,10 @@ static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request
uint8_t const * buffer = NULL;
uint16_t const len = get_descriptor(rhport, p_request, &buffer);
+
if ( len )
{
- STASK_ASSERT( len <= CFG_TUD_CTRL_BUFSIZE );
+ TU_ASSERT( len <= CFG_TUD_CTRL_BUFSIZE );
memcpy(_usbd_ctrl_buf, buffer, len);
usbd_control_xfer_st(rhport, p_request->bmRequestType_bit.direction, _usbd_ctrl_buf, len);
}else
@@ -365,7 +363,7 @@ static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request
{
if (_usbd_dev.itf2drv[ tu_u16_low(p_request->wIndex) ] < USBD_CLASS_DRIVER_COUNT)
{
- STASK_INVOKE( usbd_class_drivers[ _usbd_dev.itf2drv[ tu_u16_low(p_request->wIndex) ] ].control_req_st(rhport, p_request), error );
+ error = usbd_class_drivers[ _usbd_dev.itf2drv[ tu_u16_low(p_request->wIndex) ] ].control_req_st(rhport, p_request);
}else
{
dcd_control_stall(rhport); // Stall unsupported request
@@ -406,8 +404,10 @@ static tusb_error_t proc_control_request_st(uint8_t rhport, tusb_control_request
{
dcd_control_stall(rhport); // Stall unsupported request
}
-
- OSAL_SUBTASK_END
+ if (error != TUSB_ERROR_NONE) {
+ dcd_control_stall(rhport); // Stall errored requests
+ }
+ return error;
}
// Process Set Configure Request
@@ -548,8 +548,6 @@ static void mark_interface_endpoint(uint8_t const* p_desc, uint16_t desc_len, ui
//--------------------------------------------------------------------+
void dcd_event_handler(dcd_event_t const * event, bool in_isr)
{
- uint8_t const rhport = event->rhport;
-
switch (event->event_id)
{
case DCD_EVENT_BUS_RESET:
@@ -590,9 +588,49 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
}
}
+void dcd_event_handler(dcd_event_t const * event, bool in_isr);
+
+// helper to send bus signal event
+void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr)
+{
+ dcd_event_t event = { .rhport = 0, .event_id = eid, };
+ dcd_event_handler(&event, in_isr);
+}
+
+// helper to send setup received
+void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr)
+{
+ dcd_event_t event = { .rhport = 0, .event_id = DCD_EVENT_SETUP_RECEIVED };
+ memcpy(&event.setup_received, setup, 8);
+
+ dcd_event_handler(&event, true);
+}
+
+// helper to send transfer complete event
+void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr)
+{
+ dcd_event_t event = { .rhport = 0, .event_id = DCD_EVENT_XFER_COMPLETE };
+
+ event.xfer_complete.ep_addr = ep_addr;
+ event.xfer_complete.len = xferred_bytes;
+ event.xfer_complete.result = result;
+
+ dcd_event_handler(&event, in_isr);
+}
+
//--------------------------------------------------------------------+
// Helper
//--------------------------------------------------------------------+
+uint32_t usbd_control_xfer_st(uint8_t _rhport, uint8_t _dir, uint8_t* _buffer, uint16_t _len) {
+ uint32_t err = TUSB_ERROR_NONE;
+ if (_len) {
+ dcd_control_xfer(_rhport, _dir, (uint8_t*) _buffer, _len);
+ }
+
+ dcd_control_status(_rhport, _dir);
+ return err;
+}
+
tusb_error_t usbd_open_edpt_pair(uint8_t rhport, tusb_desc_endpoint_t const* p_desc_ep, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in)
{
for(int i=0; i<2; i++)
diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h
index 0b6b56d7d..ecb71f771 100644
--- a/src/device/usbd_pvt.h
+++ b/src/device/usbd_pvt.h
@@ -64,20 +64,7 @@ void usbd_task (void* param);
// helper to parse an pair of In and Out endpoint descriptors. They must be consecutive
tusb_error_t usbd_open_edpt_pair(uint8_t rhport, tusb_desc_endpoint_t const* p_desc_ep, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in);
-// Carry out Data and Status stage of control transfer
-// Must be call in a subtask (_st) function
-#define usbd_control_xfer_st(_rhport, _dir, _buffer, _len) \
- do { \
- if (_len) { \
- uint32_t err; \
- dcd_control_xfer(_rhport, _dir, (uint8_t*) _buffer, _len); \
- osal_semaphore_wait( _usbd_ctrl_sem, OSAL_TIMEOUT_CONTROL_XFER, &err ); \
- STASK_ASSERT_ERR( err ); \
- } \
- dcd_control_status(_rhport, _dir); \
- /* No need to wait for status phase to complete */ \
- }while(0)
-
+uint32_t usbd_control_xfer_st(uint8_t _rhport, uint8_t _dir, uint8_t* _buffer, uint16_t _len);
/*------------------------------------------------------------------*/
/* Other Helpers
diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h
index ae988ec1f..f29759225 100644
--- a/src/osal/osal_freertos.h
+++ b/src/osal/osal_freertos.h
@@ -183,4 +183,3 @@ static inline void osal_queue_reset(osal_queue_t const queue_hdl)
/** @} */
/** @} */
-
diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h
index 796ddc15f..6e67c8ea6 100644
--- a/src/osal/osal_none.h
+++ b/src/osal/osal_none.h
@@ -60,8 +60,6 @@
//
// OSAL_TASK_LOOP_ENG
// }
-//
-// NOTE: no switch statement is allowed in Task and subtask
//--------------------------------------------------------------------+
#define OSAL_TASK_DEF(_name, _str, _func, _prio, _stack_sz) osal_task_def_t _name;
@@ -73,52 +71,8 @@ static inline bool osal_task_create(osal_task_def_t* taskdef)
return true;
}
-#define TASK_RESTART \
- _state = 0
-
-#define osal_task_delay(_msec) \
- do { \
- _timeout = tusb_hal_millis(); \
- _state = __LINE__; case __LINE__: \
- if ( _timeout + (_msec) > tusb_hal_millis() ) \
- return TUSB_ERROR_OSAL_WAITING; \
- }while(0)
-
-//--------------------------------------------------------------------+
-// SUBTASK (a sub function that uses OS blocking services & called by a task
-//--------------------------------------------------------------------+
-#define OSAL_SUBTASK_BEGIN \
- static uint16_t _state = 0; \
- ATTR_UNUSED static uint32_t _timeout = 0; \
- (void) _timeout; \
- switch(_state) { \
- case 0: {
-
-#define OSAL_SUBTASK_END \
- default: TASK_RESTART; break; \
- }} \
- return TUSB_ERROR_NONE;
-
-#define STASK_INVOKE(_subtask, _status) \
- do { \
- _state = __LINE__; case __LINE__: \
- { \
- (_status) = _subtask; /* invoke sub task */ \
- if (TUSB_ERROR_OSAL_WAITING == (_status)) return TUSB_ERROR_OSAL_WAITING; \
- } \
- }while(0)
-
-//------------- Sub Task Assert -------------//
-#define STASK_RETURN(error) do { TASK_RESTART; return error; } while(0)
-
-#define STASK_ASSERT_ERR(_err) TU_VERIFY_ERR_HDLR(_err, TU_BREAKPOINT(); TASK_RESTART, TUSB_ERROR_FAILED)
-#define STASK_ASSERT_ERR_HDLR(_err, _func) TU_VERIFY_ERR_HDLR(_err, TU_BREAKPOINT(); _func; TASK_RESTART, TUSB_ERROR_FAILED )
-
-#define STASK_ASSERT(_cond) TU_VERIFY_HDLR(_cond, TU_BREAKPOINT(); TASK_RESTART, TUSB_ERROR_FAILED)
-#define STASK_ASSERT_HDLR(_cond, _func) TU_VERIFY_HDLR(_cond, TU_BREAKPOINT(); _func; TASK_RESTART, TUSB_ERROR_FAILED)
-
//--------------------------------------------------------------------+
-// Semaphore API
+// Binary Semaphore API
//--------------------------------------------------------------------+
typedef struct
{
@@ -135,7 +89,6 @@ static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semde
static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
{
- (void) in_isr;
sem_hdl->count++;
return true;
}
@@ -145,22 +98,21 @@ static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl)
sem_hdl->count = 0;
}
-#define osal_semaphore_wait(_sem_hdl, _msec, _err) \
- do { \
- _timeout = tusb_hal_millis(); \
- _state = __LINE__; case __LINE__: \
- if( (_sem_hdl)->count == 0 ) { \
- if ( ((_msec) != OSAL_TIMEOUT_WAIT_FOREVER) && (_timeout + (_msec) <= tusb_hal_millis()) ) \
- *(_err) = TUSB_ERROR_OSAL_TIMEOUT; \
- else \
- return TUSB_ERROR_OSAL_WAITING; \
- } else{ \
- /* Enter critical ? */ \
- (_sem_hdl)->count--; \
- /* Exit critical ? */ \
- *(_err) = TUSB_ERROR_NONE; \
- } \
- }while(0)
+static inline tusb_error_t osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) {
+ (void) msec;
+ while (true) {
+ while (sem_hdl->count == 0) {
+ }
+ // tusb_hal_int_disable_all();
+ if (sem_hdl->count == 0) {
+ sem_hdl->count--;
+ // tusb_hal_int_enable_all();
+ break;
+ }
+ // tusb_hal_int_enable_all();
+ }
+ return TUSB_ERROR_NONE;
+}
//--------------------------------------------------------------------+
// MUTEX API
@@ -218,22 +170,13 @@ static inline void osal_queue_reset(osal_queue_t const queue_hdl)
queue_hdl->count = queue_hdl->rd_idx = queue_hdl->wr_idx = 0;
}
-#define osal_queue_receive(_q_hdl, p_data, _msec, _err) \
- do { \
- _timeout = tusb_hal_millis(); \
- _state = __LINE__; case __LINE__: \
- if( (_q_hdl)->count == 0 ) { \
- if ( ((_msec) != OSAL_TIMEOUT_WAIT_FOREVER) && ( _timeout + (_msec) <= tusb_hal_millis()) ) \
- *(_err) = TUSB_ERROR_OSAL_TIMEOUT; \
- else \
- return TUSB_ERROR_OSAL_WAITING; \
- } else{ \
- /* Enter critical ? */ \
- tu_fifo_read(_q_hdl, p_data); \
- /* Exit critical ? */ \
- *(_err) = TUSB_ERROR_NONE; \
- } \
- }while(0)
+static inline tusb_error_t osal_queue_receive(osal_queue_t const queue_hdl, void* data) {
+ if (!tu_fifo_read(queue_hdl, data)) {
+ return TUSB_ERROR_OSAL_WAITING;
+ }
+ return TUSB_ERROR_NONE;
+}
+
#ifdef __cplusplus
}
diff --git a/src/portable/microchip/samd21/dcd.c b/src/portable/microchip/samd21/dcd.c
new file mode 100644
index 000000000..c9e88ad17
--- /dev/null
+++ b/src/portable/microchip/samd21/dcd.c
@@ -0,0 +1,341 @@
+/**************************************************************************/
+/*!
+ @file dcd_nrf5x.c
+ @author hathach
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Scott Shawcroft for Adafruit Industries
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#include "tusb_option.h"
+
+#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMD51
+
+#include "device/dcd.h"
+
+#include "device/usbd.h"
+#include "device/usbd_pvt.h" // to use defer function helper
+
+#include "class/msc/msc_device.h"
+
+#include "sam.h"
+
+/*------------------------------------------------------------------*/
+/* MACRO TYPEDEF CONSTANT ENUM
+ *------------------------------------------------------------------*/
+enum
+{
+ // Max allowed by USB specs
+ MAX_PACKET_SIZE = 64,
+};
+
+UsbDeviceDescBank sram_registers[8][2];
+ATTR_ALIGNED(4) uint8_t control_out_buffer[64];
+ATTR_ALIGNED(4) uint8_t control_in_buffer[64];
+
+volatile uint32_t setup_count = 0;
+
+// Setup the control endpoint 0.
+static void bus_reset(void) {
+ // Max size of packets is 64 bytes.
+ UsbDeviceDescBank* bank_out = &sram_registers[0][TUSB_DIR_OUT];
+ bank_out->PCKSIZE.bit.SIZE = 0x3;
+ UsbDeviceDescBank* bank_in = &sram_registers[0][TUSB_DIR_IN];
+ bank_in->PCKSIZE.bit.SIZE = 0x3;
+
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[0];
+ ep->EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(0x1) | USB_DEVICE_EPCFG_EPTYPE1(0x1);
+ ep->EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0 | USB_DEVICE_EPINTENSET_TRCPT1 | USB_DEVICE_EPINTENSET_RXSTP;
+
+ dcd_edpt_xfer(0, 0, control_out_buffer, 64);
+ setup_count = 0;
+}
+
+
+/*------------------------------------------------------------------*/
+/* Controller API
+ *------------------------------------------------------------------*/
+bool dcd_init (uint8_t rhport)
+{
+ (void) rhport;
+ USB->DEVICE.DESCADD.reg = (uint32_t) &sram_registers;
+ USB->DEVICE.CTRLB.reg = USB_DEVICE_CTRLB_SPDCONF_FS;
+ USB->DEVICE.CTRLA.reg = USB_CTRLA_MODE_DEVICE | USB_CTRLA_ENABLE;
+ USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SOF | USB_DEVICE_INTENSET_EORST;
+
+ return true;
+}
+
+void dcd_connect (uint8_t rhport)
+{
+
+}
+void dcd_disconnect (uint8_t rhport)
+{
+
+}
+
+void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
+{
+ (void) rhport;
+ dcd_edpt_xfer (0, TUSB_DIR_IN_MASK, NULL, 0);
+ // Wait for EP0 to finish before switching the address.
+ while (USB->DEVICE.DeviceEndpoint[0].EPSTATUS.bit.BK1RDY == 1) {}
+ USB->DEVICE.DADD.reg = USB_DEVICE_DADD_DADD(dev_addr) | USB_DEVICE_DADD_ADDEN;
+}
+
+void dcd_set_config (uint8_t rhport, uint8_t config_num)
+{
+ (void) rhport;
+ (void) config_num;
+ // Nothing to do
+}
+
+/*------------------------------------------------------------------*/
+/* Control
+ *------------------------------------------------------------------*/
+
+bool dcd_control_xfer (uint8_t rhport, uint8_t dir, uint8_t * buffer, uint16_t length)
+{
+ (void) rhport;
+ uint8_t ep_addr = 0;
+ if (dir == TUSB_DIR_IN) {
+ ep_addr |= TUSB_DIR_IN_MASK;
+ }
+
+ return dcd_edpt_xfer (rhport, ep_addr, buffer, length);
+}
+
+bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
+{
+ (void) rhport;
+
+ uint8_t const epnum = edpt_number(desc_edpt->bEndpointAddress);
+ uint8_t const dir = edpt_dir(desc_edpt->bEndpointAddress);
+
+ UsbDeviceDescBank* bank = &sram_registers[epnum][dir];
+ uint32_t size_value = 0;
+ while (size_value < 7) {
+ if (1 << (size_value + 3) == desc_edpt->wMaxPacketSize.size) {
+ break;
+ }
+ size_value++;
+ }
+ bank->PCKSIZE.bit.SIZE = size_value;
+
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ if ( dir == TUSB_DIR_OUT )
+ {
+ ep->EPCFG.bit.EPTYPE0 = desc_edpt->bmAttributes.xfer + 1;
+ ep->EPINTENSET.bit.TRCPT0 = true;
+ }else
+ {
+ ep->EPCFG.bit.EPTYPE1 = desc_edpt->bmAttributes.xfer + 1;
+ ep->EPINTENSET.bit.TRCPT1 = true;
+ }
+ __ISB(); __DSB();
+
+ return true;
+}
+
+bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
+{
+ (void) rhport;
+
+ uint8_t const epnum = edpt_number(ep_addr);
+ uint8_t const dir = edpt_dir(ep_addr);
+
+ UsbDeviceDescBank* bank = &sram_registers[epnum][dir];
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ bank->ADDR.reg = (uint32_t) buffer;
+ if ( dir == TUSB_DIR_OUT )
+ {
+ bank->PCKSIZE.bit.MULTI_PACKET_SIZE = total_bytes;
+ bank->PCKSIZE.bit.BYTE_COUNT = 0;
+ ep->EPSTATUSCLR.reg |= USB_DEVICE_EPSTATUSCLR_BK0RDY;
+ ep->EPINTFLAG.reg |= USB_DEVICE_EPINTFLAG_TRFAIL0;
+ } else
+ {
+ bank->PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
+ bank->PCKSIZE.bit.BYTE_COUNT = total_bytes;
+ // bank->PCKSIZE.bit.AUTO_ZLP = 1;
+ ep->EPSTATUSSET.reg |= USB_DEVICE_EPSTATUSSET_BK1RDY;
+ ep->EPINTFLAG.reg |= USB_DEVICE_EPINTFLAG_TRFAIL1;
+ }
+
+ return true;
+}
+
+bool dcd_edpt_stalled (uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+
+ // control is never got halted
+ if ( ep_addr == 0 ) {
+ return false;
+ }
+
+ uint8_t const epnum = edpt_number(ep_addr);
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+ return (edpt_dir(ep_addr) == TUSB_DIR_IN ) ? ep->EPINTFLAG.bit.STALL1 : ep->EPINTFLAG.bit.STALL0;
+}
+
+void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+
+ uint8_t const epnum = edpt_number(ep_addr);
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ if (edpt_dir(ep_addr) == TUSB_DIR_IN) {
+ ep->EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1;
+ } else {
+ ep->EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0;
+ }
+
+ __ISB(); __DSB();
+}
+
+void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+
+ uint8_t const epnum = edpt_number(ep_addr);
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ if (edpt_dir(ep_addr) == TUSB_DIR_IN) {
+ ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1;
+ } else {
+ ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0;
+ }
+}
+
+bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+
+ // USBD shouldn't check control endpoint state
+ if ( 0 == ep_addr ) return false;
+
+ uint8_t const epnum = edpt_number(ep_addr);
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ if (edpt_dir(ep_addr) == TUSB_DIR_IN) {
+ return ep->EPINTFLAG.bit.TRCPT1 == 0 && ep->EPSTATUS.bit.BK1RDY == 1;
+ }
+ return ep->EPINTFLAG.bit.TRCPT0 == 0 && ep->EPSTATUS.bit.BK0RDY == 1;
+}
+
+/*------------------------------------------------------------------*/
+
+static bool maybe_handle_setup_packet(void) {
+ if (USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.RXSTP)
+ {
+ USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP;
+
+ // This copies the data elsewhere so we can reuse the buffer.
+ dcd_event_setup_received(0, (uint8_t*) sram_registers[0][0].ADDR.reg, true);
+ dcd_edpt_xfer(0, 0, control_out_buffer, 64);
+ setup_count += 1;
+ return true;
+ }
+ return false;
+}
+
+void maybe_transfer_complete(void) {
+ uint32_t epints = USB->DEVICE.EPINTSMRY.reg;
+ for (uint8_t epnum = 0; epnum < USB_EPT_NUM; epnum++) {
+ if ((epints & (1 << epnum)) == 0) {
+ continue;
+ }
+
+ if (maybe_handle_setup_packet()) {
+ continue;
+ }
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ uint32_t epintflag = ep->EPINTFLAG.reg;
+
+ // Handle IN completions
+ if ((epintflag & USB_DEVICE_EPINTFLAG_TRCPT1) != 0) {
+ ep->EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
+
+ UsbDeviceDescBank* bank = &sram_registers[epnum][TUSB_DIR_IN];
+ uint16_t total_transfer_size = bank->PCKSIZE.bit.BYTE_COUNT;
+
+ uint8_t ep_addr = epnum | TUSB_DIR_IN_MASK;
+ dcd_event_xfer_complete(0, ep_addr, total_transfer_size, DCD_XFER_SUCCESS, true);
+ }
+
+ // Handle OUT completions
+ if ((epintflag & USB_DEVICE_EPINTFLAG_TRCPT0) != 0) {
+ ep->EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
+
+ UsbDeviceDescBank* bank = &sram_registers[epnum][TUSB_DIR_OUT];
+ uint16_t total_transfer_size = bank->PCKSIZE.bit.BYTE_COUNT;
+
+ uint8_t ep_addr = epnum;
+ dcd_event_xfer_complete(0, ep_addr, total_transfer_size, DCD_XFER_SUCCESS, true);
+ if (epnum == 0) {
+ dcd_edpt_xfer(0, 0, control_out_buffer, 64);
+ }
+ }
+ }
+}
+
+void USB_Handler(void) {
+ uint32_t int_status = USB->DEVICE.INTFLAG.reg;
+
+ /*------------- Interrupt Processing -------------*/
+ if ( int_status & USB_DEVICE_INTFLAG_EORST )
+ {
+ USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTENCLR_EORST;
+ bus_reset();
+ dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
+ }
+
+ if ( int_status & USB_DEVICE_INTFLAG_SOF )
+ {
+ USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF;
+ dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
+ }
+
+ // Setup packet received.
+ maybe_handle_setup_packet();
+
+ // Handle complete transfer
+ maybe_transfer_complete();
+}
+
+#endif
diff --git a/src/portable/microchip/samd21/hal.c b/src/portable/microchip/samd21/hal.c
new file mode 100644
index 000000000..524840be2
--- /dev/null
+++ b/src/portable/microchip/samd21/hal.c
@@ -0,0 +1,82 @@
+/**************************************************************************/
+/*!
+ @file hal_nrf5x.c
+ @author hathach
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, hathach (tinyusb.org)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#include "tusb_option.h"
+
+#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMD21
+
+#include "sam.h"
+
+#include "tusb_hal.h"
+
+/*------------------------------------------------------------------*/
+/* MACRO TYPEDEF CONSTANT ENUM
+ *------------------------------------------------------------------*/
+#define USB_NVIC_PRIO 7
+
+void tusb_hal_nrf_power_event(uint32_t event);
+
+/*------------------------------------------------------------------*/
+/* TUSB HAL
+ *------------------------------------------------------------------*/
+bool tusb_hal_init(void)
+{
+ USB->DEVICE.PADCAL.bit.TRANSP = (*((uint32_t*) USB_FUSES_TRANSP_ADDR) & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
+ USB->DEVICE.PADCAL.bit.TRANSN = (*((uint32_t*) USB_FUSES_TRANSN_ADDR) & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
+ USB->DEVICE.PADCAL.bit.TRIM = (*((uint32_t*) USB_FUSES_TRIM_ADDR) & USB_FUSES_TRIM_Msk) >> USB_FUSES_TRIM_Pos;
+
+ USB->DEVICE.QOSCTRL.bit.CQOS = USB_QOSCTRL_CQOS_HIGH_Val;
+ USB->DEVICE.QOSCTRL.bit.DQOS = USB_QOSCTRL_DQOS_HIGH_Val;
+
+ tusb_hal_int_enable(0);
+ return true;
+}
+
+void tusb_hal_int_enable(uint8_t rhport)
+{
+ (void) rhport;
+ NVIC_EnableIRQ(USB_IRQn);
+}
+
+void tusb_hal_int_disable(uint8_t rhport)
+{
+ (void) rhport;
+ NVIC_DisableIRQ(USB_IRQn);
+}
+
+#endif
diff --git a/src/portable/microchip/samd51/dcd.c b/src/portable/microchip/samd51/dcd.c
new file mode 100644
index 000000000..e67fbd295
--- /dev/null
+++ b/src/portable/microchip/samd51/dcd.c
@@ -0,0 +1,360 @@
+/**************************************************************************/
+/*!
+ @file dcd_nrf5x.c
+ @author hathach
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Scott Shawcroft for Adafruit Industries
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#include "tusb_option.h"
+
+#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMD51
+
+#include "device/dcd.h"
+
+#include "device/usbd.h"
+#include "device/usbd_pvt.h" // to use defer function helper
+
+#include "sam.h"
+
+/*------------------------------------------------------------------*/
+/* MACRO TYPEDEF CONSTANT ENUM
+ *------------------------------------------------------------------*/
+enum
+{
+ // Max allowed by USB specs
+ MAX_PACKET_SIZE = 64,
+};
+
+UsbDeviceDescBank sram_registers[8][2];
+ATTR_ALIGNED(4) uint8_t control_out_buffer[64];
+ATTR_ALIGNED(4) uint8_t control_in_buffer[64];
+
+volatile uint32_t setup_count = 0;
+
+// Setup the control endpoint 0.
+static void bus_reset(void) {
+ // Max size of packets is 64 bytes.
+ UsbDeviceDescBank* bank_out = &sram_registers[0][TUSB_DIR_OUT];
+ bank_out->PCKSIZE.bit.SIZE = 0x3;
+ UsbDeviceDescBank* bank_in = &sram_registers[0][TUSB_DIR_IN];
+ bank_in->PCKSIZE.bit.SIZE = 0x3;
+
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[0];
+ ep->EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(0x1) | USB_DEVICE_EPCFG_EPTYPE1(0x1);
+ ep->EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0 | USB_DEVICE_EPINTENSET_TRCPT1 | USB_DEVICE_EPINTENSET_RXSTP;
+
+ dcd_edpt_xfer(0, 0, control_out_buffer, 64);
+ setup_count = 0;
+}
+
+
+/*------------------------------------------------------------------*/
+/* Controller API
+ *------------------------------------------------------------------*/
+bool dcd_init (uint8_t rhport)
+{
+ (void) rhport;
+ USB->DEVICE.DESCADD.reg = (uint32_t) &sram_registers;
+ USB->DEVICE.CTRLB.reg = USB_DEVICE_CTRLB_SPDCONF_FS;
+ USB->DEVICE.CTRLA.reg = USB_CTRLA_MODE_DEVICE | USB_CTRLA_ENABLE;
+ USB->DEVICE.INTENSET.reg = USB_DEVICE_INTENSET_SOF | USB_DEVICE_INTENSET_EORST;
+
+ return true;
+}
+
+void dcd_connect (uint8_t rhport)
+{
+
+}
+void dcd_disconnect (uint8_t rhport)
+{
+
+}
+
+void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
+{
+ (void) rhport;
+ dcd_edpt_xfer (0, TUSB_DIR_IN_MASK, NULL, 0);
+ // Wait for EP0 to finish before switching the address.
+ while (USB->DEVICE.DeviceEndpoint[0].EPSTATUS.bit.BK1RDY == 1) {}
+ USB->DEVICE.DADD.reg = USB_DEVICE_DADD_DADD(dev_addr) | USB_DEVICE_DADD_ADDEN;
+}
+
+void dcd_set_config (uint8_t rhport, uint8_t config_num)
+{
+ (void) rhport;
+ (void) config_num;
+ // Nothing to do
+}
+
+/*------------------------------------------------------------------*/
+/* Control
+ *------------------------------------------------------------------*/
+
+bool dcd_control_xfer (uint8_t rhport, uint8_t dir, uint8_t * buffer, uint16_t length)
+{
+ (void) rhport;
+ uint8_t ep_addr = 0;
+ if (dir == TUSB_DIR_IN) {
+ ep_addr |= TUSB_DIR_IN_MASK;
+ }
+
+ return dcd_edpt_xfer (rhport, ep_addr, buffer, length);
+}
+
+bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
+{
+ (void) rhport;
+
+ uint8_t const epnum = edpt_number(desc_edpt->bEndpointAddress);
+ uint8_t const dir = edpt_dir(desc_edpt->bEndpointAddress);
+
+ UsbDeviceDescBank* bank = &sram_registers[epnum][dir];
+ uint32_t size_value = 0;
+ while (size_value < 7) {
+ if (1 << (size_value + 3) == desc_edpt->wMaxPacketSize.size) {
+ break;
+ }
+ size_value++;
+ }
+ bank->PCKSIZE.bit.SIZE = size_value;
+
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ if ( dir == TUSB_DIR_OUT )
+ {
+ ep->EPCFG.bit.EPTYPE0 = desc_edpt->bmAttributes.xfer + 1;
+ ep->EPINTENSET.bit.TRCPT0 = true;
+ }else
+ {
+ ep->EPCFG.bit.EPTYPE1 = desc_edpt->bmAttributes.xfer + 1;
+ ep->EPINTENSET.bit.TRCPT1 = true;
+ }
+ __ISB(); __DSB();
+
+ return true;
+}
+
+bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
+{
+ (void) rhport;
+
+ uint8_t const epnum = edpt_number(ep_addr);
+ uint8_t const dir = edpt_dir(ep_addr);
+
+ UsbDeviceDescBank* bank = &sram_registers[epnum][dir];
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ bank->ADDR.reg = (uint32_t) buffer;
+ if ( dir == TUSB_DIR_OUT )
+ {
+ bank->PCKSIZE.bit.MULTI_PACKET_SIZE = total_bytes;
+ bank->PCKSIZE.bit.BYTE_COUNT = 0;
+ ep->EPSTATUSCLR.reg |= USB_DEVICE_EPSTATUSCLR_BK0RDY;
+ ep->EPINTFLAG.reg |= USB_DEVICE_EPINTFLAG_TRFAIL0;
+ } else
+ {
+ bank->PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
+ bank->PCKSIZE.bit.BYTE_COUNT = total_bytes;
+ ep->EPSTATUSSET.reg |= USB_DEVICE_EPSTATUSSET_BK1RDY;
+ ep->EPINTFLAG.reg |= USB_DEVICE_EPINTFLAG_TRFAIL1;
+ }
+
+ return true;
+}
+
+bool dcd_edpt_stalled (uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+
+ // control is never got halted
+ if ( ep_addr == 0 ) {
+ return false;
+ }
+
+ uint8_t const epnum = edpt_number(ep_addr);
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+ return (edpt_dir(ep_addr) == TUSB_DIR_IN ) ? ep->EPINTFLAG.bit.STALL1 : ep->EPINTFLAG.bit.STALL0;
+}
+
+void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+
+ uint8_t const epnum = edpt_number(ep_addr);
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ if (edpt_dir(ep_addr) == TUSB_DIR_IN) {
+ ep->EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1;
+ } else {
+ ep->EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0;
+ }
+
+ __ISB(); __DSB();
+}
+
+void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+
+ uint8_t const epnum = edpt_number(ep_addr);
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ if (edpt_dir(ep_addr) == TUSB_DIR_IN) {
+ ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1;
+ } else {
+ ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0;
+ }
+}
+
+bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr)
+{
+ (void) rhport;
+
+ // USBD shouldn't check control endpoint state
+ if ( 0 == ep_addr ) return false;
+
+ uint8_t const epnum = edpt_number(ep_addr);
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ if (edpt_dir(ep_addr) == TUSB_DIR_IN) {
+ return ep->EPINTFLAG.bit.TRCPT1 == 0 && ep->EPSTATUS.bit.BK1RDY == 1;
+ }
+ return ep->EPINTFLAG.bit.TRCPT0 == 0 && ep->EPSTATUS.bit.BK0RDY == 1;
+}
+
+/*------------------------------------------------------------------*/
+
+static bool maybe_handle_setup_packet(void) {
+ if (USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.RXSTP)
+ {
+ USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP;
+ // uint8_t* buf = (uint8_t*) sram_registers[0][0].ADDR.reg;
+ //
+ // if (buf[6] == 0x12) asm("bkpt");
+ // This copies the data elsewhere so we can reuse the buffer.
+ dcd_event_setup_received(0, (uint8_t*) sram_registers[0][0].ADDR.reg, true);
+ dcd_edpt_xfer(0, 0, control_out_buffer, 64);
+ setup_count += 1;
+ return true;
+ }
+ return false;
+}
+/*
+ *------------------------------------------------------------------*/
+/* USB_EORSM_DNRSM, USB_EORST_RST, USB_LPMSUSP_DDISC, USB_LPM_DCONN,
+USB_MSOF, USB_RAMACER, USB_RXSTP_TXSTP_0, USB_RXSTP_TXSTP_1,
+USB_RXSTP_TXSTP_2, USB_RXSTP_TXSTP_3, USB_RXSTP_TXSTP_4,
+USB_RXSTP_TXSTP_5, USB_RXSTP_TXSTP_6, USB_RXSTP_TXSTP_7,
+USB_STALL0_STALL_0, USB_STALL0_STALL_1, USB_STALL0_STALL_2,
+USB_STALL0_STALL_3, USB_STALL0_STALL_4, USB_STALL0_STALL_5,
+USB_STALL0_STALL_6, USB_STALL0_STALL_7, USB_STALL1_0, USB_STALL1_1,
+USB_STALL1_2, USB_STALL1_3, USB_STALL1_4, USB_STALL1_5, USB_STALL1_6,
+USB_STALL1_7, USB_SUSPEND, USB_TRFAIL0_TRFAIL_0, USB_TRFAIL0_TRFAIL_1,
+USB_TRFAIL0_TRFAIL_2, USB_TRFAIL0_TRFAIL_3, USB_TRFAIL0_TRFAIL_4,
+USB_TRFAIL0_TRFAIL_5, USB_TRFAIL0_TRFAIL_6, USB_TRFAIL0_TRFAIL_7,
+USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2,
+USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5,
+USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */
+void USB_0_Handler(void) {
+ uint32_t int_status = USB->DEVICE.INTFLAG.reg;
+
+ /*------------- Interrupt Processing -------------*/
+ if ( int_status & USB_DEVICE_INTFLAG_EORST )
+ {
+ USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTENCLR_EORST;
+ bus_reset();
+ dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
+ }
+
+ // Setup packet received.
+ maybe_handle_setup_packet();
+}
+/* USB_SOF_HSOF */
+void USB_1_Handler(void) {
+ USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF;
+ dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
+}
+
+void transfer_complete(uint8_t direction) {
+ // uint8_t* buf = (uint8_t*) sram_registers[0][0].ADDR.reg;
+ //
+ // if (buf[6] == 0x12 || setup_count == 2) asm("bkpt");
+ uint32_t epints = USB->DEVICE.EPINTSMRY.reg;
+ for (uint8_t epnum = 0; epnum < USB_EPT_NUM; epnum++) {
+ if ((epints & (1 << epnum)) == 0) {
+ continue;
+ }
+
+ if (direction == TUSB_DIR_OUT && maybe_handle_setup_packet()) {
+ continue;
+ }
+ UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
+
+ UsbDeviceDescBank* bank = &sram_registers[epnum][direction];
+ uint16_t total_transfer_size = bank->PCKSIZE.bit.BYTE_COUNT;
+
+ uint8_t ep_addr = epnum;
+ if (direction == TUSB_DIR_IN) {
+ ep_addr |= TUSB_DIR_IN_MASK;
+ }
+ dcd_event_xfer_complete(0, ep_addr, total_transfer_size, DCD_XFER_SUCCESS, true);
+ if (epnum == 0 && direction == TUSB_DIR_OUT) {
+ dcd_edpt_xfer(0, 0, control_out_buffer, 64);
+ }
+ if (direction == TUSB_DIR_IN) {
+ ep->EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
+ } else {
+ ep->EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
+ }
+ }
+}
+
+// Bank zero is for OUT and SETUP transactions.
+/* USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2,
+USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5,
+USB_TRCPT0_6, USB_TRCPT0_7 */
+void USB_2_Handler(void) {
+ transfer_complete(TUSB_DIR_OUT);
+}
+
+// Bank one is used for IN transactions.
+/* USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2,
+USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5,
+USB_TRCPT1_6, USB_TRCPT1_7 */
+void USB_3_Handler(void) {
+ transfer_complete(TUSB_DIR_IN);
+}
+
+#endif
diff --git a/src/portable/microchip/samd51/hal.c b/src/portable/microchip/samd51/hal.c
new file mode 100644
index 000000000..d8c71a7fe
--- /dev/null
+++ b/src/portable/microchip/samd51/hal.c
@@ -0,0 +1,88 @@
+/**************************************************************************/
+/*!
+ @file hal_nrf5x.c
+ @author hathach
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, hathach (tinyusb.org)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#include "tusb_option.h"
+
+#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMD51
+
+#include "sam.h"
+
+#include "tusb_hal.h"
+
+/*------------------------------------------------------------------*/
+/* MACRO TYPEDEF CONSTANT ENUM
+ *------------------------------------------------------------------*/
+#define USB_NVIC_PRIO 7
+
+void tusb_hal_nrf_power_event(uint32_t event);
+
+/*------------------------------------------------------------------*/
+/* TUSB HAL
+ *------------------------------------------------------------------*/
+bool tusb_hal_init(void)
+{
+ USB->DEVICE.PADCAL.bit.TRANSP = (*((uint32_t*) USB_FUSES_TRANSP_ADDR) & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
+ USB->DEVICE.PADCAL.bit.TRANSN = (*((uint32_t*) USB_FUSES_TRANSN_ADDR) & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
+ USB->DEVICE.PADCAL.bit.TRIM = (*((uint32_t*) USB_FUSES_TRIM_ADDR) & USB_FUSES_TRIM_Msk) >> USB_FUSES_TRIM_Pos;
+
+ USB->DEVICE.QOSCTRL.bit.CQOS = 3;
+ USB->DEVICE.QOSCTRL.bit.DQOS = 3;
+
+ tusb_hal_int_enable(0);
+ return true;
+}
+
+void tusb_hal_int_enable(uint8_t rhport)
+{
+ (void) rhport;
+ NVIC_EnableIRQ(USB_0_IRQn);
+ NVIC_EnableIRQ(USB_1_IRQn);
+ NVIC_EnableIRQ(USB_2_IRQn);
+ NVIC_EnableIRQ(USB_3_IRQn);
+}
+
+void tusb_hal_int_disable(uint8_t rhport)
+{
+ (void) rhport;
+ NVIC_DisableIRQ(USB_3_IRQn);
+ NVIC_DisableIRQ(USB_2_IRQn);
+ NVIC_DisableIRQ(USB_1_IRQn);
+ NVIC_DisableIRQ(USB_0_IRQn);
+}
+
+#endif
diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c
index 69e001240..7eeab1306 100644
--- a/src/portable/nordic/nrf5x/dcd_nrf5x.c
+++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c
@@ -203,7 +203,9 @@ static void xact_control_start(void)
bool dcd_control_xfer (uint8_t rhport, uint8_t dir, uint8_t * buffer, uint16_t length)
{
+
(void) rhport;
+ osal_semaphore_wait( _usbd_ctrl_sem, OSAL_TIMEOUT_CONTROL_XFER);
if ( length )
{
@@ -216,9 +218,11 @@ bool dcd_control_xfer (uint8_t rhport, uint8_t dir, uint8_t * buffer, uint16_t l
xact_control_start();
}else
{
+ NRF_USBD->EPIN[0].PTR = 0;
+ NRF_USBD->EPIN[0].MAXCNT = 0;
// Status Phase also require Easy DMA has to be free as well !!!!
- edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS);
- edpt_dma_end();
+ NRF_USBD->TASKS_EP0STATUS = 1;
+ osal_semaphore_post(_usbd_ctrl_sem, false);
}
return true;
@@ -434,7 +438,7 @@ void USBD_IRQHandler(void)
NRF_USBD->BMREQUESTTYPE , NRF_USBD->BREQUEST, NRF_USBD->WVALUEL , NRF_USBD->WVALUEH,
NRF_USBD->WINDEXL , NRF_USBD->WINDEXH , NRF_USBD->WLENGTHL, NRF_USBD->WLENGTHH
};
- dcd_event_setup_recieved(0, setup, true);
+ dcd_event_setup_received(0, setup, true);
}
if ( int_status & USBD_INTEN_EP0DATADONE_Msk )
diff --git a/src/tusb_option.h b/src/tusb_option.h
index 846367129..d7a6c6fe0 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -147,6 +147,8 @@
#ifndef CFG_TUD_ENUM_BUFFER_SIZE
#define CFG_TUD_CTRL_BUFSIZE 256
+ #else
+ #define CFG_TUD_CTRL_BUFSIZE CFG_TUD_ENUM_BUFFER_SIZE
#endif
#ifndef CFG_TUD_DESC_AUTO