Merge branch 'change/usb_host_minor_optimizations_v5.2' into 'release/v5.2'

change(usb/host): Remove unecessary features (v5.2)

See merge request espressif/esp-idf!27593
This commit is contained in:
morris 2024-02-19 10:41:44 +08:00
commit 4bd5fa28b4
4 changed files with 81 additions and 107 deletions

View File

@ -938,7 +938,7 @@ esp_err_t hub_install(hub_config_t *hub_config)
HUB_DRIVER_EXIT_CRITICAL();
// Allocate Hub driver object
hub_driver_t *hub_driver_obj = heap_caps_calloc(1, sizeof(hub_driver_t), MALLOC_CAP_DEFAULT);
urb_t *enum_urb = urb_alloc(sizeof(usb_setup_packet_t) + ENUM_CTRL_TRANSFER_MAX_DATA_LEN, 0, 0);
urb_t *enum_urb = urb_alloc(sizeof(usb_setup_packet_t) + ENUM_CTRL_TRANSFER_MAX_DATA_LEN, 0);
if (hub_driver_obj == NULL || enum_urb == NULL) {
return ESP_ERR_NO_MEM;
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -43,7 +43,6 @@ struct urb_s {
uint32_t hcd_var;
// Host Lib Layer:
void *usb_host_client; // Currently only used when submitted to shared pipes (i.e., Device default pipes)
size_t usb_host_header_size; // USB Host may need the data buffer to have a transparent header
bool usb_host_inflight; // Debugging variable, used to prevent re-submitting URBs already inflight
// Public transfer structure. Must be last due to variable length array
usb_transfer_t transfer;
@ -76,15 +75,13 @@ typedef bool (*usb_proc_req_cb_t)(usb_proc_req_source_t source, bool in_isr, voi
*
* - Data buffer is allocated in DMA capable memory
* - The constant fields of the URB are also set
* - The data_buffer field of the URB is set to point to start of the allocated data buffer AFTER the header. To access
* the header, users need a negative offset from data_buffer.
* - The data_buffer field of the URB is set to point to start of the allocated data buffer.
*
* @param data_buffer_size Size of the URB's data buffer
* @param header_size Size of header to put in front of URB's data buffer
* @param num_isoc_packets Number of isochronous packet descriptors
* @return urb_t* URB object
*/
urb_t *urb_alloc(size_t data_buffer_size, size_t header_size, int num_isoc_packets);
urb_t *urb_alloc(size_t data_buffer_size, int num_isoc_packets);
/**
* @brief Free a URB

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -94,11 +94,9 @@ struct client_s {
TAILQ_HEAD(tailhead_done_ctrl_xfers, urb_s) done_ctrl_xfer_tailq;
union {
struct {
uint32_t events_pending: 1;
uint32_t handling_events: 1;
uint32_t blocked: 1;
uint32_t taking_mux: 1;
uint32_t reserved4: 4;
uint32_t reserved6: 6;
uint32_t num_intf_claimed: 8;
uint32_t reserved16: 16;
};
@ -128,10 +126,8 @@ typedef struct {
uint32_t lib_event_flags;
union {
struct {
uint32_t process_pending: 1;
uint32_t handling_events: 1;
uint32_t blocked: 1;
uint32_t reserved5: 5;
uint32_t reserved7: 7;
uint32_t num_clients: 8;
uint32_t reserved16: 16;
};
@ -176,24 +172,16 @@ static inline bool _check_client_opened_device(client_t *client_obj, uint8_t dev
static bool _unblock_client(client_t *client_obj, bool in_isr)
{
bool send_sem;
if (!client_obj->dynamic.flags.events_pending && !client_obj->dynamic.flags.handling_events) {
client_obj->dynamic.flags.events_pending = 1;
send_sem = true;
} else {
send_sem = false;
}
bool yield;
HOST_EXIT_CRITICAL_SAFE();
bool yield = false;
if (send_sem) {
if (in_isr) {
BaseType_t xTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(client_obj->constant.event_sem, &xTaskWoken);
yield = (xTaskWoken == pdTRUE);
} else {
xSemaphoreGive(client_obj->constant.event_sem);
}
yield = false;
}
HOST_ENTER_CRITICAL_SAFE();
@ -202,24 +190,16 @@ static bool _unblock_client(client_t *client_obj, bool in_isr)
static bool _unblock_lib(bool in_isr)
{
bool send_sem;
if (!p_host_lib_obj->dynamic.flags.process_pending && !p_host_lib_obj->dynamic.flags.handling_events) {
p_host_lib_obj->dynamic.flags.process_pending = 1;
send_sem = true;
} else {
send_sem = false;
}
bool yield;
HOST_EXIT_CRITICAL_SAFE();
bool yield = false;
if (send_sem) {
if (in_isr) {
BaseType_t xTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(p_host_lib_obj->constant.event_sem, &xTaskWoken);
yield = (xTaskWoken == pdTRUE);
} else {
xSemaphoreGive(p_host_lib_obj->constant.event_sem);
}
yield = false;
}
HOST_ENTER_CRITICAL_SAFE();
@ -515,45 +495,49 @@ esp_err_t usb_host_uninstall(void)
esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_flags_ret)
{
esp_err_t ret;
uint32_t event_flags = 0;
// Check arguments and state
HOST_CHECK(p_host_lib_obj != NULL, ESP_ERR_INVALID_STATE);
esp_err_t ret = (timeout_ticks == 0) ? ESP_OK : ESP_ERR_TIMEOUT; // We don't want to return ESP_ERR_TIMEOUT if we aren't blocking
uint32_t event_flags;
HOST_ENTER_CRITICAL();
if (!p_host_lib_obj->dynamic.flags.process_pending) {
// There is currently processing that needs to be done. Wait for some processing
// Set handling_events flag. This prevents the host library from being uninstalled
p_host_lib_obj->dynamic.flags.handling_events = 1;
HOST_EXIT_CRITICAL();
BaseType_t sem_ret = xSemaphoreTake(p_host_lib_obj->constant.event_sem, timeout_ticks);
if (sem_ret == pdFALSE) {
ret = ESP_ERR_TIMEOUT;
goto exit;
}
HOST_ENTER_CRITICAL();
while (1) {
// Loop until there are no more events
if (xSemaphoreTake(p_host_lib_obj->constant.event_sem, timeout_ticks) == pdFALSE) {
// Timed out waiting for semaphore or currently no events
break;
}
// Read and clear process pending flags
HOST_ENTER_CRITICAL();
uint32_t process_pending_flags = p_host_lib_obj->dynamic.process_pending_flags;
p_host_lib_obj->dynamic.process_pending_flags = 0;
p_host_lib_obj->dynamic.flags.handling_events = 1;
while (process_pending_flags) {
HOST_EXIT_CRITICAL();
if (process_pending_flags & PROCESS_REQUEST_PENDING_FLAG_USBH) {
ESP_ERROR_CHECK(usbh_process());
}
if (process_pending_flags & PROCESS_REQUEST_PENDING_FLAG_HUB) {
ESP_ERROR_CHECK(hub_process());
}
HOST_ENTER_CRITICAL();
// Read and clear process pending flags again, and loop back if there is more to process
process_pending_flags = p_host_lib_obj->dynamic.process_pending_flags;
p_host_lib_obj->dynamic.process_pending_flags = 0;
ret = ESP_OK;
// Set timeout_ticks to 0 so that we can check for events again without blocking
timeout_ticks = 0;
}
p_host_lib_obj->dynamic.flags.process_pending = 0;
HOST_ENTER_CRITICAL();
p_host_lib_obj->dynamic.flags.handling_events = 0;
// Read and clear any event flags
event_flags = p_host_lib_obj->dynamic.lib_event_flags;
p_host_lib_obj->dynamic.lib_event_flags = 0;
HOST_EXIT_CRITICAL();
ret = ESP_OK;
exit:
if (event_flags_ret != NULL) {
*event_flags_ret = event_flags;
}
@ -709,7 +693,6 @@ esp_err_t usb_host_client_deregister(usb_host_client_handle_t client_hdl)
!TAILQ_EMPTY(&client_obj->dynamic.idle_ep_tailq) ||
!TAILQ_EMPTY(&client_obj->dynamic.done_ctrl_xfer_tailq) ||
client_obj->dynamic.flags.handling_events ||
client_obj->dynamic.flags.blocked ||
client_obj->dynamic.flags.taking_mux ||
client_obj->dynamic.flags.num_intf_claimed != 0 ||
client_obj->dynamic.num_done_ctrl_xfer != 0 ||
@ -746,28 +729,26 @@ exit:
esp_err_t usb_host_client_handle_events(usb_host_client_handle_t client_hdl, TickType_t timeout_ticks)
{
// Check arguments and state
HOST_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG);
esp_err_t ret;
HOST_CHECK(p_host_lib_obj != NULL, ESP_ERR_INVALID_STATE);
esp_err_t ret = (timeout_ticks == 0) ? ESP_OK : ESP_ERR_TIMEOUT; // We don't want to return ESP_ERR_TIMEOUT if we aren't blocking
client_t *client_obj = (client_t *)client_hdl;
HOST_ENTER_CRITICAL();
if (!client_obj->dynamic.flags.events_pending) {
// There are currently no events, wait for one to occur
client_obj->dynamic.flags.blocked = 1;
HOST_EXIT_CRITICAL();
BaseType_t sem_ret = xSemaphoreTake(client_obj->constant.event_sem, timeout_ticks);
HOST_ENTER_CRITICAL();
client_obj->dynamic.flags.blocked = 0;
if (sem_ret == pdFALSE) {
HOST_EXIT_CRITICAL();
// Timed out waiting for semaphore
ret = ESP_ERR_TIMEOUT;
goto exit;
}
}
// Mark that we're processing events
// Set handling_events flag. This prevents the client from being deregistered
client_obj->dynamic.flags.handling_events = 1;
while (client_obj->dynamic.flags.handling_events) {
HOST_EXIT_CRITICAL();
while (1) {
// Loop until there are no more events
if (xSemaphoreTake(client_obj->constant.event_sem, timeout_ticks) == pdFALSE) {
// Timed out waiting for semaphore or currently no events
break;
}
HOST_ENTER_CRITICAL();
// Handle pending endpoints
if (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq)) {
_handle_pending_ep(client_obj);
@ -784,29 +765,26 @@ esp_err_t usb_host_client_handle_events(usb_host_client_handle_t client_hdl, Tic
urb->transfer.callback(&urb->transfer);
HOST_ENTER_CRITICAL();
}
HOST_EXIT_CRITICAL();
// Handle event messages
while (uxQueueMessagesWaiting(client_obj->constant.event_msg_queue) > 0) {
HOST_EXIT_CRITICAL();
// Dequeue the event message and call the client event callback
usb_host_client_event_msg_t event_msg;
BaseType_t queue_ret = xQueueReceive(client_obj->constant.event_msg_queue, &event_msg, 0);
assert(queue_ret == pdTRUE);
client_obj->constant.event_callback(&event_msg, client_obj->constant.callback_arg);
HOST_ENTER_CRITICAL();
}
// Check each event again to see any new events occurred
if (TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq) &&
client_obj->dynamic.num_done_ctrl_xfer == 0 &&
uxQueueMessagesWaiting(client_obj->constant.event_msg_queue) == 0) {
// All pending endpoints and event messages handled
client_obj->dynamic.flags.events_pending = 0;
client_obj->dynamic.flags.handling_events = 0;
}
}
HOST_EXIT_CRITICAL();
ret = ESP_OK;
exit:
// Set timeout_ticks to 0 so that we can check for events again without blocking
timeout_ticks = 0;
}
HOST_ENTER_CRITICAL();
client_obj->dynamic.flags.handling_events = 0;
HOST_EXIT_CRITICAL();
return ret;
}
@ -1245,7 +1223,7 @@ exit:
esp_err_t usb_host_transfer_alloc(size_t data_buffer_size, int num_isoc_packets, usb_transfer_t **transfer)
{
urb_t *urb = urb_alloc(data_buffer_size, 0, num_isoc_packets);
urb_t *urb = urb_alloc(data_buffer_size, num_isoc_packets);
if (urb == NULL) {
return ESP_ERR_NO_MEM;
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -8,17 +8,16 @@
#include "usb_private.h"
#include "usb/usb_types_ch9.h"
urb_t *urb_alloc(size_t data_buffer_size, size_t header_size, int num_isoc_packets)
urb_t *urb_alloc(size_t data_buffer_size, int num_isoc_packets)
{
urb_t *urb = heap_caps_calloc(1, sizeof(urb_t) + (sizeof(usb_isoc_packet_desc_t) * num_isoc_packets), MALLOC_CAP_DEFAULT);
uint8_t *data_buffer = heap_caps_malloc(data_buffer_size + header_size, MALLOC_CAP_DMA);
uint8_t *data_buffer = heap_caps_malloc(data_buffer_size, MALLOC_CAP_DMA);
if (urb == NULL || data_buffer == NULL) {
goto err;
}
urb->usb_host_header_size = header_size; // Indicate that this URB's data_buffer has a header in front of it.
// Case as dummy transfer to write to initialize const fields
// Cast as dummy transfer so that we can assign to const fields
usb_transfer_dummy_t *dummy_transfer = (usb_transfer_dummy_t *)&urb->transfer;
dummy_transfer->data_buffer = (uint8_t *)(data_buffer + header_size);
dummy_transfer->data_buffer = data_buffer;
dummy_transfer->data_buffer_size = data_buffer_size;
dummy_transfer->num_isoc_packets = num_isoc_packets;
return urb;
@ -33,6 +32,6 @@ void urb_free(urb_t *urb)
if (urb == NULL) {
return;
}
heap_caps_free((uint8_t *)(urb->transfer.data_buffer - urb->usb_host_header_size));
heap_caps_free(urb->transfer.data_buffer);
heap_caps_free(urb);
}