Skip to content

Commit

Permalink
Merge pull request #1440 from hathach/osal-queue-timeout
Browse files Browse the repository at this point in the history
Osal queue timeout
  • Loading branch information
hathach authored Apr 20, 2022
2 parents 9c8c5c1 + 8757287 commit 55a5fd5
Show file tree
Hide file tree
Showing 17 changed files with 184 additions and 122 deletions.
4 changes: 4 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: TinyUSB Discussion
url: https://github.com/hathach/tinyusb/discussions
about: If you have other questions or need help, post it here.
- name: TinyUSB Docs
url: https://docs.tinyusb.org/
about: Online documentation
14 changes: 9 additions & 5 deletions examples/device/cdc_msc_freertos/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,11 @@ void usb_device_task(void* param)
// RTOS forever loop
while (1)
{
// tinyusb device task
// put this thread to waiting state until there is new events
tud_task();

// following code only run if tud_task() process at least 1 event
tud_cdc_write_flush();
}
}

Expand Down Expand Up @@ -181,7 +184,7 @@ void cdc_task(void* params)
// if ( tud_cdc_connected() )
{
// There are data available
if ( tud_cdc_available() )
while ( tud_cdc_available() )
{
uint8_t buf[64];

Expand All @@ -194,12 +197,13 @@ void cdc_task(void* params)
// for throughput test e.g
// $ dd if=/dev/zero of=/dev/ttyACM0 count=10000
tud_cdc_write(buf, count);
tud_cdc_write_flush();
}

tud_cdc_write_flush();
}

// For ESP32-S2 this delay is essential to allow idle how to run and reset wdt
vTaskDelay(pdMS_TO_TICKS(10));
// For ESP32-Sx this delay is essential to allow idle how to run and reset watchdog
vTaskDelay(1);
}
}

Expand Down
4 changes: 3 additions & 1 deletion examples/device/hid_composite_freertos/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,10 @@ void usb_device_task(void* param)
// RTOS forever loop
while (1)
{
// tinyusb device task
// put this thread to waiting state until there is new events
tud_task();

// following code only run if tud_task() process at least 1 event
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/common/tusb_verify.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@
*------------------------------------------------------------------*/

// Helper to implement optional parameter for TU_VERIFY Macro family
#define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3
#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
#define _GET_3RD_ARG(arg1, arg2, arg3, ...) arg3
#define _GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4

/*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/
#define TU_VERIFY_DEFINE(_cond, _handler, _ret) do \
Expand All @@ -116,7 +116,7 @@
#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false)
#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret)

#define TU_VERIFY(...) GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__)
#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__)


/*------------------------------------------------------------------*/
Expand All @@ -127,7 +127,7 @@
#define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false)
#define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret)

#define TU_VERIFY_HDLR(...) GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__)
#define TU_VERIFY_HDLR(...) _GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__)

/*------------------------------------------------------------------*/
/* ASSERT
Expand All @@ -139,7 +139,7 @@
#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret)

#ifndef TU_ASSERT
#define TU_ASSERT(...) GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__)
#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__)
#endif

/*------------------------------------------------------------------*/
Expand Down
12 changes: 9 additions & 3 deletions src/device/usbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,17 +466,18 @@ bool tud_task_event_ready(void)
}
@endcode
*/
void tud_task (void)
void tud_task_ext(uint32_t timeout_ms, bool in_isr)
{
(void) in_isr; // not implemented yet

// Skip if stack is not initialized
if ( !tusb_inited() ) return;

// Loop until there is no more events in the queue
while (1)
{
dcd_event_t event;

if ( !osal_queue_receive(_usbd_q, &event) ) return;
if ( !osal_queue_receive(_usbd_q, &event, timeout_ms) ) return;

#if CFG_TUSB_DEBUG >= 2
if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG2("\r\n"); // extra line for setup
Expand Down Expand Up @@ -593,6 +594,11 @@ void tud_task (void)
TU_BREAKPOINT();
break;
}

#if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO
// return if there is no more events, for application to run other background
if (osal_queue_empty(_usbd_q)) return;
#endif
}
}

Expand Down
11 changes: 10 additions & 1 deletion src/device/usbd.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,17 @@ bool tud_init (uint8_t rhport);
// Check if device stack is already initialized
bool tud_inited(void);

// Task function should be called in main/rtos loop, extended version of tud_task()
// - timeout_ms: millisecond to wait, zero = no wait, 0xFFFFFFFF = wait forever
// - in_isr: if function is called in ISR
void tud_task_ext(uint32_t timeout_ms, bool in_isr);

// Task function should be called in main/rtos loop
void tud_task (void);
TU_ATTR_ALWAYS_INLINE static inline
void tud_task (void)
{
tud_task_ext(UINT32_MAX, false);
}

// Check if there is pending events need proccessing by tud_task()
bool tud_task_event_ready(void);
Expand Down
11 changes: 9 additions & 2 deletions src/host/usbh.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,16 +392,18 @@ bool tuh_init(uint8_t rhport)
}
@endcode
*/
void tuh_task(void)
void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
{
(void) in_isr; // not implemented yet

// Skip if stack is not initialized
if ( !tusb_inited() ) return;

// Loop until there is no more events in the queue
while (1)
{
hcd_event_t event;
if ( !osal_queue_receive(_usbh_q, &event) ) return;
if ( !osal_queue_receive(_usbh_q, &event, timeout_ms) ) return;

switch (event.event_id)
{
Expand Down Expand Up @@ -497,6 +499,11 @@ void tuh_task(void)

default: break;
}

#if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO
// return if there is no more events, for application to run other background
if (osal_queue_empty(_usbh_q)) return;
#endif
}
}

Expand Down
19 changes: 14 additions & 5 deletions src/host/usbh.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,17 @@ bool tuh_init(uint8_t rhport);
// Check if host stack is already initialized
bool tuh_inited(void);

// Task function should be called in main/rtos loop, extended version of tuh_task()
// - timeout_ms: millisecond to wait, zero = no wait, 0xFFFFFFFF = wait forever
// - in_isr: if function is called in ISR
void tuh_task_ext(uint32_t timeout_ms, bool in_isr);

// Task function should be called in main/rtos loop
void tuh_task(void);
TU_ATTR_ALWAYS_INLINE static inline
void tuh_task(void)
{
tuh_task_ext(UINT32_MAX, false);
}

// Interrupt handler, name alias to HCD
extern void hcd_int_handler(uint8_t rhport);
Expand All @@ -106,17 +115,17 @@ tusb_speed_t tuh_speed_get(uint8_t daddr);
bool tuh_mounted(uint8_t daddr);

// Check if device is suspended
TU_ATTR_ALWAYS_INLINE
static inline bool tuh_suspended(uint8_t daddr)
TU_ATTR_ALWAYS_INLINE static inline
bool tuh_suspended(uint8_t daddr)
{
// TODO implement suspend & resume on host
(void) daddr;
return false;
}

// Check if device is ready to communicate with
TU_ATTR_ALWAYS_INLINE
static inline bool tuh_ready(uint8_t daddr)
TU_ATTR_ALWAYS_INLINE static inline
bool tuh_ready(uint8_t daddr)
{
return tuh_mounted(daddr) && !tuh_suspended(daddr);
}
Expand Down
22 changes: 11 additions & 11 deletions src/osal/osal.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,19 @@ typedef void (*osal_task_func_t)( void * );
// OSAL Porting API
// Should be implemented as static inline function in osal_port.h header
/*
static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef);
static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr);
static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec);
static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl); // TODO removed
osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef);
bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr);
bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec);
void osal_semaphore_reset(osal_semaphore_t sem_hdl); // TODO removed
static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef);
static inline bool osal_mutex_lock (osal_mutex_t sem_hdl, uint32_t msec);
static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl);
osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef);
bool osal_mutex_lock (osal_mutex_t sem_hdl, uint32_t msec);
bool osal_mutex_unlock(osal_mutex_t mutex_hdl);
static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef);
static inline bool osal_queue_receive(osal_queue_t qhdl, void* data);
static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr);
static inline bool osal_queue_empty(osal_queue_t qhdl);
osal_queue_t osal_queue_create(osal_queue_def_t* qdef);
bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec);
bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr);
bool osal_queue_empty(osal_queue_t qhdl);
*/
//--------------------------------------------------------------------+

Expand Down
45 changes: 29 additions & 16 deletions src/osal/osal_freertos.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,24 @@
extern "C" {
#endif

TU_ATTR_ALWAYS_INLINE static inline uint32_t _osal_ms2tick(uint32_t msec)
{
if (msec == OSAL_TIMEOUT_WAIT_FOREVER) return portMAX_DELAY;
if (msec == 0) return 0;

uint32_t ticks = pdMS_TO_TICKS(msec);

// configTICK_RATE_HZ is less than 1000 and 1 tick > 1 ms
// we still need to delay at least 1 tick
if (ticks == 0) ticks =1 ;

return ticks;
}

//--------------------------------------------------------------------+
// TASK API
//--------------------------------------------------------------------+
static inline void osal_task_delay(uint32_t msec)
TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
{
vTaskDelay( pdMS_TO_TICKS(msec) );
}
Expand All @@ -51,12 +65,12 @@ static inline void osal_task_delay(uint32_t msec)
typedef StaticSemaphore_t osal_semaphore_def_t;
typedef SemaphoreHandle_t osal_semaphore_t;

static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef)
TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef)
{
return xSemaphoreCreateBinaryStatic(semdef);
}

static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
{
if ( !in_isr )
{
Expand All @@ -78,13 +92,12 @@ static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
}
}

static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec)
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec)
{
uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? portMAX_DELAY : pdMS_TO_TICKS(msec);
return xSemaphoreTake(sem_hdl, ticks);
return xSemaphoreTake(sem_hdl, _osal_ms2tick(msec));
}

static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl)
TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl)
{
xQueueReset(sem_hdl);
}
Expand All @@ -95,17 +108,17 @@ static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl)
typedef StaticSemaphore_t osal_mutex_def_t;
typedef SemaphoreHandle_t osal_mutex_t;

static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef)
TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef)
{
return xSemaphoreCreateMutexStatic(mdef);
}

static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec)
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec)
{
return osal_semaphore_wait(mutex_hdl, msec);
}

static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl)
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl)
{
return xSemaphoreGive(mutex_hdl);
}
Expand All @@ -114,7 +127,7 @@ static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl)
// QUEUE API
//--------------------------------------------------------------------+

// role device/host is used by OS NONE for mutex (disable usb isr) only
// _int_set is not used with an RTOS
#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
static _type _name##_##buf[_depth];\
osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf };
Expand All @@ -130,17 +143,17 @@ typedef struct

typedef QueueHandle_t osal_queue_t;

static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
{
return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq);
}

static inline bool osal_queue_receive(osal_queue_t qhdl, void* data)
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec)
{
return xQueueReceive(qhdl, data, portMAX_DELAY);
return xQueueReceive(qhdl, data, _osal_ms2tick(msec));
}

static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr)
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr)
{
if ( !in_isr )
{
Expand All @@ -162,7 +175,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in
}
}

static inline bool osal_queue_empty(osal_queue_t qhdl)
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl)
{
return uxQueueMessagesWaiting(qhdl) == 0;
}
Expand Down
Loading

0 comments on commit 55a5fd5

Please sign in to comment.