From cdaf1eef5cc0b5e638d1cf23e2a733ae837b789f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thi=C3=A9baud=20Fuchs?= Date: Fri, 6 Sep 2024 19:32:02 +0200 Subject: [PATCH 1/3] Add nested critical section macro --- src/CMakeLists.txt | 4 +- .../HSPIDeviceScheduled/hspi_scheduled.c | 5 +- src/wch-ch56x-lib/USBDevice/usb_device.h | 12 +++-- src/wch-ch56x-lib/logging/log_printf.c | 6 ++- src/wch-ch56x-lib/logging/log_serdes.c | 6 +-- src/wch-ch56x-lib/logging/log_to_buffer.c | 10 ++-- src/wch-ch56x-lib/memory/alloc.c | 15 +++++- src/wch-ch56x-lib/memory/alloc.h | 9 ++++ src/wch-ch56x-lib/memory/fifo.h | 33 ++++++------ src/wch-ch56x-lib/memory/pool.h | 17 +++--- src/wch-ch56x-lib/memory/ramx_alloc.h | 31 +++++++++-- .../fifo.c => utils/critical_section.c} | 11 ++-- src/wch-ch56x-lib/utils/critical_section.h | 52 +++++++++++++++++++ 13 files changed, 154 insertions(+), 57 deletions(-) rename src/wch-ch56x-lib/{memory/fifo.c => utils/critical_section.c} (71%) create mode 100644 src/wch-ch56x-lib/utils/critical_section.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d6985e5..b732572 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,7 @@ add_library(wch-ch56x-lib INTERFACE) # With HSPIDeviceScheduled target_sources(wch-ch56x-lib INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/utils/critical_section.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/HSPIDevice/hspi.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/interrupt_queue/interrupt_queue.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/logging/log_printf.c @@ -10,7 +11,6 @@ target_sources(wch-ch56x-lib INTERFACE ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/logging/logging.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/logging/nanoprintf_impl.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/memory/alloc.c - ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/memory/fifo.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/memory/ramx_alloc.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/SerDesDevice/serdes.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/USBDevice/usb_device.c @@ -28,6 +28,7 @@ target_link_libraries(wch-ch56x-lib INTERFACE wch-ch56x-bsp lwrb nanoprintf) add_library(wch-ch56x-lib-scheduled INTERFACE) target_sources(wch-ch56x-lib-scheduled INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/utils/critical_section.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/HSPIDeviceScheduled/hspi_scheduled.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/interrupt_queue/interrupt_queue.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/logging/log_printf.c @@ -36,7 +37,6 @@ target_sources(wch-ch56x-lib-scheduled INTERFACE ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/logging/logging.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/logging/nanoprintf_impl.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/memory/alloc.c - ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/memory/fifo.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/memory/ramx_alloc.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/SerDesDevice/serdes.c ${CMAKE_CURRENT_LIST_DIR}/wch-ch56x-lib/USBDevice/usb_device.c diff --git a/src/wch-ch56x-lib/HSPIDeviceScheduled/hspi_scheduled.c b/src/wch-ch56x-lib/HSPIDeviceScheduled/hspi_scheduled.c index 98785e0..b74efe7 100644 --- a/src/wch-ch56x-lib/HSPIDeviceScheduled/hspi_scheduled.c +++ b/src/wch-ch56x-lib/HSPIDeviceScheduled/hspi_scheduled.c @@ -23,6 +23,7 @@ limitations under the License. #include "wch-ch56x-lib/logging/logging.h" #include "wch-ch56x-lib/memory/fifo.h" #include "wch-ch56x-lib/memory/pool.h" +#include "wch-ch56x-lib/utils/critical_section.h" #include __attribute__((aligned(16))) uint8_t* hspi_rx_buffer_0; @@ -251,7 +252,7 @@ bool _hspi_send(uint8_t* data) if (hspi_task_args == NULL) return false; - bsp_disable_interrupt(); + BSP_ENTER_CRITICAL(); if (R8_HSPI_TX_SC & RB_HSPI_TX_TOG) { R32_HSPI_TX_ADDR1 = (vuint32_t)hspi_task_args->args.buffer; @@ -277,7 +278,7 @@ bool _hspi_send(uint8_t* data) // tx1_addr[1], tx1_addr[2], tx1_addr[3], tx1_addr[4]); } hspi_transmission_finished = false; - bsp_enable_interrupt(); + BSP_EXIT_CRITICAL(); HSPI_DMA_Tx(); diff --git a/src/wch-ch56x-lib/USBDevice/usb_device.h b/src/wch-ch56x-lib/USBDevice/usb_device.h index c0eb129..2fce06a 100644 --- a/src/wch-ch56x-lib/USBDevice/usb_device.h +++ b/src/wch-ch56x-lib/USBDevice/usb_device.h @@ -45,9 +45,12 @@ USB3.0/USB2.0 management in the back. #pragma GCC diagnostic pop #pragma GCC diagnostic pop #pragma GCC diagnostic pop + +#include "wch-ch56x-lib/logging/logging.h" #include "wch-ch56x-lib/USBDevice/usb_descriptors.h" #include "wch-ch56x-lib/USBDevice/usb_endpoints.h" #include "wch-ch56x-lib/USBDevice/usb_types.h" +#include "wch-ch56x-lib/utils/critical_section.h" #include #ifdef __cplusplus @@ -136,14 +139,14 @@ void usb_device_set_endpoint_mask(usb_device_t* usb_device, uint32_t endpoint_ma __attribute__((always_inline)) inline static bool endp_tx_set_new_buffer(usb_device_t* usb_device, uint8_t endp_num, uint8_t* const ptr, uint16_t size) { - bsp_disable_interrupt(); volatile USB_ENDPOINT* ep = &usb_device->endpoints.tx[endp_num]; + BSP_ENTER_CRITICAL(); + if (size > ep->max_packet_size_with_burst || ptr == 0) { - bsp_enable_interrupt(); + BSP_EXIT_CRITICAL(); return false; } - ep->buffer = ptr; if (endp_num == 0) @@ -152,12 +155,11 @@ endp_tx_set_new_buffer(usb_device_t* usb_device, uint8_t endp_num, uint8_t* cons memcpy(usb_device->endpoints.rx[0].buffer, ptr, size); } - bsp_enable_interrupt(); if (usb_device->speed == USB30_SUPERSPEED) usb3_endpoints_backend_handled.usb3_endp_tx_ready(endp_num, size); else usb2_endpoints_backend_handled.usb2_endp_tx_ready(endp_num, size); - + BSP_EXIT_CRITICAL(); return true; } diff --git a/src/wch-ch56x-lib/logging/log_printf.c b/src/wch-ch56x-lib/logging/log_printf.c index fde55eb..8362eaa 100644 --- a/src/wch-ch56x-lib/logging/log_printf.c +++ b/src/wch-ch56x-lib/logging/log_printf.c @@ -17,7 +17,9 @@ limitations under the License. *******************************************************************************/ #include "wch-ch56x-lib/logging/log_printf.h" +#include "wch-ch56x-lib/logging/logging_definitions.h" #include "wch-ch56x-lib/logging/nanoprintf_impl.h" +#include "wch-ch56x-lib/utils/critical_section.h" // Add option in pre-processor compiler option // CH56x_DEBUG_LOG_BASIC_TIMESTAMP=1 @@ -113,7 +115,7 @@ void _vlog_printf(const char* fmt, va_list args) #endif #endif // ifndef CH56x_DEBUG_LOG_BASIC_TIMESTAMP - bsp_disable_interrupt(); // Enter Critical Section + BSP_ENTER_CRITICAL(); // Enter Critical Section #ifdef CH56x_DEBUG_LOG_BASIC_TIMESTAMP print_size1 = npf_snprintf(log_printf_buff, sizeof(log_printf_buff), "0x%08X ", (uint32_t)(delta)); @@ -137,7 +139,7 @@ void _vlog_printf(const char* fmt, va_list args) } UART1_SendString((uint8_t*)log_printf_buff, print_size2); } - bsp_enable_interrupt(); // Exit Critical Section + BSP_EXIT_CRITICAL(); // Exit Critical Section bsp_uled_off(); } diff --git a/src/wch-ch56x-lib/logging/log_serdes.c b/src/wch-ch56x-lib/logging/log_serdes.c index 56c57d1..cf55a4a 100644 --- a/src/wch-ch56x-lib/logging/log_serdes.c +++ b/src/wch-ch56x-lib/logging/log_serdes.c @@ -17,9 +17,9 @@ limitations under the License. *******************************************************************************/ #include "wch-ch56x-lib/logging/log_serdes.h" -#include "CH56x_common.h" #include "wch-ch56x-lib/logging/nanoprintf_impl.h" #include "wch-ch56x-lib/SerDesDevice/serdes.h" +#include "wch-ch56x-lib/utils/critical_section.h" #include // Add option in pre-processor compiler option @@ -116,7 +116,7 @@ void vlog_serdes(const char* fmt, va_list args) #endif #endif // ifndef CH56x_DEBUG_LOG_BASIC_TIMESTAMP - bsp_disable_interrupt(); // Enter Critical Section + BSP_ENTER_CRITICAL(); // Enter Critical Section #ifdef CH56x_DEBUG_LOG_BASIC_TIMESTAMP print_size1 = npf_snprintf(serdes_buffer, sizeof(serdes_buffer), "0x%08X ", (uint32_t)(delta)); @@ -140,7 +140,7 @@ void vlog_serdes(const char* fmt, va_list args) } serdes_send((uint8_t*)serdes_buffer, print_size2, 0); } - bsp_enable_interrupt(); // Exit Critical Section + BSP_EXIT_CRITICAL(); // Exit Critical Section } void log_serdes(const char* fmt, ...) diff --git a/src/wch-ch56x-lib/logging/log_to_buffer.c b/src/wch-ch56x-lib/logging/log_to_buffer.c index 052df59..9cc2ec2 100644 --- a/src/wch-ch56x-lib/logging/log_to_buffer.c +++ b/src/wch-ch56x-lib/logging/log_to_buffer.c @@ -17,8 +17,8 @@ limitations under the License. *******************************************************************************/ #include "wch-ch56x-lib/logging/log_to_buffer.h" -#include "CH56x_common.h" #include "wch-ch56x-lib/logging/nanoprintf_impl.h" +#include "wch-ch56x-lib/utils/critical_section.h" #include #include "lwrb/lwrb.h" @@ -146,9 +146,9 @@ void vlog_to_buffer(const char* fmt, va_list args) print_size2 += print_size1; if (print_size2 > 0) { - bsp_disable_interrupt(); + BSP_ENTER_CRITICAL(); lwrb_write(&lwrb_buffer, temp_buffer, print_size2); - bsp_enable_interrupt(); + BSP_EXIT_CRITICAL(); } } @@ -180,7 +180,7 @@ void log_to_buffer_dump_to_uart(void) void _write_to_buffer(char* buffer, size_t size) { - bsp_disable_interrupt(); + BSP_ENTER_CRITICAL(); lwrb_write(&lwrb_buffer, buffer, size); - bsp_enable_interrupt(); + BSP_EXIT_CRITICAL(); } diff --git a/src/wch-ch56x-lib/memory/alloc.c b/src/wch-ch56x-lib/memory/alloc.c index 4b42ced..c8d6db5 100644 --- a/src/wch-ch56x-lib/memory/alloc.c +++ b/src/wch-ch56x-lib/memory/alloc.c @@ -35,7 +35,7 @@ static pool_t ram_pool; void pool_init(void) { uint32_t i; - + RAM_ALLOC_ENTER_CRITICAL(); ram_pool.pool_size = POOL_BLOCK_NUM; ram_pool.block_size = POOL_BLOCK_SIZE; ram_pool.blocks_used = 0; @@ -45,6 +45,7 @@ void pool_init(void) { ram_pool.blocks[i] = 0; } + RAM_ALLOC_EXIT_CRITICAL(); } /** @@ -61,13 +62,17 @@ void* pool_alloc_blocks(uint8_t num_blocks) { uint32_t i, j; uint8_t space_found; + void* ret = NULL; + RAM_ALLOC_ENTER_CRITICAL(); if (num_blocks == 0) { + RAM_ALLOC_EXIT_CRITICAL(); return 0; } if (num_blocks > POOL_BLOCK_NUM) { + RAM_ALLOC_EXIT_CRITICAL(); return 0; } @@ -96,10 +101,13 @@ void* pool_alloc_blocks(uint8_t num_blocks) ram_pool.blocks[i + j] = num_blocks; } ram_pool.blocks_used += num_blocks; - return ram_pool.pool + (ram_pool.block_size * i); + ret = ram_pool.pool + (ram_pool.block_size * i); + RAM_ALLOC_EXIT_CRITICAL(); + return ret; } } } + RAM_ALLOC_EXIT_CRITICAL(); return 0; } @@ -131,8 +139,10 @@ void pool_free(void* ptr) { uint8_t block_index, num_blocks, i; + RAM_ALLOC_ENTER_CRITICAL(); if (ptr == 0) { + RAM_ALLOC_EXIT_CRITICAL(); return; } @@ -144,6 +154,7 @@ void pool_free(void* ptr) ram_pool.blocks[block_index + i] = 0; } ram_pool.blocks_used -= num_blocks; + RAM_ALLOC_EXIT_CRITICAL(); } uint8_t pool_stats_free() { return ram_pool.pool_size - ram_pool.blocks_used; } diff --git a/src/wch-ch56x-lib/memory/alloc.h b/src/wch-ch56x-lib/memory/alloc.h index 1632845..18e1428 100644 --- a/src/wch-ch56x-lib/memory/alloc.h +++ b/src/wch-ch56x-lib/memory/alloc.h @@ -19,6 +19,7 @@ limitations under the License. #ifndef _ALLOC_H_ #define _ALLOC_H_ +#include "wch-ch56x-lib/utils/critical_section.h" #include /** @@ -32,6 +33,14 @@ You must pass the following defines to your compiler extern "C" { #endif +#ifndef RAM_ALLOC_ENTER_CRITICAL +#define RAM_ALLOC_ENTER_CRITICAL() BSP_ENTER_CRITICAL() +#endif + +#ifndef RAM_ALLOC_EXIT_CRITICAL +#define RAM_ALLOC_EXIT_CRITICAL() BSP_EXIT_CRITICAL() +#endif + typedef struct pool { uint8_t* pool; diff --git a/src/wch-ch56x-lib/memory/fifo.h b/src/wch-ch56x-lib/memory/fifo.h index c64d400..c84f3d3 100644 --- a/src/wch-ch56x-lib/memory/fifo.h +++ b/src/wch-ch56x-lib/memory/fifo.h @@ -25,6 +25,7 @@ limitations under the License. #include #include "wch-ch56x-lib/logging/logging.h" +#include "wch-ch56x-lib/utils/critical_section.h" #ifdef __cplusplus extern "C" { @@ -90,11 +91,13 @@ typedef struct hydra_fifo_t .rd_idx = 0, \ .wr_idx = 0 } -/** - * @brief Set this pointer to disable/enable interrupts. Not necessary with - * single-producer/single-consumer. - */ -extern void (*hydra_fifo_disable_interrupt)(bool); +#ifndef HYDRA_FIFO_ENTER_CRITICAL +#define HYDRA_FIFO_ENTER_CRITICAL() BSP_ENTER_CRITICAL() +#endif + +#ifndef HYDRA_FIFO_EXIT_CRITICAL +#define HYDRA_FIFO_EXIT_CRITICAL() BSP_EXIT_CRITICAL() +#endif #define ABS(x) x < 0 ? -x : x #define MIN(x, y) x < y ? x : y @@ -262,14 +265,14 @@ _fifo_advance_write(hydra_fifo_t* fifo, uint16_t wr_idx, uint16_t offset) __attribute__((always_inline)) static inline uint16_t fifo_read(hydra_fifo_t* fifo, void* buffer) { - hydra_fifo_disable_interrupt(true); + HYDRA_FIFO_ENTER_CRITICAL(); uint16_t rd_idx = fifo->rd_idx; uint16_t wr_idx = fifo->wr_idx; uint16_t count_read = _fifo_read_n(fifo, buffer, _fifo_get_count(rd_idx, wr_idx, fifo->size), rd_idx, wr_idx); _fifo_advance_read(fifo, rd_idx, count_read); - hydra_fifo_disable_interrupt(false); + HYDRA_FIFO_EXIT_CRITICAL(); return count_read; } @@ -284,12 +287,12 @@ fifo_read(hydra_fifo_t* fifo, void* buffer) __attribute__((always_inline)) static inline uint16_t fifo_read_n(hydra_fifo_t* fifo, void* buffer, uint16_t n) { - hydra_fifo_disable_interrupt(true); + HYDRA_FIFO_ENTER_CRITICAL(); uint16_t rd_idx = fifo->rd_idx; uint16_t wr_idx = fifo->wr_idx; uint16_t count_read = _fifo_read_n(fifo, buffer, n, rd_idx, wr_idx); _fifo_advance_read(fifo, rd_idx, count_read); - hydra_fifo_disable_interrupt(false); + HYDRA_FIFO_EXIT_CRITICAL(); return count_read; } @@ -305,11 +308,11 @@ fifo_read_n(hydra_fifo_t* fifo, void* buffer, uint16_t n) __attribute__((always_inline)) static inline uint16_t fifo_peek_n(hydra_fifo_t* fifo, void* buffer, uint16_t n) { - hydra_fifo_disable_interrupt(true); + HYDRA_FIFO_ENTER_CRITICAL(); uint16_t rd_idx = fifo->rd_idx; uint16_t wr_idx = fifo->wr_idx; uint16_t count_read = _fifo_read_n(fifo, buffer, n, rd_idx, wr_idx); - hydra_fifo_disable_interrupt(false); + HYDRA_FIFO_EXIT_CRITICAL(); return count_read; } @@ -324,12 +327,12 @@ fifo_peek_n(hydra_fifo_t* fifo, void* buffer, uint16_t n) __attribute__((always_inline)) static inline uint16_t fifo_write(hydra_fifo_t* fifo, void* buffer, uint16_t n) { - hydra_fifo_disable_interrupt(true); + HYDRA_FIFO_ENTER_CRITICAL(); uint16_t rd_idx = fifo->rd_idx; uint16_t wr_idx = fifo->wr_idx; uint16_t count_written = _fifo_write_n(fifo, buffer, n, rd_idx, wr_idx); _fifo_advance_write(fifo, wr_idx, count_written); - hydra_fifo_disable_interrupt(false); + HYDRA_FIFO_EXIT_CRITICAL(); return count_written; } @@ -351,11 +354,11 @@ fifo_count(hydra_fifo_t* fifo) __attribute__((always_inline)) static inline void fifo_clean(hydra_fifo_t* fifo) { - hydra_fifo_disable_interrupt(true); + HYDRA_FIFO_ENTER_CRITICAL(); fifo->rd_idx = 0; fifo->wr_idx = 0; memset(fifo->buffer, 0, fifo->size * fifo->type_size); - hydra_fifo_disable_interrupt(false); + HYDRA_FIFO_EXIT_CRITICAL(); } #ifdef __cplusplus diff --git a/src/wch-ch56x-lib/memory/pool.h b/src/wch-ch56x-lib/memory/pool.h index 5577772..014e568 100644 --- a/src/wch-ch56x-lib/memory/pool.h +++ b/src/wch-ch56x-lib/memory/pool.h @@ -30,6 +30,7 @@ limitations under the License. #pragma GCC diagnostic pop #pragma GCC diagnostic pop +#include "wch-ch56x-lib/utils/critical_section.h" #include #include #include @@ -74,18 +75,18 @@ typedef struct hydra_pool_t __attribute__((always_inline)) static inline void* hydra_pool_get(hydra_pool_t* pool) { - bsp_disable_interrupt(); + BSP_ENTER_CRITICAL(); for (uint16_t i = 0; i < pool->size; ++i) { if (!pool->pool_manager[i]) { pool->pool_manager[i] = true; - bsp_enable_interrupt(); + BSP_EXIT_CRITICAL(); return (void*)(pool->pool_members + i * pool->type_size); } } LOG_IF_LEVEL(LOG_LEVEL_CRITICAL, "Pool %x is full\r\n", pool); - bsp_enable_interrupt(); + BSP_EXIT_CRITICAL(); return NULL; } @@ -98,14 +99,14 @@ __attribute__((always_inline)) static inline void hydra_pool_free(hydra_pool_t* pool, void* ptr) { uint16_t i = ((uint8_t*)(ptr)-pool->pool_members) / pool->type_size; - bsp_disable_interrupt(); + BSP_ENTER_CRITICAL(); if (i >= pool->size || !pool->pool_manager[i]) { - bsp_enable_interrupt(); + BSP_EXIT_CRITICAL(); return; } pool->pool_manager[i] = false; - bsp_enable_interrupt(); + BSP_EXIT_CRITICAL(); } /** @@ -115,13 +116,13 @@ hydra_pool_free(hydra_pool_t* pool, void* ptr) __attribute__((always_inline)) static inline void hydra_pool_clean(hydra_pool_t* pool) { - bsp_disable_interrupt(); + BSP_ENTER_CRITICAL(); for (uint16_t i = 0; i < pool->size; ++i) { pool->pool_manager[i] = false; } memset(pool->pool_members, 0, pool->size * pool->type_size); - bsp_enable_interrupt(); + BSP_EXIT_CRITICAL(); } #ifdef __cplusplus diff --git a/src/wch-ch56x-lib/memory/ramx_alloc.h b/src/wch-ch56x-lib/memory/ramx_alloc.h index a4ec5c3..150ab7d 100644 --- a/src/wch-ch56x-lib/memory/ramx_alloc.h +++ b/src/wch-ch56x-lib/memory/ramx_alloc.h @@ -23,6 +23,7 @@ limitations under the License. #include #include "wch-ch56x-lib/logging/logging.h" +#include "wch-ch56x-lib/utils/critical_section.h" /** You must pass the following defines to your compiler @@ -35,6 +36,14 @@ You must pass the following defines to your compiler extern "C" { #endif +#ifndef RAMX_ALLOC_ENTER_CRITICAL +#define RAMX_ALLOC_ENTER_CRITICAL() BSP_ENTER_CRITICAL() +#endif + +#ifndef RAMX_ALLOC_EXIT_CRITICAL +#define RAMX_ALLOC_EXIT_CRITICAL() BSP_EXIT_CRITICAL() +#endif + /* Taken from linux kernel */ #define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) @@ -83,13 +92,17 @@ __attribute__((always_inline)) static inline void* ramx_pool_alloc_blocks(uint8_ { uint32_t i, j; uint8_t space_found; + void* ret = NULL; + RAMX_ALLOC_ENTER_CRITICAL(); if (num_blocks == 0) { + RAMX_ALLOC_EXIT_CRITICAL(); return 0; } if (num_blocks > POOL_BLOCK_NUM) { + RAMX_ALLOC_EXIT_CRITICAL(); return 0; } @@ -119,10 +132,13 @@ __attribute__((always_inline)) static inline void* ramx_pool_alloc_blocks(uint8_ ramx_pool.blocks_reference_counter[i + j] = 1; } ramx_pool.blocks_used += num_blocks; - return ramx_pool.pool + (ramx_pool.block_size * i); + ret = ramx_pool.pool + (ramx_pool.block_size * i); + RAMX_ALLOC_EXIT_CRITICAL(); + return ret; } } } + RAMX_ALLOC_EXIT_CRITICAL(); return 0; } @@ -145,12 +161,13 @@ __attribute__((always_inline)) static inline void* ramx_pool_alloc_bytes(uint32_ */ __attribute__((always_inline)) static inline void ramx_take_ownership(void* ptr) { - LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "ramx_take_ownership ptr %x free %d used %d \r\n", ptr, ramx_pool_stats_free(), ramx_pool_stats_used()); - uint8_t block_index, num_blocks, i; + RAMX_ALLOC_ENTER_CRITICAL(); + LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "ramx_take_ownership ptr %x free %d used %d \r\n", ptr, ramx_pool_stats_free(), ramx_pool_stats_used()); if (ptr == 0) { + RAMX_ALLOC_EXIT_CRITICAL(); return; } @@ -162,6 +179,7 @@ __attribute__((always_inline)) static inline void ramx_take_ownership(void* ptr) { ramx_pool.blocks_reference_counter[block_index + i] += 1; } + RAMX_ALLOC_EXIT_CRITICAL(); } /** @@ -172,13 +190,15 @@ __attribute__((always_inline)) static inline void ramx_take_ownership(void* ptr) */ __attribute__((always_inline)) static inline void ramx_pool_free(void* ptr) { - LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "ramx_pool_free ptr %x free %d used %d \r\n", ptr, ramx_pool_stats_free(), ramx_pool_stats_used()); - uint8_t block_index, num_blocks, i; uint8_t num_freed = 0; + RAMX_ALLOC_ENTER_CRITICAL(); + + LOG_IF_LEVEL(LOG_LEVEL_DEBUG, "ramx_pool_free ptr %x free %d used %d \r\n", ptr, ramx_pool_stats_free(), ramx_pool_stats_used()); if (ptr == 0) { + RAMX_ALLOC_EXIT_CRITICAL(); return; } @@ -199,6 +219,7 @@ __attribute__((always_inline)) static inline void ramx_pool_free(void* ptr) } } ramx_pool.blocks_used -= num_freed; + RAMX_ALLOC_EXIT_CRITICAL(); } #ifdef __cplusplus diff --git a/src/wch-ch56x-lib/memory/fifo.c b/src/wch-ch56x-lib/utils/critical_section.c similarity index 71% rename from src/wch-ch56x-lib/memory/fifo.c rename to src/wch-ch56x-lib/utils/critical_section.c index eb829dc..c0a6e41 100644 --- a/src/wch-ch56x-lib/memory/fifo.c +++ b/src/wch-ch56x-lib/utils/critical_section.c @@ -1,6 +1,5 @@ /********************************** (C) COPYRIGHT ******************************* -Copyright (c) 2023 Quarkslab - +Copyright (c) 2024 Quarkslab Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,10 +15,6 @@ limitations under the License. *******************************************************************************/ -#include "wch-ch56x-lib/memory/fifo.h" - -void _default_hydra_fifo_disable_interrupt(bool disable); -void _default_hydra_fifo_disable_interrupt(bool /*disable*/) {} +#include "wch-ch56x-lib/utils/critical_section.h" -void (*hydra_fifo_disable_interrupt)(bool) = - _default_hydra_fifo_disable_interrupt; +size_t bsp_critical_nesting = 0; diff --git a/src/wch-ch56x-lib/utils/critical_section.h b/src/wch-ch56x-lib/utils/critical_section.h new file mode 100644 index 0000000..ee0f238 --- /dev/null +++ b/src/wch-ch56x-lib/utils/critical_section.h @@ -0,0 +1,52 @@ +/********************************** (C) COPYRIGHT ******************************* +Copyright (c) 2024 Quarkslab + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*******************************************************************************/ + +#ifndef CRITICAL_SECTION_H +#define CRITICAL_SECTION_H + +// Disable warnings in bsp arising from -pedantic -Wall -Wconversion +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#pragma GCC diagnostic ignored "-Wvariadic-macros" +#pragma GCC diagnostic ignored "-Wsign-conversion" +#include "CH56x_common.h" +#include "CH56xSFR.h" +#pragma GCC diagnostic pop +#pragma GCC diagnostic pop +#pragma GCC diagnostic pop + +/** + * Totally based on FreeRTOS +*/ + +extern size_t bsp_critical_nesting; +#define BSP_ENTER_CRITICAL() \ + { \ + bsp_disable_interrupt(); \ + bsp_critical_nesting++; \ + } + +#define BSP_EXIT_CRITICAL() \ + { \ + bsp_critical_nesting--; \ + if (bsp_critical_nesting == 0) \ + { \ + bsp_enable_interrupt(); \ + } \ + } + +#endif From 5f77e3b4585376682baac64ae7b282df7e7d8cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thi=C3=A9baud=20Fuchs?= Date: Fri, 6 Sep 2024 19:32:41 +0200 Subject: [PATCH 2/3] Fix unnecessary condition in USB3 --- src/wch-ch56x-lib/USBDevice/usb30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wch-ch56x-lib/USBDevice/usb30.c b/src/wch-ch56x-lib/USBDevice/usb30.c index 92d035f..805ae9e 100644 --- a/src/wch-ch56x-lib/USBDevice/usb30.c +++ b/src/wch-ch56x-lib/USBDevice/usb30.c @@ -552,7 +552,7 @@ usb30_ep_in_handler(uint8_t endp_num) } } - if (nump == 0 && *usb30_get_tx_endpoint_remaining_length(endp_num) == 0) + if (*usb30_get_tx_endpoint_remaining_length(endp_num) == 0) { LOG_IF(LOG_LEVEL_DEBUG, LOG_ID_USB3, "Finished IN transfer on ep %d, remaining length %d\r\n", endp_num, From ecf7f47daaf68abe4931e71cbf8dbd337b054571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thi=C3=A9baud=20Fuchs?= Date: Fri, 6 Sep 2024 19:34:13 +0200 Subject: [PATCH 3/3] Add USB3 to usb stress test : not ready yet --- .../test_firmware_usb_stress_test/User/main.c | 19 ++ .../User/usb3_ss_device_descriptors.h | 173 ++++++++++++++++++ .../User/usb_device.h | 19 ++ 3 files changed, 211 insertions(+) create mode 100644 tests/test_firmware_usb_stress_test/User/usb3_ss_device_descriptors.h diff --git a/tests/test_firmware_usb_stress_test/User/main.c b/tests/test_firmware_usb_stress_test/User/main.c index 39acc9b..bc201ec 100644 --- a/tests/test_firmware_usb_stress_test/User/main.c +++ b/tests/test_firmware_usb_stress_test/User/main.c @@ -29,9 +29,11 @@ limitations under the License. #include "usb2_fs_device_descriptors.h" #include "usb2_hs_device_descriptors.h" #include "usb2_ls_device_descriptors.h" +#include "usb3_ss_device_descriptors.h" #include "usb_device.h" #include "wch-ch56x-lib/logging/logging.h" #include "wch-ch56x-lib/USBDevice/usb20.h" +#include "wch-ch56x-lib/USBDevice/usb30.h" #include "wch-ch56x-lib/USBDevice/usb_descriptors.h" #include "wch-ch56x-lib/USBDevice/usb_endpoints.h" @@ -242,6 +244,23 @@ int main() usb2_device_init(); usb2_enable_nak(true); } + else if (usb_device_0.speed == USB30_SUPERSPEED) + { + /* + IMPORTANT NOTE : won't work. This firmware detects IN requests by detecting NAK. + WCH does not provide documentation for the USB3 controller and examples do not use NAKs (in USB2 as well, but USB3 has not documentation). + */ + // Finish initializing the descriptor parameters + init_usb3_ss_descriptors(); + init_string_descriptors(); + + usb_device_set_usb3_device_descriptor(&usb_device_0, &usb3_descriptors.usb_device_descr); + usb_device_set_usb3_config_descriptors(&usb_device_0, usb3_device_configs); + usb_device_set_bos_descriptor(&usb_device_0, &usb3_descriptors.capabilities.usb_bos_descr); + usb_device_set_endpoint_mask(&usb_device_0, ENDPOINT_1_RX | ENDPOINT_2_TX); + init_endpoints_ss(); + usb30_device_init(false); + } // Infinite loop USB2/USB3 managed with Interrupt while (1) diff --git a/tests/test_firmware_usb_stress_test/User/usb3_ss_device_descriptors.h b/tests/test_firmware_usb_stress_test/User/usb3_ss_device_descriptors.h new file mode 100644 index 0000000..573c6f2 --- /dev/null +++ b/tests/test_firmware_usb_stress_test/User/usb3_ss_device_descriptors.h @@ -0,0 +1,173 @@ +/********************************** (C) COPYRIGHT ******************************* +Copyright (c) 2023 Quarkslab + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*******************************************************************************/ + +#ifndef USB3_DEVICE_DESCRIPTOR_H +#define USB3_DEVICE_DESCRIPTOR_H + +#include "definitions.h" +#include "wch-ch56x-lib/USBDevice/usb_descriptors.h" + +const uint8_t* usb3_device_configs[1]; + +struct usb3_descriptors +{ + USB_DEV_DESCR usb_device_descr; + struct __PACKED + { + USB_CFG_DESCR usb_cfg_descr; + USB_ITF_DESCR usb_itf_descr; + USB_ENDP_DESCR usb_endp_descr_1; + USB_ENDP_COMPANION_DESCR usb_endp_companion_descr_1; + USB_ENDP_DESCR usb_endp_descr_2_tx; + USB_ENDP_COMPANION_DESCR usb_endp_companion_descr_2_tx; + } other_descr; + struct __PACKED + { + USB_BOS_DESCR usb_bos_descr; + USB_BOS_USB2_EXTENSION usb_bos_usb2_extension; + USB_BOS_SUPERSPEED_USB_DEVICE_CAPABILITY + usb_bos_superspeed_usb_device_capability; + } capabilities; +} usb3_descriptors; + +void init_usb3_ss_descriptors(void); + +void init_usb3_ss_descriptors(void) +{ + usb3_descriptors.usb_device_descr = (USB_DEV_DESCR){ + .bLength = 0x12, + .bDescriptorType = 0x01, // device descriptor type + .bcdUSB = 0x0300, // usb3.0 + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = 9, // this is a requirement for usb3 (max packet size = + // 2^9 thus the 9) + .bcdDevice = 0x0001, + .idVendor = + 0x1209, // https://github.com/obdev/v-usb/blob/master/usbdrv/usb-ids-for-free.txt + .idProduct = 0x0001, + .iProduct = 0x01, + .iManufacturer = 0x00, + .iSerialNumber = 0x00, + .bNumConfigurations = 0x01 + }; + + usb3_descriptors.other_descr.usb_cfg_descr = (USB_CFG_DESCR){ + .bLength = 0x09, + .bDescriptorType = 0x02, + .wTotalLength = sizeof(usb3_descriptors.other_descr), + .bNumInterfaces = 0x01, + .bConfigurationValue = 0x01, + .iConfiguration = 0x00, + .bmAttributes = 0xa0, // supports remote wake-up + .MaxPower = 100 // x2 in HS (200mA), x8 in 3.x (800mA) + }; + + usb3_descriptors.other_descr.usb_itf_descr = + (USB_ITF_DESCR){ .bLength = 0x09, + .bDescriptorType = 0x04, + .bInterfaceNumber = 0x00, + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x02, + .bInterfaceClass = 0xff, // vendor-specific + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .iInterface = 0x00 }; + + usb3_descriptors.other_descr.usb_endp_descr_1 = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_OUT | 0x01) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x04, // 1024 bytes + .bInterval = 0 + }; + + usb3_descriptors.other_descr.usb_endp_companion_descr_1 = + (USB_ENDP_COMPANION_DESCR){ + .bLength = 0x06, + .bDescriptorType = 0x30, + .bMaxBurst = DEF_ENDP_IN_BURST_LEVEL - 1, + .bmAttributes = 0x00, + .wBytesPerInterval = 0x00, + }; + + usb3_descriptors.capabilities.usb_bos_descr = (USB_BOS_DESCR){ + .bLength = 0x05, + .bDescriptorType = 0x0f, + .wTotalLength = sizeof( + usb3_descriptors.capabilities), // number of bytes of this descriptor + // and all its subordinates + .bNumDeviceCaps = 0x02 // number of device capability descriptor contained + // in this BOS descriptor + }; + + usb3_descriptors.other_descr.usb_endp_descr_2_tx = (USB_ENDP_DESCR){ + .bLength = 0x07, + .bDescriptorType = 0x05, + .bEndpointAddress = (ENDPOINT_DESCRIPTOR_ADDRESS_IN | 0x02) & + ENDPOINT_DESCRIPTOR_ADDRESS_MASK, + .bmAttributes = ENDPOINT_DESCRIPTOR_BULK_TRANSFER, + .wMaxPacketSizeL = 0x00, + .wMaxPacketSizeH = 0x04, // 1024 bytes + .bInterval = 0 + }; + + usb3_descriptors.other_descr.usb_endp_companion_descr_2_tx = + (USB_ENDP_COMPANION_DESCR){ + .bLength = 0x06, + .bDescriptorType = 0x30, + .bMaxBurst = DEF_ENDP_IN_BURST_LEVEL - 1, + .bmAttributes = 0x00, + .wBytesPerInterval = 0x00, + }; + + usb3_descriptors.capabilities.usb_bos_usb2_extension = + (USB_BOS_USB2_EXTENSION){ + .capability = + (USB_BOS_DEVICE_CAPABILITY_DESCR){ .bLength = 0x07, + .bDescriptorType = 0x10, + .bDevCapabilityType = 0x02 }, + .bmAttributes = + 0xf41e // LPM Capable=1, BESL And Alternate HIRD Supported=1, + // Baseline BESL Valid=1, Deep BESL Valid=1, + // Baseline BESL=4 (400 us), Deep BESL=15 (10000 us) + }; + + usb3_descriptors.capabilities.usb_bos_superspeed_usb_device_capability = + (USB_BOS_SUPERSPEED_USB_DEVICE_CAPABILITY){ + .capability = + (USB_BOS_DEVICE_CAPABILITY_DESCR){ .bLength = 0x0a, + .bDescriptorType = 0x10, + .bDevCapabilityType = 0x03 }, + .bmAttributes = 0x00, + .wSpeedsSupported = + SUPERSPEED_USB_DEVICE_CAPABILITY_SUPPORTED_SPEEDS_SS | + SUPERSPEED_USB_DEVICE_CAPABILITY_SUPPORTED_SPEEDS_HS, + .bFunctionalitySupport = + SUPERSPEED_USB_DEVICE_CAPABILITY_SUPPORTED_SPEEDS_HS, + .bU1DevExitLat = 0x0a, // max 0xa (10us) + .wU2DevExitLat = 0x7ff // max 0x7ff (2047us) + }; + + usb3_device_configs[0] = (uint8_t*)&usb3_descriptors.other_descr; +} + +#endif diff --git a/tests/test_firmware_usb_stress_test/User/usb_device.h b/tests/test_firmware_usb_stress_test/User/usb_device.h index 9042c4d..0b173c8 100644 --- a/tests/test_firmware_usb_stress_test/User/usb_device.h +++ b/tests/test_firmware_usb_stress_test/User/usb_device.h @@ -187,6 +187,25 @@ void init_string_descriptors(void) &usb_string_descriptors.product_string_descriptor; } +void init_endpoints_ss(void); +void init_endpoints_ss(void) +{ + usb_device_0.endpoints.rx[0].buffer = endp0_buffer; + usb_device_0.endpoints.rx[0].max_packet_size = 512; + usb_device_0.endpoints.rx[0].max_burst = 1; + usb_device_0.endpoints.rx[0].max_packet_size_with_burst = 512; + + usb_device_0.endpoints.rx[1].buffer = endp1_rx_buffer; + usb_device_0.endpoints.rx[1].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.rx[1].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.rx[1].max_packet_size_with_burst = ENDP_1_15_MAX_PACKET_SIZE * DEF_ENDP_OUT_BURST_LEVEL; + + usb_device_0.endpoints.tx[2].buffer = NULL; + usb_device_0.endpoints.tx[2].max_packet_size = ENDP_1_15_MAX_PACKET_SIZE; + usb_device_0.endpoints.tx[2].max_burst = DEF_ENDP_OUT_BURST_LEVEL; + usb_device_0.endpoints.tx[2].max_packet_size_with_burst = ENDP_1_15_MAX_PACKET_SIZE * DEF_ENDP_OUT_BURST_LEVEL; +} + void init_endpoints_hs(void); void init_endpoints_hs(void) {