mirror of
https://github.com/hathach/tinyusb.git
synced 2025-03-29 01:20:19 +00:00
add nrf52 walkaround for errata 104, 171, 187.
clean up osal_none
This commit is contained in:
parent
b9fc708e41
commit
9be8e7bef6
@ -74,27 +74,27 @@ static inline osal_task_t osal_task_create(osal_func_t code, const char* name, u
|
||||
return (osal_task_t) 1;
|
||||
}
|
||||
|
||||
#define TASK_RESTART \
|
||||
#define TASK_RESTART \
|
||||
_state = 0
|
||||
|
||||
#define OSAL_TASK_BEGIN \
|
||||
static uint16_t _state = 0; \
|
||||
ATTR_UNUSED static uint32_t _timeout = 0; \
|
||||
(void) _timeout; \
|
||||
switch(_state) { \
|
||||
#define OSAL_TASK_BEGIN \
|
||||
static uint16_t _state = 0; \
|
||||
ATTR_UNUSED static uint32_t _timeout = 0; \
|
||||
(void) _timeout; \
|
||||
switch(_state) { \
|
||||
case 0: {
|
||||
|
||||
#define OSAL_TASK_END \
|
||||
default: TASK_RESTART; break; \
|
||||
}}\
|
||||
#define OSAL_TASK_END \
|
||||
default: TASK_RESTART; break; \
|
||||
}} \
|
||||
return;
|
||||
|
||||
#define osal_task_delay(msec) \
|
||||
do {\
|
||||
_timeout = tusb_hal_millis();\
|
||||
_state = __LINE__; case __LINE__:\
|
||||
#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;\
|
||||
return TUSB_ERROR_OSAL_WAITING; \
|
||||
}while(0)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@ -156,23 +156,21 @@ static inline void osal_queue_flush(osal_queue_t const queue_hdl)
|
||||
queue_hdl->count = queue_hdl->rd_idx = queue_hdl->wr_idx = 0;
|
||||
}
|
||||
|
||||
#define osal_queue_receive(queue_hdl, p_data, msec, p_error) \
|
||||
do {\
|
||||
_timeout = tusb_hal_millis();\
|
||||
_state = __LINE__; case __LINE__:\
|
||||
if( queue_hdl->count == 0 ) {\
|
||||
if ( (msec != OSAL_TIMEOUT_WAIT_FOREVER) && ( _timeout + msec <= tusb_hal_millis()) ) /* time out */ \
|
||||
*(p_error) = TUSB_ERROR_OSAL_TIMEOUT;\
|
||||
else\
|
||||
return TUSB_ERROR_OSAL_WAITING;\
|
||||
} else{\
|
||||
/*TODO mutex lock tusb_hal_int_disable */\
|
||||
memcpy(p_data, queue_hdl->buffer + (queue_hdl->rd_idx * queue_hdl->item_size), queue_hdl->item_size);\
|
||||
queue_hdl->rd_idx = (queue_hdl->rd_idx + 1) % queue_hdl->depth;\
|
||||
queue_hdl->count--;\
|
||||
/*TODO mutex unlock tusb_hal_int_enable */\
|
||||
*(p_error) = TUSB_ERROR_NONE;\
|
||||
}\
|
||||
#define osal_queue_receive(queue_hdl, p_data, msec, p_error) \
|
||||
do { \
|
||||
_timeout = tusb_hal_millis(); \
|
||||
_state = __LINE__; case __LINE__: \
|
||||
if( queue_hdl->count == 0 ) { \
|
||||
if ( (msec != OSAL_TIMEOUT_WAIT_FOREVER) && ( _timeout + msec <= tusb_hal_millis()) ) \
|
||||
*(p_error) = TUSB_ERROR_OSAL_TIMEOUT; \
|
||||
else \
|
||||
return TUSB_ERROR_OSAL_WAITING; \
|
||||
} else{ \
|
||||
/*tusb_hal_int_disable_all();*/ \
|
||||
fifo_read(queue_hdl, p_data); \
|
||||
/*tusb_hal_int_enable_all();*/ \
|
||||
*(p_error) = TUSB_ERROR_NONE; \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
|
||||
@ -210,19 +208,21 @@ static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl)
|
||||
sem_hdl->count = 0;
|
||||
}
|
||||
|
||||
#define osal_semaphore_wait(sem_hdl, msec, p_error) \
|
||||
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()) ) /* time out */ \
|
||||
*(p_error) = TUSB_ERROR_OSAL_TIMEOUT;\
|
||||
else\
|
||||
return TUSB_ERROR_OSAL_WAITING;\
|
||||
} else{\
|
||||
if (sem_hdl->count) sem_hdl->count--; /*TODO mutex tusb_hal_int_disable consideration*/\
|
||||
*(p_error) = TUSB_ERROR_NONE;\
|
||||
}\
|
||||
#define osal_semaphore_wait(sem_hdl, msec, p_error) \
|
||||
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()) ) \
|
||||
*(p_error) = TUSB_ERROR_OSAL_TIMEOUT; \
|
||||
else \
|
||||
return TUSB_ERROR_OSAL_WAITING; \
|
||||
} else{ \
|
||||
/*tusb_hal_int_disable_all();*/ \
|
||||
sem_hdl->count--; \
|
||||
/*tusb_hal_int_enable_all();*/ \
|
||||
*(p_error) = TUSB_ERROR_NONE; \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -64,10 +64,14 @@ enum
|
||||
typedef struct
|
||||
{
|
||||
uint8_t* buffer;
|
||||
|
||||
uint16_t total_len;
|
||||
uint16_t actual_len;
|
||||
|
||||
uint8_t mps; // max packet size
|
||||
|
||||
// FIXME Errata 104 walkaround
|
||||
uint16_t frame_num;
|
||||
} nom_xfer_t;
|
||||
|
||||
/*static*/ struct
|
||||
@ -80,7 +84,7 @@ typedef struct
|
||||
}control;
|
||||
|
||||
// Non control: 7 endpoints IN & OUT (offset 1)
|
||||
nom_xfer_t xfer[2][7];
|
||||
nom_xfer_t xfer[7][2];
|
||||
|
||||
volatile bool dma_running;
|
||||
}_dcd;
|
||||
@ -227,14 +231,14 @@ bool dcd_control_xfer (uint8_t rhport, tusb_dir_t dir, uint8_t * buffer, uint16_
|
||||
*------------------------------------------------------------------*/
|
||||
static void normal_xact_start(uint8_t epnum, uint8_t dir)
|
||||
{
|
||||
nom_xfer_t* xfer = &_dcd.xfer[dir][epnum-1];
|
||||
nom_xfer_t* xfer = &_dcd.xfer[epnum-1][dir];
|
||||
|
||||
// Each transaction is up to Max Packet Size
|
||||
uint8_t const xact_len = min16_of(xfer->total_len - xfer->actual_len, xfer->mps);
|
||||
|
||||
if ( dir == TUSB_DIR_OUT )
|
||||
{
|
||||
// HW issue on nrf5284 sample, SIZE.EPOUT won't trigger ACK as spec
|
||||
// Errata 135: HW issue on nrf5284 sample, SIZE.EPOUT won't trigger ACK as spec
|
||||
// use the back door interface as sdk for walk around
|
||||
if ( nrf_drv_usbd_errata_sizeepout_rw() )
|
||||
{
|
||||
@ -266,7 +270,7 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
|
||||
uint8_t const epnum = edpt_number(desc_edpt->bEndpointAddress);
|
||||
uint8_t const dir = edpt_dir(desc_edpt->bEndpointAddress);
|
||||
|
||||
_dcd.xfer[dir][epnum-1].mps = desc_edpt->wMaxPacketSize.size;
|
||||
_dcd.xfer[epnum-1][dir].mps = desc_edpt->wMaxPacketSize.size;
|
||||
|
||||
if ( dir == TUSB_DIR_OUT )
|
||||
{
|
||||
@ -289,9 +293,17 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
|
||||
uint8_t const epnum = edpt_number(ep_addr);
|
||||
uint8_t const dir = edpt_dir(ep_addr);
|
||||
|
||||
_dcd.xfer[dir][epnum-1].buffer = buffer;
|
||||
_dcd.xfer[dir][epnum-1].total_len = total_bytes;
|
||||
_dcd.xfer[dir][epnum-1].actual_len = 0;
|
||||
nom_xfer_t* xfer = &_dcd.xfer[epnum-1][dir];
|
||||
|
||||
xfer->buffer = buffer;
|
||||
xfer->total_len = total_bytes;
|
||||
xfer->actual_len = 0;
|
||||
|
||||
// FIXME Errata 104 walkaround
|
||||
if ( nrf_drv_usbd_errata_104() )
|
||||
{
|
||||
xfer->frame_num = (uint16_t) NRF_USBD->FRAMECNTR;
|
||||
}
|
||||
|
||||
normal_xact_start(epnum, dir);
|
||||
|
||||
@ -340,7 +352,7 @@ bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr)
|
||||
uint8_t const epnum = edpt_number(ep_addr);
|
||||
uint8_t const dir = edpt_dir(ep_addr);
|
||||
|
||||
nom_xfer_t* xfer = &_dcd.xfer[dir][epnum-1];
|
||||
nom_xfer_t* xfer = &_dcd.xfer[epnum-1][dir];
|
||||
|
||||
return xfer->actual_len < xfer->total_len;
|
||||
}
|
||||
@ -376,11 +388,6 @@ void USBD_IRQHandler(void)
|
||||
dcd_bus_event(0, USBD_BUS_EVENT_RESET);
|
||||
}
|
||||
|
||||
if ( int_status & USBD_INTEN_SOF_Msk )
|
||||
{
|
||||
dcd_bus_event(0, USBD_BUS_EVENT_SOF);
|
||||
}
|
||||
|
||||
if ( int_status & EDPT_END_ALL_MASK )
|
||||
{
|
||||
// DMA complete move data from SRAM -> Endpoint
|
||||
@ -444,7 +451,7 @@ void USBD_IRQHandler(void)
|
||||
{
|
||||
if ( BIT_TEST_(data_status, epnum ) )
|
||||
{
|
||||
nom_xfer_t* xfer = &_dcd.xfer[TUSB_DIR_IN][epnum-1];
|
||||
nom_xfer_t* xfer = &_dcd.xfer[epnum-1][TUSB_DIR_IN];
|
||||
|
||||
xfer->actual_len += NRF_USBD->EPIN[epnum].MAXCNT;
|
||||
|
||||
@ -465,7 +472,7 @@ void USBD_IRQHandler(void)
|
||||
{
|
||||
if ( BIT_TEST_(data_status, 16+epnum ) )
|
||||
{
|
||||
nom_xfer_t* xfer = &_dcd.xfer[TUSB_DIR_OUT][epnum-1];
|
||||
nom_xfer_t* xfer = &_dcd.xfer[epnum-1][TUSB_DIR_OUT];
|
||||
|
||||
uint8_t const xact_len = NRF_USBD->SIZE.EPOUT[epnum];
|
||||
|
||||
@ -486,7 +493,7 @@ void USBD_IRQHandler(void)
|
||||
{
|
||||
if ( BIT_TEST_(int_status, USBD_INTEN_ENDEPOUT0_Pos+epnum) )
|
||||
{
|
||||
nom_xfer_t* xfer = &_dcd.xfer[TUSB_DIR_OUT][epnum-1];
|
||||
nom_xfer_t* xfer = &_dcd.xfer[epnum-1][TUSB_DIR_OUT];
|
||||
|
||||
// Transfer complete if transaction len < Max Packet Size or total len is transferred
|
||||
if ( (NRF_USBD->EPOUT[epnum].AMOUNT == xfer->mps) && (xfer->actual_len < xfer->total_len) )
|
||||
@ -517,6 +524,46 @@ void USBD_IRQHandler(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// SOF interrupt
|
||||
if ( int_status & USBD_INTEN_SOF_Msk )
|
||||
{
|
||||
// FIXME Errata 104 The EPDATA event might not be generated, and the related update of EPDATASTATUS does not occur.
|
||||
// There is no way for software to tell if a xfer is complete or not.
|
||||
// Walkaround: we will asssume an non-control IN transfer is always complete after 10 frames
|
||||
if ( nrf_drv_usbd_errata_104() )
|
||||
{
|
||||
// Check all the queued IN transfer, retire all transfer if 10 frames has passed
|
||||
for (int i=0; i<7; i++)
|
||||
{
|
||||
nom_xfer_t* xfer = &_dcd.xfer[i][TUSB_DIR_IN];
|
||||
|
||||
if (xfer->actual_len < xfer->total_len)
|
||||
{
|
||||
uint16_t diff = (uint16_t) NRF_USBD->FRAMECNTR;
|
||||
|
||||
if ( diff > xfer->frame_num )
|
||||
{
|
||||
diff -= xfer->frame_num;
|
||||
}else
|
||||
{
|
||||
diff = (diff + 1024) - xfer->frame_num; // Frame counter cap at 1024
|
||||
}
|
||||
|
||||
// Walkaround, mark this transfer as complete
|
||||
if (diff > 10)
|
||||
{
|
||||
xfer->actual_len = xfer->total_len;
|
||||
dcd_xfer_complete(0, (i+1) | TUSB_DIR_IN_MASK, xfer->actual_len, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dcd_bus_event(0, USBD_BUS_EVENT_SOF);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -199,6 +199,40 @@ void power_usb_event_handler(uint32_t event)
|
||||
nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK);
|
||||
|
||||
/* Enable the peripheral */
|
||||
// ERRATA 171, 187
|
||||
|
||||
if (nrf_drv_usbd_errata_187())
|
||||
{
|
||||
// CRITICAL_REGION_ENTER();
|
||||
if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
|
||||
{
|
||||
*((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
|
||||
*((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
|
||||
*((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
|
||||
}
|
||||
else
|
||||
{
|
||||
*((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
|
||||
}
|
||||
// CRITICAL_REGION_EXIT();
|
||||
}
|
||||
|
||||
if (nrf_drv_usbd_errata_171())
|
||||
{
|
||||
// CRITICAL_REGION_ENTER();
|
||||
if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
|
||||
{
|
||||
*((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
|
||||
*((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
|
||||
*((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
|
||||
}
|
||||
else
|
||||
{
|
||||
*((volatile uint32_t *)(0x4006EC14)) = 0x000000C0;
|
||||
}
|
||||
// CRITICAL_REGION_EXIT();
|
||||
}
|
||||
|
||||
nrf_usbd_enable();
|
||||
|
||||
// Enable HFCLK
|
||||
@ -212,6 +246,39 @@ void power_usb_event_handler(uint32_t event)
|
||||
nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK);
|
||||
nrf_usbd_event_clear(NRF_USBD_EVENT_USBEVENT);
|
||||
|
||||
if (nrf_drv_usbd_errata_171())
|
||||
{
|
||||
// CRITICAL_REGION_ENTER();
|
||||
if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
|
||||
{
|
||||
*((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
|
||||
*((volatile uint32_t *)(0x4006EC14)) = 0x00000000;
|
||||
*((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
|
||||
}
|
||||
else
|
||||
{
|
||||
*((volatile uint32_t *)(0x4006EC14)) = 0x00000000;
|
||||
}
|
||||
|
||||
// CRITICAL_REGION_EXIT();
|
||||
}
|
||||
|
||||
if (nrf_drv_usbd_errata_187())
|
||||
{
|
||||
// CRITICAL_REGION_ENTER();
|
||||
if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
|
||||
{
|
||||
*((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
|
||||
*((volatile uint32_t *)(0x4006ED14)) = 0x00000000;
|
||||
*((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
|
||||
}
|
||||
else
|
||||
{
|
||||
*((volatile uint32_t *)(0x4006ED14)) = 0x00000000;
|
||||
}
|
||||
// CRITICAL_REGION_EXIT();
|
||||
}
|
||||
|
||||
if ( nrf_drv_usbd_errata_166() )
|
||||
{
|
||||
*((volatile uint32_t *) (NRF_USBD_BASE + 0x800)) = 0x7E3;
|
||||
@ -227,10 +294,9 @@ void power_usb_event_handler(uint32_t event)
|
||||
USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk |
|
||||
USBD_INTEN_EPDATA_Msk | USBD_INTEN_SOF_Msk;
|
||||
|
||||
// if (enable_sof || nrf_drv_usbd_errata_104())
|
||||
// {
|
||||
// ints_to_enable |= NRF_USBD_INT_SOF_MASK;
|
||||
// }
|
||||
// FIXME Errata 104: USB complete event is not generated (happedn randomly).
|
||||
// Requires to enable SOF to perform clean up task.
|
||||
// nrf_drv_usbd_errata_104()
|
||||
|
||||
// Enable interrupt, Priorities 0,1,4,5 (nRF52) are reserved for SoftDevice
|
||||
NVIC_SetPriority(USBD_IRQn, 7);
|
||||
|
@ -78,6 +78,33 @@ void tusb_hal_int_disable(uint8_t rhport);
|
||||
// Only required to implement if using No RTOS (osal_none)
|
||||
uint32_t tusb_hal_millis(void);
|
||||
|
||||
|
||||
// Enable all ports' interrupt
|
||||
static inline void tusb_hal_int_enable_all(void)
|
||||
{
|
||||
#ifdef TUSB_CFG_CONTROLLER_0_MODE
|
||||
tusb_hal_int_enable(0);
|
||||
#endif
|
||||
|
||||
#ifdef TUSB_CFG_CONTROLLER_0_MODE
|
||||
tusb_hal_int_enable(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Disable all ports' interrupt
|
||||
static inline void tusb_hal_int_disable_all(void)
|
||||
{
|
||||
#ifdef TUSB_CFG_CONTROLLER_0_MODE
|
||||
tusb_hal_int_disable(0);
|
||||
#endif
|
||||
|
||||
#ifdef TUSB_CFG_CONTROLLER_0_MODE
|
||||
tusb_hal_int_disable(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -45,6 +45,7 @@
|
||||
#define TUSB_VERSION_NAME "alpha"
|
||||
#define TUSB_VERSION XSTRING_(TUSB_VERSION_YEAR) "." XSTRING_(TUSB_VERSION_MONTH)
|
||||
|
||||
// TODO remove, use vendor specific flag
|
||||
/** \defgroup group_mcu Supported MCU
|
||||
* \ref TUSB_CFG_MCU must be defined to one of these
|
||||
* @{ */
|
||||
@ -57,6 +58,7 @@
|
||||
#define MCU_LPC43XX 7 ///< NXP LPC43xx family
|
||||
/** @} */
|
||||
|
||||
// Allow to use command line to change the config name/location
|
||||
#ifndef TUSB_CFG_CONFIG_FILE
|
||||
#define TUSB_CFG_CONFIG_FILE "tusb_config.h"
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user