Merge pull request #2530 from hathach/add-tuh-deinit

This commit is contained in:
Ha Thach 2024-03-25 19:15:39 +07:00 committed by GitHub
commit 5b0e255f7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 402 additions and 315 deletions

View File

@ -52,7 +52,7 @@ jobs:
- name: Upload Artifacts for Hardware Testing
if: matrix.board == 'espressif_s3_devkitc' && github.repository_owner == 'hathach'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.board }}
path: |
@ -98,7 +98,7 @@ jobs:
sparse-checkout: test/hil
- name: Download Artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ matrix.board }}
path: cmake-build/cmake-build-${{ matrix.board }}

View File

@ -27,7 +27,7 @@ jobs:
language: c++
fuzz-seconds: 600
- name: Upload Crash
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts

View File

@ -93,7 +93,7 @@ jobs:
- name: Upload Artifacts for Hardware Testing (rp2040)
if: matrix.family == 'rp2040' && github.repository_owner == 'hathach'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: raspberry_pi_pico
path: |
@ -101,7 +101,7 @@ jobs:
- name: Upload Artifacts for Hardware Testing (nRF)
if: matrix.family == 'nrf' && github.repository_owner == 'hathach'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: feather_nrf52840_express
path: |
@ -109,7 +109,7 @@ jobs:
- name: Upload Artifacts for Hardware Testing (samd51)
if: matrix.family == 'samd51' && github.repository_owner == 'hathach'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: itsybitsy_m4
path: |
@ -153,7 +153,7 @@ jobs:
sparse-checkout: test/hil
- name: Download Artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ matrix.board }}
path: cmake-build/cmake-build-${{ matrix.board }}

View File

@ -130,7 +130,7 @@ jobs:
category: "/language:${{matrix.language}}"
- name: Archive CodeQL results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: codeql-results
path: ${{ steps.step1.outputs.sarif-output }}

View File

@ -8,5 +8,6 @@ family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR})
# family_add_subdirectory will filter what to actually add based on selected FAMILY
family_add_subdirectory(bare_api)
family_add_subdirectory(cdc_msc_hid)
family_add_subdirectory(cdc_msc_hid_freertos)
family_add_subdirectory(hid_controller)
family_add_subdirectory(msc_file_explorer)

View File

@ -6,7 +6,6 @@ mcu:LPC43XX
mcu:MIMXRT1XXX
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:RP2040
mcu:MSP432E4
mcu:RX65X
mcu:RAXXX

View File

@ -46,11 +46,12 @@
#define UART_TX_PIN 6
// SPI for USB host shield
#define MAX3421_SCK_PIN _PINNUM(1, 15)
#define MAX3421_MOSI_PIN _PINNUM(1, 13)
#define MAX3421_MISO_PIN _PINNUM(1, 14)
#define MAX3421_CS_PIN _PINNUM(1, 12)
#define MAX3421_INTR_PIN _PINNUM(1, 11)
// Pin is correct but not working probably due to signal incompatible (1.8V 3v3) with MAC3421E !?
//#define MAX3421_SCK_PIN _PINNUM(1, 15)
//#define MAX3421_MOSI_PIN _PINNUM(1, 13)
//#define MAX3421_MISO_PIN _PINNUM(1, 14)
//#define MAX3421_CS_PIN _PINNUM(1, 12)
//#define MAX3421_INTR_PIN _PINNUM(1, 11)
#ifdef __cplusplus
}

View File

@ -1,9 +1,6 @@
set(MCU_VARIANT nrf5340_application)
set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf5340_xxaa_application.ld)
# enable max3421 host driver for this board
set(MAX3421_HOST 1)
function(update_board TARGET)
target_sources(${TARGET} PRIVATE
${NRFX_DIR}/drivers/src/nrfx_usbreg.c

View File

@ -46,11 +46,12 @@
#define UART_TX_PIN 20
// SPI for USB host shield
#define MAX3421_SCK_PIN _PINNUM(1, 15)
#define MAX3421_MOSI_PIN _PINNUM(1, 13)
#define MAX3421_MISO_PIN _PINNUM(1, 14)
#define MAX3421_CS_PIN _PINNUM(1, 12)
#define MAX3421_INTR_PIN _PINNUM(1, 11)
// Pin is correct but not working probably due to signal incompatible (1.8V 3v3) with MAC3421E !?
//#define MAX3421_SCK_PIN _PINNUM(1, 15)
//#define MAX3421_MOSI_PIN _PINNUM(1, 13)
//#define MAX3421_MISO_PIN _PINNUM(1, 14)
//#define MAX3421_CS_PIN _PINNUM(1, 12)
//#define MAX3421_INTR_PIN _PINNUM(1, 11)
#ifdef __cplusplus
}

View File

@ -292,20 +292,7 @@ void max3421_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
}
static void max3421_init(void) {
// MAX3421 need 3.3v signal (may not be needed)
// #if defined(UICR_REGOUT0_VOUT_Msk)
// if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != UICR_REGOUT0_VOUT_3V3) {
// NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
// while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
//
// NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~UICR_REGOUT0_VOUT_Msk) | UICR_REGOUT0_VOUT_3V3;
//
// NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
// while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
//
// NVIC_SystemReset();
// }
// #endif
// Somehow pca10056/95 is not working probably due to signal incompatible (1.8V 3v3) with MAC3421E !?
// manually manage CS
nrf_gpio_cfg_output(MAX3421_CS_PIN);

View File

@ -171,7 +171,7 @@ function(family_configure_target TARGET RTOS)
pico_add_extra_outputs(${TARGET})
pico_enable_stdio_uart(${TARGET} 1)
target_link_libraries(${TARGET} PUBLIC pico_stdlib pico_bootsel_via_double_reset tinyusb_board${RTOS_SUFFIX} tinyusb_additions)
target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_board${RTOS_SUFFIX} tinyusb_additions)
family_flash_openocd(${TARGET} ${OPENOCD_OPTION})
family_flash_jlink(${TARGET})

View File

@ -621,12 +621,11 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding,
// CLASS-USBH API
//--------------------------------------------------------------------+
void cdch_init(void) {
bool cdch_init(void) {
TU_LOG_DRV("sizeof(cdch_interface_t) = %u\r\n", sizeof(cdch_interface_t));
tu_memclr(cdch_data, sizeof(cdch_data));
for (size_t i = 0; i < CFG_TUH_CDC; i++) {
cdch_interface_t* p_cdc = &cdch_data[i];
tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false,
p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE,
p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE);
@ -635,6 +634,17 @@ void cdch_init(void) {
p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE,
p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE);
}
return true;
}
bool cdch_deinit(void) {
for (size_t i = 0; i < CFG_TUH_CDC; i++) {
cdch_interface_t* p_cdc = &cdch_data[i];
tu_edpt_stream_deinit(&p_cdc->stream.tx);
tu_edpt_stream_deinit(&p_cdc->stream.rx);
}
return true;
}
void cdch_close(uint8_t daddr) {

View File

@ -192,7 +192,8 @@ TU_ATTR_WEAK extern void tuh_cdc_tx_complete_cb(uint8_t idx);
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void cdch_init (void);
bool cdch_init (void);
bool cdch_deinit (void);
bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num);
bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);

View File

@ -372,8 +372,14 @@ bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const vo
//--------------------------------------------------------------------+
// USBH API
//--------------------------------------------------------------------+
void hidh_init(void) {
bool hidh_init(void) {
TU_LOG_DRV("sizeof(hidh_interface_t) = %u\r\n", sizeof(hidh_interface_t));
tu_memclr(_hidh_itf, sizeof(_hidh_itf));
return true;
}
bool hidh_deinit(void) {
return true;
}
bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {

View File

@ -163,7 +163,8 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void hidh_init(void);
bool hidh_init(void);
bool hidh_deinit(void);
bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len);
bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num);
bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);

View File

@ -284,8 +284,14 @@ bool tuh_msc_reset(uint8_t dev_addr) {
//--------------------------------------------------------------------+
// CLASS-USBH API
//--------------------------------------------------------------------+
void msch_init(void) {
bool msch_init(void) {
TU_LOG_DRV("sizeof(msch_interface_t) = %u\r\n", sizeof(msch_interface_t));
tu_memclr(_msch_itf, sizeof(_msch_itf));
return true;
}
bool msch_deinit(void) {
return true;
}
void msch_close(uint8_t dev_addr) {

View File

@ -113,7 +113,8 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr);
// Internal Class Driver API
//--------------------------------------------------------------------+
void msch_init (void);
bool msch_init (void);
bool msch_deinit (void);
bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
bool msch_set_config (uint8_t dev_addr, uint8_t itf_num);
void msch_close (uint8_t dev_addr);

View File

@ -102,10 +102,8 @@ extern "C" {
* |
* -------------------------
* | R | 1 | 2 | W | 4 | 5 |
*/
typedef struct
{
typedef struct {
uint8_t* buffer ; // buffer pointer
uint16_t depth ; // max items
@ -124,16 +122,14 @@ typedef struct
} tu_fifo_t;
typedef struct
{
typedef struct {
uint16_t len_lin ; ///< linear length in item size
uint16_t len_wrap ; ///< wrapped length in item size
void * ptr_lin ; ///< linear part start pointer
void * ptr_wrap ; ///< wrapped part start pointer
} tu_fifo_buffer_info_t;
#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \
{ \
#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable){\
.buffer = _buffer, \
.depth = _depth, \
.item_size = sizeof(_type), \
@ -144,23 +140,18 @@ typedef struct
uint8_t _name##_buf[_depth*sizeof(_type)]; \
tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable)
bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable);
bool tu_fifo_clear(tu_fifo_t *f);
bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable);
#if OSAL_MUTEX_REQUIRED
TU_ATTR_ALWAYS_INLINE static inline
void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_mutex)
{
f->mutex_wr = wr_mutex;
f->mutex_rd = rd_mutex;
}
TU_ATTR_ALWAYS_INLINE static inline
void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_mutex) {
f->mutex_wr = wr_mutex;
f->mutex_rd = rd_mutex;
}
#else
#define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex)
#define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex)
#endif
bool tu_fifo_write (tu_fifo_t* f, void const * p_data);
@ -182,8 +173,7 @@ bool tu_fifo_overflowed (tu_fifo_t* f);
void tu_fifo_correct_read_pointer (tu_fifo_t* f);
TU_ATTR_ALWAYS_INLINE static inline
uint16_t tu_fifo_depth(tu_fifo_t* f)
{
uint16_t tu_fifo_depth(tu_fifo_t* f) {
return f->depth;
}
@ -198,7 +188,6 @@ void tu_fifo_advance_read_pointer (tu_fifo_t *f, uint16_t n);
void tu_fifo_get_read_info (tu_fifo_t *f, tu_fifo_buffer_info_t *info);
void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info);
#ifdef __cplusplus
}
#endif

View File

@ -60,7 +60,7 @@ typedef struct {
tu_fifo_t ff;
// mutex: read if ep rx, write if e tx
OSAL_MUTEX_DEF(ff_mutex);
OSAL_MUTEX_DEF(ff_mutexdef);
}tu_edpt_stream_t;
@ -87,15 +87,17 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex);
// Endpoint Stream
//--------------------------------------------------------------------+
// Init an stream, should only be called once
// Init an endpoint stream
bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable,
void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize);
// Deinit an endpoint stream
bool tu_edpt_stream_deinit(tu_edpt_stream_t* s);
// Open an stream for an endpoint
// hwid is either device address (host mode) or rhport (device mode)
TU_ATTR_ALWAYS_INLINE static inline
void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t const *desc_ep)
{
void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t const *desc_ep) {
tu_fifo_clear(&s->ff);
s->hwid = hwid;
s->ep_addr = desc_ep->bEndpointAddress;
@ -103,16 +105,14 @@ void tu_edpt_stream_open(tu_edpt_stream_t* s, uint8_t hwid, tusb_desc_endpoint_t
}
TU_ATTR_ALWAYS_INLINE static inline
void tu_edpt_stream_close(tu_edpt_stream_t* s)
{
void tu_edpt_stream_close(tu_edpt_stream_t* s) {
s->hwid = 0;
s->ep_addr = 0;
}
// Clear fifo
TU_ATTR_ALWAYS_INLINE static inline
bool tu_edpt_stream_clear(tu_edpt_stream_t* s)
{
bool tu_edpt_stream_clear(tu_edpt_stream_t* s) {
return tu_fifo_clear(&s->ff);
}
@ -131,8 +131,7 @@ bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferr
// Get the number of bytes available for writing
TU_ATTR_ALWAYS_INLINE static inline
uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t* s)
{
uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t* s) {
return (uint32_t) tu_fifo_remaining(&s->ff);
}

View File

@ -130,6 +130,9 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) TU_AT
// Initialize controller to host mode
bool hcd_init(uint8_t rhport);
// De-initialize controller
bool hcd_deinit(uint8_t rhport);
// Interrupt Handler
void hcd_int_handler(uint8_t rhport, bool in_isr);

View File

@ -182,9 +182,13 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp,
//--------------------------------------------------------------------+
// CLASS-USBH API (don't require to verify parameters)
//--------------------------------------------------------------------+
void hub_init(void)
{
bool hub_init(void) {
tu_memclr(hub_data, sizeof(hub_data));
return true;
}
bool hub_deinit(void) {
return true;
}
bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)

View File

@ -187,16 +187,14 @@ bool hub_port_get_status (uint8_t hub_addr, uint8_t hub_port, void* resp,
bool hub_edpt_status_xfer(uint8_t dev_addr);
// Reset a port
static inline bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port,
tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
TU_ATTR_ALWAYS_INLINE static inline
bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb, user_data);
}
// Clear Reset Change
static inline bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port,
tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
TU_ATTR_ALWAYS_INLINE static inline
bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_data);
}
@ -204,7 +202,8 @@ static inline bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_por
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void hub_init (void);
bool hub_init (void);
bool hub_deinit (void);
bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
bool hub_set_config (uint8_t dev_addr, uint8_t itf_num);
bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);

View File

@ -45,8 +45,13 @@
#endif
//--------------------------------------------------------------------+
// Callback weak stubs (called if application does not provide)
// Weak stubs: invoked if no strong implementation is available
//--------------------------------------------------------------------+
TU_ATTR_WEAK bool hcd_deinit(uint8_t rhport) {
(void) rhport;
return false;
}
TU_ATTR_WEAK void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) {
(void) rhport;
(void) eventid;
@ -119,16 +124,17 @@ typedef struct {
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL
#define DRIVER_NAME(_name) .name = _name,
#define DRIVER_NAME(_name) _name
#else
#define DRIVER_NAME(_name)
#define DRIVER_NAME(_name) NULL
#endif
static usbh_class_driver_t const usbh_class_drivers[] = {
#if CFG_TUH_CDC
{
DRIVER_NAME("CDC")
.name = DRIVER_NAME("CDC"),
.init = cdch_init,
.deinit = cdch_deinit,
.open = cdch_open,
.set_config = cdch_set_config,
.xfer_cb = cdch_xfer_cb,
@ -138,8 +144,9 @@ static usbh_class_driver_t const usbh_class_drivers[] = {
#if CFG_TUH_MSC
{
DRIVER_NAME("MSC")
.name = DRIVER_NAME("MSC"),
.init = msch_init,
.deinit = msch_deinit,
.open = msch_open,
.set_config = msch_set_config,
.xfer_cb = msch_xfer_cb,
@ -149,8 +156,9 @@ static usbh_class_driver_t const usbh_class_drivers[] = {
#if CFG_TUH_HID
{
DRIVER_NAME("HID")
.name = DRIVER_NAME("HID"),
.init = hidh_init,
.deinit = hidh_deinit,
.open = hidh_open,
.set_config = hidh_set_config,
.xfer_cb = hidh_xfer_cb,
@ -160,8 +168,9 @@ static usbh_class_driver_t const usbh_class_drivers[] = {
#if CFG_TUH_HUB
{
DRIVER_NAME("HUB")
.name = DRIVER_NAME("HUB"),
.init = hub_init,
.deinit = hub_deinit,
.open = hub_open,
.set_config = hub_set_config,
.xfer_cb = hub_xfer_cb,
@ -171,9 +180,11 @@ static usbh_class_driver_t const usbh_class_drivers[] = {
#if CFG_TUH_VENDOR
{
DRIVER_NAME("VENDOR")
.name = DRIVER_NAME("VENDOR"),
.init = cush_init,
.open = cush_open_subtask,
.deinit = cush_deinit,
.open = cush_open,
.set_config = cush_set_config,
.xfer_cb = cush_isr,
.close = cush_close
}
@ -338,55 +349,92 @@ bool tuh_inited(void) {
return _usbh_controller != TUSB_INDEX_INVALID_8;
}
bool tuh_init(uint8_t controller_id) {
bool tuh_init(uint8_t rhport) {
// skip if already initialized
if ( tuh_inited() ) return true;
if (tuh_rhport_is_active(rhport)) return true;
TU_LOG_USBH("USBH init on controller %u\r\n", controller_id);
TU_LOG_INT_USBH(sizeof(usbh_device_t));
TU_LOG_INT_USBH(sizeof(hcd_event_t));
TU_LOG_INT_USBH(sizeof(_ctrl_xfer));
TU_LOG_INT_USBH(sizeof(tuh_xfer_t));
TU_LOG_INT_USBH(sizeof(tu_fifo_t));
TU_LOG_INT_USBH(sizeof(tu_edpt_stream_t));
TU_LOG_USBH("USBH init on controller %u\r\n", rhport);
// Event queue
_usbh_q = osal_queue_create( &_usbh_qdef );
TU_ASSERT(_usbh_q != NULL);
// Init host stack if not already
if (!tuh_inited()) {
TU_LOG_INT_USBH(sizeof(usbh_device_t));
TU_LOG_INT_USBH(sizeof(hcd_event_t));
TU_LOG_INT_USBH(sizeof(_ctrl_xfer));
TU_LOG_INT_USBH(sizeof(tuh_xfer_t));
TU_LOG_INT_USBH(sizeof(tu_fifo_t));
TU_LOG_INT_USBH(sizeof(tu_edpt_stream_t));
// Event queue
_usbh_q = osal_queue_create(&_usbh_qdef);
TU_ASSERT(_usbh_q != NULL);
#if OSAL_MUTEX_REQUIRED
// Init mutex
_usbh_mutex = osal_mutex_create(&_usbh_mutexdef);
TU_ASSERT(_usbh_mutex);
// Init mutex
_usbh_mutex = osal_mutex_create(&_usbh_mutexdef);
TU_ASSERT(_usbh_mutex);
#endif
// Get application driver if available
if ( usbh_app_driver_get_cb ) {
_app_driver = usbh_app_driver_get_cb(&_app_driver_count);
}
// Get application driver if available
if (usbh_app_driver_get_cb) {
_app_driver = usbh_app_driver_get_cb(&_app_driver_count);
}
// Device
tu_memclr(&_dev0, sizeof(_dev0));
tu_memclr(_usbh_devices, sizeof(_usbh_devices));
tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer));
// Device
tu_memclr(&_dev0, sizeof(_dev0));
tu_memclr(_usbh_devices, sizeof(_usbh_devices));
tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer));
for(uint8_t i=0; i<TOTAL_DEVICES; i++) {
clear_device(&_usbh_devices[i]);
}
for (uint8_t i = 0; i < TOTAL_DEVICES; i++) {
clear_device(&_usbh_devices[i]);
}
// Class drivers
for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
usbh_class_driver_t const* driver = get_driver(drv_id);
if (driver) {
TU_LOG_USBH("%s init\r\n", driver->name);
driver->init();
// Class drivers
for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
usbh_class_driver_t const* driver = get_driver(drv_id);
if (driver) {
TU_LOG_USBH("%s init\r\n", driver->name);
driver->init();
}
}
}
_usbh_controller = controller_id;;
// Init host controller
_usbh_controller = rhport;;
TU_ASSERT(hcd_init(rhport));
hcd_int_enable(rhport);
TU_ASSERT(hcd_init(controller_id));
hcd_int_enable(controller_id);
return true;
}
bool tuh_deinit(uint8_t rhport) {
if (!tuh_rhport_is_active(rhport)) return true;
// deinit host controller
hcd_int_disable(rhport);
hcd_deinit(rhport);
_usbh_controller = TUSB_INDEX_INVALID_8;
// deinit host stack if no controller is active
if (!tuh_inited()) {
// Class drivers
for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
usbh_class_driver_t const* driver = get_driver(drv_id);
if (driver) {
TU_LOG_USBH("%s deinit\r\n", driver->name);
driver->deinit();
}
}
osal_queue_delete(_usbh_q);
_usbh_q = NULL;
#if OSAL_MUTEX_REQUIRED
// TODO make sure there is no task waiting on this mutex
osal_mutex_delete(_usbh_mutex);
_usbh_mutex = NULL;
#endif
}
return true;
}

View File

@ -109,7 +109,11 @@ bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param);
// Init host stack
bool tuh_init(uint8_t rhport);
// Deinit host stack on rhport
bool tuh_deinit(uint8_t rhport);
// Check if host stack is already initialized with any roothub ports
// To check if an rhport is initialized, use tuh_rhport_is_active()
bool tuh_inited(void);
// Task function should be called in main/rtos loop, extended version of tuh_task()

View File

@ -50,11 +50,9 @@ enum {
//--------------------------------------------------------------------+
typedef struct {
#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL
char const* name;
#endif
void (* const init )(void);
bool (* const init )(void);
bool (* const deinit )(void);
bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num);
bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);

View File

@ -74,15 +74,18 @@ typedef void (*osal_task_func_t)( void * );
// Should be implemented as static inline function in osal_port.h header
/*
osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef);
bool osal_semaphore_delete(osal_semaphore_t semd_hdl);
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
osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef);
bool osal_mutex_delete(osal_mutex_t mutex_hdl)
bool osal_mutex_lock (osal_mutex_t sem_hdl, uint32_t msec);
bool osal_mutex_unlock(osal_mutex_t mutex_hdl);
osal_queue_t osal_queue_create(osal_queue_def_t* qdef);
bool osal_queue_delete(osal_queue_t qhdl);
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);

View File

@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
#ifndef _TUSB_OSAL_FREERTOS_H_
#define _TUSB_OSAL_FREERTOS_H_
#ifndef TUSB_OSAL_FREERTOS_H_
#define TUSB_OSAL_FREERTOS_H_
// FreeRTOS Headers
#include TU_INCLUDE_PATH(CFG_TUSB_OS_INC_PATH,FreeRTOS.h)
@ -114,6 +114,11 @@ TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_
#endif
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
vSemaphoreDelete(semd_hdl);
return true;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
if ( !in_isr ) {
return xSemaphoreGive(sem_hdl) != 0;
@ -153,6 +158,11 @@ TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_de
#endif
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
vSemaphoreDelete(mutex_hdl);
return true;
}
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);
}
@ -181,6 +191,11 @@ TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_de
return q;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
vQueueDelete(qhdl);
return true;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
return xQueueReceive(qhdl, data, _osal_ms2tick(msec));
}

View File

@ -36,8 +36,7 @@
//--------------------------------------------------------------------+
// TASK API
//--------------------------------------------------------------------+
TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
{
TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) {
os_time_delay( os_time_ms_to_ticks32(msec) );
}
@ -47,25 +46,26 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
typedef struct os_sem osal_semaphore_def_t;
typedef struct os_sem* osal_semaphore_t;
TU_ATTR_ALWAYS_INLINE 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 (os_sem_init(semdef, 0) == OS_OK) ? (osal_semaphore_t) semdef : NULL;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
{
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
(void) semd_hdl;
return true; // nothing to do
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
(void) in_isr;
return os_sem_release(sem_hdl) == OS_OK;
}
TU_ATTR_ALWAYS_INLINE 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) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec);
return os_sem_pend(sem_hdl, ticks) == OS_OK;
}
static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl)
{
static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) {
// TODO implement later
}
@ -75,19 +75,21 @@ static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl)
typedef struct os_mutex osal_mutex_def_t;
typedef struct os_mutex* osal_mutex_t;
TU_ATTR_ALWAYS_INLINE 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 (os_mutex_init(mdef) == OS_OK) ? (osal_mutex_t) mdef : NULL;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec)
{
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
(void) mutex_hdl;
return true; // nothing to do
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) {
uint32_t const ticks = (msec == OSAL_TIMEOUT_WAIT_FOREVER) ? OS_TIMEOUT_NEVER : os_time_ms_to_ticks32(msec);
return os_mutex_pend(mutex_hdl, ticks) == OS_OK;
}
TU_ATTR_ALWAYS_INLINE 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 os_mutex_release(mutex_hdl) == OS_OK;
}
@ -101,8 +103,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
static struct os_event _name##_##evbuf[_depth];\
osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, .evbuf = _name##_##evbuf};\
typedef struct
{
typedef struct {
uint16_t depth;
uint16_t item_sz;
void* buf;
@ -116,17 +117,20 @@ typedef struct
typedef osal_queue_def_t* osal_queue_t;
TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
{
if ( OS_OK != os_mempool_init(&qdef->mpool, qdef->depth, qdef->item_sz, qdef->buf, "usbd queue") ) return NULL;
if ( OS_OK != os_mempool_init(&qdef->epool, qdef->depth, sizeof(struct os_event), qdef->evbuf, "usbd evqueue") ) return NULL;
TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
if ( OS_OK != os_mempool_init(&qdef->mpool, qdef->depth, qdef->item_sz, qdef->buf, "usb queue") ) return NULL;
if ( OS_OK != os_mempool_init(&qdef->epool, qdef->depth, sizeof(struct os_event), qdef->evbuf, "usb evqueue") ) return NULL;
os_eventq_init(&qdef->evq);
return (osal_queue_t) qdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec)
{
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
(void) qhdl;
return true; // nothing to do
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
(void) msec; // os_eventq_get() does not take timeout, always behave as msec = WAIT_FOREVER
struct os_event* ev;
@ -139,8 +143,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v
return true;
}
static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr)
{
static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) {
(void) in_isr;
// get a block from mem pool for data
@ -150,8 +153,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in
// get a block from event pool to put into queue
struct os_event* ev = (struct os_event*) os_memblock_get(&qhdl->epool);
if (!ev)
{
if (!ev) {
os_memblock_put(&qhdl->mpool, ptr);
return false;
}
@ -163,8 +165,7 @@ static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in
return true;
}
TU_ATTR_ALWAYS_INLINE 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 STAILQ_EMPTY(&qhdl->evq.evq_list);
}

View File

@ -54,6 +54,12 @@ TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_
return semdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
(void) semd_hdl;
return true; // nothing to do
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
(void) in_isr;
sem_hdl->count++;
@ -90,6 +96,11 @@ TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_de
return mdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
(void) mutex_hdl;
return true; // nothing to do
}
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);
}
@ -143,6 +154,11 @@ TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_de
return (osal_queue_t) qdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
(void) qhdl;
return true; // nothing to do
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
(void) msec; // not used, always behave as msec = 0

View File

@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
#ifndef _TUSB_OSAL_PICO_H_
#define _TUSB_OSAL_PICO_H_
#ifndef TUSB_OSAL_PICO_H_
#define TUSB_OSAL_PICO_H_
#include "pico/time.h"
#include "pico/sem.h"
@ -33,42 +33,42 @@
#include "pico/critical_section.h"
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
//--------------------------------------------------------------------+
// TASK API
//--------------------------------------------------------------------+
TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
{
TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) {
sleep_ms(msec);
}
//--------------------------------------------------------------------+
// Binary Semaphore API
//--------------------------------------------------------------------+
typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t;
typedef struct semaphore osal_semaphore_def_t, * osal_semaphore_t;
TU_ATTR_ALWAYS_INLINE 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) {
sem_init(semdef, 0, 255);
return semdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
{
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
(void) semd_hdl;
return true; // nothing to do
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
(void) in_isr;
sem_release(sem_hdl);
return true;
}
TU_ATTR_ALWAYS_INLINE 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) {
return sem_acquire_timeout_ms(sem_hdl, msec);
}
TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl)
{
TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) {
sem_reset(sem_hdl, 0);
}
@ -76,21 +76,23 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t s
// MUTEX API
// Within tinyusb, mutex is never used in ISR context
//--------------------------------------------------------------------+
typedef struct mutex osal_mutex_def_t, *osal_mutex_t;
typedef struct mutex osal_mutex_def_t, * osal_mutex_t;
TU_ATTR_ALWAYS_INLINE 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) {
mutex_init(mdef);
return mdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec)
{
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
(void) mutex_hdl;
return true; // nothing to do
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) {
return mutex_enter_timeout_ms(mutex_hdl, msec);
}
TU_ATTR_ALWAYS_INLINE 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) {
mutex_exit(mutex_hdl);
return true;
}
@ -100,75 +102,54 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
//--------------------------------------------------------------------+
#include "common/tusb_fifo.h"
typedef struct
{
tu_fifo_t ff;
struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section
typedef struct {
tu_fifo_t ff;
struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section
} osal_queue_def_t;
typedef osal_queue_def_t* osal_queue_t;
// role device/host is used by OS NONE for mutex (disable usb isr) only
#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
uint8_t _name##_buf[_depth*sizeof(_type)]; \
osal_queue_def_t _name = { \
.ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \
}
// lock queue by disable USB interrupt
TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl)
{
critical_section_enter_blocking(&qhdl->critsec);
}
// unlock queue
TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl)
{
critical_section_exit(&qhdl->critsec);
}
TU_ATTR_ALWAYS_INLINE 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) {
critical_section_init(&qdef->critsec);
tu_fifo_clear(&qdef->ff);
return (osal_queue_t) qdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec)
{
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
osal_queue_def_t* qdef = (osal_queue_def_t*) qhdl;
critical_section_deinit(&qdef->critsec);
return true;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
(void) msec; // not used, always behave as msec = 0
// TODO: revisit... docs say that mutexes are never used from IRQ context,
// however osal_queue_recieve may be. therefore my assumption is that
// the fifo mutex is not populated for queues used from an IRQ context
//assert(!qhdl->ff.mutex);
_osal_q_lock(qhdl);
critical_section_enter_blocking(&qhdl->critsec);
bool success = tu_fifo_read(&qhdl->ff, data);
_osal_q_unlock(qhdl);
critical_section_exit(&qhdl->critsec);
return success;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr)
{
// TODO: revisit... docs say that mutexes are never used from IRQ context,
// however osal_queue_recieve may be. therefore my assumption is that
// the fifo mutex is not populated for queues used from an IRQ context
//assert(!qhdl->ff.mutex);
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) {
(void) in_isr;
_osal_q_lock(qhdl);
critical_section_enter_blocking(&qhdl->critsec);
bool success = tu_fifo_write(&qhdl->ff, data);
_osal_q_unlock(qhdl);
critical_section_exit(&qhdl->critsec);
TU_ASSERT(success);
return success;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl)
{
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) {
// TODO: revisit; whether this is true or not currently, tu_fifo_empty is a single
// volatile read.
@ -178,7 +159,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl)
}
#ifdef __cplusplus
}
}
#endif
#endif /* _TUSB_OSAL_PICO_H_ */
#endif

View File

@ -25,8 +25,8 @@
* This file is part of the TinyUSB stack.
*/
#ifndef _TUSB_OSAL_RTTHREAD_H_
#define _TUSB_OSAL_RTTHREAD_H_
#ifndef TUSB_OSAL_RTTHREAD_H_
#define TUSB_OSAL_RTTHREAD_H_
// RT-Thread Headers
#include "rtthread.h"
@ -48,23 +48,27 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) {
typedef struct rt_semaphore osal_semaphore_def_t;
typedef rt_sem_t osal_semaphore_t;
TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t
osal_semaphore_create(osal_semaphore_def_t *semdef) {
rt_sem_init(semdef, "tusb", 0, RT_IPC_FLAG_PRIO);
return semdef;
TU_ATTR_ALWAYS_INLINE static inline
osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) {
rt_sem_init(semdef, "tusb", 0, RT_IPC_FLAG_PRIO);
return semdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
return RT_EOK == rt_sem_detach(semd_hdl);
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
(void) in_isr;
return rt_sem_release(sem_hdl) == RT_EOK;
(void) in_isr;
return rt_sem_release(sem_hdl) == RT_EOK;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) {
return rt_sem_take(sem_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK;
return rt_sem_take(sem_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK;
}
TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) {
rt_sem_control(sem_hdl, RT_IPC_CMD_RESET, 0);
rt_sem_control(sem_hdl, RT_IPC_CMD_RESET, 0);
}
//--------------------------------------------------------------------+
@ -74,16 +78,20 @@ typedef struct rt_mutex osal_mutex_def_t;
typedef rt_mutex_t osal_mutex_t;
TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) {
rt_mutex_init(mdef, "tusb", RT_IPC_FLAG_PRIO);
return mdef;
rt_mutex_init(mdef, "tusb", RT_IPC_FLAG_PRIO);
return mdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
return RT_EOK == rt_mutex_detach(mutex_hdl);
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) {
return rt_mutex_take(mutex_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK;
return rt_mutex_take(mutex_hdl, rt_tick_from_millisecond((rt_int32_t) msec)) == RT_EOK;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) {
return rt_mutex_release(mutex_hdl) == RT_EOK;
return rt_mutex_release(mutex_hdl) == RT_EOK;
}
//--------------------------------------------------------------------+
@ -106,31 +114,35 @@ typedef struct {
typedef rt_mq_t osal_queue_t;
TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) {
rt_mq_init(&(qdef->sq), "tusb", qdef->buf, qdef->item_sz,
qdef->item_sz * qdef->depth, RT_IPC_FLAG_PRIO);
return &(qdef->sq);
rt_mq_init(&(qdef->sq), "tusb", qdef->buf, qdef->item_sz,
qdef->item_sz * qdef->depth, RT_IPC_FLAG_PRIO);
return &(qdef->sq);
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
return RT_EOK == rt_mq_detach(qhdl);
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec) {
rt_tick_t tick = rt_tick_from_millisecond((rt_int32_t) msec);
rt_tick_t tick = rt_tick_from_millisecond((rt_int32_t) msec);
#if RT_VERSION_MAJOR >= 5
return rt_mq_recv(qhdl, data, qhdl->msg_size, tick) > 0;
return rt_mq_recv(qhdl, data, qhdl->msg_size, tick) > 0;
#else
return rt_mq_recv(qhdl, data, qhdl->msg_size, tick) == RT_EOK;
return rt_mq_recv(qhdl, data, qhdl->msg_size, tick) == RT_EOK;
#endif /* RT_VERSION_MAJOR >= 5 */
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) {
(void) in_isr;
return rt_mq_send(qhdl, (void *)data, qhdl->msg_size) == RT_EOK;
(void) in_isr;
return rt_mq_send(qhdl, (void *)data, qhdl->msg_size) == RT_EOK;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) {
return (qhdl->entry) == 0;
return (qhdl->entry) == 0;
}
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_OSAL_RTTHREAD_H_ */
#endif

View File

@ -25,8 +25,8 @@
* This file is part of the TinyUSB stack.
*/
#ifndef _TUSB_OSAL_RTX4_H_
#define _TUSB_OSAL_RTX4_H_
#ifndef TUSB_OSAL_RTX4_H_
#define TUSB_OSAL_RTX4_H_
#include <rtl.h>
@ -37,8 +37,7 @@ extern "C" {
//--------------------------------------------------------------------+
// TASK API
//--------------------------------------------------------------------+
TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
{
TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) {
uint16_t hi = msec >> 16;
uint16_t lo = msec;
while (hi--) {
@ -48,12 +47,13 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec)
}
TU_ATTR_ALWAYS_INLINE static inline uint16_t msec2wait(uint32_t msec) {
if (msec == OSAL_TIMEOUT_WAIT_FOREVER)
if (msec == OSAL_TIMEOUT_WAIT_FOREVER) {
return 0xFFFF;
else if (msec >= 0xFFFE)
} else if (msec >= 0xFFFE) {
return 0xFFFE;
else
} else {
return msec;
}
}
//--------------------------------------------------------------------+
@ -67,6 +67,11 @@ TU_ATTR_ALWAYS_INLINE static inline OS_ID osal_semaphore_create(osal_semaphore_d
return semdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) {
(void) semd_hdl;
return true; // nothing to do
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) {
if ( !in_isr ) {
os_sem_send(sem_hdl);
@ -90,19 +95,21 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t c
typedef OS_MUT osal_mutex_def_t;
typedef OS_ID osal_mutex_t;
TU_ATTR_ALWAYS_INLINE 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) {
os_mut_init(mdef);
return mdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec)
{
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) {
(void) mutex_hdl;
return true; // nothing to do
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) {
return os_mut_wait(mutex_hdl, msec2wait(msec)) != OS_R_TMO;
}
TU_ATTR_ALWAYS_INLINE 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 os_mut_release(mutex_hdl) == OS_R_OK;
}
@ -116,9 +123,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
_declare_box(_name##__pool, sizeof(_type), _depth); \
osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .pool = _name##__pool, .mbox = _name##__mbox };
typedef struct
{
typedef struct {
uint16_t depth;
uint16_t item_sz;
U32* pool;
@ -127,15 +132,13 @@ typedef struct
typedef osal_queue_def_t* osal_queue_t;
TU_ATTR_ALWAYS_INLINE 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) {
os_mbx_init(qdef->mbox, (qdef->depth + 4) * 4);
_init_box(qdef->pool, ((qdef->item_sz+3)/4)*(qdef->depth) + 3, qdef->item_sz);
return qdef;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec)
{
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
void* buf;
os_mbx_wait(qhdl->mbox, &buf, msec2wait(msec));
memcpy(data, buf, qhdl->item_sz);
@ -143,23 +146,23 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v
return true;
}
TU_ATTR_ALWAYS_INLINE 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_delete(osal_queue_t qhdl) {
(void) qhdl;
return true; // nothing to do ?
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) {
void* buf = _alloc_box(qhdl->pool);
memcpy(buf, data, qhdl->item_sz);
if ( !in_isr )
{
if ( !in_isr ) {
os_mbx_send(qhdl->mbox, buf, 0xFFFF);
}
else
{
} else {
isr_mbx_send(qhdl->mbox, buf);
}
return true;
}
TU_ATTR_ALWAYS_INLINE 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 os_mbx_check(qhdl->mbox) == qhdl->depth;
}

View File

@ -44,15 +44,15 @@
//--------------------------------------------------------------------+
bool tusb_init(void) {
#if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT)
#if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT)
// init device stack CFG_TUSB_RHPORTx_MODE must be defined
TU_ASSERT ( tud_init(TUD_OPT_RHPORT) );
#endif
#endif
#if CFG_TUH_ENABLED && defined(TUH_OPT_RHPORT)
#if CFG_TUH_ENABLED && defined(TUH_OPT_RHPORT)
// init host stack CFG_TUSB_RHPORTx_MODE must be defined
TU_ASSERT( tuh_init(TUH_OPT_RHPORT) );
#endif
#endif
return true;
}
@ -60,13 +60,13 @@ bool tusb_init(void) {
bool tusb_inited(void) {
bool ret = false;
#if CFG_TUD_ENABLED
#if CFG_TUD_ENABLED
ret = ret || tud_inited();
#endif
#endif
#if CFG_TUH_ENABLED
#if CFG_TUH_ENABLED
ret = ret || tuh_inited();
#endif
#endif
return ret;
}
@ -168,18 +168,17 @@ bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed) {
return true;
}
void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id) {
void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len,
uint8_t driver_id) {
uint8_t const* p_desc = (uint8_t const*) desc_itf;
uint8_t const* desc_end = p_desc + desc_len;
while (p_desc < desc_end) {
if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) {
uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress;
TU_LOG(2, " Bind EP %02x to driver id %u\r\n", ep_addr, driver_id);
ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id;
}
p_desc = tu_desc_next(p_desc);
}
}
@ -195,8 +194,9 @@ uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf,
while (len < max_len) {
// return on IAD regardless of itf count
if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION) return len;
if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION) {
return len;
}
if ((tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) &&
((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0) {
break;
@ -216,7 +216,7 @@ uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf,
bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable,
void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize) {
osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutex);
osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutexdef);
(void) new_mutex;
(void) is_tx;
@ -230,7 +230,17 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove
return true;
}
TU_ATTR_ALWAYS_INLINE static inline bool stream_claim(tu_edpt_stream_t* s) {
bool tu_edpt_stream_deinit(tu_edpt_stream_t* s) {
(void) s;
#if OSAL_MUTEX_REQUIRED
if (s->ff.mutex_wr) osal_mutex_delete(s->ff.mutex_wr);
if (s->ff.mutex_rd) osal_mutex_delete(s->ff.mutex_rd);
#endif
return true;
}
TU_ATTR_ALWAYS_INLINE static inline
bool stream_claim(tu_edpt_stream_t* s) {
if (s->is_host) {
#if CFG_TUH_ENABLED
return usbh_edpt_claim(s->daddr, s->ep_addr);
@ -240,11 +250,11 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_claim(tu_edpt_stream_t* s) {
return usbd_edpt_claim(s->rhport, s->ep_addr);
#endif
}
return false;
}
TU_ATTR_ALWAYS_INLINE static inline bool stream_xfer(tu_edpt_stream_t* s, uint16_t count) {
TU_ATTR_ALWAYS_INLINE static inline
bool stream_xfer(tu_edpt_stream_t* s, uint16_t count) {
if (s->is_host) {
#if CFG_TUH_ENABLED
return usbh_edpt_xfer(s->daddr, s->ep_addr, count ? s->ep_buf : NULL, count);
@ -254,11 +264,11 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_xfer(tu_edpt_stream_t* s, uint16
return usbd_edpt_xfer(s->rhport, s->ep_addr, count ? s->ep_buf : NULL, count);
#endif
}
return false;
}
TU_ATTR_ALWAYS_INLINE static inline bool stream_release(tu_edpt_stream_t* s) {
TU_ATTR_ALWAYS_INLINE static inline
bool stream_release(tu_edpt_stream_t* s) {
if (s->is_host) {
#if CFG_TUH_ENABLED
return usbh_edpt_release(s->daddr, s->ep_addr);
@ -268,20 +278,17 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_release(tu_edpt_stream_t* s) {
return usbd_edpt_release(s->rhport, s->ep_addr);
#endif
}
return false;
}
//--------------------------------------------------------------------+
// Stream Write
//--------------------------------------------------------------------+
bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t* s, uint32_t last_xferred_bytes) {
// ZLP condition: no pending data, last transferred bytes is multiple of packet size
TU_VERIFY(!tu_fifo_count(&s->ff) && last_xferred_bytes && (0 == (last_xferred_bytes & (s->ep_packetsize - 1))));
TU_VERIFY(stream_claim(s));
TU_ASSERT(stream_xfer(s, 0));
return true;
}
@ -308,7 +315,6 @@ uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t* s) {
uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const* buffer, uint32_t bufsize) {
TU_VERIFY(bufsize); // TODO support ZLP
uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize);
// flush if fifo has more than packet size or
@ -323,7 +329,6 @@ uint32_t tu_edpt_stream_write(tu_edpt_stream_t* s, void const* buffer, uint32_t
//--------------------------------------------------------------------+
// Stream Read
//--------------------------------------------------------------------+
uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s) {
uint16_t available = tu_fifo_remaining(&s->ff);
@ -343,6 +348,7 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t* s) {
// multiple of packet size limit by ep bufsize
uint16_t count = (uint16_t) (available & ~(s->ep_packetsize - 1));
count = tu_min16(count, s->ep_bufsize);
TU_ASSERT(stream_xfer(s, count), 0);
return count;
} else {
@ -390,13 +396,11 @@ char const* const tu_str_xfer_result[] = {
static void dump_str_line(uint8_t const* buf, uint16_t count) {
tu_printf(" |");
// each line is 16 bytes
for (uint16_t i = 0; i < count; i++) {
const char ch = buf[i];
tu_printf("%c", isprint(ch) ? ch : '.');
}
tu_printf("|\r\n");
}
@ -407,17 +411,14 @@ static void dump_str_line(uint8_t const* buf, uint16_t count) {
*/
void tu_print_mem(void const* buf, uint32_t count, uint8_t indent) {
uint8_t const size = 1; // fixed 1 byte for now
if (!buf || !count) {
tu_printf("NULL\r\n");
return;
}
uint8_t const* buf8 = (uint8_t const*) buf;
char format[] = "%00X";
format[2] += (uint8_t) (2 * size); // 1 byte = 2 hex digits
const uint8_t item_per_line = 16 / size;
for (unsigned int i = 0; i < count; i++) {
@ -425,12 +426,8 @@ void tu_print_mem(void const* buf, uint32_t count, uint8_t indent) {
if (i % item_per_line == 0) {
// Print Ascii
if (i != 0) {
dump_str_line(buf8 - 16, 16);
}
if (i != 0) dump_str_line(buf8 - 16, 16);
for (uint8_t s = 0; s < indent; s++) tu_printf(" ");
// print offset or absolute address
tu_printf("%04X: ", 16 * i / item_per_line);
}
@ -445,7 +442,6 @@ void tu_print_mem(void const* buf, uint32_t count, uint8_t indent) {
// fill up last row to 16 for printing ascii
const uint32_t remain = count % 16;
uint8_t nback = (uint8_t) (remain ? remain : 16);
if (remain) {
for (uint32_t i = 0; i < 16 - remain; i++) {
tu_printf(" ");

View File

@ -29,9 +29,14 @@
#include "common/tusb_compiler.h"
// Version is release as major.minor.revision eg 1.0.0. though there could be notable APIs before a new release.
// For notable API changes within a release, we increase the build number.
#define TUSB_VERSION_MAJOR 0
#define TUSB_VERSION_MINOR 16
#define TUSB_VERSION_REVISION 0
#define TUSB_VERSION_BUILD 1
#define TUSB_VERSION_NUMBER (TUSB_VERSION_MAJOR << 24 | TUSB_VERSION_MINOR << 16 | TUSB_VERSION_REVISION << 8 | TUSB_VERSION_BUILD)
#define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION)
//--------------------------------------------------------------------+