Skip to content

Commit 5595065

Browse files
committed
add freertos build support for video_capture example
1 parent d52909e commit 5595065

File tree

6 files changed

+170
-23
lines changed

6 files changed

+170
-23
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# This file is for ESP-IDF only
2+
idf_component_register(SRCS "main.c" "usb_descriptors.c"
3+
INCLUDE_DIRS "."
4+
REQUIRES boards tinyusb_src)

examples/device/video_capture/src/main.c

Lines changed: 117 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,25 @@ enum {
4848

4949
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
5050

51-
void led_blinking_task(void);
52-
void video_task(void);
51+
void led_blinking_task(void* param);
52+
void usb_device_task(void *param);
53+
void video_task(void* param);
5354

54-
/*------------- MAIN -------------*/
55+
#if CFG_TUSB_OS == OPT_OS_FREERTOS
56+
void freertos_init_task(void);
57+
#endif
58+
59+
60+
//--------------------------------------------------------------------+
61+
// Main
62+
//--------------------------------------------------------------------+
5563
int main(void) {
5664
board_init();
5765

66+
// If using FreeRTOS: create blinky, tinyusb device, video task
67+
#if CFG_TUSB_OS == OPT_OS_FREERTOS
68+
freertos_init_task();
69+
#else
5870
// init device stack on configured roothub port
5971
tud_init(BOARD_TUD_RHPORT);
6072

@@ -64,10 +76,10 @@ int main(void) {
6476

6577
while (1) {
6678
tud_task(); // tinyusb device task
67-
led_blinking_task();
68-
69-
video_task();
79+
led_blinking_task(NULL);
80+
video_task(NULL);
7081
}
82+
#endif
7183
}
7284

7385
//--------------------------------------------------------------------+
@@ -169,7 +181,7 @@ static void fill_color_bar(uint8_t* buffer, unsigned start_position) {
169181

170182
#endif
171183

172-
void video_task(void) {
184+
void video_send_frame(void) {
173185
static unsigned start_ms = 0;
174186
static unsigned already_sent = 0;
175187

@@ -213,6 +225,21 @@ void video_task(void) {
213225
#endif
214226
}
215227

228+
229+
void video_task(void* param) {
230+
(void) param;
231+
232+
while(1) {
233+
video_send_frame();
234+
235+
#if CFG_TUSB_OS == OPT_OS_FREERTOS
236+
vTaskDelay(interval_ms / portTICK_PERIOD_MS);
237+
#else
238+
return;
239+
#endif
240+
}
241+
}
242+
216243
void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) {
217244
(void) ctl_idx;
218245
(void) stm_idx;
@@ -231,16 +258,92 @@ int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx,
231258
}
232259

233260
//--------------------------------------------------------------------+
234-
// BLINKING TASK
261+
// Blinking Task
235262
//--------------------------------------------------------------------+
236-
void led_blinking_task(void) {
263+
void led_blinking_task(void* param) {
264+
(void) param;
237265
static uint32_t start_ms = 0;
238266
static bool led_state = false;
239267

240-
// Blink every interval ms
241-
if (board_millis() - start_ms < blink_interval_ms) return; // not enough time
242-
start_ms += blink_interval_ms;
268+
while (1) {
269+
#if CFG_TUSB_OS == OPT_OS_FREERTOS
270+
vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS);
271+
#else
272+
if (board_millis() - start_ms < blink_interval_ms) return; // not enough time
273+
#endif
274+
275+
start_ms += blink_interval_ms;
276+
board_led_write(led_state);
277+
led_state = 1 - led_state; // toggle
278+
}
279+
}
280+
281+
//--------------------------------------------------------------------+
282+
// FreeRTOS
283+
//--------------------------------------------------------------------+
284+
#if CFG_TUSB_OS == OPT_OS_FREERTOS
285+
286+
#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE
287+
#define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4)
288+
289+
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
290+
#define USBD_STACK_SIZE 4096
291+
int main(void);
292+
void app_main(void) {
293+
main();
294+
}
295+
#else
296+
// Increase stack size when debug log is enabled
297+
#define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
298+
#endif
299+
300+
// static task
301+
#if configSUPPORT_STATIC_ALLOCATION
302+
StackType_t blinky_stack[BLINKY_STACK_SIZE];
303+
StaticTask_t blinky_taskdef;
304+
305+
StackType_t usb_device_stack[USBD_STACK_SIZE];
306+
StaticTask_t usb_device_taskdef;
307+
308+
StackType_t video_stack[VIDEO_STACK_SIZE];
309+
StaticTask_t video_taskdef;
310+
#endif
311+
312+
// USB Device Driver task
313+
// This top level thread process all usb events and invoke callbacks
314+
void usb_device_task(void *param) {
315+
(void) param;
316+
317+
// init device stack on configured roothub port
318+
// This should be called after scheduler/kernel is started.
319+
// Otherwise, it could cause kernel issue since USB IRQ handler does use RTOS queue API.
320+
tud_init(BOARD_TUD_RHPORT);
321+
322+
if (board_init_after_tusb) {
323+
board_init_after_tusb();
324+
}
243325

244-
board_led_write(led_state);
245-
led_state = 1 - led_state; // toggle
326+
// RTOS forever loop
327+
while (1) {
328+
// put this thread to waiting state until there is new events
329+
tud_task();
330+
}
246331
}
332+
333+
void freertos_init_task(void) {
334+
#if configSUPPORT_STATIC_ALLOCATION
335+
xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef);
336+
xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef);
337+
xTaskCreateStatic(video_task, "cdc", VIDEO_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, video_stack, &video_taskdef);
338+
#else
339+
xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL);
340+
xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL);
341+
xTaskCreate(video_task, "video", VIDEO_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL);
342+
#endif
343+
344+
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
345+
#if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
346+
vTaskStartScheduler();
347+
#endif
348+
}
349+
#endif

examples/device/video_capture/src/tusb_config.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@
5757
#define CFG_TUSB_OS OPT_OS_NONE
5858
#endif
5959

60+
// Espressif IDF requires "freertos/" prefix in include path
61+
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
62+
#define CFG_TUSB_OS_INC_PATH freertos/
63+
#endif
64+
6065
#ifndef CFG_TUSB_DEBUG
6166
#define CFG_TUSB_DEBUG 0
6267
#endif
@@ -103,6 +108,9 @@
103108
// use bulk endpoint for streaming interface
104109
#define CFG_TUD_VIDEO_STREAMING_BULK 1
105110

111+
//#define CFG_EXAMPLE_VIDEO_READONLY
112+
//#define CFG_EXAMPLE_VIDEO_DISABLE_MJPEG
113+
106114
#ifdef __cplusplus
107115
}
108116
#endif

examples/device/video_capture/src/usb_descriptors.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,22 @@ const uvc_cfg_desc_t desc_fs_configuration = {
364364
};
365365

366366
#if TUD_OPT_HIGH_SPEED
367-
uvc_cfg_desc_t desc_hs_configuration = desc_fs_configuration;
367+
uvc_cfg_desc_t desc_hs_configuration;
368+
369+
static uint8_t * get_hs_configuration_desc(void) {
370+
static bool init = false;
371+
372+
if (!init) {
373+
desc_hs_configuration = desc_fs_configuration;
374+
// change endpoint bulk size to 512 if bulk streaming
375+
if (CFG_TUD_VIDEO_STREAMING_BULK) {
376+
desc_hs_configuration.video_streaming.ep.wMaxPacketSize = 512;
377+
}
378+
}
379+
init = true;
380+
381+
return (uint8_t *) &desc_hs_configuration;
382+
}
368383

369384
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
370385
tusb_desc_device_qualifier_t const desc_device_qualifier = {
@@ -395,7 +410,11 @@ uint8_t const* tud_descriptor_device_qualifier_cb(void) {
395410
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) {
396411
(void) index; // for multiple configurations
397412
// if link speed is high return fullspeed config, and vice versa
398-
return (uint8_t const*) ((tud_speed_get() == TUSB_SPEED_HIGH) ? &desc_fs_configuration : &desc_hs_configuration);
413+
if (tud_speed_get() == TUSB_SPEED_HIGH) {
414+
return (uint8_t const*) &desc_fs_configuration;
415+
} else {
416+
return get_hs_configuration_desc();
417+
}
399418
}
400419
#endif // highspeed
401420

@@ -408,11 +427,7 @@ uint8_t const* tud_descriptor_configuration_cb(uint8_t index) {
408427
#if TUD_OPT_HIGH_SPEED
409428
// Although we are highspeed, host may be fullspeed.
410429
if (tud_speed_get() == TUSB_SPEED_HIGH) {
411-
// change endpoint bulk size to 512 if bulk streaming
412-
if (CFG_TUD_VIDEO_STREAMING_BULK) {
413-
desc_hs_configuration.video_streaming.ep.wMaxPacketSize = 512;
414-
}
415-
return (uint8_t const*) &desc_hs_configuration;
430+
return get_hs_configuration_desc();
416431
} else
417432
#endif
418433
{

hw/bsp/board_api.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,26 @@ extern "C" {
3333

3434
#include <stdint.h>
3535
#include <stdbool.h>
36-
3736
#include "tusb.h"
3837

38+
#if CFG_TUSB_OS == OPT_OS_FREERTOS
39+
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
40+
// ESP-IDF need "freertos/" prefix in include path.
41+
// CFG_TUSB_OS_INC_PATH should be defined accordingly.
42+
#include "freertos/FreeRTOS.h"
43+
#include "freertos/semphr.h"
44+
#include "freertos/queue.h"
45+
#include "freertos/task.h"
46+
#include "freertos/timers.h"
47+
#else
48+
#include "FreeRTOS.h"
49+
#include "semphr.h"
50+
#include "queue.h"
51+
#include "task.h"
52+
#include "timers.h"
53+
#endif
54+
#endif
55+
3956
// Define the default baudrate
4057
#ifndef CFG_BOARD_UART_BAUDRATE
4158
#define CFG_BOARD_UART_BAUDRATE 115200 ///< Default baud rate

src/class/video/video.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ typedef tusb_desc_video_frame_uncompressed_3int_t tusb_desc_video_frame_uncompre
398398
TU_VERIFY_STATIC(sizeof(tusb_desc_video_frame_uncompressed_continuous_t) == 38, "size is not correct");
399399

400400
//------------- MJPEG -------------//
401-
// MJPEG payload specs: 3.1.1 formatt descriptor
401+
// MJPEG payload specs: 3.1.1 format descriptor
402402
typedef struct TU_ATTR_PACKED {
403403
uint8_t bLength;
404404
uint8_t bDescriptorType;

0 commit comments

Comments
 (0)