Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the use of non-static allocation for FreeRTOS mutexes & queues #1767

Merged
merged 8 commits into from
Dec 5, 2022
11 changes: 9 additions & 2 deletions examples/device/cdc_msc_freertos/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,15 @@ SRC_C += \
$(FREERTOS_SRC)/timers.c \
$(subst ../../../,,$(wildcard ../../../$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT)/*.c))

# Suppress FreeRTOS warnings
CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls
# include heap manage if configSUPPORT_DYNAMIC_ALLOCATION = 1
# SRC_C += $(FREERTOS_SRC)/portable/MemMang/heap_1.c
# CFLAGS += -Wno-error=sign-compare

# Suppress FreeRTOSConfig.h warnings
CFLAGS += -Wno-error=redundant-decls

# Suppress FreeRTOS source warnings
CFLAGS += -Wno-error=cast-qual

# FreeRTOS (lto + Os) linker issue
LDFLAGS += -Wl,--undefined=vTaskSwitchContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( 0*1024 ) // dynamic is not used
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
Expand Down
24 changes: 16 additions & 8 deletions examples/device/cdc_msc_freertos/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
#endif

#define CDC_STACK_SZIE configMINIMAL_STACK_SIZE

//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
Expand All @@ -66,19 +68,18 @@ enum {
BLINK_SUSPENDED = 2500,
};

// static timer
// static timer & task
#if configSUPPORT_STATIC_ALLOCATION
StaticTimer_t blinky_tmdef;
TimerHandle_t blinky_tm;

// static task
StackType_t usb_device_stack[USBD_STACK_SIZE];
StaticTask_t usb_device_taskdef;

// static task for cdc
#define CDC_STACK_SZIE configMINIMAL_STACK_SIZE
StackType_t cdc_stack[CDC_STACK_SZIE];
StaticTask_t cdc_taskdef;
#endif

TimerHandle_t blinky_tm;

void led_blinky_cb(TimerHandle_t xTimer);
void usb_device_task(void* param);
Expand All @@ -92,15 +93,22 @@ int main(void)
{
board_init();

#if configSUPPORT_STATIC_ALLOCATION
// soft timer for blinky
blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef);
xTimerStart(blinky_tm, 0);

// Create a task for tinyusb device stack
(void) xTaskCreateStatic( usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef);
xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef);

// Create CDC task
(void) xTaskCreateStatic( cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef);
xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef);
#else
blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb);
xTaskCreate( usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL);
xTaskCreate( cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL);
#endif

xTimerStart(blinky_tm, 0);

// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
#if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
Expand Down
11 changes: 9 additions & 2 deletions examples/device/hid_composite_freertos/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,15 @@ SRC_C += \
$(FREERTOS_SRC)/timers.c \
$(subst ../../../,,$(wildcard ../../../$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT)/*.c))

# Suppress FreeRTOS warnings
CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls
# include heap manage if configSUPPORT_DYNAMIC_ALLOCATION = 1
# SRC_C += $(FREERTOS_SRC)/portable/MemMang/heap_1.c
# CFLAGS += -Wno-error=sign-compare

# Suppress FreeRTOSConfig.h warnings
CFLAGS += -Wno-error=redundant-decls

# Suppress FreeRTOS source warnings
CFLAGS += -Wno-error=cast-qual

# FreeRTOS (lto + Os) linker issue
LDFLAGS += -Wl,--undefined=vTaskSwitchContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@
#include "bsp/board_mcu.h"

#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3
#error "ESP32-Sx should use IDF's FreeRTOSConfig.h"
#error "ESP32-Sx should use IDF's FreeRTOSConfig.h"
#endif

// TODO fix later
#if CFG_TUSB_MCU == OPT_MCU_MM32F327X
// TODO fix/remove later
extern u32 SystemCoreClock;
#else
// FIXME cause redundant-decls warnings
extern uint32_t SystemCoreClock;
#endif

Expand All @@ -68,7 +69,7 @@
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( 0*1024 ) // dynamic is not used
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
Expand Down
24 changes: 16 additions & 8 deletions examples/device/hid_composite_freertos/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
#define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
#endif

#define HID_STACK_SZIE configMINIMAL_STACK_SIZE

//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
Expand All @@ -68,19 +70,18 @@ enum {
BLINK_SUSPENDED = 2500,
};

// static timer
// static timer & task
#if configSUPPORT_STATIC_ALLOCATION
StaticTimer_t blinky_tmdef;
TimerHandle_t blinky_tm;

// static task
StackType_t usb_device_stack[USBD_STACK_SIZE];
StaticTask_t usb_device_taskdef;

// static task for hid
#define HID_STACK_SZIE configMINIMAL_STACK_SIZE
StackType_t hid_stack[HID_STACK_SZIE];
StaticTask_t hid_taskdef;
#endif

TimerHandle_t blinky_tm;

void led_blinky_cb(TimerHandle_t xTimer);
void usb_device_task(void* param);
Expand All @@ -94,15 +95,22 @@ int main(void)
{
board_init();

#if configSUPPORT_STATIC_ALLOCATION
// soft timer for blinky
blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef);
xTimerStart(blinky_tm, 0);

// Create a task for tinyusb device stack
(void) xTaskCreateStatic( usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef);
xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef);

// Create HID task
(void) xTaskCreateStatic( hid_task, "hid", HID_STACK_SZIE, NULL, configMAX_PRIORITIES-2, hid_stack, &hid_taskdef);
xTaskCreateStatic(hid_task, "hid", HID_STACK_SZIE, NULL, configMAX_PRIORITIES-2, hid_stack, &hid_taskdef);
#else
blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb);
xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL);
xTaskCreate(hid_task, "hid", HID_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL);
#endif

xTimerStart(blinky_tm, 0);

// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
#if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
Expand Down
80 changes: 54 additions & 26 deletions src/osal/osal_freertos.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,43 @@
extern "C" {
#endif

//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+

#if configSUPPORT_STATIC_ALLOCATION
typedef StaticSemaphore_t osal_semaphore_def_t;
typedef StaticSemaphore_t osal_mutex_def_t;
#else
// not used therefore defined to smallest possible type to save space
typedef uint8_t osal_semaphore_def_t;
typedef uint8_t osal_mutex_def_t;
#endif

typedef SemaphoreHandle_t osal_semaphore_t;
typedef SemaphoreHandle_t osal_mutex_t;

// _int_set is not used with an RTOS
#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
static _type _name##_##buf[_depth];\
osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf };

typedef struct
{
uint16_t depth;
uint16_t item_sz;
void* buf;
#if configSUPPORT_STATIC_ALLOCATION
StaticQueue_t sq;
#endif
}osal_queue_def_t;

typedef QueueHandle_t osal_queue_t;

//--------------------------------------------------------------------+
// TASK API
//--------------------------------------------------------------------+

TU_ATTR_ALWAYS_INLINE static inline uint32_t _osal_ms2tick(uint32_t msec)
{
if (msec == OSAL_TIMEOUT_WAIT_FOREVER) return portMAX_DELAY;
Expand All @@ -51,9 +88,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t _osal_ms2tick(uint32_t msec)
return ticks;
}

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

TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef)
{
#if configSUPPORT_STATIC_ALLOCATION
return xSemaphoreCreateBinaryStatic(semdef);
#else
(void) semdef;
return xSemaphoreCreateBinary();
hathach marked this conversation as resolved.
Show resolved Hide resolved
#endif
}

TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr)
Expand All @@ -92,7 +129,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t se
}
}

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 xSemaphoreTake(sem_hdl, _osal_ms2tick(msec));
}
Expand All @@ -105,15 +142,18 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t c
//--------------------------------------------------------------------+
// MUTEX API (priority inheritance)
//--------------------------------------------------------------------+
typedef StaticSemaphore_t osal_mutex_def_t;
typedef SemaphoreHandle_t osal_mutex_t;

TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef)
{
#if configSUPPORT_STATIC_ALLOCATION
return xSemaphoreCreateMutexStatic(mdef);
#else
(void) mdef;
return xSemaphoreCreateMutex();
#endif
}

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_lock(osal_mutex_t mutex_hdl, uint32_t msec)
{
return osal_semaphore_wait(mutex_hdl, msec);
}
Expand All @@ -127,25 +167,13 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd
// QUEUE API
//--------------------------------------------------------------------+

// _int_set is not used with an RTOS
#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
static _type _name##_##buf[_depth];\
osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf };

typedef struct
{
uint16_t depth;
uint16_t item_sz;
void* buf;

StaticQueue_t sq;
}osal_queue_def_t;

typedef QueueHandle_t osal_queue_t;

TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef)
{
return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq);
#if configSUPPORT_STATIC_ALLOCATION
return xQueueCreateStatic(qdef->depth, qdef->item_sz, (uint8_t*) qdef->buf, &qdef->sq);
hathach marked this conversation as resolved.
Show resolved Hide resolved
#else
return xQueueCreate(qdef->depth, qdef->item_sz);
#endif
}

TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec)
Expand Down