From 92025b00f0a7d7d0b45d8a2bcc3f3704dbe77733 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Thu, 31 Aug 2023 20:32:42 +0200 Subject: code review: add NCM options in example config --- examples/device/net_lwip_webserver/src/tusb_config.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index fe72ecdfe..025c0b0bf 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -82,6 +82,16 @@ #define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) #endif +// number of NCM transfer blocks for reception side (only valid if NCM is selected below) +#ifndef CFG_TUD_NCM_OUT_NTB_N +#define CFG_TUD_NCM_OUT_NTB_N 2 +#endif + +// number of NCM transfer blocks for transmission side (only valid if NCM is selected below) +#ifndef CFG_TUD_NCM_IN_NTB_N +#define CFG_TUD_NCM_IN_NTB_N 3 +#endif + //-------------------------------------------------------------------- // DEVICE CONFIGURATION //-------------------------------------------------------------------- @@ -94,8 +104,8 @@ // Network class has 2 drivers: ECM/RNDIS and NCM. // Only one of the drivers can be enabled -#define CFG_TUD_ECM_RNDIS 1 -#define CFG_TUD_NCM (1-CFG_TUD_ECM_RNDIS) +#define CFG_TUD_ECM_RNDIS 0 +#define CFG_TUD_NCM (1-CFG_TUD_ECM_RNDIS) #ifdef __cplusplus } -- cgit v1.3.1 From 745c154dbc33bff9a45bc8bee636e7e90152a9c7 Mon Sep 17 00:00:00 2001 From: Hardy Griech Date: Fri, 8 Sep 2023 07:00:08 +0200 Subject: ECM/RNDIS again selected for webserver example --- examples/device/net_lwip_webserver/src/tusb_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index 025c0b0bf..841525cad 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -104,7 +104,7 @@ // Network class has 2 drivers: ECM/RNDIS and NCM. // Only one of the drivers can be enabled -#define CFG_TUD_ECM_RNDIS 0 +#define CFG_TUD_ECM_RNDIS 1 #define CFG_TUD_NCM (1-CFG_TUD_ECM_RNDIS) #ifdef __cplusplus -- cgit v1.3.1 From c2bbcc9f60a2b7293fad4e24468d3f045fde28ee Mon Sep 17 00:00:00 2001 From: IngHK Date: Tue, 26 Dec 2023 20:14:03 +0100 Subject: initial support of CH34x CDC device --- examples/host/cdc_msc_hid/src/tusb_config.h | 1 + .../host/cdc_msc_hid_freertos/src/tusb_config.h | 1 + src/class/cdc/cdc_host.c | 466 ++++++++++++++++++++- src/class/cdc/serial/ch34x.h | 113 +++++ src/tusb_option.h | 17 + 5 files changed, 595 insertions(+), 3 deletions(-) create mode 100644 src/class/cdc/serial/ch34x.h (limited to 'examples') diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 61abb85eb..76d59c316 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -105,6 +105,7 @@ #define CFG_TUH_CDC 1 // CDC ACM #define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API +#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index c661f47be..bb7c3388d 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -110,6 +110,7 @@ #define CFG_TUH_CDC 1 // CDC ACM #define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API +#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index a6dfb45ae..9b5186e0c 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Copyright (c) 2023 Heiko Kuester (CH34x support) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -69,7 +70,16 @@ typedef struct { uint8_t rx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE]; CFG_TUH_MEM_ALIGN uint8_t rx_ep_buf[CFG_TUH_CDC_TX_EPSIZE]; } stream; - + #if CFG_TUH_CDC_CH34X + struct { + uint32_t baud_rate; + uint8_t mcr; + uint8_t msr; + uint8_t lcr; + uint32_t quirks; + uint8_t version; + } ch34x; + #endif } cdch_interface_t; CFG_TUH_MEM_SECTION @@ -121,6 +131,23 @@ static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif +//------------- CH34x prototypes -------------// +#if CFG_TUH_CDC_CH34X +#include "serial/ch34x.h" + +static uint16_t const ch34x_vids_pids[][2] = { CFG_TUH_CDC_CH34X_VID_PID_LIST }; +enum { + CH34X_VID_PID_COUNT = sizeof ( ch34x_vids_pids ) / sizeof ( ch34x_vids_pids[0] ) +}; + +static bool ch34x_open ( uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len ); +static void ch34x_process_config ( tuh_xfer_t* xfer ); + +static bool ch34x_set_modem_ctrl ( cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data ); +static bool ch34x_set_baudrate ( cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data ); +#endif + + enum { SERIAL_DRIVER_ACM = 0, @@ -131,6 +158,10 @@ enum { #if CFG_TUH_CDC_CP210X SERIAL_DRIVER_CP210X, #endif + +#if CFG_TUH_CDC_CH34X + SERIAL_DRIVER_CH34X, +#endif }; typedef struct { @@ -159,6 +190,13 @@ static const cdch_serial_driver_t serial_drivers[] = { .set_baudrate = cp210x_set_baudrate }, #endif + + #if CFG_TUH_CDC_CH34X + { .process_set_config = ch34x_process_config, + .set_control_line_state = ch34x_set_modem_ctrl, + .set_baudrate = ch34x_set_baudrate + }, +#endif }; enum { @@ -426,6 +464,12 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer) break; #endif + #if CFG_TUH_CDC_CH34X + case SERIAL_DRIVER_CH34X: + TU_ASSERT(false, ); // see special ch34x_control_complete function + break; + #endif + default: break; } } @@ -641,7 +685,7 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d { return acm_open(daddr, itf_desc, max_len); } - #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X + #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X else if ( 0xff == itf_desc->bInterfaceClass ) { uint16_t vid, pid; @@ -666,8 +710,16 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d } } #endif + + #if CFG_TUH_CDC_CH34X + for (size_t i = 0; i < CH34X_VID_PID_COUNT; i++) { + if ( ch34x_vids_pids[i][0] == vid && ch34x_vids_pids[i][1] == pid ) { + return ch34x_open(daddr, itf_desc, max_len); + } + } + #endif } - #endif + #endif // CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X return false; } @@ -1176,4 +1228,412 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { #endif +//--------------------------------------------------------------------+ +// CH34x +//--------------------------------------------------------------------+ + +#if CFG_TUH_CDC_CH34X + +enum { + CONFIG_CH34X_STEP1 = 0, + CONFIG_CH34X_STEP2, + CONFIG_CH34X_STEP3, + CONFIG_CH34X_STEP4, + CONFIG_CH34X_STEP5, + CONFIG_CH34X_STEP6, + CONFIG_CH34X_STEP7, + CONFIG_CH34X_STEP8, + CONFIG_CH34X_COMPLETE +}; + +static bool ch34x_open ( uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len ) +{ + // CH34x Interface includes 1 vendor interface + 3 bulk endpoints + TU_VERIFY ( itf_desc->bNumEndpoints == 3 ); + TU_VERIFY ( sizeof ( tusb_desc_interface_t ) + 2 * sizeof ( tusb_desc_endpoint_t ) <= max_len ); + + cdch_interface_t *p_cdc = make_new_itf ( daddr, itf_desc ); + TU_VERIFY ( p_cdc ); + + TU_LOG_DRV ( "CH34x opened\r\n" ); + p_cdc->serial_drid = SERIAL_DRIVER_CH34X; + + // endpoint pair + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next ( itf_desc ); + + // data endpoints expected to be in pairs + return open_ep_stream_pair ( p_cdc, desc_ep ); +} + +static bool ch34x_set_request ( cdch_interface_t* p_cdc, uint8_t direction, uint8_t request, uint16_t value, uint16_t index, uint8_t* buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +{ + tusb_control_request_t const request_setup = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_VENDOR, + .direction = direction + }, + .bRequest = request, + .wValue = tu_htole16 ( value ), + .wIndex = tu_htole16 ( index ), + .wLength = tu_htole16 ( length ) + }; + + // use usbh enum buf since application variable does not live long enough + uint8_t* enum_buf = NULL; + + if ( buffer && length > 0 ) { + enum_buf = usbh_get_enum_buf(); + tu_memcpy_s ( enum_buf, CFG_TUH_ENUMERATION_BUFSIZE, buffer, length ); + } + + tuh_xfer_t xfer = { + .daddr = p_cdc->daddr, + .ep_addr = 0, + .setup = &request_setup, + .buffer = enum_buf, + .complete_cb = complete_cb, + // CH34x needs a special handling of bInterfaceNumber, because wIndex is used for other purposes and not for bInterfaceNumber + .user_data = (uintptr_t)( ( p_cdc->bInterfaceNumber & 0xff ) << 8 ) | ( user_data & 0xff ) + }; + + return tuh_control_xfer ( &xfer ); + return false; +} + +static bool ch341_control_out ( cdch_interface_t* p_cdc, uint8_t request, uint16_t value, uint16_t index, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +{ + return ch34x_set_request ( p_cdc, TUSB_DIR_OUT, request, value, index, /* buffer */ NULL, /* length */ 0, complete_cb, user_data ); +} + +static bool ch341_control_in ( cdch_interface_t* p_cdc, uint8_t request, uint16_t value, uint16_t index, uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +{ + return ch34x_set_request ( p_cdc, TUSB_DIR_IN, request, value, index, buffer, buffersize, complete_cb, user_data ); +} + +static int32_t ch341_write_reg ( cdch_interface_t* p_cdc, uint16_t reg, uint16_t value, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +{ + return ch341_control_out ( p_cdc, CH341_REQ_WRITE_REG, /* value */ reg, /* index */ value, complete_cb, user_data ); +} + +static int32_t ch341_read_reg_request ( cdch_interface_t* p_cdc, uint16_t reg, uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +{ + return ch341_control_in ( p_cdc, CH341_REQ_READ_REG, reg, /* index */ 0, buffer, buffersize, complete_cb, user_data ); +} + +/* + * The device line speed is given by the following equation: + * + * baudrate = 48000000 / (2^(12 - 3 * ps - fact) * div), where + * + * 0 <= ps <= 3, + * 0 <= fact <= 1, + * 2 <= div <= 256 if fact = 0, or + * 9 <= div <= 256 if fact = 1 + */ +// calculate baudrate devisors +// Parts of this functions have been taken over from Linux driver /drivers/usb/serial/ch341.c +static int32_t ch341_get_divisor ( cdch_interface_t* p_cdc, uint32_t speed ) +{ + uint32_t fact, div, clk_div; + bool force_fact0 = false; + int32_t ps; + static const uint32_t ch341_min_rates[] = { + CH341_MIN_RATE(0), + CH341_MIN_RATE(1), + CH341_MIN_RATE(2), + CH341_MIN_RATE(3), + }; + + /* + * Clamp to supported range, this makes the (ps < 0) and (div < 2) + * sanity checks below redundant. + */ + inline uint32_t max ( uint32_t val, uint32_t maxval ) { return val > maxval ? val : maxval; } + inline uint32_t min ( uint32_t val, uint32_t minval ) { return val < minval ? val : minval; } + inline uint32_t clamp_val ( uint32_t val, uint32_t minval, uint32_t maxval ) { return min ( max ( val, minval ), maxval ); } + speed = clamp_val(speed, CH341_MIN_BPS, CH341_MAX_BPS); + + /* + * Start with highest possible base clock (fact = 1) that will give a + * divisor strictly less than 512. + */ + fact = 1; + for (ps = 3; ps >= 0; ps--) { + if (speed > ch341_min_rates[ps]) + break; + } + + if (ps < 0) + return -EINVAL; + + /* Determine corresponding divisor, rounding down. */ + clk_div = CH341_CLK_DIV(ps, fact); + div = CH341_CLKRATE / (clk_div * speed); + + /* Some devices require a lower base clock if ps < 3. */ + if (ps < 3 && (p_cdc->ch34x.quirks & CH341_QUIRK_LIMITED_PRESCALER)) + force_fact0 = true; + + /* Halve base clock (fact = 0) if required. */ + if (div < 9 || div > 255 || force_fact0) { + div /= 2; + clk_div *= 2; + fact = 0; + } + + if (div < 2) + return -EINVAL; + + /* + * Pick next divisor if resulting rate is closer to the requested one, + * scale up to avoid rounding errors on low rates. + */ + if (16 * CH341_CLKRATE / (clk_div * div) - 16 * speed >= + 16 * speed - 16 * CH341_CLKRATE / (clk_div * (div + 1))) + div++; + + /* + * Prefer lower base clock (fact = 0) if even divisor. + * + * Note that this makes the receiver more tolerant to errors. + */ + if (fact == 1 && div % 2 == 0) { + div /= 2; + fact = 0; + } + + return (0x100 - div) << 8 | fact << 2 | ps; +} + +// set baudrate (low level) +// do not confuse with ch34x_set_baudrate +// Parts of this functions have been taken over from Linux driver /drivers/usb/serial/ch341.c +static int32_t ch341_set_baudrate ( cdch_interface_t* p_cdc, uint32_t baud_rate, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +{ + int val; + + if (!baud_rate) + return -EINVAL; + + val = ch341_get_divisor(p_cdc, baud_rate); + if (val < 0) + return -EINVAL; + + /* + * CH341A buffers data until a full endpoint-size packet (32 bytes) + * has been received unless bit 7 is set. + * + * At least one device with version 0x27 appears to have this bit + * inverted. + */ + if ( p_cdc->ch34x.version > 0x27 ) + val |= BIT(7); + + return ch341_write_reg ( p_cdc, CH341_REG_DIVISOR << 8 | CH341_REG_PRESCALER, val, complete_cb, user_data ); +} + +// set lcr register +// Parts of this functions have been taken over from Linux driver /drivers/usb/serial/ch341.c +static int32_t ch341_set_lcr ( cdch_interface_t* p_cdc, uint8_t lcr, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +{ + /* + * Chip versions before version 0x30 as read using + * CH341_REQ_READ_VERSION used separate registers for line control + * (stop bits, parity and word length). Version 0x30 and above use + * CH341_REG_LCR only and CH341_REG_LCR2 is always set to zero. + */ + if ( p_cdc->ch34x.version < 0x30 ) + return 0; + + return ch341_write_reg ( p_cdc, CH341_REG_LCR2 << 8 | CH341_REG_LCR, lcr, complete_cb, user_data ); +} + +// set handshake (modem controls) +// Parts of this functions have been taken over from Linux driver /drivers/usb/serial/ch341.c +static int32_t ch341_set_handshake ( cdch_interface_t* p_cdc, uint8_t control, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +{ + return ch341_control_out ( p_cdc, CH341_REQ_MODEM_CTRL, /* value */ ~control, /* index */ 0, complete_cb, user_data ); +} + +// detect quirks (special versions of CH34x) +// Parts of this functions have been taken over from Linux driver /drivers/usb/serial/ch341.c +static int32_t ch341_detect_quirks ( tuh_xfer_t* xfer, cdch_interface_t* p_cdc, uint8_t step, uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +{ + /* + * A subset of CH34x devices does not support all features. The + * prescaler is limited and there is no support for sending a RS232 + * break condition. A read failure when trying to set up the latter is + * used to detect these devices. + */ + switch ( step ) + { + case 1: + p_cdc->ch34x.quirks = 0; + return ch341_read_reg_request ( p_cdc, CH341_REG_BREAK, buffer, buffersize, complete_cb, user_data ); + break; + case 2: + if ( xfer->result != XFER_RESULT_SUCCESS ) + p_cdc->ch34x.quirks |= CH341_QUIRK_LIMITED_PRESCALER | CH341_QUIRK_SIMULATE_BREAK; + return true; + break; + default: + TU_ASSERT ( false ); // suspicious step + break; + } +} + +// internal control complete to update state such as line state, encoding +// CH34x needs a special interface recovery due to abnormal wIndex usage +static void ch34x_control_complete(tuh_xfer_t* xfer) +{ + uint8_t const itf_num = (uint8_t)( ( xfer->user_data & 0xff00 ) >> 8 ); + uint8_t const idx = tuh_cdc_itf_get_index ( xfer->daddr, itf_num ); + cdch_interface_t *p_cdc = get_itf ( idx ); + TU_ASSERT ( p_cdc, ); + TU_ASSERT ( p_cdc->serial_drid == SERIAL_DRIVER_CH34X, ); // ch34x_control_complete is only used for CH34x + + if (xfer->result == XFER_RESULT_SUCCESS) { + switch (xfer->setup->bRequest) { + case CH341_REQ_WRITE_REG: { // register write request + switch ( tu_le16toh ( xfer->setup->wValue ) ) { + case ( CH341_REG_DIVISOR << 8 | CH341_REG_PRESCALER ): { // baudrate write + p_cdc->line_coding.bit_rate = p_cdc->ch34x.baud_rate; + break; + } + default: { + TU_ASSERT(false, ); // unexpected register write + break; + } + } + break; + } + default: { + TU_ASSERT(false, ); // unexpected request + break; + } + } + xfer->complete_cb = p_cdc->user_control_cb; + if (xfer->complete_cb) + xfer->complete_cb(xfer); + } +} + +static bool ch34x_set_baudrate ( cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) // do not confuse with ch341_set_baudrate +{ + TU_LOG_DRV("CDC CH34x Set BaudRate = %lu\r\n", baudrate); + uint32_t baud_le = tu_htole32(baudrate); + p_cdc->ch34x.baud_rate = baudrate; + p_cdc->user_control_cb = complete_cb; + return ch341_set_baudrate ( p_cdc, baud_le, complete_cb ? ch34x_control_complete : NULL, user_data ); +} + +static bool ch34x_set_modem_ctrl ( cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +{ + TU_LOG_DRV("CDC CH34x Set Control Line State\r\n"); + // todo later + return false; +} + +static void ch34x_process_config ( tuh_xfer_t* xfer ) +{ + uintptr_t const state = xfer->user_data & 0xff; + // CH34x needs a special handling of bInterfaceNumber, because wIndex is used for other purposes and not for bInterfaceNumber + uint8_t const itf_num = (uint8_t)( ( xfer->user_data & 0xff00 ) >> 8 ); + uint8_t const idx = tuh_cdc_itf_get_index ( xfer->daddr, itf_num ); + cdch_interface_t *p_cdc = get_itf ( idx ); + uint8_t buffer [ CH34X_BUFFER_SIZE ]; + cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; + TU_ASSERT ( p_cdc, ); + + if ( state == 0 ) { + // defaults + p_cdc->ch34x.baud_rate = DEFAULT_BAUD_RATE; + p_cdc->ch34x.mcr = 0; + p_cdc->ch34x.msr = 0; + p_cdc->ch34x.quirks = 0; + p_cdc->ch34x.version = 0; + /* + * Some CH340 devices appear unable to change the initial LCR + * settings, so set a sane 8N1 default. + */ + p_cdc->ch34x.lcr = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX | CH341_LCR_CS8; + } + // This process flow has been taken over from Linux driver /drivers/usb/serial/ch341.c + switch ( state ) { + case CONFIG_CH34X_STEP1: // request version read + TU_ASSERT ( ch341_control_in ( p_cdc, /* request */ CH341_REQ_READ_VERSION, /* value */ 0, /* index */ 0, buffer, CH34X_BUFFER_SIZE, ch34x_process_config, CONFIG_CH34X_STEP2 ), ); + break; + case CONFIG_CH34X_STEP2: // handle version read data, request to init CH34x + p_cdc->ch34x.version = xfer->buffer[0]; + TU_LOG_DRV ( "Chip version=%02x\r\n", p_cdc->ch34x.version ); + TU_ASSERT ( ch341_control_out ( p_cdc, /* request */ CH341_REQ_SERIAL_INIT, /* value */ 0, /* index */ 0, ch34x_process_config, CONFIG_CH34X_STEP3 ), ); + break; + case CONFIG_CH34X_STEP3: // set baudrate with default values (see above) + TU_ASSERT ( ch341_set_baudrate ( p_cdc, p_cdc->ch34x.baud_rate, ch34x_process_config, CONFIG_CH34X_STEP4 ) > 0, ); + break; + case CONFIG_CH34X_STEP4: // set line controls with default values (see above) + TU_ASSERT ( ch341_set_lcr ( p_cdc, p_cdc->ch34x.lcr, ch34x_process_config, CONFIG_CH34X_STEP5 ) > 0, ); + break; + case CONFIG_CH34X_STEP5: // set handshake RTS/DTR + TU_ASSERT ( ch341_set_handshake ( p_cdc, p_cdc->ch34x.mcr, ch34x_process_config, CONFIG_CH34X_STEP6 ) > 0, ); + break; + case CONFIG_CH34X_STEP6: // detect quirks step 1 + TU_ASSERT ( ch341_detect_quirks ( xfer, p_cdc, /* step */ 1, buffer, CH34X_BUFFER_SIZE, ch34x_process_config, CONFIG_CH34X_STEP7 ) > 0, ); + break; + case CONFIG_CH34X_STEP7: // detect quirks step 2 and set baudrate with configured values + TU_ASSERT ( ch341_detect_quirks ( xfer, p_cdc, /* step */ 2, NULL, 0, NULL, 0 ) > 0, ); +#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + TU_ASSERT ( ch34x_set_baudrate ( p_cdc, line_coding.bit_rate, ch34x_process_config, CONFIG_CH34X_STEP8 ), ); +#else + TU_ATTR_FALLTHROUGH; #endif + break; + case CONFIG_CH34X_STEP8: // set data/stop bit quantities, parity +#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + p_cdc->ch34x.lcr = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX; + switch ( line_coding.data_bits ) { + case 5: + p_cdc->ch34x.lcr |= CH341_LCR_CS5; + break; + case 6: + p_cdc->ch34x.lcr |= CH341_LCR_CS6; + break; + case 7: + p_cdc->ch34x.lcr |= CH341_LCR_CS7; + break; + case 8: + p_cdc->ch34x.lcr |= CH341_LCR_CS8; + break; + default: + TU_ASSERT ( false, ); // not supported data_bits + p_cdc->ch34x.lcr |= CH341_LCR_CS8; + break; + } + if ( line_coding.parity != CDC_LINE_CODING_PARITY_NONE ) { + p_cdc->ch34x.lcr |= CH341_LCR_ENABLE_PAR; + if ( line_coding.parity == CDC_LINE_CODING_PARITY_EVEN || line_coding.parity == CDC_LINE_CODING_PARITY_SPACE ) + p_cdc->ch34x.lcr |= CH341_LCR_PAR_EVEN; + if ( line_coding.parity == CDC_LINE_CODING_PARITY_MARK || line_coding.parity == CDC_LINE_CODING_PARITY_SPACE ) + p_cdc->ch34x.lcr |= CH341_LCR_MARK_SPACE; + } + TU_ASSERT ( line_coding.stop_bits == CDC_LINE_CODING_STOP_BITS_1 || line_coding.stop_bits == CDC_LINE_CODING_STOP_BITS_2, ); // not supported 1.5 stop bits + if ( line_coding.stop_bits == CDC_LINE_CODING_STOP_BITS_2 ) + p_cdc->ch34x.lcr |= CH341_LCR_STOP_BITS_2; + TU_ASSERT ( ch341_set_lcr ( p_cdc, p_cdc->ch34x.lcr, ch34x_process_config, CONFIG_CH34X_COMPLETE ) > 0, ); +#else + TU_ATTR_FALLTHROUGH; +#endif + break; + case CONFIG_CH34X_COMPLETE: + set_config_complete ( p_cdc, idx, itf_num ); + break; + default: + TU_ASSERT ( false, ); + break; + } +} + +#endif // CFG_TUH_CDC_CH34X + +#endif // (CFG_TUH_ENABLED && CFG_TUH_CDC) diff --git a/src/class/cdc/serial/ch34x.h b/src/class/cdc/serial/ch34x.h new file mode 100644 index 000000000..94e18b252 --- /dev/null +++ b/src/class/cdc/serial/ch34x.h @@ -0,0 +1,113 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Heiko Kuester (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _CH34X_H_ +#define _CH34X_H_ + +#include + +#define BIT(nr) ( (uint32_t)1 << (nr) ) + +#define CH34X_BUFFER_SIZE 2 + +// The following defines have been taken over from Linux driver /drivers/usb/serial/ch341.c + +#define DEFAULT_BAUD_RATE 9600 + +/* flags for IO-Bits */ +#define CH341_BIT_RTS (1 << 6) +#define CH341_BIT_DTR (1 << 5) + +/******************************/ +/* interrupt pipe definitions */ +/******************************/ +/* always 4 interrupt bytes */ +/* first irq byte normally 0x08 */ +/* second irq byte base 0x7d + below */ +/* third irq byte base 0x94 + below */ +/* fourth irq byte normally 0xee */ + +/* second interrupt byte */ +#define CH341_MULT_STAT 0x04 /* multiple status since last interrupt event */ + +/* status returned in third interrupt answer byte, inverted in data + from irq */ +#define CH341_BIT_CTS 0x01 +#define CH341_BIT_DSR 0x02 +#define CH341_BIT_RI 0x04 +#define CH341_BIT_DCD 0x08 +#define CH341_BITS_MODEM_STAT 0x0f /* all bits */ + +/* Break support - the information used to implement this was gleaned from + * the Net/FreeBSD uchcom.c driver by Takanori Watanabe. Domo arigato. + */ + +// USB requests +#define CH341_REQ_READ_VERSION 0x5F // dec 95 +#define CH341_REQ_WRITE_REG 0x9A +#define CH341_REQ_READ_REG 0x95 +#define CH341_REQ_SERIAL_INIT 0xA1 +#define CH341_REQ_MODEM_CTRL 0xA4 + +// CH34x registers +#define CH341_REG_BREAK 0x05 +#define CH341_REG_PRESCALER 0x12 +#define CH341_REG_DIVISOR 0x13 +#define CH341_REG_LCR 0x18 +#define CH341_REG_LCR2 0x25 + +#define CH341_NBREAK_BITS 0x01 + +// line control bits +#define CH341_LCR_ENABLE_RX 0x80 +#define CH341_LCR_ENABLE_TX 0x40 +#define CH341_LCR_MARK_SPACE 0x20 +#define CH341_LCR_PAR_EVEN 0x10 +#define CH341_LCR_ENABLE_PAR 0x08 +#define CH341_LCR_STOP_BITS_2 0x04 +#define CH341_LCR_CS8 0x03 +#define CH341_LCR_CS7 0x02 +#define CH341_LCR_CS6 0x01 +#define CH341_LCR_CS5 0x00 + +#define CH341_QUIRK_LIMITED_PRESCALER BIT(0) +#define CH341_QUIRK_SIMULATE_BREAK BIT(1) + +#define CH341_CLKRATE 48000000 +#define CH341_CLK_DIV(ps, fact) (1 << (12 - 3 * (ps) - (fact))) +#define CH341_MIN_RATE(ps) (CH341_CLKRATE / (CH341_CLK_DIV((ps), 1) * 512)) + +/* Supported range is 46 to 3000000 bps. */ +#define CH341_MIN_BPS DIV_ROUND_UP(CH341_CLKRATE, CH341_CLK_DIV(0, 0) * 256) +#define CH341_MAX_BPS (CH341_CLKRATE / (CH341_CLK_DIV(3, 0) * 2)) + +#define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP +#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + +// error codes +#define EINVAL 22 /* Invalid argument */ + +#endif /* _CH34X_H_ */ diff --git a/src/tusb_option.h b/src/tusb_option.h index a76281c0c..13151a07b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -470,6 +470,23 @@ 0xEA60, 0xEA70 #endif +#ifndef CFG_TUH_CDC_CH34X + // CH34X is not part of CDC class, only to re-use CDC driver API + #define CFG_TUH_CDC_CH34X 0 +#endif + +#ifndef CFG_TUH_CDC_CH34X_VID_PID_LIST + // List of product IDs that can use the CH34X CDC driver + #define CFG_TUH_CDC_CH34X_VID_PID_LIST \ + { 0x1a86, 0x7523 }, /* ch340 chip */ \ + { 0x1a86, 0x7522 }, /* ch340k chip */ \ + { 0x1a86, 0x5523 }, /* ch341 chip */ \ + { 0x1a86, 0xe523 }, /* ch330 chip */ \ + { 0x4348, 0x5523 }, /* ch340 custom chip */ \ + { 0x2184, 0x0057 }, /* overtaken from Linux driver /drivers/usb/serial/ch341.c */ \ + { 0x9986, 0x7523 } /* overtaken from Linux driver /drivers/usb/serial/ch341.c */ +#endif + #ifndef CFG_TUH_HID #define CFG_TUH_HID 0 #endif -- cgit v1.3.1 From 98781bb903d94190d57ad4b9436a85a31d67404c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jan 2024 15:58:05 +0700 Subject: - add ch34x_set_data_format() - add ch34x_set_line_coding() --- examples/host/cdc_msc_hid/src/cdc_app.c | 68 ++++++++++------------ src/class/cdc/cdc_host.c | 100 ++++++++++++++++++++++---------- src/class/cdc/serial/ch34x.h | 3 +- 3 files changed, 102 insertions(+), 69 deletions(-) (limited to 'examples') diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index a1b26e49c..81052047c 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -27,20 +27,11 @@ #include "tusb.h" #include "bsp/board_api.h" -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - - -//------------- IMPLEMENTATION -------------// - -size_t get_console_inputs(uint8_t* buf, size_t bufsize) -{ +size_t get_console_inputs(uint8_t* buf, size_t bufsize) { size_t count = 0; - while (count < bufsize) - { + while (count < bufsize) { int ch = board_getchar(); - if ( ch <= 0 ) break; + if (ch <= 0) break; buf[count] = (uint8_t) ch; count++; @@ -49,22 +40,18 @@ size_t get_console_inputs(uint8_t* buf, size_t bufsize) return count; } -void cdc_app_task(void) -{ - uint8_t buf[64+1]; // +1 for extra null character - uint32_t const bufsize = sizeof(buf)-1; +void cdc_app_task(void) { + uint8_t buf[64 + 1]; // +1 for extra null character + uint32_t const bufsize = sizeof(buf) - 1; uint32_t count = get_console_inputs(buf, bufsize); buf[count] = 0; // loop over all mounted interfaces - for(uint8_t idx=0; idx cdc interfaces - if (count) - { + if (count) { tuh_cdc_write(idx, buf, count); tuh_cdc_write_flush(idx); } @@ -72,11 +59,14 @@ void cdc_app_task(void) } } +//--------------------------------------------------------------------+ +// TinyUSB callbacks +//--------------------------------------------------------------------+ + // Invoked when received new data -void tuh_cdc_rx_cb(uint8_t idx) -{ - uint8_t buf[64+1]; // +1 for extra null character - uint32_t const bufsize = sizeof(buf)-1; +void tuh_cdc_rx_cb(uint8_t idx) { + uint8_t buf[64 + 1]; // +1 for extra null character + uint32_t const bufsize = sizeof(buf) - 1; // forward cdc interfaces -> console uint32_t count = tuh_cdc_read(idx, buf, bufsize); @@ -85,29 +75,31 @@ void tuh_cdc_rx_cb(uint8_t idx) printf((char*) buf); } -void tuh_cdc_mount_cb(uint8_t idx) -{ - tuh_itf_info_t itf_info = { 0 }; +// Invoked when a device with CDC interface is mounted +// idx is index of cdc interface in the internal pool. +void tuh_cdc_mount_cb(uint8_t idx) { + tuh_itf_info_t itf_info = {0}; tuh_cdc_itf_get_info(idx, &itf_info); - printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber); + printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, + itf_info.desc.bInterfaceNumber); #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM // CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration // otherwise you need to call tuh_cdc_set_line_coding() first - cdc_line_coding_t line_coding = { 0 }; - if ( tuh_cdc_get_local_line_coding(idx, &line_coding) ) - { + cdc_line_coding_t line_coding = {0}; + if (tuh_cdc_get_local_line_coding(idx, &line_coding)) { printf(" Baudrate: %lu, Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); - printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity , line_coding.data_bits); + printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits); } #endif } -void tuh_cdc_umount_cb(uint8_t idx) -{ - tuh_itf_info_t itf_info = { 0 }; +// Invoked when a device with CDC interface is unmounted +void tuh_cdc_umount_cb(uint8_t idx) { + tuh_itf_info_t itf_info = {0}; tuh_cdc_itf_get_info(idx, &itf_info); - printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber); + printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, + itf_info.desc.bInterfaceNumber); } diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index bfaa64a77..37fa30982 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -1327,48 +1327,88 @@ static void ch34x_control_complete(tuh_xfer_t* xfer) { process_internal_control_complete(p_cdc, xfer); } -//static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, -// tuh_xfer_cb_t complete_cb, uintptr_t user_data) { -// uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits); -// p_cdc->requested_line_coding.stop_bits = stop_bits; -// p_cdc->requested_line_coding.parity = parity; -// p_cdc->requested_line_coding.data_bits = data_bits; -// -// TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr, -// complete_cb ? ch34x_control_complete : NULL, user_data)); -// return false; -//} +static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->requested_line_coding.stop_bits = stop_bits; + p_cdc->requested_line_coding.parity = parity; + p_cdc->requested_line_coding.data_bits = data_bits; + + uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits); + TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr, + complete_cb ? ch34x_control_complete : NULL, user_data)); + return true; +} -static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t const div_ps = ch34x_get_divisor_prescaler(baudrate); TU_VERIFY(div_ps != 0); + TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, + complete_cb, user_data)); + return true; +} +static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->requested_line_coding.bit_rate = baudrate; p_cdc->user_control_cb = complete_cb; - TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, - complete_cb ? ch34x_control_complete : NULL, user_data)); - + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, baudrate, + complete_cb ? ch34x_control_complete : NULL, user_data)); return true; } -//static void ch34x_set_line_coding_stage1(tuh_xfer_t* xfer) { -// -//} +static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) { + uint8_t const itf_num = 0; + uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t* p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); + if (xfer->result == XFER_RESULT_SUCCESS) { + // stage 1 success, continue to stage 2 + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + TU_ASSERT(ch34x_set_data_format(p_cdc, p_cdc->requested_line_coding.stop_bits, p_cdc->requested_line_coding.parity, + p_cdc->requested_line_coding.data_bits, ch34x_control_complete, xfer->user_data), ); + } else { + // stage 1 failed, notify user + xfer->complete_cb = p_cdc->user_control_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } + } +} + +// 2 stages: set baudrate (stage1) + set data format (stage2) static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { -// p_cdc->baudrate_requested = line_coding->bit_rate; -// p_cdc->user_control_cb = complete_cb; -// uint8_t factor, divisor, lcr; -// TU_ASSERT (ch34x_get_factor_divisor(line_coding->bit_rate, &factor, &divisor)); -// TU_ASSERT (ch34x_get_lcr(line_coding, &lcr)); -// TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, (uint16_t) (lcr << 8 | 0x9c), (uint16_t) (factor << 8 | 0x80 | divisor), -// complete_cb ? ch34x_control_complete : NULL, user_data)); - (void) p_cdc; - (void) line_coding; - (void) complete_cb; - (void) user_data; + p_cdc->requested_line_coding = *line_coding; + p_cdc->user_control_cb = complete_cb; + + if (complete_cb) { + // stage 1 set baudrate + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate, + ch34x_set_line_coding_stage1_complete, user_data)); + } else { + // sync call + xfer_result_t result; + + // stage 1 set baudrate + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate, NULL, (uintptr_t) &result)); + TU_VERIFY(result == XFER_RESULT_SUCCESS); + p_cdc->line_coding.bit_rate = line_coding->bit_rate; + + // stage 2 set data format + TU_ASSERT(ch34x_set_data_format(p_cdc, line_coding->stop_bits, line_coding->parity, line_coding->data_bits, + NULL, (uintptr_t) &result)); + TU_VERIFY(result == XFER_RESULT_SUCCESS); + p_cdc->line_coding.stop_bits = line_coding->stop_bits; + p_cdc->line_coding.parity = line_coding->parity; + p_cdc->line_coding.data_bits = line_coding->data_bits; + + // update transfer result, user_data is expected to point to xfer_result_t + if (user_data) { + user_data = result; + } + } return true; } diff --git a/src/class/cdc/serial/ch34x.h b/src/class/cdc/serial/ch34x.h index 3f78a3007..5def8d212 100644 --- a/src/class/cdc/serial/ch34x.h +++ b/src/class/cdc/serial/ch34x.h @@ -63,7 +63,8 @@ #define CH341_REG_0x2C 0x2C // undocumented register #define CH341_REG_0x27 0x27 // hardware flow control (cts/rts) -#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER) +#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER) +#define CH32X_REG16_LCR2_LCR TU_U16(CH34X_REG_LCR2, CH34X_REG_LCR) // modem control bits #define CH34X_BIT_RTS ( 1 << 6 ) -- cgit v1.3.1 From 87d509d416ea7c250f4256f897f6cc9a7b7d2121 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 20 Jan 2024 01:42:31 +0700 Subject: make CFG_TUH_CDC_LINE_CODING_ON_ENUM optional for ch34x --- examples/host/cdc_msc_hid/src/cdc_app.c | 8 ++++++-- src/class/cdc/cdc_host.c | 19 ++++++++++++++----- src/class/cdc/serial/ch34x.h | 12 +----------- 3 files changed, 21 insertions(+), 18 deletions(-) (limited to 'examples') diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index 81052047c..e275e7943 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -85,13 +85,17 @@ void tuh_cdc_mount_cb(uint8_t idx) { itf_info.desc.bInterfaceNumber); #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - // CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration - // otherwise you need to call tuh_cdc_set_line_coding() first + // If CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined, line coding will be set by tinyusb stack + // while eneumerating new cdc device cdc_line_coding_t line_coding = {0}; if (tuh_cdc_get_local_line_coding(idx, &line_coding)) { printf(" Baudrate: %lu, Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits); } +#else + // Set Line Coding upon mounted + cdc_line_coding_t new_line_coding = { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }; + tuh_cdc_set_line_coding(idx, &new_line_coding, NULL, 0); #endif } diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index f5182efc2..cd948243d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -1510,10 +1510,11 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t* p_cdc = get_itf(idx); uintptr_t const state = xfer->user_data; - cdc_line_coding_t const line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; uint8_t buffer[2]; // TODO remove TU_ASSERT (p_cdc,); + // TODO check xfer->result + switch (state) { case CONFIG_CH34X_READ_VERSION: TU_LOG_DRV("[%u] CDCh CH34x attempt to read Chip Version\r\n", p_cdc->daddr); @@ -1527,20 +1528,28 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { // only versions >= 0x30 are tested, below 0x30 seems having other programming, see drivers from WCH vendor, Linux kernel and FreeBSD TU_ASSERT (version >= 0x30,); + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + cdc_line_coding_t const line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; + uint8_t const lcr = ch34x_get_lcr(line_coding.stop_bits, line_coding.parity, line_coding.data_bits); + uint16_t const first_arg = tu_u16(lcr, 0x9c); uint16_t const div_ps = ch34x_get_divisor_prescaler(line_coding.bit_rate); TU_ASSERT(div_ps != 0, ); - - uint8_t const lcr = ch34x_get_lcr(line_coding.stop_bits, line_coding.parity, line_coding.data_bits); + #else + uint16_t const first_arg = 0; + uint16_t const div_ps = 0; + #endif // Init CH34x with line coding - TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, tu_u16(lcr, 0x9c), div_ps, + TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, first_arg, div_ps, ch34x_process_config, CONFIG_CH34X_SPECIAL_REG_WRITE),); break; } case CONFIG_CH34X_SPECIAL_REG_WRITE: // do special reg write, purpose unknown, overtaken from WCH driver - p_cdc->line_coding = line_coding; + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + p_cdc->line_coding = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM); + #endif TU_ASSERT (ch34x_write_reg(p_cdc, 0x0f2c, 0x0007, ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL),); break; diff --git a/src/class/cdc/serial/ch34x.h b/src/class/cdc/serial/ch34x.h index 5def8d212..b9121afb3 100644 --- a/src/class/cdc/serial/ch34x.h +++ b/src/class/cdc/serial/ch34x.h @@ -27,21 +27,11 @@ #ifndef _CH34X_H_ #define _CH34X_H_ -// For simplicity, only the name CH34X is used here, -// but specifically only CH340 and CH341 are supported. - -// There is no official documentation for the CH34x chips. Reference can be found +// There is no official documentation for the CH34x (CH340, CH341) chips. Reference can be found // - https://github.com/WCHSoftGroup/ch341ser_linux // - https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ch341.c // - https://github.com/freebsd/freebsd-src/blob/main/sys/dev/usb/serial/uchcom.c -// set line_coding @ enumeration -#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM -#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X CFG_TUH_CDC_LINE_CODING_ON_ENUM -#else // this default is necessary to work properly -#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X { 9600, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } -#endif - // USB requests #define CH34X_REQ_READ_VERSION 0x5F // dec 95 #define CH34X_REQ_WRITE_REG 0x9A // dec 154 -- cgit v1.3.1 From de1266699dc804d1ac35254abd3d0dc54d81ad75 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 13 Jan 2024 00:10:24 +0700 Subject: clean up video example for readability --- examples/device/video_capture/src/images.h | 3 + examples/device/video_capture/src/main.c | 86 ++++++------ examples/device/video_capture/src/tusb_config.h | 2 +- .../device/video_capture/src/usb_descriptors.c | 150 +++++++-------------- hw/bsp/family_support.cmake | 1 - 5 files changed, 96 insertions(+), 146 deletions(-) (limited to 'examples') diff --git a/examples/device/video_capture/src/images.h b/examples/device/video_capture/src/images.h index 784e7754c..ac372cb16 100644 --- a/examples/device/video_capture/src/images.h +++ b/examples/device/video_capture/src/images.h @@ -1,4 +1,5 @@ #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) +// uncopmressed frame static const unsigned char frame_buffer[128 * (96 + 1) * 2] = { /* 0 */ 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, @@ -1650,8 +1651,10 @@ static const unsigned char frame_buffer[128 * (96 + 1) * 2] = { 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, }; + #else +// mpeg compressed data (not CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) #define color_bar_0_jpg_len 511 #define color_bar_1_jpg_len 512 #define color_bar_2_jpg_len 511 diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c index 711d4710a..7b180dd6b 100644 --- a/examples/device/video_capture/src/main.c +++ b/examples/device/video_capture/src/main.c @@ -40,7 +40,7 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -52,8 +52,7 @@ void led_blinking_task(void); void video_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port @@ -63,8 +62,7 @@ int main(void) board_init_after_tusb(); } - while (1) - { + while (1) { tud_task(); // tinyusb device task led_blinking_task(); @@ -77,33 +75,28 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } - //--------------------------------------------------------------------+ // USB Video //--------------------------------------------------------------------+ @@ -111,11 +104,12 @@ static unsigned frame_num = 0; static unsigned tx_busy = 0; static unsigned interval_ms = 1000 / FRAME_RATE; -/* YUY2 frame buffer */ #ifdef CFG_EXAMPLE_VIDEO_READONLY +// For mcus that does not have enough SRAM for frame buffer, we use fixed frame data. +// To further reduce the size, we use MJPEG format instead of YUY2. #include "images.h" -# if !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) +#if !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) static struct { uint32_t size; uint8_t const *buffer; @@ -129,29 +123,31 @@ static struct { {color_bar_6_jpg_len, color_bar_6_jpg}, {color_bar_7_jpg_len, color_bar_7_jpg}, }; -# endif +#endif #else + +// YUY2 frame buffer static uint8_t frame_buffer[FRAME_WIDTH * FRAME_HEIGHT * 16 / 8]; -static void fill_color_bar(uint8_t *buffer, unsigned start_position) -{ + +static void fill_color_bar(uint8_t* buffer, unsigned start_position) { /* EBU color bars * See also https://stackoverflow.com/questions/6939422 */ static uint8_t const bar_color[8][4] = { - /* Y, U, Y, V */ - { 235, 128, 235, 128}, /* 100% White */ - { 219, 16, 219, 138}, /* Yellow */ - { 188, 154, 188, 16}, /* Cyan */ - { 173, 42, 173, 26}, /* Green */ - { 78, 214, 78, 230}, /* Magenta */ - { 63, 102, 63, 240}, /* Red */ - { 32, 240, 32, 118}, /* Blue */ - { 16, 128, 16, 128}, /* Black */ + /* Y, U, Y, V */ + { 235, 128, 235, 128}, /* 100% White */ + { 219, 16, 219, 138}, /* Yellow */ + { 188, 154, 188, 16}, /* Cyan */ + { 173, 42, 173, 26}, /* Green */ + { 78, 214, 78, 230}, /* Magenta */ + { 63, 102, 63, 240}, /* Red */ + { 32, 240, 32, 118}, /* Blue */ + { 16, 128, 16, 128}, /* Black */ }; - uint8_t *p; + uint8_t* p; /* Generate the 1st line */ - uint8_t *end = &buffer[FRAME_WIDTH * 2]; + uint8_t* end = &buffer[FRAME_WIDTH * 2]; unsigned idx = (FRAME_WIDTH / 2 - 1) - (start_position % (FRAME_WIDTH / 2)); p = &buffer[idx * 4]; for (unsigned i = 0; i < 8; ++i) { @@ -163,6 +159,7 @@ static void fill_color_bar(uint8_t *buffer, unsigned start_position) } } } + /* Duplicate the 1st line to the others */ p = &buffer[FRAME_WIDTH * 2]; for (unsigned i = 1; i < FRAME_HEIGHT; ++i) { @@ -170,16 +167,16 @@ static void fill_color_bar(uint8_t *buffer, unsigned start_position) p += FRAME_WIDTH * 2; } } + #endif -void video_task(void) -{ +void video_task(void) { static unsigned start_ms = 0; static unsigned already_sent = 0; if (!tud_video_n_streaming(0, 0)) { - already_sent = 0; - frame_num = 0; + already_sent = 0; + frame_num = 0; return; } @@ -195,7 +192,7 @@ void video_task(void) # endif #else fill_color_bar(frame_buffer, frame_num); - tud_video_n_frame_xfer(0, 0, (void*)frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16/8); + tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); #endif } @@ -213,22 +210,22 @@ void video_task(void) # endif #else fill_color_bar(frame_buffer, frame_num); - tud_video_n_frame_xfer(0, 0, (void*)frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16/8); + tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); #endif } -void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) -{ - (void)ctl_idx; (void)stm_idx; +void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { + (void) ctl_idx; + (void) stm_idx; tx_busy = 0; /* flip buffer */ ++frame_num; } int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, - video_probe_and_commit_control_t const *parameters) -{ - (void)ctl_idx; (void)stm_idx; + video_probe_and_commit_control_t const* parameters) { + (void) ctl_idx; + (void) stm_idx; /* convert unit to ms from 100 ns */ interval_ms = parameters->dwFrameInterval / 10000; return VIDEO_ERROR_NONE; @@ -237,13 +234,12 @@ int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/video_capture/src/tusb_config.h b/examples/device/video_capture/src/tusb_config.h index 274bf2b9c..8440b47ef 100644 --- a/examples/device/video_capture/src/tusb_config.h +++ b/examples/device/video_capture/src/tusb_config.h @@ -101,7 +101,7 @@ #define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 256 // use bulk endpoint for streaming interface -#define CFG_TUD_VIDEO_STREAMING_BULK 0 +#define CFG_TUD_VIDEO_STREAMING_BULK 1 #ifdef __cplusplus } diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c index 49919fc58..d38f158c8 100644 --- a/examples/device/video_capture/src/usb_descriptors.c +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -43,8 +43,7 @@ //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ +tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -70,111 +69,70 @@ tusb_desc_device_t const desc_device = // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ - return (uint8_t const *) &desc_device; +uint8_t const* tud_descriptor_device_cb(void) { + return (uint8_t const*) &desc_device; } //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ -#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_MJPEG_BULK_LEN) -# else -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_MJPEG_LEN) -# endif -#else -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_UNCOMPR_BULK_LEN) -# else -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN) -# endif -#endif - +// Select appropriate endpoint number #if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ... -#if 1 == CFG_TUD_VIDEO_STREAMING_BULK - #define EPNUM_VIDEO_IN 0x82 -#else - #define EPNUM_VIDEO_IN 0x83 -#endif - + #define EPNUM_VIDEO_IN (CFG_TUD_VIDEO_STREAMING_BULK ? 0x82 : 0x83) #elif TU_CHECK_MCU(OPT_MCU_NRF5X) // nRF5x ISO can only be endpoint 8 - #define EPNUM_VIDEO_IN 0x88 - + #define EPNUM_VIDEO_IN (CFG_TUD_VIDEO_STREAMING_BULK ? 0x81 : 0x88) #else #define EPNUM_VIDEO_IN 0x81 - #endif -uint8_t const desc_fs_configuration[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 500), - - // IAD for Video Control +// For mcus that does not have enough SRAM for frame buffer, we use fixed frame data. +// To further reduce the size, we use MJPEG format instead of YUY2. +// Select interface descriptor and length accordingly. #if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK - TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - 64) -# else - TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -# endif + #if CFG_TUD_VIDEO_STREAMING_BULK + #define ITF_VIDEO_DESC(epsize) TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(4, EPNUM_VIDEO_IN, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, epsize) + #define ITF_VIDEO_LEN TUD_VIDEO_CAPTURE_DESC_MJPEG_BULK_LEN + #else + #define ITF_VIDEO_DESC(epsize) TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(4, EPNUM_VIDEO_IN, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, epsize) + #define ITF_VIDEO_LEN TUD_VIDEO_CAPTURE_DESC_MJPEG_LEN + #endif #else -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK - TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - 64) -# else - TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -# endif + #if CFG_TUD_VIDEO_STREAMING_BULK + #define ITF_VIDEO_DESC(epsize) TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(4, EPNUM_VIDEO_IN, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, epsize) + #define ITF_VIDEO_LEN TUD_VIDEO_CAPTURE_DESC_UNCOMPR_BULK_LEN + #else + #define ITF_VIDEO_DESC(epsize) TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(4, EPNUM_VIDEO_IN, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, epsize) + #define ITF_VIDEO_LEN TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN + #endif #endif + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + ITF_VIDEO_LEN) + +// full speed descriptor +uint8_t const desc_fs_configuration[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 500), + + // IAD for Video Control + ITF_VIDEO_DESC(CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) }; #if TUD_OPT_HIGH_SPEED // Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration - -uint8_t const desc_hs_configuration[] = -{ +uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 500), // IAD for Video Control -#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK - TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - 512) -# else - TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -# endif -#else -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK - TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - 512) -# else - TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -# endif -#endif + ITF_VIDEO_DESC(CFG_TUD_VIDEO_STREAMING_BULK ? 512 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) }; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = -{ +tusb_desc_device_qualifier_t const desc_device_qualifier = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -192,29 +150,24 @@ tusb_desc_device_qualifier_t const desc_device_qualifier = // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. // device_qualifier descriptor describes information about a high-speed capable device that would // change if the device were operating at the other speed. If not highspeed capable stall this request. -uint8_t const* tud_descriptor_device_qualifier_cb(void) -{ +uint8_t const* tud_descriptor_device_qualifier_cb(void) { return (uint8_t const*) &desc_device_qualifier; } // Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete // Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa -uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) -{ +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - // if link speed is high return fullspeed config, and vice versa return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration; } - #endif // highspeed // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ +uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations #if TUD_OPT_HIGH_SPEED @@ -238,24 +191,23 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = -{ - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - NULL, // 3: Serials will use unique ID if possible - "TinyUSB UVC", // 4: UVC Interface +char const* string_desc_arr[] = { + (const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "TinyUSB UVC", // 4: UVC Interface }; static uint16_t _desc_str[32 + 1]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void) langid; size_t chr_count; - switch ( index ) { + switch (index) { case STRID_LANGID: memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; @@ -269,17 +221,17 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (index >= sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) return NULL; - const char *str = string_desc_arr[index]; + const char* str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) chr_count = max_count; // Convert ASCII string into UTF-16 - for ( size_t i = 0; i < chr_count; i++ ) { + for (size_t i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; } break; diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 539a776a6..ff3393cfd 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -211,7 +211,6 @@ function(family_configure_common TARGET RTOS) target_link_options(${TARGET} PUBLIC "LINKER:--map=$.map") endif() - # ETM Trace option if (TRACE_ETM STREQUAL "1") target_compile_definitions(${TARGET} PUBLIC TRACE_ETM) -- cgit v1.3.1 From 0b8b8af83dfac97caa7c41f9d5c8c1a3af1b9ac1 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 25 Jan 2024 17:25:48 +0700 Subject: minor update to video capture example --- examples/device/video_capture/src/main.c | 15 +- examples/device/video_capture/src/tusb_config.h | 2 +- .../device/video_capture/src/usb_descriptors.h | 69 +++------ src/class/video/video_device.c | 6 +- src/common/tusb_types.h | 154 ++++++++------------- 5 files changed, 92 insertions(+), 154 deletions(-) (limited to 'examples') diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c index 7b180dd6b..e63335e67 100644 --- a/examples/device/video_capture/src/main.c +++ b/examples/device/video_capture/src/main.c @@ -131,8 +131,7 @@ static struct { static uint8_t frame_buffer[FRAME_WIDTH * FRAME_HEIGHT * 16 / 8]; static void fill_color_bar(uint8_t* buffer, unsigned start_position) { - /* EBU color bars - * See also https://stackoverflow.com/questions/6939422 */ + /* EBU color bars: https://stackoverflow.com/questions/6939422 */ static uint8_t const bar_color[8][4] = { /* Y, U, Y, V */ { 235, 128, 235, 128}, /* 100% White */ @@ -184,12 +183,12 @@ void video_task(void) { already_sent = 1; start_ms = board_millis(); #ifdef CFG_EXAMPLE_VIDEO_READONLY -# if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) + #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)&frame_buffer[(frame_num % (FRAME_WIDTH / 2)) * 4], FRAME_WIDTH * FRAME_HEIGHT * 16/8); -# else + #else tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)frames[frame_num % 8].buffer, frames[frame_num % 8].size); -# endif + #endif #else fill_color_bar(frame_buffer, frame_num); tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); @@ -202,12 +201,12 @@ void video_task(void) { start_ms += interval_ms; #ifdef CFG_EXAMPLE_VIDEO_READONLY -# if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) + #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)&frame_buffer[(frame_num % (FRAME_WIDTH / 2)) * 4], FRAME_WIDTH * FRAME_HEIGHT * 16/8); -# else + #else tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)frames[frame_num % 8].buffer, frames[frame_num % 8].size); -# endif + #endif #else fill_color_bar(frame_buffer, frame_num); tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); diff --git a/examples/device/video_capture/src/tusb_config.h b/examples/device/video_capture/src/tusb_config.h index 8440b47ef..d563c6f5c 100644 --- a/examples/device/video_capture/src/tusb_config.h +++ b/examples/device/video_capture/src/tusb_config.h @@ -97,7 +97,7 @@ // The number of video streaming interfaces #define CFG_TUD_VIDEO_STREAMING 1 -// video streaming endpoint size +// video streaming endpoint buffer size #define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 256 // use bulk endpoint for streaming interface diff --git a/examples/device/video_capture/src/usb_descriptors.h b/examples/device/video_capture/src/usb_descriptors.h index b924c8dbe..fa3c1fbd2 100644 --- a/examples/device/video_capture/src/usb_descriptors.h +++ b/examples/device/video_capture/src/usb_descriptors.h @@ -126,23 +126,17 @@ enum { #define TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(_stridx, _epin, _width, _height, _fps, _epsize) \ TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ - TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 0, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ - /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ @@ -163,23 +157,17 @@ enum { #define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(_stridx, _epin, _width, _height, _fps, _epsize) \ TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ - TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 0, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ - /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ @@ -202,22 +190,17 @@ enum { TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 1, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ @@ -235,23 +218,17 @@ enum { #define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(_stridx, _epin, _width, _height, _fps, _epsize) \ TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ - TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 1, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ - /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c index 3b29454a3..c16a45fcd 100644 --- a/src/class/video/video_device.c +++ b/src/class/video/video_device.c @@ -434,8 +434,9 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm uint_fast32_t interval_ms = interval / 10000; TU_ASSERT(interval_ms); uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; - if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) + if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) { payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE; + } param->dwMaxPayloadTransferSize = payload_size; return true; } @@ -577,8 +578,9 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * } else { payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; } - if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) + if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) { payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE; + } param->dwMaxPayloadTransferSize = payload_size; } return true; diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index fab680989..d4ef1fd09 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -44,43 +44,38 @@ *------------------------------------------------------------------*/ /// defined base on EHCI specs value for Endpoint Speed -typedef enum -{ +typedef enum { TUSB_SPEED_FULL = 0, TUSB_SPEED_LOW = 1, TUSB_SPEED_HIGH = 2, TUSB_SPEED_INVALID = 0xff, -}tusb_speed_t; +} tusb_speed_t; /// defined base on USB Specs Endpoint's bmAttributes -typedef enum -{ +typedef enum { TUSB_XFER_CONTROL = 0 , TUSB_XFER_ISOCHRONOUS , TUSB_XFER_BULK , TUSB_XFER_INTERRUPT -}tusb_xfer_type_t; +} tusb_xfer_type_t; -typedef enum -{ +typedef enum { TUSB_DIR_OUT = 0, TUSB_DIR_IN = 1, TUSB_DIR_IN_MASK = 0x80 -}tusb_dir_t; +} tusb_dir_t; -enum -{ +enum { TUSB_EPSIZE_BULK_FS = 64, - TUSB_EPSIZE_BULK_HS= 512, + TUSB_EPSIZE_BULK_HS = 512, TUSB_EPSIZE_ISO_FS_MAX = 1023, TUSB_EPSIZE_ISO_HS_MAX = 1024, }; -/// Isochronous End Point Attributes -typedef enum -{ +/// Isochronous Endpoint Attributes +typedef enum { TUSB_ISO_EP_ATT_NO_SYNC = 0x00, TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, @@ -88,11 +83,10 @@ typedef enum TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback -}tusb_iso_ep_attribute_t; +} tusb_iso_ep_attribute_t; /// USB Descriptor Types -typedef enum -{ +typedef enum { TUSB_DESC_DEVICE = 0x01, TUSB_DESC_CONFIGURATION = 0x02, TUSB_DESC_STRING = 0x03, @@ -119,10 +113,9 @@ typedef enum TUSB_DESC_SUPERSPEED_ENDPOINT_COMPANION = 0x30, TUSB_DESC_SUPERSPEED_ISO_ENDPOINT_COMPANION = 0x31 -}tusb_desc_type_t; +} tusb_desc_type_t; -typedef enum -{ +typedef enum { TUSB_REQ_GET_STATUS = 0 , TUSB_REQ_CLEAR_FEATURE = 1 , TUSB_REQ_RESERVED = 2 , @@ -136,25 +129,22 @@ typedef enum TUSB_REQ_GET_INTERFACE = 10 , TUSB_REQ_SET_INTERFACE = 11 , TUSB_REQ_SYNCH_FRAME = 12 -}tusb_request_code_t; +} tusb_request_code_t; -typedef enum -{ +typedef enum { TUSB_REQ_FEATURE_EDPT_HALT = 0, TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1, TUSB_REQ_FEATURE_TEST_MODE = 2 -}tusb_request_feature_selector_t; +} tusb_request_feature_selector_t; -typedef enum -{ +typedef enum { TUSB_REQ_TYPE_STANDARD = 0, TUSB_REQ_TYPE_CLASS, TUSB_REQ_TYPE_VENDOR, TUSB_REQ_TYPE_INVALID } tusb_request_type_t; -typedef enum -{ +typedef enum { TUSB_REQ_RCPT_DEVICE =0, TUSB_REQ_RCPT_INTERFACE, TUSB_REQ_RCPT_ENDPOINT, @@ -162,8 +152,7 @@ typedef enum } tusb_request_recipient_t; // https://www.usb.org/defined-class-codes -typedef enum -{ +typedef enum { TUSB_CLASS_UNSPECIFIED = 0 , TUSB_CLASS_AUDIO = 1 , TUSB_CLASS_CDC = 2 , @@ -187,26 +176,23 @@ typedef enum TUSB_CLASS_MISC = 0xEF , TUSB_CLASS_APPLICATION_SPECIFIC = 0xFE , TUSB_CLASS_VENDOR_SPECIFIC = 0xFF -}tusb_class_code_t; +} tusb_class_code_t; typedef enum { MISC_SUBCLASS_COMMON = 2 }misc_subclass_type_t; -typedef enum -{ +typedef enum { MISC_PROTOCOL_IAD = 1 -}misc_protocol_type_t; +} misc_protocol_type_t; -typedef enum -{ +typedef enum { APP_SUBCLASS_USBTMC = 0x03, APP_SUBCLASS_DFU_RUNTIME = 0x01 } app_subclass_type_t; -typedef enum -{ +typedef enum { DEVICE_CAPABILITY_WIRELESS_USB = 0x01, DEVICE_CAPABILITY_USB20_EXTENSION = 0x02, DEVICE_CAPABILITY_SUPERSPEED_USB = 0x03, @@ -223,7 +209,7 @@ typedef enum DEVICE_CAPABILITY_AUTHENTICATION = 0x0E, DEVICE_CAPABILITY_BILLBOARD_EX = 0x0F, DEVICE_CAPABILITY_CONFIGURATION_SUMMARY = 0x10 -}device_capability_type_t; +} device_capability_type_t; enum { TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = TU_BIT(5), @@ -235,28 +221,25 @@ enum { //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -typedef enum -{ +typedef enum { XFER_RESULT_SUCCESS = 0, XFER_RESULT_FAILED, XFER_RESULT_STALLED, XFER_RESULT_TIMEOUT, XFER_RESULT_INVALID -}xfer_result_t; +} xfer_result_t; -enum // TODO remove -{ +// TODO remove +enum { DESC_OFFSET_LEN = 0, DESC_OFFSET_TYPE = 1 }; -enum -{ +enum { INTERFACE_INVALID_NUMBER = 0xff }; -typedef enum -{ +typedef enum { MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00, MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01, MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02, @@ -268,16 +251,14 @@ typedef enum MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 } microsoft_os_20_type_t; -enum -{ +enum { CONTROL_STAGE_IDLE, CONTROL_STAGE_SETUP, CONTROL_STAGE_DATA, CONTROL_STAGE_ACK }; -enum -{ +enum { TUSB_INDEX_INVALID_8 = 0xFFu }; @@ -290,8 +271,7 @@ TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN /// USB Device Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< DEVICE Descriptor Type. uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). This field identifies the release of the USB Specification with which the device and its descriptors are compliant. @@ -314,8 +294,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); // USB Binary Device Object Store (BOS) Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type uint16_t wTotalLength ; ///< Total length of data returned for this descriptor @@ -325,8 +304,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct"); /// USB Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type uint16_t wTotalLength ; ///< Total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration. @@ -341,8 +319,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); /// USB Interface Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< INTERFACE Descriptor Type @@ -358,8 +335,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct"); /// USB Endpoint Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; // Size of this descriptor in bytes uint8_t bDescriptorType ; // ENDPOINT Descriptor Type @@ -379,8 +355,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7, "size is not correct"); /// USB Other Speed Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Other_speed_Configuration Type uint16_t wTotalLength ; ///< Total length of data returned @@ -393,8 +368,7 @@ typedef struct TU_ATTR_PACKED } tusb_desc_other_speed_t; /// USB Device Qualifier Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Device Qualifier Type uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) @@ -411,8 +385,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct"); /// USB Interface Association Descriptor (IAD ECN) -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Other_speed_Configuration Type @@ -427,16 +400,14 @@ typedef struct TU_ATTR_PACKED } tusb_desc_interface_assoc_t; // USB String Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< Descriptor Type uint16_t unicode_string[]; } tusb_desc_string_t; // USB Binary Device Object Store (BOS) -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType ; uint8_t bDevCapabilityType; @@ -445,9 +416,8 @@ typedef struct TU_ATTR_PACKED uint8_t CapabilityData[]; } tusb_desc_bos_platform_t; -// USB WebuSB URL Descriptor -typedef struct TU_ATTR_PACKED -{ +// USB WebUSB URL Descriptor +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; uint8_t bScheme; @@ -455,8 +425,7 @@ typedef struct TU_ATTR_PACKED } tusb_desc_webusb_url_t; // DFU Functional Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; @@ -481,7 +450,7 @@ typedef struct TU_ATTR_PACKED // //--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED{ +typedef struct TU_ATTR_PACKED { union { struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. @@ -509,36 +478,30 @@ TU_ATTR_BIT_FIELD_ORDER_END //--------------------------------------------------------------------+ // Get direction from Endpoint address -TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) -{ +TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) { return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; } // Get Endpoint number from address -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) { return (uint8_t)(addr & (~TUSB_DIR_IN_MASK)); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) { return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0)); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) { return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0); } #if CFG_TUSB_DEBUG -TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_dir_str(tusb_dir_t dir) -{ +TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_dir_str(tusb_dir_t dir) { tu_static const char *str[] = {"out", "in"}; return str[dir]; } -TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t) -{ +TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t) { tu_static const char *str[] = {"control", "isochronous", "bulk", "interrupt"}; return str[t]; } @@ -549,21 +512,18 @@ TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_ //--------------------------------------------------------------------+ // return next descriptor -TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) { uint8_t const* desc8 = (uint8_t const*) desc; return desc8 + desc8[DESC_OFFSET_LEN]; } // get descriptor type -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; } // get descriptor length -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; } -- cgit v1.3.1 From 4c9f462423338a812378924233eac55ce0e96fb8 Mon Sep 17 00:00:00 2001 From: YixingShen Date: Fri, 26 Jan 2024 09:09:18 +0800 Subject: add "set tx_busy 1" into video_capture's video_tas for "if (tx_busy) return" --- examples/device/video_capture/src/main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'examples') diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c index 711d4710a..759c06057 100644 --- a/examples/device/video_capture/src/main.c +++ b/examples/device/video_capture/src/main.c @@ -185,6 +185,7 @@ void video_task(void) if (!already_sent) { already_sent = 1; + tx_busy = 1; start_ms = board_millis(); #ifdef CFG_EXAMPLE_VIDEO_READONLY # if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) @@ -203,6 +204,7 @@ void video_task(void) if (cur - start_ms < interval_ms) return; // not enough time if (tx_busy) return; start_ms += interval_ms; + tx_busy = 1; #ifdef CFG_EXAMPLE_VIDEO_READONLY # if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) -- cgit v1.3.1 From b5cd673330fc87f2981ecf139b24940df5cb3cfe Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 26 Jan 2024 22:55:55 +0700 Subject: rename and add more video descriptors use struct to define uvc descriptor for video_capture since uvc is rather too complicated to use macro templates --- .../device/video_capture/src/usb_descriptors.c | 233 +++++++++++++++++++-- .../device/video_capture/src/usb_descriptors.h | 4 +- src/class/video/video.h | 224 ++++++++++++++------ src/class/video/video_device.c | 20 +- src/common/tusb_types.h | 3 +- 5 files changed, 389 insertions(+), 95 deletions(-) (limited to 'examples') diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c index d38f158c8..8e54d3afd 100644 --- a/examples/device/video_capture/src/usb_descriptors.c +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -40,6 +40,26 @@ #define USB_VID 0xCafe #define USB_BCD 0x0200 +// String Descriptor Index +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, + STRID_UVC_CONTROL, + STRID_UVC_STREAMING, +}; + +// array of pointer to string descriptors +char const* string_desc_arr[] = { + (const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "TinyUSB UVC Control", // 4: UVC Interface + "TinyUSB UVC Streaming", // 5: UVC Interface +}; + //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ @@ -60,9 +80,9 @@ tusb_desc_device_t const desc_device = { .idProduct = USB_PID, .bcdDevice = 0x0100, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, + .iManufacturer = STRID_MANUFACTURER, + .iProduct = STRID_PRODUCT, + .iSerialNumber = STRID_SERIAL, .bNumConfigurations = 0x01 }; @@ -164,6 +184,193 @@ uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { } #endif // highspeed +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_control_header_1itf_t header; + tusb_desc_video_control_camera_terminal_t camera_terminal; + tusb_desc_video_control_output_terminal_t output_terminal; +} uvc_control_desc_t; + +/* Windows support YUY2 and NV12 + * https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/usb-video-class-driver-overview */ + +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_streaming_input_header_1byte_t header; + tusb_desc_video_format_uncompressed_t format; + tusb_desc_video_frame_uncompressed_continuous_t frame; + tusb_desc_video_streaming_color_matching_t color; + tusb_desc_endpoint_t ep; +} uvc_streaming_desc_t; + +typedef struct TU_ATTR_PACKED { + tusb_desc_configuration_t config; + tusb_desc_interface_assoc_t iad; + uvc_control_desc_t video_control; + uvc_streaming_desc_t video_streaming; +} uvc_cfg_desc_t; + +const uvc_cfg_desc_t config_desc = { + .config = { + .bLength = sizeof(tusb_desc_configuration_t), + .bDescriptorType = TUSB_DESC_CONFIGURATION, + + .wTotalLength = sizeof(uvc_cfg_desc_t), + .bNumInterfaces = ITF_NUM_TOTAL, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, + .bMaxPower = 100 / 2 + }, + .iad = { + .bLength = sizeof(tusb_desc_interface_assoc_t), + .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, + + .bFirstInterface = ITF_NUM_VIDEO_CONTROL, + .bInterfaceCount = 2, + .bFunctionClass = TUSB_CLASS_VIDEO, + .bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION, + .bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED, + .iFunction = 0 + }, + + .video_control = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_CONTROL, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_CONTROL + }, + .header = { + .bLength = sizeof(tusb_desc_video_control_header_1itf_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER, + + .bcdUVC = VIDEO_BCD_1_50, + .wTotalLength = sizeof(uvc_control_desc_t) - sizeof(tusb_desc_interface_t), // CS VC descriptors only + .dwClockFrequency = UVC_CLOCK_FREQUENCY, + .bInCollection = 1, + .baInterfaceNr = { ITF_NUM_VIDEO_STREAMING } + }, + .camera_terminal = { + .bLength = sizeof(tusb_desc_video_control_camera_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .wTerminalType = VIDEO_ITT_CAMERA, + .bAssocTerminal = 0, + .iTerminal = 0, + .wObjectiveFocalLengthMin = 0, + .wObjectiveFocalLengthMax = 0, + .wOcularFocalLength = 0, + .bControlSize = 3, + .bmControls = { 0, 0, 0 } + }, + .output_terminal = { + .bLength = sizeof(tusb_desc_video_control_output_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .wTerminalType = VIDEO_TT_STREAMING, + .bAssocTerminal = 0, + .bSourceID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .iTerminal = 0 + } + }, + + .video_streaming = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING + }, + .header = { + .bLength = sizeof(tusb_desc_video_streaming_input_header_1byte_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, + + .bNumFormats = 1, + .wTotalLength = sizeof(uvc_streaming_desc_t) - sizeof(tusb_desc_interface_t) - sizeof(tusb_desc_endpoint_t), // CS VS descriptors only + .bEndpointAddress = EPNUM_VIDEO_IN, + .bmInfo = 0, + .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .bStillCaptureMethod = 0, + .bTriggerSupport = 0, + .bTriggerUsage = 0, + .bControlSize = 1, + .bmaControls = { 0 } + }, + .format = { + .bLength = sizeof(tusb_desc_video_format_uncompressed_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, + + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .guidFormat = { TUD_VIDEO_GUID_YUY2 }, + .bBitsPerPixel = 16, + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, + .bAspectRatioY = 0, + .bmInterlaceFlags = 0, + .bCopyProtect = 0 + }, + .frame = { + .bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, + + .bFrameIndex = 1, // 1-based index + .bmCapabilities = 0, + .wWidth = FRAME_WIDTH, + .wHeight = FRAME_HEIGHT, + .dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1, + .dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE, + .dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8, + .dwDefaultFrameInterval = 10000000 / FRAME_RATE, + .bFrameIntervalType = 0, // continuous + .dwFrameInterval = { + 10000000 / FRAME_RATE, // min + 10000000, // max + 10000000 / FRAME_RATE // step + } + }, + .color = { + .bLength = sizeof(tusb_desc_video_streaming_color_matching_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT, + + .bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709, + .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, + .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M + }, + .ep = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = EPNUM_VIDEO_IN, + .bmAttributes = { .xfer = TUSB_XFER_BULK }, + .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, + .bInterval = 1 + } + } +}; + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete @@ -174,7 +381,8 @@ uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { // Although we are highspeed, host may be fullspeed. return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; #else - return desc_fs_configuration; +// return desc_fs_configuration; + return (uint8_t const*) &config_desc; #endif } @@ -182,23 +390,6 @@ uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { // String Descriptors //--------------------------------------------------------------------+ -// String Descriptor Index -enum { - STRID_LANGID = 0, - STRID_MANUFACTURER, - STRID_PRODUCT, - STRID_SERIAL, -}; - -// array of pointer to string descriptors -char const* string_desc_arr[] = { - (const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - NULL, // 3: Serials will use unique ID if possible - "TinyUSB UVC", // 4: UVC Interface -}; - static uint16_t _desc_str[32 + 1]; // Invoked when received GET STRING DESCRIPTOR request diff --git a/examples/device/video_capture/src/usb_descriptors.h b/examples/device/video_capture/src/usb_descriptors.h index fa3c1fbd2..fd908c9c2 100644 --- a/examples/device/video_capture/src/usb_descriptors.h +++ b/examples/device/video_capture/src/usb_descriptors.h @@ -210,7 +210,7 @@ enum { /* Video stream frame format */ \ TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \ _width * _height * 16, _width * _height * 16 * _fps, \ - _width * _height * 16, \ + _width * _height * 16 / 8, \ (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1) @@ -223,7 +223,7 @@ enum { TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ - TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ + TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, UVC_ENTITY_CAP_INPUT_TERMINAL, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 1, _stridx), \ /* Video stream header for without still image capture */ \ diff --git a/src/class/video/video.h b/src/class/video/video.h index d9880c291..162d4e4c4 100644 --- a/src/class/video/video.h +++ b/src/class/video/video.h @@ -29,6 +29,10 @@ #include "common/tusb_common.h" +enum { + VIDEO_BCD_1_50 = 0x0150, +}; + // Table 3-19 Color Matching Descriptor typedef enum { VIDEO_COLOR_PRIMARIES_UNDEFINED = 0x00, @@ -198,55 +202,98 @@ typedef enum { } video_terminal_type_t; //--------------------------------------------------------------------+ -// Descriptors +// Video Control (VC) Descriptors //--------------------------------------------------------------------+ /* 2.3.4.2 */ +#define tusb_desc_video_control_header_nitf_t(_nitf) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t bDescriptorSubType; \ + uint16_t bcdUVC; \ + uint16_t wTotalLength; \ + uint32_t dwClockFrequency; /* deprecated */ \ + uint8_t bInCollection; \ + uint8_t baInterfaceNr[_nitf]; \ + } + +typedef tusb_desc_video_control_header_nitf_t() tusb_desc_video_control_header_t; +typedef tusb_desc_video_control_header_nitf_t(1) tusb_desc_video_control_header_1itf_t; +typedef tusb_desc_video_control_header_nitf_t(2) tusb_desc_video_control_header_2itf_t; +typedef tusb_desc_video_control_header_nitf_t(3) tusb_desc_video_control_header_3itf_t; +typedef tusb_desc_video_control_header_nitf_t(4) tusb_desc_video_control_header_4itf_t; + typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubType; - uint16_t bcdUVC; - uint16_t wTotalLength; - uint32_t dwClockFrequency; - uint8_t bInCollection; - uint8_t baInterfaceNr[]; -} tusb_desc_cs_video_ctl_itf_hdr_t; + uint8_t bTerminalID; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t iTerminal; +} tusb_desc_video_control_input_terminal_t; + +TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_input_terminal_t) == 8, "size is not correct"); -/* 2.4.3.3 */ typedef struct TU_ATTR_PACKED { - uint8_t bHeaderLength; - union { - uint8_t bmHeaderInfo; - struct { - uint8_t FrameID: 1; - uint8_t EndOfFrame: 1; - uint8_t PresentationTime: 1; - uint8_t SourceClockReference: 1; - uint8_t PayloadSpecific: 1; - uint8_t StillImage: 1; - uint8_t Error: 1; - uint8_t EndOfHeader: 1; - }; - }; -} tusb_video_payload_header_t; + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bTerminalID; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t bSourceID; + uint8_t iTerminal; +} tusb_desc_video_control_output_terminal_t; + +TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_output_terminal_t) == 9, "size is not correct"); -/* 3.9.2.1 */ typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - uint8_t bmInfo; - uint8_t bTerminalLink; - uint8_t bStillCaptureMethod; - uint8_t bTriggerSupport; - uint8_t bTriggerUsage; + uint8_t bTerminalID; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t iTerminal; + + uint16_t wObjectiveFocalLengthMin; + uint16_t wObjectiveFocalLengthMax; + uint16_t wOcularFocalLength; uint8_t bControlSize; - uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_in_hdr_t; + uint8_t bmControls[3]; +} tusb_desc_video_control_camera_terminal_t; + +TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_camera_terminal_t) == 18, "size is not correct"); + +//--------------------------------------------------------------------+ +// Video Streaming (VS) Descriptors +//--------------------------------------------------------------------+ + +/* 3.9.2.1 */ +#define tusb_desc_video_streaming_input_header_nbyte_t(_nb) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t bDescriptorSubType; \ + uint8_t bNumFormats; /* Number of video payload Format descriptors for this interface */ \ + uint16_t wTotalLength; \ + uint8_t bEndpointAddress; \ + uint8_t bmInfo; /* Bit 0: dynamic format change supported */ \ + uint8_t bTerminalLink; \ + uint8_t bStillCaptureMethod; \ + uint8_t bTriggerSupport; /* Hardware trigger supported */ \ + uint8_t bTriggerUsage; \ + uint8_t bControlSize; /* sizeof of each control item */ \ + uint8_t bmaControls[_nb]; \ + } + +typedef tusb_desc_video_streaming_input_header_nbyte_t() tusb_desc_video_streaming_input_header_t; +typedef tusb_desc_video_streaming_input_header_nbyte_t(1) tusb_desc_video_streaming_input_header_1byte_t; +typedef tusb_desc_video_streaming_input_header_nbyte_t(2) tusb_desc_video_streaming_input_header_2byte_t; +typedef tusb_desc_video_streaming_input_header_nbyte_t(3) tusb_desc_video_streaming_input_header_3byte_t; +typedef tusb_desc_video_streaming_input_header_nbyte_t(4) tusb_desc_video_streaming_input_header_4byte_t; /* 3.9.2.2 */ typedef struct TU_ATTR_PACKED { @@ -259,7 +306,7 @@ typedef struct TU_ATTR_PACKED { uint8_t bTerminalLink; uint8_t bControlSize; uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_out_hdr_t; +} tusb_desc_video_streaming_output_header_t; typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -285,14 +332,33 @@ typedef struct TU_ATTR_PACKED { uint8_t bmaControls[]; } output; }; -} tusb_desc_cs_video_stm_itf_hdr_t; +} tusb_desc_video_streaming_inout_header_t; +// 3.9.2.6 Color Matching Descriptor +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bColorPrimaries; + uint8_t bTransferCharacteristics; + uint8_t bMatrixCoefficients; +} tusb_desc_video_streaming_color_matching_t; + +TU_VERIFY_STATIC(sizeof(tusb_desc_video_streaming_color_matching_t) == 6, "size is not correct"); + +//--------------------------------------------------------------------+ +// Format and Frame Descriptor +// Note: bFormatIndex & bFrameIndex are 1-based index +//--------------------------------------------------------------------+ + +//------------- Uncompressed -------------// +// Uncompressed payload specs: 3.1.1 format descriptor typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubType; uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; + uint8_t bNumFrameDescriptors; // Number of frame descriptors for this format uint8_t guidFormat[16]; uint8_t bBitsPerPixel; uint8_t bDefaultFrameIndex; @@ -300,8 +366,39 @@ typedef struct TU_ATTR_PACKED { uint8_t bAspectRatioY; uint8_t bmInterlaceFlags; uint8_t bCopyProtect; -} tusb_desc_cs_video_fmt_uncompressed_t; - +} tusb_desc_video_format_uncompressed_t; + +// Uncompressed payload specs: 3.1.2 frame descriptor +#define tusb_desc_video_frame_uncompressed_nint_t(_nint) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t bDescriptorSubType; \ + uint8_t bFrameIndex; \ + uint8_t bmCapabilities; \ + uint16_t wWidth; \ + uint16_t wHeight; \ + uint32_t dwMinBitRate; \ + uint32_t dwMaxBitRate; \ + uint32_t dwMaxVideoFrameBufferSize; /* deprecated in 1.5 */ \ + uint32_t dwDefaultFrameInterval; \ + uint8_t bFrameIntervalType; \ + uint32_t dwFrameInterval[_nint]; \ + } + +typedef tusb_desc_video_frame_uncompressed_nint_t() tusb_desc_video_frame_uncompressed_t; +typedef tusb_desc_video_frame_uncompressed_nint_t(1) tusb_desc_video_frame_uncompressed_1int_t; +typedef tusb_desc_video_frame_uncompressed_nint_t(2) tusb_desc_video_frame_uncompressed_2int_t; +typedef tusb_desc_video_frame_uncompressed_nint_t(3) tusb_desc_video_frame_uncompressed_3int_t; +typedef tusb_desc_video_frame_uncompressed_nint_t(4) tusb_desc_video_frame_uncompressed_4int_t; + +// continuous = 3 intervals: min, max, step +typedef tusb_desc_video_frame_uncompressed_3int_t tusb_desc_video_frame_uncompressed_continuous_t; + +TU_VERIFY_STATIC(sizeof(tusb_desc_video_frame_uncompressed_continuous_t) == 38, "size is not correct"); + +//------------- MJPEG -------------// +// MJPEG payload specs: 3.1.1 formatt descriptor typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; @@ -314,8 +411,12 @@ typedef struct TU_ATTR_PACKED { uint8_t bAspectRatioY; uint8_t bmInterlaceFlags; uint8_t bCopyProtect; -} tusb_desc_cs_video_fmt_mjpeg_t; +} tusb_desc_video_format_mjpeg_t; +// MJPEG payload specs: 3.1.2 frame descriptor (same as uncompressed) +typedef tusb_desc_video_frame_uncompressed_t tusb_desc_video_frame_mjpeg_t; + +// DV payload specs: 3.1.1 typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; @@ -323,8 +424,9 @@ typedef struct TU_ATTR_PACKED { uint8_t bFormatIndex; uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ uint8_t bFormatType; -} tusb_desc_cs_video_fmt_dv_t; +} tusb_desc_video_format_dv_t; +// Frame Based payload specs: 3.1.1 typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; @@ -339,25 +441,7 @@ typedef struct TU_ATTR_PACKED { uint8_t bmInterlaceFlags; uint8_t bCopyProtect; uint8_t bVaribaleSize; -} tusb_desc_cs_video_fmt_frame_based_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFrameIndex; - uint8_t bmCapabilities; - uint16_t wWidth; - uint16_t wHeight; - uint32_t dwMinBitRate; - uint32_t dwMaxBitRate; - uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ - uint32_t dwDefaultFrameInterval; - uint8_t bFrameIntervalType; - uint32_t dwFrameInterval[]; -} tusb_desc_cs_video_frm_uncompressed_t; - -typedef tusb_desc_cs_video_frm_uncompressed_t tusb_desc_cs_video_frm_mjpeg_t; +} tusb_desc_video_format_framebased_t; typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -373,12 +457,30 @@ typedef struct TU_ATTR_PACKED { uint8_t bFrameIntervalType; uint32_t dwBytesPerLine; uint32_t dwFrameInterval[]; -} tusb_desc_cs_video_frm_frame_based_t; +} tusb_desc_video_frame_framebased_t; //--------------------------------------------------------------------+ // Requests //--------------------------------------------------------------------+ +/* 2.4.3.3 */ +typedef struct TU_ATTR_PACKED { + uint8_t bHeaderLength; + union { + uint8_t bmHeaderInfo; + struct { + uint8_t FrameID: 1; + uint8_t EndOfFrame: 1; + uint8_t PresentationTime: 1; + uint8_t SourceClockReference: 1; + uint8_t PayloadSpecific: 1; + uint8_t StillImage: 1; + uint8_t Error: 1; + uint8_t EndOfHeader: 1; + }; + }; +} tusb_video_payload_header_t; + /* 4.3.1.1 */ typedef struct TU_ATTR_PACKED { union { diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c index c16a45fcd..1affd615e 100644 --- a/src/class/video/video_device.c +++ b/src/class/video/video_device.c @@ -50,17 +50,17 @@ typedef struct { tusb_desc_interface_t std; - tusb_desc_cs_video_ctl_itf_hdr_t ctl; + tusb_desc_video_control_header_t ctl; } tusb_desc_vc_itf_t; typedef struct { tusb_desc_interface_t std; - tusb_desc_cs_video_stm_itf_hdr_t stm; + tusb_desc_video_streaming_inout_header_t stm; } tusb_desc_vs_itf_t; typedef union { - tusb_desc_cs_video_ctl_itf_hdr_t ctl; - tusb_desc_cs_video_stm_itf_hdr_t stm; + tusb_desc_video_control_header_t ctl; + tusb_desc_video_streaming_inout_header_t stm; } tusb_desc_video_itf_hdr_t; typedef struct TU_ATTR_PACKED { @@ -78,9 +78,9 @@ typedef union { uint8_t bFormatIndex; uint8_t bNumFrameDescriptors; }; - tusb_desc_cs_video_fmt_uncompressed_t uncompressed; - tusb_desc_cs_video_fmt_mjpeg_t mjpeg; - tusb_desc_cs_video_fmt_frame_based_t frame_based; + tusb_desc_video_format_uncompressed_t uncompressed; + tusb_desc_video_format_mjpeg_t mjpeg; + tusb_desc_video_format_framebased_t frame_based; } tusb_desc_cs_video_fmt_t; typedef union { @@ -93,9 +93,9 @@ typedef union { uint16_t wWidth; uint16_t wHeight; }; - tusb_desc_cs_video_frm_uncompressed_t uncompressed; - tusb_desc_cs_video_frm_mjpeg_t mjpeg; - tusb_desc_cs_video_frm_frame_based_t frame_based; + tusb_desc_video_frame_uncompressed_t uncompressed; + tusb_desc_video_frame_mjpeg_t mjpeg; + tusb_desc_video_frame_framebased_t frame_based; } tusb_desc_cs_video_frm_t; /* video streaming interface */ diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index d4ef1fd09..2c5dce723 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -399,6 +399,8 @@ typedef struct TU_ATTR_PACKED { uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. } tusb_desc_interface_assoc_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_interface_assoc_t) == 8, "size is not correct"); + // USB String Descriptor typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes @@ -469,7 +471,6 @@ typedef struct TU_ATTR_PACKED { TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); - TU_ATTR_PACKED_END // End of all packed definitions TU_ATTR_BIT_FIELD_ORDER_END -- cgit v1.3.1 From 0daf8ec51b9513fbab9601fedb2150dda3927b05 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 26 Jan 2024 23:23:38 +0700 Subject: update example to work bulk mjpeg --- .../device/video_capture/src/usb_descriptors.c | 27 +++++++++++++++++++++- src/class/video/video.h | 10 +++++++- 2 files changed, 35 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c index 8e54d3afd..90a6b27a2 100644 --- a/examples/device/video_capture/src/usb_descriptors.c +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -109,6 +109,10 @@ uint8_t const* tud_descriptor_device_cb(void) { #define EPNUM_VIDEO_IN 0x81 #endif +#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) + #define USE_MJPEG +#endif + // For mcus that does not have enough SRAM for frame buffer, we use fixed frame data. // To further reduce the size, we use MJPEG format instead of YUY2. // Select interface descriptor and length accordingly. @@ -197,8 +201,15 @@ typedef struct TU_ATTR_PACKED { typedef struct TU_ATTR_PACKED { tusb_desc_interface_t itf; tusb_desc_video_streaming_input_header_1byte_t header; + +#ifdef USE_MJPEG + tusb_desc_video_format_mjpeg_t format; + tusb_desc_video_frame_mjpeg_continuous_t frame; +#else tusb_desc_video_format_uncompressed_t format; tusb_desc_video_frame_uncompressed_continuous_t frame; +#endif + tusb_desc_video_streaming_color_matching_t color; tusb_desc_endpoint_t ep; } uvc_streaming_desc_t; @@ -316,14 +327,22 @@ const uvc_cfg_desc_t config_desc = { .bmaControls = { 0 } }, .format = { +#ifdef USE_MJPEG + .bLength = sizeof(tusb_desc_video_format_mjpeg_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_MJPEG, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .bmFlags = 0, +#else .bLength = sizeof(tusb_desc_video_format_uncompressed_t), .bDescriptorType = TUSB_DESC_CS_INTERFACE, .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, - .bFormatIndex = 1, // 1-based index .bNumFrameDescriptors = 1, .guidFormat = { TUD_VIDEO_GUID_YUY2 }, .bBitsPerPixel = 16, +#endif .bDefaultFrameIndex = 1, .bAspectRatioX = 0, .bAspectRatioY = 0, @@ -331,9 +350,15 @@ const uvc_cfg_desc_t config_desc = { .bCopyProtect = 0 }, .frame = { +#ifdef USE_MJPEG + .bLength = sizeof(tusb_desc_video_frame_mjpeg_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_MJPEG, +#else .bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t), .bDescriptorType = TUSB_DESC_CS_INTERFACE, .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, +#endif .bFrameIndex = 1, // 1-based index .bmCapabilities = 0, diff --git a/src/class/video/video.h b/src/class/video/video.h index 162d4e4c4..bed8eeecf 100644 --- a/src/class/video/video.h +++ b/src/class/video/video.h @@ -405,7 +405,7 @@ typedef struct TU_ATTR_PACKED { uint8_t bDescriptorSubType; uint8_t bFormatIndex; uint8_t bNumFrameDescriptors; - uint8_t bmFlags; + uint8_t bmFlags; // Bit 0: fixed size samples (1 = yes) uint8_t bDefaultFrameIndex; uint8_t bAspectRatioX; uint8_t bAspectRatioY; @@ -415,7 +415,15 @@ typedef struct TU_ATTR_PACKED { // MJPEG payload specs: 3.1.2 frame descriptor (same as uncompressed) typedef tusb_desc_video_frame_uncompressed_t tusb_desc_video_frame_mjpeg_t; +typedef tusb_desc_video_frame_uncompressed_1int_t tusb_desc_video_frame_mjpeg_1int_t; +typedef tusb_desc_video_frame_uncompressed_2int_t tusb_desc_video_frame_mjpeg_2int_t; +typedef tusb_desc_video_frame_uncompressed_3int_t tusb_desc_video_frame_mjpeg_3int_t; +typedef tusb_desc_video_frame_uncompressed_4int_t tusb_desc_video_frame_mjpeg_4int_t; +// continuous = 3 intervals: min, max, step +typedef tusb_desc_video_frame_mjpeg_3int_t tusb_desc_video_frame_mjpeg_continuous_t; + +//------------- DV -------------// // DV payload specs: 3.1.1 typedef struct TU_ATTR_PACKED { uint8_t bLength; -- cgit v1.3.1 From 2da8f763d751f658a4b7859ceb69e4247e1fbc5f Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 26 Jan 2024 23:50:58 +0700 Subject: update example to work with iso streaming --- .../device/video_capture/src/usb_descriptors.c | 46 ++++++++++++++++++---- .../device/video_capture/src/usb_descriptors.h | 2 +- 2 files changed, 39 insertions(+), 9 deletions(-) (limited to 'examples') diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c index 90a6b27a2..6f2a207fb 100644 --- a/examples/device/video_capture/src/usb_descriptors.c +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -110,9 +110,13 @@ uint8_t const* tud_descriptor_device_cb(void) { #endif #if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) - #define USE_MJPEG + #define USE_MJPEG 1 +#else + #define USE_MJPEG 0 #endif +#define USE_ISO_STREAMING (!CFG_TUD_VIDEO_STREAMING_BULK) + // For mcus that does not have enough SRAM for frame buffer, we use fixed frame data. // To further reduce the size, we use MJPEG format instead of YUY2. // Select interface descriptor and length accordingly. @@ -202,7 +206,7 @@ typedef struct TU_ATTR_PACKED { tusb_desc_interface_t itf; tusb_desc_video_streaming_input_header_1byte_t header; -#ifdef USE_MJPEG +#if USE_MJPEG tusb_desc_video_format_mjpeg_t format; tusb_desc_video_frame_mjpeg_continuous_t frame; #else @@ -211,6 +215,12 @@ typedef struct TU_ATTR_PACKED { #endif tusb_desc_video_streaming_color_matching_t color; + +#if USE_ISO_STREAMING + // For ISO streaming, USB spec requires to alternate interface + tusb_desc_interface_t itf_alt; +#endif + tusb_desc_endpoint_t ep; } uvc_streaming_desc_t; @@ -230,7 +240,7 @@ const uvc_cfg_desc_t config_desc = { .bNumInterfaces = ITF_NUM_TOTAL, .bConfigurationValue = 1, .iConfiguration = 0, - .bmAttributes = TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, + .bmAttributes = TU_BIT(7), .bMaxPower = 100 / 2 }, .iad = { @@ -304,7 +314,7 @@ const uvc_cfg_desc_t config_desc = { .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING, .bAlternateSetting = 0, - .bNumEndpoints = 1, + .bNumEndpoints = CFG_TUD_VIDEO_STREAMING_BULK, // bulk 1, iso 0 .bInterfaceClass = TUSB_CLASS_VIDEO, .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, @@ -316,7 +326,8 @@ const uvc_cfg_desc_t config_desc = { .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, .bNumFormats = 1, - .wTotalLength = sizeof(uvc_streaming_desc_t) - sizeof(tusb_desc_interface_t) - sizeof(tusb_desc_endpoint_t), // CS VS descriptors only + .wTotalLength = sizeof(uvc_streaming_desc_t) - sizeof(tusb_desc_interface_t) + - sizeof(tusb_desc_endpoint_t) - (USE_ISO_STREAMING ? sizeof(tusb_desc_interface_t) : 0) , // CS VS descriptors only .bEndpointAddress = EPNUM_VIDEO_IN, .bmInfo = 0, .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, @@ -327,7 +338,7 @@ const uvc_cfg_desc_t config_desc = { .bmaControls = { 0 } }, .format = { -#ifdef USE_MJPEG +#if USE_MJPEG .bLength = sizeof(tusb_desc_video_format_mjpeg_t), .bDescriptorType = TUSB_DESC_CS_INTERFACE, .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_MJPEG, @@ -350,7 +361,7 @@ const uvc_cfg_desc_t config_desc = { .bCopyProtect = 0 }, .frame = { -#ifdef USE_MJPEG +#if USE_MJPEG .bLength = sizeof(tusb_desc_video_frame_mjpeg_continuous_t), .bDescriptorType = TUSB_DESC_CS_INTERFACE, .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_MJPEG, @@ -384,12 +395,31 @@ const uvc_cfg_desc_t config_desc = { .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M }, + +#if USE_ISO_STREAMING + .itf_alt = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING, + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING + }, +#endif + .ep = { .bLength = sizeof(tusb_desc_endpoint_t), .bDescriptorType = TUSB_DESC_ENDPOINT, .bEndpointAddress = EPNUM_VIDEO_IN, - .bmAttributes = { .xfer = TUSB_XFER_BULK }, + .bmAttributes = { + .xfer = CFG_TUD_VIDEO_STREAMING_BULK ? TUSB_XFER_BULK : TUSB_XFER_ISOCHRONOUS, + .sync = CFG_TUD_VIDEO_STREAMING_BULK ? 0 : 1 // asynchronous + }, .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, .bInterval = 1 } diff --git a/examples/device/video_capture/src/usb_descriptors.h b/examples/device/video_capture/src/usb_descriptors.h index fd908c9c2..aba0d4b7a 100644 --- a/examples/device/video_capture/src/usb_descriptors.h +++ b/examples/device/video_capture/src/usb_descriptors.h @@ -146,7 +146,7 @@ enum { /* Video stream frame format */ \ TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \ _width * _height * 16, _width * _height * 16 * _fps, \ - _width * _height * 16, \ + _width * _height * 16 / 8, \ (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ /* VS alt 1 */\ -- cgit v1.3.1 From d52909ec5caae5413758eeb169e68c82c7588f3d Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 29 Jan 2024 18:02:57 +0700 Subject: remove the use of descriptor template for video capture example --- .../device/video_capture/src/usb_descriptors.c | 141 +++++++++------------ .../device/video_capture/src/usb_descriptors.h | 12 +- 2 files changed, 61 insertions(+), 92 deletions(-) (limited to 'examples') diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c index 6f2a207fb..17e11229d 100644 --- a/examples/device/video_capture/src/usb_descriptors.c +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -97,6 +97,19 @@ uint8_t const* tud_descriptor_device_cb(void) { // Configuration Descriptor //--------------------------------------------------------------------+ +/* Time stamp base clock. It is a deprecated parameter. */ +#define UVC_CLOCK_FREQUENCY 27000000 + +/* video capture path */ +#define UVC_ENTITY_CAP_INPUT_TERMINAL 0x01 +#define UVC_ENTITY_CAP_OUTPUT_TERMINAL 0x02 + +enum { + ITF_NUM_VIDEO_CONTROL, + ITF_NUM_VIDEO_STREAMING, + ITF_NUM_TOTAL +}; + // Select appropriate endpoint number #if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number @@ -117,81 +130,6 @@ uint8_t const* tud_descriptor_device_cb(void) { #define USE_ISO_STREAMING (!CFG_TUD_VIDEO_STREAMING_BULK) -// For mcus that does not have enough SRAM for frame buffer, we use fixed frame data. -// To further reduce the size, we use MJPEG format instead of YUY2. -// Select interface descriptor and length accordingly. -#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) - #if CFG_TUD_VIDEO_STREAMING_BULK - #define ITF_VIDEO_DESC(epsize) TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(4, EPNUM_VIDEO_IN, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, epsize) - #define ITF_VIDEO_LEN TUD_VIDEO_CAPTURE_DESC_MJPEG_BULK_LEN - #else - #define ITF_VIDEO_DESC(epsize) TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(4, EPNUM_VIDEO_IN, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, epsize) - #define ITF_VIDEO_LEN TUD_VIDEO_CAPTURE_DESC_MJPEG_LEN - #endif -#else - #if CFG_TUD_VIDEO_STREAMING_BULK - #define ITF_VIDEO_DESC(epsize) TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(4, EPNUM_VIDEO_IN, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, epsize) - #define ITF_VIDEO_LEN TUD_VIDEO_CAPTURE_DESC_UNCOMPR_BULK_LEN - #else - #define ITF_VIDEO_DESC(epsize) TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(4, EPNUM_VIDEO_IN, FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, epsize) - #define ITF_VIDEO_LEN TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN - #endif -#endif - -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + ITF_VIDEO_LEN) - -// full speed descriptor -uint8_t const desc_fs_configuration[] = { - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 500), - - // IAD for Video Control - ITF_VIDEO_DESC(CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -}; - -#if TUD_OPT_HIGH_SPEED -// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration -uint8_t const desc_hs_configuration[] = { - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 500), - - // IAD for Video Control - ITF_VIDEO_DESC(CFG_TUD_VIDEO_STREAMING_BULK ? 512 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -}; - -// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = USB_BCD, - - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .bNumConfigurations = 0x01, - .bReserved = 0x00 -}; - -// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. -// device_qualifier descriptor describes information about a high-speed capable device that would -// change if the device were operating at the other speed. If not highspeed capable stall this request. -uint8_t const* tud_descriptor_device_qualifier_cb(void) { - return (uint8_t const*) &desc_device_qualifier; -} - -// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa -uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { - (void) index; // for multiple configurations - // if link speed is high return fullspeed config, and vice versa - return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration; -} -#endif // highspeed - typedef struct TU_ATTR_PACKED { tusb_desc_interface_t itf; tusb_desc_video_control_header_1itf_t header; @@ -231,7 +169,7 @@ typedef struct TU_ATTR_PACKED { uvc_streaming_desc_t video_streaming; } uvc_cfg_desc_t; -const uvc_cfg_desc_t config_desc = { +const uvc_cfg_desc_t desc_fs_configuration = { .config = { .bLength = sizeof(tusb_desc_configuration_t), .bDescriptorType = TUSB_DESC_CONFIGURATION, @@ -370,7 +308,6 @@ const uvc_cfg_desc_t config_desc = { .bDescriptorType = TUSB_DESC_CS_INTERFACE, .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, #endif - .bFrameIndex = 1, // 1-based index .bmCapabilities = 0, .wWidth = FRAME_WIDTH, @@ -426,6 +363,42 @@ const uvc_cfg_desc_t config_desc = { } }; +#if TUD_OPT_HIGH_SPEED +uvc_cfg_desc_t desc_hs_configuration = desc_fs_configuration; + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const* tud_descriptor_device_qualifier_cb(void) { + return (uint8_t const*) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations + // if link speed is high return fullspeed config, and vice versa + return (uint8_t const*) ((tud_speed_get() == TUSB_SPEED_HIGH) ? &desc_fs_configuration : &desc_hs_configuration); +} +#endif // highspeed + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete @@ -434,11 +407,17 @@ uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { #if TUD_OPT_HIGH_SPEED // Although we are highspeed, host may be fullspeed. - return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; -#else -// return desc_fs_configuration; - return (uint8_t const*) &config_desc; + if (tud_speed_get() == TUSB_SPEED_HIGH) { + // change endpoint bulk size to 512 if bulk streaming + if (CFG_TUD_VIDEO_STREAMING_BULK) { + desc_hs_configuration.video_streaming.ep.wMaxPacketSize = 512; + } + return (uint8_t const*) &desc_hs_configuration; + } else #endif + { + return (uint8_t const*) &desc_fs_configuration; + } } //--------------------------------------------------------------------+ diff --git a/examples/device/video_capture/src/usb_descriptors.h b/examples/device/video_capture/src/usb_descriptors.h index aba0d4b7a..12d41b2f3 100644 --- a/examples/device/video_capture/src/usb_descriptors.h +++ b/examples/device/video_capture/src/usb_descriptors.h @@ -27,21 +27,11 @@ #ifndef _USB_DESCRIPTORS_H_ #define _USB_DESCRIPTORS_H_ -/* Time stamp base clock. It is a deprecated parameter. */ -#define UVC_CLOCK_FREQUENCY 27000000 -/* video capture path */ -#define UVC_ENTITY_CAP_INPUT_TERMINAL 0x01 -#define UVC_ENTITY_CAP_OUTPUT_TERMINAL 0x02 - #define FRAME_WIDTH 128 #define FRAME_HEIGHT 96 #define FRAME_RATE 10 -enum { - ITF_NUM_VIDEO_CONTROL, - ITF_NUM_VIDEO_STREAMING, - ITF_NUM_TOTAL -}; +// NOTE: descriptor template is not used but leave here as reference #define TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN (\ TUD_VIDEO_DESC_IAD_LEN\ -- cgit v1.3.1 From 55950656cbee915662a9a33477ddd549489ffcf0 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 29 Jan 2024 23:23:06 +0700 Subject: add freertos build support for video_capture example --- examples/device/video_capture/src/CMakeLists.txt | 4 + examples/device/video_capture/src/main.c | 131 ++++++++++++++++++--- examples/device/video_capture/src/tusb_config.h | 8 ++ .../device/video_capture/src/usb_descriptors.c | 29 +++-- hw/bsp/board_api.h | 19 ++- src/class/video/video.h | 2 +- 6 files changed, 170 insertions(+), 23 deletions(-) create mode 100644 examples/device/video_capture/src/CMakeLists.txt (limited to 'examples') diff --git a/examples/device/video_capture/src/CMakeLists.txt b/examples/device/video_capture/src/CMakeLists.txt new file mode 100644 index 000000000..cef2b46ee --- /dev/null +++ b/examples/device/video_capture/src/CMakeLists.txt @@ -0,0 +1,4 @@ +# This file is for ESP-IDF only +idf_component_register(SRCS "main.c" "usb_descriptors.c" + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c index e63335e67..091eb8d0c 100644 --- a/examples/device/video_capture/src/main.c +++ b/examples/device/video_capture/src/main.c @@ -48,13 +48,25 @@ enum { static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; -void led_blinking_task(void); -void video_task(void); +void led_blinking_task(void* param); +void usb_device_task(void *param); +void video_task(void* param); -/*------------- MAIN -------------*/ +#if CFG_TUSB_OS == OPT_OS_FREERTOS +void freertos_init_task(void); +#endif + + +//--------------------------------------------------------------------+ +// Main +//--------------------------------------------------------------------+ int main(void) { board_init(); + // If using FreeRTOS: create blinky, tinyusb device, video task +#if CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init_task(); +#else // init device stack on configured roothub port tud_init(BOARD_TUD_RHPORT); @@ -64,10 +76,10 @@ int main(void) { while (1) { tud_task(); // tinyusb device task - led_blinking_task(); - - video_task(); + led_blinking_task(NULL); + video_task(NULL); } +#endif } //--------------------------------------------------------------------+ @@ -169,7 +181,7 @@ static void fill_color_bar(uint8_t* buffer, unsigned start_position) { #endif -void video_task(void) { +void video_send_frame(void) { static unsigned start_ms = 0; static unsigned already_sent = 0; @@ -213,6 +225,21 @@ void video_task(void) { #endif } + +void video_task(void* param) { + (void) param; + + while(1) { + video_send_frame(); + + #if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(interval_ms / portTICK_PERIOD_MS); + #else + return; + #endif + } +} + void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { (void) ctl_idx; (void) stm_idx; @@ -231,16 +258,92 @@ int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, } //--------------------------------------------------------------------+ -// BLINKING TASK +// Blinking Task //--------------------------------------------------------------------+ -void led_blinking_task(void) { +void led_blinking_task(void* param) { + (void) param; static uint32_t start_ms = 0; static bool led_state = false; - // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time - start_ms += blink_interval_ms; + while (1) { + #if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + #else + if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + #endif + + start_ms += blink_interval_ms; + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } +} + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS + +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4) + +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + #define USBD_STACK_SIZE 4096 + int main(void); + void app_main(void) { + main(); + } +#else + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) +#endif + +// static task +#if configSUPPORT_STATIC_ALLOCATION +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; + +StackType_t usb_device_stack[USBD_STACK_SIZE]; +StaticTask_t usb_device_taskdef; + +StackType_t video_stack[VIDEO_STACK_SIZE]; +StaticTask_t video_taskdef; +#endif + +// USB Device Driver task +// This top level thread process all usb events and invoke callbacks +void usb_device_task(void *param) { + (void) param; + + // init device stack on configured roothub port + // This should be called after scheduler/kernel is started. + // Otherwise, it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tud_init(BOARD_TUD_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } - board_led_write(led_state); - led_state = 1 - led_state; // toggle + // RTOS forever loop + while (1) { + // put this thread to waiting state until there is new events + tud_task(); + } } + +void freertos_init_task(void) { + #if configSUPPORT_STATIC_ALLOCATION + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); + xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); + xTaskCreateStatic(video_task, "cdc", VIDEO_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, video_stack, &video_taskdef); + #else + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(video_task, "video", VIDEO_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL); + #endif + + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 + #if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + vTaskStartScheduler(); + #endif +} +#endif diff --git a/examples/device/video_capture/src/tusb_config.h b/examples/device/video_capture/src/tusb_config.h index d563c6f5c..bdfc37d87 100644 --- a/examples/device/video_capture/src/tusb_config.h +++ b/examples/device/video_capture/src/tusb_config.h @@ -57,6 +57,11 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + #ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 #endif @@ -103,6 +108,9 @@ // use bulk endpoint for streaming interface #define CFG_TUD_VIDEO_STREAMING_BULK 1 +//#define CFG_EXAMPLE_VIDEO_READONLY +//#define CFG_EXAMPLE_VIDEO_DISABLE_MJPEG + #ifdef __cplusplus } #endif diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c index 17e11229d..f308c75a7 100644 --- a/examples/device/video_capture/src/usb_descriptors.c +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -364,7 +364,22 @@ const uvc_cfg_desc_t desc_fs_configuration = { }; #if TUD_OPT_HIGH_SPEED -uvc_cfg_desc_t desc_hs_configuration = desc_fs_configuration; +uvc_cfg_desc_t desc_hs_configuration; + +static uint8_t * get_hs_configuration_desc(void) { + static bool init = false; + + if (!init) { + desc_hs_configuration = desc_fs_configuration; + // change endpoint bulk size to 512 if bulk streaming + if (CFG_TUD_VIDEO_STREAMING_BULK) { + desc_hs_configuration.video_streaming.ep.wMaxPacketSize = 512; + } + } + init = true; + + return (uint8_t *) &desc_hs_configuration; +} // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed tusb_desc_device_qualifier_t const desc_device_qualifier = { @@ -395,7 +410,11 @@ uint8_t const* tud_descriptor_device_qualifier_cb(void) { uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void) index; // for multiple configurations // if link speed is high return fullspeed config, and vice versa - return (uint8_t const*) ((tud_speed_get() == TUSB_SPEED_HIGH) ? &desc_fs_configuration : &desc_hs_configuration); + if (tud_speed_get() == TUSB_SPEED_HIGH) { + return (uint8_t const*) &desc_fs_configuration; + } else { + return get_hs_configuration_desc(); + } } #endif // highspeed @@ -408,11 +427,7 @@ uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { #if TUD_OPT_HIGH_SPEED // Although we are highspeed, host may be fullspeed. if (tud_speed_get() == TUSB_SPEED_HIGH) { - // change endpoint bulk size to 512 if bulk streaming - if (CFG_TUD_VIDEO_STREAMING_BULK) { - desc_hs_configuration.video_streaming.ep.wMaxPacketSize = 512; - } - return (uint8_t const*) &desc_hs_configuration; + return get_hs_configuration_desc(); } else #endif { diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 404509a28..0c8a35924 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -33,9 +33,26 @@ extern "C" { #include #include - #include "tusb.h" +#if CFG_TUSB_OS == OPT_OS_FREERTOS +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // ESP-IDF need "freertos/" prefix in include path. + // CFG_TUSB_OS_INC_PATH should be defined accordingly. + #include "freertos/FreeRTOS.h" + #include "freertos/semphr.h" + #include "freertos/queue.h" + #include "freertos/task.h" + #include "freertos/timers.h" +#else + #include "FreeRTOS.h" + #include "semphr.h" + #include "queue.h" + #include "task.h" + #include "timers.h" +#endif +#endif + // Define the default baudrate #ifndef CFG_BOARD_UART_BAUDRATE #define CFG_BOARD_UART_BAUDRATE 115200 ///< Default baud rate diff --git a/src/class/video/video.h b/src/class/video/video.h index bed8eeecf..fb0d0af1d 100644 --- a/src/class/video/video.h +++ b/src/class/video/video.h @@ -398,7 +398,7 @@ typedef tusb_desc_video_frame_uncompressed_3int_t tusb_desc_video_frame_uncompre TU_VERIFY_STATIC(sizeof(tusb_desc_video_frame_uncompressed_continuous_t) == 38, "size is not correct"); //------------- MJPEG -------------// -// MJPEG payload specs: 3.1.1 formatt descriptor +// MJPEG payload specs: 3.1.1 format descriptor typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; -- cgit v1.3.1 From 6c4a5292a6a59dec1b7f37be42725ea85205f3c9 Mon Sep 17 00:00:00 2001 From: Jerry Palacios Date: Wed, 7 Feb 2024 17:03:13 -0600 Subject: Back to original --- .github/workflows/build_aarch64.yml | 2 +- .github/workflows/build_arm.yml | 2 +- .github/workflows/build_esp.yml | 6 +- .github/workflows/build_iar.yml | 2 + .github/workflows/build_msp430.yml | 2 +- .github/workflows/build_renesas.yml | 2 +- .github/workflows/build_riscv.yml | 2 +- .github/workflows/build_win_mac.yml | 2 +- .github/workflows/cmake_arm.yml | 4 +- .github/workflows/pre-commit.yml | 2 +- examples/device/video_capture/src/CMakeLists.txt | 4 + examples/device/video_capture/src/images.h | 3 + examples/device/video_capture/src/main.c | 228 +++-- examples/device/video_capture/src/tusb_config.h | 12 +- .../device/video_capture/src/usb_descriptors.c | 450 +++++++--- .../device/video_capture/src/usb_descriptors.h | 87 +- examples/host/cdc_msc_hid/src/cdc_app.c | 76 +- examples/host/cdc_msc_hid/src/tusb_config.h | 1 + .../host/cdc_msc_hid_freertos/src/tusb_config.h | 1 + hw/bsp/board_api.h | 19 +- hw/bsp/espressif/boards/family.c | 30 +- hw/bsp/espressif/components/led_strip/CHANGELOG.md | 38 + .../espressif/components/led_strip/CMakeLists.txt | 27 +- hw/bsp/espressif/components/led_strip/LICENSE | 202 +++++ hw/bsp/espressif/components/led_strip/README.md | 97 +++ hw/bsp/espressif/components/led_strip/api.md | 454 ++++++++++ .../examples/led_strip_rmt_ws2812/CMakeLists.txt | 9 + .../examples/led_strip_rmt_ws2812/README.md | 31 + .../led_strip_rmt_ws2812/dependencies.lock | 15 + .../led_strip_rmt_ws2812/main/CMakeLists.txt | 2 + .../led_strip_rmt_ws2812/main/idf_component.yml | 5 + .../main/led_strip_rmt_ws2812_main.c | 75 ++ .../components/led_strip/idf_component.yml | 5 + .../components/led_strip/include/led_strip.h | 191 ++--- .../components/led_strip/include/led_strip_rmt.h | 53 ++ .../components/led_strip/include/led_strip_spi.h | 46 ++ .../components/led_strip/include/led_strip_types.h | 54 ++ .../led_strip/interface/led_strip_interface.h | 95 +++ .../components/led_strip/src/led_strip_api.c | 94 +++ .../components/led_strip/src/led_strip_rmt_dev.c | 164 ++++ .../led_strip/src/led_strip_rmt_dev_idf4.c | 194 +++++ .../led_strip/src/led_strip_rmt_encoder.c | 146 ++++ .../led_strip/src/led_strip_rmt_encoder.h | 38 + .../led_strip/src/led_strip_rmt_ws2812.c | 171 ---- .../components/led_strip/src/led_strip_spi_dev.c | 209 +++++ hw/bsp/family_support.cmake | 1 - hw/bsp/mcx/boards/bunny-brain/board.cmake | 21 - hw/bsp/mcx/boards/bunny-brain/board.h | 66 -- hw/bsp/mcx/boards/bunny-brain/board.mk | 11 - hw/bsp/mcx/boards/bunny-brain/clock_config.c | 338 -------- hw/bsp/mcx/boards/bunny-brain/clock_config.h | 177 ---- hw/bsp/mcx/boards/bunny-brain/pin_mux.c | 141 ---- hw/bsp/mcx/boards/bunny-brain/pin_mux.h | 51 -- hw/bsp/mcx/boards/frdm-mcxn947/board.cmake | 21 - hw/bsp/mcx/boards/frdm-mcxn947/board.h | 66 -- hw/bsp/mcx/boards/frdm-mcxn947/board.mk | 11 - hw/bsp/mcx/boards/frdm-mcxn947/clock_config.c | 338 -------- hw/bsp/mcx/boards/frdm-mcxn947/clock_config.h | 177 ---- hw/bsp/mcx/boards/frdm-mcxn947/pin_mux.c | 143 ---- hw/bsp/mcx/boards/frdm-mcxn947/pin_mux.h | 51 -- src/class/audio/audio_device.c | 2 +- src/class/cdc/cdc.h | 20 +- src/class/cdc/cdc_host.c | 916 ++++++++++++++++----- src/class/cdc/cdc_host.h | 13 +- src/class/cdc/serial/ch34x.h | 84 ++ src/class/hid/hid_host.c | 6 +- src/class/vendor/vendor_device.c | 8 +- src/class/video/video.h | 236 ++++-- src/class/video/video_device.c | 26 +- src/common/tusb_common.h | 1 + src/common/tusb_types.h | 157 ++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 4 +- src/tusb_option.h | 17 + test/hil/hil_test.py | 11 +- 74 files changed, 3839 insertions(+), 2627 deletions(-) create mode 100644 examples/device/video_capture/src/CMakeLists.txt create mode 100644 hw/bsp/espressif/components/led_strip/CHANGELOG.md create mode 100644 hw/bsp/espressif/components/led_strip/LICENSE create mode 100644 hw/bsp/espressif/components/led_strip/README.md create mode 100644 hw/bsp/espressif/components/led_strip/api.md create mode 100644 hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/CMakeLists.txt create mode 100644 hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/README.md create mode 100644 hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/dependencies.lock create mode 100644 hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/CMakeLists.txt create mode 100644 hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/idf_component.yml create mode 100644 hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/led_strip_rmt_ws2812_main.c create mode 100644 hw/bsp/espressif/components/led_strip/idf_component.yml create mode 100644 hw/bsp/espressif/components/led_strip/include/led_strip_rmt.h create mode 100644 hw/bsp/espressif/components/led_strip/include/led_strip_spi.h create mode 100644 hw/bsp/espressif/components/led_strip/include/led_strip_types.h create mode 100644 hw/bsp/espressif/components/led_strip/interface/led_strip_interface.h create mode 100644 hw/bsp/espressif/components/led_strip/src/led_strip_api.c create mode 100644 hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev.c create mode 100644 hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev_idf4.c create mode 100644 hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.c create mode 100644 hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.h delete mode 100644 hw/bsp/espressif/components/led_strip/src/led_strip_rmt_ws2812.c create mode 100644 hw/bsp/espressif/components/led_strip/src/led_strip_spi_dev.c delete mode 100644 hw/bsp/mcx/boards/bunny-brain/board.cmake delete mode 100644 hw/bsp/mcx/boards/bunny-brain/board.h delete mode 100644 hw/bsp/mcx/boards/bunny-brain/board.mk delete mode 100644 hw/bsp/mcx/boards/bunny-brain/clock_config.c delete mode 100644 hw/bsp/mcx/boards/bunny-brain/clock_config.h delete mode 100644 hw/bsp/mcx/boards/bunny-brain/pin_mux.c delete mode 100644 hw/bsp/mcx/boards/bunny-brain/pin_mux.h delete mode 100644 hw/bsp/mcx/boards/frdm-mcxn947/board.cmake delete mode 100644 hw/bsp/mcx/boards/frdm-mcxn947/board.h delete mode 100644 hw/bsp/mcx/boards/frdm-mcxn947/board.mk delete mode 100644 hw/bsp/mcx/boards/frdm-mcxn947/clock_config.c delete mode 100644 hw/bsp/mcx/boards/frdm-mcxn947/clock_config.h delete mode 100644 hw/bsp/mcx/boards/frdm-mcxn947/pin_mux.c delete mode 100644 hw/bsp/mcx/boards/frdm-mcxn947/pin_mux.h create mode 100644 src/class/cdc/serial/ch34x.h (limited to 'examples') diff --git a/.github/workflows/build_aarch64.yml b/.github/workflows/build_aarch64.yml index 40fc8d63a..e5dbf9494 100644 --- a/.github/workflows/build_aarch64.yml +++ b/.github/workflows/build_aarch64.yml @@ -36,7 +36,7 @@ jobs: - 'broadcom_64bit' steps: - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml index 4127db5bf..9f3270c91 100644 --- a/.github/workflows/build_arm.yml +++ b/.github/workflows/build_arm.yml @@ -46,7 +46,7 @@ jobs: - 'tm4c123 xmc4000' steps: - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/build_esp.yml b/.github/workflows/build_esp.yml index 33caa0edb..8fbdb31ff 100644 --- a/.github/workflows/build_esp.yml +++ b/.github/workflows/build_esp.yml @@ -8,6 +8,7 @@ on: - 'examples/**' - 'lib/**' - 'hw/**' + - 'test/hil/**' - '.github/workflows/build_esp.yml' pull_request: branches: [ master ] @@ -16,6 +17,7 @@ on: - 'examples/**' - 'lib/**' - 'hw/**' + - 'test/hil/**' - '.github/workflows/build_esp.yml' concurrency: @@ -35,7 +37,7 @@ jobs: - 'espressif_s3_devkitc' steps: - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' @@ -46,7 +48,7 @@ jobs: uses: actions/checkout@v4 - name: Build - run: docker run --rm -v $PWD:/project -w /project espressif/idf:latest python3 tools/build_esp32.py ${{ matrix.board }} + run: docker run --rm -v $PWD:/project -w /project espressif/idf:v5.1.1 python3 tools/build_esp32.py ${{ matrix.board }} - name: Upload Artifacts for Hardware Testing if: matrix.board == 'espressif_s3_devkitc' && github.repository_owner == 'hathach' diff --git a/.github/workflows/build_iar.yml b/.github/workflows/build_iar.yml index 9f2cc0351..a0a022ecc 100644 --- a/.github/workflows/build_iar.yml +++ b/.github/workflows/build_iar.yml @@ -9,6 +9,7 @@ on: - 'lib/**' - 'hw/**' - 'tools/get_deps.py' + - 'test/hil/**' - '.github/workflows/build_iar.yml' pull_request: branches: [ master ] @@ -18,6 +19,7 @@ on: - 'lib/**' - 'hw/**' - 'tools/get_deps.py' + - 'test/hil/**' - '.github/workflows/build_iar.yml' concurrency: diff --git a/.github/workflows/build_msp430.yml b/.github/workflows/build_msp430.yml index 296dbb766..f913df913 100644 --- a/.github/workflows/build_msp430.yml +++ b/.github/workflows/build_msp430.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/build_renesas.yml b/.github/workflows/build_renesas.yml index 017a29eee..ec06c9426 100644 --- a/.github/workflows/build_renesas.yml +++ b/.github/workflows/build_renesas.yml @@ -35,7 +35,7 @@ jobs: - 'rx' steps: - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/build_riscv.yml b/.github/workflows/build_riscv.yml index e030bb77f..e891a3a51 100644 --- a/.github/workflows/build_riscv.yml +++ b/.github/workflows/build_riscv.yml @@ -37,7 +37,7 @@ jobs: - 'gd32vf103' steps: - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/build_win_mac.yml b/.github/workflows/build_win_mac.yml index 7fa1a6943..b33b5b593 100644 --- a/.github/workflows/build_win_mac.yml +++ b/.github/workflows/build_win_mac.yml @@ -35,7 +35,7 @@ jobs: steps: - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index 8b87fef21..f97645ad1 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -8,6 +8,7 @@ on: - 'examples/**' - 'lib/**' - 'hw/**' + - 'test/hil/**' - 'tools/get_deps.py' - '.github/workflows/cmake_arm.yml' pull_request: @@ -17,6 +18,7 @@ on: - 'examples/**' - 'lib/**' - 'hw/**' + - 'test/hil/**' - 'tools/get_deps.py' - '.github/workflows/cmake_arm.yml' @@ -57,7 +59,7 @@ jobs: - 'stm32u5' steps: - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 2e9ae9264..e36259daa 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/examples/device/video_capture/src/CMakeLists.txt b/examples/device/video_capture/src/CMakeLists.txt new file mode 100644 index 000000000..cef2b46ee --- /dev/null +++ b/examples/device/video_capture/src/CMakeLists.txt @@ -0,0 +1,4 @@ +# This file is for ESP-IDF only +idf_component_register(SRCS "main.c" "usb_descriptors.c" + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/device/video_capture/src/images.h b/examples/device/video_capture/src/images.h index 784e7754c..ac372cb16 100644 --- a/examples/device/video_capture/src/images.h +++ b/examples/device/video_capture/src/images.h @@ -1,4 +1,5 @@ #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) +// uncopmressed frame static const unsigned char frame_buffer[128 * (96 + 1) * 2] = { /* 0 */ 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, @@ -1650,8 +1651,10 @@ static const unsigned char frame_buffer[128 * (96 + 1) * 2] = { 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, }; + #else +// mpeg compressed data (not CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) #define color_bar_0_jpg_len 511 #define color_bar_1_jpg_len 512 #define color_bar_2_jpg_len 511 diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c index 711d4710a..2a2b0961f 100644 --- a/examples/device/video_capture/src/main.c +++ b/examples/device/video_capture/src/main.c @@ -40,7 +40,7 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -48,14 +48,25 @@ enum { static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; -void led_blinking_task(void); -void video_task(void); +void led_blinking_task(void* param); +void usb_device_task(void *param); +void video_task(void* param); -/*------------- MAIN -------------*/ -int main(void) -{ +#if CFG_TUSB_OS == OPT_OS_FREERTOS +void freertos_init_task(void); +#endif + + +//--------------------------------------------------------------------+ +// Main +//--------------------------------------------------------------------+ +int main(void) { board_init(); + // If using FreeRTOS: create blinky, tinyusb device, video task +#if CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init_task(); +#else // init device stack on configured roothub port tud_init(BOARD_TUD_RHPORT); @@ -63,13 +74,12 @@ int main(void) board_init_after_tusb(); } - while (1) - { + while (1) { tud_task(); // tinyusb device task - led_blinking_task(); - - video_task(); + led_blinking_task(NULL); + video_task(NULL); } +#endif } //--------------------------------------------------------------------+ @@ -77,33 +87,28 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } - //--------------------------------------------------------------------+ // USB Video //--------------------------------------------------------------------+ @@ -111,11 +116,12 @@ static unsigned frame_num = 0; static unsigned tx_busy = 0; static unsigned interval_ms = 1000 / FRAME_RATE; -/* YUY2 frame buffer */ #ifdef CFG_EXAMPLE_VIDEO_READONLY +// For mcus that does not have enough SRAM for frame buffer, we use fixed frame data. +// To further reduce the size, we use MJPEG format instead of YUY2. #include "images.h" -# if !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) +#if !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) static struct { uint32_t size; uint8_t const *buffer; @@ -129,29 +135,30 @@ static struct { {color_bar_6_jpg_len, color_bar_6_jpg}, {color_bar_7_jpg_len, color_bar_7_jpg}, }; -# endif +#endif #else + +// YUY2 frame buffer static uint8_t frame_buffer[FRAME_WIDTH * FRAME_HEIGHT * 16 / 8]; -static void fill_color_bar(uint8_t *buffer, unsigned start_position) -{ - /* EBU color bars - * See also https://stackoverflow.com/questions/6939422 */ + +static void fill_color_bar(uint8_t* buffer, unsigned start_position) { + /* EBU color bars: https://stackoverflow.com/questions/6939422 */ static uint8_t const bar_color[8][4] = { - /* Y, U, Y, V */ - { 235, 128, 235, 128}, /* 100% White */ - { 219, 16, 219, 138}, /* Yellow */ - { 188, 154, 188, 16}, /* Cyan */ - { 173, 42, 173, 26}, /* Green */ - { 78, 214, 78, 230}, /* Magenta */ - { 63, 102, 63, 240}, /* Red */ - { 32, 240, 32, 118}, /* Blue */ - { 16, 128, 16, 128}, /* Black */ + /* Y, U, Y, V */ + { 235, 128, 235, 128}, /* 100% White */ + { 219, 16, 219, 138}, /* Yellow */ + { 188, 154, 188, 16}, /* Cyan */ + { 173, 42, 173, 26}, /* Green */ + { 78, 214, 78, 230}, /* Magenta */ + { 63, 102, 63, 240}, /* Red */ + { 32, 240, 32, 118}, /* Blue */ + { 16, 128, 16, 128}, /* Black */ }; - uint8_t *p; + uint8_t* p; /* Generate the 1st line */ - uint8_t *end = &buffer[FRAME_WIDTH * 2]; + uint8_t* end = &buffer[FRAME_WIDTH * 2]; unsigned idx = (FRAME_WIDTH / 2 - 1) - (start_position % (FRAME_WIDTH / 2)); p = &buffer[idx * 4]; for (unsigned i = 0; i < 8; ++i) { @@ -163,6 +170,7 @@ static void fill_color_bar(uint8_t *buffer, unsigned start_position) } } } + /* Duplicate the 1st line to the others */ p = &buffer[FRAME_WIDTH * 2]; for (unsigned i = 1; i < FRAME_HEIGHT; ++i) { @@ -170,32 +178,33 @@ static void fill_color_bar(uint8_t *buffer, unsigned start_position) p += FRAME_WIDTH * 2; } } + #endif -void video_task(void) -{ +void video_send_frame(void) { static unsigned start_ms = 0; static unsigned already_sent = 0; if (!tud_video_n_streaming(0, 0)) { - already_sent = 0; - frame_num = 0; + already_sent = 0; + frame_num = 0; return; } if (!already_sent) { already_sent = 1; + tx_busy = 1; start_ms = board_millis(); #ifdef CFG_EXAMPLE_VIDEO_READONLY -# if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) + #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)&frame_buffer[(frame_num % (FRAME_WIDTH / 2)) * 4], FRAME_WIDTH * FRAME_HEIGHT * 16/8); -# else + #else tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)frames[frame_num % 8].buffer, frames[frame_num % 8].size); -# endif + #endif #else fill_color_bar(frame_buffer, frame_num); - tud_video_n_frame_xfer(0, 0, (void*)frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16/8); + tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); #endif } @@ -203,49 +212,140 @@ void video_task(void) if (cur - start_ms < interval_ms) return; // not enough time if (tx_busy) return; start_ms += interval_ms; + tx_busy = 1; #ifdef CFG_EXAMPLE_VIDEO_READONLY -# if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) + #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)&frame_buffer[(frame_num % (FRAME_WIDTH / 2)) * 4], FRAME_WIDTH * FRAME_HEIGHT * 16/8); -# else + #else tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)frames[frame_num % 8].buffer, frames[frame_num % 8].size); -# endif + #endif #else fill_color_bar(frame_buffer, frame_num); - tud_video_n_frame_xfer(0, 0, (void*)frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16/8); + tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); #endif } -void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) -{ - (void)ctl_idx; (void)stm_idx; + +void video_task(void* param) { + (void) param; + + while(1) { + video_send_frame(); + + #if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(interval_ms / portTICK_PERIOD_MS); + #else + return; + #endif + } +} + +void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { + (void) ctl_idx; + (void) stm_idx; tx_busy = 0; /* flip buffer */ ++frame_num; } int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, - video_probe_and_commit_control_t const *parameters) -{ - (void)ctl_idx; (void)stm_idx; + video_probe_and_commit_control_t const* parameters) { + (void) ctl_idx; + (void) stm_idx; /* convert unit to ms from 100 ns */ interval_ms = parameters->dwFrameInterval / 10000; return VIDEO_ERROR_NONE; } //--------------------------------------------------------------------+ -// BLINKING TASK +// Blinking Task //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void* param) { + (void) param; static uint32_t start_ms = 0; static bool led_state = false; - // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time - start_ms += blink_interval_ms; + while (1) { + #if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + #else + if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + #endif + + start_ms += blink_interval_ms; + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } +} + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS + +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4) + +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + #define USBD_STACK_SIZE 4096 + int main(void); + void app_main(void) { + main(); + } +#else + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) +#endif + +// static task +#if configSUPPORT_STATIC_ALLOCATION +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; + +StackType_t usb_device_stack[USBD_STACK_SIZE]; +StaticTask_t usb_device_taskdef; + +StackType_t video_stack[VIDEO_STACK_SIZE]; +StaticTask_t video_taskdef; +#endif + +// USB Device Driver task +// This top level thread process all usb events and invoke callbacks +void usb_device_task(void *param) { + (void) param; + + // init device stack on configured roothub port + // This should be called after scheduler/kernel is started. + // Otherwise, it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tud_init(BOARD_TUD_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } + + // RTOS forever loop + while (1) { + // put this thread to waiting state until there is new events + tud_task(); + } +} - board_led_write(led_state); - led_state = 1 - led_state; // toggle +void freertos_init_task(void) { + #if configSUPPORT_STATIC_ALLOCATION + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); + xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); + xTaskCreateStatic(video_task, "cdc", VIDEO_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, video_stack, &video_taskdef); + #else + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(video_task, "video", VIDEO_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL); + #endif + + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 + #if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + vTaskStartScheduler(); + #endif } +#endif diff --git a/examples/device/video_capture/src/tusb_config.h b/examples/device/video_capture/src/tusb_config.h index 274bf2b9c..bdfc37d87 100644 --- a/examples/device/video_capture/src/tusb_config.h +++ b/examples/device/video_capture/src/tusb_config.h @@ -57,6 +57,11 @@ #define CFG_TUSB_OS OPT_OS_NONE #endif +// Espressif IDF requires "freertos/" prefix in include path +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + #ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 #endif @@ -97,11 +102,14 @@ // The number of video streaming interfaces #define CFG_TUD_VIDEO_STREAMING 1 -// video streaming endpoint size +// video streaming endpoint buffer size #define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 256 // use bulk endpoint for streaming interface -#define CFG_TUD_VIDEO_STREAMING_BULK 0 +#define CFG_TUD_VIDEO_STREAMING_BULK 1 + +//#define CFG_EXAMPLE_VIDEO_READONLY +//#define CFG_EXAMPLE_VIDEO_DISABLE_MJPEG #ifdef __cplusplus } diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c index 49919fc58..f308c75a7 100644 --- a/examples/device/video_capture/src/usb_descriptors.c +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -40,11 +40,30 @@ #define USB_VID 0xCafe #define USB_BCD 0x0200 +// String Descriptor Index +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, + STRID_UVC_CONTROL, + STRID_UVC_STREAMING, +}; + +// array of pointer to string descriptors +char const* string_desc_arr[] = { + (const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "TinyUSB UVC Control", // 4: UVC Interface + "TinyUSB UVC Streaming", // 5: UVC Interface +}; + //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ +tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -61,201 +80,374 @@ tusb_desc_device_t const desc_device = .idProduct = USB_PID, .bcdDevice = 0x0100, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, + .iManufacturer = STRID_MANUFACTURER, + .iProduct = STRID_PRODUCT, + .iSerialNumber = STRID_SERIAL, .bNumConfigurations = 0x01 }; // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ - return (uint8_t const *) &desc_device; +uint8_t const* tud_descriptor_device_cb(void) { + return (uint8_t const*) &desc_device; } //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ -#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_MJPEG_BULK_LEN) -# else -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_MJPEG_LEN) -# endif -#else -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_UNCOMPR_BULK_LEN) -# else -# define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN) -# endif -#endif +/* Time stamp base clock. It is a deprecated parameter. */ +#define UVC_CLOCK_FREQUENCY 27000000 + +/* video capture path */ +#define UVC_ENTITY_CAP_INPUT_TERMINAL 0x01 +#define UVC_ENTITY_CAP_OUTPUT_TERMINAL 0x02 + +enum { + ITF_NUM_VIDEO_CONTROL, + ITF_NUM_VIDEO_STREAMING, + ITF_NUM_TOTAL +}; +// Select appropriate endpoint number #if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ... -#if 1 == CFG_TUD_VIDEO_STREAMING_BULK - #define EPNUM_VIDEO_IN 0x82 -#else - #define EPNUM_VIDEO_IN 0x83 -#endif - + #define EPNUM_VIDEO_IN (CFG_TUD_VIDEO_STREAMING_BULK ? 0x82 : 0x83) #elif TU_CHECK_MCU(OPT_MCU_NRF5X) // nRF5x ISO can only be endpoint 8 - #define EPNUM_VIDEO_IN 0x88 - + #define EPNUM_VIDEO_IN (CFG_TUD_VIDEO_STREAMING_BULK ? 0x81 : 0x88) #else #define EPNUM_VIDEO_IN 0x81 +#endif +#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) + #define USE_MJPEG 1 +#else + #define USE_MJPEG 0 #endif -uint8_t const desc_fs_configuration[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 500), +#define USE_ISO_STREAMING (!CFG_TUD_VIDEO_STREAMING_BULK) - // IAD for Video Control -#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK - TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - 64) -# else - TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -# endif +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_control_header_1itf_t header; + tusb_desc_video_control_camera_terminal_t camera_terminal; + tusb_desc_video_control_output_terminal_t output_terminal; +} uvc_control_desc_t; + +/* Windows support YUY2 and NV12 + * https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/usb-video-class-driver-overview */ + +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_streaming_input_header_1byte_t header; + +#if USE_MJPEG + tusb_desc_video_format_mjpeg_t format; + tusb_desc_video_frame_mjpeg_continuous_t frame; #else -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK - TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - 64) -# else - TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -# endif + tusb_desc_video_format_uncompressed_t format; + tusb_desc_video_frame_uncompressed_continuous_t frame; #endif -}; -#if TUD_OPT_HIGH_SPEED -// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration + tusb_desc_video_streaming_color_matching_t color; -uint8_t const desc_hs_configuration[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0, 500), +#if USE_ISO_STREAMING + // For ISO streaming, USB spec requires to alternate interface + tusb_desc_interface_t itf_alt; +#endif - // IAD for Video Control -#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK - TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - 512) -# else - TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -# endif + tusb_desc_endpoint_t ep; +} uvc_streaming_desc_t; + +typedef struct TU_ATTR_PACKED { + tusb_desc_configuration_t config; + tusb_desc_interface_assoc_t iad; + uvc_control_desc_t video_control; + uvc_streaming_desc_t video_streaming; +} uvc_cfg_desc_t; + +const uvc_cfg_desc_t desc_fs_configuration = { + .config = { + .bLength = sizeof(tusb_desc_configuration_t), + .bDescriptorType = TUSB_DESC_CONFIGURATION, + + .wTotalLength = sizeof(uvc_cfg_desc_t), + .bNumInterfaces = ITF_NUM_TOTAL, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = TU_BIT(7), + .bMaxPower = 100 / 2 + }, + .iad = { + .bLength = sizeof(tusb_desc_interface_assoc_t), + .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, + + .bFirstInterface = ITF_NUM_VIDEO_CONTROL, + .bInterfaceCount = 2, + .bFunctionClass = TUSB_CLASS_VIDEO, + .bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION, + .bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED, + .iFunction = 0 + }, + + .video_control = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_CONTROL, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_CONTROL + }, + .header = { + .bLength = sizeof(tusb_desc_video_control_header_1itf_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER, + + .bcdUVC = VIDEO_BCD_1_50, + .wTotalLength = sizeof(uvc_control_desc_t) - sizeof(tusb_desc_interface_t), // CS VC descriptors only + .dwClockFrequency = UVC_CLOCK_FREQUENCY, + .bInCollection = 1, + .baInterfaceNr = { ITF_NUM_VIDEO_STREAMING } + }, + .camera_terminal = { + .bLength = sizeof(tusb_desc_video_control_camera_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .wTerminalType = VIDEO_ITT_CAMERA, + .bAssocTerminal = 0, + .iTerminal = 0, + .wObjectiveFocalLengthMin = 0, + .wObjectiveFocalLengthMax = 0, + .wOcularFocalLength = 0, + .bControlSize = 3, + .bmControls = { 0, 0, 0 } + }, + .output_terminal = { + .bLength = sizeof(tusb_desc_video_control_output_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .wTerminalType = VIDEO_TT_STREAMING, + .bAssocTerminal = 0, + .bSourceID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .iTerminal = 0 + } + }, + + .video_streaming = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING, + .bAlternateSetting = 0, + .bNumEndpoints = CFG_TUD_VIDEO_STREAMING_BULK, // bulk 1, iso 0 + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING + }, + .header = { + .bLength = sizeof(tusb_desc_video_streaming_input_header_1byte_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, + + .bNumFormats = 1, + .wTotalLength = sizeof(uvc_streaming_desc_t) - sizeof(tusb_desc_interface_t) + - sizeof(tusb_desc_endpoint_t) - (USE_ISO_STREAMING ? sizeof(tusb_desc_interface_t) : 0) , // CS VS descriptors only + .bEndpointAddress = EPNUM_VIDEO_IN, + .bmInfo = 0, + .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .bStillCaptureMethod = 0, + .bTriggerSupport = 0, + .bTriggerUsage = 0, + .bControlSize = 1, + .bmaControls = { 0 } + }, + .format = { +#if USE_MJPEG + .bLength = sizeof(tusb_desc_video_format_mjpeg_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_MJPEG, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .bmFlags = 0, +#else + .bLength = sizeof(tusb_desc_video_format_uncompressed_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .guidFormat = { TUD_VIDEO_GUID_YUY2 }, + .bBitsPerPixel = 16, +#endif + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, + .bAspectRatioY = 0, + .bmInterlaceFlags = 0, + .bCopyProtect = 0 + }, + .frame = { +#if USE_MJPEG + .bLength = sizeof(tusb_desc_video_frame_mjpeg_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_MJPEG, #else -# if 1 == CFG_TUD_VIDEO_STREAMING_BULK - TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - 512) -# else - TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(4, EPNUM_VIDEO_IN, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_RATE, - CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE) -# endif + .bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, #endif + .bFrameIndex = 1, // 1-based index + .bmCapabilities = 0, + .wWidth = FRAME_WIDTH, + .wHeight = FRAME_HEIGHT, + .dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1, + .dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE, + .dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8, + .dwDefaultFrameInterval = 10000000 / FRAME_RATE, + .bFrameIntervalType = 0, // continuous + .dwFrameInterval = { + 10000000 / FRAME_RATE, // min + 10000000, // max + 10000000 / FRAME_RATE // step + } + }, + .color = { + .bLength = sizeof(tusb_desc_video_streaming_color_matching_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT, + + .bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709, + .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, + .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M + }, + +#if USE_ISO_STREAMING + .itf_alt = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING, + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING + }, +#endif + + .ep = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = EPNUM_VIDEO_IN, + .bmAttributes = { + .xfer = CFG_TUD_VIDEO_STREAMING_BULK ? TUSB_XFER_BULK : TUSB_XFER_ISOCHRONOUS, + .sync = CFG_TUD_VIDEO_STREAMING_BULK ? 0 : 1 // asynchronous + }, + .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, + .bInterval = 1 + } + } }; +#if TUD_OPT_HIGH_SPEED +uvc_cfg_desc_t desc_hs_configuration; + +static uint8_t * get_hs_configuration_desc(void) { + static bool init = false; + + if (!init) { + desc_hs_configuration = desc_fs_configuration; + // change endpoint bulk size to 512 if bulk streaming + if (CFG_TUD_VIDEO_STREAMING_BULK) { + desc_hs_configuration.video_streaming.ep.wMaxPacketSize = 512; + } + } + init = true; + + return (uint8_t *) &desc_hs_configuration; +} + // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = USB_BCD, - - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .bNumConfigurations = 0x01, - .bReserved = 0x00 +tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 }; // Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. // device_qualifier descriptor describes information about a high-speed capable device that would // change if the device were operating at the other speed. If not highspeed capable stall this request. -uint8_t const* tud_descriptor_device_qualifier_cb(void) -{ +uint8_t const* tud_descriptor_device_qualifier_cb(void) { return (uint8_t const*) &desc_device_qualifier; } // Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete // Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa -uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) -{ +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - // if link speed is high return fullspeed config, and vice versa - return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration; + if (tud_speed_get() == TUSB_SPEED_HIGH) { + return (uint8_t const*) &desc_fs_configuration; + } else { + return get_hs_configuration_desc(); + } } - #endif // highspeed // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ +uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations #if TUD_OPT_HIGH_SPEED // Although we are highspeed, host may be fullspeed. - return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; -#else - return desc_fs_configuration; + if (tud_speed_get() == TUSB_SPEED_HIGH) { + return get_hs_configuration_desc(); + } else #endif + { + return (uint8_t const*) &desc_fs_configuration; + } } //--------------------------------------------------------------------+ // String Descriptors //--------------------------------------------------------------------+ -// String Descriptor Index -enum { - STRID_LANGID = 0, - STRID_MANUFACTURER, - STRID_PRODUCT, - STRID_SERIAL, -}; - -// array of pointer to string descriptors -char const *string_desc_arr[] = -{ - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - NULL, // 3: Serials will use unique ID if possible - "TinyUSB UVC", // 4: UVC Interface -}; - static uint16_t _desc_str[32 + 1]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void) langid; size_t chr_count; - switch ( index ) { + switch (index) { case STRID_LANGID: memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; @@ -269,17 +461,17 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (index >= sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) return NULL; - const char *str = string_desc_arr[index]; + const char* str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) chr_count = max_count; // Convert ASCII string into UTF-16 - for ( size_t i = 0; i < chr_count; i++ ) { + for (size_t i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; } break; diff --git a/examples/device/video_capture/src/usb_descriptors.h b/examples/device/video_capture/src/usb_descriptors.h index b924c8dbe..12d41b2f3 100644 --- a/examples/device/video_capture/src/usb_descriptors.h +++ b/examples/device/video_capture/src/usb_descriptors.h @@ -27,21 +27,11 @@ #ifndef _USB_DESCRIPTORS_H_ #define _USB_DESCRIPTORS_H_ -/* Time stamp base clock. It is a deprecated parameter. */ -#define UVC_CLOCK_FREQUENCY 27000000 -/* video capture path */ -#define UVC_ENTITY_CAP_INPUT_TERMINAL 0x01 -#define UVC_ENTITY_CAP_OUTPUT_TERMINAL 0x02 - #define FRAME_WIDTH 128 #define FRAME_HEIGHT 96 #define FRAME_RATE 10 -enum { - ITF_NUM_VIDEO_CONTROL, - ITF_NUM_VIDEO_STREAMING, - ITF_NUM_TOTAL -}; +// NOTE: descriptor template is not used but leave here as reference #define TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN (\ TUD_VIDEO_DESC_IAD_LEN\ @@ -126,23 +116,17 @@ enum { #define TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(_stridx, _epin, _width, _height, _fps, _epsize) \ TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ - TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 0, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ - /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ @@ -152,7 +136,7 @@ enum { /* Video stream frame format */ \ TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \ _width * _height * 16, _width * _height * 16 * _fps, \ - _width * _height * 16, \ + _width * _height * 16 / 8, \ (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ /* VS alt 1 */\ @@ -163,23 +147,17 @@ enum { #define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(_stridx, _epin, _width, _height, _fps, _epsize) \ TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ - TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 0, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ - /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ @@ -202,22 +180,17 @@ enum { TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 1, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ @@ -227,7 +200,7 @@ enum { /* Video stream frame format */ \ TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \ _width * _height * 16, _width * _height * 16 * _fps, \ - _width * _height * 16, \ + _width * _height * 16 / 8, \ (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1) @@ -235,23 +208,17 @@ enum { #define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(_stridx, _epin, _width, _height, _fps, _epsize) \ TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ /* Video control 0 */ \ - TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ - TUD_VIDEO_DESC_CS_VC( /* UVC 1.5*/ 0x0150, \ - /* wTotalLength - bLength */ \ - TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, \ - UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ - TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0,\ - /*wObjectiveFocalLengthMin*/0, /*wObjectiveFocalLengthMax*/0,\ - /*wObjectiveFocalLength*/0, /*bmControls*/0), \ - TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ + TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, UVC_ENTITY_CAP_INPUT_TERMINAL, 0), \ /* Video stream alt. 0 */ \ TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 1, _stridx), \ /* Video stream header for without still image capture */ \ TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ - /*wTotalLength - bLength */\ - TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\ - + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\ - + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ /*bmaControls(1)*/0), \ diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index a1b26e49c..e275e7943 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -27,20 +27,11 @@ #include "tusb.h" #include "bsp/board_api.h" -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - - -//------------- IMPLEMENTATION -------------// - -size_t get_console_inputs(uint8_t* buf, size_t bufsize) -{ +size_t get_console_inputs(uint8_t* buf, size_t bufsize) { size_t count = 0; - while (count < bufsize) - { + while (count < bufsize) { int ch = board_getchar(); - if ( ch <= 0 ) break; + if (ch <= 0) break; buf[count] = (uint8_t) ch; count++; @@ -49,22 +40,18 @@ size_t get_console_inputs(uint8_t* buf, size_t bufsize) return count; } -void cdc_app_task(void) -{ - uint8_t buf[64+1]; // +1 for extra null character - uint32_t const bufsize = sizeof(buf)-1; +void cdc_app_task(void) { + uint8_t buf[64 + 1]; // +1 for extra null character + uint32_t const bufsize = sizeof(buf) - 1; uint32_t count = get_console_inputs(buf, bufsize); buf[count] = 0; // loop over all mounted interfaces - for(uint8_t idx=0; idx cdc interfaces - if (count) - { + if (count) { tuh_cdc_write(idx, buf, count); tuh_cdc_write_flush(idx); } @@ -72,11 +59,14 @@ void cdc_app_task(void) } } +//--------------------------------------------------------------------+ +// TinyUSB callbacks +//--------------------------------------------------------------------+ + // Invoked when received new data -void tuh_cdc_rx_cb(uint8_t idx) -{ - uint8_t buf[64+1]; // +1 for extra null character - uint32_t const bufsize = sizeof(buf)-1; +void tuh_cdc_rx_cb(uint8_t idx) { + uint8_t buf[64 + 1]; // +1 for extra null character + uint32_t const bufsize = sizeof(buf) - 1; // forward cdc interfaces -> console uint32_t count = tuh_cdc_read(idx, buf, bufsize); @@ -85,29 +75,35 @@ void tuh_cdc_rx_cb(uint8_t idx) printf((char*) buf); } -void tuh_cdc_mount_cb(uint8_t idx) -{ - tuh_itf_info_t itf_info = { 0 }; +// Invoked when a device with CDC interface is mounted +// idx is index of cdc interface in the internal pool. +void tuh_cdc_mount_cb(uint8_t idx) { + tuh_itf_info_t itf_info = {0}; tuh_cdc_itf_get_info(idx, &itf_info); - printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber); + printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, + itf_info.desc.bInterfaceNumber); #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - // CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration - // otherwise you need to call tuh_cdc_set_line_coding() first - cdc_line_coding_t line_coding = { 0 }; - if ( tuh_cdc_get_local_line_coding(idx, &line_coding) ) - { + // If CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined, line coding will be set by tinyusb stack + // while eneumerating new cdc device + cdc_line_coding_t line_coding = {0}; + if (tuh_cdc_get_local_line_coding(idx, &line_coding)) { printf(" Baudrate: %lu, Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); - printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity , line_coding.data_bits); + printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits); } +#else + // Set Line Coding upon mounted + cdc_line_coding_t new_line_coding = { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }; + tuh_cdc_set_line_coding(idx, &new_line_coding, NULL, 0); #endif } -void tuh_cdc_umount_cb(uint8_t idx) -{ - tuh_itf_info_t itf_info = { 0 }; +// Invoked when a device with CDC interface is unmounted +void tuh_cdc_umount_cb(uint8_t idx) { + tuh_itf_info_t itf_info = {0}; tuh_cdc_itf_get_info(idx, &itf_info); - printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber); + printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, + itf_info.desc.bInterfaceNumber); } diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 61abb85eb..76d59c316 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -105,6 +105,7 @@ #define CFG_TUH_CDC 1 // CDC ACM #define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API +#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index c661f47be..bb7c3388d 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -110,6 +110,7 @@ #define CFG_TUH_CDC 1 // CDC ACM #define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API +#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 404509a28..0c8a35924 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -33,9 +33,26 @@ extern "C" { #include #include - #include "tusb.h" +#if CFG_TUSB_OS == OPT_OS_FREERTOS +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // ESP-IDF need "freertos/" prefix in include path. + // CFG_TUSB_OS_INC_PATH should be defined accordingly. + #include "freertos/FreeRTOS.h" + #include "freertos/semphr.h" + #include "freertos/queue.h" + #include "freertos/task.h" + #include "freertos/timers.h" +#else + #include "FreeRTOS.h" + #include "semphr.h" + #include "queue.h" + #include "task.h" + #include "timers.h" +#endif +#endif + // Define the default baudrate #ifndef CFG_BOARD_UART_BAUDRATE #define CFG_BOARD_UART_BAUDRATE 115200 ///< Default baud rate diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index 325e9ab0f..5599d1504 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -33,7 +33,7 @@ #include "hal/usb_hal.h" #include "soc/usb_periph.h" -#include "driver/rmt.h" +#include "driver/gpio.h" #include "driver/uart.h" #if ESP_IDF_VERSION_MAJOR > 4 @@ -48,7 +48,7 @@ #ifdef NEOPIXEL_PIN #include "led_strip.h" -static led_strip_t* strip; +static led_strip_handle_t led_strip; #endif #if CFG_TUH_ENABLED && CFG_TUH_MAX3421 @@ -85,15 +85,23 @@ void board_init(void) { #endif // WS2812 Neopixel driver with RMT peripheral - rmt_config_t config = RMT_DEFAULT_CONFIG_TX(NEOPIXEL_PIN, RMT_CHANNEL_0); - config.clk_div = 2; // set counter clock to 40MHz + led_strip_rmt_config_t rmt_config = { + .clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption + .resolution_hz = 10 * 1000 * 1000, // RMT counter clock frequency, default = 10 Mhz + .flags.with_dma = false, // DMA feature is available on ESP target like ESP32-S3 + }; + + led_strip_config_t strip_config = { + .strip_gpio_num = NEOPIXEL_PIN, // The GPIO that connected to the LED strip's data line + .max_leds = 1, // The number of LEDs in the strip, + .led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip + .led_model = LED_MODEL_WS2812, // LED strip model + .flags.invert_out = false, // whether to invert the output signal + }; - rmt_config(&config); - rmt_driver_install(config.channel, 0, 0); + ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip)); - led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(1, (led_strip_dev_t) config.channel); - strip = led_strip_new_rmt_ws2812(&strip_config); - strip->clear(strip, 100); // off led + led_strip_clear(led_strip); // off #endif // Button @@ -158,8 +166,8 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) { void board_led_write(bool state) { #ifdef NEOPIXEL_PIN - strip->set_pixel(strip, 0, state ? 0x08 : 0x00, 0x00, 0x00); - strip->refresh(strip, 100); + led_strip_set_pixel(led_strip, 0, state ? 0x08 : 0x00, 0x00, 0x00); + led_strip_refresh(led_strip); #endif } diff --git a/hw/bsp/espressif/components/led_strip/CHANGELOG.md b/hw/bsp/espressif/components/led_strip/CHANGELOG.md new file mode 100644 index 000000000..51c0cd30c --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/CHANGELOG.md @@ -0,0 +1,38 @@ +## 2.5.0 + +- Enabled support for IDF4.4 and above + - with RMT backend only +- Added API `led_strip_set_pixel_hsv` + +## 2.4.0 + +- Support configurable SPI mode to control leds + - recommend enabling DMA when using SPI mode + +## 2.3.0 + +- Support configurable RMT channel size by setting `mem_block_symbols` + +## 2.2.0 + +- Support for 4 components RGBW leds (SK6812): + - in led_strip_config_t new fields + led_pixel_format, controlling byte format (LED_PIXEL_FORMAT_GRB, LED_PIXEL_FORMAT_GRBW) + led_model, used to configure bit timing (LED_MODEL_WS2812, LED_MODEL_SK6812) + - new API led_strip_set_pixel_rgbw + - new interface type set_pixel_rgbw + +## 2.1.0 + +- Support DMA feature, which offloads the CPU by a lot when it comes to drive a bunch of LEDs +- Support various RMT clock sources +- Acquire and release the power management lock before and after each refresh +- New driver flag: `invert_out` which can invert the led control signal by hardware + +## 2.0.0 + +- Reimplemented the driver using the new RMT driver (`driver/rmt_tx.h`) + +## 1.0.0 + +- Initial driver version, based on the legacy RMT driver (`driver/rmt.h`) diff --git a/hw/bsp/espressif/components/led_strip/CMakeLists.txt b/hw/bsp/espressif/components/led_strip/CMakeLists.txt index 8266c5a1c..15de610cc 100644 --- a/hw/bsp/espressif/components/led_strip/CMakeLists.txt +++ b/hw/bsp/espressif/components/led_strip/CMakeLists.txt @@ -1,7 +1,22 @@ -set(component_srcs "src/led_strip_rmt_ws2812.c") +include($ENV{IDF_PATH}/tools/cmake/version.cmake) -idf_component_register(SRCS "${component_srcs}" - INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "" - PRIV_REQUIRES "driver" - REQUIRES "") +set(srcs "src/led_strip_api.c") + +if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0") + if(CONFIG_SOC_RMT_SUPPORTED) + list(APPEND srcs "src/led_strip_rmt_dev.c" "src/led_strip_rmt_encoder.c") + endif() +else() + list(APPEND srcs "src/led_strip_rmt_dev_idf4.c") +endif() + +# the SPI backend driver relies on something that was added in IDF 5.1 +if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.1") + if(CONFIG_SOC_GPSPI_SUPPORTED) + list(APPEND srcs "src/led_strip_spi_dev.c") + endif() +endif() + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS "include" "interface" + REQUIRES "driver") diff --git a/hw/bsp/espressif/components/led_strip/LICENSE b/hw/bsp/espressif/components/led_strip/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/hw/bsp/espressif/components/led_strip/README.md b/hw/bsp/espressif/components/led_strip/README.md new file mode 100644 index 000000000..543d29642 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/README.md @@ -0,0 +1,97 @@ +# LED Strip Driver + +[![Component Registry](https://components.espressif.com/components/espressif/led_strip/badge.svg)](https://components.espressif.com/components/espressif/led_strip) + +This driver is designed for addressable LEDs like [WS2812](http://www.world-semi.com/Certifications/WS2812B.html), where each LED is controlled by a single data line. + +## Backend Controllers + +### The [RMT](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/rmt.html) Peripheral + +This is the most economical way to drive the LEDs because it only consumes one RMT channel, leaving other channels free to use. However, the memory usage increases dramatically with the number of LEDs. If the RMT hardware can't be assist by DMA, the driver will going into interrupt very frequently, thus result in a high CPU usage. What's worse, if the RMT interrupt is delayed or not serviced in time (e.g. if Wi-Fi interrupt happens on the same CPU core), the RMT transaction will be corrupted and the LEDs will display incorrect colors. If you want to use RMT to drive a large number of LEDs, you'd better to enable the DMA feature if possible [^1]. + +#### Allocate LED Strip Object with RMT Backend + +```c +#define BLINK_GPIO 0 + +led_strip_handle_t led_strip; + +/* LED strip initialization with the GPIO and pixels number*/ +led_strip_config_t strip_config = { + .strip_gpio_num = BLINK_GPIO, // The GPIO that connected to the LED strip's data line + .max_leds = 1, // The number of LEDs in the strip, + .led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip + .led_model = LED_MODEL_WS2812, // LED strip model + .flags.invert_out = false, // whether to invert the output signal (useful when your hardware has a level inverter) +}; + +led_strip_rmt_config_t rmt_config = { +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) + .rmt_channel = 0, +#else + .clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption + .resolution_hz = 10 * 1000 * 1000, // 10MHz + .flags.with_dma = false, // whether to enable the DMA feature +#endif +}; +ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip)); +``` + +You can create multiple LED strip objects with different GPIOs and pixel numbers. The backend driver will automatically allocate the RMT channel for you if there is more available. + +### The [SPI](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html) Peripheral + +SPI peripheral can also be used to generate the timing required by the LED strip. However this backend is not as economical as the RMT one, because it will take up the whole **bus**, unlike the RMT just takes one **channel**. You **CAN'T** connect other devices to the same SPI bus if it's been used by the led_strip, because the led_strip doesn't have the concept of "Chip Select". + +Please note, the SPI backend has a dependency of **ESP-IDF >= 5.1** + +#### Allocate LED Strip Object with SPI Backend + +```c +#define BLINK_GPIO 0 + +led_strip_handle_t led_strip; + +/* LED strip initialization with the GPIO and pixels number*/ +led_strip_config_t strip_config = { + .strip_gpio_num = BLINK_GPIO, // The GPIO that connected to the LED strip's data line + .max_leds = 1, // The number of LEDs in the strip, + .led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip + .led_model = LED_MODEL_WS2812, // LED strip model + .flags.invert_out = false, // whether to invert the output signal (useful when your hardware has a level inverter) +}; + +led_strip_spi_config_t spi_config = { + .clk_src = SPI_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption + .flags.with_dma = true, // Using DMA can improve performance and help drive more LEDs + .spi_bus = SPI2_HOST, // SPI bus ID +}; +ESP_ERROR_CHECK(led_strip_new_spi_device(&strip_config, &spi_config, &led_strip)); +``` + +The number of LED strip objects can be created depends on how many free SPI buses are free to use in your project. + +## FAQ + +* Which led_strip backend should I choose? + * It depends on your application requirement and target chip's ability. + + ```mermaid + flowchart LR + A{Is RMT supported?} + A --> |No| B[SPI backend] + B --> C{Does the led strip has \n a larger number of LEDs?} + C --> |No| D[Don't have to enable the DMA of the backend] + C --> |Yes| E[Enable the DMA of the backend] + A --> |Yes| F{Does the led strip has \n a larger number of LEDs?} + F --> |Yes| G{Does RMT support DMA?} + G --> |Yes| E + G --> |No| B + F --> |No| H[RMT backend] --> D + ``` + +* How to set the brightness of the LED strip? + * You can tune the brightness by scaling the value of each R-G-B element with a **same** factor. But pay attention to the overflow of the value. + +[^1]: The RMT DMA feature is not available on all ESP chips. Please check the data sheet before using it. diff --git a/hw/bsp/espressif/components/led_strip/api.md b/hw/bsp/espressif/components/led_strip/api.md new file mode 100644 index 000000000..6581d6604 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/api.md @@ -0,0 +1,454 @@ +# API Reference + +## Header files + +- [include/led_strip.h](#file-includeled_striph) +- [include/led_strip_rmt.h](#file-includeled_strip_rmth) +- [include/led_strip_spi.h](#file-includeled_strip_spih) +- [include/led_strip_types.h](#file-includeled_strip_typesh) +- [interface/led_strip_interface.h](#file-interfaceled_strip_interfaceh) + +## File include/led_strip.h + +## Functions + +| Type | Name | +| ---: | :--- | +| esp\_err\_t | [**led\_strip\_clear**](#function-led_strip_clear) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip)
_Clear LED strip (turn off all LEDs)_ | +| esp\_err\_t | [**led\_strip\_del**](#function-led_strip_del) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip)
_Free LED strip resources._ | +| esp\_err\_t | [**led\_strip\_refresh**](#function-led_strip_refresh) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip)
_Refresh memory colors to LEDs._ | +| esp\_err\_t | [**led\_strip\_set\_pixel**](#function-led_strip_set_pixel) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip, uint32\_t index, uint32\_t red, uint32\_t green, uint32\_t blue)
_Set RGB for a specific pixel._ | +| esp\_err\_t | [**led\_strip\_set\_pixel\_hsv**](#function-led_strip_set_pixel_hsv) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip, uint32\_t index, uint16\_t hue, uint8\_t saturation, uint8\_t value)
_Set HSV for a specific pixel._ | +| esp\_err\_t | [**led\_strip\_set\_pixel\_rgbw**](#function-led_strip_set_pixel_rgbw) ([**led\_strip\_handle\_t**](#struct-led_strip_t) strip, uint32\_t index, uint32\_t red, uint32\_t green, uint32\_t blue, uint32\_t white)
_Set RGBW for a specific pixel._ | + +## Functions Documentation + +### function `led_strip_clear` + +_Clear LED strip (turn off all LEDs)_ + +```c +esp_err_t led_strip_clear ( + led_strip_handle_t strip +) +``` + +**Parameters:** + +- `strip` LED strip + +**Returns:** + +- ESP\_OK: Clear LEDs successfully +- ESP\_FAIL: Clear LEDs failed because some other error occurred + +### function `led_strip_del` + +_Free LED strip resources._ + +```c +esp_err_t led_strip_del ( + led_strip_handle_t strip +) +``` + +**Parameters:** + +- `strip` LED strip + +**Returns:** + +- ESP\_OK: Free resources successfully +- ESP\_FAIL: Free resources failed because error occurred + +### function `led_strip_refresh` + +_Refresh memory colors to LEDs._ + +```c +esp_err_t led_strip_refresh ( + led_strip_handle_t strip +) +``` + +**Parameters:** + +- `strip` LED strip + +**Returns:** + +- ESP\_OK: Refresh successfully +- ESP\_FAIL: Refresh failed because some other error occurred + +**Note:** + +: After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. + +### function `led_strip_set_pixel` + +_Set RGB for a specific pixel._ + +```c +esp_err_t led_strip_set_pixel ( + led_strip_handle_t strip, + uint32_t index, + uint32_t red, + uint32_t green, + uint32_t blue +) +``` + +**Parameters:** + +- `strip` LED strip +- `index` index of pixel to set +- `red` red part of color +- `green` green part of color +- `blue` blue part of color + +**Returns:** + +- ESP\_OK: Set RGB for a specific pixel successfully +- ESP\_ERR\_INVALID\_ARG: Set RGB for a specific pixel failed because of invalid parameters +- ESP\_FAIL: Set RGB for a specific pixel failed because other error occurred + +### function `led_strip_set_pixel_hsv` + +_Set HSV for a specific pixel._ + +```c +esp_err_t led_strip_set_pixel_hsv ( + led_strip_handle_t strip, + uint32_t index, + uint16_t hue, + uint8_t saturation, + uint8_t value +) +``` + +**Parameters:** + +- `strip` LED strip +- `index` index of pixel to set +- `hue` hue part of color (0 - 360) +- `saturation` saturation part of color (0 - 255) +- `value` value part of color (0 - 255) + +**Returns:** + +- ESP\_OK: Set HSV color for a specific pixel successfully +- ESP\_ERR\_INVALID\_ARG: Set HSV color for a specific pixel failed because of an invalid argument +- ESP\_FAIL: Set HSV color for a specific pixel failed because other error occurred + +### function `led_strip_set_pixel_rgbw` + +_Set RGBW for a specific pixel._ + +```c +esp_err_t led_strip_set_pixel_rgbw ( + led_strip_handle_t strip, + uint32_t index, + uint32_t red, + uint32_t green, + uint32_t blue, + uint32_t white +) +``` + +**Note:** + +Only call this function if your led strip does have the white component (e.g. SK6812-RGBW) + +**Note:** + +Also see `led_strip_set_pixel` if you only want to specify the RGB part of the color and bypass the white component + +**Parameters:** + +- `strip` LED strip +- `index` index of pixel to set +- `red` red part of color +- `green` green part of color +- `blue` blue part of color +- `white` separate white component + +**Returns:** + +- ESP\_OK: Set RGBW color for a specific pixel successfully +- ESP\_ERR\_INVALID\_ARG: Set RGBW color for a specific pixel failed because of an invalid argument +- ESP\_FAIL: Set RGBW color for a specific pixel failed because other error occurred + +## File include/led_strip_rmt.h + +## Structures and Types + +| Type | Name | +| ---: | :--- | +| struct | [**led\_strip\_rmt\_config\_t**](#struct-led_strip_rmt_config_t)
_LED Strip RMT specific configuration._ | + +## Functions + +| Type | Name | +| ---: | :--- | +| esp\_err\_t | [**led\_strip\_new\_rmt\_device**](#function-led_strip_new_rmt_device) (const [**led\_strip\_config\_t**](#struct-led_strip_config_t) \*led\_config, const [**led\_strip\_rmt\_config\_t**](#struct-led_strip_rmt_config_t) \*rmt\_config, [**led\_strip\_handle\_t**](#struct-led_strip_t) \*ret\_strip)
_Create LED strip based on RMT TX channel._ | + +## Structures and Types Documentation + +### struct `led_strip_rmt_config_t` + +_LED Strip RMT specific configuration._ + +Variables: + +- rmt\_clock\_source\_t clk_src
RMT clock source + +- struct [**led\_strip\_rmt\_config\_t**](#struct-led_strip_rmt_config_t) flags
Extra driver flags + +- size\_t mem_block_symbols
How many RMT symbols can one RMT channel hold at one time. Set to 0 will fallback to use the default size. + +- uint32\_t resolution_hz
RMT tick resolution, if set to zero, a default resolution (10MHz) will be applied + +- uint32\_t with_dma
Use DMA to transmit data + +## Functions Documentation + +### function `led_strip_new_rmt_device` + +_Create LED strip based on RMT TX channel._ + +```c +esp_err_t led_strip_new_rmt_device ( + const led_strip_config_t *led_config, + const led_strip_rmt_config_t *rmt_config, + led_strip_handle_t *ret_strip +) +``` + +**Parameters:** + +- `led_config` LED strip configuration +- `rmt_config` RMT specific configuration +- `ret_strip` Returned LED strip handle + +**Returns:** + +- ESP\_OK: create LED strip handle successfully +- ESP\_ERR\_INVALID\_ARG: create LED strip handle failed because of invalid argument +- ESP\_ERR\_NO\_MEM: create LED strip handle failed because of out of memory +- ESP\_FAIL: create LED strip handle failed because some other error + +## File include/led_strip_spi.h + +## Structures and Types + +| Type | Name | +| ---: | :--- | +| struct | [**led\_strip\_spi\_config\_t**](#struct-led_strip_spi_config_t)
_LED Strip SPI specific configuration._ | + +## Functions + +| Type | Name | +| ---: | :--- | +| esp\_err\_t | [**led\_strip\_new\_spi\_device**](#function-led_strip_new_spi_device) (const [**led\_strip\_config\_t**](#struct-led_strip_config_t) \*led\_config, const [**led\_strip\_spi\_config\_t**](#struct-led_strip_spi_config_t) \*spi\_config, [**led\_strip\_handle\_t**](#struct-led_strip_t) \*ret\_strip)
_Create LED strip based on SPI MOSI channel._ | + +## Structures and Types Documentation + +### struct `led_strip_spi_config_t` + +_LED Strip SPI specific configuration._ + +Variables: + +- spi\_clock\_source\_t clk_src
SPI clock source + +- struct [**led\_strip\_spi\_config\_t**](#struct-led_strip_spi_config_t) flags
Extra driver flags + +- spi\_host\_device\_t spi_bus
SPI bus ID. Which buses are available depends on the specific chip + +- uint32\_t with_dma
Use DMA to transmit data + +## Functions Documentation + +### function `led_strip_new_spi_device` + +_Create LED strip based on SPI MOSI channel._ + +```c +esp_err_t led_strip_new_spi_device ( + const led_strip_config_t *led_config, + const led_strip_spi_config_t *spi_config, + led_strip_handle_t *ret_strip +) +``` + +**Note:** + +Although only the MOSI line is used for generating the signal, the whole SPI bus can't be used for other purposes. + +**Parameters:** + +- `led_config` LED strip configuration +- `spi_config` SPI specific configuration +- `ret_strip` Returned LED strip handle + +**Returns:** + +- ESP\_OK: create LED strip handle successfully +- ESP\_ERR\_INVALID\_ARG: create LED strip handle failed because of invalid argument +- ESP\_ERR\_NOT\_SUPPORTED: create LED strip handle failed because of unsupported configuration +- ESP\_ERR\_NO\_MEM: create LED strip handle failed because of out of memory +- ESP\_FAIL: create LED strip handle failed because some other error + +## File include/led_strip_types.h + +## Structures and Types + +| Type | Name | +| ---: | :--- | +| enum | [**led\_model\_t**](#enum-led_model_t)
_LED strip model._ | +| enum | [**led\_pixel\_format\_t**](#enum-led_pixel_format_t)
_LED strip pixel format._ | +| struct | [**led\_strip\_config\_t**](#struct-led_strip_config_t)
_LED Strip Configuration._ | +| typedef struct [**led\_strip\_t**](#struct-led_strip_t) \* | [**led\_strip\_handle\_t**](#typedef-led_strip_handle_t)
_LED strip handle._ | + +## Structures and Types Documentation + +### enum `led_model_t` + +_LED strip model._ + +```c +enum led_model_t { + LED_MODEL_WS2812, + LED_MODEL_SK6812, + LED_MODEL_INVALID +}; +``` + +**Note:** + +Different led model may have different timing parameters, so we need to distinguish them. + +### enum `led_pixel_format_t` + +_LED strip pixel format._ + +```c +enum led_pixel_format_t { + LED_PIXEL_FORMAT_GRB, + LED_PIXEL_FORMAT_GRBW, + LED_PIXEL_FORMAT_INVALID +}; +``` + +### struct `led_strip_config_t` + +_LED Strip Configuration._ + +Variables: + +- struct [**led\_strip\_config\_t**](#struct-led_strip_config_t) flags
Extra driver flags + +- uint32\_t invert_out
Invert output signal + +- led\_model\_t led_model
LED model + +- led\_pixel\_format\_t led_pixel_format
LED pixel format + +- uint32\_t max_leds
Maximum LEDs in a single strip + +- int strip_gpio_num
GPIO number that used by LED strip + +### typedef `led_strip_handle_t` + +_LED strip handle._ + +```c +typedef struct led_strip_t* led_strip_handle_t; +``` + +## File interface/led_strip_interface.h + +## Structures and Types + +| Type | Name | +| ---: | :--- | +| struct | [**led\_strip\_t**](#struct-led_strip_t)
_LED strip interface definition._ | +| typedef struct [**led\_strip\_t**](#struct-led_strip_t) | [**led\_strip\_t**](#typedef-led_strip_t)
| + +## Structures and Types Documentation + +### struct `led_strip_t` + +_LED strip interface definition._ + +Variables: + +- esp\_err\_t(\* clear
_Clear LED strip (turn off all LEDs)_
**Parameters:** + +- `strip` LED strip +- `timeout_ms` timeout value for clearing task + +**Returns:** + +- ESP\_OK: Clear LEDs successfully +- ESP\_FAIL: Clear LEDs failed because some other error occurred + +- esp\_err\_t(\* del
_Free LED strip resources._
**Parameters:** + +- `strip` LED strip + +**Returns:** + +- ESP\_OK: Free resources successfully +- ESP\_FAIL: Free resources failed because error occurred + +- esp\_err\_t(\* refresh
_Refresh memory colors to LEDs._
**Parameters:** + +- `strip` LED strip +- `timeout_ms` timeout value for refreshing task + +**Returns:** + +- ESP\_OK: Refresh successfully +- ESP\_FAIL: Refresh failed because some other error occurred + +**Note:** + +: After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. + +- esp\_err\_t(\* set_pixel
_Set RGB for a specific pixel._
**Parameters:** + +- `strip` LED strip +- `index` index of pixel to set +- `red` red part of color +- `green` green part of color +- `blue` blue part of color + +**Returns:** + +- ESP\_OK: Set RGB for a specific pixel successfully +- ESP\_ERR\_INVALID\_ARG: Set RGB for a specific pixel failed because of invalid parameters +- ESP\_FAIL: Set RGB for a specific pixel failed because other error occurred + +- esp\_err\_t(\* set_pixel_rgbw
_Set RGBW for a specific pixel. Similar to_ `set_pixel`_but also set the white component._
**Parameters:** + +- `strip` LED strip +- `index` index of pixel to set +- `red` red part of color +- `green` green part of color +- `blue` blue part of color +- `white` separate white component + +**Returns:** + +- ESP\_OK: Set RGBW color for a specific pixel successfully +- ESP\_ERR\_INVALID\_ARG: Set RGBW color for a specific pixel failed because of an invalid argument +- ESP\_FAIL: Set RGBW color for a specific pixel failed because other error occurred + +### typedef `led_strip_t` + +```c +typedef struct led_strip_t led_strip_t; +``` + +Type of LED strip diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/CMakeLists.txt b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/CMakeLists.txt new file mode 100644 index 000000000..923c46310 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/CMakeLists.txt @@ -0,0 +1,9 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +set(IDF_TARGET "esp32s3") +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(led_strip_rmt_ws2812) diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/README.md b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/README.md new file mode 100644 index 000000000..ad52235d5 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/README.md @@ -0,0 +1,31 @@ +# LED Strip Example (RMT backend + WS2812) + +This example demonstrates how to blink the WS2812 LED using the [led_strip](https://components.espressif.com/component/espressif/led_strip) component. + +## How to Use Example + +### Hardware Required + +* A development board with Espressif SoC +* A USB cable for Power supply and programming +* WS2812 LED strip + +### Configure the Example + +Before project configuration and build, be sure to set the correct chip target using `idf.py set-target `. Then assign the proper GPIO in the [source file](main/led_strip_rmt_ws2812_main.c). If your led strip has multiple LEDs, don't forget update the number. + +### Build and Flash + +Run `idf.py -p PORT build flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +```text +I (299) gpio: GPIO[8]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 +I (309) example: Created LED strip object with RMT backend +I (309) example: Start blinking LED strip +``` diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/dependencies.lock b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/dependencies.lock new file mode 100644 index 000000000..97840a153 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/dependencies.lock @@ -0,0 +1,15 @@ +dependencies: + espressif/led_strip: + component_hash: null + source: + path: /home/hathach/code/idf-extra-components/led_strip + type: local + version: 2.5.2 + idf: + component_hash: null + source: + type: idf + version: 5.1.1 +manifest_hash: 47d47762be26168b388cb0e6cbfee6b22c68d630ebf4b27a49c47c4c54191590 +target: esp32s3 +version: 1.0.0 diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/CMakeLists.txt b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/CMakeLists.txt new file mode 100644 index 000000000..37b9c1458 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "led_strip_rmt_ws2812_main.c" + INCLUDE_DIRS ".") diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/idf_component.yml b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/idf_component.yml new file mode 100644 index 000000000..916c366c7 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/idf_component.yml @@ -0,0 +1,5 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/led_strip: + version: '^2' + override_path: '../../../' diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/led_strip_rmt_ws2812_main.c b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/led_strip_rmt_ws2812_main.c new file mode 100644 index 000000000..4b20a5958 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/main/led_strip_rmt_ws2812_main.c @@ -0,0 +1,75 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "led_strip.h" +#include "esp_log.h" +#include "esp_err.h" + +// GPIO assignment +#define LED_STRIP_BLINK_GPIO 48 +// Numbers of the LED in the strip +#define LED_STRIP_LED_NUMBERS 1 +// 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution) +#define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000) + +static const char *TAG = "example"; + +led_strip_handle_t configure_led(void) +{ + // LED strip general initialization, according to your led board design + led_strip_config_t strip_config = { + .strip_gpio_num = LED_STRIP_BLINK_GPIO, // The GPIO that connected to the LED strip's data line + .max_leds = LED_STRIP_LED_NUMBERS, // The number of LEDs in the strip, + .led_pixel_format = LED_PIXEL_FORMAT_GRB, // Pixel format of your LED strip + .led_model = LED_MODEL_WS2812, // LED strip model + .flags.invert_out = false, // whether to invert the output signal + }; + + // LED strip backend configuration: RMT + led_strip_rmt_config_t rmt_config = { +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) + .rmt_channel = 0, +#else + .clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption + .resolution_hz = LED_STRIP_RMT_RES_HZ, // RMT counter clock frequency + .flags.with_dma = false, // DMA feature is available on ESP target like ESP32-S3 +#endif + }; + + // LED Strip object handle + led_strip_handle_t led_strip; + ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip)); + ESP_LOGI(TAG, "Created LED strip object with RMT backend"); + return led_strip; +} + +void app_main(void) +{ + led_strip_handle_t led_strip = configure_led(); + bool led_on_off = false; + + ESP_LOGI(TAG, "Start blinking LED strip"); + while (1) { + if (led_on_off) { + /* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */ + for (int i = 0; i < LED_STRIP_LED_NUMBERS; i++) { + ESP_ERROR_CHECK(led_strip_set_pixel(led_strip, i, 5, 5, 5)); + } + /* Refresh the strip to send data */ + ESP_ERROR_CHECK(led_strip_refresh(led_strip)); + ESP_LOGI(TAG, "LED ON!"); + } else { + /* Set all LED off to clear all pixels */ + ESP_ERROR_CHECK(led_strip_clear(led_strip)); + ESP_LOGI(TAG, "LED OFF!"); + } + + led_on_off = !led_on_off; + vTaskDelay(pdMS_TO_TICKS(500)); + } +} diff --git a/hw/bsp/espressif/components/led_strip/idf_component.yml b/hw/bsp/espressif/components/led_strip/idf_component.yml new file mode 100644 index 000000000..1fd9b83ee --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/idf_component.yml @@ -0,0 +1,5 @@ +version: "2.5.2" +description: Driver for Addressable LED Strip (WS2812, etc) +url: https://github.com/espressif/idf-extra-components/tree/master/led_strip +dependencies: + idf: ">=4.4" diff --git a/hw/bsp/espressif/components/led_strip/include/led_strip.h b/hw/bsp/espressif/components/led_strip/include/led_strip.h index a9dffc325..38711744a 100644 --- a/hw/bsp/espressif/components/led_strip/include/led_strip.h +++ b/hw/bsp/espressif/components/led_strip/include/led_strip.h @@ -1,125 +1,110 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// 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. +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once +#include +#include "esp_err.h" +#include "led_strip_rmt.h" +#include "esp_idf_version.h" + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) +#include "led_strip_spi.h" +#endif + #ifdef __cplusplus extern "C" { #endif -#include "esp_err.h" - /** -* @brief LED Strip Type -* -*/ -typedef struct led_strip_s led_strip_t; + * @brief Set RGB for a specific pixel + * + * @param strip: LED strip + * @param index: index of pixel to set + * @param red: red part of color + * @param green: green part of color + * @param blue: blue part of color + * + * @return + * - ESP_OK: Set RGB for a specific pixel successfully + * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters + * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred + */ +esp_err_t led_strip_set_pixel(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); /** -* @brief LED Strip Device Type -* -*/ -typedef void *led_strip_dev_t; + * @brief Set RGBW for a specific pixel + * + * @note Only call this function if your led strip does have the white component (e.g. SK6812-RGBW) + * @note Also see `led_strip_set_pixel` if you only want to specify the RGB part of the color and bypass the white component + * + * @param strip: LED strip + * @param index: index of pixel to set + * @param red: red part of color + * @param green: green part of color + * @param blue: blue part of color + * @param white: separate white component + * + * @return + * - ESP_OK: Set RGBW color for a specific pixel successfully + * - ESP_ERR_INVALID_ARG: Set RGBW color for a specific pixel failed because of an invalid argument + * - ESP_FAIL: Set RGBW color for a specific pixel failed because other error occurred + */ +esp_err_t led_strip_set_pixel_rgbw(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white); /** -* @brief Declare of LED Strip Type -* -*/ -struct led_strip_s { - /** - * @brief Set RGB for a specific pixel - * - * @param strip: LED strip - * @param index: index of pixel to set - * @param red: red part of color - * @param green: green part of color - * @param blue: blue part of color - * - * @return - * - ESP_OK: Set RGB for a specific pixel successfully - * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters - * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred - */ - esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); - - /** - * @brief Refresh memory colors to LEDs - * - * @param strip: LED strip - * @param timeout_ms: timeout value for refreshing task - * - * @return - * - ESP_OK: Refresh successfully - * - ESP_ERR_TIMEOUT: Refresh failed because of timeout - * - ESP_FAIL: Refresh failed because some other error occurred - * - * @note: - * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. - */ - esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Clear LED strip (turn off all LEDs) - * - * @param strip: LED strip - * @param timeout_ms: timeout value for clearing task - * - * @return - * - ESP_OK: Clear LEDs successfully - * - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout - * - ESP_FAIL: Clear LEDs failed because some other error occurred - */ - esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms); - - /** - * @brief Free LED strip resources - * - * @param strip: LED strip - * - * @return - * - ESP_OK: Free resources successfully - * - ESP_FAIL: Free resources failed because error occurred - */ - esp_err_t (*del)(led_strip_t *strip); -}; + * @brief Set HSV for a specific pixel + * + * @param strip: LED strip + * @param index: index of pixel to set + * @param hue: hue part of color (0 - 360) + * @param saturation: saturation part of color (0 - 255) + * @param value: value part of color (0 - 255) + * + * @return + * - ESP_OK: Set HSV color for a specific pixel successfully + * - ESP_ERR_INVALID_ARG: Set HSV color for a specific pixel failed because of an invalid argument + * - ESP_FAIL: Set HSV color for a specific pixel failed because other error occurred + */ +esp_err_t led_strip_set_pixel_hsv(led_strip_handle_t strip, uint32_t index, uint16_t hue, uint8_t saturation, uint8_t value); /** -* @brief LED Strip Configuration Type -* -*/ -typedef struct { - uint32_t max_leds; /*!< Maximum LEDs in a single strip */ - led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */ -} led_strip_config_t; + * @brief Refresh memory colors to LEDs + * + * @param strip: LED strip + * + * @return + * - ESP_OK: Refresh successfully + * - ESP_FAIL: Refresh failed because some other error occurred + * + * @note: + * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. + */ +esp_err_t led_strip_refresh(led_strip_handle_t strip); /** - * @brief Default configuration for LED strip + * @brief Clear LED strip (turn off all LEDs) + * + * @param strip: LED strip * + * @return + * - ESP_OK: Clear LEDs successfully + * - ESP_FAIL: Clear LEDs failed because some other error occurred */ -#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \ - { \ - .max_leds = number, \ - .dev = dev_hdl, \ - } +esp_err_t led_strip_clear(led_strip_handle_t strip); /** -* @brief Install a new ws2812 driver (based on RMT peripheral) -* -* @param config: LED strip configuration -* @return -* LED strip instance or NULL -*/ -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config); + * @brief Free LED strip resources + * + * @param strip: LED strip + * + * @return + * - ESP_OK: Free resources successfully + * - ESP_FAIL: Free resources failed because error occurred + */ +esp_err_t led_strip_del(led_strip_handle_t strip); #ifdef __cplusplus } diff --git a/hw/bsp/espressif/components/led_strip/include/led_strip_rmt.h b/hw/bsp/espressif/components/led_strip/include/led_strip_rmt.h new file mode 100644 index 000000000..b575aeaba --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/include/led_strip_rmt.h @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "esp_err.h" +#include "led_strip_types.h" +#include "esp_idf_version.h" + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) +#include "driver/rmt_types.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LED Strip RMT specific configuration + */ +typedef struct { +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) + uint8_t rmt_channel; /*!< Specify the channel number, the legacy RMT driver doesn't support channel allocator */ +#else // new driver supports specify the clock source and clock resolution + rmt_clock_source_t clk_src; /*!< RMT clock source */ + uint32_t resolution_hz; /*!< RMT tick resolution, if set to zero, a default resolution (10MHz) will be applied */ +#endif + size_t mem_block_symbols; /*!< How many RMT symbols can one RMT channel hold at one time. Set to 0 will fallback to use the default size. */ + struct { + uint32_t with_dma: 1; /*!< Use DMA to transmit data */ + } flags; /*!< Extra driver flags */ +} led_strip_rmt_config_t; + +/** + * @brief Create LED strip based on RMT TX channel + * + * @param led_config LED strip configuration + * @param rmt_config RMT specific configuration + * @param ret_strip Returned LED strip handle + * @return + * - ESP_OK: create LED strip handle successfully + * - ESP_ERR_INVALID_ARG: create LED strip handle failed because of invalid argument + * - ESP_ERR_NO_MEM: create LED strip handle failed because of out of memory + * - ESP_FAIL: create LED strip handle failed because some other error + */ +esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const led_strip_rmt_config_t *rmt_config, led_strip_handle_t *ret_strip); + +#ifdef __cplusplus +} +#endif diff --git a/hw/bsp/espressif/components/led_strip/include/led_strip_spi.h b/hw/bsp/espressif/components/led_strip/include/led_strip_spi.h new file mode 100644 index 000000000..eb3524936 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/include/led_strip_spi.h @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "esp_err.h" +#include "driver/spi_master.h" +#include "led_strip_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LED Strip SPI specific configuration + */ +typedef struct { + spi_clock_source_t clk_src; /*!< SPI clock source */ + spi_host_device_t spi_bus; /*!< SPI bus ID. Which buses are available depends on the specific chip */ + struct { + uint32_t with_dma: 1; /*!< Use DMA to transmit data */ + } flags; /*!< Extra driver flags */ +} led_strip_spi_config_t; + +/** + * @brief Create LED strip based on SPI MOSI channel + * @note Although only the MOSI line is used for generating the signal, the whole SPI bus can't be used for other purposes. + * + * @param led_config LED strip configuration + * @param spi_config SPI specific configuration + * @param ret_strip Returned LED strip handle + * @return + * - ESP_OK: create LED strip handle successfully + * - ESP_ERR_INVALID_ARG: create LED strip handle failed because of invalid argument + * - ESP_ERR_NOT_SUPPORTED: create LED strip handle failed because of unsupported configuration + * - ESP_ERR_NO_MEM: create LED strip handle failed because of out of memory + * - ESP_FAIL: create LED strip handle failed because some other error + */ +esp_err_t led_strip_new_spi_device(const led_strip_config_t *led_config, const led_strip_spi_config_t *spi_config, led_strip_handle_t *ret_strip); + +#ifdef __cplusplus +} +#endif diff --git a/hw/bsp/espressif/components/led_strip/include/led_strip_types.h b/hw/bsp/espressif/components/led_strip/include/led_strip_types.h new file mode 100644 index 000000000..691f0bc39 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/include/led_strip_types.h @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LED strip pixel format + */ +typedef enum { + LED_PIXEL_FORMAT_GRB, /*!< Pixel format: GRB */ + LED_PIXEL_FORMAT_GRBW, /*!< Pixel format: GRBW */ + LED_PIXEL_FORMAT_INVALID /*!< Invalid pixel format */ +} led_pixel_format_t; + +/** + * @brief LED strip model + * @note Different led model may have different timing parameters, so we need to distinguish them. + */ +typedef enum { + LED_MODEL_WS2812, /*!< LED strip model: WS2812 */ + LED_MODEL_SK6812, /*!< LED strip model: SK6812 */ + LED_MODEL_INVALID /*!< Invalid LED strip model */ +} led_model_t; + +/** + * @brief LED strip handle + */ +typedef struct led_strip_t *led_strip_handle_t; + +/** + * @brief LED Strip Configuration + */ +typedef struct { + int strip_gpio_num; /*!< GPIO number that used by LED strip */ + uint32_t max_leds; /*!< Maximum LEDs in a single strip */ + led_pixel_format_t led_pixel_format; /*!< LED pixel format */ + led_model_t led_model; /*!< LED model */ + + struct { + uint32_t invert_out: 1; /*!< Invert output signal */ + } flags; /*!< Extra driver flags */ +} led_strip_config_t; + +#ifdef __cplusplus +} +#endif diff --git a/hw/bsp/espressif/components/led_strip/interface/led_strip_interface.h b/hw/bsp/espressif/components/led_strip/interface/led_strip_interface.h new file mode 100644 index 000000000..3de4c2715 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/interface/led_strip_interface.h @@ -0,0 +1,95 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct led_strip_t led_strip_t; /*!< Type of LED strip */ + +/** + * @brief LED strip interface definition + */ +struct led_strip_t { + /** + * @brief Set RGB for a specific pixel + * + * @param strip: LED strip + * @param index: index of pixel to set + * @param red: red part of color + * @param green: green part of color + * @param blue: blue part of color + * + * @return + * - ESP_OK: Set RGB for a specific pixel successfully + * - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters + * - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred + */ + esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue); + + /** + * @brief Set RGBW for a specific pixel. Similar to `set_pixel` but also set the white component + * + * @param strip: LED strip + * @param index: index of pixel to set + * @param red: red part of color + * @param green: green part of color + * @param blue: blue part of color + * @param white: separate white component + * + * @return + * - ESP_OK: Set RGBW color for a specific pixel successfully + * - ESP_ERR_INVALID_ARG: Set RGBW color for a specific pixel failed because of an invalid argument + * - ESP_FAIL: Set RGBW color for a specific pixel failed because other error occurred + */ + esp_err_t (*set_pixel_rgbw)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white); + + /** + * @brief Refresh memory colors to LEDs + * + * @param strip: LED strip + * @param timeout_ms: timeout value for refreshing task + * + * @return + * - ESP_OK: Refresh successfully + * - ESP_FAIL: Refresh failed because some other error occurred + * + * @note: + * After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip. + */ + esp_err_t (*refresh)(led_strip_t *strip); + + /** + * @brief Clear LED strip (turn off all LEDs) + * + * @param strip: LED strip + * @param timeout_ms: timeout value for clearing task + * + * @return + * - ESP_OK: Clear LEDs successfully + * - ESP_FAIL: Clear LEDs failed because some other error occurred + */ + esp_err_t (*clear)(led_strip_t *strip); + + /** + * @brief Free LED strip resources + * + * @param strip: LED strip + * + * @return + * - ESP_OK: Free resources successfully + * - ESP_FAIL: Free resources failed because error occurred + */ + esp_err_t (*del)(led_strip_t *strip); +}; + +#ifdef __cplusplus +} +#endif diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_api.c b/hw/bsp/espressif/components/led_strip/src/led_strip_api.c new file mode 100644 index 000000000..6eb86b8f1 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/src/led_strip_api.c @@ -0,0 +1,94 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "esp_log.h" +#include "esp_check.h" +#include "led_strip.h" +#include "led_strip_interface.h" + +static const char *TAG = "led_strip"; + +esp_err_t led_strip_set_pixel(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) +{ + ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + return strip->set_pixel(strip, index, red, green, blue); +} + +esp_err_t led_strip_set_pixel_hsv(led_strip_handle_t strip, uint32_t index, uint16_t hue, uint8_t saturation, uint8_t value) +{ + ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + + uint32_t red = 0; + uint32_t green = 0; + uint32_t blue = 0; + + uint32_t rgb_max = value; + uint32_t rgb_min = rgb_max * (255 - saturation) / 255.0f; + + uint32_t i = hue / 60; + uint32_t diff = hue % 60; + + // RGB adjustment amount by hue + uint32_t rgb_adj = (rgb_max - rgb_min) * diff / 60; + + switch (i) { + case 0: + red = rgb_max; + green = rgb_min + rgb_adj; + blue = rgb_min; + break; + case 1: + red = rgb_max - rgb_adj; + green = rgb_max; + blue = rgb_min; + break; + case 2: + red = rgb_min; + green = rgb_max; + blue = rgb_min + rgb_adj; + break; + case 3: + red = rgb_min; + green = rgb_max - rgb_adj; + blue = rgb_max; + break; + case 4: + red = rgb_min + rgb_adj; + green = rgb_min; + blue = rgb_max; + break; + default: + red = rgb_max; + green = rgb_min; + blue = rgb_max - rgb_adj; + break; + } + + return strip->set_pixel(strip, index, red, green, blue); +} + +esp_err_t led_strip_set_pixel_rgbw(led_strip_handle_t strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white) +{ + ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + return strip->set_pixel_rgbw(strip, index, red, green, blue, white); +} + +esp_err_t led_strip_refresh(led_strip_handle_t strip) +{ + ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + return strip->refresh(strip); +} + +esp_err_t led_strip_clear(led_strip_handle_t strip) +{ + ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + return strip->clear(strip); +} + +esp_err_t led_strip_del(led_strip_handle_t strip) +{ + ESP_RETURN_ON_FALSE(strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + return strip->del(strip); +} diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev.c b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev.c new file mode 100644 index 000000000..1cbf0e45a --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev.c @@ -0,0 +1,164 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include "esp_log.h" +#include "esp_check.h" +#include "driver/rmt_tx.h" +#include "led_strip.h" +#include "led_strip_interface.h" +#include "led_strip_rmt_encoder.h" + +#define LED_STRIP_RMT_DEFAULT_RESOLUTION 10000000 // 10MHz resolution +#define LED_STRIP_RMT_DEFAULT_TRANS_QUEUE_SIZE 4 +// the memory size of each RMT channel, in words (4 bytes) +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 +#define LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS 64 +#else +#define LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS 48 +#endif + +static const char *TAG = "led_strip_rmt"; + +typedef struct { + led_strip_t base; + rmt_channel_handle_t rmt_chan; + rmt_encoder_handle_t strip_encoder; + uint32_t strip_len; + uint8_t bytes_per_pixel; + uint8_t pixel_buf[]; +} led_strip_rmt_obj; + +static esp_err_t led_strip_rmt_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) +{ + led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base); + ESP_RETURN_ON_FALSE(index < rmt_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs"); + uint32_t start = index * rmt_strip->bytes_per_pixel; + // In thr order of GRB, as LED strip like WS2812 sends out pixels in this order + rmt_strip->pixel_buf[start + 0] = green & 0xFF; + rmt_strip->pixel_buf[start + 1] = red & 0xFF; + rmt_strip->pixel_buf[start + 2] = blue & 0xFF; + if (rmt_strip->bytes_per_pixel > 3) { + rmt_strip->pixel_buf[start + 3] = 0; + } + return ESP_OK; +} + +static esp_err_t led_strip_rmt_set_pixel_rgbw(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white) +{ + led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base); + ESP_RETURN_ON_FALSE(index < rmt_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs"); + ESP_RETURN_ON_FALSE(rmt_strip->bytes_per_pixel == 4, ESP_ERR_INVALID_ARG, TAG, "wrong LED pixel format, expected 4 bytes per pixel"); + uint8_t *buf_start = rmt_strip->pixel_buf + index * 4; + // SK6812 component order is GRBW + *buf_start = green & 0xFF; + *++buf_start = red & 0xFF; + *++buf_start = blue & 0xFF; + *++buf_start = white & 0xFF; + return ESP_OK; +} + +static esp_err_t led_strip_rmt_refresh(led_strip_t *strip) +{ + led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base); + rmt_transmit_config_t tx_conf = { + .loop_count = 0, + }; + + ESP_RETURN_ON_ERROR(rmt_enable(rmt_strip->rmt_chan), TAG, "enable RMT channel failed"); + ESP_RETURN_ON_ERROR(rmt_transmit(rmt_strip->rmt_chan, rmt_strip->strip_encoder, rmt_strip->pixel_buf, + rmt_strip->strip_len * rmt_strip->bytes_per_pixel, &tx_conf), TAG, "transmit pixels by RMT failed"); + ESP_RETURN_ON_ERROR(rmt_tx_wait_all_done(rmt_strip->rmt_chan, -1), TAG, "flush RMT channel failed"); + ESP_RETURN_ON_ERROR(rmt_disable(rmt_strip->rmt_chan), TAG, "disable RMT channel failed"); + return ESP_OK; +} + +static esp_err_t led_strip_rmt_clear(led_strip_t *strip) +{ + led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base); + // Write zero to turn off all leds + memset(rmt_strip->pixel_buf, 0, rmt_strip->strip_len * rmt_strip->bytes_per_pixel); + return led_strip_rmt_refresh(strip); +} + +static esp_err_t led_strip_rmt_del(led_strip_t *strip) +{ + led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base); + ESP_RETURN_ON_ERROR(rmt_del_channel(rmt_strip->rmt_chan), TAG, "delete RMT channel failed"); + ESP_RETURN_ON_ERROR(rmt_del_encoder(rmt_strip->strip_encoder), TAG, "delete strip encoder failed"); + free(rmt_strip); + return ESP_OK; +} + +esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const led_strip_rmt_config_t *rmt_config, led_strip_handle_t *ret_strip) +{ + led_strip_rmt_obj *rmt_strip = NULL; + esp_err_t ret = ESP_OK; + ESP_GOTO_ON_FALSE(led_config && rmt_config && ret_strip, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + ESP_GOTO_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid led_pixel_format"); + uint8_t bytes_per_pixel = 3; + if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) { + bytes_per_pixel = 4; + } else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) { + bytes_per_pixel = 3; + } else { + assert(false); + } + rmt_strip = calloc(1, sizeof(led_strip_rmt_obj) + led_config->max_leds * bytes_per_pixel); + ESP_GOTO_ON_FALSE(rmt_strip, ESP_ERR_NO_MEM, err, TAG, "no mem for rmt strip"); + uint32_t resolution = rmt_config->resolution_hz ? rmt_config->resolution_hz : LED_STRIP_RMT_DEFAULT_RESOLUTION; + + // for backward compatibility, if the user does not set the clk_src, use the default value + rmt_clock_source_t clk_src = RMT_CLK_SRC_DEFAULT; + if (rmt_config->clk_src) { + clk_src = rmt_config->clk_src; + } + size_t mem_block_symbols = LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS; + // override the default value if the user sets it + if (rmt_config->mem_block_symbols) { + mem_block_symbols = rmt_config->mem_block_symbols; + } + rmt_tx_channel_config_t rmt_chan_config = { + .clk_src = clk_src, + .gpio_num = led_config->strip_gpio_num, + .mem_block_symbols = mem_block_symbols, + .resolution_hz = resolution, + .trans_queue_depth = LED_STRIP_RMT_DEFAULT_TRANS_QUEUE_SIZE, + .flags.with_dma = rmt_config->flags.with_dma, + .flags.invert_out = led_config->flags.invert_out, + }; + ESP_GOTO_ON_ERROR(rmt_new_tx_channel(&rmt_chan_config, &rmt_strip->rmt_chan), err, TAG, "create RMT TX channel failed"); + + led_strip_encoder_config_t strip_encoder_conf = { + .resolution = resolution, + .led_model = led_config->led_model + }; + ESP_GOTO_ON_ERROR(rmt_new_led_strip_encoder(&strip_encoder_conf, &rmt_strip->strip_encoder), err, TAG, "create LED strip encoder failed"); + + + rmt_strip->bytes_per_pixel = bytes_per_pixel; + rmt_strip->strip_len = led_config->max_leds; + rmt_strip->base.set_pixel = led_strip_rmt_set_pixel; + rmt_strip->base.set_pixel_rgbw = led_strip_rmt_set_pixel_rgbw; + rmt_strip->base.refresh = led_strip_rmt_refresh; + rmt_strip->base.clear = led_strip_rmt_clear; + rmt_strip->base.del = led_strip_rmt_del; + + *ret_strip = &rmt_strip->base; + return ESP_OK; +err: + if (rmt_strip) { + if (rmt_strip->rmt_chan) { + rmt_del_channel(rmt_strip->rmt_chan); + } + if (rmt_strip->strip_encoder) { + rmt_del_encoder(rmt_strip->strip_encoder); + } + free(rmt_strip); + } + return ret; +} diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev_idf4.c b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev_idf4.c new file mode 100644 index 000000000..a1067cd7c --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_dev_idf4.c @@ -0,0 +1,194 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include "esp_log.h" +#include "esp_check.h" +#include "driver/rmt.h" +#include "led_strip.h" +#include "led_strip_interface.h" + +static const char *TAG = "led_strip_rmt"; + +#define WS2812_T0H_NS (300) +#define WS2812_T0L_NS (900) +#define WS2812_T1H_NS (900) +#define WS2812_T1L_NS (300) + +#define SK6812_T0H_NS (300) +#define SK6812_T0L_NS (900) +#define SK6812_T1H_NS (600) +#define SK6812_T1L_NS (600) + +#define LED_STRIP_RESET_MS (10) + +// the memory size of each RMT channel, in words (4 bytes) +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 +#define LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS 64 +#else +#define LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS 48 +#endif + +static uint32_t led_t0h_ticks = 0; +static uint32_t led_t1h_ticks = 0; +static uint32_t led_t0l_ticks = 0; +static uint32_t led_t1l_ticks = 0; + +typedef struct { + led_strip_t base; + rmt_channel_t rmt_channel; + uint32_t strip_len; + uint8_t bytes_per_pixel; + uint8_t buffer[0]; +} led_strip_rmt_obj; + +static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, + size_t wanted_num, size_t *translated_size, size_t *item_num) +{ + if (src == NULL || dest == NULL) { + *translated_size = 0; + *item_num = 0; + return; + } + const rmt_item32_t bit0 = {{{ led_t0h_ticks, 1, led_t0l_ticks, 0 }}}; //Logical 0 + const rmt_item32_t bit1 = {{{ led_t1h_ticks, 1, led_t1l_ticks, 0 }}}; //Logical 1 + size_t size = 0; + size_t num = 0; + uint8_t *psrc = (uint8_t *)src; + rmt_item32_t *pdest = dest; + while (size < src_size && num < wanted_num) { + for (int i = 0; i < 8; i++) { + // MSB first + if (*psrc & (1 << (7 - i))) { + pdest->val = bit1.val; + } else { + pdest->val = bit0.val; + } + num++; + pdest++; + } + size++; + psrc++; + } + *translated_size = size; + *item_num = num; +} + +static esp_err_t led_strip_rmt_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) +{ + led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base); + ESP_RETURN_ON_FALSE(index < rmt_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of the maximum number of leds"); + uint32_t start = index * rmt_strip->bytes_per_pixel; + // In thr order of GRB + rmt_strip->buffer[start + 0] = green & 0xFF; + rmt_strip->buffer[start + 1] = red & 0xFF; + rmt_strip->buffer[start + 2] = blue & 0xFF; + if (rmt_strip->bytes_per_pixel > 3) { + rmt_strip->buffer[start + 3] = 0; + } + return ESP_OK; +} + +static esp_err_t led_strip_rmt_refresh(led_strip_t *strip) +{ + led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base); + ESP_RETURN_ON_ERROR(rmt_write_sample(rmt_strip->rmt_channel, rmt_strip->buffer, rmt_strip->strip_len * rmt_strip->bytes_per_pixel, true), TAG, + "transmit RMT samples failed"); + vTaskDelay(pdMS_TO_TICKS(LED_STRIP_RESET_MS)); + return ESP_OK; +} + +static esp_err_t led_strip_rmt_clear(led_strip_t *strip) +{ + led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base); + // Write zero to turn off all LEDs + memset(rmt_strip->buffer, 0, rmt_strip->strip_len * rmt_strip->bytes_per_pixel); + return led_strip_rmt_refresh(strip); +} + +static esp_err_t led_strip_rmt_del(led_strip_t *strip) +{ + led_strip_rmt_obj *rmt_strip = __containerof(strip, led_strip_rmt_obj, base); + ESP_RETURN_ON_ERROR(rmt_driver_uninstall(rmt_strip->rmt_channel), TAG, "uninstall RMT driver failed"); + free(rmt_strip); + return ESP_OK; +} + +esp_err_t led_strip_new_rmt_device(const led_strip_config_t *led_config, const led_strip_rmt_config_t *dev_config, led_strip_handle_t *ret_strip) +{ + led_strip_rmt_obj *rmt_strip = NULL; + esp_err_t ret = ESP_OK; + ESP_RETURN_ON_FALSE(led_config && dev_config && ret_strip, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, TAG, "invalid led_pixel_format"); + ESP_RETURN_ON_FALSE(dev_config->flags.with_dma == 0, ESP_ERR_NOT_SUPPORTED, TAG, "DMA is not supported"); + + uint8_t bytes_per_pixel = 3; + if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) { + bytes_per_pixel = 4; + } else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) { + bytes_per_pixel = 3; + } else { + assert(false); + } + + // allocate memory for led_strip object + rmt_strip = calloc(1, sizeof(led_strip_rmt_obj) + led_config->max_leds * bytes_per_pixel); + ESP_RETURN_ON_FALSE(rmt_strip, ESP_ERR_NO_MEM, TAG, "request memory for les_strip failed"); + + // install RMT channel driver + rmt_config_t config = RMT_DEFAULT_CONFIG_TX(led_config->strip_gpio_num, dev_config->rmt_channel); + // set the minimal clock division because the LED strip needs a high clock resolution + config.clk_div = 2; + + uint8_t mem_block_num = 2; + // override the default value if the user specify the mem block size + if (dev_config->mem_block_symbols) { + mem_block_num = (dev_config->mem_block_symbols + LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS / 2) / LED_STRIP_RMT_DEFAULT_MEM_BLOCK_SYMBOLS; + } + config.mem_block_num = mem_block_num; + + ESP_GOTO_ON_ERROR(rmt_config(&config), err, TAG, "RMT config failed"); + ESP_GOTO_ON_ERROR(rmt_driver_install(config.channel, 0, 0), err, TAG, "RMT install failed"); + + uint32_t counter_clk_hz = 0; + rmt_get_counter_clock((rmt_channel_t)dev_config->rmt_channel, &counter_clk_hz); + // ns -> ticks + float ratio = (float)counter_clk_hz / 1e9; + if (led_config->led_model == LED_MODEL_WS2812) { + led_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS); + led_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS); + led_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS); + led_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS); + } else if (led_config->led_model == LED_MODEL_SK6812) { + led_t0h_ticks = (uint32_t)(ratio * SK6812_T0H_NS); + led_t0l_ticks = (uint32_t)(ratio * SK6812_T0L_NS); + led_t1h_ticks = (uint32_t)(ratio * SK6812_T1H_NS); + led_t1l_ticks = (uint32_t)(ratio * SK6812_T1L_NS); + } else { + assert(false); + } + + // adapter to translates the LES strip date frame into RMT symbols + rmt_translator_init((rmt_channel_t)dev_config->rmt_channel, ws2812_rmt_adapter); + + rmt_strip->bytes_per_pixel = bytes_per_pixel; + rmt_strip->rmt_channel = (rmt_channel_t)dev_config->rmt_channel; + rmt_strip->strip_len = led_config->max_leds; + rmt_strip->base.set_pixel = led_strip_rmt_set_pixel; + rmt_strip->base.refresh = led_strip_rmt_refresh; + rmt_strip->base.clear = led_strip_rmt_clear; + rmt_strip->base.del = led_strip_rmt_del; + + *ret_strip = &rmt_strip->base; + return ESP_OK; + +err: + if (rmt_strip) { + free(rmt_strip); + } + return ret; +} diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.c b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.c new file mode 100644 index 000000000..d352ac07f --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.c @@ -0,0 +1,146 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_check.h" +#include "led_strip_rmt_encoder.h" + +static const char *TAG = "led_rmt_encoder"; + +typedef struct { + rmt_encoder_t base; + rmt_encoder_t *bytes_encoder; + rmt_encoder_t *copy_encoder; + int state; + rmt_symbol_word_t reset_code; +} rmt_led_strip_encoder_t; + +static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state) +{ + rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); + rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder; + rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder; + rmt_encode_state_t session_state = 0; + rmt_encode_state_t state = 0; + size_t encoded_symbols = 0; + switch (led_encoder->state) { + case 0: // send RGB data + encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state); + if (session_state & RMT_ENCODING_COMPLETE) { + led_encoder->state = 1; // switch to next state when current encoding session finished + } + if (session_state & RMT_ENCODING_MEM_FULL) { + state |= RMT_ENCODING_MEM_FULL; + goto out; // yield if there's no free space for encoding artifacts + } + // fall-through + case 1: // send reset code + encoded_symbols += copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code, + sizeof(led_encoder->reset_code), &session_state); + if (session_state & RMT_ENCODING_COMPLETE) { + led_encoder->state = 0; // back to the initial encoding session + state |= RMT_ENCODING_COMPLETE; + } + if (session_state & RMT_ENCODING_MEM_FULL) { + state |= RMT_ENCODING_MEM_FULL; + goto out; // yield if there's no free space for encoding artifacts + } + } +out: + *ret_state = state; + return encoded_symbols; +} + +static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder) +{ + rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); + rmt_del_encoder(led_encoder->bytes_encoder); + rmt_del_encoder(led_encoder->copy_encoder); + free(led_encoder); + return ESP_OK; +} + +static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder) +{ + rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base); + rmt_encoder_reset(led_encoder->bytes_encoder); + rmt_encoder_reset(led_encoder->copy_encoder); + led_encoder->state = 0; + return ESP_OK; +} + +esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder) +{ + esp_err_t ret = ESP_OK; + rmt_led_strip_encoder_t *led_encoder = NULL; + ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + ESP_GOTO_ON_FALSE(config->led_model < LED_MODEL_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid led model"); + led_encoder = calloc(1, sizeof(rmt_led_strip_encoder_t)); + ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder"); + led_encoder->base.encode = rmt_encode_led_strip; + led_encoder->base.del = rmt_del_led_strip_encoder; + led_encoder->base.reset = rmt_led_strip_encoder_reset; + rmt_bytes_encoder_config_t bytes_encoder_config; + if (config->led_model == LED_MODEL_SK6812) { + bytes_encoder_config = (rmt_bytes_encoder_config_t) { + .bit0 = { + .level0 = 1, + .duration0 = 0.3 * config->resolution / 1000000, // T0H=0.3us + .level1 = 0, + .duration1 = 0.9 * config->resolution / 1000000, // T0L=0.9us + }, + .bit1 = { + .level0 = 1, + .duration0 = 0.6 * config->resolution / 1000000, // T1H=0.6us + .level1 = 0, + .duration1 = 0.6 * config->resolution / 1000000, // T1L=0.6us + }, + .flags.msb_first = 1 // SK6812 transfer bit order: G7...G0R7...R0B7...B0(W7...W0) + }; + } else if (config->led_model == LED_MODEL_WS2812) { + // different led strip might have its own timing requirements, following parameter is for WS2812 + bytes_encoder_config = (rmt_bytes_encoder_config_t) { + .bit0 = { + .level0 = 1, + .duration0 = 0.3 * config->resolution / 1000000, // T0H=0.3us + .level1 = 0, + .duration1 = 0.9 * config->resolution / 1000000, // T0L=0.9us + }, + .bit1 = { + .level0 = 1, + .duration0 = 0.9 * config->resolution / 1000000, // T1H=0.9us + .level1 = 0, + .duration1 = 0.3 * config->resolution / 1000000, // T1L=0.3us + }, + .flags.msb_first = 1 // WS2812 transfer bit order: G7...G0R7...R0B7...B0 + }; + } else { + assert(false); + } + ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder), err, TAG, "create bytes encoder failed"); + rmt_copy_encoder_config_t copy_encoder_config = {}; + ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &led_encoder->copy_encoder), err, TAG, "create copy encoder failed"); + + uint32_t reset_ticks = config->resolution / 1000000 * 50 / 2; // reset code duration defaults to 50us + led_encoder->reset_code = (rmt_symbol_word_t) { + .level0 = 0, + .duration0 = reset_ticks, + .level1 = 0, + .duration1 = reset_ticks, + }; + *ret_encoder = &led_encoder->base; + return ESP_OK; +err: + if (led_encoder) { + if (led_encoder->bytes_encoder) { + rmt_del_encoder(led_encoder->bytes_encoder); + } + if (led_encoder->copy_encoder) { + rmt_del_encoder(led_encoder->copy_encoder); + } + free(led_encoder); + } + return ret; +} diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.h b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.h new file mode 100644 index 000000000..ba71e60ab --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_encoder.h @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "driver/rmt_encoder.h" +#include "led_strip_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Type of led strip encoder configuration + */ +typedef struct { + uint32_t resolution; /*!< Encoder resolution, in Hz */ + led_model_t led_model; /*!< LED model */ +} led_strip_encoder_config_t; + +/** + * @brief Create RMT encoder for encoding LED strip pixels into RMT symbols + * + * @param[in] config Encoder configuration + * @param[out] ret_encoder Returned encoder handle + * @return + * - ESP_ERR_INVALID_ARG for any invalid arguments + * - ESP_ERR_NO_MEM out of memory when creating led strip encoder + * - ESP_OK if creating encoder successfully + */ +esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder); + +#ifdef __cplusplus +} +#endif diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_ws2812.c b/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_ws2812.c deleted file mode 100644 index fd1746cad..000000000 --- a/hw/bsp/espressif/components/led_strip/src/led_strip_rmt_ws2812.c +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// 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. -#include -#include -#include -#include "esp_log.h" -#include "esp_attr.h" -#include "led_strip.h" -#include "driver/rmt.h" - -static const char *TAG = "ws2812"; -#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \ - do \ - { \ - if (!(a)) \ - { \ - ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ - ret = ret_value; \ - goto goto_tag; \ - } \ - } while (0) - -#define WS2812_T0H_NS (350) -#define WS2812_T0L_NS (1000) -#define WS2812_T1H_NS (1000) -#define WS2812_T1L_NS (350) -#define WS2812_RESET_US (280) - -static uint32_t ws2812_t0h_ticks = 0; -static uint32_t ws2812_t1h_ticks = 0; -static uint32_t ws2812_t0l_ticks = 0; -static uint32_t ws2812_t1l_ticks = 0; - -typedef struct { - led_strip_t parent; - rmt_channel_t rmt_channel; - uint32_t strip_len; - uint8_t buffer[0]; -} ws2812_t; - -/** - * @brief Convert RGB data to RMT format. - * - * @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t) - * - * @param[in] src: source data, to converted to RMT format - * @param[in] dest: place where to store the convert result - * @param[in] src_size: size of source data - * @param[in] wanted_num: number of RMT items that want to get - * @param[out] translated_size: number of source data that got converted - * @param[out] item_num: number of RMT items which are converted from source data - */ -static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size, - size_t wanted_num, size_t *translated_size, size_t *item_num) -{ - if (src == NULL || dest == NULL) { - *translated_size = 0; - *item_num = 0; - return; - } - const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0 - const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1 - size_t size = 0; - size_t num = 0; - uint8_t *psrc = (uint8_t *)src; - rmt_item32_t *pdest = dest; - while (size < src_size && num < wanted_num) { - for (int i = 0; i < 8; i++) { - // MSB first - if (*psrc & (1 << (7 - i))) { - pdest->val = bit1.val; - } else { - pdest->val = bit0.val; - } - num++; - pdest++; - } - size++; - psrc++; - } - *translated_size = size; - *item_num = num; -} - -static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG); - uint32_t start = index * 3; - // In thr order of GRB - ws2812->buffer[start + 0] = green & 0xFF; - ws2812->buffer[start + 1] = red & 0xFF; - ws2812->buffer[start + 2] = blue & 0xFF; - return ESP_OK; -err: - return ret; -} - -static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms) -{ - esp_err_t ret = ESP_OK; - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK, - "transmit RMT samples failed", err, ESP_FAIL); - return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms)); -err: - return ret; -} - -static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - // Write zero to turn off all leds - memset(ws2812->buffer, 0, ws2812->strip_len * 3); - return ws2812_refresh(strip, timeout_ms); -} - -static esp_err_t ws2812_del(led_strip_t *strip) -{ - ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent); - free(ws2812); - return ESP_OK; -} - -led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config) -{ - led_strip_t *ret = NULL; - STRIP_CHECK(config, "configuration can't be null", err, NULL); - - // 24 bits per led - uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3; - ws2812_t *ws2812 = calloc(1, ws2812_size); - STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL); - - uint32_t counter_clk_hz = 0; - STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK, - "get rmt counter clock failed", err, NULL); - // ns -> ticks - float ratio = (float)counter_clk_hz / 1e9; - ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS); - ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS); - ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS); - ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS); - - // set ws2812 to rmt adapter - rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter); - - ws2812->rmt_channel = (rmt_channel_t)config->dev; - ws2812->strip_len = config->max_leds; - - ws2812->parent.set_pixel = ws2812_set_pixel; - ws2812->parent.refresh = ws2812_refresh; - ws2812->parent.clear = ws2812_clear; - ws2812->parent.del = ws2812_del; - - return &ws2812->parent; -err: - return ret; -} diff --git a/hw/bsp/espressif/components/led_strip/src/led_strip_spi_dev.c b/hw/bsp/espressif/components/led_strip/src/led_strip_spi_dev.c new file mode 100644 index 000000000..12ea8fbf3 --- /dev/null +++ b/hw/bsp/espressif/components/led_strip/src/led_strip_spi_dev.c @@ -0,0 +1,209 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include "esp_log.h" +#include "esp_check.h" +#include "esp_rom_gpio.h" +#include "soc/spi_periph.h" +#include "led_strip.h" +#include "led_strip_interface.h" +#include "hal/spi_hal.h" + +#define LED_STRIP_SPI_DEFAULT_RESOLUTION (2.5 * 1000 * 1000) // 2.5MHz resolution +#define LED_STRIP_SPI_DEFAULT_TRANS_QUEUE_SIZE 4 + +#define SPI_BYTES_PER_COLOR_BYTE 3 +#define SPI_BITS_PER_COLOR_BYTE (SPI_BYTES_PER_COLOR_BYTE * 8) + +static const char *TAG = "led_strip_spi"; + +typedef struct { + led_strip_t base; + spi_host_device_t spi_host; + spi_device_handle_t spi_device; + uint32_t strip_len; + uint8_t bytes_per_pixel; + uint8_t pixel_buf[]; +} led_strip_spi_obj; + +// please make sure to zero-initialize the buf before calling this function +static void __led_strip_spi_bit(uint8_t data, uint8_t *buf) +{ + // Each color of 1 bit is represented by 3 bits of SPI, low_level:100 ,high_level:110 + // So a color byte occupies 3 bytes of SPI. + *(buf + 2) |= data & BIT(0) ? BIT(2) | BIT(1) : BIT(2); + *(buf + 2) |= data & BIT(1) ? BIT(5) | BIT(4) : BIT(5); + *(buf + 2) |= data & BIT(2) ? BIT(7) : 0x00; + *(buf + 1) |= BIT(0); + *(buf + 1) |= data & BIT(3) ? BIT(3) | BIT(2) : BIT(3); + *(buf + 1) |= data & BIT(4) ? BIT(6) | BIT(5) : BIT(6); + *(buf + 0) |= data & BIT(5) ? BIT(1) | BIT(0) : BIT(1); + *(buf + 0) |= data & BIT(6) ? BIT(4) | BIT(3) : BIT(4); + *(buf + 0) |= data & BIT(7) ? BIT(7) | BIT(6) : BIT(7); +} + +static esp_err_t led_strip_spi_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue) +{ + led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base); + ESP_RETURN_ON_FALSE(index < spi_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs"); + // LED_PIXEL_FORMAT_GRB takes 72bits(9bytes) + uint32_t start = index * spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE; + memset(spi_strip->pixel_buf + start, 0, spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE); + __led_strip_spi_bit(green, &spi_strip->pixel_buf[start]); + __led_strip_spi_bit(red, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE]); + __led_strip_spi_bit(blue, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 2]); + if (spi_strip->bytes_per_pixel > 3) { + __led_strip_spi_bit(0, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 3]); + } + return ESP_OK; +} + +static esp_err_t led_strip_spi_set_pixel_rgbw(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue, uint32_t white) +{ + led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base); + ESP_RETURN_ON_FALSE(index < spi_strip->strip_len, ESP_ERR_INVALID_ARG, TAG, "index out of maximum number of LEDs"); + ESP_RETURN_ON_FALSE(spi_strip->bytes_per_pixel == 4, ESP_ERR_INVALID_ARG, TAG, "wrong LED pixel format, expected 4 bytes per pixel"); + // LED_PIXEL_FORMAT_GRBW takes 96bits(12bytes) + uint32_t start = index * spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE; + // SK6812 component order is GRBW + memset(spi_strip->pixel_buf + start, 0, spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE); + __led_strip_spi_bit(green, &spi_strip->pixel_buf[start]); + __led_strip_spi_bit(red, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE]); + __led_strip_spi_bit(blue, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 2]); + __led_strip_spi_bit(white, &spi_strip->pixel_buf[start + SPI_BYTES_PER_COLOR_BYTE * 3]); + + return ESP_OK; +} + +static esp_err_t led_strip_spi_refresh(led_strip_t *strip) +{ + led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base); + spi_transaction_t tx_conf; + memset(&tx_conf, 0, sizeof(tx_conf)); + + tx_conf.length = spi_strip->strip_len * spi_strip->bytes_per_pixel * SPI_BITS_PER_COLOR_BYTE; + tx_conf.tx_buffer = spi_strip->pixel_buf; + tx_conf.rx_buffer = NULL; + ESP_RETURN_ON_ERROR(spi_device_transmit(spi_strip->spi_device, &tx_conf), TAG, "transmit pixels by SPI failed"); + + return ESP_OK; +} + +static esp_err_t led_strip_spi_clear(led_strip_t *strip) +{ + led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base); + //Write zero to turn off all leds + memset(spi_strip->pixel_buf, 0, spi_strip->strip_len * spi_strip->bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE); + uint8_t *buf = spi_strip->pixel_buf; + for (int index = 0; index < spi_strip->strip_len * spi_strip->bytes_per_pixel; index++) { + __led_strip_spi_bit(0, buf); + buf += SPI_BYTES_PER_COLOR_BYTE; + } + + return led_strip_spi_refresh(strip); +} + +static esp_err_t led_strip_spi_del(led_strip_t *strip) +{ + led_strip_spi_obj *spi_strip = __containerof(strip, led_strip_spi_obj, base); + + ESP_RETURN_ON_ERROR(spi_bus_remove_device(spi_strip->spi_device), TAG, "delete spi device failed"); + ESP_RETURN_ON_ERROR(spi_bus_free(spi_strip->spi_host), TAG, "free spi bus failed"); + + free(spi_strip); + return ESP_OK; +} + +esp_err_t led_strip_new_spi_device(const led_strip_config_t *led_config, const led_strip_spi_config_t *spi_config, led_strip_handle_t *ret_strip) +{ + led_strip_spi_obj *spi_strip = NULL; + esp_err_t ret = ESP_OK; + ESP_GOTO_ON_FALSE(led_config && spi_config && ret_strip, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + ESP_GOTO_ON_FALSE(led_config->led_pixel_format < LED_PIXEL_FORMAT_INVALID, ESP_ERR_INVALID_ARG, err, TAG, "invalid led_pixel_format"); + uint8_t bytes_per_pixel = 3; + if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRBW) { + bytes_per_pixel = 4; + } else if (led_config->led_pixel_format == LED_PIXEL_FORMAT_GRB) { + bytes_per_pixel = 3; + } else { + assert(false); + } + uint32_t mem_caps = MALLOC_CAP_DEFAULT; + if (spi_config->flags.with_dma) { + // DMA buffer must be placed in internal SRAM + mem_caps |= MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA; + } + spi_strip = heap_caps_calloc(1, sizeof(led_strip_spi_obj) + led_config->max_leds * bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE, mem_caps); + + ESP_GOTO_ON_FALSE(spi_strip, ESP_ERR_NO_MEM, err, TAG, "no mem for spi strip"); + + spi_strip->spi_host = spi_config->spi_bus; + // for backward compatibility, if the user does not set the clk_src, use the default value + spi_clock_source_t clk_src = SPI_CLK_SRC_DEFAULT; + if (spi_config->clk_src) { + clk_src = spi_config->clk_src; + } + + spi_bus_config_t spi_bus_cfg = { + .mosi_io_num = led_config->strip_gpio_num, + //Only use MOSI to generate the signal, set -1 when other pins are not used. + .miso_io_num = -1, + .sclk_io_num = -1, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = led_config->max_leds * bytes_per_pixel * SPI_BYTES_PER_COLOR_BYTE, + }; + ESP_GOTO_ON_ERROR(spi_bus_initialize(spi_strip->spi_host, &spi_bus_cfg, spi_config->flags.with_dma ? SPI_DMA_CH_AUTO : SPI_DMA_DISABLED), err, TAG, "create SPI bus failed"); + + if (led_config->flags.invert_out == true) { + esp_rom_gpio_connect_out_signal(led_config->strip_gpio_num, spi_periph_signal[spi_strip->spi_host].spid_out, true, false); + } + + spi_device_interface_config_t spi_dev_cfg = { + .clock_source = clk_src, + .command_bits = 0, + .address_bits = 0, + .dummy_bits = 0, + .clock_speed_hz = LED_STRIP_SPI_DEFAULT_RESOLUTION, + .mode = 0, + //set -1 when CS is not used + .spics_io_num = -1, + .queue_size = LED_STRIP_SPI_DEFAULT_TRANS_QUEUE_SIZE, + }; + + ESP_GOTO_ON_ERROR(spi_bus_add_device(spi_strip->spi_host, &spi_dev_cfg, &spi_strip->spi_device), err, TAG, "Failed to add spi device"); + + int clock_resolution_khz = 0; + spi_device_get_actual_freq(spi_strip->spi_device, &clock_resolution_khz); + // TODO: ideally we should decide the SPI_BYTES_PER_COLOR_BYTE by the real clock resolution + // But now, let's fixed the resolution, the downside is, we don't support a clock source whose frequency is not multiple of LED_STRIP_SPI_DEFAULT_RESOLUTION + ESP_GOTO_ON_FALSE(clock_resolution_khz == LED_STRIP_SPI_DEFAULT_RESOLUTION / 1000, ESP_ERR_NOT_SUPPORTED, err, + TAG, "unsupported clock resolution:%dKHz", clock_resolution_khz); + + spi_strip->bytes_per_pixel = bytes_per_pixel; + spi_strip->strip_len = led_config->max_leds; + spi_strip->base.set_pixel = led_strip_spi_set_pixel; + spi_strip->base.set_pixel_rgbw = led_strip_spi_set_pixel_rgbw; + spi_strip->base.refresh = led_strip_spi_refresh; + spi_strip->base.clear = led_strip_spi_clear; + spi_strip->base.del = led_strip_spi_del; + + *ret_strip = &spi_strip->base; + return ESP_OK; +err: + if (spi_strip) { + if (spi_strip->spi_device) { + spi_bus_remove_device(spi_strip->spi_device); + } + if (spi_strip->spi_host) { + spi_bus_free(spi_strip->spi_host); + } + free(spi_strip); + } + return ret; +} diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 539a776a6..ff3393cfd 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -211,7 +211,6 @@ function(family_configure_common TARGET RTOS) target_link_options(${TARGET} PUBLIC "LINKER:--map=$.map") endif() - # ETM Trace option if (TRACE_ETM STREQUAL "1") target_compile_definitions(${TARGET} PUBLIC TRACE_ETM) diff --git a/hw/bsp/mcx/boards/bunny-brain/board.cmake b/hw/bsp/mcx/boards/bunny-brain/board.cmake deleted file mode 100644 index 8c3280743..000000000 --- a/hw/bsp/mcx/boards/bunny-brain/board.cmake +++ /dev/null @@ -1,21 +0,0 @@ -set(MCU_VARIANT MCXN947) -set(MCU_CORE MCXN947_cm33_core0) - -set(JLINK_DEVICE MCXN947_M33_0) -set(PYOCD_TARGET MCXN947) -set(NXPLINK_DEVICE MCXN947:MCXN947) - -set(PORT 1) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - CPU_MCXN947VDF_cm33_core0 - BOARD_TUD_RHPORT=${PORT} - # port 0 is fullspeed, port 1 is highspeed - BOARD_TUD_MAX_SPEED=$ - ) - target_sources(${TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/clock_config.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/pin_mux.c - ) -endfunction() diff --git a/hw/bsp/mcx/boards/bunny-brain/board.h b/hw/bsp/mcx/boards/bunny-brain/board.h deleted file mode 100644 index eae98bfa7..000000000 --- a/hw/bsp/mcx/boards/bunny-brain/board.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_GPIO GPIO3 -#define LED_CLK kCLOCK_Gpio3 -#define LED_PIN 4 // red -#define LED_STATE_ON 0 - -// WAKE button (Dummy, use unused pin -#define BUTTON_GPIO GPIO0 -#define BUTTON_CLK kCLOCK_Gpio0 -#define BUTTON_PIN 6 -#define BUTTON_STATE_ACTIVE 0 - -// UART -#define UART_DEV LPUART4 - -static inline void board_uart_init_clock(void) { - /* attach FRO 12M to FLEXCOMM4 */ - CLOCK_SetClkDiv(kCLOCK_DivFlexcom4Clk, 1u); - CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4); - RESET_ClearPeripheralReset(kFC4_RST_SHIFT_RSTn); -} - -//#define UART_RX_PINMUX 0, 24, IOCON_PIO_DIG_FUNC1_EN -//#define UART_TX_PINMUX 0, 25, IOCON_PIO_DIG_FUNC1_EN - -// XTAL -#define XTAL0_CLK_HZ (24 * 1000 * 1000U) - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/hw/bsp/mcx/boards/bunny-brain/board.mk b/hw/bsp/mcx/boards/bunny-brain/board.mk deleted file mode 100644 index aaad5e73e..000000000 --- a/hw/bsp/mcx/boards/bunny-brain/board.mk +++ /dev/null @@ -1,11 +0,0 @@ -MCU_VARIANT = MCXN947 -MCU_CORE = MCXN947_cm33_core0 -PORT ?= 1 - -CFLAGS += -DCPU_MCXN947VDF_cm33_core0 - -JLINK_DEVICE = MCXN947_M33_0 -PYOCD_TARGET = MCXN947 - -# flash using pyocd -flash: flash-jlink diff --git a/hw/bsp/mcx/boards/bunny-brain/clock_config.c b/hw/bsp/mcx/boards/bunny-brain/clock_config.c deleted file mode 100644 index 37d2b4dfc..000000000 --- a/hw/bsp/mcx/boards/bunny-brain/clock_config.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2022 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ -/* - * How to setup clock using clock driver functions: - * - * 1. Setup clock sources. - * - * 2. Set up wait states of the flash. - * - * 3. Set up all dividers. - * - * 4. Set up all selectors to provide selected clocks. - * - */ - -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!GlobalInfo -product: Clocks v10.0 -processor: MCXN947 -package_id: MCXN947VDF -mcu_data: ksdk2_0 -processor_version: 0.12.3 -board: MCX-N9XX-EVK - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -#include "clock_config.h" -#include "fsl_clock.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/******************************************************************************* - * Variables - ******************************************************************************/ -/* System clock frequency. */ -// extern uint32_t SystemCoreClock; - -/******************************************************************************* - ************************ BOARD_InitBootClocks function ************************ - ******************************************************************************/ -void BOARD_InitBootClocks(void) -{ - BOARD_BootClockPLL150M(); -} - -/******************************************************************************* - ******************** Configuration BOARD_BootClockFRO12M ********************** - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockFRO12M -outputs: -- {id: CLK_144M_clock.outFreq, value: 144 MHz} -- {id: CLK_48M_clock.outFreq, value: 48 MHz} -- {id: FRO_12M_clock.outFreq, value: 12 MHz} -- {id: MAIN_clock.outFreq, value: 12 MHz} -- {id: Slow_clock.outFreq, value: 3 MHz} -- {id: System_clock.outFreq, value: 12 MHz} -- {id: gdet_clock.outFreq, value: 48 MHz} -- {id: trng_clock.outFreq, value: 48 MHz} -settings: -- {id: SCGMode, value: SIRC} -- {id: SCG.SCSSEL.sel, value: SCG.SIRC} -- {id: SCG_FIRCCSR_FIRCEN_CFG, value: Disabled} -- {id: SYSCON.FREQMEREFCLKSEL.sel, value: SYSCON.evtg_out0a} -- {id: SYSCON.FREQMETARGETCLKSEL.sel, value: SYSCON.evtg_out0a} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockFRO12M configuration - ******************************************************************************/ -/******************************************************************************* - * Code for BOARD_BootClockFRO12M configuration - ******************************************************************************/ -void BOARD_BootClockFRO12M(void) -{ - /*!< Enable SCG clock */ - CLOCK_EnableClock(kCLOCK_Scg); - - /*!< Set up clock selectors - Attach clocks to the peripheries */ - CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO12M */ - - /*!< Set up dividers */ - CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U); /*!< Set AHBCLKDIV divider to value 1 */ - - /* Set SystemCoreClock variable */ - SystemCoreClock = BOARD_BOOTCLOCKFRO12M_CORE_CLOCK; -} - -/******************************************************************************* - ******************* Configuration BOARD_BootClockFROHF48M ********************* - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockFROHF48M -outputs: -- {id: CLK_144M_clock.outFreq, value: 144 MHz} -- {id: CLK_48M_clock.outFreq, value: 48 MHz} -- {id: FRO_12M_clock.outFreq, value: 12 MHz} -- {id: FRO_HF_clock.outFreq, value: 48 MHz} -- {id: MAIN_clock.outFreq, value: 48 MHz} -- {id: Slow_clock.outFreq, value: 12 MHz} -- {id: System_clock.outFreq, value: 48 MHz} -- {id: gdet_clock.outFreq, value: 48 MHz} -- {id: trng_clock.outFreq, value: 48 MHz} -settings: -- {id: SYSCON.FLEXCAN0CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FLEXCAN1CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FREQMEREFCLKSEL.sel, value: SYSCON.evtg_out0a} -- {id: SYSCON.FREQMETARGETCLKSEL.sel, value: SYSCON.evtg_out0a} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockFROHF48M configuration - ******************************************************************************/ -/******************************************************************************* - * Code for BOARD_BootClockFROHF48M configuration - ******************************************************************************/ -void BOARD_BootClockFROHF48M(void) -{ - /*!< Enable SCG clock */ - CLOCK_EnableClock(kCLOCK_Scg); - - CLOCK_SetupFROHFClocking(48000000U); /*!< Enable FRO HF(48MHz) output */ - - /*!< Set up clock selectors - Attach clocks to the peripheries */ - CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO_HF */ - - /*!< Set up dividers */ - CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U); /*!< Set AHBCLKDIV divider to value 1 */ - - /* Set SystemCoreClock variable */ - SystemCoreClock = BOARD_BOOTCLOCKFROHF48M_CORE_CLOCK; -} - -/******************************************************************************* - ******************* Configuration BOARD_BootClockFROHF144M ******************** - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockFROHF144M -outputs: -- {id: CLK_144M_clock.outFreq, value: 144 MHz} -- {id: CLK_48M_clock.outFreq, value: 48 MHz} -- {id: FRO_12M_clock.outFreq, value: 12 MHz} -- {id: FRO_HF_clock.outFreq, value: 144 MHz} -- {id: MAIN_clock.outFreq, value: 144 MHz} -- {id: Slow_clock.outFreq, value: 18 MHz} -- {id: System_clock.outFreq, value: 72 MHz} -- {id: gdet_clock.outFreq, value: 48 MHz} -- {id: trng_clock.outFreq, value: 48 MHz} -settings: -- {id: SYSCON.AHBCLKDIV.scale, value: '2', locked: true} -- {id: SYSCON.FLEXCAN0CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FLEXCAN1CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FREQMEREFCLKSEL.sel, value: SYSCON.evtg_out0a} -- {id: SYSCON.FREQMETARGETCLKSEL.sel, value: SYSCON.evtg_out0a} -sources: -- {id: SCG.FIRC.outFreq, value: 144 MHz} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockFROHF144M configuration - ******************************************************************************/ -/******************************************************************************* - * Code for BOARD_BootClockFROHF144M configuration - ******************************************************************************/ -void BOARD_BootClockFROHF144M(void) -{ - /*!< Enable SCG clock */ - CLOCK_EnableClock(kCLOCK_Scg); - - CLOCK_SetupFROHFClocking(144000000U); /*!< Enable FRO HF(144MHz) output */ - - /*!< Set up clock selectors - Attach clocks to the peripheries */ - CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO_HF */ - - /*!< Set up dividers */ - CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 2U); /*!< Set AHBCLKDIV divider to value 2 */ - - /* Set SystemCoreClock variable */ - SystemCoreClock = BOARD_BOOTCLOCKFROHF144M_CORE_CLOCK; -} - -/******************************************************************************* - ******************** Configuration BOARD_BootClockPLL150M ********************* - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockPLL150M -called_from_default_init: true -outputs: -- {id: CLK_144M_clock.outFreq, value: 144 MHz} -- {id: CLK_48M_clock.outFreq, value: 48 MHz} -- {id: FRO_12M_clock.outFreq, value: 12 MHz} -- {id: FRO_HF_clock.outFreq, value: 48 MHz} -- {id: MAIN_clock.outFreq, value: 150 MHz} -- {id: PLL0_CLK_clock.outFreq, value: 150 MHz} -- {id: Slow_clock.outFreq, value: 37.5 MHz} -- {id: System_clock.outFreq, value: 150 MHz} -- {id: gdet_clock.outFreq, value: 48 MHz} -- {id: trng_clock.outFreq, value: 48 MHz} -settings: -- {id: PLL0_Mode, value: Normal} -- {id: RunPowerMode, value: OD} -- {id: SCGMode, value: PLL0} -- {id: SCG.PLL0M_MULT.scale, value: '50', locked: true} -- {id: SCG.PLL0SRCSEL.sel, value: SCG.FIRC_48M} -- {id: SCG.PLL0_NDIV.scale, value: '8', locked: true} -- {id: SCG.SCSSEL.sel, value: SCG.PLL0_CLK} -- {id: SYSCON.FLEXCAN0CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FLEXCAN1CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FREQMEREFCLKSEL.sel, value: SYSCON.evtg_out0a} -- {id: SYSCON.FREQMETARGETCLKSEL.sel, value: SYSCON.evtg_out0a} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockPLL150M configuration - ******************************************************************************/ -/******************************************************************************* - * Code for BOARD_BootClockPLL150M configuration - ******************************************************************************/ -void BOARD_BootClockPLL150M(void) -{ - /*!< Enable SCG clock */ - CLOCK_EnableClock(kCLOCK_Scg); - - CLOCK_SetupFROHFClocking(48000000U); /*!< Enable FRO HF(48MHz) output */ - - /*!< Set up PLL0 */ - const pll_setup_t pll0Setup = { - .pllctrl = SCG_APLLCTRL_SOURCE(1U) | SCG_APLLCTRL_SELI(27U) | SCG_APLLCTRL_SELP(13U), - .pllndiv = SCG_APLLNDIV_NDIV(8U), - .pllpdiv = SCG_APLLPDIV_PDIV(1U), - .pllmdiv = SCG_APLLMDIV_MDIV(50U), - .pllRate = 150000000U - }; - CLOCK_SetPLL0Freq(&pll0Setup); /*!< Configure PLL0 to the desired values */ - CLOCK_SetPll0MonitorMode(kSCG_Pll0MonitorDisable); /* Pll0 Monitor is disabled */ - - /*!< Set up clock selectors - Attach clocks to the peripheries */ - CLOCK_AttachClk(kPLL0_to_MAIN_CLK); /*!< Switch MAIN_CLK to PLL0 */ - - /*!< Set up dividers */ - CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U); /*!< Set AHBCLKDIV divider to value 1 */ - - /* Set SystemCoreClock variable */ - SystemCoreClock = BOARD_BOOTCLOCKPLL150M_CORE_CLOCK; -} - -/******************************************************************************* - ******************** Configuration BOARD_BootClockPLL100M ********************* - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockPLL100M -outputs: -- {id: CLK_144M_clock.outFreq, value: 144 MHz} -- {id: CLK_48M_clock.outFreq, value: 48 MHz} -- {id: CLK_IN_clock.outFreq, value: 24 MHz} -- {id: FRO_12M_clock.outFreq, value: 12 MHz} -- {id: MAIN_clock.outFreq, value: 100 MHz} -- {id: PLL1_CLK_clock.outFreq, value: 100 MHz} -- {id: Slow_clock.outFreq, value: 25 MHz} -- {id: System_clock.outFreq, value: 100 MHz} -- {id: gdet_clock.outFreq, value: 48 MHz} -- {id: trng_clock.outFreq, value: 48 MHz} -settings: -- {id: PLL1_Mode, value: Normal} -- {id: SCGMode, value: PLL1} -- {id: SCG.PLL1M_MULT.scale, value: '100', locked: true} -- {id: SCG.PLL1_NDIV.scale, value: '6', locked: true} -- {id: SCG.PLL1_PDIV.scale, value: '4', locked: true} -- {id: SCG.SCSSEL.sel, value: SCG.PLL1_CLK} -- {id: SCG_FIRCCSR_FIRCEN_CFG, value: Disabled} -- {id: SCG_SOSCCSR_SOSCEN_CFG, value: Enabled} -- {id: SYSCON.FREQMEREFCLKSEL.sel, value: SYSCON.evtg_out0a} -- {id: SYSCON.FREQMETARGETCLKSEL.sel, value: SYSCON.evtg_out0a} -sources: -- {id: SCG.SOSC.outFreq, value: 24 MHz, enabled: true} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockPLL100M configuration - ******************************************************************************/ -/******************************************************************************* - * Code for BOARD_BootClockPLL100M configuration - ******************************************************************************/ -void BOARD_BootClockPLL100M(void) -{ - /*!< Enable SCG clock */ - CLOCK_EnableClock(kCLOCK_Scg); - - CLOCK_SetupExtClocking(24000000U); - CLOCK_SetSysOscMonitorMode(kSCG_SysOscMonitorDisable); /* System OSC Clock Monitor is disabled */ - - /*!< Set up PLL1 */ - const pll_setup_t pll1Setup = { - .pllctrl = SCG_SPLLCTRL_SOURCE(0U) | SCG_SPLLCTRL_SELI(53U) | SCG_SPLLCTRL_SELP(26U), - .pllndiv = SCG_SPLLNDIV_NDIV(6U), - .pllpdiv = SCG_SPLLPDIV_PDIV(2U), - .pllmdiv = SCG_SPLLMDIV_MDIV(100U), - .pllRate = 100000000U - }; - CLOCK_SetPLL1Freq(&pll1Setup); /*!< Configure PLL1 to the desired values */ - CLOCK_SetPll1MonitorMode(kSCG_Pll1MonitorDisable); /* Pll1 Monitor is disabled */ - - /*!< Set up clock selectors - Attach clocks to the peripheries */ - CLOCK_AttachClk(kPLL1_to_MAIN_CLK); /*!< Switch MAIN_CLK to PLL1 */ - - /*!< Set up dividers */ - CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U); /*!< Set AHBCLKDIV divider to value 1 */ - - /* Set SystemCoreClock variable */ - SystemCoreClock = BOARD_BOOTCLOCKPLL100M_CORE_CLOCK; -} diff --git a/hw/bsp/mcx/boards/bunny-brain/clock_config.h b/hw/bsp/mcx/boards/bunny-brain/clock_config.h deleted file mode 100644 index c238a0423..000000000 --- a/hw/bsp/mcx/boards/bunny-brain/clock_config.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2022 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ - -#ifndef _CLOCK_CONFIG_H_ -#define _CLOCK_CONFIG_H_ - -#include "fsl_common.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ -#define BOARD_XTAL0_CLK_HZ 24000000U /*!< Board xtal frequency in Hz */ -#define BOARD_XTAL32K_CLK_HZ 32768U /*!< Board xtal32K frequency in Hz */ - -/******************************************************************************* - ************************ BOARD_InitBootClocks function ************************ - ******************************************************************************/ - -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes default configuration of clocks. - * - */ -void BOARD_InitBootClocks(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************** Configuration BOARD_BootClockFRO12M ********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockFRO12M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKFRO12M_CORE_CLOCK 12000000U /*!< Core clock frequency: 12000000Hz */ -#define BOARD_BOOTCLOCKFRO12M_ROSC_CLOCK 0U /*!< ROSC clock frequency: 0Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockFRO12M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockFRO12M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************* Configuration BOARD_BootClockFROHF48M ********************* - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockFROHF48M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKFROHF48M_CORE_CLOCK 48000000U /*!< Core clock frequency: 48000000Hz */ -#define BOARD_BOOTCLOCKFROHF48M_ROSC_CLOCK 0U /*!< ROSC clock frequency: 0Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockFROHF48M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockFROHF48M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************* Configuration BOARD_BootClockFROHF144M ******************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockFROHF144M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKFROHF144M_CORE_CLOCK 144000000U /*!< Core clock frequency: 144000000Hz */ -#define BOARD_BOOTCLOCKFROHF144M_ROSC_CLOCK 0U /*!< ROSC clock frequency: 0Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockFROHF144M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockFROHF144M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************** Configuration BOARD_BootClockPLL150M ********************* - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockPLL150M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKPLL150M_CORE_CLOCK 150000000U /*!< Core clock frequency: 150000000Hz */ -#define BOARD_BOOTCLOCKPLL150M_ROSC_CLOCK 0U /*!< ROSC clock frequency: 0Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockPLL150M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockPLL150M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************** Configuration BOARD_BootClockPLL100M ********************* - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockPLL100M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKPLL100M_CORE_CLOCK 100000000U /*!< Core clock frequency: 100000000Hz */ -#define BOARD_BOOTCLOCKPLL100M_ROSC_CLOCK 0U /*!< ROSC clock frequency: 0Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockPLL100M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockPLL100M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -#endif /* _CLOCK_CONFIG_H_ */ diff --git a/hw/bsp/mcx/boards/bunny-brain/pin_mux.c b/hw/bsp/mcx/boards/bunny-brain/pin_mux.c deleted file mode 100644 index acc2f3e45..000000000 --- a/hw/bsp/mcx/boards/bunny-brain/pin_mux.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2022 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ - -/* clang-format off */ -/* - * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!GlobalInfo -product: Pins v12.0 -processor: MCXN947 -package_id: MCXN947VDF -mcu_data: ksdk2_0 -processor_version: 0.12.3 - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** - */ -/* clang-format on */ - -#include "fsl_common.h" -#include "fsl_port.h" -#include "pin_mux.h" - -/* FUNCTION ************************************************************************************************************ - * - * Function Name : BOARD_InitBootPins - * Description : Calls initialization functions. - * - * END ****************************************************************************************************************/ -void BOARD_InitBootPins(void) -{ - BOARD_InitPins(); -} - -/* clang-format off */ -/* - * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -BOARD_InitPins: -- options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} -- pin_list: - - {pin_num: A1, peripheral: LPFlexcomm4, signal: LPFLEXCOMM_P0, pin_signal: PIO1_8/WUU0_IN10/LPTMR1_ALT3/TRACE_DATA0/FC4_P0/FC5_P4/CT_INP8/SCT0_OUT2/FLEXIO0_D16/PLU_OUT0/ENET0_TXD2/I3C1_SDA/TSI0_CH17/ADC1_A8, - slew_rate: fast, open_drain: disable, drive_strength: low, pull_select: down, pull_enable: disable, passive_filter: disable, pull_value: low, input_buffer: enable, - invert_input: normal} - - {pin_num: B1, peripheral: LPFlexcomm4, signal: LPFLEXCOMM_P1, pin_signal: PIO1_9/TRACE_DATA1/FC4_P1/FC5_P5/CT_INP9/SCT0_OUT3/FLEXIO0_D17/PLU_OUT1/ENET0_TXD3/I3C1_SCL/TSI0_CH18/ADC1_A9, - slew_rate: fast, open_drain: disable, drive_strength: low, pull_select: down, pull_enable: disable, passive_filter: disable, input_buffer: enable, invert_input: normal} - - {pin_num: F14, peripheral: GPIO3, signal: 'GPIO, 4', pin_signal: PIO3_4/FC7_P2/CT_INP18/PWM0_X2/FLEXIO0_D12/SIM1_CLK, slew_rate: fast, open_drain: disable, drive_strength: low, - pull_select: down, pull_enable: disable, input_buffer: enable, invert_input: normal} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** - */ -/* clang-format on */ - -/* FUNCTION ************************************************************************************************************ - * - * Function Name : BOARD_InitPins - * Description : Configures pin routing and optionally pin electrical features. - * - * END ****************************************************************************************************************/ -void BOARD_InitPins(void) -{ - /* Enables the clock for PORT1: Enables clock */ - CLOCK_EnableClock(kCLOCK_Port1); - /* Enables the clock for PORT3: Enables clock */ - CLOCK_EnableClock(kCLOCK_Port3); - - const port_pin_config_t port1_8_pinA1_config = {/* Internal pull-up/down resistor is disabled */ - kPORT_PullDisable, - /* Low internal pull resistor value is selected. */ - kPORT_LowPullResistor, - /* Fast slew rate is configured */ - kPORT_FastSlewRate, - /* Passive input filter is disabled */ - kPORT_PassiveFilterDisable, - /* Open drain output is disabled */ - kPORT_OpenDrainDisable, - /* Low drive strength is configured */ - kPORT_LowDriveStrength, - /* Pin is configured as FC4_P0 */ - kPORT_MuxAlt2, - /* Digital input enabled */ - kPORT_InputBufferEnable, - /* Digital input is not inverted */ - kPORT_InputNormal, - /* Pin Control Register fields [15:0] are not locked */ - kPORT_UnlockRegister}; - /* PORT1_8 (pin A1) is configured as FC4_P0 */ - PORT_SetPinConfig(PORT1, 8U, &port1_8_pinA1_config); - - const port_pin_config_t port1_9_pinB1_config = {/* Internal pull-up/down resistor is disabled */ - kPORT_PullDisable, - /* Low internal pull resistor value is selected. */ - kPORT_LowPullResistor, - /* Fast slew rate is configured */ - kPORT_FastSlewRate, - /* Passive input filter is disabled */ - kPORT_PassiveFilterDisable, - /* Open drain output is disabled */ - kPORT_OpenDrainDisable, - /* Low drive strength is configured */ - kPORT_LowDriveStrength, - /* Pin is configured as FC4_P1 */ - kPORT_MuxAlt2, - /* Digital input enabled */ - kPORT_InputBufferEnable, - /* Digital input is not inverted */ - kPORT_InputNormal, - /* Pin Control Register fields [15:0] are not locked */ - kPORT_UnlockRegister}; - /* PORT1_9 (pin B1) is configured as FC4_P1 */ - PORT_SetPinConfig(PORT1, 9U, &port1_9_pinB1_config); - - const port_pin_config_t port3_4_pinF14_config = {/* Internal pull-up/down resistor is disabled */ - kPORT_PullDisable, - /* Low internal pull resistor value is selected. */ - kPORT_LowPullResistor, - /* Fast slew rate is configured */ - kPORT_FastSlewRate, - /* Passive input filter is disabled */ - kPORT_PassiveFilterDisable, - /* Open drain output is disabled */ - kPORT_OpenDrainDisable, - /* Low drive strength is configured */ - kPORT_LowDriveStrength, - /* Pin is configured as PIO3_4 */ - kPORT_MuxAlt0, - /* Digital input enabled */ - kPORT_InputBufferEnable, - /* Digital input is not inverted */ - kPORT_InputNormal, - /* Pin Control Register fields [15:0] are not locked */ - kPORT_UnlockRegister}; - /* PORT3_4 (pin F14) is configured as PIO3_4 */ - PORT_SetPinConfig(PORT3, 4U, &port3_4_pinF14_config); -} -/*********************************************************************************************************************** - * EOF - **********************************************************************************************************************/ diff --git a/hw/bsp/mcx/boards/bunny-brain/pin_mux.h b/hw/bsp/mcx/boards/bunny-brain/pin_mux.h deleted file mode 100644 index 40968c275..000000000 --- a/hw/bsp/mcx/boards/bunny-brain/pin_mux.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2022 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ - -#ifndef _PIN_MUX_H_ -#define _PIN_MUX_H_ - -/*! - * @addtogroup pin_mux - * @{ - */ - -/*********************************************************************************************************************** - * API - **********************************************************************************************************************/ - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - * @brief Calls initialization functions. - * - */ -void BOARD_InitBootPins(void); - -/*! - * @brief Configures pin routing and optionally pin electrical features. - * - */ -void BOARD_InitPins(void); - -#if defined(__cplusplus) -} -#endif - -/*! - * @} - */ -#endif /* _PIN_MUX_H_ */ - -/*********************************************************************************************************************** - * EOF - **********************************************************************************************************************/ diff --git a/hw/bsp/mcx/boards/frdm-mcxn947/board.cmake b/hw/bsp/mcx/boards/frdm-mcxn947/board.cmake deleted file mode 100644 index 8c3280743..000000000 --- a/hw/bsp/mcx/boards/frdm-mcxn947/board.cmake +++ /dev/null @@ -1,21 +0,0 @@ -set(MCU_VARIANT MCXN947) -set(MCU_CORE MCXN947_cm33_core0) - -set(JLINK_DEVICE MCXN947_M33_0) -set(PYOCD_TARGET MCXN947) -set(NXPLINK_DEVICE MCXN947:MCXN947) - -set(PORT 1) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - CPU_MCXN947VDF_cm33_core0 - BOARD_TUD_RHPORT=${PORT} - # port 0 is fullspeed, port 1 is highspeed - BOARD_TUD_MAX_SPEED=$ - ) - target_sources(${TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/clock_config.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/pin_mux.c - ) -endfunction() diff --git a/hw/bsp/mcx/boards/frdm-mcxn947/board.h b/hw/bsp/mcx/boards/frdm-mcxn947/board.h deleted file mode 100644 index acb73363f..000000000 --- a/hw/bsp/mcx/boards/frdm-mcxn947/board.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2021, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -// LED -#define LED_GPIO GPIO0 -#define LED_CLK kCLOCK_Gpio0 -#define LED_PIN 10 // red -#define LED_STATE_ON 0 - -// WAKE button (Dummy, use unused pin -#define BUTTON_GPIO GPIO0 -#define BUTTON_CLK kCLOCK_Gpio0 -#define BUTTON_PIN 23 -#define BUTTON_STATE_ACTIVE 0 - -// UART -#define UART_DEV LPUART4 - -static inline void board_uart_init_clock(void) { - /* attach FRO 12M to FLEXCOMM4 */ - CLOCK_SetClkDiv(kCLOCK_DivFlexcom4Clk, 1u); - CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4); - RESET_ClearPeripheralReset(kFC4_RST_SHIFT_RSTn); -} - -//#define UART_RX_PINMUX 0, 24, IOCON_PIO_DIG_FUNC1_EN -//#define UART_TX_PINMUX 0, 25, IOCON_PIO_DIG_FUNC1_EN - -// XTAL -#define XTAL0_CLK_HZ (24 * 1000 * 1000U) - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/hw/bsp/mcx/boards/frdm-mcxn947/board.mk b/hw/bsp/mcx/boards/frdm-mcxn947/board.mk deleted file mode 100644 index aaad5e73e..000000000 --- a/hw/bsp/mcx/boards/frdm-mcxn947/board.mk +++ /dev/null @@ -1,11 +0,0 @@ -MCU_VARIANT = MCXN947 -MCU_CORE = MCXN947_cm33_core0 -PORT ?= 1 - -CFLAGS += -DCPU_MCXN947VDF_cm33_core0 - -JLINK_DEVICE = MCXN947_M33_0 -PYOCD_TARGET = MCXN947 - -# flash using pyocd -flash: flash-jlink diff --git a/hw/bsp/mcx/boards/frdm-mcxn947/clock_config.c b/hw/bsp/mcx/boards/frdm-mcxn947/clock_config.c deleted file mode 100644 index 37d2b4dfc..000000000 --- a/hw/bsp/mcx/boards/frdm-mcxn947/clock_config.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2022 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ -/* - * How to setup clock using clock driver functions: - * - * 1. Setup clock sources. - * - * 2. Set up wait states of the flash. - * - * 3. Set up all dividers. - * - * 4. Set up all selectors to provide selected clocks. - * - */ - -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!GlobalInfo -product: Clocks v10.0 -processor: MCXN947 -package_id: MCXN947VDF -mcu_data: ksdk2_0 -processor_version: 0.12.3 -board: MCX-N9XX-EVK - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -#include "clock_config.h" -#include "fsl_clock.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/******************************************************************************* - * Variables - ******************************************************************************/ -/* System clock frequency. */ -// extern uint32_t SystemCoreClock; - -/******************************************************************************* - ************************ BOARD_InitBootClocks function ************************ - ******************************************************************************/ -void BOARD_InitBootClocks(void) -{ - BOARD_BootClockPLL150M(); -} - -/******************************************************************************* - ******************** Configuration BOARD_BootClockFRO12M ********************** - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockFRO12M -outputs: -- {id: CLK_144M_clock.outFreq, value: 144 MHz} -- {id: CLK_48M_clock.outFreq, value: 48 MHz} -- {id: FRO_12M_clock.outFreq, value: 12 MHz} -- {id: MAIN_clock.outFreq, value: 12 MHz} -- {id: Slow_clock.outFreq, value: 3 MHz} -- {id: System_clock.outFreq, value: 12 MHz} -- {id: gdet_clock.outFreq, value: 48 MHz} -- {id: trng_clock.outFreq, value: 48 MHz} -settings: -- {id: SCGMode, value: SIRC} -- {id: SCG.SCSSEL.sel, value: SCG.SIRC} -- {id: SCG_FIRCCSR_FIRCEN_CFG, value: Disabled} -- {id: SYSCON.FREQMEREFCLKSEL.sel, value: SYSCON.evtg_out0a} -- {id: SYSCON.FREQMETARGETCLKSEL.sel, value: SYSCON.evtg_out0a} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockFRO12M configuration - ******************************************************************************/ -/******************************************************************************* - * Code for BOARD_BootClockFRO12M configuration - ******************************************************************************/ -void BOARD_BootClockFRO12M(void) -{ - /*!< Enable SCG clock */ - CLOCK_EnableClock(kCLOCK_Scg); - - /*!< Set up clock selectors - Attach clocks to the peripheries */ - CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO12M */ - - /*!< Set up dividers */ - CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U); /*!< Set AHBCLKDIV divider to value 1 */ - - /* Set SystemCoreClock variable */ - SystemCoreClock = BOARD_BOOTCLOCKFRO12M_CORE_CLOCK; -} - -/******************************************************************************* - ******************* Configuration BOARD_BootClockFROHF48M ********************* - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockFROHF48M -outputs: -- {id: CLK_144M_clock.outFreq, value: 144 MHz} -- {id: CLK_48M_clock.outFreq, value: 48 MHz} -- {id: FRO_12M_clock.outFreq, value: 12 MHz} -- {id: FRO_HF_clock.outFreq, value: 48 MHz} -- {id: MAIN_clock.outFreq, value: 48 MHz} -- {id: Slow_clock.outFreq, value: 12 MHz} -- {id: System_clock.outFreq, value: 48 MHz} -- {id: gdet_clock.outFreq, value: 48 MHz} -- {id: trng_clock.outFreq, value: 48 MHz} -settings: -- {id: SYSCON.FLEXCAN0CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FLEXCAN1CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FREQMEREFCLKSEL.sel, value: SYSCON.evtg_out0a} -- {id: SYSCON.FREQMETARGETCLKSEL.sel, value: SYSCON.evtg_out0a} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockFROHF48M configuration - ******************************************************************************/ -/******************************************************************************* - * Code for BOARD_BootClockFROHF48M configuration - ******************************************************************************/ -void BOARD_BootClockFROHF48M(void) -{ - /*!< Enable SCG clock */ - CLOCK_EnableClock(kCLOCK_Scg); - - CLOCK_SetupFROHFClocking(48000000U); /*!< Enable FRO HF(48MHz) output */ - - /*!< Set up clock selectors - Attach clocks to the peripheries */ - CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO_HF */ - - /*!< Set up dividers */ - CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U); /*!< Set AHBCLKDIV divider to value 1 */ - - /* Set SystemCoreClock variable */ - SystemCoreClock = BOARD_BOOTCLOCKFROHF48M_CORE_CLOCK; -} - -/******************************************************************************* - ******************* Configuration BOARD_BootClockFROHF144M ******************** - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockFROHF144M -outputs: -- {id: CLK_144M_clock.outFreq, value: 144 MHz} -- {id: CLK_48M_clock.outFreq, value: 48 MHz} -- {id: FRO_12M_clock.outFreq, value: 12 MHz} -- {id: FRO_HF_clock.outFreq, value: 144 MHz} -- {id: MAIN_clock.outFreq, value: 144 MHz} -- {id: Slow_clock.outFreq, value: 18 MHz} -- {id: System_clock.outFreq, value: 72 MHz} -- {id: gdet_clock.outFreq, value: 48 MHz} -- {id: trng_clock.outFreq, value: 48 MHz} -settings: -- {id: SYSCON.AHBCLKDIV.scale, value: '2', locked: true} -- {id: SYSCON.FLEXCAN0CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FLEXCAN1CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FREQMEREFCLKSEL.sel, value: SYSCON.evtg_out0a} -- {id: SYSCON.FREQMETARGETCLKSEL.sel, value: SYSCON.evtg_out0a} -sources: -- {id: SCG.FIRC.outFreq, value: 144 MHz} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockFROHF144M configuration - ******************************************************************************/ -/******************************************************************************* - * Code for BOARD_BootClockFROHF144M configuration - ******************************************************************************/ -void BOARD_BootClockFROHF144M(void) -{ - /*!< Enable SCG clock */ - CLOCK_EnableClock(kCLOCK_Scg); - - CLOCK_SetupFROHFClocking(144000000U); /*!< Enable FRO HF(144MHz) output */ - - /*!< Set up clock selectors - Attach clocks to the peripheries */ - CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /*!< Switch MAIN_CLK to FRO_HF */ - - /*!< Set up dividers */ - CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 2U); /*!< Set AHBCLKDIV divider to value 2 */ - - /* Set SystemCoreClock variable */ - SystemCoreClock = BOARD_BOOTCLOCKFROHF144M_CORE_CLOCK; -} - -/******************************************************************************* - ******************** Configuration BOARD_BootClockPLL150M ********************* - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockPLL150M -called_from_default_init: true -outputs: -- {id: CLK_144M_clock.outFreq, value: 144 MHz} -- {id: CLK_48M_clock.outFreq, value: 48 MHz} -- {id: FRO_12M_clock.outFreq, value: 12 MHz} -- {id: FRO_HF_clock.outFreq, value: 48 MHz} -- {id: MAIN_clock.outFreq, value: 150 MHz} -- {id: PLL0_CLK_clock.outFreq, value: 150 MHz} -- {id: Slow_clock.outFreq, value: 37.5 MHz} -- {id: System_clock.outFreq, value: 150 MHz} -- {id: gdet_clock.outFreq, value: 48 MHz} -- {id: trng_clock.outFreq, value: 48 MHz} -settings: -- {id: PLL0_Mode, value: Normal} -- {id: RunPowerMode, value: OD} -- {id: SCGMode, value: PLL0} -- {id: SCG.PLL0M_MULT.scale, value: '50', locked: true} -- {id: SCG.PLL0SRCSEL.sel, value: SCG.FIRC_48M} -- {id: SCG.PLL0_NDIV.scale, value: '8', locked: true} -- {id: SCG.SCSSEL.sel, value: SCG.PLL0_CLK} -- {id: SYSCON.FLEXCAN0CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FLEXCAN1CLKSEL.sel, value: NO_CLOCK} -- {id: SYSCON.FREQMEREFCLKSEL.sel, value: SYSCON.evtg_out0a} -- {id: SYSCON.FREQMETARGETCLKSEL.sel, value: SYSCON.evtg_out0a} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockPLL150M configuration - ******************************************************************************/ -/******************************************************************************* - * Code for BOARD_BootClockPLL150M configuration - ******************************************************************************/ -void BOARD_BootClockPLL150M(void) -{ - /*!< Enable SCG clock */ - CLOCK_EnableClock(kCLOCK_Scg); - - CLOCK_SetupFROHFClocking(48000000U); /*!< Enable FRO HF(48MHz) output */ - - /*!< Set up PLL0 */ - const pll_setup_t pll0Setup = { - .pllctrl = SCG_APLLCTRL_SOURCE(1U) | SCG_APLLCTRL_SELI(27U) | SCG_APLLCTRL_SELP(13U), - .pllndiv = SCG_APLLNDIV_NDIV(8U), - .pllpdiv = SCG_APLLPDIV_PDIV(1U), - .pllmdiv = SCG_APLLMDIV_MDIV(50U), - .pllRate = 150000000U - }; - CLOCK_SetPLL0Freq(&pll0Setup); /*!< Configure PLL0 to the desired values */ - CLOCK_SetPll0MonitorMode(kSCG_Pll0MonitorDisable); /* Pll0 Monitor is disabled */ - - /*!< Set up clock selectors - Attach clocks to the peripheries */ - CLOCK_AttachClk(kPLL0_to_MAIN_CLK); /*!< Switch MAIN_CLK to PLL0 */ - - /*!< Set up dividers */ - CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U); /*!< Set AHBCLKDIV divider to value 1 */ - - /* Set SystemCoreClock variable */ - SystemCoreClock = BOARD_BOOTCLOCKPLL150M_CORE_CLOCK; -} - -/******************************************************************************* - ******************** Configuration BOARD_BootClockPLL100M ********************* - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockPLL100M -outputs: -- {id: CLK_144M_clock.outFreq, value: 144 MHz} -- {id: CLK_48M_clock.outFreq, value: 48 MHz} -- {id: CLK_IN_clock.outFreq, value: 24 MHz} -- {id: FRO_12M_clock.outFreq, value: 12 MHz} -- {id: MAIN_clock.outFreq, value: 100 MHz} -- {id: PLL1_CLK_clock.outFreq, value: 100 MHz} -- {id: Slow_clock.outFreq, value: 25 MHz} -- {id: System_clock.outFreq, value: 100 MHz} -- {id: gdet_clock.outFreq, value: 48 MHz} -- {id: trng_clock.outFreq, value: 48 MHz} -settings: -- {id: PLL1_Mode, value: Normal} -- {id: SCGMode, value: PLL1} -- {id: SCG.PLL1M_MULT.scale, value: '100', locked: true} -- {id: SCG.PLL1_NDIV.scale, value: '6', locked: true} -- {id: SCG.PLL1_PDIV.scale, value: '4', locked: true} -- {id: SCG.SCSSEL.sel, value: SCG.PLL1_CLK} -- {id: SCG_FIRCCSR_FIRCEN_CFG, value: Disabled} -- {id: SCG_SOSCCSR_SOSCEN_CFG, value: Enabled} -- {id: SYSCON.FREQMEREFCLKSEL.sel, value: SYSCON.evtg_out0a} -- {id: SYSCON.FREQMETARGETCLKSEL.sel, value: SYSCON.evtg_out0a} -sources: -- {id: SCG.SOSC.outFreq, value: 24 MHz, enabled: true} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockPLL100M configuration - ******************************************************************************/ -/******************************************************************************* - * Code for BOARD_BootClockPLL100M configuration - ******************************************************************************/ -void BOARD_BootClockPLL100M(void) -{ - /*!< Enable SCG clock */ - CLOCK_EnableClock(kCLOCK_Scg); - - CLOCK_SetupExtClocking(24000000U); - CLOCK_SetSysOscMonitorMode(kSCG_SysOscMonitorDisable); /* System OSC Clock Monitor is disabled */ - - /*!< Set up PLL1 */ - const pll_setup_t pll1Setup = { - .pllctrl = SCG_SPLLCTRL_SOURCE(0U) | SCG_SPLLCTRL_SELI(53U) | SCG_SPLLCTRL_SELP(26U), - .pllndiv = SCG_SPLLNDIV_NDIV(6U), - .pllpdiv = SCG_SPLLPDIV_PDIV(2U), - .pllmdiv = SCG_SPLLMDIV_MDIV(100U), - .pllRate = 100000000U - }; - CLOCK_SetPLL1Freq(&pll1Setup); /*!< Configure PLL1 to the desired values */ - CLOCK_SetPll1MonitorMode(kSCG_Pll1MonitorDisable); /* Pll1 Monitor is disabled */ - - /*!< Set up clock selectors - Attach clocks to the peripheries */ - CLOCK_AttachClk(kPLL1_to_MAIN_CLK); /*!< Switch MAIN_CLK to PLL1 */ - - /*!< Set up dividers */ - CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U); /*!< Set AHBCLKDIV divider to value 1 */ - - /* Set SystemCoreClock variable */ - SystemCoreClock = BOARD_BOOTCLOCKPLL100M_CORE_CLOCK; -} diff --git a/hw/bsp/mcx/boards/frdm-mcxn947/clock_config.h b/hw/bsp/mcx/boards/frdm-mcxn947/clock_config.h deleted file mode 100644 index c238a0423..000000000 --- a/hw/bsp/mcx/boards/frdm-mcxn947/clock_config.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2022 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ - -#ifndef _CLOCK_CONFIG_H_ -#define _CLOCK_CONFIG_H_ - -#include "fsl_common.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ -#define BOARD_XTAL0_CLK_HZ 24000000U /*!< Board xtal frequency in Hz */ -#define BOARD_XTAL32K_CLK_HZ 32768U /*!< Board xtal32K frequency in Hz */ - -/******************************************************************************* - ************************ BOARD_InitBootClocks function ************************ - ******************************************************************************/ - -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes default configuration of clocks. - * - */ -void BOARD_InitBootClocks(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************** Configuration BOARD_BootClockFRO12M ********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockFRO12M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKFRO12M_CORE_CLOCK 12000000U /*!< Core clock frequency: 12000000Hz */ -#define BOARD_BOOTCLOCKFRO12M_ROSC_CLOCK 0U /*!< ROSC clock frequency: 0Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockFRO12M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockFRO12M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************* Configuration BOARD_BootClockFROHF48M ********************* - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockFROHF48M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKFROHF48M_CORE_CLOCK 48000000U /*!< Core clock frequency: 48000000Hz */ -#define BOARD_BOOTCLOCKFROHF48M_ROSC_CLOCK 0U /*!< ROSC clock frequency: 0Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockFROHF48M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockFROHF48M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************* Configuration BOARD_BootClockFROHF144M ******************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockFROHF144M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKFROHF144M_CORE_CLOCK 144000000U /*!< Core clock frequency: 144000000Hz */ -#define BOARD_BOOTCLOCKFROHF144M_ROSC_CLOCK 0U /*!< ROSC clock frequency: 0Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockFROHF144M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockFROHF144M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************** Configuration BOARD_BootClockPLL150M ********************* - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockPLL150M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKPLL150M_CORE_CLOCK 150000000U /*!< Core clock frequency: 150000000Hz */ -#define BOARD_BOOTCLOCKPLL150M_ROSC_CLOCK 0U /*!< ROSC clock frequency: 0Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockPLL150M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockPLL150M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************** Configuration BOARD_BootClockPLL100M ********************* - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockPLL100M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKPLL100M_CORE_CLOCK 100000000U /*!< Core clock frequency: 100000000Hz */ -#define BOARD_BOOTCLOCKPLL100M_ROSC_CLOCK 0U /*!< ROSC clock frequency: 0Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockPLL100M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockPLL100M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -#endif /* _CLOCK_CONFIG_H_ */ diff --git a/hw/bsp/mcx/boards/frdm-mcxn947/pin_mux.c b/hw/bsp/mcx/boards/frdm-mcxn947/pin_mux.c deleted file mode 100644 index 30a5ae456..000000000 --- a/hw/bsp/mcx/boards/frdm-mcxn947/pin_mux.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2022 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ - -/* clang-format off */ -/* - * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!GlobalInfo -product: Pins v12.0 -processor: MCXN947 -package_id: MCXN947VDF -mcu_data: ksdk2_0 -processor_version: 0.12.3 - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** - */ -/* clang-format on */ - -#include "fsl_common.h" -#include "fsl_port.h" -#include "pin_mux.h" - -/* FUNCTION ************************************************************************************************************ - * - * Function Name : BOARD_InitBootPins - * Description : Calls initialization functions. - * - * END ****************************************************************************************************************/ -void BOARD_InitBootPins(void) -{ - BOARD_InitPins(); -} - -/* clang-format off */ -/* - * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -BOARD_InitPins: -- options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} -- pin_list: - - {pin_num: A1, peripheral: LPFlexcomm4, signal: LPFLEXCOMM_P0, pin_signal: PIO1_8/WUU0_IN10/LPTMR1_ALT3/TRACE_DATA0/FC4_P0/FC5_P4/CT_INP8/SCT0_OUT2/FLEXIO0_D16/PLU_OUT0/ENET0_TXD2/I3C1_SDA/TSI0_CH17/ADC1_A8, - slew_rate: fast, open_drain: disable, drive_strength: low, pull_select: down, pull_enable: disable, passive_filter: disable, pull_value: low, input_buffer: enable, - invert_input: normal} - - {pin_num: B1, peripheral: LPFlexcomm4, signal: LPFLEXCOMM_P1, pin_signal: PIO1_9/TRACE_DATA1/FC4_P1/FC5_P5/CT_INP9/SCT0_OUT3/FLEXIO0_D17/PLU_OUT1/ENET0_TXD3/I3C1_SCL/TSI0_CH18/ADC1_A9, - slew_rate: fast, open_drain: disable, drive_strength: low, pull_select: down, pull_enable: disable, passive_filter: disable, input_buffer: enable, invert_input: normal} - - {pin_num: B12, peripheral: GPIO0, signal: 'GPIO, 10', pin_signal: PIO0_12/ADC0_B10/FC0_P6/CT0O_MAT0/FLEXIO0_D2, slew_rate: fast, open_drain: disable, drive_strength: low, - pull_select: down, pull_enable: disable, input_buffer: enable, invert_input: normal} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** - */ -/* clang-format on */ - -/* FUNCTION ************************************************************************************************************ - * - * Function Name : BOARD_InitPins - * Description : Configures pin routing and optionally pin electrical features. - * - * END ****************************************************************************************************************/ -void BOARD_InitPins(void) -{ - /* Enables the clock for PORT0: Enables clock */ - CLOCK_EnableClock(kCLOCK_Port0); - - /* Enables the clock for PORT1: Enables clock */ - CLOCK_EnableClock(kCLOCK_Port1); - - - const port_pin_config_t port1_8_pinA1_config = {/* Internal pull-up/down resistor is disabled */ - kPORT_PullDisable, - /* Low internal pull resistor value is selected. */ - kPORT_LowPullResistor, - /* Fast slew rate is configured */ - kPORT_FastSlewRate, - /* Passive input filter is disabled */ - kPORT_PassiveFilterDisable, - /* Open drain output is disabled */ - kPORT_OpenDrainDisable, - /* Low drive strength is configured */ - kPORT_LowDriveStrength, - /* Pin is configured as FC4_P0 */ - kPORT_MuxAlt2, - /* Digital input enabled */ - kPORT_InputBufferEnable, - /* Digital input is not inverted */ - kPORT_InputNormal, - /* Pin Control Register fields [15:0] are not locked */ - kPORT_UnlockRegister}; - /* PORT1_8 (pin A1) is configured as FC4_P0 */ - PORT_SetPinConfig(PORT1, 8U, &port1_8_pinA1_config); - - const port_pin_config_t port1_9_pinB1_config = {/* Internal pull-up/down resistor is disabled */ - kPORT_PullDisable, - /* Low internal pull resistor value is selected. */ - kPORT_LowPullResistor, - /* Fast slew rate is configured */ - kPORT_FastSlewRate, - /* Passive input filter is disabled */ - kPORT_PassiveFilterDisable, - /* Open drain output is disabled */ - kPORT_OpenDrainDisable, - /* Low drive strength is configured */ - kPORT_LowDriveStrength, - /* Pin is configured as FC4_P1 */ - kPORT_MuxAlt2, - /* Digital input enabled */ - kPORT_InputBufferEnable, - /* Digital input is not inverted */ - kPORT_InputNormal, - /* Pin Control Register fields [15:0] are not locked */ - kPORT_UnlockRegister}; - /* PORT1_9 (pin B1) is configured as FC4_P1 */ - PORT_SetPinConfig(PORT1, 9U, &port1_9_pinB1_config); - - const port_pin_config_t port0_10_pinB12_config = {/* Internal pull-up/down resistor is disabled */ - kPORT_PullDisable, - /* Low internal pull resistor value is selected. */ - kPORT_LowPullResistor, - /* Fast slew rate is configured */ - kPORT_FastSlewRate, - /* Passive input filter is disabled */ - kPORT_PassiveFilterDisable, - /* Open drain output is disabled */ - kPORT_OpenDrainDisable, - /* Low drive strength is configured */ - kPORT_LowDriveStrength, - /* Pin is configured as PIO0_10 */ - kPORT_MuxAlt0, - /* Digital input enabled */ - kPORT_InputBufferEnable, - /* Digital input is not inverted */ - kPORT_InputNormal, - /* Pin Control Register fields [15:0] are not locked */ - kPORT_UnlockRegister}; - /* PORT0_10 (pin B12) is configured as PIO0_10 */ - PORT_SetPinConfig(PORT0, 10U, &port0_10_pinB12_config); -} -/*********************************************************************************************************************** - * EOF - **********************************************************************************************************************/ diff --git a/hw/bsp/mcx/boards/frdm-mcxn947/pin_mux.h b/hw/bsp/mcx/boards/frdm-mcxn947/pin_mux.h deleted file mode 100644 index 40968c275..000000000 --- a/hw/bsp/mcx/boards/frdm-mcxn947/pin_mux.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2022 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ - -#ifndef _PIN_MUX_H_ -#define _PIN_MUX_H_ - -/*! - * @addtogroup pin_mux - * @{ - */ - -/*********************************************************************************************************************** - * API - **********************************************************************************************************************/ - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - * @brief Calls initialization functions. - * - */ -void BOARD_InitBootPins(void); - -/*! - * @brief Configures pin routing and optionally pin electrical features. - * - */ -void BOARD_InitPins(void); - -#if defined(__cplusplus) -} -#endif - -/*! - * @} - */ -#endif /* _PIN_MUX_H_ */ - -/*********************************************************************************************************************** - * EOF - **********************************************************************************************************************/ diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index d438d0715..4adc558a6 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1729,7 +1729,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Find correct interface if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) { -#if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_ENABLE_DECODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL +#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING) uint8_t const * p_desc_parse_for_params = p_desc; #endif // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index deec32ae4..5cbd658fe 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -136,8 +136,7 @@ typedef enum{ //--------------------------------------------------------------------+ /// Communication Interface Management Element Request Codes -typedef enum -{ +typedef enum { CDC_REQUEST_SEND_ENCAPSULATED_COMMAND = 0x00, ///< is used to issue a command in the format of the supported control protocol of the Communications Class interface CDC_REQUEST_GET_ENCAPSULATED_RESPONSE = 0x01, ///< is used to request a response in the format of the supported control protocol of the Communications Class interface. CDC_REQUEST_SET_COMM_FEATURE = 0x02, @@ -180,39 +179,38 @@ typedef enum CDC_REQUEST_GET_ATM_VC_STATISTICS = 0x53, CDC_REQUEST_MDLM_SEMANTIC_MODEL = 0x60, -}cdc_management_request_t; +} cdc_management_request_t; -enum { +typedef enum { CDC_CONTROL_LINE_STATE_DTR = 0x01, CDC_CONTROL_LINE_STATE_RTS = 0x02, -}; +} cdc_control_line_state_t; -enum { +typedef enum { CDC_LINE_CODING_STOP_BITS_1 = 0, // 1 bit CDC_LINE_CODING_STOP_BITS_1_5 = 1, // 1.5 bits CDC_LINE_CODING_STOP_BITS_2 = 2, // 2 bits -}; +} cdc_line_coding_stopbits_t; // TODO Backward compatible for typos. Maybe removed in the future release #define CDC_LINE_CONDING_STOP_BITS_1 CDC_LINE_CODING_STOP_BITS_1 #define CDC_LINE_CONDING_STOP_BITS_1_5 CDC_LINE_CODING_STOP_BITS_1_5 #define CDC_LINE_CONDING_STOP_BITS_2 CDC_LINE_CODING_STOP_BITS_2 -enum { +typedef enum { CDC_LINE_CODING_PARITY_NONE = 0, CDC_LINE_CODING_PARITY_ODD = 1, CDC_LINE_CODING_PARITY_EVEN = 2, CDC_LINE_CODING_PARITY_MARK = 3, CDC_LINE_CODING_PARITY_SPACE = 4, -}; +} cdc_line_coding_parity_t; //--------------------------------------------------------------------+ // Management Element Notification (Notification Endpoint) //--------------------------------------------------------------------+ /// 6.3 Notification Codes -typedef enum -{ +typedef enum { CDC_NOTIF_NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status. CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request. CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08, diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 2463671c6..2fb37d835 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -22,6 +22,9 @@ * THE SOFTWARE. * * This file is part of the TinyUSB stack. + * + * Contribution + * - Heiko Kuester: CH34x support */ #include "tusb_option.h" @@ -50,12 +53,18 @@ typedef struct { uint8_t bInterfaceSubClass; uint8_t bInterfaceProtocol; + uint8_t ep_notif; uint8_t serial_drid; // Serial Driver ID + bool mounted; // Enumeration is complete cdc_acm_capability_t acm_capability; - uint8_t ep_notif; - uint8_t line_state; // DTR (bit0), RTS (bit1) TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; // Baudrate, stop bits, parity, data width + uint8_t line_state; // DTR (bit0), RTS (bit1) + + #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X + cdc_line_coding_t requested_line_coding; + // 1 byte padding + #endif tuh_xfer_cb_t user_control_cb; @@ -69,7 +78,6 @@ typedef struct { uint8_t rx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE]; CFG_TUH_MEM_ALIGN uint8_t rx_ep_buf[CFG_TUH_CDC_TX_EPSIZE]; } stream; - } cdch_interface_t; CFG_TUH_MEM_SECTION @@ -83,45 +91,57 @@ static cdch_interface_t cdch_data[CFG_TUH_CDC]; static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); static void acm_process_config(tuh_xfer_t* xfer); +static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); //------------- FTDI prototypes -------------// #if CFG_TUH_CDC_FTDI #include "serial/ftdi_sio.h" -static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST }; -enum { - FTDI_PID_COUNT = sizeof(ftdi_vid_pid_list) / sizeof(ftdi_vid_pid_list[0]) -}; - -// Store last request baudrate since divisor to baudrate is not easy -static uint32_t _ftdi_requested_baud; +static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST}; static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); static void ftdi_process_config(tuh_xfer_t* xfer); -static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif //------------- CP210X prototypes -------------// #if CFG_TUH_CDC_CP210X #include "serial/cp210x.h" -static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIST }; -enum { - CP210X_PID_COUNT = sizeof(cp210x_vid_pid_list) / sizeof(cp210x_vid_pid_list[0]) -}; +static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIST}; static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); static void cp210x_process_config(tuh_xfer_t* xfer); -static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif +//------------- CH34x prototypes -------------// +#if CFG_TUH_CDC_CH34X +#include "serial/ch34x.h" + +static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST}; + +static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len); +static void ch34x_process_config(tuh_xfer_t* xfer); + +static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +#endif + +//------------- Common -------------// enum { SERIAL_DRIVER_ACM = 0, @@ -132,60 +152,96 @@ enum { #if CFG_TUH_CDC_CP210X SERIAL_DRIVER_CP210X, #endif + +#if CFG_TUH_CDC_CH34X + SERIAL_DRIVER_CH34X, +#endif + + SERIAL_DRIVER_COUNT }; typedef struct { + uint16_t const (*vid_pid_list)[2]; + uint16_t const vid_pid_count; + bool (*const open)(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); void (*const process_set_config)(tuh_xfer_t* xfer); bool (*const set_control_line_state)(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); bool (*const set_baudrate)(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_data_format)(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_line_coding)(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); } cdch_serial_driver_t; // Note driver list must be in the same order as SERIAL_DRIVER enum static const cdch_serial_driver_t serial_drivers[] = { - { .process_set_config = acm_process_config, - .set_control_line_state = acm_set_control_line_state, - .set_baudrate = acm_set_baudrate + { + .vid_pid_list = NULL, + .vid_pid_count = 0, + .open = acm_open, + .process_set_config = acm_process_config, + .set_control_line_state = acm_set_control_line_state, + .set_baudrate = acm_set_baudrate, + .set_data_format = acm_set_data_format, + .set_line_coding = acm_set_line_coding }, #if CFG_TUH_CDC_FTDI - { .process_set_config = ftdi_process_config, - .set_control_line_state = ftdi_sio_set_modem_ctrl, - .set_baudrate = ftdi_sio_set_baudrate + { + .vid_pid_list = ftdi_vid_pid_list, + .vid_pid_count = TU_ARRAY_SIZE(ftdi_vid_pid_list), + .open = ftdi_open, + .process_set_config = ftdi_process_config, + .set_control_line_state = ftdi_sio_set_modem_ctrl, + .set_baudrate = ftdi_sio_set_baudrate, + .set_data_format = ftdi_set_data_format, + .set_line_coding = ftdi_set_line_coding }, #endif #if CFG_TUH_CDC_CP210X - { .process_set_config = cp210x_process_config, - .set_control_line_state = cp210x_set_modem_ctrl, - .set_baudrate = cp210x_set_baudrate + { + .vid_pid_list = cp210x_vid_pid_list, + .vid_pid_count = TU_ARRAY_SIZE(cp210x_vid_pid_list), + .open = cp210x_open, + .process_set_config = cp210x_process_config, + .set_control_line_state = cp210x_set_modem_ctrl, + .set_baudrate = cp210x_set_baudrate, + .set_data_format = cp210x_set_data_format, + .set_line_coding = cp210x_set_line_coding }, #endif -}; -enum { - SERIAL_DRIVER_COUNT = sizeof(serial_drivers) / sizeof(serial_drivers[0]) + #if CFG_TUH_CDC_CH34X + { + .vid_pid_list = ch34x_vid_pid_list, + .vid_pid_count = TU_ARRAY_SIZE(ch34x_vid_pid_list), + .open = ch34x_open, + .process_set_config = ch34x_process_config, + .set_control_line_state = ch34x_set_modem_ctrl, + .set_baudrate = ch34x_set_baudrate, + .set_data_format = ch34x_set_data_format, + .set_line_coding = ch34x_set_line_coding + }, + #endif }; +TU_VERIFY_STATIC(TU_ARRAY_SIZE(serial_drivers) == SERIAL_DRIVER_COUNT, "Serial driver count mismatch"); + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -static inline cdch_interface_t* get_itf(uint8_t idx) -{ +static inline cdch_interface_t* get_itf(uint8_t idx) { TU_ASSERT(idx < CFG_TUH_CDC, NULL); cdch_interface_t* p_cdc = &cdch_data[idx]; return (p_cdc->daddr != 0) ? p_cdc : NULL; } -static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) -{ - for(uint8_t i=0; idaddr == daddr) && - (ep_addr == p_cdc->ep_notif || ep_addr == p_cdc->stream.rx.ep_addr || ep_addr == p_cdc->stream.tx.ep_addr)) - { + (ep_addr == p_cdc->ep_notif || ep_addr == p_cdc->stream.rx.ep_addr || ep_addr == p_cdc->stream.tx.ep_addr)) { return i; } } @@ -193,14 +249,10 @@ static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) return TUSB_INDEX_INVALID_8; } - -static cdch_interface_t* make_new_itf(uint8_t daddr, tusb_desc_interface_t const *itf_desc) -{ - for(uint8_t i=0; idaddr = daddr; p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber; p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass; @@ -221,20 +273,16 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer); // APPLICATION API //--------------------------------------------------------------------+ -uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num) -{ - for(uint8_t i=0; idaddr == daddr && p_cdc->bInterfaceNumber == itf_num) return i; } return TUSB_INDEX_INVALID_8; } -bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info) -{ +bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && info); @@ -256,30 +304,27 @@ bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info) return true; } -bool tuh_cdc_mounted(uint8_t idx) -{ +bool tuh_cdc_mounted(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); - return p_cdc != NULL; + TU_VERIFY(p_cdc); + return p_cdc->mounted; } -bool tuh_cdc_get_dtr(uint8_t idx) -{ +bool tuh_cdc_get_dtr(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_DTR) ? true : false; } -bool tuh_cdc_get_rts(uint8_t idx) -{ +bool tuh_cdc_get_rts(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_RTS) ? true : false; } -bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding) -{ +bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); @@ -292,32 +337,28 @@ bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding) // Write //--------------------------------------------------------------------+ -uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize) -{ +uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_write(&p_cdc->stream.tx, buffer, bufsize); } -uint32_t tuh_cdc_write_flush(uint8_t idx) -{ +uint32_t tuh_cdc_write_flush(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_write_xfer(&p_cdc->stream.tx); } -bool tuh_cdc_write_clear(uint8_t idx) -{ +bool tuh_cdc_write_clear(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_clear(&p_cdc->stream.tx); } -uint32_t tuh_cdc_write_available(uint8_t idx) -{ +uint32_t tuh_cdc_write_available(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); @@ -328,32 +369,28 @@ uint32_t tuh_cdc_write_available(uint8_t idx) // Read //--------------------------------------------------------------------+ -uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize) -{ +uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_read(&p_cdc->stream.rx, buffer, bufsize); } -uint32_t tuh_cdc_read_available(uint8_t idx) -{ +uint32_t tuh_cdc_read_available(uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_read_available(&p_cdc->stream.rx); } -bool tuh_cdc_peek(uint8_t idx, uint8_t* ch) -{ +bool tuh_cdc_peek(uint8_t idx, uint8_t* ch) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_peek(&p_cdc->stream.rx, ch); } -bool tuh_cdc_read_clear (uint8_t idx) -{ +bool tuh_cdc_read_clear (uint8_t idx) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc); @@ -366,28 +403,25 @@ bool tuh_cdc_read_clear (uint8_t idx) // Control Endpoint API //--------------------------------------------------------------------+ -// internal control complete to update state such as line state, encoding -static void cdch_internal_control_complete(tuh_xfer_t* xfer) -{ - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); +static void process_internal_control_complete(tuh_xfer_t* xfer, uint8_t itf_num) { uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t* p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); + uint16_t const value = tu_le16toh(xfer->setup->wValue); - if (xfer->result == XFER_RESULT_SUCCESS) - { + if (xfer->result == XFER_RESULT_SUCCESS) { switch (p_cdc->serial_drid) { case SERIAL_DRIVER_ACM: switch (xfer->setup->bRequest) { case CDC_REQUEST_SET_CONTROL_LINE_STATE: - p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue); + p_cdc->line_state = (uint8_t) value; break; case CDC_REQUEST_SET_LINE_CODING: { uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength)); memcpy(&p_cdc->line_coding, xfer->buffer, len); - } break; + } default: break; } @@ -397,12 +431,11 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer) case SERIAL_DRIVER_FTDI: switch (xfer->setup->bRequest) { case FTDI_SIO_MODEM_CTRL: - p_cdc->line_state = (uint8_t) (tu_le16toh(xfer->setup->wValue) & 0x00ff); + p_cdc->line_state = (uint8_t) value; break; case FTDI_SIO_SET_BAUD_RATE: - // convert from divisor to baudrate is not supported - p_cdc->line_coding.bit_rate = _ftdi_requested_baud; + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; break; default: break; @@ -414,15 +447,61 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer) case SERIAL_DRIVER_CP210X: switch(xfer->setup->bRequest) { case CP210X_SET_MHS: - p_cdc->line_state = (uint8_t) (tu_le16toh(xfer->setup->wValue) & 0x00ff); + p_cdc->line_state = (uint8_t) value; break; case CP210X_SET_BAUDRATE: { uint32_t baudrate; memcpy(&baudrate, xfer->buffer, sizeof(uint32_t)); p_cdc->line_coding.bit_rate = tu_le32toh(baudrate); + break; } + + default: break; + } + break; + #endif + + #if CFG_TUH_CDC_CH34X + case SERIAL_DRIVER_CH34X: + switch (xfer->setup->bRequest) { + case CH34X_REQ_WRITE_REG: + // register write request + switch (value) { + case CH34X_REG16_DIVISOR_PRESCALER: + // baudrate + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + break; + + case CH32X_REG16_LCR2_LCR: + // data format + p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; + p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; + p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; + break; + + default: break; + } + break; + + case CH34X_REQ_MODEM_CTRL: { + // set modem controls RTS/DTR request. Note: signals are inverted + uint16_t const modem_signal = ~value; + if (modem_signal & CH34X_BIT_RTS) { + p_cdc->line_state |= CDC_CONTROL_LINE_STATE_RTS; + } else { + p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_RTS; + } + + if (modem_signal & CH34X_BIT_DTR) { + p_cdc->line_state |= CDC_CONTROL_LINE_STATE_DTR; + } else { + p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_DTR; + } break; + } + + default: break; } break; #endif @@ -437,14 +516,20 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer) } } +// internal control complete to update state such as line state, encoding +static void cdch_internal_control_complete(tuh_xfer_t* xfer) { + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + process_internal_control_complete(xfer, itf_num); +} + bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; - if ( complete_cb ) { + if (complete_cb) { return driver->set_control_line_state(p_cdc, line_state, complete_cb, user_data); - }else { + } else { // blocking xfer_result_t result = XFER_RESULT_INVALID; bool ret = driver->set_control_line_state(p_cdc, line_state, complete_cb, (uintptr_t) &result); @@ -455,7 +540,6 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c } TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); - p_cdc->line_state = (uint8_t) line_state; return true; } @@ -466,9 +550,9 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; - if ( complete_cb ) { + if (complete_cb) { return driver->set_baudrate(p_cdc, baudrate, complete_cb, user_data); - }else { + } else { // blocking xfer_result_t result = XFER_RESULT_INVALID; bool ret = driver->set_baudrate(p_cdc, baudrate, complete_cb, (uintptr_t) &result); @@ -479,25 +563,23 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete } TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); - p_cdc->line_coding.bit_rate = baudrate; return true; } } -bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); - // only ACM support this set line coding request - TU_VERIFY(p_cdc && p_cdc->serial_drid == SERIAL_DRIVER_ACM); - TU_VERIFY(p_cdc->acm_capability.support_line_request); + TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; - if ( complete_cb ) { - return acm_set_line_coding(p_cdc, line_coding, complete_cb, user_data); - }else { + if (complete_cb) { + return driver->set_data_format(p_cdc, stop_bits, parity, data_bits, complete_cb, user_data); + } else { // blocking xfer_result_t result = XFER_RESULT_INVALID; - bool ret = acm_set_line_coding(p_cdc, line_coding, complete_cb, (uintptr_t) &result); + bool ret = driver->set_data_format(p_cdc, stop_bits, parity, data_bits, complete_cb, (uintptr_t) &result); if (user_data) { // user_data is not NULL, return result via user_data @@ -505,7 +587,31 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, } TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); + p_cdc->line_coding.stop_bits = stop_bits; + p_cdc->line_coding.parity = parity; + p_cdc->line_coding.data_bits = data_bits; + return true; + } +} + +bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + cdch_interface_t* p_cdc = get_itf(idx); + TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; + + if ( complete_cb ) { + return driver->set_line_coding(p_cdc, line_coding, complete_cb, user_data); + } else { + // blocking + xfer_result_t result = XFER_RESULT_INVALID; + bool ret = driver->set_line_coding(p_cdc, line_coding, complete_cb, (uintptr_t) &result); + + if (user_data) { + // user_data is not NULL, return result via user_data + *((xfer_result_t*) user_data) = result; + } + TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); p_cdc->line_coding = *line_coding; return true; } @@ -515,39 +621,34 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, // CLASS-USBH API //--------------------------------------------------------------------+ -void cdch_init(void) -{ +void cdch_init(void) { tu_memclr(cdch_data, sizeof(cdch_data)); - for(size_t i=0; istream.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); + p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, + p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE); tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, - p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE, - p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE); + p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE, + p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE); } } -void cdch_close(uint8_t daddr) -{ - for(uint8_t idx=0; idxdaddr == daddr) - { + if (p_cdc->daddr == daddr) { TU_LOG_DRV(" CDCh close addr = %u index = %u\r\n", daddr, idx); // Invoke application callback if (tuh_cdc_umount_cb) tuh_cdc_umount_cb(idx); - //tu_memclr(p_cdc, sizeof(cdch_interface_t)); p_cdc->daddr = 0; p_cdc->bInterfaceNumber = 0; + p_cdc->mounted = false; tu_edpt_stream_close(&p_cdc->stream.tx); tu_edpt_stream_close(&p_cdc->stream.rx); } @@ -571,16 +672,11 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t // - xferred_bytes is multiple of EP Packet size and not zero tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes); } - } - else if ( ep_addr == p_cdc->stream.rx.ep_addr ) { + } else if ( ep_addr == p_cdc->stream.rx.ep_addr ) { #if CFG_TUH_CDC_FTDI if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI) { // FTDI reserve 2 bytes for status - // FTDI status -// uint8_t status[2] = { -// p_cdc->stream.rx.ep_buf[0], -// p_cdc->stream.rx.ep_buf[1] -// }; + // uint8_t status[2] = {p_cdc->stream.rx.ep_buf[0], p_cdc->stream.rx.ep_buf[1]}; tu_edpt_stream_read_xfer_complete_offset(&p_cdc->stream.rx, xferred_bytes, 2); }else #endif @@ -606,20 +702,15 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t // Enumeration //--------------------------------------------------------------------+ -static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t const *desc_ep) -{ - for(size_t i=0; i<2; i++) - { +static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t const* desc_ep) { + for (size_t i = 0; i < 2; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && - TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); - + TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep)); - if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN ) - { + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { tu_edpt_stream_open(&p_cdc->stream.rx, p_cdc->daddr, desc_ep); - }else - { + } else { tu_edpt_stream_open(&p_cdc->stream.tx, p_cdc->daddr, desc_ep); } @@ -629,45 +720,36 @@ static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t co return true; } -bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ +bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; - // Only support ACM subclass + // For CDC: only support ACM subclass // Note: Protocol 0xFF can be RNDIS device - if ( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass) - { + if (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass) { return acm_open(daddr, itf_desc, max_len); } - #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X - else if ( TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass ) - { + else if (SERIAL_DRIVER_COUNT > 1 && + TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { uint16_t vid, pid; TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); - #if CFG_TUH_CDC_FTDI - for (size_t i = 0; i < FTDI_PID_COUNT; i++) { - if (ftdi_vid_pid_list[i][0] == vid && ftdi_vid_pid_list[i][1] == pid) { - return ftdi_open(daddr, itf_desc, max_len); - } - } - #endif - - #if CFG_TUH_CDC_CP210X - for (size_t i = 0; i < CP210X_PID_COUNT; i++) { - if (cp210x_vid_pid_list[i][0] == vid && cp210x_vid_pid_list[i][1] == pid) { - return cp210x_open(daddr, itf_desc, max_len); + for (size_t dr = 1; dr < SERIAL_DRIVER_COUNT; dr++) { + cdch_serial_driver_t const* driver = &serial_drivers[dr]; + for (size_t i = 0; i < driver->vid_pid_count; i++) { + if (driver->vid_pid_list[i][0] == vid && driver->vid_pid_list[i][1] == pid) { + return driver->open(daddr, itf_desc, max_len); + } } } - #endif } - #endif return false; } static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num) { + TU_LOG_DRV("CDCh Set Configure complete\r\n"); + p_cdc->mounted = true; if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(idx); // Prepare for incoming data @@ -677,9 +759,7 @@ static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t i usbh_driver_set_config_complete(p_cdc->daddr, itf_num); } - -bool cdch_set_config(uint8_t daddr, uint8_t itf_num) -{ +bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { tusb_control_request_t request; request.wIndex = tu_htole16((uint16_t) itf_num); @@ -708,94 +788,84 @@ enum { CONFIG_ACM_COMPLETE, }; -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ - uint8_t const * p_desc_end = ((uint8_t const*) itf_desc) + max_len; +static bool acm_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len) { + uint8_t const* p_desc_end = ((uint8_t const*) itf_desc) + max_len; - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); + cdch_interface_t* p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); - p_cdc->serial_drid = SERIAL_DRIVER_ACM; //------------- Control Interface -------------// - uint8_t const * p_desc = tu_desc_next(itf_desc); + uint8_t const* p_desc = tu_desc_next(itf_desc); // Communication Functional Descriptors - while( (p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) ) - { - if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) ) - { + while ((p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) { + if (CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc)) { // save ACM bmCapabilities - p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; + p_cdc->acm_capability = ((cdc_desc_func_acm_t const*) p_desc)->bmCapabilities; } p_desc = tu_desc_next(p_desc); } // Open notification endpoint of control interface if any - if (itf_desc->bNumEndpoints == 1) - { + if (itf_desc->bNumEndpoints == 1) { TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) p_desc; - TU_ASSERT( tuh_edpt_open(daddr, desc_ep) ); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); p_cdc->ep_notif = desc_ep->bEndpointAddress; p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) - { + if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const*) p_desc)->bInterfaceClass)) { // next to endpoint descriptor p_desc = tu_desc_next(p_desc); // data endpoints expected to be in pairs - TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const *) p_desc)); + TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const*) p_desc)); } return true; } -static void acm_process_config(tuh_xfer_t* xfer) -{ +static void acm_process_config(tuh_xfer_t* xfer) { uintptr_t const state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); + cdch_interface_t* p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); - switch(state) - { + switch (state) { case CONFIG_ACM_SET_CONTROL_LINE_STATE: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - if (p_cdc->acm_capability.support_line_request) - { - TU_ASSERT(acm_set_control_line_state(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, acm_process_config, - CONFIG_ACM_SET_LINE_CODING), ); + if (p_cdc->acm_capability.support_line_request) { + TU_ASSERT(acm_set_control_line_state(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, acm_process_config, CONFIG_ACM_SET_LINE_CODING),); break; } - #endif + #endif TU_ATTR_FALLTHROUGH; case CONFIG_ACM_SET_LINE_CODING: - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - if (p_cdc->acm_capability.support_line_request) - { + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + if (p_cdc->acm_capability.support_line_request) { cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(acm_set_line_coding(p_cdc, &line_coding, acm_process_config, CONFIG_ACM_COMPLETE), ); + TU_ASSERT(acm_set_line_coding(p_cdc, &line_coding, acm_process_config, CONFIG_ACM_COMPLETE),); break; } - #endif + #endif TU_ATTR_FALLTHROUGH; case CONFIG_ACM_COMPLETE: // itf_num+1 to account for data interface as well - set_config_complete(p_cdc, idx, itf_num+1); + set_config_complete(p_cdc, idx, itf_num + 1); break; - default: break; + default: + break; } } @@ -863,6 +933,19 @@ static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const return true; } +static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_LOG_DRV("CDC ACM Set Data Format\r\n"); + + cdc_line_coding_t line_coding; + line_coding.bit_rate = p_cdc->line_coding.bit_rate; + line_coding.stop_bits = stop_bits; + line_coding.parity = parity; + line_coding.data_bits = data_bits; + + return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data); +} + static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); cdc_line_coding_t line_coding = p_cdc->line_coding; @@ -892,7 +975,6 @@ static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint TU_VERIFY(p_cdc); TU_LOG_DRV("FTDI opened\r\n"); - p_cdc->serial_drid = SERIAL_DRIVER_FTDI; // endpoint pair @@ -928,13 +1010,32 @@ static bool ftdi_sio_set_request(cdch_interface_t* p_cdc, uint8_t command, uint1 return tuh_control_xfer(&xfer); } -static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ftdi_sio_set_request(p_cdc, FTDI_SIO_RESET, FTDI_SIO_RESET_SIO, complete_cb, user_data); } -static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +static bool ftdi_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + (void) p_cdc; + (void) stop_bits; + (void) parity; + (void) data_bits; + (void) complete_cb; + (void) user_data; + // TODO not implemented yet + return false; +} + +static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + (void) p_cdc; + (void) line_coding; + (void) complete_cb; + (void) user_data; + // TODO not implemented yet + return false; +} + +static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG_DRV("CDC FTDI Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state, @@ -942,8 +1043,7 @@ static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state return true; } -static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) -{ +static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { const uint8_t divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; uint32_t divisor; @@ -963,18 +1063,16 @@ static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) return divisor; } -static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) -{ +static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) { return ftdi_232bm_baud_base_to_divisor(baud, 48000000u); } -static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate); TU_LOG_DRV("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\r\n", baudrate, divisor); p_cdc->user_control_cb = complete_cb; - _ftdi_requested_baud = baudrate; + p_cdc->requested_line_coding.bit_rate = baudrate; TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, complete_cb ? cdch_internal_control_complete : NULL, user_data)); @@ -996,8 +1094,7 @@ static void ftdi_process_config(tuh_xfer_t* xfer) { case CONFIG_FTDI_MODEM_CTRL: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - TU_ASSERT( - ftdi_sio_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE),); + TU_ASSERT(ftdi_sio_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE),); break; #else TU_ATTR_FALLTHROUGH; @@ -1105,6 +1202,15 @@ static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfe return cp210x_set_request(p_cdc, CP210X_IFC_ENABLE, enabled, NULL, 0, complete_cb, user_data); } +static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // TODO implement later + (void) p_cdc; + (void) line_coding; + (void) complete_cb; + (void) user_data; + return false; +} + static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG_DRV("CDC CP210x Set BaudRate = %lu\r\n", baudrate); uint32_t baud_le = tu_htole32(baudrate); @@ -1113,8 +1219,19 @@ static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_ complete_cb ? cdch_internal_control_complete : NULL, user_data); } -static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + (void) p_cdc; + (void) stop_bits; + (void) parity; + (void) data_bits; + (void) complete_cb; + (void) user_data; + // TODO not implemented yet + return false; +} + +static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG_DRV("CDC CP210x Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, @@ -1154,8 +1271,7 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { case CONFIG_CP210X_SET_DTR_RTS: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - TU_ASSERT( - cp210x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, cp210x_process_config, CONFIG_CP210X_COMPLETE),); + TU_ASSERT(cp210x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, cp210x_process_config, CONFIG_CP210X_COMPLETE),); break; #else TU_ATTR_FALLTHROUGH; @@ -1171,4 +1287,374 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { #endif +//--------------------------------------------------------------------+ +// CH34x (CH340 & CH341) +//--------------------------------------------------------------------+ + +#if CFG_TUH_CDC_CH34X + +static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bits); +static uint16_t ch34x_get_divisor_prescaler(uint32_t baval); + +//------------- control request -------------// + +static bool ch34x_set_request(cdch_interface_t* p_cdc, uint8_t direction, uint8_t request, uint16_t value, + uint16_t index, uint8_t* buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + tusb_control_request_t const request_setup = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_VENDOR, + .direction = direction & 0x01u + }, + .bRequest = request, + .wValue = tu_htole16 (value), + .wIndex = tu_htole16 (index), + .wLength = tu_htole16 (length) + }; + + // use usbh enum buf since application variable does not live long enough + uint8_t* enum_buf = NULL; + + if (buffer && length > 0) { + enum_buf = usbh_get_enum_buf(); + if (direction == TUSB_DIR_OUT) { + tu_memcpy_s(enum_buf, CFG_TUH_ENUMERATION_BUFSIZE, buffer, length); + } + } + + tuh_xfer_t xfer = { + .daddr = p_cdc->daddr, + .ep_addr = 0, + .setup = &request_setup, + .buffer = enum_buf, + .complete_cb = complete_cb, + .user_data = user_data + }; + + return tuh_control_xfer(&xfer); +} + +static inline bool ch34x_control_out(cdch_interface_t* p_cdc, uint8_t request, uint16_t value, uint16_t index, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return ch34x_set_request(p_cdc, TUSB_DIR_OUT, request, value, index, NULL, 0, complete_cb, user_data); +} + +static inline bool ch34x_control_in(cdch_interface_t* p_cdc, uint8_t request, uint16_t value, uint16_t index, + uint8_t* buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return ch34x_set_request(p_cdc, TUSB_DIR_IN, request, value, index, buffer, buffersize, + complete_cb, user_data); +} + +static inline bool ch34x_write_reg(cdch_interface_t* p_cdc, uint16_t reg, uint16_t reg_value, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, reg, reg_value, complete_cb, user_data); +} + +//static bool ch34x_read_reg_request ( cdch_interface_t* p_cdc, uint16_t reg, +// uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +//{ +// return ch34x_control_in ( p_cdc, CH34X_REQ_READ_REG, reg, 0, buffer, buffersize, complete_cb, user_data ); +//} + +static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint16_t const div_ps = ch34x_get_divisor_prescaler(baudrate); + TU_VERIFY(div_ps); + TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, + complete_cb, user_data)); + return true; +} + +//------------- Driver API -------------// + +// internal control complete to update state such as line state, encoding +static void ch34x_control_complete(tuh_xfer_t* xfer) { + // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber + process_internal_control_complete(xfer, 0); +} + +static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->requested_line_coding.stop_bits = stop_bits; + p_cdc->requested_line_coding.parity = parity; + p_cdc->requested_line_coding.data_bits = data_bits; + + uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits); + TU_VERIFY(lcr); + TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr, + complete_cb ? ch34x_control_complete : NULL, user_data)); + return true; +} + +static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->requested_line_coding.bit_rate = baudrate; + p_cdc->user_control_cb = complete_cb; + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, baudrate, + complete_cb ? ch34x_control_complete : NULL, user_data)); + return true; +} + +static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) { + // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber + uint8_t const itf_num = 0; + uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t* p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); + + if (xfer->result == XFER_RESULT_SUCCESS) { + // stage 1 success, continue to stage 2 + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + TU_ASSERT(ch34x_set_data_format(p_cdc, p_cdc->requested_line_coding.stop_bits, p_cdc->requested_line_coding.parity, + p_cdc->requested_line_coding.data_bits, ch34x_control_complete, xfer->user_data), ); + } else { + // stage 1 failed, notify user + xfer->complete_cb = p_cdc->user_control_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } + } +} + +// 2 stages: set baudrate (stage1) + set data format (stage2) +static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->requested_line_coding = *line_coding; + p_cdc->user_control_cb = complete_cb; + + if (complete_cb) { + // stage 1 set baudrate + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate, + ch34x_set_line_coding_stage1_complete, user_data)); + } else { + // sync call + xfer_result_t result; + + // stage 1 set baudrate + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate, NULL, (uintptr_t) &result)); + TU_VERIFY(result == XFER_RESULT_SUCCESS); + p_cdc->line_coding.bit_rate = line_coding->bit_rate; + + // stage 2 set data format + TU_ASSERT(ch34x_set_data_format(p_cdc, line_coding->stop_bits, line_coding->parity, line_coding->data_bits, + NULL, (uintptr_t) &result)); + TU_VERIFY(result == XFER_RESULT_SUCCESS); + p_cdc->line_coding.stop_bits = line_coding->stop_bits; + p_cdc->line_coding.parity = line_coding->parity; + p_cdc->line_coding.data_bits = line_coding->data_bits; + + // update transfer result, user_data is expected to point to xfer_result_t + if (user_data) { + *((xfer_result_t*) user_data) = result; + } + } + + return true; +} + +static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint8_t control = 0; + if (line_state & CDC_CONTROL_LINE_STATE_RTS) { + control |= CH34X_BIT_RTS; + } + if (line_state & CDC_CONTROL_LINE_STATE_DTR) { + control |= CH34X_BIT_DTR; + } + + // CH34x signals are inverted + control = ~control; + + p_cdc->user_control_cb = complete_cb; + TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, + complete_cb ? ch34x_control_complete : NULL, user_data)); + return true; +} + +//------------- Enumeration -------------// +enum { + CONFIG_CH34X_READ_VERSION = 0, + CONFIG_CH34X_SERIAL_INIT, + CONFIG_CH34X_SPECIAL_REG_WRITE, + CONFIG_CH34X_FLOW_CONTROL, + CONFIG_CH34X_MODEM_CONTROL, + CONFIG_CH34X_COMPLETE +}; + +static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len) { + // CH34x Interface includes 1 vendor interface + 2 bulk + 1 interrupt endpoints + TU_VERIFY (itf_desc->bNumEndpoints == 3); + TU_VERIFY (sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t) <= max_len); + + cdch_interface_t* p_cdc = make_new_itf(daddr, itf_desc); + TU_VERIFY (p_cdc); + + TU_LOG_DRV ("CH34x opened\r\n"); + p_cdc->serial_drid = SERIAL_DRIVER_CH34X; + + tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) tu_desc_next(itf_desc); + + // data endpoints expected to be in pairs + TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep)); + desc_ep += 2; + + // Interrupt endpoint: not used for now + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && + TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); + p_cdc->ep_notif = desc_ep->bEndpointAddress; + + return true; +} + +static void ch34x_process_config(tuh_xfer_t* xfer) { + // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber + uint8_t const itf_num = 0; + uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t* p_cdc = get_itf(idx); + uintptr_t const state = xfer->user_data; + uint8_t buffer[2]; // TODO remove + TU_ASSERT (p_cdc,); + TU_ASSERT (xfer->result == XFER_RESULT_SUCCESS,); + + switch (state) { + case CONFIG_CH34X_READ_VERSION: + TU_LOG_DRV("[%u] CDCh CH34x attempt to read Chip Version\r\n", p_cdc->daddr); + TU_ASSERT (ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, ch34x_process_config, CONFIG_CH34X_SERIAL_INIT),); + break; + + case CONFIG_CH34X_SERIAL_INIT: { + // handle version read data, set CH34x line coding (incl. baudrate) + uint8_t const version = xfer->buffer[0]; + TU_LOG_DRV("[%u] CDCh CH34x Chip Version = %02x\r\n", p_cdc->daddr, version); + // only versions >= 0x30 are tested, below 0x30 seems having other programming, see drivers from WCH vendor, Linux kernel and FreeBSD + TU_ASSERT (version >= 0x30,); + // init CH34x with line coding + cdc_line_coding_t const line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; + uint16_t const div_ps = ch34x_get_divisor_prescaler(line_coding.bit_rate); + TU_ASSERT(div_ps, ); + uint8_t const lcr = ch34x_get_lcr(line_coding.stop_bits, line_coding.parity, line_coding.data_bits); + TU_ASSERT(lcr, ); + TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, tu_u16(lcr, 0x9c), div_ps, + ch34x_process_config, CONFIG_CH34X_SPECIAL_REG_WRITE),); + break; + } + + case CONFIG_CH34X_SPECIAL_REG_WRITE: + // overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver + p_cdc->line_coding = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X); + TU_ASSERT (ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL),); + break; + + case CONFIG_CH34X_FLOW_CONTROL: + // no hardware flow control + TU_ASSERT (ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x27, CH341_REG_0x27), 0x0000, ch34x_process_config, CONFIG_CH34X_MODEM_CONTROL),); + break; + + case CONFIG_CH34X_MODEM_CONTROL: + // !always! set modem controls RTS/DTR (CH34x has no reset state after CH34X_REQ_SERIAL_INIT) + TU_ASSERT (ch34x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ch34x_process_config, CONFIG_CH34X_COMPLETE),); + break; + + case CONFIG_CH34X_COMPLETE: + set_config_complete(p_cdc, idx, itf_num); + break; + + default: + TU_ASSERT (false,); + break; + } +} + +//------------- CH34x helper -------------// + +// calculate divisor and prescaler for baudrate, return it as 16-bit combined value +static uint16_t ch34x_get_divisor_prescaler(uint32_t baval) { + uint8_t a; + uint8_t b; + uint32_t c; + + TU_VERIFY(baval != 0 && baval <= 2000000, 0); + switch (baval) { + case 921600: + a = 0xf3; + b = 7; + break; + + case 307200: + a = 0xd9; + b = 7; + break; + + default: + if (baval > 6000000 / 255) { + b = 3; + c = 6000000; + } else if (baval > 750000 / 255) { + b = 2; + c = 750000; + } else if (baval > 93750 / 255) { + b = 1; + c = 93750; + } else { + b = 0; + c = 11719; + } + a = (uint8_t) (c / baval); + if (a == 0 || a == 0xFF) { + return 0; + } + if ((c / a - baval) > (baval - c / (a + 1))) { + a++; + } + a = (uint8_t) (256 - a); + break; + } + + // reg divisor = a, reg prescaler = b + // According to linux code we need to set bit 7 of UCHCOM_REG_BPS_PRE, + // otherwise the chip will buffer data. + return (uint16_t) ((uint16_t)a << 8 | 0x80 | b); +} + +// calculate lcr value from data coding +static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bits) { + uint8_t lcr = CH34X_LCR_ENABLE_RX | CH34X_LCR_ENABLE_TX; + TU_VERIFY(data_bits >= 5 && data_bits <= 8, 0); + lcr |= (uint8_t) (data_bits - 5); + + switch(parity) { + case CDC_LINE_CODING_PARITY_NONE: + break; + + case CDC_LINE_CODING_PARITY_ODD: + lcr |= CH34X_LCR_ENABLE_PAR; + break; + + case CDC_LINE_CODING_PARITY_EVEN: + lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_PAR_EVEN; + break; + + case CDC_LINE_CODING_PARITY_MARK: + lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_MARK_SPACE; + break; + + case CDC_LINE_CODING_PARITY_SPACE: + lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_MARK_SPACE | CH34X_LCR_PAR_EVEN; + break; + + default: break; + } + + // 1.5 stop bits not supported + TU_VERIFY(stop_bits != CDC_LINE_CODING_STOP_BITS_1_5, 0); + if (stop_bits == CDC_LINE_CODING_STOP_BITS_2) { + lcr |= CH34X_LCR_STOP_BITS_2; + } + + return lcr; +} + + +#endif // CFG_TUH_CDC_CH34X + #endif diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 9e5edd94e..d512a23a5 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -148,8 +148,11 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c // Request to set baudrate bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -// Request to Set Line Coding (ACM only) -// Should only use if you don't work with serial devices such as FTDI/CP210x +// Request to set data format +bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + +// Request to Set Line Coding = baudrate + data format +// Note: only implemented by ACM and CH34x, not supported by FTDI and CP210x yet bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Get Line Coding (ACM only) @@ -159,15 +162,13 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, // Connect by set both DTR, RTS TU_ATTR_ALWAYS_INLINE static inline -bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return tuh_cdc_set_control_line_state(idx, CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS, complete_cb, user_data); } // Disconnect by clear both DTR, RTS TU_ATTR_ALWAYS_INLINE static inline -bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return tuh_cdc_set_control_line_state(idx, 0x00, complete_cb, user_data); } diff --git a/src/class/cdc/serial/ch34x.h b/src/class/cdc/serial/ch34x.h new file mode 100644 index 000000000..c18066f57 --- /dev/null +++ b/src/class/cdc/serial/ch34x.h @@ -0,0 +1,84 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Heiko Kuester + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _CH34X_H_ +#define _CH34X_H_ + +// There is no official documentation for the CH34x (CH340, CH341) chips. Reference can be found +// - https://github.com/WCHSoftGroup/ch341ser_linux +// - https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ch341.c +// - https://github.com/freebsd/freebsd-src/blob/main/sys/dev/usb/serial/uchcom.c + +// set line_coding @ enumeration +#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM +#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X CFG_TUH_CDC_LINE_CODING_ON_ENUM +#else // this default is necessary to work properly +#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X { 9600, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } +#endif + +// USB requests +#define CH34X_REQ_READ_VERSION 0x5F // dec 95 +#define CH34X_REQ_WRITE_REG 0x9A // dec 154 +#define CH34X_REQ_READ_REG 0x95 // dec 149 +#define CH34X_REQ_SERIAL_INIT 0xA1 // dec 161 +#define CH34X_REQ_MODEM_CTRL 0xA4 // dev 164 + +// registers +#define CH34X_REG_BREAK 0x05 +#define CH34X_REG_PRESCALER 0x12 +#define CH34X_REG_DIVISOR 0x13 +#define CH34X_REG_LCR 0x18 +#define CH34X_REG_LCR2 0x25 +#define CH34X_REG_MCR_MSR 0x06 +#define CH34X_REG_MCR_MSR2 0x07 +#define CH34X_NBREAK_BITS 0x01 + +#define CH341_REG_0x0F 0x0F // undocumented register +#define CH341_REG_0x2C 0x2C // undocumented register +#define CH341_REG_0x27 0x27 // hardware flow control (cts/rts) + +#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER) +#define CH32X_REG16_LCR2_LCR TU_U16(CH34X_REG_LCR2, CH34X_REG_LCR) + +// modem control bits +#define CH34X_BIT_RTS ( 1 << 6 ) +#define CH34X_BIT_DTR ( 1 << 5 ) + +// line control bits +#define CH34X_LCR_ENABLE_RX 0x80 +#define CH34X_LCR_ENABLE_TX 0x40 +#define CH34X_LCR_MARK_SPACE 0x20 +#define CH34X_LCR_PAR_EVEN 0x10 +#define CH34X_LCR_ENABLE_PAR 0x08 +#define CH34X_LCR_PAR_MASK 0x38 // all parity bits +#define CH34X_LCR_STOP_BITS_2 0x04 +#define CH34X_LCR_CS8 0x03 +#define CH34X_LCR_CS7 0x02 +#define CH34X_LCR_CS6 0x01 +#define CH34X_LCR_CS5 0x00 +#define CH34X_LCR_CS_MASK 0x03 // all CSx bits + +#endif /* _CH34X_H_ */ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index db52b503f..709fa3dd8 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -50,6 +50,7 @@ typedef struct uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; + bool mounted; // Enumeration is complete uint8_t itf_protocol; // None, Keyboard, Mouse uint8_t protocol_mode; // Boot (0) or Report protocol (1) @@ -139,7 +140,8 @@ uint8_t tuh_hid_itf_get_total_count(void) bool tuh_hid_mounted(uint8_t daddr, uint8_t idx) { hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - return p_hid != NULL; + TU_VERIFY(p_hid); + return p_hid->mounted; } bool tuh_hid_itf_get_info(uint8_t daddr, uint8_t idx, tuh_itf_info_t* info) @@ -463,6 +465,7 @@ void hidh_close(uint8_t daddr) TU_LOG_DRV(" HIDh close addr = %u index = %u\r\n", daddr, i); if(tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i); p_hid->daddr = 0; + p_hid->mounted = false; } } } @@ -632,6 +635,7 @@ static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t con { hidh_interface_t* p_hid = get_hid_itf(daddr, idx); TU_VERIFY(p_hid, ); + p_hid->mounted = true; // enumeration is complete if (tuh_hid_mount_cb) tuh_hid_mount_cb(daddr, idx, desc_report, desc_len); diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 389a29696..a68cb2156 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -49,10 +49,8 @@ typedef struct uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE]; uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE]; -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; -#endif + OSAL_MUTEX_DEF(rx_ff_mutex); + OSAL_MUTEX_DEF(tx_ff_mutex); // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_VENDOR_EPSIZE]; @@ -183,10 +181,8 @@ void vendord_init(void) tu_fifo_config(&p_itf->rx_ff, p_itf->rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, 1, false); tu_fifo_config(&p_itf->tx_ff, p_itf->tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, 1, false); -#if CFG_FIFO_MUTEX tu_fifo_config_mutex(&p_itf->rx_ff, NULL, osal_mutex_create(&p_itf->rx_ff_mutex)); tu_fifo_config_mutex(&p_itf->tx_ff, osal_mutex_create(&p_itf->tx_ff_mutex), NULL); -#endif } } diff --git a/src/class/video/video.h b/src/class/video/video.h index d9880c291..6319c6536 100644 --- a/src/class/video/video.h +++ b/src/class/video/video.h @@ -29,6 +29,10 @@ #include "common/tusb_common.h" +enum { + VIDEO_BCD_1_50 = 0x0150, +}; + // Table 3-19 Color Matching Descriptor typedef enum { VIDEO_COLOR_PRIMARIES_UNDEFINED = 0x00, @@ -198,55 +202,98 @@ typedef enum { } video_terminal_type_t; //--------------------------------------------------------------------+ -// Descriptors +// Video Control (VC) Descriptors //--------------------------------------------------------------------+ /* 2.3.4.2 */ +#define tusb_desc_video_control_header_nitf_t(_nitf) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t bDescriptorSubType; \ + uint16_t bcdUVC; \ + uint16_t wTotalLength; \ + uint32_t dwClockFrequency; /* deprecated */ \ + uint8_t bInCollection; \ + uint8_t baInterfaceNr[_nitf]; \ + } + +typedef tusb_desc_video_control_header_nitf_t() tusb_desc_video_control_header_t; +typedef tusb_desc_video_control_header_nitf_t(1) tusb_desc_video_control_header_1itf_t; +typedef tusb_desc_video_control_header_nitf_t(2) tusb_desc_video_control_header_2itf_t; +typedef tusb_desc_video_control_header_nitf_t(3) tusb_desc_video_control_header_3itf_t; +typedef tusb_desc_video_control_header_nitf_t(4) tusb_desc_video_control_header_4itf_t; + typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubType; - uint16_t bcdUVC; - uint16_t wTotalLength; - uint32_t dwClockFrequency; - uint8_t bInCollection; - uint8_t baInterfaceNr[]; -} tusb_desc_cs_video_ctl_itf_hdr_t; + uint8_t bTerminalID; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t iTerminal; +} tusb_desc_video_control_input_terminal_t; + +TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_input_terminal_t) == 8, "size is not correct"); -/* 2.4.3.3 */ typedef struct TU_ATTR_PACKED { - uint8_t bHeaderLength; - union { - uint8_t bmHeaderInfo; - struct { - uint8_t FrameID: 1; - uint8_t EndOfFrame: 1; - uint8_t PresentationTime: 1; - uint8_t SourceClockReference: 1; - uint8_t PayloadSpecific: 1; - uint8_t StillImage: 1; - uint8_t Error: 1; - uint8_t EndOfHeader: 1; - }; - }; -} tusb_video_payload_header_t; + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bTerminalID; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t bSourceID; + uint8_t iTerminal; +} tusb_desc_video_control_output_terminal_t; + +TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_output_terminal_t) == 9, "size is not correct"); -/* 3.9.2.1 */ typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubType; - uint8_t bNumFormats; - uint16_t wTotalLength; - uint8_t bEndpointAddress; - uint8_t bmInfo; - uint8_t bTerminalLink; - uint8_t bStillCaptureMethod; - uint8_t bTriggerSupport; - uint8_t bTriggerUsage; + uint8_t bTerminalID; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t iTerminal; + + uint16_t wObjectiveFocalLengthMin; + uint16_t wObjectiveFocalLengthMax; + uint16_t wOcularFocalLength; uint8_t bControlSize; - uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_in_hdr_t; + uint8_t bmControls[3]; +} tusb_desc_video_control_camera_terminal_t; + +TU_VERIFY_STATIC(sizeof(tusb_desc_video_control_camera_terminal_t) == 18, "size is not correct"); + +//--------------------------------------------------------------------+ +// Video Streaming (VS) Descriptors +//--------------------------------------------------------------------+ + +/* 3.9.2.1 */ +#define tusb_desc_video_streaming_input_header_nbyte_t(_nb) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t bDescriptorSubType; \ + uint8_t bNumFormats; /* Number of video payload Format descriptors for this interface */ \ + uint16_t wTotalLength; \ + uint8_t bEndpointAddress; \ + uint8_t bmInfo; /* Bit 0: dynamic format change supported */ \ + uint8_t bTerminalLink; \ + uint8_t bStillCaptureMethod; \ + uint8_t bTriggerSupport; /* Hardware trigger supported */ \ + uint8_t bTriggerUsage; \ + uint8_t bControlSize; /* sizeof of each control item */ \ + uint8_t bmaControls[_nb]; \ + } + +typedef tusb_desc_video_streaming_input_header_nbyte_t() tusb_desc_video_streaming_input_header_t; +typedef tusb_desc_video_streaming_input_header_nbyte_t(1) tusb_desc_video_streaming_input_header_1byte_t; +typedef tusb_desc_video_streaming_input_header_nbyte_t(2) tusb_desc_video_streaming_input_header_2byte_t; +typedef tusb_desc_video_streaming_input_header_nbyte_t(3) tusb_desc_video_streaming_input_header_3byte_t; +typedef tusb_desc_video_streaming_input_header_nbyte_t(4) tusb_desc_video_streaming_input_header_4byte_t; /* 3.9.2.2 */ typedef struct TU_ATTR_PACKED { @@ -259,7 +306,7 @@ typedef struct TU_ATTR_PACKED { uint8_t bTerminalLink; uint8_t bControlSize; uint8_t bmaControls[]; -} tusb_desc_cs_video_stm_itf_out_hdr_t; +} tusb_desc_video_streaming_output_header_t; typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -285,14 +332,33 @@ typedef struct TU_ATTR_PACKED { uint8_t bmaControls[]; } output; }; -} tusb_desc_cs_video_stm_itf_hdr_t; +} tusb_desc_video_streaming_inout_header_t; + +// 3.9.2.6 Color Matching Descriptor +typedef struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bColorPrimaries; + uint8_t bTransferCharacteristics; + uint8_t bMatrixCoefficients; +} tusb_desc_video_streaming_color_matching_t; +TU_VERIFY_STATIC(sizeof(tusb_desc_video_streaming_color_matching_t) == 6, "size is not correct"); + +//--------------------------------------------------------------------+ +// Format and Frame Descriptor +// Note: bFormatIndex & bFrameIndex are 1-based index +//--------------------------------------------------------------------+ + +//------------- Uncompressed -------------// +// Uncompressed payload specs: 3.1.1 format descriptor typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubType; uint8_t bFormatIndex; - uint8_t bNumFrameDescriptors; + uint8_t bNumFrameDescriptors; // Number of frame descriptors for this format uint8_t guidFormat[16]; uint8_t bBitsPerPixel; uint8_t bDefaultFrameIndex; @@ -300,22 +366,65 @@ typedef struct TU_ATTR_PACKED { uint8_t bAspectRatioY; uint8_t bmInterlaceFlags; uint8_t bCopyProtect; -} tusb_desc_cs_video_fmt_uncompressed_t; - +} tusb_desc_video_format_uncompressed_t; + +// Uncompressed payload specs: 3.1.2 frame descriptor +#define tusb_desc_video_frame_uncompressed_nint_t(_nint) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t bDescriptorSubType; \ + uint8_t bFrameIndex; \ + uint8_t bmCapabilities; \ + uint16_t wWidth; \ + uint16_t wHeight; \ + uint32_t dwMinBitRate; \ + uint32_t dwMaxBitRate; \ + uint32_t dwMaxVideoFrameBufferSize; /* deprecated in 1.5 */ \ + uint32_t dwDefaultFrameInterval; \ + uint8_t bFrameIntervalType; \ + uint32_t dwFrameInterval[_nint]; \ + } + +typedef tusb_desc_video_frame_uncompressed_nint_t() tusb_desc_video_frame_uncompressed_t; +typedef tusb_desc_video_frame_uncompressed_nint_t(1) tusb_desc_video_frame_uncompressed_1int_t; +typedef tusb_desc_video_frame_uncompressed_nint_t(2) tusb_desc_video_frame_uncompressed_2int_t; +typedef tusb_desc_video_frame_uncompressed_nint_t(3) tusb_desc_video_frame_uncompressed_3int_t; +typedef tusb_desc_video_frame_uncompressed_nint_t(4) tusb_desc_video_frame_uncompressed_4int_t; + +// continuous = 3 intervals: min, max, step +typedef tusb_desc_video_frame_uncompressed_3int_t tusb_desc_video_frame_uncompressed_continuous_t; + +TU_VERIFY_STATIC(sizeof(tusb_desc_video_frame_uncompressed_continuous_t) == 38, "size is not correct"); + +//------------- MJPEG -------------// +// MJPEG payload specs: 3.1.1 format descriptor typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDescriptorSubType; uint8_t bFormatIndex; uint8_t bNumFrameDescriptors; - uint8_t bmFlags; + uint8_t bmFlags; // Bit 0: fixed size samples (1 = yes) uint8_t bDefaultFrameIndex; uint8_t bAspectRatioX; uint8_t bAspectRatioY; uint8_t bmInterlaceFlags; uint8_t bCopyProtect; -} tusb_desc_cs_video_fmt_mjpeg_t; +} tusb_desc_video_format_mjpeg_t; +// MJPEG payload specs: 3.1.2 frame descriptor (same as uncompressed) +typedef tusb_desc_video_frame_uncompressed_t tusb_desc_video_frame_mjpeg_t; +typedef tusb_desc_video_frame_uncompressed_1int_t tusb_desc_video_frame_mjpeg_1int_t; +typedef tusb_desc_video_frame_uncompressed_2int_t tusb_desc_video_frame_mjpeg_2int_t; +typedef tusb_desc_video_frame_uncompressed_3int_t tusb_desc_video_frame_mjpeg_3int_t; +typedef tusb_desc_video_frame_uncompressed_4int_t tusb_desc_video_frame_mjpeg_4int_t; + +// continuous = 3 intervals: min, max, step +typedef tusb_desc_video_frame_mjpeg_3int_t tusb_desc_video_frame_mjpeg_continuous_t; + +//------------- DV -------------// +// DV payload specs: 3.1.1 typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; @@ -323,8 +432,9 @@ typedef struct TU_ATTR_PACKED { uint8_t bFormatIndex; uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ uint8_t bFormatType; -} tusb_desc_cs_video_fmt_dv_t; +} tusb_desc_video_format_dv_t; +// Frame Based payload specs: 3.1.1 typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; @@ -339,25 +449,7 @@ typedef struct TU_ATTR_PACKED { uint8_t bmInterlaceFlags; uint8_t bCopyProtect; uint8_t bVaribaleSize; -} tusb_desc_cs_video_fmt_frame_based_t; - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubType; - uint8_t bFrameIndex; - uint8_t bmCapabilities; - uint16_t wWidth; - uint16_t wHeight; - uint32_t dwMinBitRate; - uint32_t dwMaxBitRate; - uint32_t dwMaxVideoFrameBufferSize; /* deprecated */ - uint32_t dwDefaultFrameInterval; - uint8_t bFrameIntervalType; - uint32_t dwFrameInterval[]; -} tusb_desc_cs_video_frm_uncompressed_t; - -typedef tusb_desc_cs_video_frm_uncompressed_t tusb_desc_cs_video_frm_mjpeg_t; +} tusb_desc_video_format_framebased_t; typedef struct TU_ATTR_PACKED { uint8_t bLength; @@ -373,12 +465,30 @@ typedef struct TU_ATTR_PACKED { uint8_t bFrameIntervalType; uint32_t dwBytesPerLine; uint32_t dwFrameInterval[]; -} tusb_desc_cs_video_frm_frame_based_t; +} tusb_desc_video_frame_framebased_t; //--------------------------------------------------------------------+ // Requests //--------------------------------------------------------------------+ +/* 2.4.3.3 */ +typedef struct TU_ATTR_PACKED { + uint8_t bHeaderLength; + union { + uint8_t bmHeaderInfo; + struct { + uint8_t FrameID: 1; + uint8_t EndOfFrame: 1; + uint8_t PresentationTime: 1; + uint8_t SourceClockReference: 1; + uint8_t PayloadSpecific: 1; + uint8_t StillImage: 1; + uint8_t Error: 1; + uint8_t EndOfHeader: 1; + }; + }; +} tusb_video_payload_header_t; + /* 4.3.1.1 */ typedef struct TU_ATTR_PACKED { union { @@ -537,7 +647,7 @@ TU_VERIFY_STATIC( sizeof(video_probe_and_commit_control_t) == 48, "size is not c /* Motion-JPEG 3.1.1 Table 3-2 and 3-4 */ #define TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC(_frmidx, _cap, _width, _height, _minbr, _maxbr, _maxfrmbufsz, _frminterval, ...) \ TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_DISC_LEN + (TU_ARGS_NUM(__VA_ARGS__)) * 4, \ - TUSB_DESC_CS_INTERFACE, VIDEO_CS_VS_INTERFACE_FRAME_MJPEG, \ + TUSB_DESC_CS_INTERFACE, VIDEO_CS_ITF_VS_FRAME_MJPEG, \ _frmidx, _cap, U16_TO_U8S_LE(_width), U16_TO_U8S_LE(_height), U32_TO_U8S_LE(_minbr), U32_TO_U8S_LE(_maxbr), \ U32_TO_U8S_LE(_maxfrmbufsz), U32_TO_U8S_LE(_frminterval), (TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c index 3b29454a3..1affd615e 100644 --- a/src/class/video/video_device.c +++ b/src/class/video/video_device.c @@ -50,17 +50,17 @@ typedef struct { tusb_desc_interface_t std; - tusb_desc_cs_video_ctl_itf_hdr_t ctl; + tusb_desc_video_control_header_t ctl; } tusb_desc_vc_itf_t; typedef struct { tusb_desc_interface_t std; - tusb_desc_cs_video_stm_itf_hdr_t stm; + tusb_desc_video_streaming_inout_header_t stm; } tusb_desc_vs_itf_t; typedef union { - tusb_desc_cs_video_ctl_itf_hdr_t ctl; - tusb_desc_cs_video_stm_itf_hdr_t stm; + tusb_desc_video_control_header_t ctl; + tusb_desc_video_streaming_inout_header_t stm; } tusb_desc_video_itf_hdr_t; typedef struct TU_ATTR_PACKED { @@ -78,9 +78,9 @@ typedef union { uint8_t bFormatIndex; uint8_t bNumFrameDescriptors; }; - tusb_desc_cs_video_fmt_uncompressed_t uncompressed; - tusb_desc_cs_video_fmt_mjpeg_t mjpeg; - tusb_desc_cs_video_fmt_frame_based_t frame_based; + tusb_desc_video_format_uncompressed_t uncompressed; + tusb_desc_video_format_mjpeg_t mjpeg; + tusb_desc_video_format_framebased_t frame_based; } tusb_desc_cs_video_fmt_t; typedef union { @@ -93,9 +93,9 @@ typedef union { uint16_t wWidth; uint16_t wHeight; }; - tusb_desc_cs_video_frm_uncompressed_t uncompressed; - tusb_desc_cs_video_frm_mjpeg_t mjpeg; - tusb_desc_cs_video_frm_frame_based_t frame_based; + tusb_desc_video_frame_uncompressed_t uncompressed; + tusb_desc_video_frame_mjpeg_t mjpeg; + tusb_desc_video_frame_framebased_t frame_based; } tusb_desc_cs_video_frm_t; /* video streaming interface */ @@ -434,8 +434,9 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm uint_fast32_t interval_ms = interval / 10000; TU_ASSERT(interval_ms); uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; - if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) + if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) { payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE; + } param->dwMaxPayloadTransferSize = payload_size; return true; } @@ -577,8 +578,9 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * } else { payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; } - if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) + if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) { payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE; + } param->dwMaxPayloadTransferSize = payload_size; } return true; diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index caeb5f2ef..1f08ce4ed 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -37,6 +37,7 @@ #define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) #define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) ) #define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) ) +#define TU_DIV_CEIL(n, d) (((n) + (d) - 1) / (d)) #define TU_U16(_high, _low) ((uint16_t) (((_high) << 8) | (_low))) #define TU_U16_HIGH(_u16) ((uint8_t) (((_u16) >> 8) & 0x00ff)) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index fab680989..2c5dce723 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -44,43 +44,38 @@ *------------------------------------------------------------------*/ /// defined base on EHCI specs value for Endpoint Speed -typedef enum -{ +typedef enum { TUSB_SPEED_FULL = 0, TUSB_SPEED_LOW = 1, TUSB_SPEED_HIGH = 2, TUSB_SPEED_INVALID = 0xff, -}tusb_speed_t; +} tusb_speed_t; /// defined base on USB Specs Endpoint's bmAttributes -typedef enum -{ +typedef enum { TUSB_XFER_CONTROL = 0 , TUSB_XFER_ISOCHRONOUS , TUSB_XFER_BULK , TUSB_XFER_INTERRUPT -}tusb_xfer_type_t; +} tusb_xfer_type_t; -typedef enum -{ +typedef enum { TUSB_DIR_OUT = 0, TUSB_DIR_IN = 1, TUSB_DIR_IN_MASK = 0x80 -}tusb_dir_t; +} tusb_dir_t; -enum -{ +enum { TUSB_EPSIZE_BULK_FS = 64, - TUSB_EPSIZE_BULK_HS= 512, + TUSB_EPSIZE_BULK_HS = 512, TUSB_EPSIZE_ISO_FS_MAX = 1023, TUSB_EPSIZE_ISO_HS_MAX = 1024, }; -/// Isochronous End Point Attributes -typedef enum -{ +/// Isochronous Endpoint Attributes +typedef enum { TUSB_ISO_EP_ATT_NO_SYNC = 0x00, TUSB_ISO_EP_ATT_ASYNCHRONOUS = 0x04, TUSB_ISO_EP_ATT_ADAPTIVE = 0x08, @@ -88,11 +83,10 @@ typedef enum TUSB_ISO_EP_ATT_DATA = 0x00, ///< Data End Point TUSB_ISO_EP_ATT_EXPLICIT_FB = 0x10, ///< Feedback End Point TUSB_ISO_EP_ATT_IMPLICIT_FB = 0x20, ///< Data endpoint that also serves as an implicit feedback -}tusb_iso_ep_attribute_t; +} tusb_iso_ep_attribute_t; /// USB Descriptor Types -typedef enum -{ +typedef enum { TUSB_DESC_DEVICE = 0x01, TUSB_DESC_CONFIGURATION = 0x02, TUSB_DESC_STRING = 0x03, @@ -119,10 +113,9 @@ typedef enum TUSB_DESC_SUPERSPEED_ENDPOINT_COMPANION = 0x30, TUSB_DESC_SUPERSPEED_ISO_ENDPOINT_COMPANION = 0x31 -}tusb_desc_type_t; +} tusb_desc_type_t; -typedef enum -{ +typedef enum { TUSB_REQ_GET_STATUS = 0 , TUSB_REQ_CLEAR_FEATURE = 1 , TUSB_REQ_RESERVED = 2 , @@ -136,25 +129,22 @@ typedef enum TUSB_REQ_GET_INTERFACE = 10 , TUSB_REQ_SET_INTERFACE = 11 , TUSB_REQ_SYNCH_FRAME = 12 -}tusb_request_code_t; +} tusb_request_code_t; -typedef enum -{ +typedef enum { TUSB_REQ_FEATURE_EDPT_HALT = 0, TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1, TUSB_REQ_FEATURE_TEST_MODE = 2 -}tusb_request_feature_selector_t; +} tusb_request_feature_selector_t; -typedef enum -{ +typedef enum { TUSB_REQ_TYPE_STANDARD = 0, TUSB_REQ_TYPE_CLASS, TUSB_REQ_TYPE_VENDOR, TUSB_REQ_TYPE_INVALID } tusb_request_type_t; -typedef enum -{ +typedef enum { TUSB_REQ_RCPT_DEVICE =0, TUSB_REQ_RCPT_INTERFACE, TUSB_REQ_RCPT_ENDPOINT, @@ -162,8 +152,7 @@ typedef enum } tusb_request_recipient_t; // https://www.usb.org/defined-class-codes -typedef enum -{ +typedef enum { TUSB_CLASS_UNSPECIFIED = 0 , TUSB_CLASS_AUDIO = 1 , TUSB_CLASS_CDC = 2 , @@ -187,26 +176,23 @@ typedef enum TUSB_CLASS_MISC = 0xEF , TUSB_CLASS_APPLICATION_SPECIFIC = 0xFE , TUSB_CLASS_VENDOR_SPECIFIC = 0xFF -}tusb_class_code_t; +} tusb_class_code_t; typedef enum { MISC_SUBCLASS_COMMON = 2 }misc_subclass_type_t; -typedef enum -{ +typedef enum { MISC_PROTOCOL_IAD = 1 -}misc_protocol_type_t; +} misc_protocol_type_t; -typedef enum -{ +typedef enum { APP_SUBCLASS_USBTMC = 0x03, APP_SUBCLASS_DFU_RUNTIME = 0x01 } app_subclass_type_t; -typedef enum -{ +typedef enum { DEVICE_CAPABILITY_WIRELESS_USB = 0x01, DEVICE_CAPABILITY_USB20_EXTENSION = 0x02, DEVICE_CAPABILITY_SUPERSPEED_USB = 0x03, @@ -223,7 +209,7 @@ typedef enum DEVICE_CAPABILITY_AUTHENTICATION = 0x0E, DEVICE_CAPABILITY_BILLBOARD_EX = 0x0F, DEVICE_CAPABILITY_CONFIGURATION_SUMMARY = 0x10 -}device_capability_type_t; +} device_capability_type_t; enum { TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = TU_BIT(5), @@ -235,28 +221,25 @@ enum { //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ -typedef enum -{ +typedef enum { XFER_RESULT_SUCCESS = 0, XFER_RESULT_FAILED, XFER_RESULT_STALLED, XFER_RESULT_TIMEOUT, XFER_RESULT_INVALID -}xfer_result_t; +} xfer_result_t; -enum // TODO remove -{ +// TODO remove +enum { DESC_OFFSET_LEN = 0, DESC_OFFSET_TYPE = 1 }; -enum -{ +enum { INTERFACE_INVALID_NUMBER = 0xff }; -typedef enum -{ +typedef enum { MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00, MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01, MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02, @@ -268,16 +251,14 @@ typedef enum MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 } microsoft_os_20_type_t; -enum -{ +enum { CONTROL_STAGE_IDLE, CONTROL_STAGE_SETUP, CONTROL_STAGE_DATA, CONTROL_STAGE_ACK }; -enum -{ +enum { TUSB_INDEX_INVALID_8 = 0xFFu }; @@ -290,8 +271,7 @@ TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN /// USB Device Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< DEVICE Descriptor Type. uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). This field identifies the release of the USB Specification with which the device and its descriptors are compliant. @@ -314,8 +294,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); // USB Binary Device Object Store (BOS) Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type uint16_t wTotalLength ; ///< Total length of data returned for this descriptor @@ -325,8 +304,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct"); /// USB Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type uint16_t wTotalLength ; ///< Total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration. @@ -341,8 +319,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); /// USB Interface Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< INTERFACE Descriptor Type @@ -358,8 +335,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct"); /// USB Endpoint Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; // Size of this descriptor in bytes uint8_t bDescriptorType ; // ENDPOINT Descriptor Type @@ -379,8 +355,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7, "size is not correct"); /// USB Other Speed Configuration Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Other_speed_Configuration Type uint16_t wTotalLength ; ///< Total length of data returned @@ -393,8 +368,7 @@ typedef struct TU_ATTR_PACKED } tusb_desc_other_speed_t; /// USB Device Qualifier Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Device Qualifier Type uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) @@ -411,8 +385,7 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct"); /// USB Interface Association Descriptor (IAD ECN) -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of descriptor uint8_t bDescriptorType ; ///< Other_speed_Configuration Type @@ -426,17 +399,17 @@ typedef struct TU_ATTR_PACKED uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. } tusb_desc_interface_assoc_t; +TU_VERIFY_STATIC( sizeof(tusb_desc_interface_assoc_t) == 8, "size is not correct"); + // USB String Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< Descriptor Type uint16_t unicode_string[]; } tusb_desc_string_t; // USB Binary Device Object Store (BOS) -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType ; uint8_t bDevCapabilityType; @@ -445,9 +418,8 @@ typedef struct TU_ATTR_PACKED uint8_t CapabilityData[]; } tusb_desc_bos_platform_t; -// USB WebuSB URL Descriptor -typedef struct TU_ATTR_PACKED -{ +// USB WebUSB URL Descriptor +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; uint8_t bScheme; @@ -455,8 +427,7 @@ typedef struct TU_ATTR_PACKED } tusb_desc_webusb_url_t; // DFU Functional Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength; uint8_t bDescriptorType; @@ -481,7 +452,7 @@ typedef struct TU_ATTR_PACKED // //--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED{ +typedef struct TU_ATTR_PACKED { union { struct TU_ATTR_PACKED { uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. @@ -500,7 +471,6 @@ typedef struct TU_ATTR_PACKED{ TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); - TU_ATTR_PACKED_END // End of all packed definitions TU_ATTR_BIT_FIELD_ORDER_END @@ -509,36 +479,30 @@ TU_ATTR_BIT_FIELD_ORDER_END //--------------------------------------------------------------------+ // Get direction from Endpoint address -TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) -{ +TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) { return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; } // Get Endpoint number from address -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) { return (uint8_t)(addr & (~TUSB_DIR_IN_MASK)); } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) { return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0)); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) { return tu_le16toh(desc_ep->wMaxPacketSize) & TU_GENMASK(10, 0); } #if CFG_TUSB_DEBUG -TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_dir_str(tusb_dir_t dir) -{ +TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_dir_str(tusb_dir_t dir) { tu_static const char *str[] = {"out", "in"}; return str[dir]; } -TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t) -{ +TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_t t) { tu_static const char *str[] = {"control", "isochronous", "bulk", "interrupt"}; return str[t]; } @@ -549,21 +513,18 @@ TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_ //--------------------------------------------------------------------+ // return next descriptor -TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) { uint8_t const* desc8 = (uint8_t const*) desc; return desc8 + desc8[DESC_OFFSET_LEN]; } // get descriptor type -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; } // get descriptor length -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index ac93632be..3e15d51c6 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1130,8 +1130,8 @@ void dcd_int_handler(uint8_t rhport) { dwc2->gotgint = otg_int; } - if (int_status & GINTSTS_SOF) { - dwc2->gotgint = GINTSTS_SOF; + if(int_status & GINTSTS_SOF) { + dwc2->gintsts = GINTSTS_SOF; if (_sof_en) { uint32_t frame = (dwc2->dsts & (DSTS_FNSOF)) >> 8; diff --git a/src/tusb_option.h b/src/tusb_option.h index 57f026312..767323bdd 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -472,6 +472,23 @@ {0x10C4, 0xEA60}, {0x10C4, 0xEA70} #endif +#ifndef CFG_TUH_CDC_CH34X + // CH34X is not part of CDC class, only to re-use CDC driver API + #define CFG_TUH_CDC_CH34X 0 +#endif + +#ifndef CFG_TUH_CDC_CH34X_VID_PID_LIST + // List of product IDs that can use the CH34X CDC driver + #define CFG_TUH_CDC_CH34X_VID_PID_LIST \ + { 0x1a86, 0x5523 }, /* ch341 chip */ \ + { 0x1a86, 0x7522 }, /* ch340k chip */ \ + { 0x1a86, 0x7523 }, /* ch340 chip */ \ + { 0x1a86, 0xe523 }, /* ch330 chip */ \ + { 0x4348, 0x5523 }, /* ch340 custom chip */ \ + { 0x2184, 0x0057 }, /* overtaken from Linux Kernel driver /drivers/usb/serial/ch341.c */ \ + { 0x9986, 0x7523 } /* overtaken from Linux Kernel driver /drivers/usb/serial/ch341.c */ +#endif + #ifndef CFG_TUH_HID #define CFG_TUH_HID 0 #endif diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 7c662aeea..7f03ce43f 100644 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -364,8 +364,15 @@ def main(config_file, board): print(f' {test} ...', end='') - # flash firmware - ret = globals()[f'flash_{flasher}'](item, fw) + # flash firmware. It may fail randomly, retry a few times + for i in range(3): + ret = globals()[f'flash_{flasher}'](item, fw) + if ret.returncode == 0: + break + else: + print(f'Flashing failed, retry {i+1}') + time.sleep(1) + assert ret.returncode == 0, 'Flash failed\n' + ret.stdout.decode() # run test -- cgit v1.3.1 From b9c6b22165ce1912ec40b808570e13756e8faf4e Mon Sep 17 00:00:00 2001 From: Jerry Palacios Date: Thu, 8 Feb 2024 11:10:10 -0600 Subject: cortex m33+nodsp+nofpu make file created --- .../build_system/make/cpu/cortex-m33-nodsp-nofp.mk | 18 ++++++++++++++++++ hw/bsp/mcxa/boards/frdmmcxa153/board.mk | 13 ------------- hw/bsp/mcxa/family.mk | 2 +- 3 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk (limited to 'examples') diff --git a/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk new file mode 100644 index 000000000..0a2f99ab0 --- /dev/null +++ b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk @@ -0,0 +1,18 @@ +ifeq ($(TOOLCHAIN),gcc) + CFLAGS += \ + -mthumb \ + -mcpu=cortex-m33+nodsp \ + -mfloat-abi=soft \ + +#else ifeq ($(TOOLCHAIN),iar) +# CFLAGS += \ +# --cpu cortex-m33 \ +# --fpu VFPv5-SP \ +# +# ASFLAGS += \ +# --cpu cortex-m33 \ +# --fpu VFPv5-SP \ +# +endif +# +FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure \ No newline at end of file diff --git a/hw/bsp/mcxa/boards/frdmmcxa153/board.mk b/hw/bsp/mcxa/boards/frdmmcxa153/board.mk index e8797cd95..18f7e3cb5 100644 --- a/hw/bsp/mcxa/boards/frdmmcxa153/board.mk +++ b/hw/bsp/mcxa/boards/frdmmcxa153/board.mk @@ -4,19 +4,6 @@ PORT = 0 CFLAGS += \ -DCPU_MCXA153VLH \ - -DCPU_MCXA153VLH_cm33_nodsp \ - -DPRINTF_FLOAT_ENABLE=0 \ - -DSCANF_FLOAT_ENABLE=0 \ - -DPRINTF_ADVANCED_ENABLE=0 \ - -DSCANF_ADVANCED_ENABLE=0 \ - -mcpu=cortex-m33+nodsp+nofp+nosimd - -#FORCING NOT TO USE DPS AND FPU UNITS (THIS CHIP DOESN'T HAVE) -CFLAGS += -D__SOFTFP__ -# Undefine __ARM_FEATURE_DSP if it's already defined -CFLAGS += -U__ARM_FEATURE_DSP -# Define __ARM_FEATURE_DSP with the new value -CFLAGS += -D__ARM_FEATURE_DSP=0 JLINK_DEVICE = MCXA153 diff --git a/hw/bsp/mcxa/family.mk b/hw/bsp/mcxa/family.mk index b32282d04..87ae92fab 100644 --- a/hw/bsp/mcxa/family.mk +++ b/hw/bsp/mcxa/family.mk @@ -4,7 +4,7 @@ SDK_DIR = hw/mcu/nxp/mcux-sdk DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5 #not found include $(TOP)/$(BOARD_PATH)/board.mk -CPU_CORE ?= cortex-m33 +CPU_CORE ?= cortex-m33-nodsp-nofp CFLAGS += \ -flto \ -- cgit v1.3.1 From b44cae8f182408031290268ca7b42f3c77665225 Mon Sep 17 00:00:00 2001 From: Jerry Palacios Date: Fri, 9 Feb 2024 11:07:51 -0600 Subject: frdmmcxa153 now working with cmake+ninja --- .../build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake | 17 +++++++++++++++++ .../build_system/make/cpu/cortex-m33-nodsp-nofp.mk | 18 ++++++++---------- hw/bsp/mcxa/family.cmake | 4 ++-- 3 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake (limited to 'examples') diff --git a/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake b/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake new file mode 100644 index 000000000..7946affbe --- /dev/null +++ b/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake @@ -0,0 +1,17 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -mthumb + -mcpu=cortex-m33+nodsp + -mfloat-abi=soft + ) + + set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "iar") + set(TOOLCHAIN_COMMON_FLAGS + --cpu cortex-m33+nodsp + ) + + set(FREERTOS_PORT IAR_ARM_CM4F CACHE INTERNAL "") + +endif () diff --git a/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk index 0a2f99ab0..f74f46d54 100644 --- a/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk +++ b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk @@ -4,15 +4,13 @@ ifeq ($(TOOLCHAIN),gcc) -mcpu=cortex-m33+nodsp \ -mfloat-abi=soft \ -#else ifeq ($(TOOLCHAIN),iar) -# CFLAGS += \ -# --cpu cortex-m33 \ -# --fpu VFPv5-SP \ -# -# ASFLAGS += \ -# --cpu cortex-m33 \ -# --fpu VFPv5-SP \ -# +else ifeq ($(TOOLCHAIN),iar) + CFLAGS += \ + --cpu cortex-m33+nodsp \ + + ASFLAGS += \ + --cpu cortex-m33+nodsp \ + endif -# + FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure \ No newline at end of file diff --git a/hw/bsp/mcxa/family.cmake b/hw/bsp/mcxa/family.cmake index 0aa690afc..d2b2321d6 100644 --- a/hw/bsp/mcxa/family.cmake +++ b/hw/bsp/mcxa/family.cmake @@ -11,7 +11,7 @@ set(CMSIS_DIR ${TOP}/lib/CMSIS_5) include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) # toolchain set up -set(CMAKE_SYSTEM_PROCESSOR cortex-m33 CACHE INTERNAL "System Processor") +set(CMAKE_SYSTEM_PROCESSOR cortex-m33-nodsp-nofp CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) set(FAMILY_MCUS MCXA CACHE INTERNAL "") @@ -31,7 +31,7 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_gpio.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_common_arm.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_lpuart.c - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_lpflexcomm.c + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_spc.c # mcu ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_reset.c -- cgit v1.3.1 From 13d26d216613792e814dda4742ef7ab4fb9b0d37 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 22 Feb 2024 19:20:28 +0700 Subject: slightly change cdc_msc_freertos example --- examples/device/cdc_msc_freertos/src/main.c | 51 +++++++++++++++-------------- src/class/video/video.h | 6 +++- 2 files changed, 32 insertions(+), 25 deletions(-) (limited to 'examples') diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 1dadc4513..e94e8eaec 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -52,7 +52,8 @@ #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) #endif -#define CDC_STACK_SZIE configMINIMAL_STACK_SIZE +#define CDC_STACK_SIZE configMINIMAL_STACK_SIZE +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPES @@ -69,21 +70,22 @@ enum { BLINK_SUSPENDED = 2500, }; -// static timer & task +// static task #if configSUPPORT_STATIC_ALLOCATION -StaticTimer_t blinky_tmdef; +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; -StackType_t cdc_stack[CDC_STACK_SZIE]; +StackType_t cdc_stack[CDC_STACK_SIZE]; StaticTask_t cdc_taskdef; #endif -TimerHandle_t blinky_tm; +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; -static void led_blinky_cb(TimerHandle_t xTimer); static void usb_device_task(void *param); +void led_blinking_task(void* param); void cdc_task(void *params); //--------------------------------------------------------------------+ @@ -94,22 +96,20 @@ 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); + // blinky task + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); // Create a task for tinyusb device stack xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); // Create CDC task - xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); + xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SIZE, 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(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); 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) vTaskStartScheduler(); @@ -154,12 +154,12 @@ static void usb_device_task(void *param) { // Invoked when device is mounted void tud_mount_cb(void) { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); + blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted void tud_umount_cb(void) { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); + blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended @@ -167,16 +167,12 @@ void tud_umount_cb(void) { // Within 7ms, device must draw an average of current less than 2.5 mA from bus void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0); + blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed void tud_resume_cb(void) { - if (tud_mounted()) { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); - } else { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); - } + blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } //--------------------------------------------------------------------+ @@ -235,10 +231,17 @@ void tud_cdc_rx_cb(uint8_t itf) { //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -static void led_blinky_cb(TimerHandle_t xTimer) { - (void) xTimer; +void led_blinking_task(void* param) { + (void) param; + static uint32_t start_ms = 0; static bool led_state = false; - board_led_write(led_state); - led_state = 1 - led_state; // toggle + while (1) { + // Blink every interval ms + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } } diff --git a/src/class/video/video.h b/src/class/video/video.h index 6319c6536..abf1e34b9 100644 --- a/src/class/video/video.h +++ b/src/class/video/video.h @@ -368,6 +368,8 @@ typedef struct TU_ATTR_PACKED { uint8_t bCopyProtect; } tusb_desc_video_format_uncompressed_t; +TU_VERIFY_STATIC(sizeof(tusb_desc_video_format_uncompressed_t) == 27, "size is not correct"); + // Uncompressed payload specs: 3.1.2 frame descriptor #define tusb_desc_video_frame_uncompressed_nint_t(_nint) \ struct TU_ATTR_PACKED { \ @@ -381,7 +383,7 @@ typedef struct TU_ATTR_PACKED { uint32_t dwMinBitRate; \ uint32_t dwMaxBitRate; \ uint32_t dwMaxVideoFrameBufferSize; /* deprecated in 1.5 */ \ - uint32_t dwDefaultFrameInterval; \ + uint32_t dwDefaultFrameInterval; /* 100ns unit */\ uint8_t bFrameIntervalType; \ uint32_t dwFrameInterval[_nint]; \ } @@ -413,6 +415,8 @@ typedef struct TU_ATTR_PACKED { uint8_t bCopyProtect; } tusb_desc_video_format_mjpeg_t; +TU_VERIFY_STATIC(sizeof(tusb_desc_video_format_mjpeg_t) == 11, "size is not correct"); + // MJPEG payload specs: 3.1.2 frame descriptor (same as uncompressed) typedef tusb_desc_video_frame_uncompressed_t tusb_desc_video_frame_mjpeg_t; typedef tusb_desc_video_frame_uncompressed_1int_t tusb_desc_video_frame_mjpeg_1int_t; -- cgit v1.3.1 From ec91660119c6ce4ccc6aa011f2c6cc9869ab9410 Mon Sep 17 00:00:00 2001 From: Jerry Palacios Date: Thu, 22 Feb 2024 16:11:23 -0600 Subject: Revert "Merge branch 'hathach:master' into MCX" This reverts commit 6afd4a57896f9c9e794de3ab6eabc73d18be4bd0, reversing changes made to 5c14bd13da211ff2679115b0dba96ac80c1a516c. --- examples/device/cdc_msc_freertos/src/main.c | 51 +-- hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk | 3 + .../boards/frdm_k32l2a4s/clock_config.c | 491 --------------------- .../boards/frdm_k32l2a4s/clock_config.h | 164 ------- hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/board.mk | 3 + .../boards/frdm_k32l2b/clock_config.c | 220 --------- .../boards/frdm_k32l2b/clock_config.h | 110 ----- hw/bsp/nrf/boards/pca10095/board.cmake | 3 - hw/bsp/nrf/boards/pca10095/board.h | 4 +- hw/bsp/nrf/boards/pca10095/board.mk | 3 - hw/bsp/nrf/family.c | 1 - src/class/msc/msc_device.c | 2 +- src/class/video/video.h | 6 +- src/class/video/video_device.c | 1 - src/common/tusb_debug.h | 3 +- src/common/tusb_fifo.c | 1 - src/device/usbd.c | 1 + src/host/usbh.c | 22 +- src/host/usbh_pvt.h | 6 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 8 +- src/portable/ohci/ohci.h | 2 +- 21 files changed, 52 insertions(+), 1053 deletions(-) delete mode 100644 hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/clock_config.c delete mode 100644 hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/clock_config.h delete mode 100644 hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/clock_config.c delete mode 100644 hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/clock_config.h (limited to 'examples') diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index e94e8eaec..1dadc4513 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -52,8 +52,7 @@ #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) #endif -#define CDC_STACK_SIZE configMINIMAL_STACK_SIZE -#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define CDC_STACK_SZIE configMINIMAL_STACK_SIZE //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPES @@ -70,22 +69,21 @@ enum { BLINK_SUSPENDED = 2500, }; -// static task +// static timer & task #if configSUPPORT_STATIC_ALLOCATION -StackType_t blinky_stack[BLINKY_STACK_SIZE]; -StaticTask_t blinky_taskdef; +StaticTimer_t blinky_tmdef; StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; -StackType_t cdc_stack[CDC_STACK_SIZE]; +StackType_t cdc_stack[CDC_STACK_SZIE]; StaticTask_t cdc_taskdef; #endif -static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; +TimerHandle_t blinky_tm; +static void led_blinky_cb(TimerHandle_t xTimer); static void usb_device_task(void *param); -void led_blinking_task(void* param); void cdc_task(void *params); //--------------------------------------------------------------------+ @@ -96,20 +94,22 @@ int main(void) { board_init(); #if configSUPPORT_STATIC_ALLOCATION - // blinky task - xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); + // soft timer for blinky + blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); // Create a task for tinyusb device stack xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); // Create CDC task - xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, cdc_stack, &cdc_taskdef); + xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); #else - xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + 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) vTaskStartScheduler(); @@ -154,12 +154,12 @@ static void usb_device_task(void *param) { // Invoked when device is mounted void tud_mount_cb(void) { - blink_interval_ms = BLINK_MOUNTED; + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); } // Invoked when device is unmounted void tud_umount_cb(void) { - blink_interval_ms = BLINK_NOT_MOUNTED; + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); } // Invoked when usb bus is suspended @@ -167,12 +167,16 @@ void tud_umount_cb(void) { // Within 7ms, device must draw an average of current less than 2.5 mA from bus void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; - blink_interval_ms = BLINK_SUSPENDED; + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0); } // Invoked when usb bus is resumed void tud_resume_cb(void) { - blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; + if (tud_mounted()) { + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); + } else { + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); + } } //--------------------------------------------------------------------+ @@ -231,17 +235,10 @@ void tud_cdc_rx_cb(uint8_t itf) { //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void* param) { - (void) param; - static uint32_t start_ms = 0; +static void led_blinky_cb(TimerHandle_t xTimer) { + (void) xTimer; static bool led_state = false; - while (1) { - // Blink every interval ms - vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); - start_ms += blink_interval_ms; - - board_led_write(led_state); - led_state = 1 - led_state; // toggle - } + board_led_write(led_state); + led_state = 1 - led_state; // toggle } diff --git a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk index c4dc65b63..f69700139 100644 --- a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk +++ b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk @@ -8,6 +8,9 @@ CFLAGS += -Wno-error=unused-parameter -Wno-error=redundant-decls -Wno-error=cast # All source paths should be relative to the top level. LD_FILE = $(MCU_DIR)/gcc/K32L2A41xxxxA_flash.ld +SRC_C += \ + $(MCU_DIR)/project_template/clock_config.c \ + # For flash-jlink target JLINK_DEVICE = K32L2A41xxxxA diff --git a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/clock_config.c b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/clock_config.c deleted file mode 100644 index 2814efc86..000000000 --- a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/clock_config.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright 2019 ,2021 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ -/* - * How to setup clock using clock driver functions: - * - * 1. Call CLOCK_InitXXX() to configure corresponding SCG clock source. - * Note: The clock could not be set when it is being used as system clock. - * In default out of reset, the CPU is clocked from FIRC(IRC48M), - * so before setting FIRC, change to use another available clock source. - * - * 2. Call CLOCK_SetXtal0Freq() to set XTAL0 frequency based on board settings. - * - * 3. Call CLOCK_SetXxxModeSysClkConfig() to set SCG mode for Xxx run mode. - * Wait until the system clock source is changed to target source. - * - * 4. If power mode change is needed, call SMC_SetPowerModeProtection() to allow - * corresponding power mode and SMC_SetPowerModeXxx() to change to Xxx mode. - * Supported run mode and clock restrictions could be found in Reference Manual. - */ - -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!GlobalInfo -product: Clocks v7.0 -processor: K32L2A41xxxxA -package_id: K32L2A41VLL1A -mcu_data: ksdk2_0 -processor_version: 9.0.0 - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -#include "fsl_smc.h" -#include "clock_config.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ -#define SCG_CLKOUTCNFG_SIRC 2U /*!< SCG CLKOUT clock select: Slow IRC */ -#define SCG_SOSC_DISABLE 0U /*!< System OSC disabled */ -#define SCG_SPLL_DISABLE 0U /*!< System PLL disabled */ -#define SCG_SYS_OSC_CAP_0P 0U /*!< Oscillator 0pF capacitor load */ - -/******************************************************************************* - * Variables - ******************************************************************************/ -/* System clock frequency. */ -extern uint32_t SystemCoreClock; - -/******************************************************************************* - * Code - ******************************************************************************/ -/*FUNCTION********************************************************************** - * - * Function Name : CLOCK_CONFIG_SetScgOutSel - * Description : Set the SCG clock out select (CLKOUTSEL). - * Param setting : The selected clock source. - * - *END**************************************************************************/ -static void CLOCK_CONFIG_SetScgOutSel(uint8_t setting) -{ - SCG->CLKOUTCNFG = SCG_CLKOUTCNFG_CLKOUTSEL(setting); -} - -/*FUNCTION********************************************************************** - * - * Function Name : CLOCK_CONFIG_FircSafeConfig - * Description : This function is used to safely configure FIRC clock. - * In default out of reset, the CPU is clocked from FIRC(IRC48M). - * Before setting FIRC, change to use SIRC as system clock, - * then configure FIRC. After FIRC is set, change back to use FIRC - * in case SIRC need to be configured. - * Param fircConfig : FIRC configuration. - * - *END**************************************************************************/ -static void CLOCK_CONFIG_FircSafeConfig(const scg_firc_config_t *fircConfig) -{ - scg_sys_clk_config_t curConfig; - const scg_sirc_config_t scgSircConfig = {.enableMode = kSCG_SircEnable, - .div1 = kSCG_AsyncClkDisable, - .div3 = kSCG_AsyncClkDivBy2, - .range = kSCG_SircRangeHigh}; - scg_sys_clk_config_t sysClkSafeConfigSource = { - .divSlow = kSCG_SysClkDivBy4, /* Slow clock divider */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved1 = 0, - .reserved2 = 0, - .reserved3 = 0, -#endif - .divCore = kSCG_SysClkDivBy1, /* Core clock divider */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved4 = 0, -#endif - .src = kSCG_SysClkSrcSirc, /* System clock source */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved5 = 0, -#endif - }; - /* Init Sirc. */ - CLOCK_InitSirc(&scgSircConfig); - /* Change to use SIRC as system clock source to prepare to change FIRCCFG register. */ - CLOCK_SetRunModeSysClkConfig(&sysClkSafeConfigSource); - /* Wait for clock source switch finished. */ - do - { - CLOCK_GetCurSysClkConfig(&curConfig); - } while (curConfig.src != sysClkSafeConfigSource.src); - - /* Init Firc. */ - CLOCK_InitFirc(fircConfig); - /* Change back to use FIRC as system clock source in order to configure SIRC if needed. */ - sysClkSafeConfigSource.src = kSCG_SysClkSrcFirc; - CLOCK_SetRunModeSysClkConfig(&sysClkSafeConfigSource); - /* Wait for clock source switch finished. */ - do - { - CLOCK_GetCurSysClkConfig(&curConfig); - } while (curConfig.src != sysClkSafeConfigSource.src); -} - -/******************************************************************************* - ************************ BOARD_InitBootClocks function ************************ - ******************************************************************************/ -void BOARD_InitBootClocks(void) -{ - BOARD_BootClockRUN(); -} - -/******************************************************************************* - ********************** Configuration BOARD_BootClockRUN *********************** - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockRUN -called_from_default_init: true -outputs: -- {id: Core_clock.outFreq, value: 48 MHz} -- {id: FIRCDIV1_CLK.outFreq, value: 48 MHz} -- {id: FIRCDIV3_CLK.outFreq, value: 48 MHz} -- {id: LPO_clock.outFreq, value: 1 kHz} -- {id: OSC32KCLK.outFreq, value: 32.768 kHz} -- {id: SIRCDIV3_CLK.outFreq, value: 4 MHz} -- {id: SIRC_CLK.outFreq, value: 8 MHz} -- {id: SOSCDIV3_CLK.outFreq, value: 32.768 kHz} -- {id: SOSCER_CLK.outFreq, value: 32.768 kHz} -- {id: SOSC_CLK.outFreq, value: 32.768 kHz} -- {id: Slow_clock.outFreq, value: 24 MHz} -- {id: System_clock.outFreq, value: 48 MHz} -settings: -- {id: SCG.FIRCDIV1.scale, value: '1', locked: true} -- {id: SCG.FIRCDIV3.scale, value: '1', locked: true} -- {id: SCG.SIRCDIV3.scale, value: '2', locked: true} -- {id: SCG.SOSCDIV3.scale, value: '1', locked: true} -- {id: SCG_SOSCCFG_OSC_MODE_CFG, value: ModeOscLowPower} -- {id: SCG_SOSCCSR_SOSCEN_CFG, value: Enabled} -- {id: SCG_SOSCCSR_SOSCERCLKEN_CFG, value: Enabled} -sources: -- {id: SCG.SOSC.outFreq, value: 32.768 kHz, enabled: true} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockRUN configuration - ******************************************************************************/ -const scg_sys_clk_config_t g_sysClkConfig_BOARD_BootClockRUN = - { - .divSlow = kSCG_SysClkDivBy2, /* Slow Clock Divider: divided by 2 */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved1 = 0, - .reserved2 = 0, - .reserved3 = 0, -#endif - .divCore = kSCG_SysClkDivBy1, /* Core Clock Divider: divided by 1 */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved4 = 0, -#endif - .src = kSCG_SysClkSrcFirc, /* Fast IRC is selected as System Clock Source */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved5 = 0, -#endif - }; -const scg_sosc_config_t g_scgSysOscConfig_BOARD_BootClockRUN = - { - .freq = 32768U, /* System Oscillator frequency: 32768Hz */ - .enableMode = kSCG_SysOscEnable | kSCG_SysOscEnableErClk,/* Enable System OSC clock, Enable OSCERCLK */ - .monitorMode = kSCG_SysOscMonitorDisable, /* Monitor disabled */ - .div1 = kSCG_AsyncClkDisable, /* System OSC Clock Divider 1: Clock output is disabled */ - .div3 = kSCG_AsyncClkDivBy1, /* System OSC Clock Divider 3: divided by 1 */ - .capLoad = SCG_SYS_OSC_CAP_0P, /* Oscillator capacity load: 0pF */ - .workMode = kSCG_SysOscModeOscLowPower, /* Oscillator low power */ - }; -const scg_sirc_config_t g_scgSircConfig_BOARD_BootClockRUN = - { - .enableMode = kSCG_SircEnable | kSCG_SircEnableInLowPower,/* Enable SIRC clock, Enable SIRC in low power mode */ - .div1 = kSCG_AsyncClkDisable, /* Slow IRC Clock Divider 1: Clock output is disabled */ - .div3 = kSCG_AsyncClkDivBy2, /* Slow IRC Clock Divider 3: divided by 2 */ - .range = kSCG_SircRangeHigh, /* Slow IRC high range clock (8 MHz) */ - }; -const scg_firc_config_t g_scgFircConfig_BOARD_BootClockRUN = - { - .enableMode = kSCG_FircEnable, /* Enable FIRC clock */ - .div1 = kSCG_AsyncClkDivBy1, /* Fast IRC Clock Divider 1: divided by 1 */ - .div3 = kSCG_AsyncClkDivBy1, /* Fast IRC Clock Divider 3: divided by 1 */ - .range = kSCG_FircRange48M, /* Fast IRC is trimmed to 48MHz */ - .trimConfig = NULL, /* Fast IRC Trim disabled */ - }; -const scg_spll_config_t g_scgSysPllConfig_BOARD_BootClockRUN = - { - .enableMode = SCG_SPLL_DISABLE, /* System PLL disabled */ - .monitorMode = kSCG_SysPllMonitorDisable, /* Monitor disabled */ - .div1 = kSCG_AsyncClkDisable, /* System PLL Clock Divider 1: Clock output is disabled */ - .div3 = kSCG_AsyncClkDisable, /* System PLL Clock Divider 3: Clock output is disabled */ - .src = kSCG_SysPllSrcSysOsc, /* System PLL clock source is System OSC */ - .prediv = 0, /* Divided by 1 */ - .mult = 0, /* Multiply Factor is 16 */ - }; -/******************************************************************************* - * Code for BOARD_BootClockRUN configuration - ******************************************************************************/ -void BOARD_BootClockRUN(void) -{ - scg_sys_clk_config_t curConfig; - - /* Init SOSC according to board configuration. */ - CLOCK_InitSysOsc(&g_scgSysOscConfig_BOARD_BootClockRUN); - /* Set the XTAL0 frequency based on board settings. */ - CLOCK_SetXtal0Freq(g_scgSysOscConfig_BOARD_BootClockRUN.freq); - /* Init FIRC. */ - CLOCK_CONFIG_FircSafeConfig(&g_scgFircConfig_BOARD_BootClockRUN); - /* Init SIRC. */ - CLOCK_InitSirc(&g_scgSircConfig_BOARD_BootClockRUN); - /* Set SCG to FIRC mode. */ - CLOCK_SetRunModeSysClkConfig(&g_sysClkConfig_BOARD_BootClockRUN); - /* Wait for clock source switch finished. */ - do - { - CLOCK_GetCurSysClkConfig(&curConfig); - } while (curConfig.src != g_sysClkConfig_BOARD_BootClockRUN.src); - /* Set SystemCoreClock variable. */ - SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; -} - -/******************************************************************************* - ********************* Configuration BOARD_BootClockHSRUN ********************** - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockHSRUN -outputs: -- {id: CLKOUT.outFreq, value: 8 MHz} -- {id: Core_clock.outFreq, value: 96 MHz, locked: true, accuracy: '0.001'} -- {id: FIRCDIV1_CLK.outFreq, value: 48 MHz} -- {id: FIRCDIV3_CLK.outFreq, value: 48 MHz} -- {id: LPO_clock.outFreq, value: 1 kHz} -- {id: OSC32KCLK.outFreq, value: 32.768 kHz} -- {id: PLLDIV1_CLK.outFreq, value: 96 MHz} -- {id: PLLDIV3_CLK.outFreq, value: 96 MHz} -- {id: SIRCDIV1_CLK.outFreq, value: 8 MHz} -- {id: SIRCDIV3_CLK.outFreq, value: 8 MHz} -- {id: SIRC_CLK.outFreq, value: 8 MHz} -- {id: SOSCDIV1_CLK.outFreq, value: 32.768 kHz} -- {id: SOSCDIV3_CLK.outFreq, value: 32.768 kHz} -- {id: SOSCER_CLK.outFreq, value: 32.768 kHz} -- {id: SOSC_CLK.outFreq, value: 32.768 kHz} -- {id: Slow_clock.outFreq, value: 24 MHz, locked: true, accuracy: '0.001'} -- {id: System_clock.outFreq, value: 96 MHz} -settings: -- {id: SCGMode, value: SPLL} -- {id: powerMode, value: HSRUN} -- {id: CLKOUTConfig, value: 'yes'} -- {id: SCG.DIVSLOW.scale, value: '4'} -- {id: SCG.FIRCDIV1.scale, value: '1', locked: true} -- {id: SCG.FIRCDIV3.scale, value: '1', locked: true} -- {id: SCG.PREDIV.scale, value: '4'} -- {id: SCG.SCSSEL.sel, value: SCG.SPLL_DIV2_CLK} -- {id: SCG.SIRCDIV1.scale, value: '1', locked: true} -- {id: SCG.SIRCDIV3.scale, value: '1', locked: true} -- {id: SCG.SOSCDIV1.scale, value: '1', locked: true} -- {id: SCG.SOSCDIV3.scale, value: '1', locked: true} -- {id: SCG.SPLLDIV1.scale, value: '1', locked: true} -- {id: SCG.SPLLDIV3.scale, value: '1', locked: true} -- {id: SCG.SPLLSRCSEL.sel, value: SCG.FIRC} -- {id: SCG_SOSCCFG_OSC_MODE_CFG, value: ModeOscLowPower} -- {id: SCG_SOSCCSR_SOSCEN_CFG, value: Enabled} -- {id: SCG_SOSCCSR_SOSCERCLKEN_CFG, value: Enabled} -- {id: SCG_SPLLCSR_SPLLEN_CFG, value: Enabled} -sources: -- {id: SCG.SOSC.outFreq, value: 32.768 kHz, enabled: true} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockHSRUN configuration - ******************************************************************************/ -const scg_sys_clk_config_t g_sysClkConfig_BOARD_BootClockHSRUN = - { - .divSlow = kSCG_SysClkDivBy4, /* Slow Clock Divider: divided by 4 */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved1 = 0, - .reserved2 = 0, - .reserved3 = 0, -#endif - .divCore = kSCG_SysClkDivBy1, /* Core Clock Divider: divided by 1 */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved4 = 0, -#endif - .src = kSCG_SysClkSrcSysPll, /* System PLL is selected as System Clock Source */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved5 = 0, -#endif - }; -const scg_sosc_config_t g_scgSysOscConfig_BOARD_BootClockHSRUN = - { - .freq = 32768U, /* System Oscillator frequency: 32768Hz */ - .enableMode = kSCG_SysOscEnable | kSCG_SysOscEnableErClk,/* Enable System OSC clock, Enable OSCERCLK */ - .monitorMode = kSCG_SysOscMonitorDisable, /* Monitor disabled */ - .div1 = kSCG_AsyncClkDivBy1, /* System OSC Clock Divider 1: divided by 1 */ - .div3 = kSCG_AsyncClkDivBy1, /* System OSC Clock Divider 3: divided by 1 */ - .capLoad = SCG_SYS_OSC_CAP_0P, /* Oscillator capacity load: 0pF */ - .workMode = kSCG_SysOscModeOscLowPower, /* Oscillator low power */ - }; -const scg_sirc_config_t g_scgSircConfig_BOARD_BootClockHSRUN = - { - .enableMode = kSCG_SircEnable | kSCG_SircEnableInLowPower,/* Enable SIRC clock, Enable SIRC in low power mode */ - .div1 = kSCG_AsyncClkDivBy1, /* Slow IRC Clock Divider 1: divided by 1 */ - .div3 = kSCG_AsyncClkDivBy1, /* Slow IRC Clock Divider 3: divided by 1 */ - .range = kSCG_SircRangeHigh, /* Slow IRC high range clock (8 MHz) */ - }; -const scg_firc_config_t g_scgFircConfig_BOARD_BootClockHSRUN = - { - .enableMode = kSCG_FircEnable, /* Enable FIRC clock */ - .div1 = kSCG_AsyncClkDivBy1, /* Fast IRC Clock Divider 1: divided by 1 */ - .div3 = kSCG_AsyncClkDivBy1, /* Fast IRC Clock Divider 3: divided by 1 */ - .range = kSCG_FircRange48M, /* Fast IRC is trimmed to 48MHz */ - .trimConfig = NULL, /* Fast IRC Trim disabled */ - }; -const scg_spll_config_t g_scgSysPllConfig_BOARD_BootClockHSRUN = - { - .enableMode = kSCG_SysPllEnable, /* Enable SPLL clock */ - .monitorMode = kSCG_SysPllMonitorDisable, /* Monitor disabled */ - .div1 = kSCG_AsyncClkDivBy1, /* System PLL Clock Divider 1: divided by 1 */ - .div3 = kSCG_AsyncClkDivBy1, /* System PLL Clock Divider 3: divided by 1 */ - .src = kSCG_SysPllSrcFirc, /* System PLL clock source is Fast IRC */ - .prediv = 3, /* Divided by 4 */ - .mult = 0, /* Multiply Factor is 16 */ - }; -/******************************************************************************* - * Code for BOARD_BootClockHSRUN configuration - ******************************************************************************/ -void BOARD_BootClockHSRUN(void) -{ - scg_sys_clk_config_t curConfig; - - /* Init SOSC according to board configuration. */ - CLOCK_InitSysOsc(&g_scgSysOscConfig_BOARD_BootClockHSRUN); - /* Set the XTAL0 frequency based on board settings. */ - CLOCK_SetXtal0Freq(g_scgSysOscConfig_BOARD_BootClockHSRUN.freq); - /* Init FIRC. */ - CLOCK_CONFIG_FircSafeConfig(&g_scgFircConfig_BOARD_BootClockHSRUN); - /* Init SIRC. */ - CLOCK_InitSirc(&g_scgSircConfig_BOARD_BootClockHSRUN); - /* Init SysPll. */ - CLOCK_InitSysPll(&g_scgSysPllConfig_BOARD_BootClockHSRUN); - /* Set HSRUN power mode. */ - SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll); - SMC_SetPowerModeHsrun(SMC); - while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateHsrun) - { - } - - /* Set SCG to SPLL mode. */ - CLOCK_SetHsrunModeSysClkConfig(&g_sysClkConfig_BOARD_BootClockHSRUN); - /* Wait for clock source switch finished. */ - do - { - CLOCK_GetCurSysClkConfig(&curConfig); - } while (curConfig.src != g_sysClkConfig_BOARD_BootClockHSRUN.src); - /* Set SystemCoreClock variable. */ - SystemCoreClock = BOARD_BOOTCLOCKHSRUN_CORE_CLOCK; - /* Set SCG CLKOUT selection. */ - CLOCK_CONFIG_SetScgOutSel(SCG_CLKOUTCNFG_SIRC); -} - -/******************************************************************************* - ********************* Configuration BOARD_BootClockVLPR *********************** - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockVLPR -outputs: -- {id: Core_clock.outFreq, value: 8 MHz, locked: true, accuracy: '0.001'} -- {id: LPO_clock.outFreq, value: 1 kHz} -- {id: SIRC_CLK.outFreq, value: 8 MHz} -- {id: Slow_clock.outFreq, value: 1 MHz, locked: true, accuracy: '0.001'} -- {id: System_clock.outFreq, value: 8 MHz} -settings: -- {id: SCGMode, value: SIRC} -- {id: powerMode, value: VLPR} -- {id: SCG.DIVSLOW.scale, value: '8'} -- {id: SCG.SCSSEL.sel, value: SCG.SIRC} -- {id: SCG_FIRCCSR_FIRCLPEN_CFG, value: Enabled} -sources: -- {id: SCG.SOSC.outFreq, value: 32.768 kHz, enabled: true} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockVLPR configuration - ******************************************************************************/ -const scg_sys_clk_config_t g_sysClkConfig_BOARD_BootClockVLPR = - { - .divSlow = kSCG_SysClkDivBy8, /* Slow Clock Divider: divided by 8 */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved1 = 0, - .reserved2 = 0, - .reserved3 = 0, -#endif - .divCore = kSCG_SysClkDivBy1, /* Core Clock Divider: divided by 1 */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved4 = 0, -#endif - .src = kSCG_SysClkSrcSirc, /* Slow IRC is selected as System Clock Source */ -#if FSL_CLOCK_DRIVER_VERSION < MAKE_VERSION(2, 1, 1) - .reserved5 = 0, -#endif - }; -const scg_sosc_config_t g_scgSysOscConfig_BOARD_BootClockVLPR = - { - .freq = 0U, /* System Oscillator frequency: 0Hz */ - .enableMode = SCG_SOSC_DISABLE, /* System OSC disabled */ - .monitorMode = kSCG_SysOscMonitorDisable, /* Monitor disabled */ - .div1 = kSCG_AsyncClkDisable, /* System OSC Clock Divider 1: Clock output is disabled */ - .div3 = kSCG_AsyncClkDisable, /* System OSC Clock Divider 3: Clock output is disabled */ - .capLoad = SCG_SYS_OSC_CAP_0P, /* Oscillator capacity load: 0pF */ - .workMode = kSCG_SysOscModeExt, /* Use external clock */ - }; -const scg_sirc_config_t g_scgSircConfig_BOARD_BootClockVLPR = - { - .enableMode = kSCG_SircEnable | kSCG_SircEnableInLowPower,/* Enable SIRC clock, Enable SIRC in low power mode */ - .div1 = kSCG_AsyncClkDisable, /* Slow IRC Clock Divider 1: Clock output is disabled */ - .div3 = kSCG_AsyncClkDisable, /* Slow IRC Clock Divider 3: Clock output is disabled */ - .range = kSCG_SircRangeHigh, /* Slow IRC high range clock (8 MHz) */ - }; -const scg_firc_config_t g_scgFircConfig_BOARD_BootClockVLPR = - { - .enableMode = kSCG_FircEnable | kSCG_FircEnableInLowPower,/* Enable FIRC clock, Enable FIRC in low power mode */ - .div1 = kSCG_AsyncClkDisable, /* Fast IRC Clock Divider 1: Clock output is disabled */ - .div3 = kSCG_AsyncClkDisable, /* Fast IRC Clock Divider 3: Clock output is disabled */ - .range = kSCG_FircRange48M, /* Fast IRC is trimmed to 48MHz */ - .trimConfig = NULL, /* Fast IRC Trim disabled */ - }; -const scg_spll_config_t g_scgSysPllConfig_BOARD_BootClockVLPR = - { - .enableMode = SCG_SPLL_DISABLE, /* System PLL disabled */ - .monitorMode = kSCG_SysPllMonitorDisable, /* Monitor disabled */ - .div1 = kSCG_AsyncClkDisable, /* System PLL Clock Divider 1: Clock output is disabled */ - .div3 = kSCG_AsyncClkDisable, /* System PLL Clock Divider 3: Clock output is disabled */ - .src = kSCG_SysPllSrcSysOsc, /* System PLL clock source is System OSC */ - .prediv = 0, /* Divided by 1 */ - .mult = 0, /* Multiply Factor is 16 */ - }; -/******************************************************************************* - * Code for BOARD_BootClockVLPR configuration - ******************************************************************************/ -void BOARD_BootClockVLPR(void) -{ - /* Init FIRC. */ - CLOCK_CONFIG_FircSafeConfig(&g_scgFircConfig_BOARD_BootClockVLPR); - /* Init SIRC. */ - CLOCK_InitSirc(&g_scgSircConfig_BOARD_BootClockVLPR); - /* Allow SMC all power modes. */ - SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll); - /* Set VLPR power mode. */ - SMC_SetPowerModeVlpr(SMC); - while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateVlpr) - { - } - /* Set SystemCoreClock variable. */ - SystemCoreClock = BOARD_BOOTCLOCKVLPR_CORE_CLOCK; -} diff --git a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/clock_config.h b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/clock_config.h deleted file mode 100644 index c01d5e03c..000000000 --- a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/clock_config.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2019 ,2021 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ - -#ifndef _CLOCK_CONFIG_H_ -#define _CLOCK_CONFIG_H_ - -#include "fsl_common.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ -#define BOARD_XTAL0_CLK_HZ 32768U /*!< Board xtal0 frequency in Hz */ - -/******************************************************************************* - ************************ BOARD_InitBootClocks function ************************ - ******************************************************************************/ - -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes default configuration of clocks. - * - */ -void BOARD_InitBootClocks(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ********************** Configuration BOARD_BootClockRUN *********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockRUN configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKRUN_CORE_CLOCK 48000000U /*!< Core clock frequency: 48000000Hz */ - -/*! @brief SCG set for BOARD_BootClockRUN configuration. - */ -extern const scg_sys_clk_config_t g_sysClkConfig_BOARD_BootClockRUN; -/*! @brief System OSC set for BOARD_BootClockRUN configuration. - */ -extern const scg_sosc_config_t g_scgSysOscConfig_BOARD_BootClockRUN; -/*! @brief SIRC set for BOARD_BootClockRUN configuration. - */ -extern const scg_sirc_config_t g_scgSircConfig_BOARD_BootClockRUN; -/*! @brief FIRC set for BOARD_BootClockRUN configuration. - */ -extern const scg_firc_config_t g_scgFircConfigBOARD_BootClockRUN; -extern const scg_spll_config_t g_scgSysPllConfigBOARD_BootClockRUN; -/*! @brief Low Power FLL set for BOARD_BootClockRUN configuration. - */ - -/******************************************************************************* - * API for BOARD_BootClockRUN configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockRUN(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ********************* Configuration BOARD_BootClockHSRUN ********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockHSRUN configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKHSRUN_CORE_CLOCK 96000000U /*!< Core clock frequency: 96000000Hz */ - -/*! @brief SCG set for BOARD_BootClockHSRUN configuration. - */ -extern const scg_sys_clk_config_t g_sysClkConfig_BOARD_BootClockHSRUN; -/*! @brief System OSC set for BOARD_BootClockHSRUN configuration. - */ -extern const scg_sosc_config_t g_scgSysOscConfig_BOARD_BootClockHSRUN; -/*! @brief SIRC set for BOARD_BootClockHSRUN configuration. - */ -extern const scg_sirc_config_t g_scgSircConfig_BOARD_BootClockHSRUN; -/*! @brief FIRC set for BOARD_BootClockHSRUN configuration. - */ -extern const scg_firc_config_t g_scgFircConfigBOARD_BootClockHSRUN; -extern const scg_spll_config_t g_scgSysPllConfigBOARD_BootClockHSRUN; -/*! @brief Low Power FLL set for BOARD_BootClockHSRUN configuration. - */ - -/******************************************************************************* - * API for BOARD_BootClockHSRUN configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockHSRUN(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ********************* Configuration BOARD_BootClockVLPR *********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockVLPR configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKVLPR_CORE_CLOCK 8000000U /*!< Core clock frequency: 8000000Hz */ - -/*! @brief SCG set for BOARD_BootClockVLPR configuration. - */ -extern const scg_sys_clk_config_t g_sysClkConfig_BOARD_BootClockVLPR; -/*! @brief System OSC set for BOARD_BootClockVLPR configuration. - */ -extern const scg_sosc_config_t g_scgSysOscConfig_BOARD_BootClockVLPR; -/*! @brief SIRC set for BOARD_BootClockVLPR configuration. - */ -extern const scg_sirc_config_t g_scgSircConfig_BOARD_BootClockVLPR; -/*! @brief FIRC set for BOARD_BootClockVLPR configuration. - */ -extern const scg_firc_config_t g_scgFircConfigBOARD_BootClockVLPR; -extern const scg_spll_config_t g_scgSysPllConfigBOARD_BootClockVLPR; -/*! @brief Low Power FLL set for BOARD_BootClockVLPR configuration. - */ - -/******************************************************************************* - * API for BOARD_BootClockVLPR configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockVLPR(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -#endif /* _CLOCK_CONFIG_H_ */ diff --git a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/board.mk b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/board.mk index 9cf36c500..82456b721 100644 --- a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/board.mk +++ b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/board.mk @@ -8,6 +8,9 @@ CFLAGS += -Wno-error=unused-parameter -Wno-error=redundant-decls # All source paths should be relative to the top level. LD_FILE = $(MCU_DIR)/gcc/K32L2B31xxxxA_flash.ld +SRC_C += \ + $(MCU_DIR)/project_template/clock_config.c \ + # For flash-jlink target JLINK_DEVICE = K32L2B31xxxxA diff --git a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/clock_config.c b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/clock_config.c deleted file mode 100644 index e74000827..000000000 --- a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/clock_config.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2019 ,2021 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ -/* - * How to setup clock using clock driver functions: - * - * 1. CLOCK_SetSimSafeDivs, to make sure core clock, bus clock, flexbus clock - * and flash clock are in allowed range during clock mode switch. - * - * 2. Call CLOCK_Osc0Init to setup OSC clock, if it is used in target mode. - * - * 3. Call CLOCK_SetMcgliteConfig to set MCG_Lite configuration. - * - * 4. Call CLOCK_SetSimConfig to set the clock configuration in SIM. - */ - -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!GlobalInfo -product: Clocks v7.0 -processor: K32L2B31xxxxA -package_id: K32L2B31VLH0A -mcu_data: ksdk2_0 -processor_version: 9.0.0 -board: FRDM-K32L2B - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -#include "fsl_smc.h" -#include "clock_config.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ -#define OSC_CAP0P 0U /*!< Oscillator 0pF capacitor load */ -#define OSC_ER_CLK_DISABLE 0U /*!< Disable external reference clock */ -#define SIM_OSC32KSEL_OSC32KCLK_CLK 0U /*!< OSC32KSEL select: OSC32KCLK clock */ - -/******************************************************************************* - * Variables - ******************************************************************************/ -/* System clock frequency. */ -extern uint32_t SystemCoreClock; - -/******************************************************************************* - ************************ BOARD_InitBootClocks function ************************ - ******************************************************************************/ -void BOARD_InitBootClocks(void) -{ - BOARD_BootClockRUN(); -} - -/******************************************************************************* - ********************** Configuration BOARD_BootClockRUN *********************** - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockRUN -called_from_default_init: true -outputs: -- {id: Bus_clock.outFreq, value: 24 MHz} -- {id: Core_clock.outFreq, value: 48 MHz} -- {id: Flash_clock.outFreq, value: 24 MHz} -- {id: LPO_clock.outFreq, value: 1 kHz} -- {id: MCGIRCLK.outFreq, value: 8 MHz} -- {id: MCGPCLK.outFreq, value: 48 MHz} -- {id: System_clock.outFreq, value: 48 MHz} -settings: -- {id: MCGMode, value: HIRC} -- {id: MCG.CLKS.sel, value: MCG.HIRC} -- {id: MCG_C2_OSC_MODE_CFG, value: ModeOscLowPower} -- {id: MCG_C2_RANGE0_CFG, value: Very_high} -- {id: MCG_MC_HIRCEN_CFG, value: Enabled} -- {id: OSC0_CR_ERCLKEN_CFG, value: Enabled} -- {id: OSC_CR_ERCLKEN_CFG, value: Enabled} -- {id: SIM.CLKOUTSEL.sel, value: MCG.MCGPCLK} -- {id: SIM.COPCLKSEL.sel, value: OSC.OSCERCLK} -- {id: SIM.FLEXIOSRCSEL.sel, value: MCG.MCGPCLK} -- {id: SIM.LPUART0SRCSEL.sel, value: MCG.MCGPCLK} -- {id: SIM.LPUART1SRCSEL.sel, value: MCG.MCGPCLK} -- {id: SIM.RTCCLKOUTSEL.sel, value: OSC.OSCERCLK} -- {id: SIM.TPMSRCSEL.sel, value: MCG.MCGPCLK} -- {id: SIM.USBSRCSEL.sel, value: MCG.MCGPCLK} -sources: -- {id: MCG.HIRC.outFreq, value: 48 MHz} -- {id: OSC.OSC.outFreq, value: 32 MHz} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockRUN configuration - ******************************************************************************/ -const mcglite_config_t mcgliteConfig_BOARD_BootClockRUN = - { - .outSrc = kMCGLITE_ClkSrcHirc, /* MCGOUTCLK source is HIRC */ - .irclkEnableMode = kMCGLITE_IrclkEnable, /* MCGIRCLK enabled, MCGIRCLK disabled in STOP mode */ - .ircs = kMCGLITE_Lirc8M, /* Slow internal reference (LIRC) 8 MHz clock selected */ - .fcrdiv = kMCGLITE_LircDivBy1, /* Low-frequency Internal Reference Clock Divider: divided by 1 */ - .lircDiv2 = kMCGLITE_LircDivBy1, /* Second Low-frequency Internal Reference Clock Divider: divided by 1 */ - .hircEnableInNotHircMode = true, /* HIRC source is enabled */ - }; -const sim_clock_config_t simConfig_BOARD_BootClockRUN = - { - .er32kSrc = SIM_OSC32KSEL_OSC32KCLK_CLK, /* OSC32KSEL select: OSC32KCLK clock */ - .clkdiv1 = 0x10000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV4: /2 */ - }; -const osc_config_t oscConfig_BOARD_BootClockRUN = - { - .freq = 0U, /* Oscillator frequency: 0Hz */ - .capLoad = (OSC_CAP0P), /* Oscillator capacity load: 0pF */ - .workMode = kOSC_ModeOscLowPower, /* Oscillator low power */ - .oscerConfig = - { - .enableMode = kOSC_ErClkEnable, /* Enable external reference clock, disable external reference clock in STOP mode */ - } - }; - -/******************************************************************************* - * Code for BOARD_BootClockRUN configuration - ******************************************************************************/ -void BOARD_BootClockRUN(void) -{ - /* Set the system clock dividers in SIM to safe value. */ - CLOCK_SetSimSafeDivs(); - /* Set MCG to HIRC mode. */ - CLOCK_SetMcgliteConfig(&mcgliteConfig_BOARD_BootClockRUN); - /* Set the clock configuration in SIM module. */ - CLOCK_SetSimConfig(&simConfig_BOARD_BootClockRUN); - /* Set SystemCoreClock variable. */ - SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; -} - -/******************************************************************************* - ********************* Configuration BOARD_BootClockVLPR *********************** - ******************************************************************************/ -/* clang-format off */ -/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!Configuration -name: BOARD_BootClockVLPR -outputs: -- {id: Bus_clock.outFreq, value: 1 MHz} -- {id: Core_clock.outFreq, value: 2 MHz} -- {id: Flash_clock.outFreq, value: 1 MHz} -- {id: LPO_clock.outFreq, value: 1 kHz} -- {id: MCGIRCLK.outFreq, value: 2 MHz} -- {id: System_clock.outFreq, value: 2 MHz} -settings: -- {id: MCGMode, value: LIRC2M} -- {id: powerMode, value: VLPR} -- {id: MCG_C2_OSC_MODE_CFG, value: ModeOscLowPower} -- {id: RTCCLKOUTConfig, value: 'yes'} -- {id: SIM.OUTDIV4.scale, value: '2', locked: true} -- {id: SIM.RTCCLKOUTSEL.sel, value: OSC.OSCERCLK} -sources: -- {id: MCG.LIRC.outFreq, value: 2 MHz} -- {id: OSC.OSC.outFreq, value: 32.768 kHz} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ -/* clang-format on */ - -/******************************************************************************* - * Variables for BOARD_BootClockVLPR configuration - ******************************************************************************/ -const mcglite_config_t mcgliteConfig_BOARD_BootClockVLPR = - { - .outSrc = kMCGLITE_ClkSrcLirc, /* MCGOUTCLK source is LIRC */ - .irclkEnableMode = kMCGLITE_IrclkEnable, /* MCGIRCLK enabled, MCGIRCLK disabled in STOP mode */ - .ircs = kMCGLITE_Lirc2M, /* Slow internal reference (LIRC) 2 MHz clock selected */ - .fcrdiv = kMCGLITE_LircDivBy1, /* Low-frequency Internal Reference Clock Divider: divided by 1 */ - .lircDiv2 = kMCGLITE_LircDivBy1, /* Second Low-frequency Internal Reference Clock Divider: divided by 1 */ - .hircEnableInNotHircMode = false, /* HIRC source is not enabled */ - }; -const sim_clock_config_t simConfig_BOARD_BootClockVLPR = - { - .er32kSrc = SIM_OSC32KSEL_OSC32KCLK_CLK, /* OSC32KSEL select: OSC32KCLK clock */ - .clkdiv1 = 0x10000U, /* SIM_CLKDIV1 - OUTDIV1: /1, OUTDIV4: /2 */ - }; -const osc_config_t oscConfig_BOARD_BootClockVLPR = - { - .freq = 0U, /* Oscillator frequency: 0Hz */ - .capLoad = (OSC_CAP0P), /* Oscillator capacity load: 0pF */ - .workMode = kOSC_ModeOscLowPower, /* Oscillator low power */ - .oscerConfig = - { - .enableMode = OSC_ER_CLK_DISABLE, /* Disable external reference clock */ - } - }; - -/******************************************************************************* - * Code for BOARD_BootClockVLPR configuration - ******************************************************************************/ -void BOARD_BootClockVLPR(void) -{ - /* Set the system clock dividers in SIM to safe value. */ - CLOCK_SetSimSafeDivs(); - /* Set MCG to LIRC2M mode. */ - CLOCK_SetMcgliteConfig(&mcgliteConfig_BOARD_BootClockVLPR); - /* Set the clock configuration in SIM module. */ - CLOCK_SetSimConfig(&simConfig_BOARD_BootClockVLPR); - /* Set VLPR power mode. */ - SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll); -#if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) - SMC_SetPowerModeVlpr(SMC, false); -#else - SMC_SetPowerModeVlpr(SMC); -#endif - while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateVlpr) - { - } - /* Set SystemCoreClock variable. */ - SystemCoreClock = BOARD_BOOTCLOCKVLPR_CORE_CLOCK; -} diff --git a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/clock_config.h b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/clock_config.h deleted file mode 100644 index 37328e7d8..000000000 --- a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/clock_config.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2019 ,2021 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ - -#ifndef _CLOCK_CONFIG_H_ -#define _CLOCK_CONFIG_H_ - -#include "fsl_common.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/******************************************************************************* - ************************ BOARD_InitBootClocks function ************************ - ******************************************************************************/ - -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes default configuration of clocks. - * - */ -void BOARD_InitBootClocks(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ********************** Configuration BOARD_BootClockRUN *********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockRUN configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKRUN_CORE_CLOCK 48000000U /*!< Core clock frequency: 48000000Hz */ - -/*! @brief MCG lite set for BOARD_BootClockRUN configuration. - */ -extern const mcglite_config_t mcgliteConfig_BOARD_BootClockRUN; -/*! @brief SIM module set for BOARD_BootClockRUN configuration. - */ -extern const sim_clock_config_t simConfig_BOARD_BootClockRUN; -/*! @brief OSC set for BOARD_BootClockRUN configuration. - */ -extern const osc_config_t oscConfig_BOARD_BootClockRUN; - -/******************************************************************************* - * API for BOARD_BootClockRUN configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockRUN(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ********************* Configuration BOARD_BootClockVLPR *********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockVLPR configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKVLPR_CORE_CLOCK 2000000U /*!< Core clock frequency: 2000000Hz */ - -/*! @brief MCG lite set for BOARD_BootClockVLPR configuration. - */ -extern const mcglite_config_t mcgliteConfig_BOARD_BootClockVLPR; -/*! @brief SIM module set for BOARD_BootClockVLPR configuration. - */ -extern const sim_clock_config_t simConfig_BOARD_BootClockVLPR; -/*! @brief OSC set for BOARD_BootClockVLPR configuration. - */ -extern const osc_config_t oscConfig_BOARD_BootClockVLPR; - -/******************************************************************************* - * API for BOARD_BootClockVLPR configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockVLPR(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -#endif /* _CLOCK_CONFIG_H_ */ diff --git a/hw/bsp/nrf/boards/pca10095/board.cmake b/hw/bsp/nrf/boards/pca10095/board.cmake index 0fbc1d31f..ca5399a3a 100644 --- a/hw/bsp/nrf/boards/pca10095/board.cmake +++ b/hw/bsp/nrf/boards/pca10095/board.cmake @@ -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 diff --git a/hw/bsp/nrf/boards/pca10095/board.h b/hw/bsp/nrf/boards/pca10095/board.h index 7437dad48..ad3379bf6 100644 --- a/hw/bsp/nrf/boards/pca10095/board.h +++ b/hw/bsp/nrf/boards/pca10095/board.h @@ -42,8 +42,8 @@ #define BUTTON_STATE_ACTIVE 0 // UART -#define UART_RX_PIN 22 -#define UART_TX_PIN 20 +#define UART_RX_PIN 32 +#define UART_TX_PIN 33 // SPI for USB host shield #define MAX3421_SCK_PIN _PINNUM(1, 15) diff --git a/hw/bsp/nrf/boards/pca10095/board.mk b/hw/bsp/nrf/boards/pca10095/board.mk index 20580d619..9c4edbafc 100644 --- a/hw/bsp/nrf/boards/pca10095/board.mk +++ b/hw/bsp/nrf/boards/pca10095/board.mk @@ -2,9 +2,6 @@ CPU_CORE = cortex-m33 MCU_VARIANT = nrf5340_application CFLAGS += -DNRF5340_XXAA -DNRF5340_XXAA_APPLICATION -# enable max3421 host driver for this board -MAX3421_HOST = 1 - LD_FILE = hw/mcu/nordic/nrfx/mdk/nrf5340_xxaa_application.ld SRC_C += hw/mcu/nordic/nrfx/drivers/src/nrfx_usbreg.c diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 55119ef02..7a970f52e 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -76,7 +76,6 @@ enum { #define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_LFRC #define VBUSDETECT_Msk USBREG_USBREGSTATUS_VBUSDETECT_Msk #define OUTPUTRDY_Msk USBREG_USBREGSTATUS_OUTPUTRDY_Msk - #define GPIOTE_IRQn GPIOTE1_IRQn #else #define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_RC #define VBUSDETECT_Msk POWER_USBREGSTATUS_VBUSDETECT_Msk diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index c145d86a6..2589dcd2c 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -203,7 +203,7 @@ uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= CFG_TUD_MSC_LOG_LEVEL +#if CFG_TUSB_DEBUG >= 2 TU_ATTR_UNUSED tu_static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = { diff --git a/src/class/video/video.h b/src/class/video/video.h index abf1e34b9..6319c6536 100644 --- a/src/class/video/video.h +++ b/src/class/video/video.h @@ -368,8 +368,6 @@ typedef struct TU_ATTR_PACKED { uint8_t bCopyProtect; } tusb_desc_video_format_uncompressed_t; -TU_VERIFY_STATIC(sizeof(tusb_desc_video_format_uncompressed_t) == 27, "size is not correct"); - // Uncompressed payload specs: 3.1.2 frame descriptor #define tusb_desc_video_frame_uncompressed_nint_t(_nint) \ struct TU_ATTR_PACKED { \ @@ -383,7 +381,7 @@ TU_VERIFY_STATIC(sizeof(tusb_desc_video_format_uncompressed_t) == 27, "size is n uint32_t dwMinBitRate; \ uint32_t dwMaxBitRate; \ uint32_t dwMaxVideoFrameBufferSize; /* deprecated in 1.5 */ \ - uint32_t dwDefaultFrameInterval; /* 100ns unit */\ + uint32_t dwDefaultFrameInterval; \ uint8_t bFrameIntervalType; \ uint32_t dwFrameInterval[_nint]; \ } @@ -415,8 +413,6 @@ typedef struct TU_ATTR_PACKED { uint8_t bCopyProtect; } tusb_desc_video_format_mjpeg_t; -TU_VERIFY_STATIC(sizeof(tusb_desc_video_format_mjpeg_t) == 11, "size is not correct"); - // MJPEG payload specs: 3.1.2 frame descriptor (same as uncompressed) typedef tusb_desc_video_frame_uncompressed_t tusb_desc_video_frame_mjpeg_t; typedef tusb_desc_video_frame_uncompressed_1int_t tusb_desc_video_frame_mjpeg_1int_t; diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c index c33dfa0b0..1affd615e 100644 --- a/src/class/video/video_device.c +++ b/src/class/video/video_device.c @@ -559,7 +559,6 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * uint_fast8_t num_intervals = frm->uncompressed.bFrameIntervalType; if (num_intervals) { interval = 0; - interval_ms = 0; } else { interval = frm->uncompressed.dwFrameInterval[2]; interval_ms = interval / 10000; diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index 2e9f1d9cd..0f4dc93f3 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -60,7 +60,6 @@ void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); static inline void tu_print_buf(uint8_t const* buf, uint32_t bufsize) { for(uint32_t i=0; i= 2 diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 76696396b..d6c3db4ce 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -224,7 +224,6 @@ static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t if (wrap_bytes > 0) _ff_push_const_addr(ff_buf, app_buf, wrap_bytes); } break; - default: break; } } diff --git a/src/device/usbd.c b/src/device/usbd.c index be85d7769..5c94ebcc5 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -500,6 +500,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) case DCD_EVENT_SETUP_RECEIVED: TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8); + TU_LOG_USBD("\r\n"); // Mark as connected after receiving 1st setup packet. // But it is easier to set it every time instead of wasting time to check then set diff --git a/src/host/usbh.c b/src/host/usbh.c index f56290a0c..dfe6ddb42 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -343,12 +343,12 @@ bool tuh_init(uint8_t controller_id) { if ( tuh_inited() ) 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_INT(CFG_TUH_LOG_LEVEL, sizeof(usbh_device_t)); + TU_LOG_INT(CFG_TUH_LOG_LEVEL, sizeof(hcd_event_t)); + TU_LOG_INT(CFG_TUH_LOG_LEVEL, sizeof(_ctrl_xfer)); + TU_LOG_INT(CFG_TUH_LOG_LEVEL, sizeof(tuh_xfer_t)); + TU_LOG_INT(CFG_TUH_LOG_LEVEL, sizeof(tu_fifo_t)); + TU_LOG_INT(CFG_TUH_LOG_LEVEL, sizeof(tu_edpt_stream_t)); // Event queue _usbh_q = osal_queue_create( &_usbh_qdef ); @@ -588,7 +588,8 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { TU_LOG_USBH("[%u:%u] %s: ", rhport, daddr, (xfer->setup->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME) ? tu_str_std_request[xfer->setup->bRequest] : "Class Request"); - TU_LOG_BUF_USBH(xfer->setup, 8); + TU_LOG_BUF(CFG_TUH_LOG_LEVEL, xfer->setup, 8); + TU_LOG_USBH("\r\n"); if (xfer->complete_cb) { TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t const*) &_ctrl_xfer.request) ); @@ -659,8 +660,9 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result tusb_control_request_t const * request = &_ctrl_xfer.request; if (XFER_RESULT_SUCCESS != result) { - TU_LOG_USBH("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); - TU_LOG_BUF_USBH(request, 8); + TU_LOG1("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); + TU_LOG1_BUF(request, 8); + TU_LOG1("\r\n"); // terminate transfer if any stage failed _xfer_complete(dev_addr, result); @@ -678,7 +680,7 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result case CONTROL_STAGE_DATA: if (request->wLength) { TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, dev_addr); - TU_LOG_MEM_USBH(_ctrl_xfer.buffer, xferred_bytes, 2); + TU_LOG_MEM(CFG_TUH_LOG_LEVEL, _ctrl_xfer.buffer, xferred_bytes, 2); } _ctrl_xfer.actual_len = (uint16_t) xferred_bytes; diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index 4ed2a72b5..4a97a1c18 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -35,11 +35,7 @@ extern "C" { #endif -#define TU_LOG_USBH(...) TU_LOG(CFG_TUH_LOG_LEVEL, __VA_ARGS__) -#define TU_LOG_MEM_USBH(...) TU_LOG_MEM(CFG_TUH_LOG_LEVEL, __VA_ARGS__) -#define TU_LOG_BUF_USBH(...) TU_LOG_BUF(CFG_TUH_LOG_LEVEL, __VA_ARGS__) -#define TU_LOG_INT_USBH(...) TU_LOG_INT(CFG_TUH_LOG_LEVEL, __VA_ARGS__) -#define TU_LOG_HEX_USBH(...) TU_LOG_HEX(CFG_TUH_LOG_LEVEL, __VA_ARGS__) +#define TU_LOG_USBH(...) TU_LOG(CFG_TUH_LOG_LEVEL, __VA_ARGS__) enum { USBH_EPSIZE_BULK_MAX = (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 841cda752..4e702aed4 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -653,11 +653,7 @@ void dcd_int_handler(uint8_t rhport) if (NRF_USBD->EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk) { iso_enabled = true; - // Transfer from endpoint to RAM only if data is not corrupted - if ((int_status & USBD_INTEN_USBEVENT_Msk) == 0 || - (NRF_USBD->EVENTCAUSE & USBD_EVENTCAUSE_ISOOUTCRC_Msk) == 0) { - xact_out_dma(EP_ISO_NUM); - } + xact_out_dma(EP_ISO_NUM); } // ISOIN: Notify client that data was transferred @@ -687,7 +683,7 @@ void dcd_int_handler(uint8_t rhport) { TU_LOG(2, "EVENTCAUSE = 0x%04lX\r\n", NRF_USBD->EVENTCAUSE); - enum { EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk | USBD_EVENTCAUSE_ISOOUTCRC_Msk }; + enum { EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk }; uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & EVT_CAUSE_MASK; NRF_USBD->EVENTCAUSE = evt_cause; // clear interrupt diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 94bad5df7..4feefd771 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -83,7 +83,7 @@ typedef struct TU_ATTR_ALIGNED(16) volatile uint32_t condition_code : 4; // Word 1 - uint8_t* volatile current_buffer_pointer; + volatile uint8_t* current_buffer_pointer; // Word 2 : next TD volatile uint32_t next; -- cgit v1.3.1 From 4ed02ae5f97b57bd442521234b81a381c507d3a1 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 1 Mar 2024 17:34:14 +0700 Subject: reformat code hid_host.c - fix ceedling with ruby 3.1 - allow overwrite CMAKE_C_COMPILER/CMAKE_CXX_COMPILER from command line --- .../build_system/cmake/toolchain/arm_gcc.cmake | 12 +- src/class/hid/hid_host.c | 519 +++++++++------------ test/unit-test/project.yml | 13 +- 3 files changed, 231 insertions(+), 313 deletions(-) (limited to 'examples') diff --git a/examples/build_system/cmake/toolchain/arm_gcc.cmake b/examples/build_system/cmake/toolchain/arm_gcc.cmake index 7680d75ab..d3fd5b557 100644 --- a/examples/build_system/cmake/toolchain/arm_gcc.cmake +++ b/examples/build_system/cmake/toolchain/arm_gcc.cmake @@ -1,8 +1,14 @@ set(CMAKE_SYSTEM_NAME Generic) -set(CMAKE_C_COMPILER "arm-none-eabi-gcc") -set(CMAKE_CXX_COMPILER "arm-none-eabi-g++") -set(CMAKE_ASM_COMPILER "arm-none-eabi-gcc") +if (NOT DEFINED CMAKE_C_COMPILER) + set(CMAKE_C_COMPILER "arm-none-eabi-gcc") +endif () + +if (NOT DEFINED CMAKE_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "arm-none-eabi-g++") +endif () + +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) set(CMAKE_SIZE "arm-none-eabi-size" CACHE FILEPATH "") set(CMAKE_OBJCOPY "arm-none-eabi-objcopy" CACHE FILEPATH "") diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 709fa3dd8..21aee531a 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -39,12 +39,11 @@ #endif #define TU_LOG_DRV(...) TU_LOG(CFG_TUH_HID_LOG_LEVEL, __VA_ARGS__) + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ - -typedef struct -{ +typedef struct { uint8_t daddr; uint8_t itf_num; @@ -55,7 +54,7 @@ typedef struct uint8_t itf_protocol; // None, Keyboard, Mouse uint8_t protocol_mode; // Boot (0) or Report protocol (1) - uint8_t report_desc_type; + uint8_t report_desc_type; uint16_t report_desc_len; uint16_t epin_size; @@ -73,79 +72,57 @@ tu_static uint8_t _hidh_default_protocol = HID_PROTOCOL_BOOT; //--------------------------------------------------------------------+ // Helper //--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline -hidh_interface_t* get_hid_itf(uint8_t daddr, uint8_t idx) -{ +TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_hid_itf(uint8_t daddr, uint8_t idx) { TU_ASSERT(daddr > 0 && idx < CFG_TUH_HID, NULL); hidh_interface_t* p_hid = &_hidh_itf[idx]; return (p_hid->daddr == daddr) ? p_hid : NULL; } // Get instance ID by endpoint address -static uint8_t get_idx_by_epaddr(uint8_t daddr, uint8_t ep_addr) -{ - for ( uint8_t idx = 0; idx < CFG_TUH_HID; idx++ ) - { - hidh_interface_t const * p_hid = &_hidh_itf[idx]; - - if ( p_hid->daddr == daddr && - (p_hid->ep_in == ep_addr || p_hid->ep_out == ep_addr) ) - { +static uint8_t get_idx_by_epaddr(uint8_t daddr, uint8_t ep_addr) { + for (uint8_t idx = 0; idx < CFG_TUH_HID; idx++) { + hidh_interface_t const* p_hid = &_hidh_itf[idx]; + if (p_hid->daddr == daddr && + (p_hid->ep_in == ep_addr || p_hid->ep_out == ep_addr)) { return idx; } } - return TUSB_INDEX_INVALID_8; } -static hidh_interface_t* find_new_itf(void) -{ - for(uint8_t i=0; imounted; } -bool tuh_hid_itf_get_info(uint8_t daddr, uint8_t idx, tuh_itf_info_t* info) -{ +bool tuh_hid_itf_get_info(uint8_t daddr, uint8_t idx, tuh_itf_info_t* info) { hidh_interface_t* p_hid = get_hid_itf(daddr, idx); TU_VERIFY(p_hid && info); @@ -153,34 +130,30 @@ bool tuh_hid_itf_get_info(uint8_t daddr, uint8_t idx, tuh_itf_info_t* info) // re-construct descriptor tusb_desc_interface_t* desc = &info->desc; - desc->bLength = sizeof(tusb_desc_interface_t); - desc->bDescriptorType = TUSB_DESC_INTERFACE; + desc->bLength = sizeof(tusb_desc_interface_t); + desc->bDescriptorType = TUSB_DESC_INTERFACE; - desc->bInterfaceNumber = p_hid->itf_num; - desc->bAlternateSetting = 0; - desc->bNumEndpoints = (uint8_t) ((p_hid->ep_in ? 1u : 0u) + (p_hid->ep_out ? 1u : 0u)); - desc->bInterfaceClass = TUSB_CLASS_HID; + desc->bInterfaceNumber = p_hid->itf_num; + desc->bAlternateSetting = 0; + desc->bNumEndpoints = (uint8_t) ((p_hid->ep_in ? 1u : 0u) + (p_hid->ep_out ? 1u : 0u)); + desc->bInterfaceClass = TUSB_CLASS_HID; desc->bInterfaceSubClass = (p_hid->itf_protocol ? HID_SUBCLASS_BOOT : HID_SUBCLASS_NONE); desc->bInterfaceProtocol = p_hid->itf_protocol; - desc->iInterface = 0; // not used yet + desc->iInterface = 0; // not used yet return true; } -uint8_t tuh_hid_itf_get_index(uint8_t daddr, uint8_t itf_num) -{ - for ( uint8_t idx = 0; idx < CFG_TUH_HID; idx++ ) - { - hidh_interface_t const * p_hid = &_hidh_itf[idx]; - - if ( p_hid->daddr == daddr && p_hid->itf_num == itf_num) return idx; +uint8_t tuh_hid_itf_get_index(uint8_t daddr, uint8_t itf_num) { + for (uint8_t idx = 0; idx < CFG_TUH_HID; idx++) { + hidh_interface_t const* p_hid = &_hidh_itf[idx]; + if (p_hid->daddr == daddr && p_hid->itf_num == itf_num) return idx; } return TUSB_INDEX_INVALID_8; } -uint8_t tuh_hid_interface_protocol(uint8_t daddr, uint8_t idx) -{ +uint8_t tuh_hid_interface_protocol(uint8_t daddr, uint8_t idx) { hidh_interface_t* p_hid = get_hid_itf(daddr, idx); return p_hid ? p_hid->itf_protocol : 0; } @@ -188,29 +161,24 @@ uint8_t tuh_hid_interface_protocol(uint8_t daddr, uint8_t idx) //--------------------------------------------------------------------+ // Control Endpoint API //--------------------------------------------------------------------+ - -uint8_t tuh_hid_get_protocol(uint8_t daddr, uint8_t idx) -{ +uint8_t tuh_hid_get_protocol(uint8_t daddr, uint8_t idx) { hidh_interface_t* p_hid = get_hid_itf(daddr, idx); return p_hid ? p_hid->protocol_mode : 0; } -static void set_protocol_complete(tuh_xfer_t* xfer) -{ +static void set_protocol_complete(tuh_xfer_t* xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const daddr = xfer->daddr; - uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num); + uint8_t const daddr = xfer->daddr; + uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num); hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid, ); + TU_VERIFY(p_hid,); - if (XFER_RESULT_SUCCESS == xfer->result) - { + if (XFER_RESULT_SUCCESS == xfer->result) { p_hid->protocol_mode = (uint8_t) tu_le16toh(xfer->setup->wValue); } - if (tuh_hid_set_protocol_complete_cb) - { + if (tuh_hid_set_protocol_complete_cb) { tuh_hid_set_protocol_complete_cb(daddr, idx, p_hid->protocol_mode); } } @@ -219,123 +187,109 @@ void tuh_hid_set_default_protocol(uint8_t protocol) { _hidh_default_protocol = protocol; } -static bool _hidh_set_protocol(uint8_t daddr, uint8_t itf_num, uint8_t protocol, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +static bool _hidh_set_protocol(uint8_t daddr, uint8_t itf_num, uint8_t protocol, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG_DRV("HID Set Protocol = %d\r\n", protocol); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, - .wValue = protocol, - .wIndex = itf_num, - .wLength = 0 + tusb_control_request_t const request = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_PROTOCOL, + .wValue = protocol, + .wIndex = itf_num, + .wLength = 0 }; - tuh_xfer_t xfer = - { - .daddr = daddr, - .ep_addr = 0, - .setup = &request, - .buffer = NULL, - .complete_cb = complete_cb, - .user_data = user_data + tuh_xfer_t xfer = { + .daddr = daddr, + .ep_addr = 0, + .setup = &request, + .buffer = NULL, + .complete_cb = complete_cb, + .user_data = user_data }; return tuh_control_xfer(&xfer); } -bool tuh_hid_set_protocol(uint8_t daddr, uint8_t idx, uint8_t protocol) -{ +bool tuh_hid_set_protocol(uint8_t daddr, uint8_t idx, uint8_t protocol) { hidh_interface_t* p_hid = get_hid_itf(daddr, idx); TU_VERIFY(p_hid && p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE); return _hidh_set_protocol(daddr, p_hid->itf_num, protocol, set_protocol_complete, 0); } -static void set_report_complete(tuh_xfer_t* xfer) -{ +static void set_report_complete(tuh_xfer_t* xfer) { TU_LOG_DRV("HID Set Report complete\r\n"); - if (tuh_hid_set_report_complete_cb) - { + if (tuh_hid_set_report_complete_cb) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_hid_itf_get_index(xfer->daddr, itf_num); + uint8_t const idx = tuh_hid_itf_get_index(xfer->daddr, itf_num); uint8_t const report_type = tu_u16_high(xfer->setup->wValue); - uint8_t const report_id = tu_u16_low(xfer->setup->wValue); + uint8_t const report_id = tu_u16_low(xfer->setup->wValue); tuh_hid_set_report_complete_cb(xfer->daddr, idx, report_id, report_type, (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0); } } -bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) -{ +bool tuh_hid_set_report(uint8_t daddr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len) { hidh_interface_t* p_hid = get_hid_itf(daddr, idx); TU_VERIFY(p_hid); - TU_LOG_DRV("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_REPORT, - .wValue = tu_htole16(tu_u16(report_type, report_id)), - .wIndex = tu_htole16((uint16_t)p_hid->itf_num), - .wLength = len + tusb_control_request_t const request = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_REPORT, + .wValue = tu_htole16(tu_u16(report_type, report_id)), + .wIndex = tu_htole16((uint16_t) p_hid->itf_num), + .wLength = len }; - tuh_xfer_t xfer = - { - .daddr = daddr, - .ep_addr = 0, - .setup = &request, - .buffer = report, - .complete_cb = set_report_complete, - .user_data = 0 + tuh_xfer_t xfer = { + .daddr = daddr, + .ep_addr = 0, + .setup = &request, + .buffer = report, + .complete_cb = set_report_complete, + .user_data = 0 }; return tuh_control_xfer(&xfer); } -static bool _hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +static bool _hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // SET IDLE request, device can stall if not support this request TU_LOG_DRV("HID Set Idle \r\n"); - tusb_control_request_t const request = - { - .bmRequestType_bit = - { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = HID_REQ_CONTROL_SET_IDLE, - .wValue = tu_htole16(idle_rate), - .wIndex = tu_htole16((uint16_t)itf_num), - .wLength = 0 + tusb_control_request_t const request = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = HID_REQ_CONTROL_SET_IDLE, + .wValue = tu_htole16(idle_rate), + .wIndex = tu_htole16((uint16_t) itf_num), + .wLength = 0 }; - tuh_xfer_t xfer = - { - .daddr = daddr, - .ep_addr = 0, - .setup = &request, - .buffer = NULL, - .complete_cb = complete_cb, - .user_data = user_data + tuh_xfer_t xfer = { + .daddr = daddr, + .ep_addr = 0, + .setup = &request, + .buffer = NULL, + .complete_cb = complete_cb, + .user_data = user_data }; return tuh_control_xfer(&xfer); @@ -346,24 +300,20 @@ static bool _hidh_set_idle(uint8_t daddr, uint8_t itf_num, uint16_t idle_rate, t //--------------------------------------------------------------------+ // Check if HID interface is ready to receive report -bool tuh_hid_receive_ready(uint8_t dev_addr, uint8_t idx) -{ +bool tuh_hid_receive_ready(uint8_t dev_addr, uint8_t idx) { hidh_interface_t* p_hid = get_hid_itf(dev_addr, idx); TU_VERIFY(p_hid); - return !usbh_edpt_busy(dev_addr, p_hid->ep_in); } -bool tuh_hid_receive_report(uint8_t daddr, uint8_t idx) -{ +bool tuh_hid_receive_report(uint8_t daddr, uint8_t idx) { hidh_interface_t* p_hid = get_hid_itf(daddr, idx); TU_VERIFY(p_hid); // claim endpoint - TU_VERIFY( usbh_edpt_claim(daddr, p_hid->ep_in) ); + TU_VERIFY(usbh_edpt_claim(daddr, p_hid->ep_in)); - if ( !usbh_edpt_xfer(daddr, p_hid->ep_in, p_hid->epin_buf, p_hid->epin_size) ) - { + if (!usbh_edpt_xfer(daddr, p_hid->ep_in, p_hid->epin_buf, p_hid->epin_size)) { usbh_edpt_release(daddr, p_hid->ep_in); return false; } @@ -371,43 +321,34 @@ bool tuh_hid_receive_report(uint8_t daddr, uint8_t idx) return true; } -bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx) -{ +bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx) { hidh_interface_t* p_hid = get_hid_itf(dev_addr, idx); TU_VERIFY(p_hid); - return !usbh_edpt_busy(dev_addr, p_hid->ep_out); } -bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const void* report, uint16_t len) -{ +bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const void* report, uint16_t len) { TU_LOG_DRV("HID Send Report %d\r\n", report_id); hidh_interface_t* p_hid = get_hid_itf(daddr, idx); TU_VERIFY(p_hid); - if (p_hid->ep_out == 0) - { + if (p_hid->ep_out == 0) { // This HID does not have an out endpoint (other than control) return false; - } - else if (len > CFG_TUH_HID_EPOUT_BUFSIZE || - (report_id != 0 && len > (CFG_TUH_HID_EPOUT_BUFSIZE - 1))) - { + } else if (len > CFG_TUH_HID_EPOUT_BUFSIZE || + (report_id != 0 && len > (CFG_TUH_HID_EPOUT_BUFSIZE - 1))) { // ep_out buffer is not large enough to hold contents return false; } // claim endpoint - TU_VERIFY( usbh_edpt_claim(daddr, p_hid->ep_out) ); + TU_VERIFY(usbh_edpt_claim(daddr, p_hid->ep_out)); - if (report_id == 0) - { + if (report_id == 0) { // No report ID in transmission memcpy(&p_hid->epout_buf[0], report, len); - } - else - { + } else { p_hid->epout_buf[0] = report_id; memcpy(&p_hid->epout_buf[1], report, len); ++len; // 1 more byte for report_id @@ -415,8 +356,7 @@ bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const vo TU_LOG3_MEM(p_hid->epout_buf, len, 2); - if ( !usbh_edpt_xfer(daddr, p_hid->ep_out, p_hid->epout_buf, len) ) - { + if (!usbh_edpt_xfer(daddr, p_hid->ep_out, p_hid->epout_buf, len)) { usbh_edpt_release(daddr, p_hid->ep_out); return false; } @@ -427,13 +367,11 @@ bool tuh_hid_send_report(uint8_t daddr, uint8_t idx, uint8_t report_id, const vo //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ -void hidh_init(void) -{ +void hidh_init(void) { tu_memclr(_hidh_itf, sizeof(_hidh_itf)); } -bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ +bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; uint8_t const dir = tu_edpt_dir(ep_addr); @@ -442,28 +380,25 @@ bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t hidh_interface_t* p_hid = get_hid_itf(daddr, idx); TU_VERIFY(p_hid); - if ( dir == TUSB_DIR_IN ) - { + if (dir == TUSB_DIR_IN) { TU_LOG_DRV(" Get Report callback (%u, %u)\r\n", daddr, idx); TU_LOG3_MEM(p_hid->epin_buf, xferred_bytes, 2); tuh_hid_report_received_cb(daddr, idx, p_hid->epin_buf, (uint16_t) xferred_bytes); - }else - { - if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(daddr, idx, p_hid->epout_buf, (uint16_t) xferred_bytes); + } else { + if (tuh_hid_report_sent_cb) { + tuh_hid_report_sent_cb(daddr, idx, p_hid->epout_buf, (uint16_t) xferred_bytes); + } } return true; } -void hidh_close(uint8_t daddr) -{ - for(uint8_t i=0; idaddr == daddr) - { + if (p_hid->daddr == daddr) { TU_LOG_DRV(" HIDh close addr = %u index = %u\r\n", daddr, i); - if(tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i); + if (tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i); p_hid->daddr = 0; p_hid->mounted = false; } @@ -474,25 +409,22 @@ void hidh_close(uint8_t daddr) // Enumeration //--------------------------------------------------------------------+ -bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ +bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const* desc_itf, uint16_t max_len) { (void) rhport; (void) max_len; TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); - TU_LOG_DRV("[%u] HID opening Interface %u\r\n", daddr, desc_itf->bInterfaceNumber); // len = interface + hid + n*endpoints uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); TU_ASSERT(max_len >= drv_len); - - uint8_t const *p_desc = (uint8_t const *) desc_itf; + uint8_t const* p_desc = (uint8_t const*) desc_itf; //------------- HID descriptor -------------// p_desc = tu_desc_next(p_desc); - tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; + tusb_hid_descriptor_hid_t const* desc_hid = (tusb_hid_descriptor_hid_t const*) p_desc; TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType); hidh_interface_t* p_hid = find_new_itf(); @@ -501,38 +433,33 @@ bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *desc_ //------------- Endpoint Descriptors -------------// p_desc = tu_desc_next(p_desc); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) p_desc; - for(int i = 0; i < desc_itf->bNumEndpoints; i++) - { + for (int i = 0; i < desc_itf->bNumEndpoints; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - TU_ASSERT( tuh_edpt_open(daddr, desc_ep) ); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); - if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) - { - p_hid->ep_in = desc_ep->bEndpointAddress; + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { + p_hid->ep_in = desc_ep->bEndpointAddress; p_hid->epin_size = tu_edpt_packet_size(desc_ep); - } - else - { - p_hid->ep_out = desc_ep->bEndpointAddress; + } else { + p_hid->ep_out = desc_ep->bEndpointAddress; p_hid->epout_size = tu_edpt_packet_size(desc_ep); } p_desc = tu_desc_next(p_desc); - desc_ep = (tusb_desc_endpoint_t const *) p_desc; + desc_ep = (tusb_desc_endpoint_t const*) p_desc; } - p_hid->itf_num = desc_itf->bInterfaceNumber; + p_hid->itf_num = desc_itf->bInterfaceNumber; // Assume bNumDescriptors = 1 p_hid->report_desc_type = desc_hid->bReportType; - p_hid->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + p_hid->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config p_hid->protocol_mode = _hidh_default_protocol; - if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) - { + if (HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass) { p_hid->itf_protocol = desc_itf->bInterfaceProtocol; } @@ -553,15 +480,14 @@ enum { static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t const* desc_report, uint16_t desc_len); static void process_set_config(tuh_xfer_t* xfer); -bool hidh_set_config(uint8_t daddr, uint8_t itf_num) -{ +bool hidh_set_config(uint8_t daddr, uint8_t itf_num) { tusb_control_request_t request; request.wIndex = tu_htole16((uint16_t) itf_num); tuh_xfer_t xfer; - xfer.daddr = daddr; - xfer.result = XFER_RESULT_SUCCESS; - xfer.setup = &request; + xfer.daddr = daddr; + xfer.result = XFER_RESULT_SUCCESS; + xfer.setup = &request; xfer.user_data = CONFG_SET_IDLE; // fake request to kick-off the set config process @@ -570,71 +496,67 @@ bool hidh_set_config(uint8_t daddr, uint8_t itf_num) return true; } -static void process_set_config(tuh_xfer_t* xfer) -{ +static void process_set_config(tuh_xfer_t* xfer) { // Stall is a valid response for SET_IDLE, sometime SET_PROTOCOL as well // therefore we could ignore its result - if ( !(xfer->setup->bRequest == HID_REQ_CONTROL_SET_IDLE || - xfer->setup->bRequest == HID_REQ_CONTROL_SET_PROTOCOL) ) - { - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); + if (!(xfer->setup->bRequest == HID_REQ_CONTROL_SET_IDLE || + xfer->setup->bRequest == HID_REQ_CONTROL_SET_PROTOCOL)) { + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS,); } uintptr_t const state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const daddr = xfer->daddr; + uint8_t const daddr = xfer->daddr; - uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num); + uint8_t const idx = tuh_hid_itf_get_index(daddr, itf_num); hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid, ); + TU_VERIFY(p_hid,); - switch(state) - { - case CONFG_SET_IDLE: - { + switch (state) { + case CONFG_SET_IDLE: { // Idle rate = 0 mean only report when there is changes const uint16_t idle_rate = 0; - const uintptr_t next_state = (p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE) ? CONFIG_SET_PROTOCOL : CONFIG_GET_REPORT_DESC; + const uintptr_t next_state = (p_hid->itf_protocol != HID_ITF_PROTOCOL_NONE) + ? CONFIG_SET_PROTOCOL : CONFIG_GET_REPORT_DESC; _hidh_set_idle(daddr, itf_num, idle_rate, process_set_config, next_state); + break; } - break; case CONFIG_SET_PROTOCOL: _hidh_set_protocol(daddr, p_hid->itf_num, _hidh_default_protocol, process_set_config, CONFIG_GET_REPORT_DESC); - break; + break; case CONFIG_GET_REPORT_DESC: // Get Report Descriptor if possible // using usbh enumeration buffer since report descriptor can be very long - if( p_hid->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE ) - { + if (p_hid->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE) { TU_LOG_DRV("HID Skip Report Descriptor since it is too large %u bytes\r\n", p_hid->report_desc_len); // Driver is mounted without report descriptor config_driver_mount_complete(daddr, idx, NULL, 0); - }else - { - tuh_descriptor_get_hid_report(daddr, itf_num, p_hid->report_desc_type, 0, usbh_get_enum_buf(), p_hid->report_desc_len, process_set_config, CONFIG_COMPLETE); + } else { + tuh_descriptor_get_hid_report(daddr, itf_num, p_hid->report_desc_type, 0, + usbh_get_enum_buf(), p_hid->report_desc_len, + process_set_config, CONFIG_COMPLETE); } break; - case CONFIG_COMPLETE: - { + case CONFIG_COMPLETE: { uint8_t const* desc_report = usbh_get_enum_buf(); - uint16_t const desc_len = tu_le16toh(xfer->setup->wLength); + uint16_t const desc_len = tu_le16toh(xfer->setup->wLength); config_driver_mount_complete(daddr, idx, desc_report, desc_len); + break; } - break; - default: break; + default: + break; } } -static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t const* desc_report, uint16_t desc_len) -{ +static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t const* desc_report, uint16_t desc_len) { hidh_interface_t* p_hid = get_hid_itf(daddr, idx); - TU_VERIFY(p_hid, ); + TU_VERIFY(p_hid,); p_hid->mounted = true; // enumeration is complete @@ -648,21 +570,19 @@ static void config_driver_mount_complete(uint8_t daddr, uint8_t idx, uint8_t con // Report Descriptor Parser //--------------------------------------------------------------------+ -uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) -{ +uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count, + uint8_t const* desc_report, uint16_t desc_len) { // Report Item 6.2.2.2 USB HID 1.11 - union TU_ATTR_PACKED - { + union TU_ATTR_PACKED { uint8_t byte; - struct TU_ATTR_PACKED - { - uint8_t size : 2; - uint8_t type : 2; - uint8_t tag : 4; + struct TU_ATTR_PACKED { + uint8_t size : 2; + uint8_t type : 2; + uint8_t tag : 4; }; } header; - tu_memclr(report_info_arr, arr_count*sizeof(tuh_hid_report_info_t)); + tu_memclr(report_info_arr, arr_count * sizeof(tuh_hid_report_info_t)); uint8_t report_num = 0; tuh_hid_report_info_t* info = report_info_arr; @@ -672,114 +592,105 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, // uint8_t ri_report_size = 0; uint8_t ri_collection_depth = 0; - - while(desc_len && report_num < arr_count) - { + while (desc_len && report_num < arr_count) { header.byte = *desc_report++; desc_len--; - uint8_t const tag = header.tag; + uint8_t const tag = header.tag; uint8_t const type = header.type; uint8_t const size = header.size; uint8_t const data8 = desc_report[0]; TU_LOG(3, "tag = %d, type = %d, size = %d, data = ", tag, type, size); - for(uint32_t i=0; iusage_page, desc_report, size); - break; + if (ri_collection_depth == 0) memcpy(&info->usage_page, desc_report, size); + break; - case RI_GLOBAL_LOGICAL_MIN : break; - case RI_GLOBAL_LOGICAL_MAX : break; - case RI_GLOBAL_PHYSICAL_MIN : break; - case RI_GLOBAL_PHYSICAL_MAX : break; + case RI_GLOBAL_LOGICAL_MIN: break; + case RI_GLOBAL_LOGICAL_MAX: break; + case RI_GLOBAL_PHYSICAL_MIN: break; + case RI_GLOBAL_PHYSICAL_MAX: break; case RI_GLOBAL_REPORT_ID: info->report_id = data8; - break; + break; case RI_GLOBAL_REPORT_SIZE: // ri_report_size = data8; - break; + break; case RI_GLOBAL_REPORT_COUNT: // ri_report_count = data8; - break; + break; - case RI_GLOBAL_UNIT_EXPONENT : break; - case RI_GLOBAL_UNIT : break; - case RI_GLOBAL_PUSH : break; - case RI_GLOBAL_POP : break; + case RI_GLOBAL_UNIT_EXPONENT: break; + case RI_GLOBAL_UNIT: break; + case RI_GLOBAL_PUSH: break; + case RI_GLOBAL_POP: break; default: break; } - break; + break; case RI_TYPE_LOCAL: - switch(tag) - { + switch (tag) { case RI_LOCAL_USAGE: // only take in account the "usage" before starting REPORT ID - if ( ri_collection_depth == 0 ) info->usage = data8; - break; - - case RI_LOCAL_USAGE_MIN : break; - case RI_LOCAL_USAGE_MAX : break; - case RI_LOCAL_DESIGNATOR_INDEX : break; - case RI_LOCAL_DESIGNATOR_MIN : break; - case RI_LOCAL_DESIGNATOR_MAX : break; - case RI_LOCAL_STRING_INDEX : break; - case RI_LOCAL_STRING_MIN : break; - case RI_LOCAL_STRING_MAX : break; - case RI_LOCAL_DELIMITER : break; + if (ri_collection_depth == 0) info->usage = data8; + break; + + case RI_LOCAL_USAGE_MIN: break; + case RI_LOCAL_USAGE_MAX: break; + case RI_LOCAL_DESIGNATOR_INDEX: break; + case RI_LOCAL_DESIGNATOR_MIN: break; + case RI_LOCAL_DESIGNATOR_MAX: break; + case RI_LOCAL_STRING_INDEX: break; + case RI_LOCAL_STRING_MIN: break; + case RI_LOCAL_STRING_MAX: break; + case RI_LOCAL_DELIMITER: break; default: break; } - break; + break; - // error + // error default: break; } desc_report += size; - desc_len -= size; + desc_len -= size; } - for ( uint8_t i = 0; i < report_num; i++ ) - { - info = report_info_arr+i; + for (uint8_t i = 0; i < report_num; i++) { + info = report_info_arr + i; TU_LOG_DRV("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage); } diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index 562dbca09..82528f68c 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -44,12 +44,13 @@ # in order to add common defines: # 1) remove the trailing [] from the :common: section # 2) add entries to the :common: section (e.g. :test: has TEST defined) - :common: &common_defines - - _UNITY_TEST_ + :common: &common_defines [] :test: - - *common_defines + - _UNITY_TEST_ + #- *common_defines :test_preprocess: - - *common_defines + - _UNITY_TEST_ + #- *common_defines :cmock: :mock_prefix: mock_ @@ -106,9 +107,9 @@ :flag: "${1}" # or "-L ${1}" for example :common: &common_libraries [] :test: - - *common_libraries + #- *common_libraries :release: - - *common_libraries + #- *common_libraries :plugins: :load_paths: -- cgit v1.3.1 From 9b6f13716f34d6a82a60c8c6ec7969d420a8af28 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 4 Mar 2024 16:08:35 +0700 Subject: correct rp2040 host with max3421 --- examples/host/bare_api/src/tusb_config.h | 2 +- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- examples/host/cdc_msc_hid_freertos/src/tusb_config.h | 2 +- examples/host/hid_controller/src/tusb_config.h | 2 +- examples/host/msc_file_explorer/src/tusb_config.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'examples') diff --git a/examples/host/bare_api/src/tusb_config.h b/examples/host/bare_api/src/tusb_config.h index 05ffbdf75..432446e94 100644 --- a/examples/host/bare_api/src/tusb_config.h +++ b/examples/host/bare_api/src/tusb_config.h @@ -71,7 +71,7 @@ #if CFG_TUSB_MCU == OPT_MCU_RP2040 // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - // #define CFG_TUH_RPI_PIO_USB 1 // use max3421 as host controller + // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 76d59c316..a59a0ffb9 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -71,7 +71,7 @@ #if CFG_TUSB_MCU == OPT_MCU_RP2040 // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - // #define CFG_TUH_RPI_PIO_USB 1 // use max3421 as host controller + // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index bb7c3388d..35de5ee50 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -76,7 +76,7 @@ #if CFG_TUSB_MCU == OPT_MCU_RP2040 // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - // #define CFG_TUH_RPI_PIO_USB 1 // use max3421 as host controller + // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) diff --git a/examples/host/hid_controller/src/tusb_config.h b/examples/host/hid_controller/src/tusb_config.h index 8ddaddda7..3ac591d8f 100644 --- a/examples/host/hid_controller/src/tusb_config.h +++ b/examples/host/hid_controller/src/tusb_config.h @@ -71,7 +71,7 @@ #if CFG_TUSB_MCU == OPT_MCU_RP2040 // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - // #define CFG_TUH_RPI_PIO_USB 1 // use max3421 as host controller + // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h index 1703761a4..c798b4383 100644 --- a/examples/host/msc_file_explorer/src/tusb_config.h +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -71,7 +71,7 @@ #if CFG_TUSB_MCU == OPT_MCU_RP2040 // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - // #define CFG_TUH_RPI_PIO_USB 1 // use max3421 as host controller + // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) -- cgit v1.3.1 From 2a4b27ed336799c2b6a3d92063cf5a0c41bef172 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 11 Mar 2024 22:00:21 +0700 Subject: add led blinky to cdc_dual_ports example --- examples/device/cdc_dual_ports/src/main.c | 70 ++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 20 deletions(-) (limited to 'examples') diff --git a/examples/device/cdc_dual_ports/src/main.c b/examples/device/cdc_dual_ports/src/main.c index 98f3ab923..1167a5d50 100644 --- a/examples/device/cdc_dual_ports/src/main.c +++ b/examples/device/cdc_dual_ports/src/main.c @@ -31,12 +31,24 @@ #include "bsp/board_api.h" #include "tusb.h" -//------------- prototypes -------------// +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +static void led_blinking_task(void); static void cdc_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port @@ -46,28 +58,23 @@ int main(void) board_init_after_tusb(); } - while (1) - { + while (1) { tud_task(); // tinyusb device task cdc_task(); + led_blinking_task(); } } // echo to either Serial0 or Serial1 // with Serial0 as all lower case, Serial1 as all upper case -static void echo_serial_port(uint8_t itf, uint8_t buf[], uint32_t count) -{ +static void echo_serial_port(uint8_t itf, uint8_t buf[], uint32_t count) { uint8_t const case_diff = 'a' - 'A'; - for(uint32_t i=0; i Date: Fri, 22 Mar 2024 17:54:08 +0700 Subject: remove pca10095 suppport for max3421 also remove pico_bootsel_via_double_reset from rp2040 --- examples/host/CMakeLists.txt | 1 + hw/bsp/nrf/boards/pca10095/board.cmake | 3 --- hw/bsp/rp2040/family.cmake | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt index bedd2220b..e6a2ece14 100644 --- a/examples/host/CMakeLists.txt +++ b/examples/host/CMakeLists.txt @@ -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) diff --git a/hw/bsp/nrf/boards/pca10095/board.cmake b/hw/bsp/nrf/boards/pca10095/board.cmake index 0fbc1d31f..ca5399a3a 100644 --- a/hw/bsp/nrf/boards/pca10095/board.cmake +++ b/hw/bsp/nrf/boards/pca10095/board.cmake @@ -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 diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index ec40806fd..861d20bdd 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -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}) -- cgit v1.3.1 From 94c27fcdf77cdc4599df232b7785dfc5d3cc7407 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 22 Mar 2024 20:19:12 +0700 Subject: skip rp2040 build for cdc_msc_hid_freertos --- examples/host/cdc_msc_hid_freertos/only.txt | 1 - 1 file changed, 1 deletion(-) (limited to 'examples') diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index 3837ac8a2..81d993ffa 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -6,7 +6,6 @@ mcu:LPC43XX mcu:MIMXRT1XXX mcu:MIMXRT10XX mcu:MIMXRT11XX -mcu:RP2040 mcu:MSP432E4 mcu:RX65X mcu:RAXXX -- cgit v1.3.1 From aba00ed22c6fe9ce5ca636c2909a55ab48c65d14 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Sat, 23 Mar 2024 22:35:06 +0900 Subject: Fix the error that occurs when executing make in Windows --- examples/build_system/make/toolchain/arm_gcc.mk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/build_system/make/toolchain/arm_gcc.mk b/examples/build_system/make/toolchain/arm_gcc.mk index b87657f53..ed5ddc970 100644 --- a/examples/build_system/make/toolchain/arm_gcc.mk +++ b/examples/build_system/make/toolchain/arm_gcc.mk @@ -74,6 +74,8 @@ LDFLAGS += -Wl,--print-memory-usage endif # from version 12 -ifeq ($(shell expr $(CC_VERSION_MAJOR) \>= 12),1) +ifeq ($(strip $(if $(CMDEXE),\ + $(shell if $(CC_VERSION_MAJOR) geq 12 (echo 1) else (echo 0)),\ + $(shell expr $(CC_VERSION_MAJOR) \>= 12))), 1) LDFLAGS += -Wl,--no-warn-rwx-segment endif -- cgit v1.3.1 From 5a880013c8c83c51d8c444dcdf522a1ff778a618 Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Sun, 17 Mar 2024 22:36:09 +0900 Subject: Add UVC 2ch example --- examples/device/video_capture_2ch/CMakeLists.txt | 39 + examples/device/video_capture_2ch/Makefile | 18 + examples/device/video_capture_2ch/skip.txt | 4 + .../device/video_capture_2ch/src/CMakeLists.txt | 4 + examples/device/video_capture_2ch/src/images.h | 1939 ++++++++++++++++++++ examples/device/video_capture_2ch/src/main.c | 351 ++++ .../device/video_capture_2ch/src/tusb_config.h | 120 ++ .../device/video_capture_2ch/src/usb_descriptors.c | 669 +++++++ .../device/video_capture_2ch/src/usb_descriptors.h | 238 +++ 9 files changed, 3382 insertions(+) create mode 100644 examples/device/video_capture_2ch/CMakeLists.txt create mode 100644 examples/device/video_capture_2ch/Makefile create mode 100644 examples/device/video_capture_2ch/skip.txt create mode 100644 examples/device/video_capture_2ch/src/CMakeLists.txt create mode 100644 examples/device/video_capture_2ch/src/images.h create mode 100644 examples/device/video_capture_2ch/src/main.c create mode 100644 examples/device/video_capture_2ch/src/tusb_config.h create mode 100644 examples/device/video_capture_2ch/src/usb_descriptors.c create mode 100644 examples/device/video_capture_2ch/src/usb_descriptors.h (limited to 'examples') diff --git a/examples/device/video_capture_2ch/CMakeLists.txt b/examples/device/video_capture_2ch/CMakeLists.txt new file mode 100644 index 000000000..80dc39ca5 --- /dev/null +++ b/examples/device/video_capture_2ch/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.17) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. -) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT} C CXX ASM) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + +add_executable(${PROJECT}) + +if (FORCE_READONLY) +target_compile_definitions(${PROJECT} PRIVATE + CFG_EXAMPLE_VIDEO_READONLY +) +endif() + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c +) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src +) + +# Configure compilation flags and libraries for the example without RTOS. +# See the corresponding function in hw/bsp/FAMILY/family.cmake for details. +family_configure_device_example(${PROJECT} noos) diff --git a/examples/device/video_capture_2ch/Makefile b/examples/device/video_capture_2ch/Makefile new file mode 100644 index 000000000..d698a848d --- /dev/null +++ b/examples/device/video_capture_2ch/Makefile @@ -0,0 +1,18 @@ +include ../../build_system/make/make.mk + +ifeq ($(DISABLE_MJPEG),1) +CFLAGS += -DCFG_EXAMPLE_VIDEO_DISABLE_MJPEG +endif +ifeq ($(FORCE_READONLY),1) +CFLAGS += -DCFG_EXAMPLE_VIDEO_READONLY +endif + +INC += \ + src \ + $(TOP)/hw \ + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +include ../../build_system/make/rules.mk diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt new file mode 100644 index 000000000..db64cc639 --- /dev/null +++ b/examples/device/video_capture_2ch/skip.txt @@ -0,0 +1,4 @@ +mcu:MSP430x5xx +mcu:NUC121 +mcu:SAMD11 +family:espressif diff --git a/examples/device/video_capture_2ch/src/CMakeLists.txt b/examples/device/video_capture_2ch/src/CMakeLists.txt new file mode 100644 index 000000000..cef2b46ee --- /dev/null +++ b/examples/device/video_capture_2ch/src/CMakeLists.txt @@ -0,0 +1,4 @@ +# This file is for ESP-IDF only +idf_component_register(SRCS "main.c" "usb_descriptors.c" + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/device/video_capture_2ch/src/images.h b/examples/device/video_capture_2ch/src/images.h new file mode 100644 index 000000000..ac372cb16 --- /dev/null +++ b/examples/device/video_capture_2ch/src/images.h @@ -0,0 +1,1939 @@ +#if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) +// uncopmressed frame +static const unsigned char frame_buffer[128 * (96 + 1) * 2] = { + /* 0 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 1 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 2 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 3 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 4 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 5 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 6 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 7 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 8 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 9 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 10 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 11 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 12 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 13 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 14 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 15 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 16 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 17 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 18 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 19 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 20 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 21 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 22 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 23 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 24 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 25 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 26 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 27 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 28 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 29 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 30 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 31 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 32 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 33 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 34 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 35 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 36 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 37 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 38 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 39 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 40 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 41 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 42 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 43 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 44 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 45 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 46 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 47 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 48 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 49 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 50 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 51 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 52 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 53 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 54 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 55 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 56 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 57 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 58 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 59 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 60 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 61 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 62 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 63 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 64 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 65 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 66 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 67 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 68 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 69 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 70 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 71 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 72 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 73 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 74 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 75 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 76 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 77 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 78 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 79 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 80 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 81 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 82 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 83 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 84 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 85 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 86 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 87 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 88 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 89 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 90 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 91 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 92 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 93 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 94 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 95 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + /* 96 */ + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, 0xdb, 0x10, 0xdb, 0x8a, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, 0xbc, 0x9a, 0xbc, 0x10, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, 0xad, 0x2a, 0xad, 0x1a, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, 0x4e, 0xd6, 0x4e, 0xe6, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, 0x3f, 0x66, 0x3f, 0xf0, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, 0x20, 0xf0, 0x20, 0x76, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, +}; + +#else + +// mpeg compressed data (not CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) +#define color_bar_0_jpg_len 511 +#define color_bar_1_jpg_len 512 +#define color_bar_2_jpg_len 511 +#define color_bar_3_jpg_len 511 +#define color_bar_4_jpg_len 511 +#define color_bar_5_jpg_len 512 +#define color_bar_6_jpg_len 511 +#define color_bar_7_jpg_len 511 + +unsigned char color_bar_0_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x92, 0x8a, 0x00, + 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, + 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, + 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, + 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, + 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, + 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, + 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, + 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, + 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, + 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, + 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, + 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, + 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, + 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, + 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, + 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, + 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, + 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, + 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, + 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, + 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0xff, 0xd9 +}; +unsigned char color_bar_1_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x7d, 0x15, 0x98, + 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, + 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, + 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, + 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, + 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, + 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, + 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, + 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, + 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, + 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, + 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, + 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, + 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, + 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, + 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, + 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, + 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, + 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x7f, 0xff, 0xd9 +}; +unsigned char color_bar_2_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x75, 0x14, 0xcc, + 0xc4, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, + 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, + 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, + 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, + 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, + 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, + 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, + 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, + 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, + 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, + 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, + 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, + 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, + 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, + 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, + 0x40, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, + 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x18, 0xda, 0x2b, 0x63, 0x61, 0x28, 0xac, 0xc6, 0x25, + 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x2c, 0x51, 0x40, 0x09, 0x45, 0x66, 0x33, 0xff, 0xd9 +}; +unsigned char color_bar_3_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x5a, 0x2a, 0x08, + 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, + 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, + 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, + 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, + 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, + 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, + 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, + 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, + 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, + 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, + 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, + 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, + 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, + 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, + 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, + 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, + 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, + 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, + 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, + 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, + 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x91, 0xff, 0xd9 +}; +unsigned char color_bar_4_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x4a, 0x2a, 0xcb, + 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, + 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, + 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, + 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, + 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, + 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, + 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, + 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, + 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, + 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, + 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, + 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, + 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, + 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, + 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, + 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, + 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, + 0xc8, 0x4a, 0x2b, 0x31, 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, + 0x45, 0x66, 0x32, 0xc5, 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, + 0x8d, 0xa2, 0xb6, 0x36, 0x12, 0x8a, 0xcc, 0x62, 0x51, 0x5a, 0x99, 0x09, 0x45, 0x66, 0x32, 0xc5, + 0x14, 0x00, 0x94, 0x56, 0x63, 0x12, 0x8a, 0xd4, 0xc8, 0x4a, 0x2b, 0x31, 0x9f, 0xff, 0xd9 +}; +unsigned char color_bar_5_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x6d, 0x14, 0x8d, + 0x04, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, + 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, + 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, + 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, + 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, + 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, + 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, + 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, + 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, + 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, + 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, + 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, + 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, + 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, + 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, + 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, + 0x8a, 0x28, 0x01, 0x28, 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, + 0x6c, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x65, 0x8a, 0x28, 0x01, 0x28, + 0xac, 0xc6, 0x25, 0x15, 0xa9, 0x90, 0x94, 0x56, 0x63, 0x1b, 0x45, 0x6c, 0x6c, 0x7f, 0xff, 0xd9 +}; +unsigned char color_bar_6_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x65, 0x15, 0xa0, + 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, + 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, + 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, + 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, + 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, + 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, + 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, + 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, + 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, + 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, + 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, + 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, + 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, + 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, + 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, + 0x1b, 0x09, 0x45, 0x66, 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, + 0x2b, 0x31, 0x89, 0x45, 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, + 0x31, 0x28, 0xad, 0x4c, 0x84, 0xa2, 0xb3, 0x19, 0x62, 0x8a, 0x00, 0x4a, 0x2b, 0x31, 0x89, 0x45, + 0x6a, 0x64, 0x25, 0x15, 0x98, 0xc6, 0xd1, 0x5b, 0x1b, 0x09, 0x45, 0x66, 0x33, 0xff, 0xd9 +}; +unsigned char color_bar_7_jpg[] = { + 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, + 0x08, 0x00, 0x60, 0x00, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, + 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x8e, 0x8a, 0x00, + 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, + 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, + 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, + 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, + 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, + 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, + 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, + 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, + 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, + 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, + 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, + 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, + 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, + 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, + 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, + 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, + 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, + 0x18, 0x94, 0x56, 0xa6, 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, + 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, + 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, + 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x47, 0xff, 0xd9 +}; +#endif diff --git a/examples/device/video_capture_2ch/src/main.c b/examples/device/video_capture_2ch/src/main.c new file mode 100644 index 000000000..361f52b37 --- /dev/null +++ b/examples/device/video_capture_2ch/src/main.c @@ -0,0 +1,351 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include +#include +#include + +#include "bsp/board_api.h" +#include "tusb.h" +#include "usb_descriptors.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +void led_blinking_task(void* param); +void usb_device_task(void *param); +void video_task(void* param); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +void freertos_init_task(void); +#endif + + +//--------------------------------------------------------------------+ +// Main +//--------------------------------------------------------------------+ +int main(void) { + board_init(); + + // If using FreeRTOS: create blinky, tinyusb device, video task +#if CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init_task(); +#else + // init device stack on configured roothub port + tud_init(BOARD_TUD_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } + + while (1) { + tud_task(); // tinyusb device task + led_blinking_task(NULL); + video_task(NULL); + } +#endif +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) { + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) { + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) { + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) { + blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; +} + +//--------------------------------------------------------------------+ +// USB Video +//--------------------------------------------------------------------+ +static unsigned frame_num[CFG_TUD_VIDEO_STREAMING] = {1}; +static unsigned tx_busy = 0; +static unsigned interval_ms[CFG_TUD_VIDEO_STREAMING] = {1000 / FRAME_RATE}; + +#ifdef CFG_EXAMPLE_VIDEO_READONLY +// For mcus that does not have enough SRAM for frame buffer, we use fixed frame data. +// To further reduce the size, we use MJPEG format instead of YUY2. +#include "images.h" + +#if !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) +static struct { + uint32_t size; + uint8_t const *buffer; +} const frames[] = { + {color_bar_0_jpg_len, color_bar_0_jpg}, + {color_bar_1_jpg_len, color_bar_1_jpg}, + {color_bar_2_jpg_len, color_bar_2_jpg}, + {color_bar_3_jpg_len, color_bar_3_jpg}, + {color_bar_4_jpg_len, color_bar_4_jpg}, + {color_bar_5_jpg_len, color_bar_5_jpg}, + {color_bar_6_jpg_len, color_bar_6_jpg}, + {color_bar_7_jpg_len, color_bar_7_jpg}, +}; +#endif + +#else + +// YUY2 frame buffer +static uint8_t frame_buffer[2][FRAME_WIDTH * FRAME_HEIGHT * 16 / 8]; + +static void fill_color_bar(uint8_t* buffer, unsigned start_position) { + /* EBU color bars: https://stackoverflow.com/questions/6939422 */ + static uint8_t const bar_color[8][4] = { + /* Y, U, Y, V */ + { 235, 128, 235, 128}, /* 100% White */ + { 219, 16, 219, 138}, /* Yellow */ + { 188, 154, 188, 16}, /* Cyan */ + { 173, 42, 173, 26}, /* Green */ + { 78, 214, 78, 230}, /* Magenta */ + { 63, 102, 63, 240}, /* Red */ + { 32, 240, 32, 118}, /* Blue */ + { 16, 128, 16, 128}, /* Black */ + }; + uint8_t* p; + + /* Generate the 1st line */ + uint8_t* end = &buffer[FRAME_WIDTH * 2]; + unsigned idx = (FRAME_WIDTH / 2 - 1) - (start_position % (FRAME_WIDTH / 2)); + p = &buffer[idx * 4]; + for (unsigned i = 0; i < 8; ++i) { + for (int j = 0; j < FRAME_WIDTH / (2 * 8); ++j) { + memcpy(p, &bar_color[i], 4); + p += 4; + if (end <= p) { + p = buffer; + } + } + } + + /* Duplicate the 1st line to the others */ + p = &buffer[FRAME_WIDTH * 2]; + for (unsigned i = 1; i < FRAME_HEIGHT; ++i) { + memcpy(p, buffer, FRAME_WIDTH * 2); + p += FRAME_WIDTH * 2; + } +} + +#endif + +void video_send_frame(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { + static unsigned start_ms[CFG_TUD_VIDEO_STREAMING] = {0, }; + static unsigned already_sent = 0; + + uint32_t idx = ctl_idx + stm_idx; + if (!tud_video_n_streaming(ctl_idx, stm_idx)) { + already_sent &= ~(1u << idx); + frame_num[idx] = 0; + return; + } + + if (!(already_sent & (1u << idx))) { + already_sent |= 1u << idx; + tx_busy |= 1u << idx; + start_ms[idx] = board_millis(); +#ifdef CFG_EXAMPLE_VIDEO_READONLY + #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) + tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*)(uintptr_t)&frame_buffer[(frame_num[idx] % (FRAME_WIDTH / 2)) * 4], + FRAME_WIDTH * FRAME_HEIGHT * 16/8); + #else + tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*)(uintptr_t)frames[frame_num[idx] % 8].buffer, frames[frame_num[idx] % 8].size); + #endif +#else + fill_color_bar(frame_buffer[idx], frame_num[idx]); + tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*) frame_buffer[idx], FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); +#endif + } + + unsigned cur = board_millis(); + if (cur - start_ms[idx] < interval_ms[idx]) return; // not enough time + if (tx_busy & (1u << idx)) return; + start_ms[idx] += interval_ms[idx]; + tx_busy |= 1u << idx; + +#ifdef CFG_EXAMPLE_VIDEO_READONLY + #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) + tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*)(uintptr_t)&frame_buffer[(frame_num[idx] % (FRAME_WIDTH / 2)) * 4], + FRAME_WIDTH * FRAME_HEIGHT * 16/8); + #else + tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*)(uintptr_t)frames[frame_num[idx] % 8].buffer, frames[frame_num[idx] % 8].size); + #endif +#else + fill_color_bar(frame_buffer[idx], frame_num[idx]); + tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*) frame_buffer[idx], FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); +#endif +} + + +void video_task(void* param) { + (void) param; + + while(1) { + video_send_frame(0, 0); + video_send_frame(1, 0); + + #if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(interval_ms[0] / portTICK_PERIOD_MS); + #else + return; + #endif + } +} + +void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { + uint32_t idx = ctl_idx + stm_idx; + tx_busy &= ~(1u << idx); + /* flip buffer */ + ++frame_num[idx]; +} + +int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, + video_probe_and_commit_control_t const* parameters) { + uint32_t idx = ctl_idx + stm_idx; + /* convert unit to ms from 100 ns */ + interval_ms[idx] = parameters->dwFrameInterval / 10000; + return VIDEO_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// Blinking Task +//--------------------------------------------------------------------+ +void led_blinking_task(void* param) { + (void) param; + static uint32_t start_ms = 0; + static bool led_state = false; + + while (1) { + #if CFG_TUSB_OS == OPT_OS_FREERTOS + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + #else + if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + #endif + + start_ms += blink_interval_ms; + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } +} + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS + +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4) + +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + #define USBD_STACK_SIZE 4096 + int main(void); + void app_main(void) { + main(); + } +#else + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) +#endif + +// static task +#if configSUPPORT_STATIC_ALLOCATION +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; + +StackType_t usb_device_stack[USBD_STACK_SIZE]; +StaticTask_t usb_device_taskdef; + +StackType_t video_stack[VIDEO_STACK_SIZE]; +StaticTask_t video_taskdef; +#endif + +// USB Device Driver task +// This top level thread process all usb events and invoke callbacks +void usb_device_task(void *param) { + (void) param; + + // init device stack on configured roothub port + // This should be called after scheduler/kernel is started. + // Otherwise, it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tud_init(BOARD_TUD_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } + + // RTOS forever loop + while (1) { + // put this thread to waiting state until there is new events + tud_task(); + } +} + +void freertos_init_task(void) { + #if configSUPPORT_STATIC_ALLOCATION + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); + xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); + xTaskCreateStatic(video_task, "cdc", VIDEO_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, video_stack, &video_taskdef); + #else + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(video_task, "video", VIDEO_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL); + #endif + + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 + #if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + vTaskStartScheduler(); + #endif +} +#endif diff --git a/examples/device/video_capture_2ch/src/tusb_config.h b/examples/device/video_capture_2ch/src/tusb_config.h new file mode 100644 index 000000000..fe66d63b5 --- /dev/null +++ b/examples/device/video_capture_2ch/src/tusb_config.h @@ -0,0 +1,120 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 +#endif + +// RHPort max operational speed can defined by board.mk +#ifndef BOARD_TUD_MAX_SPEED +#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + +//-------------------------------------------------------------------- +// Common Configuration +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined +#endif + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +// Espressif IDF requires "freertos/" prefix in include path +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + +// Enable Device stack +#define CFG_TUD_ENABLED 1 + +// Default is max speed that hardware controller could support with on-chip PHY +#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +// The number of video control interfaces +#define CFG_TUD_VIDEO 2 + +// The number of video streaming interfaces +#define CFG_TUD_VIDEO_STREAMING 2 + +// video streaming endpoint buffer size +#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 256 + +// use bulk endpoint for streaming interface +#define CFG_TUD_VIDEO_STREAMING_BULK 1 + +//#define CFG_EXAMPLE_VIDEO_READONLY +//#define CFG_EXAMPLE_VIDEO_DISABLE_MJPEG + +#define CFG_TUD_VIDEO_LOG_LEVEL 1 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/video_capture_2ch/src/usb_descriptors.c b/examples/device/video_capture_2ch/src/usb_descriptors.c new file mode 100644 index 000000000..0c1066416 --- /dev/null +++ b/examples/device/video_capture_2ch/src/usb_descriptors.c @@ -0,0 +1,669 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "bsp/board_api.h" +#include "tusb.h" +#include "usb_descriptors.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] VIDEO | AUDIO | MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VIDEO, 5) | _PID_MAP(VENDOR, 6) ) + +#define USB_VID 0xCafe +#define USB_BCD 0x0200 + +// String Descriptor Index +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, + STRID_UVC_CONTROL_1, + STRID_UVC_STREAMING_1, + STRID_UVC_CONTROL_2, + STRID_UVC_STREAMING_2, +}; + +// array of pointer to string descriptors +char const* string_desc_arr[] = { + (const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "TinyUSB UVC Control 1", // 4: UVC Interface 1 + "TinyUSB UVC Streaming 1", // 5: UVC Interface 1 + "TinyUSB UVC Control 2", // 6: UVC Interface 2 + "TinyUSB UVC Streaming 2", // 7: UVC Interface 2 +}; + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + + // Use Interface Association Descriptor (IAD) for Video + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = USB_VID, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = STRID_MANUFACTURER, + .iProduct = STRID_PRODUCT, + .iSerialNumber = STRID_SERIAL, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const* tud_descriptor_device_cb(void) { + return (uint8_t const*) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ + +/* Time stamp base clock. It is a deprecated parameter. */ +#define UVC_CLOCK_FREQUENCY 27000000 + +/* video capture path */ +#define UVC_ENTITY_CAP_INPUT_TERMINAL 0x01 +#define UVC_ENTITY_CAP_OUTPUT_TERMINAL 0x02 + +enum { + ITF_NUM_VIDEO_CONTROL_1, + ITF_NUM_VIDEO_STREAMING_1, + ITF_NUM_VIDEO_CONTROL_2, + ITF_NUM_VIDEO_STREAMING_2, + ITF_NUM_TOTAL +}; + +#define EPNUM_VIDEO_IN_1 0x81 +#define EPNUM_VIDEO_IN_2 0x82 + +#if defined(CFG_EXAMPLE_VIDEO_READONLY) && !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) + #define USE_MJPEG 1 +#else + #define USE_MJPEG 0 +#endif + +#define USE_ISO_STREAMING (!CFG_TUD_VIDEO_STREAMING_BULK) + +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_control_header_1itf_t header; + tusb_desc_video_control_camera_terminal_t camera_terminal; + tusb_desc_video_control_output_terminal_t output_terminal; +} uvc_control_desc_t; + +/* Windows support YUY2 and NV12 + * https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/usb-video-class-driver-overview */ + +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_streaming_input_header_1byte_t header; + +#if USE_MJPEG + tusb_desc_video_format_mjpeg_t format; + tusb_desc_video_frame_mjpeg_continuous_t frame; +#else + tusb_desc_video_format_uncompressed_t format; + tusb_desc_video_frame_uncompressed_continuous_t frame; +#endif + + tusb_desc_video_streaming_color_matching_t color; + +#if USE_ISO_STREAMING + // For ISO streaming, USB spec requires to alternate interface + tusb_desc_interface_t itf_alt; +#endif + + tusb_desc_endpoint_t ep; +} uvc_streaming_desc_t; + +typedef struct TU_ATTR_PACKED { + tusb_desc_configuration_t config; + struct TU_ATTR_PACKED { + tusb_desc_interface_assoc_t iad; + uvc_control_desc_t video_control; + uvc_streaming_desc_t video_streaming; + } uvc[2]; +} uvc_cfg_desc_t; + +const uvc_cfg_desc_t desc_fs_configuration = { + .config = { + .bLength = sizeof(tusb_desc_configuration_t), + .bDescriptorType = TUSB_DESC_CONFIGURATION, + + .wTotalLength = sizeof(uvc_cfg_desc_t), + .bNumInterfaces = ITF_NUM_TOTAL, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = TU_BIT(7), + .bMaxPower = 100 / 2 + }, + .uvc = { + { + .iad = { + .bLength = sizeof(tusb_desc_interface_assoc_t), + .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, + + .bFirstInterface = ITF_NUM_VIDEO_CONTROL_1, + .bInterfaceCount = 2, + .bFunctionClass = TUSB_CLASS_VIDEO, + .bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION, + .bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED, + .iFunction = 0 + }, + + .video_control = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_CONTROL_1, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_CONTROL_1 + }, + .header = { + .bLength = sizeof(tusb_desc_video_control_header_1itf_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER, + + .bcdUVC = VIDEO_BCD_1_50, + .wTotalLength = sizeof(uvc_control_desc_t) - sizeof(tusb_desc_interface_t), // CS VC descriptors only + .dwClockFrequency = UVC_CLOCK_FREQUENCY, + .bInCollection = 1, + .baInterfaceNr = { ITF_NUM_VIDEO_STREAMING_1 } + }, + .camera_terminal = { + .bLength = sizeof(tusb_desc_video_control_camera_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .wTerminalType = VIDEO_ITT_CAMERA, + .bAssocTerminal = 0, + .iTerminal = 0, + .wObjectiveFocalLengthMin = 0, + .wObjectiveFocalLengthMax = 0, + .wOcularFocalLength = 0, + .bControlSize = 3, + .bmControls = { 0, 0, 0 } + }, + .output_terminal = { + .bLength = sizeof(tusb_desc_video_control_output_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .wTerminalType = VIDEO_TT_STREAMING, + .bAssocTerminal = 0, + .bSourceID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .iTerminal = 0 + } + }, + + .video_streaming = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_1, + .bAlternateSetting = 0, + .bNumEndpoints = CFG_TUD_VIDEO_STREAMING_BULK, // bulk 1, iso 0 + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_1 + }, + .header = { + .bLength = sizeof(tusb_desc_video_streaming_input_header_1byte_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, + + .bNumFormats = 1, + .wTotalLength = sizeof(uvc_streaming_desc_t) - sizeof(tusb_desc_interface_t) + - sizeof(tusb_desc_endpoint_t) - (USE_ISO_STREAMING ? sizeof(tusb_desc_interface_t) : 0) , // CS VS descriptors only + .bEndpointAddress = EPNUM_VIDEO_IN_1, + .bmInfo = 0, + .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .bStillCaptureMethod = 0, + .bTriggerSupport = 0, + .bTriggerUsage = 0, + .bControlSize = 1, + .bmaControls = { 0 } + }, + .format = { +#if USE_MJPEG + .bLength = sizeof(tusb_desc_video_format_mjpeg_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_MJPEG, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .bmFlags = 0, +#else + .bLength = sizeof(tusb_desc_video_format_uncompressed_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .guidFormat = { TUD_VIDEO_GUID_YUY2 }, + .bBitsPerPixel = 16, +#endif + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, + .bAspectRatioY = 0, + .bmInterlaceFlags = 0, + .bCopyProtect = 0 + }, + .frame = { +#if USE_MJPEG + .bLength = sizeof(tusb_desc_video_frame_mjpeg_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_MJPEG, +#else + .bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, +#endif + .bFrameIndex = 1, // 1-based index + .bmCapabilities = 0, + .wWidth = FRAME_WIDTH, + .wHeight = FRAME_HEIGHT, + .dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1, + .dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE, + .dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8, + .dwDefaultFrameInterval = 10000000 / FRAME_RATE, + .bFrameIntervalType = 0, // continuous + .dwFrameInterval = { + 10000000 / FRAME_RATE, // min + 10000000, // max + 10000000 / FRAME_RATE // step + } + }, + .color = { + .bLength = sizeof(tusb_desc_video_streaming_color_matching_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT, + + .bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709, + .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, + .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M + }, + +#if USE_ISO_STREAMING + .itf_alt = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_1, + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_1 + }, +#endif + + .ep = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = EPNUM_VIDEO_IN_1, + .bmAttributes = { + .xfer = CFG_TUD_VIDEO_STREAMING_BULK ? TUSB_XFER_BULK : TUSB_XFER_ISOCHRONOUS, + .sync = CFG_TUD_VIDEO_STREAMING_BULK ? 0 : 1 // asynchronous + }, + .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, + .bInterval = 1 + } + } + }, + { + .iad = { + .bLength = sizeof(tusb_desc_interface_assoc_t), + .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, + + .bFirstInterface = ITF_NUM_VIDEO_CONTROL_2, + .bInterfaceCount = 2, + .bFunctionClass = TUSB_CLASS_VIDEO, + .bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION, + .bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED, + .iFunction = 0 + }, + + .video_control = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_CONTROL_2, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_CONTROL_2 + }, + .header = { + .bLength = sizeof(tusb_desc_video_control_header_1itf_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER, + + .bcdUVC = VIDEO_BCD_1_50, + .wTotalLength = sizeof(uvc_control_desc_t) - sizeof(tusb_desc_interface_t), // CS VC descriptors only + .dwClockFrequency = UVC_CLOCK_FREQUENCY, + .bInCollection = 1, + .baInterfaceNr = { ITF_NUM_VIDEO_STREAMING_2 } + }, + .camera_terminal = { + .bLength = sizeof(tusb_desc_video_control_camera_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .wTerminalType = VIDEO_ITT_CAMERA, + .bAssocTerminal = 0, + .iTerminal = 0, + .wObjectiveFocalLengthMin = 0, + .wObjectiveFocalLengthMax = 0, + .wOcularFocalLength = 0, + .bControlSize = 3, + .bmControls = { 0, 0, 0 } + }, + .output_terminal = { + .bLength = sizeof(tusb_desc_video_control_output_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .wTerminalType = VIDEO_TT_STREAMING, + .bAssocTerminal = 0, + .bSourceID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .iTerminal = 0 + } + }, + + .video_streaming = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_2, + .bAlternateSetting = 0, + .bNumEndpoints = CFG_TUD_VIDEO_STREAMING_BULK, // bulk 1, iso 0 + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_2 + }, + .header = { + .bLength = sizeof(tusb_desc_video_streaming_input_header_1byte_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, + + .bNumFormats = 1, + .wTotalLength = sizeof(uvc_streaming_desc_t) - sizeof(tusb_desc_interface_t) + - sizeof(tusb_desc_endpoint_t) - (USE_ISO_STREAMING ? sizeof(tusb_desc_interface_t) : 0) , // CS VS descriptors only + .bEndpointAddress = EPNUM_VIDEO_IN_2, + .bmInfo = 0, + .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .bStillCaptureMethod = 0, + .bTriggerSupport = 0, + .bTriggerUsage = 0, + .bControlSize = 1, + .bmaControls = { 0 } + }, + .format = { +#if USE_MJPEG + .bLength = sizeof(tusb_desc_video_format_mjpeg_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_MJPEG, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .bmFlags = 0, +#else + .bLength = sizeof(tusb_desc_video_format_uncompressed_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .guidFormat = { TUD_VIDEO_GUID_YUY2 }, + .bBitsPerPixel = 16, +#endif + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, + .bAspectRatioY = 0, + .bmInterlaceFlags = 0, + .bCopyProtect = 0 + }, + .frame = { +#if USE_MJPEG + .bLength = sizeof(tusb_desc_video_frame_mjpeg_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_MJPEG, +#else + .bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, +#endif + .bFrameIndex = 1, // 1-based index + .bmCapabilities = 0, + .wWidth = FRAME_WIDTH, + .wHeight = FRAME_HEIGHT, + .dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1, + .dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE, + .dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8, + .dwDefaultFrameInterval = 10000000 / FRAME_RATE, + .bFrameIntervalType = 0, // continuous + .dwFrameInterval = { + 10000000 / FRAME_RATE, // min + 10000000, // max + 10000000 / FRAME_RATE // step + } + }, + .color = { + .bLength = sizeof(tusb_desc_video_streaming_color_matching_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT, + + .bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709, + .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, + .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M + }, + +#if USE_ISO_STREAMING + .itf_alt = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_2, + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_2 + }, +#endif + + .ep = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = EPNUM_VIDEO_IN_2, + .bmAttributes = { + .xfer = CFG_TUD_VIDEO_STREAMING_BULK ? TUSB_XFER_BULK : TUSB_XFER_ISOCHRONOUS, + .sync = CFG_TUD_VIDEO_STREAMING_BULK ? 0 : 1 // asynchronous + }, + .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, + .bInterval = 1 + } + } + } + } +}; + +#if TUD_OPT_HIGH_SPEED +uvc_cfg_desc_t desc_hs_configuration; + +static uint8_t * get_hs_configuration_desc(void) { + static bool init = false; + + if (!init) { + desc_hs_configuration = desc_fs_configuration; + // change endpoint bulk size to 512 if bulk streaming + if (CFG_TUD_VIDEO_STREAMING_BULK) { + desc_hs_configuration.video_streaming.ep.wMaxPacketSize = 512; + } + } + init = true; + + return (uint8_t *) &desc_hs_configuration; +} + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const* tud_descriptor_device_qualifier_cb(void) { + return (uint8_t const*) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations + // if link speed is high return fullspeed config, and vice versa + if (tud_speed_get() == TUSB_SPEED_HIGH) { + return (uint8_t const*) &desc_fs_configuration; + } else { + return get_hs_configuration_desc(); + } +} +#endif // highspeed + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const* tud_descriptor_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + if (tud_speed_get() == TUSB_SPEED_HIGH) { + return get_hs_configuration_desc(); + } else +#endif + { + return (uint8_t const*) &desc_fs_configuration; + } +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +static uint16_t _desc_str[32 + 1]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + (void) langid; + size_t chr_count; + + switch (index) { + case STRID_LANGID: + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + break; + + case STRID_SERIAL: + chr_count = board_usb_get_serial(_desc_str + 1, 32); + break; + + default: + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + + if (index >= sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type + if (chr_count > max_count) chr_count = max_count; + + // Convert ASCII string into UTF-16 + for (size_t i = 0; i < chr_count; i++) { + _desc_str[1 + i] = str[i]; + } + break; + } + + // first byte is length (including header), second byte is string type + _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); + + return _desc_str; +} diff --git a/examples/device/video_capture_2ch/src/usb_descriptors.h b/examples/device/video_capture_2ch/src/usb_descriptors.h new file mode 100644 index 000000000..12d41b2f3 --- /dev/null +++ b/examples/device/video_capture_2ch/src/usb_descriptors.h @@ -0,0 +1,238 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Jerzy Kasenbreg + * Copyright (c) 2021 Koji KITAYAMA + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _USB_DESCRIPTORS_H_ +#define _USB_DESCRIPTORS_H_ + +#define FRAME_WIDTH 128 +#define FRAME_HEIGHT 96 +#define FRAME_RATE 10 + +// NOTE: descriptor template is not used but leave here as reference + +#define TUD_VIDEO_CAPTURE_DESC_UNCOMPR_LEN (\ + TUD_VIDEO_DESC_IAD_LEN\ + /* control */\ + + TUD_VIDEO_DESC_STD_VC_LEN\ + + (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\ + + TUD_VIDEO_DESC_CAMERA_TERM_LEN\ + + TUD_VIDEO_DESC_OUTPUT_TERM_LEN\ + /* Interface 1, Alternate 0 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\ + + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\ + + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\ + + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\ + /* Interface 1, Alternate 1 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + 7/* Endpoint */\ + ) + +#define TUD_VIDEO_CAPTURE_DESC_MJPEG_LEN (\ + TUD_VIDEO_DESC_IAD_LEN\ + /* control */\ + + TUD_VIDEO_DESC_STD_VC_LEN\ + + (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\ + + TUD_VIDEO_DESC_CAMERA_TERM_LEN\ + + TUD_VIDEO_DESC_OUTPUT_TERM_LEN\ + /* Interface 1, Alternate 0 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\ + + TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\ + + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\ + + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\ + /* Interface 1, Alternate 1 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + 7/* Endpoint */\ + ) + +#define TUD_VIDEO_CAPTURE_DESC_UNCOMPR_BULK_LEN (\ + TUD_VIDEO_DESC_IAD_LEN\ + /* control */\ + + TUD_VIDEO_DESC_STD_VC_LEN\ + + (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\ + + TUD_VIDEO_DESC_CAMERA_TERM_LEN\ + + TUD_VIDEO_DESC_OUTPUT_TERM_LEN\ + /* Interface 1, Alternate 0 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\ + + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN\ + + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN\ + + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\ + + 7/* Endpoint */\ + ) + +#define TUD_VIDEO_CAPTURE_DESC_MJPEG_BULK_LEN (\ + TUD_VIDEO_DESC_IAD_LEN\ + /* control */\ + + TUD_VIDEO_DESC_STD_VC_LEN\ + + (TUD_VIDEO_DESC_CS_VC_LEN + 1/*bInCollection*/)\ + + TUD_VIDEO_DESC_CAMERA_TERM_LEN\ + + TUD_VIDEO_DESC_OUTPUT_TERM_LEN\ + /* Interface 1, Alternate 0 */\ + + TUD_VIDEO_DESC_STD_VS_LEN\ + + (TUD_VIDEO_DESC_CS_VS_IN_LEN + 1/*bNumFormats x bControlSize*/)\ + + TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN\ + + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN\ + + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN\ + + 7/* Endpoint */\ + ) + +/* Windows support YUY2 and NV12 + * https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/usb-video-class-driver-overview */ + +#define TUD_VIDEO_DESC_CS_VS_FMT_YUY2(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_YUY2, 16, _frmidx, _asrx, _asry, _interlace, _cp) +#define TUD_VIDEO_DESC_CS_VS_FMT_NV12(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_NV12, 12, _frmidx, _asrx, _asry, _interlace, _cp) +#define TUD_VIDEO_DESC_CS_VS_FMT_M420(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_M420, 12, _frmidx, _asrx, _asry, _interlace, _cp) +#define TUD_VIDEO_DESC_CS_VS_FMT_I420(_fmtidx, _numfmtdesc, _frmidx, _asrx, _asry, _interlace, _cp) \ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR(_fmtidx, _numfmtdesc, TUD_VIDEO_GUID_I420, 12, _frmidx, _asrx, _asry, _interlace, _cp) + +#define TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR(_stridx, _epin, _width, _height, _fps, _epsize) \ + TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ + /* Video control 0 */ \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ + TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ + /* Video stream alt. 0 */ \ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 0, _stridx), \ + /* Video stream header for without still image capture */ \ + TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ + /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ + /*bmaControls(1)*/0), \ + /* Video stream format */ \ + TUD_VIDEO_DESC_CS_VS_FMT_YUY2(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \ + /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \ + /* Video stream frame format */ \ + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \ + _width * _height * 16, _width * _height * 16 * _fps, \ + _width * _height * 16 / 8, \ + (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ + /* VS alt 1 */\ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 1, 1, _stridx), \ + /* EP */ \ + TUD_VIDEO_DESC_EP_ISO(_epin, _epsize, 1) + +#define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG(_stridx, _epin, _width, _height, _fps, _epsize) \ + TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ + /* Video control 0 */ \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ + TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ + /* Video stream alt. 0 */ \ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 0, _stridx), \ + /* Video stream header for without still image capture */ \ + TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ + /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ + /*bmaControls(1)*/0), \ + /* Video stream format */ \ + TUD_VIDEO_DESC_CS_VS_FMT_MJPEG(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \ + /*bmFlags*/0, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \ + /* Video stream frame format */ \ + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT(/*bFrameIndex */1, 0, _width, _height, \ + _width * _height * 16, _width * _height * 16 * _fps, \ + _width * _height * 16 / 8, \ + (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ + /* VS alt 1 */\ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 1, 1, _stridx), \ + /* EP */ \ + TUD_VIDEO_DESC_EP_ISO(_epin, _epsize, 1) + + +#define TUD_VIDEO_CAPTURE_DESCRIPTOR_UNCOMPR_BULK(_stridx, _epin, _width, _height, _fps, _epsize) \ + TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ + /* Video control 0 */ \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ + TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, 1, 0), \ + /* Video stream alt. 0 */ \ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 1, _stridx), \ + /* Video stream header for without still image capture */ \ + TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ + /*wTotalLength - bLength */\ + TUD_VIDEO_DESC_CS_VS_FMT_UNCOMPR_LEN + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ + /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ + /*bmaControls(1)*/0), \ + /* Video stream format */ \ + TUD_VIDEO_DESC_CS_VS_FMT_YUY2(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \ + /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \ + /* Video stream frame format */ \ + TUD_VIDEO_DESC_CS_VS_FRM_UNCOMPR_CONT(/*bFrameIndex */1, 0, _width, _height, \ + _width * _height * 16, _width * _height * 16 * _fps, \ + _width * _height * 16 / 8, \ + (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ + TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1) + +#define TUD_VIDEO_CAPTURE_DESCRIPTOR_MJPEG_BULK(_stridx, _epin, _width, _height, _fps, _epsize) \ + TUD_VIDEO_DESC_IAD(ITF_NUM_VIDEO_CONTROL, /* 2 Interfaces */ 0x02, _stridx), \ + /* Video control 0 */ \ + TUD_VIDEO_DESC_STD_VC(ITF_NUM_VIDEO_CONTROL, 0, _stridx), \ + /* Header: UVC 1.5, length of followed descs, clock (deprecated), streaming interfaces */ \ + TUD_VIDEO_DESC_CS_VC(0x0150, TUD_VIDEO_DESC_CAMERA_TERM_LEN + TUD_VIDEO_DESC_OUTPUT_TERM_LEN, UVC_CLOCK_FREQUENCY, ITF_NUM_VIDEO_STREAMING), \ + /* Camera Terminal: ID, bAssocTerminal, iTerminal, focal min, max, length, bmControl */ \ + TUD_VIDEO_DESC_CAMERA_TERM(UVC_ENTITY_CAP_INPUT_TERMINAL, 0, 0, 0, 0, 0, 0), \ + TUD_VIDEO_DESC_OUTPUT_TERM(UVC_ENTITY_CAP_OUTPUT_TERMINAL, VIDEO_TT_STREAMING, 0, UVC_ENTITY_CAP_INPUT_TERMINAL, 0), \ + /* Video stream alt. 0 */ \ + TUD_VIDEO_DESC_STD_VS(ITF_NUM_VIDEO_STREAMING, 0, 1, _stridx), \ + /* Video stream header for without still image capture */ \ + TUD_VIDEO_DESC_CS_VS_INPUT( /*bNumFormats*/1, \ + /*wTotalLength - bLength */ TUD_VIDEO_DESC_CS_VS_FMT_MJPEG_LEN + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT_LEN + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING_LEN,\ + _epin, /*bmInfo*/0, /*bTerminalLink*/UVC_ENTITY_CAP_OUTPUT_TERMINAL, \ + /*bStillCaptureMethod*/0, /*bTriggerSupport*/0, /*bTriggerUsage*/0, \ + /*bmaControls(1)*/0), \ + /* Video stream format */ \ + TUD_VIDEO_DESC_CS_VS_FMT_MJPEG(/*bFormatIndex*/1, /*bNumFrameDescriptors*/1, \ + /*bmFlags*/0, /*bDefaultFrameIndex*/1, 0, 0, 0, /*bCopyProtect*/0), \ + /* Video stream frame format */ \ + TUD_VIDEO_DESC_CS_VS_FRM_MJPEG_CONT(/*bFrameIndex */1, 0, _width, _height, \ + _width * _height * 16, _width * _height * 16 * _fps, \ + _width * _height * 16 / 8, \ + (10000000/_fps), (10000000/_fps), (10000000/_fps)*_fps, (10000000/_fps)), \ + TUD_VIDEO_DESC_CS_VS_COLOR_MATCHING(VIDEO_COLOR_PRIMARIES_BT709, VIDEO_COLOR_XFER_CH_BT709, VIDEO_COLOR_COEF_SMPTE170M), \ + /* EP */ \ + TUD_VIDEO_DESC_EP_BULK(_epin, _epsize, 1) + + +#endif -- cgit v1.3.1 From 8f04d96c07aff30cecb608fa61d54a6e6f5b99ef Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Mon, 25 Mar 2024 22:53:24 +0900 Subject: Add small RAM MCUs/boards to skip list --- examples/device/video_capture_2ch/skip.txt | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'examples') diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt index db64cc639..b36abf721 100644 --- a/examples/device/video_capture_2ch/skip.txt +++ b/examples/device/video_capture_2ch/skip.txt @@ -1,4 +1,13 @@ mcu:MSP430x5xx mcu:NUC121 mcu:SAMD11 +mcu:GD32VF103 +mcu:CH32V307 family:espressif +board:curiosity_nano +board:kuiic +board:frdm_k32l2b +board:lpcxpresso11u68 +board:stm32f303disco +board:stm32l412nucleo +board:ek_tm4c123gxl -- cgit v1.3.1 From 6a14dd190fa21d0632c956040fc0b2c0f41c676f Mon Sep 17 00:00:00 2001 From: kkitayam <45088311+kkitayam@users.noreply.github.com> Date: Mon, 25 Mar 2024 23:24:24 +0900 Subject: Fix compile errors when High Speed --- examples/device/video_capture_2ch/src/usb_descriptors.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/device/video_capture_2ch/src/usb_descriptors.c b/examples/device/video_capture_2ch/src/usb_descriptors.c index 0c1066416..e5798f7f2 100644 --- a/examples/device/video_capture_2ch/src/usb_descriptors.c +++ b/examples/device/video_capture_2ch/src/usb_descriptors.c @@ -558,7 +558,8 @@ static uint8_t * get_hs_configuration_desc(void) { desc_hs_configuration = desc_fs_configuration; // change endpoint bulk size to 512 if bulk streaming if (CFG_TUD_VIDEO_STREAMING_BULK) { - desc_hs_configuration.video_streaming.ep.wMaxPacketSize = 512; + desc_hs_configuration.uvc[0].video_streaming.ep.wMaxPacketSize = 512; + desc_hs_configuration.uvc[1].video_streaming.ep.wMaxPacketSize = 512; } } init = true; -- cgit v1.3.1 From 6cf27986b67996290c12f102d62c1a38e66e08d6 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 1 Apr 2024 19:55:51 +0200 Subject: UAC2: add interrupt volume control to uac2_headset example. --- examples/device/uac2_headset/src/main.c | 41 ++++++++++++++++++++++ examples/device/uac2_headset/src/tusb_config.h | 3 ++ examples/device/uac2_headset/src/usb_descriptors.c | 7 +++- examples/device/uac2_headset/src/usb_descriptors.h | 15 ++++---- 4 files changed, 59 insertions(+), 7 deletions(-) (limited to 'examples') diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 0ab72b2f3..35b7ac94b 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -96,6 +96,7 @@ uint8_t current_resolution; void led_blinking_task(void); void audio_task(void); +void audio_control_task(void); /*------------- MAIN -------------*/ int main(void) @@ -115,6 +116,7 @@ int main(void) { tud_task(); // TinyUSB device task audio_task(); + audio_control_task(); led_blinking_task(); } } @@ -428,6 +430,45 @@ void audio_task(void) } } +void audio_control_task(void) +{ + // Press on-board button to control volume + // Open host volume control, volume should switch between 10% and 100% + + // Poll every 50ms + const uint32_t interval_ms = 50; + static uint32_t start_ms = 0; + static uint32_t btn_prev = 0; + + if ( board_millis() - start_ms < interval_ms) return; // not enough time + start_ms += interval_ms; + + uint32_t btn = board_button_read(); + + if (!btn_prev && btn) + { + // Adjust volume between 0dB (100%) and -30dB (10%) + for (int i = 0; i < CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1; i++) + { + volume[i] = volume[i] == 0 ? -VOLUME_CTRL_30_DB : 0; + } + + // 6.1 Interrupt Data Message + const audio_interrupt_data_t data = { + .bInfo = 0, // Class-specific interrupt, originated from an interface + .bAttribute = AUDIO_CS_REQ_CUR, // Caused by current settings + .wValue_cn_or_mcn = 0, // CH0: master volume + .wValue_cs = AUDIO_FU_CTRL_VOLUME, // Volume change + .wIndex_ep_or_int = 0, // From the interface itself + .wIndex_entity_id = UAC2_ENTITY_SPK_FEATURE_UNIT, // From feature unit + }; + + tud_audio_int_write(&data); + } + + btn_prev = btn; +} + //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index b770483dc..4b08fa676 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -105,6 +105,9 @@ extern "C" { // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- +// Allow volume controlled by on-baord button +#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 1 + #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN // How many formats are used, need to adjust USB descriptor if changed diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index 6d1e6a23f..ff4dc2acc 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -82,27 +82,32 @@ uint8_t const * tud_descriptor_device_cb(void) // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... #define EPNUM_AUDIO_IN 0x03 #define EPNUM_AUDIO_OUT 0x03 + #define EPNUM_AUDIO_INT 0x01 #elif CFG_TUSB_MCU == OPT_MCU_NRF5X // ISO endpoints for NRF5x are fixed to 0x08 (0x88) #define EPNUM_AUDIO_IN 0x08 #define EPNUM_AUDIO_OUT 0x08 + #define EPNUM_AUDIO_INT 0x01 #elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_AUDIO_IN 0x01 #define EPNUM_AUDIO_OUT 0x02 + #define EPNUM_AUDIO_INT 0x03 #elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X // FT9XX doesn't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_AUDIO_IN 0x01 #define EPNUM_AUDIO_OUT 0x02 + #define EPNUM_AUDIO_INT 0x03 #else #define EPNUM_AUDIO_IN 0x01 #define EPNUM_AUDIO_OUT 0x01 + #define EPNUM_AUDIO_INT 0x02 #endif uint8_t const desc_configuration[] = @@ -111,7 +116,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80) + TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80, EPNUM_AUDIO_INT | 0x80) }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/examples/device/uac2_headset/src/usb_descriptors.h b/examples/device/uac2_headset/src/usb_descriptors.h index d7e170162..da0da83e8 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.h +++ b/examples/device/uac2_headset/src/usb_descriptors.h @@ -55,6 +55,7 @@ enum + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + TUD_AUDIO_DESC_INPUT_TERM_LEN\ + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO_DESC_STD_AC_INT_EP_LEN\ /* Interface 1, Alternate 0 */\ + TUD_AUDIO_DESC_STD_AS_INT_LEN\ /* Interface 1, Alternate 1 */\ @@ -84,11 +85,11 @@ enum + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) -#define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin) \ +#define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin, _epint) \ /* Standard Interface Association Descriptor (IAD) */\ TUD_AUDIO_DESC_IAD(/*_firstitf*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ ITF_NUM_TOTAL, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x01, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ @@ -103,6 +104,8 @@ enum TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ /* Output Terminal Descriptor(4.7.2.5) */\ TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + /* Standard AC Interrupt Endpoint Descriptor(4.8.2.1) */\ + TUD_AUDIO_DESC_STD_AC_INT_EP(/*_ep*/ _epint, /*_interval*/ 0x01), \ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x05),\ @@ -114,7 +117,7 @@ enum /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Interface 1, Alternate 2 - alternate interface for data streaming */\ @@ -124,7 +127,7 @@ enum /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Standard AS Interface Descriptor(4.9.1) */\ @@ -138,7 +141,7 @@ enum /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ /* Interface 2, Alternate 2 - alternate interface for data streaming */\ @@ -148,7 +151,7 @@ enum /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) -- cgit v1.3.1 From 594833374c812ccb8b7bac404b7bc7c0fbd56ccf Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Apr 2024 22:24:04 +0700 Subject: add new example to cmake include list --- examples/device/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'examples') diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt index 0a2e49ef0..c3671da69 100644 --- a/examples/device/CMakeLists.txt +++ b/examples/device/CMakeLists.txt @@ -28,4 +28,5 @@ family_add_subdirectory(net_lwip_webserver) family_add_subdirectory(uac2_headset) family_add_subdirectory(usbtmc) family_add_subdirectory(video_capture) +family_add_subdirectory(video_capture_2ch) family_add_subdirectory(webusb_serial) -- cgit v1.3.1 From 7910cc298187327e05c43770b58eac528a4fecfa Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Apr 2024 10:55:14 +0700 Subject: fix build with rp2040 + max3421 - forward MAX3421_HOST=1 from makefile to cmake - add feather_rp2040_max3421 board to run with ci for rp2040 + max3421 --- examples/build_system/make/make.mk | 1 + hw/bsp/rp2040/boards/feather_rp2040_max3421/board.cmake | 4 ++++ src/portable/analog/max3421/hcd_max3421.c | 13 ++++++------- 3 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 hw/bsp/rp2040/boards/feather_rp2040_max3421/board.cmake (limited to 'examples') diff --git a/examples/build_system/make/make.mk b/examples/build_system/make/make.mk index e1113aa52..772befca4 100644 --- a/examples/build_system/make/make.mk +++ b/examples/build_system/make/make.mk @@ -113,6 +113,7 @@ CFLAGS += -DBOARD_$(BOARD_UPPER) ifeq (${MAX3421_HOST},1) SRC_C += src/portable/analog/max3421/hcd_max3421.c CFLAGS += -DCFG_TUH_MAX3421=1 + CMAKE_DEFSYM += -DMAX3421_HOST=1 endif # Log level is mapped to TUSB DEBUG option diff --git a/hw/bsp/rp2040/boards/feather_rp2040_max3421/board.cmake b/hw/bsp/rp2040/boards/feather_rp2040_max3421/board.cmake new file mode 100644 index 000000000..b8e5890f3 --- /dev/null +++ b/hw/bsp/rp2040/boards/feather_rp2040_max3421/board.cmake @@ -0,0 +1,4 @@ +set(PICO_BOARD adafruit_feather_rp2040) + +# Enable MAX3421E USB Host +set(MAX3421_HOST 1) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 242c65501..76c1a150b 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -676,19 +676,18 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir); TU_VERIFY(ep); - // control transfer can switch direction - ep->hxfr_bm.is_out = ep_dir ? 0u : 1u; + if (ep_num == 0) { + // control transfer can switch direction + ep->hxfr_bm.is_out = ep_dir ? 0 : 1; + ep->hxfr_bm.is_setup = 0; + ep->data_toggle = 1; + } ep->buf = buffer; ep->total_len = buflen; ep->xferred_len = 0; ep->state = EP_STATE_ATTEMPT_1; - if (ep_num == 0) { - ep->hxfr_bm.is_setup = 0; - ep->data_toggle = 1; - } - // carry out transfer if not busy if (!atomic_flag_test_and_set(&_hcd_data.busy)) { xact_generic(rhport, ep, true, false); -- cgit v1.3.1 From f603c4a330f55158da7782671158fedabb62c29c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Apr 2024 13:01:16 +0700 Subject: skip cdc_msc_hid_freertos example for rp2040 --- examples/host/cdc_msc_hid_freertos/skip.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 examples/host/cdc_msc_hid_freertos/skip.txt (limited to 'examples') diff --git a/examples/host/cdc_msc_hid_freertos/skip.txt b/examples/host/cdc_msc_hid_freertos/skip.txt new file mode 100644 index 000000000..2ba4438fd --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/skip.txt @@ -0,0 +1 @@ +mcu:RP2040 -- cgit v1.3.1 From 34737f9c6061fdb05dfa3a9c4ddaf5f129b415d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Apr 2024 00:55:48 +0700 Subject: update uvc 2ch to stream0 use yuy2, stream1 use mpeg this help reduce sram requirement for example, also provide different format (uncompressed & mpeg) --- .../device/video_capture/src/usb_descriptors.c | 4 +- examples/device/video_capture_2ch/src/images.h | 16 +- examples/device/video_capture_2ch/src/main.c | 76 +-- .../device/video_capture_2ch/src/usb_descriptors.c | 711 ++++++++++----------- 4 files changed, 393 insertions(+), 414 deletions(-) (limited to 'examples') diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c index f308c75a7..5011bee18 100644 --- a/examples/device/video_capture/src/usb_descriptors.c +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -56,8 +56,8 @@ char const* string_desc_arr[] = { "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product NULL, // 3: Serials will use unique ID if possible - "TinyUSB UVC Control", // 4: UVC Interface - "TinyUSB UVC Streaming", // 5: UVC Interface + "UVC Control", // 4: UVC Interface + "UVC Streaming", // 5: UVC Interface }; //--------------------------------------------------------------------+ diff --git a/examples/device/video_capture_2ch/src/images.h b/examples/device/video_capture_2ch/src/images.h index ac372cb16..e5d69469e 100644 --- a/examples/device/video_capture_2ch/src/images.h +++ b/examples/device/video_capture_2ch/src/images.h @@ -1652,18 +1652,11 @@ static const unsigned char frame_buffer[128 * (96 + 1) * 2] = { 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, }; -#else +#endif -// mpeg compressed data (not CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) -#define color_bar_0_jpg_len 511 -#define color_bar_1_jpg_len 512 -#define color_bar_2_jpg_len 511 -#define color_bar_3_jpg_len 511 -#define color_bar_4_jpg_len 511 -#define color_bar_5_jpg_len 512 -#define color_bar_6_jpg_len 511 -#define color_bar_7_jpg_len 511 +#if 1 +// mpeg compressed data (not CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) unsigned char color_bar_0_jpg[] = { 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -1936,4 +1929,7 @@ unsigned char color_bar_7_jpg[] = { 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x47, 0xff, 0xd9 }; + + + #endif diff --git a/examples/device/video_capture_2ch/src/main.c b/examples/device/video_capture_2ch/src/main.c index 361f52b37..a373c2472 100644 --- a/examples/device/video_capture_2ch/src/main.c +++ b/examples/device/video_capture_2ch/src/main.c @@ -116,31 +116,27 @@ static unsigned frame_num[CFG_TUD_VIDEO_STREAMING] = {1}; static unsigned tx_busy = 0; static unsigned interval_ms[CFG_TUD_VIDEO_STREAMING] = {1000 / FRAME_RATE}; -#ifdef CFG_EXAMPLE_VIDEO_READONLY // For mcus that does not have enough SRAM for frame buffer, we use fixed frame data. // To further reduce the size, we use MJPEG format instead of YUY2. #include "images.h" -#if !defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) static struct { uint32_t size; uint8_t const *buffer; -} const frames[] = { - {color_bar_0_jpg_len, color_bar_0_jpg}, - {color_bar_1_jpg_len, color_bar_1_jpg}, - {color_bar_2_jpg_len, color_bar_2_jpg}, - {color_bar_3_jpg_len, color_bar_3_jpg}, - {color_bar_4_jpg_len, color_bar_4_jpg}, - {color_bar_5_jpg_len, color_bar_5_jpg}, - {color_bar_6_jpg_len, color_bar_6_jpg}, - {color_bar_7_jpg_len, color_bar_7_jpg}, +} const framebuf_mjpeg[] = { + {sizeof(color_bar_0_jpg), color_bar_0_jpg}, + {sizeof(color_bar_1_jpg), color_bar_1_jpg}, + {sizeof(color_bar_2_jpg), color_bar_2_jpg}, + {sizeof(color_bar_3_jpg), color_bar_3_jpg}, + {sizeof(color_bar_4_jpg), color_bar_4_jpg}, + {sizeof(color_bar_5_jpg), color_bar_5_jpg}, + {sizeof(color_bar_6_jpg), color_bar_6_jpg}, + {sizeof(color_bar_7_jpg), color_bar_7_jpg}, }; -#endif - -#else // YUY2 frame buffer -static uint8_t frame_buffer[2][FRAME_WIDTH * FRAME_HEIGHT * 16 / 8]; +#define FRAMEBUF_SIZE (FRAME_WIDTH * FRAME_HEIGHT * 16 / 8) +static uint8_t framebuf_yuy2[FRAMEBUF_SIZE]; static void fill_color_bar(uint8_t* buffer, unsigned start_position) { /* EBU color bars: https://stackoverflow.com/questions/6939422 */ @@ -179,7 +175,26 @@ static void fill_color_bar(uint8_t* buffer, unsigned start_position) { } } -#endif +size_t get_framebuf(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, size_t fnum, void **fb) { + uint32_t idx = ctl_idx + stm_idx; + + if (idx == 0) { + // stream 0 use uncompressed YUY2 frame + fill_color_bar(framebuf_yuy2, frame_num[idx]); + *fb = framebuf_yuy2; + return FRAMEBUF_SIZE; + }else { + // stream 1 use MJPEG frame + size_t const bar_id = fnum & 0x7; + + *fb = (void*)(uintptr_t) framebuf_mjpeg[bar_id].buffer; + return framebuf_mjpeg[bar_id].size; + } +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ void video_send_frame(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { static unsigned start_ms[CFG_TUD_VIDEO_STREAMING] = {0, }; @@ -191,22 +206,16 @@ void video_send_frame(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { frame_num[idx] = 0; return; } + void* fp; + size_t fb_size; if (!(already_sent & (1u << idx))) { already_sent |= 1u << idx; tx_busy |= 1u << idx; start_ms[idx] = board_millis(); -#ifdef CFG_EXAMPLE_VIDEO_READONLY - #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) - tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*)(uintptr_t)&frame_buffer[(frame_num[idx] % (FRAME_WIDTH / 2)) * 4], - FRAME_WIDTH * FRAME_HEIGHT * 16/8); - #else - tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*)(uintptr_t)frames[frame_num[idx] % 8].buffer, frames[frame_num[idx] % 8].size); - #endif -#else - fill_color_bar(frame_buffer[idx], frame_num[idx]); - tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*) frame_buffer[idx], FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); -#endif + + fb_size = get_framebuf(ctl_idx, stm_idx, frame_num[idx], &fp); + tud_video_n_frame_xfer(ctl_idx, stm_idx, fp, fb_size); } unsigned cur = board_millis(); @@ -215,17 +224,8 @@ void video_send_frame(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { start_ms[idx] += interval_ms[idx]; tx_busy |= 1u << idx; -#ifdef CFG_EXAMPLE_VIDEO_READONLY - #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) - tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*)(uintptr_t)&frame_buffer[(frame_num[idx] % (FRAME_WIDTH / 2)) * 4], - FRAME_WIDTH * FRAME_HEIGHT * 16/8); - #else - tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*)(uintptr_t)frames[frame_num[idx] % 8].buffer, frames[frame_num[idx] % 8].size); - #endif -#else - fill_color_bar(frame_buffer[idx], frame_num[idx]); - tud_video_n_frame_xfer(ctl_idx, stm_idx, (void*) frame_buffer[idx], FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); -#endif + fb_size = get_framebuf(ctl_idx, stm_idx, frame_num[idx], &fp); + tud_video_n_frame_xfer(ctl_idx, stm_idx, fp, fb_size); } diff --git a/examples/device/video_capture_2ch/src/usb_descriptors.c b/examples/device/video_capture_2ch/src/usb_descriptors.c index e5798f7f2..e78e452fc 100644 --- a/examples/device/video_capture_2ch/src/usb_descriptors.c +++ b/examples/device/video_capture_2ch/src/usb_descriptors.c @@ -55,13 +55,14 @@ enum { // array of pointer to string descriptors char const* string_desc_arr[] = { (const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - NULL, // 3: Serials will use unique ID if possible - "TinyUSB UVC Control 1", // 4: UVC Interface 1 - "TinyUSB UVC Streaming 1", // 5: UVC Interface 1 - "TinyUSB UVC Control 2", // 6: UVC Interface 2 - "TinyUSB UVC Streaming 2", // 7: UVC Interface 2 + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "UVC Control 1", // 4: UVC Interface 1 + "UVC Streaming 1", // 5: UVC Interface 1 + "UVC Control 2", // 6: UVC Interface 2 + "UVC Streaming 2", // 7: UVC Interface 2 + }; //--------------------------------------------------------------------+ @@ -140,15 +141,23 @@ typedef struct TU_ATTR_PACKED { typedef struct TU_ATTR_PACKED { tusb_desc_interface_t itf; tusb_desc_video_streaming_input_header_1byte_t header; - -#if USE_MJPEG - tusb_desc_video_format_mjpeg_t format; - tusb_desc_video_frame_mjpeg_continuous_t frame; -#else tusb_desc_video_format_uncompressed_t format; tusb_desc_video_frame_uncompressed_continuous_t frame; + tusb_desc_video_streaming_color_matching_t color; + +#if USE_ISO_STREAMING + // For ISO streaming, USB spec requires to alternate interface + tusb_desc_interface_t itf_alt; #endif + tusb_desc_endpoint_t ep; +} uvc_streaming_yuy2_desc_t; + +typedef struct TU_ATTR_PACKED { + tusb_desc_interface_t itf; + tusb_desc_video_streaming_input_header_1byte_t header; + tusb_desc_video_format_mjpeg_t format; + tusb_desc_video_frame_mjpeg_continuous_t frame; tusb_desc_video_streaming_color_matching_t color; #if USE_ISO_STREAMING @@ -157,15 +166,22 @@ typedef struct TU_ATTR_PACKED { #endif tusb_desc_endpoint_t ep; -} uvc_streaming_desc_t; +} uvc_streaming_mpeg_desc_t; typedef struct TU_ATTR_PACKED { tusb_desc_configuration_t config; + struct TU_ATTR_PACKED { tusb_desc_interface_assoc_t iad; uvc_control_desc_t video_control; - uvc_streaming_desc_t video_streaming; - } uvc[2]; + uvc_streaming_yuy2_desc_t video_streaming; + } uvc_yuy2; + + struct TU_ATTR_PACKED { + tusb_desc_interface_assoc_t iad; + uvc_control_desc_t video_control; + uvc_streaming_mpeg_desc_t video_streaming; + } uvc_mpeg; } uvc_cfg_desc_t; const uvc_cfg_desc_t desc_fs_configuration = { @@ -180,369 +196,336 @@ const uvc_cfg_desc_t desc_fs_configuration = { .bmAttributes = TU_BIT(7), .bMaxPower = 100 / 2 }, - .uvc = { - { - .iad = { - .bLength = sizeof(tusb_desc_interface_assoc_t), - .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, - - .bFirstInterface = ITF_NUM_VIDEO_CONTROL_1, - .bInterfaceCount = 2, - .bFunctionClass = TUSB_CLASS_VIDEO, - .bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION, - .bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED, - .iFunction = 0 + //------------- Stream 0: YUY2 -------------// + .uvc_yuy2 = { + .iad = { + .bLength = sizeof(tusb_desc_interface_assoc_t), + .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, + + .bFirstInterface = ITF_NUM_VIDEO_CONTROL_1, + .bInterfaceCount = 2, + .bFunctionClass = TUSB_CLASS_VIDEO, + .bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION, + .bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED, + .iFunction = 0 + }, + .video_control = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_CONTROL_1, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_CONTROL_1 + }, + .header = { + .bLength = sizeof(tusb_desc_video_control_header_1itf_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER, + + .bcdUVC = VIDEO_BCD_1_50, + .wTotalLength = sizeof(uvc_control_desc_t) - sizeof(tusb_desc_interface_t), // CS VC descriptors only + .dwClockFrequency = UVC_CLOCK_FREQUENCY, + .bInCollection = 1, + .baInterfaceNr = {ITF_NUM_VIDEO_STREAMING_1} + }, + .camera_terminal = { + .bLength = sizeof(tusb_desc_video_control_camera_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .wTerminalType = VIDEO_ITT_CAMERA, + .bAssocTerminal = 0, + .iTerminal = 0, + .wObjectiveFocalLengthMin = 0, + .wObjectiveFocalLengthMax = 0, + .wOcularFocalLength = 0, + .bControlSize = 3, + .bmControls = {0, 0, 0} }, + .output_terminal = { + .bLength = sizeof(tusb_desc_video_control_output_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .wTerminalType = VIDEO_TT_STREAMING, + .bAssocTerminal = 0, + .bSourceID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .iTerminal = 0 + } + }, - .video_control = { - .itf = { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - - .bInterfaceNumber = ITF_NUM_VIDEO_CONTROL_1, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = TUSB_CLASS_VIDEO, - .bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL, - .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, - .iInterface = STRID_UVC_CONTROL_1 - }, - .header = { - .bLength = sizeof(tusb_desc_video_control_header_1itf_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER, - - .bcdUVC = VIDEO_BCD_1_50, - .wTotalLength = sizeof(uvc_control_desc_t) - sizeof(tusb_desc_interface_t), // CS VC descriptors only - .dwClockFrequency = UVC_CLOCK_FREQUENCY, - .bInCollection = 1, - .baInterfaceNr = { ITF_NUM_VIDEO_STREAMING_1 } - }, - .camera_terminal = { - .bLength = sizeof(tusb_desc_video_control_camera_terminal_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL, - - .bTerminalID = UVC_ENTITY_CAP_INPUT_TERMINAL, - .wTerminalType = VIDEO_ITT_CAMERA, - .bAssocTerminal = 0, - .iTerminal = 0, - .wObjectiveFocalLengthMin = 0, - .wObjectiveFocalLengthMax = 0, - .wOcularFocalLength = 0, - .bControlSize = 3, - .bmControls = { 0, 0, 0 } - }, - .output_terminal = { - .bLength = sizeof(tusb_desc_video_control_output_terminal_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, - - .bTerminalID = UVC_ENTITY_CAP_OUTPUT_TERMINAL, - .wTerminalType = VIDEO_TT_STREAMING, - .bAssocTerminal = 0, - .bSourceID = UVC_ENTITY_CAP_INPUT_TERMINAL, - .iTerminal = 0 + .video_streaming = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_1, + .bAlternateSetting = 0, + .bNumEndpoints = CFG_TUD_VIDEO_STREAMING_BULK, // bulk 1, iso 0 + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_1 + }, + .header = { + .bLength = sizeof(tusb_desc_video_streaming_input_header_1byte_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, + + .bNumFormats = 1, + .wTotalLength = sizeof(uvc_streaming_yuy2_desc_t) - sizeof(tusb_desc_interface_t) + - sizeof(tusb_desc_endpoint_t) - + (USE_ISO_STREAMING ? sizeof(tusb_desc_interface_t) : 0), // CS VS descriptors only + .bEndpointAddress = EPNUM_VIDEO_IN_1, + .bmInfo = 0, + .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .bStillCaptureMethod = 0, + .bTriggerSupport = 0, + .bTriggerUsage = 0, + .bControlSize = 1, + .bmaControls = {0} + }, + .format = { + .bLength = sizeof(tusb_desc_video_format_uncompressed_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .guidFormat = {TUD_VIDEO_GUID_YUY2}, + .bBitsPerPixel = 16, + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, + .bAspectRatioY = 0, + .bmInterlaceFlags = 0, + .bCopyProtect = 0 + }, + .frame = { + .bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, + .bFrameIndex = 1, // 1-based index + .bmCapabilities = 0, + .wWidth = FRAME_WIDTH, + .wHeight = FRAME_HEIGHT, + .dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1, + .dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE, + .dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8, + .dwDefaultFrameInterval = 10000000 / FRAME_RATE, + .bFrameIntervalType = 0, // continuous + .dwFrameInterval = { + 10000000 / FRAME_RATE, // min + 10000000, // max + 10000000 / FRAME_RATE // step } }, - - .video_streaming = { - .itf = { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - - .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_1, - .bAlternateSetting = 0, - .bNumEndpoints = CFG_TUD_VIDEO_STREAMING_BULK, // bulk 1, iso 0 - .bInterfaceClass = TUSB_CLASS_VIDEO, - .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, - .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, - .iInterface = STRID_UVC_STREAMING_1 - }, - .header = { - .bLength = sizeof(tusb_desc_video_streaming_input_header_1byte_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, - - .bNumFormats = 1, - .wTotalLength = sizeof(uvc_streaming_desc_t) - sizeof(tusb_desc_interface_t) - - sizeof(tusb_desc_endpoint_t) - (USE_ISO_STREAMING ? sizeof(tusb_desc_interface_t) : 0) , // CS VS descriptors only - .bEndpointAddress = EPNUM_VIDEO_IN_1, - .bmInfo = 0, - .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, - .bStillCaptureMethod = 0, - .bTriggerSupport = 0, - .bTriggerUsage = 0, - .bControlSize = 1, - .bmaControls = { 0 } - }, - .format = { -#if USE_MJPEG - .bLength = sizeof(tusb_desc_video_format_mjpeg_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_MJPEG, - .bFormatIndex = 1, // 1-based index - .bNumFrameDescriptors = 1, - .bmFlags = 0, -#else - .bLength = sizeof(tusb_desc_video_format_uncompressed_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, - .bFormatIndex = 1, // 1-based index - .bNumFrameDescriptors = 1, - .guidFormat = { TUD_VIDEO_GUID_YUY2 }, - .bBitsPerPixel = 16, -#endif - .bDefaultFrameIndex = 1, - .bAspectRatioX = 0, - .bAspectRatioY = 0, - .bmInterlaceFlags = 0, - .bCopyProtect = 0 - }, - .frame = { -#if USE_MJPEG - .bLength = sizeof(tusb_desc_video_frame_mjpeg_continuous_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_MJPEG, -#else - .bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, -#endif - .bFrameIndex = 1, // 1-based index - .bmCapabilities = 0, - .wWidth = FRAME_WIDTH, - .wHeight = FRAME_HEIGHT, - .dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1, - .dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE, - .dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8, - .dwDefaultFrameInterval = 10000000 / FRAME_RATE, - .bFrameIntervalType = 0, // continuous - .dwFrameInterval = { - 10000000 / FRAME_RATE, // min - 10000000, // max - 10000000 / FRAME_RATE // step - } - }, - .color = { - .bLength = sizeof(tusb_desc_video_streaming_color_matching_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT, - - .bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709, - .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, - .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M - }, + .color = { + .bLength = sizeof(tusb_desc_video_streaming_color_matching_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT, + + .bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709, + .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, + .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M + }, #if USE_ISO_STREAMING - .itf_alt = { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - - .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_1, - .bAlternateSetting = 1, - .bNumEndpoints = 1, - .bInterfaceClass = TUSB_CLASS_VIDEO, - .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, - .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, - .iInterface = STRID_UVC_STREAMING_1 - }, + .itf_alt = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_1, + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_1 + }, #endif - - .ep = { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - - .bEndpointAddress = EPNUM_VIDEO_IN_1, - .bmAttributes = { - .xfer = CFG_TUD_VIDEO_STREAMING_BULK ? TUSB_XFER_BULK : TUSB_XFER_ISOCHRONOUS, - .sync = CFG_TUD_VIDEO_STREAMING_BULK ? 0 : 1 // asynchronous - }, - .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, - .bInterval = 1 - } + .ep = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = EPNUM_VIDEO_IN_1, + .bmAttributes = { + .xfer = CFG_TUD_VIDEO_STREAMING_BULK ? TUSB_XFER_BULK : TUSB_XFER_ISOCHRONOUS, + .sync = CFG_TUD_VIDEO_STREAMING_BULK ? 0 : 1 // asynchronous + }, + .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, + .bInterval = 1 } + } + }, + //------------- Stream 1: MPEG -------------// + .uvc_mpeg = { + .iad = { + .bLength = sizeof(tusb_desc_interface_assoc_t), + .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, + + .bFirstInterface = ITF_NUM_VIDEO_CONTROL_2, + .bInterfaceCount = 2, + .bFunctionClass = TUSB_CLASS_VIDEO, + .bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION, + .bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED, + .iFunction = 0 }, - { - .iad = { - .bLength = sizeof(tusb_desc_interface_assoc_t), - .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, - - .bFirstInterface = ITF_NUM_VIDEO_CONTROL_2, - .bInterfaceCount = 2, - .bFunctionClass = TUSB_CLASS_VIDEO, - .bFunctionSubClass = VIDEO_SUBCLASS_INTERFACE_COLLECTION, - .bFunctionProtocol = VIDEO_ITF_PROTOCOL_UNDEFINED, - .iFunction = 0 + + .video_control = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_CONTROL_2, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_CONTROL_2 + }, + .header = { + .bLength = sizeof(tusb_desc_video_control_header_1itf_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER, + + .bcdUVC = VIDEO_BCD_1_50, + .wTotalLength = sizeof(uvc_control_desc_t) - sizeof(tusb_desc_interface_t), // CS VC descriptors only + .dwClockFrequency = UVC_CLOCK_FREQUENCY, + .bInCollection = 1, + .baInterfaceNr = { ITF_NUM_VIDEO_STREAMING_2 } + }, + .camera_terminal = { + .bLength = sizeof(tusb_desc_video_control_camera_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .wTerminalType = VIDEO_ITT_CAMERA, + .bAssocTerminal = 0, + .iTerminal = 0, + .wObjectiveFocalLengthMin = 0, + .wObjectiveFocalLengthMax = 0, + .wOcularFocalLength = 0, + .bControlSize = 3, + .bmControls = { 0, 0, 0 } }, + .output_terminal = { + .bLength = sizeof(tusb_desc_video_control_output_terminal_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, + + .bTerminalID = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .wTerminalType = VIDEO_TT_STREAMING, + .bAssocTerminal = 0, + .bSourceID = UVC_ENTITY_CAP_INPUT_TERMINAL, + .iTerminal = 0 + } + }, - .video_control = { - .itf = { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - - .bInterfaceNumber = ITF_NUM_VIDEO_CONTROL_2, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = TUSB_CLASS_VIDEO, - .bInterfaceSubClass = VIDEO_SUBCLASS_CONTROL, - .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, - .iInterface = STRID_UVC_CONTROL_2 - }, - .header = { - .bLength = sizeof(tusb_desc_video_control_header_1itf_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VC_HEADER, - - .bcdUVC = VIDEO_BCD_1_50, - .wTotalLength = sizeof(uvc_control_desc_t) - sizeof(tusb_desc_interface_t), // CS VC descriptors only - .dwClockFrequency = UVC_CLOCK_FREQUENCY, - .bInCollection = 1, - .baInterfaceNr = { ITF_NUM_VIDEO_STREAMING_2 } - }, - .camera_terminal = { - .bLength = sizeof(tusb_desc_video_control_camera_terminal_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL, - - .bTerminalID = UVC_ENTITY_CAP_INPUT_TERMINAL, - .wTerminalType = VIDEO_ITT_CAMERA, - .bAssocTerminal = 0, - .iTerminal = 0, - .wObjectiveFocalLengthMin = 0, - .wObjectiveFocalLengthMax = 0, - .wOcularFocalLength = 0, - .bControlSize = 3, - .bmControls = { 0, 0, 0 } - }, - .output_terminal = { - .bLength = sizeof(tusb_desc_video_control_output_terminal_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL, - - .bTerminalID = UVC_ENTITY_CAP_OUTPUT_TERMINAL, - .wTerminalType = VIDEO_TT_STREAMING, - .bAssocTerminal = 0, - .bSourceID = UVC_ENTITY_CAP_INPUT_TERMINAL, - .iTerminal = 0 + .video_streaming = { + .itf = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_2, + .bAlternateSetting = 0, + .bNumEndpoints = CFG_TUD_VIDEO_STREAMING_BULK, // bulk 1, iso 0 + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_2 + }, + .header = { + .bLength = sizeof(tusb_desc_video_streaming_input_header_1byte_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, + + .bNumFormats = 1, + .wTotalLength = sizeof(uvc_streaming_mpeg_desc_t) - sizeof(tusb_desc_interface_t) + - sizeof(tusb_desc_endpoint_t) - (USE_ISO_STREAMING ? sizeof(tusb_desc_interface_t) : 0) , // CS VS descriptors only + .bEndpointAddress = EPNUM_VIDEO_IN_2, + .bmInfo = 0, + .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, + .bStillCaptureMethod = 0, + .bTriggerSupport = 0, + .bTriggerUsage = 0, + .bControlSize = 1, + .bmaControls = { 0 } + }, + .format = { + .bLength = sizeof(tusb_desc_video_format_mjpeg_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_MJPEG, + .bFormatIndex = 1, // 1-based index + .bNumFrameDescriptors = 1, + .bmFlags = 0, + .bDefaultFrameIndex = 1, + .bAspectRatioX = 0, + .bAspectRatioY = 0, + .bmInterlaceFlags = 0, + .bCopyProtect = 0 + }, + .frame = { + .bLength = sizeof(tusb_desc_video_frame_mjpeg_continuous_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_MJPEG, + .bFrameIndex = 1, // 1-based index + .bmCapabilities = 0, + .wWidth = FRAME_WIDTH, + .wHeight = FRAME_HEIGHT, + .dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1, + .dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE, + .dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8, + .dwDefaultFrameInterval = 10000000 / FRAME_RATE, + .bFrameIntervalType = 0, // continuous + .dwFrameInterval = { + 10000000 / FRAME_RATE, // min + 10000000, // max + 10000000 / FRAME_RATE // step } }, - - .video_streaming = { - .itf = { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - - .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_2, - .bAlternateSetting = 0, - .bNumEndpoints = CFG_TUD_VIDEO_STREAMING_BULK, // bulk 1, iso 0 - .bInterfaceClass = TUSB_CLASS_VIDEO, - .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, - .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, - .iInterface = STRID_UVC_STREAMING_2 - }, - .header = { - .bLength = sizeof(tusb_desc_video_streaming_input_header_1byte_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_INPUT_HEADER, - - .bNumFormats = 1, - .wTotalLength = sizeof(uvc_streaming_desc_t) - sizeof(tusb_desc_interface_t) - - sizeof(tusb_desc_endpoint_t) - (USE_ISO_STREAMING ? sizeof(tusb_desc_interface_t) : 0) , // CS VS descriptors only - .bEndpointAddress = EPNUM_VIDEO_IN_2, - .bmInfo = 0, - .bTerminalLink = UVC_ENTITY_CAP_OUTPUT_TERMINAL, - .bStillCaptureMethod = 0, - .bTriggerSupport = 0, - .bTriggerUsage = 0, - .bControlSize = 1, - .bmaControls = { 0 } - }, - .format = { -#if USE_MJPEG - .bLength = sizeof(tusb_desc_video_format_mjpeg_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_MJPEG, - .bFormatIndex = 1, // 1-based index - .bNumFrameDescriptors = 1, - .bmFlags = 0, -#else - .bLength = sizeof(tusb_desc_video_format_uncompressed_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED, - .bFormatIndex = 1, // 1-based index - .bNumFrameDescriptors = 1, - .guidFormat = { TUD_VIDEO_GUID_YUY2 }, - .bBitsPerPixel = 16, -#endif - .bDefaultFrameIndex = 1, - .bAspectRatioX = 0, - .bAspectRatioY = 0, - .bmInterlaceFlags = 0, - .bCopyProtect = 0 - }, - .frame = { -#if USE_MJPEG - .bLength = sizeof(tusb_desc_video_frame_mjpeg_continuous_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_MJPEG, -#else - .bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED, -#endif - .bFrameIndex = 1, // 1-based index - .bmCapabilities = 0, - .wWidth = FRAME_WIDTH, - .wHeight = FRAME_HEIGHT, - .dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1, - .dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE, - .dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8, - .dwDefaultFrameInterval = 10000000 / FRAME_RATE, - .bFrameIntervalType = 0, // continuous - .dwFrameInterval = { - 10000000 / FRAME_RATE, // min - 10000000, // max - 10000000 / FRAME_RATE // step - } - }, - .color = { - .bLength = sizeof(tusb_desc_video_streaming_color_matching_t), - .bDescriptorType = TUSB_DESC_CS_INTERFACE, - .bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT, - - .bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709, - .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, - .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M - }, + .color = { + .bLength = sizeof(tusb_desc_video_streaming_color_matching_t), + .bDescriptorType = TUSB_DESC_CS_INTERFACE, + .bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT, + + .bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709, + .bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709, + .bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M + }, #if USE_ISO_STREAMING - .itf_alt = { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - - .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_2, - .bAlternateSetting = 1, - .bNumEndpoints = 1, - .bInterfaceClass = TUSB_CLASS_VIDEO, - .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, - .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, - .iInterface = STRID_UVC_STREAMING_2 - }, + .itf_alt = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + + .bInterfaceNumber = ITF_NUM_VIDEO_STREAMING_2, + .bAlternateSetting = 1, + .bNumEndpoints = 1, + .bInterfaceClass = TUSB_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SUBCLASS_STREAMING, + .bInterfaceProtocol = VIDEO_ITF_PROTOCOL_15, + .iInterface = STRID_UVC_STREAMING_2 + }, #endif - - .ep = { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - - .bEndpointAddress = EPNUM_VIDEO_IN_2, - .bmAttributes = { - .xfer = CFG_TUD_VIDEO_STREAMING_BULK ? TUSB_XFER_BULK : TUSB_XFER_ISOCHRONOUS, - .sync = CFG_TUD_VIDEO_STREAMING_BULK ? 0 : 1 // asynchronous - }, - .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, - .bInterval = 1 - } + .ep = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + + .bEndpointAddress = EPNUM_VIDEO_IN_2, + .bmAttributes = { + .xfer = CFG_TUD_VIDEO_STREAMING_BULK ? TUSB_XFER_BULK : TUSB_XFER_ISOCHRONOUS, + .sync = CFG_TUD_VIDEO_STREAMING_BULK ? 0 : 1 // asynchronous + }, + .wMaxPacketSize = CFG_TUD_VIDEO_STREAMING_BULK ? 64 : CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE, + .bInterval = 1 } } } @@ -558,8 +541,8 @@ static uint8_t * get_hs_configuration_desc(void) { desc_hs_configuration = desc_fs_configuration; // change endpoint bulk size to 512 if bulk streaming if (CFG_TUD_VIDEO_STREAMING_BULK) { - desc_hs_configuration.uvc[0].video_streaming.ep.wMaxPacketSize = 512; - desc_hs_configuration.uvc[1].video_streaming.ep.wMaxPacketSize = 512; + desc_hs_configuration.uvc_yuy2.video_streaming.ep.wMaxPacketSize = 512; + desc_hs_configuration.uvc_mpeg.video_streaming.ep.wMaxPacketSize = 512; } } init = true; -- cgit v1.3.1 From 5b2441d8a3cae01de522d28cbac378464d3df678 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Apr 2024 16:12:31 +0700 Subject: support CFG_EXAMPLE_VIDEO_READONLY for stream0 for small mcu --- examples/device/video_capture_2ch/src/images.h | 17 ++++++++--------- examples/device/video_capture_2ch/src/main.c | 10 +++++++++- 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'examples') diff --git a/examples/device/video_capture_2ch/src/images.h b/examples/device/video_capture_2ch/src/images.h index e5d69469e..f0badd074 100644 --- a/examples/device/video_capture_2ch/src/images.h +++ b/examples/device/video_capture_2ch/src/images.h @@ -1,6 +1,8 @@ -#if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) -// uncopmressed frame -static const unsigned char frame_buffer[128 * (96 + 1) * 2] = { +#if defined(CFG_EXAMPLE_VIDEO_READONLY) +//--------------------------------------------------------------------+ +// YUY2 Uncompressed Frame (fixed) +//--------------------------------------------------------------------+ +static const unsigned char framebuf_yuy2_readonly[128 * (96 + 1) * 2] = { /* 0 */ 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, 0xeb, 0x80, @@ -1654,9 +1656,10 @@ static const unsigned char frame_buffer[128 * (96 + 1) * 2] = { #endif -#if 1 +//--------------------------------------------------------------------+ +// MPEG Compressed Frame (fixed) +//--------------------------------------------------------------------+ -// mpeg compressed data (not CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) unsigned char color_bar_0_jpg[] = { 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -1929,7 +1932,3 @@ unsigned char color_bar_7_jpg[] = { 0x42, 0x51, 0x59, 0x8c, 0xb1, 0x45, 0x00, 0x25, 0x15, 0x98, 0xc4, 0xa2, 0xb5, 0x32, 0x12, 0x8a, 0xcc, 0x63, 0x68, 0xad, 0x8d, 0x84, 0xa2, 0xb3, 0x18, 0x94, 0x56, 0xa6, 0x47, 0xff, 0xd9 }; - - - -#endif diff --git a/examples/device/video_capture_2ch/src/main.c b/examples/device/video_capture_2ch/src/main.c index a373c2472..82bc7d6ca 100644 --- a/examples/device/video_capture_2ch/src/main.c +++ b/examples/device/video_capture_2ch/src/main.c @@ -112,6 +112,8 @@ void tud_resume_cb(void) { //--------------------------------------------------------------------+ // USB Video //--------------------------------------------------------------------+ +#define FRAMEBUF_SIZE (FRAME_WIDTH * FRAME_HEIGHT * 16 / 8) + static unsigned frame_num[CFG_TUD_VIDEO_STREAMING] = {1}; static unsigned tx_busy = 0; static unsigned interval_ms[CFG_TUD_VIDEO_STREAMING] = {1000 / FRAME_RATE}; @@ -134,8 +136,8 @@ static struct { {sizeof(color_bar_7_jpg), color_bar_7_jpg}, }; +#if !defined(CFG_EXAMPLE_VIDEO_READONLY) // YUY2 frame buffer -#define FRAMEBUF_SIZE (FRAME_WIDTH * FRAME_HEIGHT * 16 / 8) static uint8_t framebuf_yuy2[FRAMEBUF_SIZE]; static void fill_color_bar(uint8_t* buffer, unsigned start_position) { @@ -174,14 +176,20 @@ static void fill_color_bar(uint8_t* buffer, unsigned start_position) { p += FRAME_WIDTH * 2; } } +#endif size_t get_framebuf(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, size_t fnum, void **fb) { uint32_t idx = ctl_idx + stm_idx; if (idx == 0) { // stream 0 use uncompressed YUY2 frame + #if defined(CFG_EXAMPLE_VIDEO_READONLY) + *fb = (void*)(uintptr_t ) framebuf_yuy2_readonly[(fnum % (FRAME_WIDTH / 2)) * 4]; + #else fill_color_bar(framebuf_yuy2, frame_num[idx]); *fb = framebuf_yuy2; + #endif + return FRAMEBUF_SIZE; }else { // stream 1 use MJPEG frame -- cgit v1.3.1 From caf2c5e0b75b72c0b0357ca364a76d70b5846bde Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Apr 2024 17:04:33 +0700 Subject: reverted un-related file changes --- examples/device/cdc_msc_freertos/src/main.c | 51 ++++++++++++---------- hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk | 3 -- hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/board.mk | 3 -- hw/bsp/nrf/boards/pca10095/board.h | 4 +- hw/bsp/nrf/boards/pca10095/board.mk | 3 ++ hw/bsp/nrf/family.c | 1 + src/class/msc/msc_device.c | 2 +- src/class/video/video.h | 6 ++- src/common/tusb_debug.h | 3 +- src/common/tusb_fifo.c | 1 + src/host/usbh_pvt.h | 6 ++- src/portable/nordic/nrf5x/dcd_nrf5x.c | 8 +++- src/portable/ohci/ohci.h | 2 +- 13 files changed, 54 insertions(+), 39 deletions(-) (limited to 'examples') diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 1dadc4513..e94e8eaec 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -52,7 +52,8 @@ #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) #endif -#define CDC_STACK_SZIE configMINIMAL_STACK_SIZE +#define CDC_STACK_SIZE configMINIMAL_STACK_SIZE +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPES @@ -69,21 +70,22 @@ enum { BLINK_SUSPENDED = 2500, }; -// static timer & task +// static task #if configSUPPORT_STATIC_ALLOCATION -StaticTimer_t blinky_tmdef; +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; -StackType_t cdc_stack[CDC_STACK_SZIE]; +StackType_t cdc_stack[CDC_STACK_SIZE]; StaticTask_t cdc_taskdef; #endif -TimerHandle_t blinky_tm; +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; -static void led_blinky_cb(TimerHandle_t xTimer); static void usb_device_task(void *param); +void led_blinking_task(void* param); void cdc_task(void *params); //--------------------------------------------------------------------+ @@ -94,22 +96,20 @@ 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); + // blinky task + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); // Create a task for tinyusb device stack xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); // Create CDC task - xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); + xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SIZE, 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(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); 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) vTaskStartScheduler(); @@ -154,12 +154,12 @@ static void usb_device_task(void *param) { // Invoked when device is mounted void tud_mount_cb(void) { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); + blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted void tud_umount_cb(void) { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); + blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended @@ -167,16 +167,12 @@ void tud_umount_cb(void) { // Within 7ms, device must draw an average of current less than 2.5 mA from bus void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0); + blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed void tud_resume_cb(void) { - if (tud_mounted()) { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); - } else { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); - } + blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } //--------------------------------------------------------------------+ @@ -235,10 +231,17 @@ void tud_cdc_rx_cb(uint8_t itf) { //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -static void led_blinky_cb(TimerHandle_t xTimer) { - (void) xTimer; +void led_blinking_task(void* param) { + (void) param; + static uint32_t start_ms = 0; static bool led_state = false; - board_led_write(led_state); - led_state = 1 - led_state; // toggle + while (1) { + // Blink every interval ms + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } } diff --git a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk index f69700139..c4dc65b63 100644 --- a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk +++ b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk @@ -8,9 +8,6 @@ CFLAGS += -Wno-error=unused-parameter -Wno-error=redundant-decls -Wno-error=cast # All source paths should be relative to the top level. LD_FILE = $(MCU_DIR)/gcc/K32L2A41xxxxA_flash.ld -SRC_C += \ - $(MCU_DIR)/project_template/clock_config.c \ - # For flash-jlink target JLINK_DEVICE = K32L2A41xxxxA diff --git a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/board.mk b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/board.mk index 82456b721..9cf36c500 100644 --- a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/board.mk +++ b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2b/board.mk @@ -8,9 +8,6 @@ CFLAGS += -Wno-error=unused-parameter -Wno-error=redundant-decls # All source paths should be relative to the top level. LD_FILE = $(MCU_DIR)/gcc/K32L2B31xxxxA_flash.ld -SRC_C += \ - $(MCU_DIR)/project_template/clock_config.c \ - # For flash-jlink target JLINK_DEVICE = K32L2B31xxxxA diff --git a/hw/bsp/nrf/boards/pca10095/board.h b/hw/bsp/nrf/boards/pca10095/board.h index 2a46e5422..846c2ee5b 100644 --- a/hw/bsp/nrf/boards/pca10095/board.h +++ b/hw/bsp/nrf/boards/pca10095/board.h @@ -42,8 +42,8 @@ #define BUTTON_STATE_ACTIVE 0 // UART -#define UART_RX_PIN 32 -#define UART_TX_PIN 33 +#define UART_RX_PIN 22 +#define UART_TX_PIN 20 // SPI for USB host shield // Pin is correct but not working probably due to signal incompatible (1.8V 3v3) with MAC3421E !? diff --git a/hw/bsp/nrf/boards/pca10095/board.mk b/hw/bsp/nrf/boards/pca10095/board.mk index 9c4edbafc..20580d619 100644 --- a/hw/bsp/nrf/boards/pca10095/board.mk +++ b/hw/bsp/nrf/boards/pca10095/board.mk @@ -2,6 +2,9 @@ CPU_CORE = cortex-m33 MCU_VARIANT = nrf5340_application CFLAGS += -DNRF5340_XXAA -DNRF5340_XXAA_APPLICATION +# enable max3421 host driver for this board +MAX3421_HOST = 1 + LD_FILE = hw/mcu/nordic/nrfx/mdk/nrf5340_xxaa_application.ld SRC_C += hw/mcu/nordic/nrfx/drivers/src/nrfx_usbreg.c diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index d6bb2d868..71c651f5f 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -76,6 +76,7 @@ enum { #define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_LFRC #define VBUSDETECT_Msk USBREG_USBREGSTATUS_VBUSDETECT_Msk #define OUTPUTRDY_Msk USBREG_USBREGSTATUS_OUTPUTRDY_Msk + #define GPIOTE_IRQn GPIOTE1_IRQn #else #define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_RC #define VBUSDETECT_Msk POWER_USBREGSTATUS_VBUSDETECT_Msk diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 2589dcd2c..c145d86a6 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -203,7 +203,7 @@ uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= 2 +#if CFG_TUSB_DEBUG >= CFG_TUD_MSC_LOG_LEVEL TU_ATTR_UNUSED tu_static tu_lookup_entry_t const _msc_scsi_cmd_lookup[] = { diff --git a/src/class/video/video.h b/src/class/video/video.h index 3b511af96..b8a9b6369 100644 --- a/src/class/video/video.h +++ b/src/class/video/video.h @@ -369,6 +369,8 @@ typedef struct TU_ATTR_PACKED { uint8_t bCopyProtect; } tusb_desc_video_format_uncompressed_t; +TU_VERIFY_STATIC(sizeof(tusb_desc_video_format_uncompressed_t) == 27, "size is not correct"); + // Uncompressed payload specs: 3.1.2 frame descriptor #define tusb_desc_video_frame_uncompressed_nint_t(_nint) \ struct TU_ATTR_PACKED { \ @@ -382,7 +384,7 @@ typedef struct TU_ATTR_PACKED { uint32_t dwMinBitRate; \ uint32_t dwMaxBitRate; \ uint32_t dwMaxVideoFrameBufferSize; /* deprecated in 1.5 */ \ - uint32_t dwDefaultFrameInterval; \ + uint32_t dwDefaultFrameInterval; /* 100ns unit */\ uint8_t bFrameIntervalType; \ uint32_t dwFrameInterval[_nint]; \ } @@ -414,6 +416,8 @@ typedef struct TU_ATTR_PACKED { uint8_t bCopyProtect; } tusb_desc_video_format_mjpeg_t; +TU_VERIFY_STATIC(sizeof(tusb_desc_video_format_mjpeg_t) == 11, "size is not correct"); + // MJPEG payload specs: 3.1.2 frame descriptor (same as uncompressed) typedef tusb_desc_video_frame_uncompressed_t tusb_desc_video_frame_mjpeg_t; typedef tusb_desc_video_frame_uncompressed_1int_t tusb_desc_video_frame_mjpeg_1int_t; diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index 0f4dc93f3..2e9f1d9cd 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -60,6 +60,7 @@ void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); static inline void tu_print_buf(uint8_t const* buf, uint32_t bufsize) { for(uint32_t i=0; i= 2 diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index d6c3db4ce..76696396b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -224,6 +224,7 @@ static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t if (wrap_bytes > 0) _ff_push_const_addr(ff_buf, app_buf, wrap_bytes); } break; + default: break; } } diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index 46d13a907..95de915e9 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -35,7 +35,11 @@ extern "C" { #endif -#define TU_LOG_USBH(...) TU_LOG(CFG_TUH_LOG_LEVEL, __VA_ARGS__) +#define TU_LOG_USBH(...) TU_LOG(CFG_TUH_LOG_LEVEL, __VA_ARGS__) +#define TU_LOG_MEM_USBH(...) TU_LOG_MEM(CFG_TUH_LOG_LEVEL, __VA_ARGS__) +#define TU_LOG_BUF_USBH(...) TU_LOG_BUF(CFG_TUH_LOG_LEVEL, __VA_ARGS__) +#define TU_LOG_INT_USBH(...) TU_LOG_INT(CFG_TUH_LOG_LEVEL, __VA_ARGS__) +#define TU_LOG_HEX_USBH(...) TU_LOG_HEX(CFG_TUH_LOG_LEVEL, __VA_ARGS__) enum { USBH_EPSIZE_BULK_MAX = (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index cf9e5923b..80a285ef0 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -653,7 +653,11 @@ void dcd_int_handler(uint8_t rhport) if (NRF_USBD->EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk) { iso_enabled = true; - xact_out_dma(EP_ISO_NUM); + // Transfer from endpoint to RAM only if data is not corrupted + if ((int_status & USBD_INTEN_USBEVENT_Msk) == 0 || + (NRF_USBD->EVENTCAUSE & USBD_EVENTCAUSE_ISOOUTCRC_Msk) == 0) { + xact_out_dma(EP_ISO_NUM); + } } // ISOIN: Notify client that data was transferred @@ -683,7 +687,7 @@ void dcd_int_handler(uint8_t rhport) { TU_LOG(3, "EVENTCAUSE = 0x%04lX\r\n", NRF_USBD->EVENTCAUSE); - enum { EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk }; + enum { EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk | USBD_EVENTCAUSE_ISOOUTCRC_Msk }; uint32_t const evt_cause = NRF_USBD->EVENTCAUSE & EVT_CAUSE_MASK; NRF_USBD->EVENTCAUSE = evt_cause; // clear interrupt diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 4feefd771..94bad5df7 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -83,7 +83,7 @@ typedef struct TU_ATTR_ALIGNED(16) volatile uint32_t condition_code : 4; // Word 1 - volatile uint8_t* current_buffer_pointer; + uint8_t* volatile current_buffer_pointer; // Word 2 : next TD volatile uint32_t next; -- cgit v1.3.1 From 5ce458588498090204cdc7c3977c0fd48e00d710 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Apr 2024 17:14:51 +0700 Subject: fix pre-commit format --- examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk | 2 +- hw/bsp/mcx/boards/frdmmcxa153/board.mk | 2 +- hw/bsp/mcx/boards/frdmmcxa153/clock_config.h | 2 +- hw/bsp/mcx/boards/frdmmcxa153/pin_mux.c | 2 +- hw/bsp/mcx/family.c | 2 +- hw/bsp/mcx/family.cmake | 6 +++--- hw/bsp/mcx/family.mk | 4 ++-- src/portable/chipidea/ci_fs/ci_fs_mcx.h | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) (limited to 'examples') diff --git a/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk index f74f46d54..c65f24376 100644 --- a/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk +++ b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk @@ -13,4 +13,4 @@ else ifeq ($(TOOLCHAIN),iar) endif -FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure \ No newline at end of file +FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure diff --git a/hw/bsp/mcx/boards/frdmmcxa153/board.mk b/hw/bsp/mcx/boards/frdmmcxa153/board.mk index a70a7dcef..cf6d9c0eb 100644 --- a/hw/bsp/mcx/boards/frdmmcxa153/board.mk +++ b/hw/bsp/mcx/boards/frdmmcxa153/board.mk @@ -6,7 +6,7 @@ CPU_CORE ?= cortex-m33-nodsp-nofp CFLAGS += \ -DCPU_MCXA153VLH \ -DCFG_TUSB_MCU=OPT_MCU_MCXA15 \ - + JLINK_DEVICE = MCXA153 PYOCD_TARGET = MCXA153 diff --git a/hw/bsp/mcx/boards/frdmmcxa153/clock_config.h b/hw/bsp/mcx/boards/frdmmcxa153/clock_config.h index 079d0d312..aae811052 100644 --- a/hw/bsp/mcx/boards/frdmmcxa153/clock_config.h +++ b/hw/bsp/mcx/boards/frdmmcxa153/clock_config.h @@ -4,7 +4,7 @@ * * SPDX-License-Identifier: BSD-3-Clause */ - + /*********************************************************************************************************************** * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. diff --git a/hw/bsp/mcx/boards/frdmmcxa153/pin_mux.c b/hw/bsp/mcx/boards/frdmmcxa153/pin_mux.c index b0e6de560..cc8f56e63 100644 --- a/hw/bsp/mcx/boards/frdmmcxa153/pin_mux.c +++ b/hw/bsp/mcx/boards/frdmmcxa153/pin_mux.c @@ -4,7 +4,7 @@ * * SPDX-License-Identifier: BSD-3-Clause */ - + /*********************************************************************************************************************** * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. diff --git a/hw/bsp/mcx/family.c b/hw/bsp/mcx/family.c index 74b84773d..96ae2fde3 100644 --- a/hw/bsp/mcx/family.c +++ b/hw/bsp/mcx/family.c @@ -151,7 +151,7 @@ void board_init(void) CLOCK_EnableClock(kCLOCK_Usb0Ram); CLOCK_EnableClock(kCLOCK_Usb0Fs); CLOCK_EnableUsbfsClock(); - + #endif #if PORT_SUPPORT_DEVICE(1) && (CFG_TUSB_MCU == OPT_MCU_MCXN9) diff --git a/hw/bsp/mcx/family.cmake b/hw/bsp/mcx/family.cmake index 078d13b9f..78490ec57 100644 --- a/hw/bsp/mcx/family.cmake +++ b/hw/bsp/mcx/family.cmake @@ -27,13 +27,13 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_gpio.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_common_arm.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_lpuart.c - + # mcu ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_reset.c ${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_CORE}.c ) - + if (${FAMILY_MCUS} STREQUAL "MCXN9") target_sources(${BOARD_TARGET} PRIVATE ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_lpflexcomm.c @@ -105,7 +105,7 @@ function(family_configure_example TARGET RTOS) elseif(${FAMILY_MCUS} STREQUAL "MCXA15") family_add_tinyusb(${TARGET} OPT_MCU_MCXA15 ${RTOS}) endif() - + target_sources(${TARGET}-tinyusb PUBLIC # TinyUSB: Port0 is chipidea FS, Port1 is chipidea HS ${TOP}/src/portable/chipidea/$ diff --git a/hw/bsp/mcx/family.mk b/hw/bsp/mcx/family.mk index 59170271c..3ee0efaf6 100644 --- a/hw/bsp/mcx/family.mk +++ b/hw/bsp/mcx/family.mk @@ -38,7 +38,7 @@ SRC_C += \ $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_gpio.c \ $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_lpuart.c \ $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_common_arm.c \ - + # fsl_lpflexcomm just needed for MCXN9 ifeq ($(MCU_VARIANT), MCXN947) @@ -54,7 +54,7 @@ ifeq ($(MCU_VARIANT), MCXA153) endif - + INC += \ $(TOP)/$(BOARD_PATH) \ diff --git a/src/portable/chipidea/ci_fs/ci_fs_mcx.h b/src/portable/chipidea/ci_fs/ci_fs_mcx.h index bf88df0f4..3f2b13323 100644 --- a/src/portable/chipidea/ci_fs/ci_fs_mcx.h +++ b/src/portable/chipidea/ci_fs/ci_fs_mcx.h @@ -36,7 +36,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_MCXA15 #define CI_FS_REG(_port) ((ci_fs_regs_t*) USB0_BASE) #define USB0_IRQN USB0_IRQn - + #else #error "MCU is not supported" #endif -- cgit v1.3.1 From c97c3418c741a26666942e184ca514f5dbdafcfa Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Apr 2024 20:31:55 +0700 Subject: minor update bsp --- examples/build_system/cmake/cpu/cortex-m23.cmake | 4 +- .../cmake/cpu/cortex-m33-nodsp-nofp.cmake | 2 +- examples/build_system/cmake/cpu/cortex-m33.cmake | 2 +- hw/bsp/mcx/boards/frdm_mcxa153/board.cmake | 3 - hw/bsp/mcx/boards/frdm_mcxa153/board.h | 20 +++-- hw/bsp/mcx/boards/frdm_mcxa153/board.mk | 2 +- hw/bsp/mcx/boards/frdm_mcxn947/board.cmake | 3 - hw/bsp/mcx/boards/frdm_mcxn947/board.mk | 2 +- hw/bsp/mcx/boards/mcxn947brk/board.cmake | 3 - hw/bsp/mcx/boards/mcxn947brk/board.mk | 2 +- hw/bsp/mcx/family.c | 92 ++++++++++------------ hw/bsp/mcx/family.cmake | 10 +++ hw/bsp/mcx/family.mk | 15 +--- src/portable/chipidea/ci_fs/ci_fs_mcx.h | 20 +++-- src/portable/chipidea/ci_fs/dcd_ci_fs.c | 2 +- 15 files changed, 81 insertions(+), 101 deletions(-) (limited to 'examples') diff --git a/examples/build_system/cmake/cpu/cortex-m23.cmake b/examples/build_system/cmake/cpu/cortex-m23.cmake index 3093dc99a..c7ce1d242 100644 --- a/examples/build_system/cmake/cpu/cortex-m23.cmake +++ b/examples/build_system/cmake/cpu/cortex-m23.cmake @@ -5,13 +5,13 @@ if (TOOLCHAIN STREQUAL "gcc") -mfloat-abi=soft ) - set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") + set(FREERTOS_PORT GCC_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS --cpu cortex-m23 ) - set(FREERTOS_PORT IAR_ARM_CM0 CACHE INTERNAL "") + set(FREERTOS_PORT IAR_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "") endif () diff --git a/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake b/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake index 7946affbe..01e6b979a 100644 --- a/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake +++ b/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake @@ -12,6 +12,6 @@ elseif (TOOLCHAIN STREQUAL "iar") --cpu cortex-m33+nodsp ) - set(FREERTOS_PORT IAR_ARM_CM4F CACHE INTERNAL "") + set(FREERTOS_PORT IAR_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "") endif () diff --git a/examples/build_system/cmake/cpu/cortex-m33.cmake b/examples/build_system/cmake/cpu/cortex-m33.cmake index 7ebaf1748..94c29099d 100644 --- a/examples/build_system/cmake/cpu/cortex-m33.cmake +++ b/examples/build_system/cmake/cpu/cortex-m33.cmake @@ -14,6 +14,6 @@ elseif (TOOLCHAIN STREQUAL "iar") --fpu VFPv5-SP ) - set(FREERTOS_PORT IAR_ARM_CM4F CACHE INTERNAL "") + set(FREERTOS_PORT IAR_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "") endif () diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake b/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake index acde3f46f..6a9a20e21 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake @@ -1,9 +1,6 @@ set(MCU_VARIANT MCXA153) set(MCU_CORE MCXA153) -set(FAMILY_MCUS MCXA15 CACHE INTERNAL "") -set(CMAKE_SYSTEM_PROCESSOR cortex-m33-nodsp-nofp CACHE INTERNAL "System Processor") - set(JLINK_DEVICE MCXA153_M33) set(PYOCD_TARGET MCXA153) set(NXPLINK_DEVICE MCXA153:MCXA153) diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board.h b/hw/bsp/mcx/boards/frdm_mcxa153/board.h index 02a452da5..e207d89d9 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/board.h +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board.h @@ -28,7 +28,7 @@ #define BOARD_H_ #ifdef __cplusplus - extern "C" { +extern "C" { #endif // LED @@ -38,29 +38,27 @@ #define LED_STATE_ON 0 // ISP button (Dummy, use unused pin - #define BUTTON_GPIO GPIO3 - #define BUTTON_CLK kCLOCK_GateGPIO3 - #define BUTTON_PIN 29 //sw2 - #define BUTTON_STATE_ACTIVE 0 +#define BUTTON_GPIO GPIO3 +#define BUTTON_CLK kCLOCK_GateGPIO3 +#define BUTTON_PIN 29 //sw2 +#define BUTTON_STATE_ACTIVE 0 // UART #define UART_DEV LPUART0 static inline void board_uart_init_clock(void) { - /* attach 12 MHz clock to LPUART0 (debug console) */ - CLOCK_SetClockDiv(kCLOCK_DivLPUART0, 1u); - CLOCK_AttachClk(kFRO12M_to_LPUART0); + CLOCK_SetClockDiv(kCLOCK_DivLPUART0, 1u); + CLOCK_AttachClk(kFRO12M_to_LPUART0); - RESET_PeripheralReset(kLPUART0_RST_SHIFT_RSTn); + RESET_PeripheralReset(kLPUART0_RST_SHIFT_RSTn); } - // XTAL #define XTAL0_CLK_HZ (24 * 1000 * 1000U) #ifdef __cplusplus - } +} #endif #endif diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board.mk b/hw/bsp/mcx/boards/frdm_mcxa153/board.mk index cf6d9c0eb..af8416d8e 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/board.mk +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board.mk @@ -2,7 +2,7 @@ MCU_VARIANT = MCXA153 MCU_CORE = MCXA153 PORT = 0 -CPU_CORE ?= cortex-m33-nodsp-nofp +CPU_CORE = cortex-m33-nodsp-nofp CFLAGS += \ -DCPU_MCXA153VLH \ -DCFG_TUSB_MCU=OPT_MCU_MCXA15 \ diff --git a/hw/bsp/mcx/boards/frdm_mcxn947/board.cmake b/hw/bsp/mcx/boards/frdm_mcxn947/board.cmake index a08d248f5..8c3280743 100644 --- a/hw/bsp/mcx/boards/frdm_mcxn947/board.cmake +++ b/hw/bsp/mcx/boards/frdm_mcxn947/board.cmake @@ -1,9 +1,6 @@ set(MCU_VARIANT MCXN947) set(MCU_CORE MCXN947_cm33_core0) -set(CMAKE_SYSTEM_PROCESSOR cortex-m33 CACHE INTERNAL "System Processor") -set(FAMILY_MCUS MCXN9 CACHE INTERNAL "") - set(JLINK_DEVICE MCXN947_M33_0) set(PYOCD_TARGET MCXN947) set(NXPLINK_DEVICE MCXN947:MCXN947) diff --git a/hw/bsp/mcx/boards/frdm_mcxn947/board.mk b/hw/bsp/mcx/boards/frdm_mcxn947/board.mk index d90780996..22fefd79b 100644 --- a/hw/bsp/mcx/boards/frdm_mcxn947/board.mk +++ b/hw/bsp/mcx/boards/frdm_mcxn947/board.mk @@ -2,7 +2,7 @@ MCU_VARIANT = MCXN947 MCU_CORE = MCXN947_cm33_core0 PORT ?= 1 -CPU_CORE ?= cortex-m33 +CPU_CORE = cortex-m33 CFLAGS += \ -DCPU_MCXN947VDF_cm33_core0 \ -DCFG_TUSB_MCU=OPT_MCU_MCXN9 \ diff --git a/hw/bsp/mcx/boards/mcxn947brk/board.cmake b/hw/bsp/mcx/boards/mcxn947brk/board.cmake index a08d248f5..8c3280743 100644 --- a/hw/bsp/mcx/boards/mcxn947brk/board.cmake +++ b/hw/bsp/mcx/boards/mcxn947brk/board.cmake @@ -1,9 +1,6 @@ set(MCU_VARIANT MCXN947) set(MCU_CORE MCXN947_cm33_core0) -set(CMAKE_SYSTEM_PROCESSOR cortex-m33 CACHE INTERNAL "System Processor") -set(FAMILY_MCUS MCXN9 CACHE INTERNAL "") - set(JLINK_DEVICE MCXN947_M33_0) set(PYOCD_TARGET MCXN947) set(NXPLINK_DEVICE MCXN947:MCXN947) diff --git a/hw/bsp/mcx/boards/mcxn947brk/board.mk b/hw/bsp/mcx/boards/mcxn947brk/board.mk index d90780996..22fefd79b 100644 --- a/hw/bsp/mcx/boards/mcxn947brk/board.mk +++ b/hw/bsp/mcx/boards/mcxn947brk/board.mk @@ -2,7 +2,7 @@ MCU_VARIANT = MCXN947 MCU_CORE = MCXN947_cm33_core0 PORT ?= 1 -CPU_CORE ?= cortex-m33 +CPU_CORE = cortex-m33 CFLAGS += \ -DCPU_MCXN947VDF_cm33_core0 \ -DCFG_TUSB_MCU=OPT_MCU_MCXN9 \ diff --git a/hw/bsp/mcx/family.c b/hw/bsp/mcx/family.c index 96ae2fde3..cc675a49d 100644 --- a/hw/bsp/mcx/family.c +++ b/hw/bsp/mcx/family.c @@ -33,6 +33,10 @@ #include "pin_mux.h" #include "clock_config.h" +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + #ifdef BOARD_TUD_RHPORT #define PORT_SUPPORT_DEVICE(_n) (BOARD_TUD_RHPORT == _n) #else @@ -45,54 +49,50 @@ #define PORT_SUPPORT_HOST(_n) 0 #endif -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ - //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ #if CFG_TUSB_MCU == OPT_MCU_MCXN9 -void USB0_FS_IRQHandler(void) -{ +void USB0_FS_IRQHandler(void) { tud_int_handler(0); } -void USB1_HS_IRQHandler(void) -{ +void USB1_HS_IRQHandler(void) { tud_int_handler(1); } #elif CFG_TUSB_MCU == OPT_MCU_MCXA15 -void USB0_IRQHandler(void) -{ + +void USB0_IRQHandler(void) { tud_int_handler(0); } + #endif -void board_init(void) -{ +void board_init(void) { BOARD_InitPins(); BOARD_InitBootClocks(); CLOCK_SetupExtClocking(XTAL0_CLK_HZ); +#if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer SysTick_Config(SystemCoreClock / 1000); - -#if CFG_TUSB_OS == OPT_OS_FREERTOS +#elif CFG_TUSB_OS == OPT_OS_FREERTOS // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(USB1_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); + #if CFG_TUSB_MCU == OPT_MCU_MCXN9 + NVIC_SetPriority(USB0_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(USB1_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + #else + NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + #endif #endif // LED CLOCK_EnableClock(LED_CLK); - gpio_pin_config_t led_config = { - kGPIO_DigitalOutput, - 0, - }; - GPIO_PinInit(LED_GPIO,LED_PIN, &led_config); + gpio_pin_config_t led_config = {kGPIO_DigitalOutput, 0}; + GPIO_PinInit(LED_GPIO, LED_PIN, &led_config); board_led_write(0); #ifdef NEOPIXEL_PIN @@ -110,7 +110,7 @@ void board_init(void) // Button #ifdef BUTTON_GPIO CLOCK_EnableClock(BUTTON_CLK); - gpio_pin_config_t const button_config = { kGPIO_DigitalInput, 0}; + gpio_pin_config_t const button_config = {kGPIO_DigitalInput, 0}; GPIO_PinInit(BUTTON_GPIO, BUTTON_PIN, &button_config); #endif @@ -125,33 +125,26 @@ void board_init(void) lpuart_config_t uart_config; LPUART_GetDefaultConfig(&uart_config); uart_config.baudRate_Bps = CFG_BOARD_UART_BAUDRATE; - uart_config.enableTx = true; - uart_config.enableRx = true; + uart_config.enableTx = true; + uart_config.enableRx = true; LPUART_Init(UART_DEV, &uart_config, 12000000u); #endif // USB VBUS /* PORT0 PIN22 configured as USB0_VBUS */ - - /* MCXA15 USB configurations */ -#if PORT_SUPPORT_DEVICE(0) && (CFG_TUSB_MCU == OPT_MCU_MCXA15) - - RESET_PeripheralReset(kUSB0_RST_SHIFT_RSTn); - CLOCK_EnableUsbfsClock(); - -#endif - - - /* MCXN9 USB configurations */ -#if PORT_SUPPORT_DEVICE(0) && (CFG_TUSB_MCU == OPT_MCU_MCXN9) +#if PORT_SUPPORT_DEVICE(0) // Port0 is Full Speed + #if CFG_TUSB_MCU == OPT_MCU_MCXA15 + RESET_PeripheralReset(kUSB0_RST_SHIFT_RSTn); + #elif CFG_TUSB_MCU == OPT_MCU_MCXN9 CLOCK_AttachClk(kCLK_48M_to_USB0); CLOCK_EnableClock(kCLOCK_Usb0Ram); CLOCK_EnableClock(kCLOCK_Usb0Fs); - CLOCK_EnableUsbfsClock(); + #endif + CLOCK_EnableUsbfsClock(); #endif #if PORT_SUPPORT_DEVICE(1) && (CFG_TUSB_MCU == OPT_MCU_MCXN9) @@ -213,9 +206,8 @@ void board_init(void) // Board porting API //--------------------------------------------------------------------+ -void board_led_write(bool state) -{ - GPIO_PinWrite(LED_GPIO, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +void board_led_write(bool state) { + GPIO_PinWrite(LED_GPIO, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); #ifdef NEOPIXEL_PIN if (state) { @@ -229,23 +221,21 @@ void board_led_write(bool state) #endif } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { #ifdef BUTTON_GPIO return BUTTON_STATE_ACTIVE == GPIO_PinRead(BUTTON_GPIO, BUTTON_PIN); #endif } -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; +int board_uart_read(uint8_t* buf, int len) { + (void) buf; + (void) len; return 0; } -int board_uart_write(void const * buf, int len) -{ +int board_uart_write(void const* buf, int len) { #ifdef UART_DEV - LPUART_WriteBlocking(UART_DEV, (uint8_t const *) buf, len); + LPUART_WriteBlocking(UART_DEV, (uint8_t const*) buf, len); return len; #else (void) buf; (void) len; @@ -255,13 +245,13 @@ int board_uart_write(void const * buf, int len) #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -void SysTick_Handler(void) -{ + +void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) -{ +uint32_t board_millis(void) { return system_ticks; } + #endif diff --git a/hw/bsp/mcx/family.cmake b/hw/bsp/mcx/family.cmake index 78490ec57..c8591b569 100644 --- a/hw/bsp/mcx/family.cmake +++ b/hw/bsp/mcx/family.cmake @@ -11,6 +11,16 @@ set(CMSIS_DIR ${TOP}/lib/CMSIS_5) include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) # toolchain set up +if (MCU_VARIANT STREQUAL "MCXA153") + set(CMAKE_SYSTEM_PROCESSOR cortex-m33-nodsp-nofp CACHE INTERNAL "System Processor") + set(FAMILY_MCUS MCXA15 CACHE INTERNAL "") +elseif (MCU_VARIANT STREQUAL "MCXN947") + set(CMAKE_SYSTEM_PROCESSOR cortex-m33 CACHE INTERNAL "System Processor") + set(FAMILY_MCUS MCXN9 CACHE INTERNAL "") +else() + message(FATAL_ERROR "MCU_VARIANT not supported") +endif() + set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) #------------------------------------ diff --git a/hw/bsp/mcx/family.mk b/hw/bsp/mcx/family.mk index 3ee0efaf6..58149fb8d 100644 --- a/hw/bsp/mcx/family.mk +++ b/hw/bsp/mcx/family.mk @@ -39,23 +39,16 @@ SRC_C += \ $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_lpuart.c \ $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_common_arm.c \ - -# fsl_lpflexcomm just needed for MCXN9 +# fsl_lpflexcomm for MCXN9 ifeq ($(MCU_VARIANT), MCXN947) - SRC_C += \ - $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_lpflexcomm.c \ - + SRC_C += $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_lpflexcomm.c endif -# fsl_spc just needed for MCXNA15 +# fsl_spc for MCXNA15 ifeq ($(MCU_VARIANT), MCXA153) - SRC_C += \ - $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_spc.c \ - + SRC_C += $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_spc.c endif - - INC += \ $(TOP)/$(BOARD_PATH) \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ diff --git a/src/portable/chipidea/ci_fs/ci_fs_mcx.h b/src/portable/chipidea/ci_fs/ci_fs_mcx.h index 3f2b13323..4b93a03a7 100644 --- a/src/portable/chipidea/ci_fs/ci_fs_mcx.h +++ b/src/portable/chipidea/ci_fs/ci_fs_mcx.h @@ -30,29 +30,27 @@ #include "fsl_device_registers.h" #if CFG_TUSB_MCU == OPT_MCU_MCXN9 - #define CI_FS_REG(_port) ((ci_fs_regs_t*) USBFS0_BASE) - #define USB0_IRQN USB0_FS_IRQn + #define CI_FS_REG(_port) ((ci_fs_regs_t*) USBFS0_BASE) + #define CIFS_IRQN USB0_FS_IRQn #elif CFG_TUSB_MCU == OPT_MCU_MCXA15 - #define CI_FS_REG(_port) ((ci_fs_regs_t*) USB0_BASE) - #define USB0_IRQN USB0_IRQn + #define CI_FS_REG(_port) ((ci_fs_regs_t*) USB0_BASE) + #define CIFS_IRQN USB0_IRQn #else #error "MCU is not supported" #endif -#define CI_REG CI_FS_REG(0) +#define CI_REG CI_FS_REG(0) -void dcd_int_enable(uint8_t rhport) -{ +void dcd_int_enable(uint8_t rhport) { (void) rhport; - NVIC_EnableIRQ(USB0_IRQN); + NVIC_EnableIRQ(CIFS_IRQN); } -void dcd_int_disable(uint8_t rhport) -{ +void dcd_int_disable(uint8_t rhport) { (void) rhport; - NVIC_DisableIRQ(USB0_IRQN); + NVIC_DisableIRQ(CIFS_IRQN); } #endif diff --git a/src/portable/chipidea/ci_fs/dcd_ci_fs.c b/src/portable/chipidea/ci_fs/dcd_ci_fs.c index a68ecf8c9..02f813ab5 100644 --- a/src/portable/chipidea/ci_fs/dcd_ci_fs.c +++ b/src/portable/chipidea/ci_fs/dcd_ci_fs.c @@ -295,7 +295,7 @@ void dcd_init(uint8_t rhport) CI_REG->INT_EN = USB_INTEN_USBRSTEN_MASK; dcd_connect(rhport); - // NVIC_ClearPendingIRQ(USB0_IRQn); + // NVIC_ClearPendingIRQ(CIFS_IRQN); } void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -- cgit v1.3.1 From 5c7876d4444de25942778728d377ec77f74a75dd Mon Sep 17 00:00:00 2001 From: Matthias Schär Date: Thu, 28 Jul 2022 13:01:36 +0200 Subject: Fixed behavior of the PRCR register. Previous write protection will be recovered. --- .idea/cmake.xml | 2 +- examples/device/cdc_msc_freertos/src/freertos_hook.c | 3 ++- examples/device/hid_composite_freertos/src/freertos_hook.c | 3 ++- src/common/tusb_compiler.h | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/.idea/cmake.xml b/.idea/cmake.xml index ebc6a0570..e4a08eaa6 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -75,7 +75,7 @@ - + diff --git a/examples/device/cdc_msc_freertos/src/freertos_hook.c b/examples/device/cdc_msc_freertos/src/freertos_hook.c index ab885947c..3cd27e08c 100644 --- a/examples/device/cdc_msc_freertos/src/freertos_hook.c +++ b/examples/device/cdc_msc_freertos/src/freertos_hook.c @@ -99,9 +99,10 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack void vApplicationSetupTimerInterrupt(void) { /* Enable CMT0 */ + unsigned short oldPRCR = SYSTEM.PRCR.WORD; SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); MSTP(CMT0) = 0; - SYSTEM.PRCR.WORD = (0xA5u<<8); + SYSTEM.PRCR.WORD = oldPRCR; CMT0.CMCNT = 0; CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); diff --git a/examples/device/hid_composite_freertos/src/freertos_hook.c b/examples/device/hid_composite_freertos/src/freertos_hook.c index ab885947c..3cd27e08c 100644 --- a/examples/device/hid_composite_freertos/src/freertos_hook.c +++ b/examples/device/hid_composite_freertos/src/freertos_hook.c @@ -99,9 +99,10 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack void vApplicationSetupTimerInterrupt(void) { /* Enable CMT0 */ + unsigned short oldPRCR = SYSTEM.PRCR.WORD; SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); MSTP(CMT0) = 0; - SYSTEM.PRCR.WORD = (0xA5u<<8); + SYSTEM.PRCR.WORD = oldPRCR; CMT0.CMCNT = 0; CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 6f07bdd53..86d150c68 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -56,7 +56,7 @@ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define TU_VERIFY_STATIC _Static_assert #elif defined(__CCRX__) - #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(Line, __LINE__)[(const_expr) ? 1 : 0]; + #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT3(Line, __LINE__, _TU_COUNTER_)[(const_expr) ? 1 : 0]; #else #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } #endif -- cgit v1.3.1 From 385611c5a9157569205986550022dee090f26c2f Mon Sep 17 00:00:00 2001 From: Matthias Schär Date: Thu, 28 Jul 2022 13:11:15 +0200 Subject: Revert "Fixed behavior of the PRCR register. Previous write protection will be recovered." This reverts commit 4d7296109e31690972d8cf09e6138131938cb0ed. --- examples/device/cdc_msc_freertos/src/freertos_hook.c | 3 +-- examples/device/hid_composite_freertos/src/freertos_hook.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/examples/device/cdc_msc_freertos/src/freertos_hook.c b/examples/device/cdc_msc_freertos/src/freertos_hook.c index 3cd27e08c..ab885947c 100644 --- a/examples/device/cdc_msc_freertos/src/freertos_hook.c +++ b/examples/device/cdc_msc_freertos/src/freertos_hook.c @@ -99,10 +99,9 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack void vApplicationSetupTimerInterrupt(void) { /* Enable CMT0 */ - unsigned short oldPRCR = SYSTEM.PRCR.WORD; SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); MSTP(CMT0) = 0; - SYSTEM.PRCR.WORD = oldPRCR; + SYSTEM.PRCR.WORD = (0xA5u<<8); CMT0.CMCNT = 0; CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); diff --git a/examples/device/hid_composite_freertos/src/freertos_hook.c b/examples/device/hid_composite_freertos/src/freertos_hook.c index 3cd27e08c..ab885947c 100644 --- a/examples/device/hid_composite_freertos/src/freertos_hook.c +++ b/examples/device/hid_composite_freertos/src/freertos_hook.c @@ -99,10 +99,9 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack void vApplicationSetupTimerInterrupt(void) { /* Enable CMT0 */ - unsigned short oldPRCR = SYSTEM.PRCR.WORD; SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); MSTP(CMT0) = 0; - SYSTEM.PRCR.WORD = oldPRCR; + SYSTEM.PRCR.WORD = (0xA5u<<8); CMT0.CMCNT = 0; CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); -- cgit v1.3.1 From bd67fdf01108304061f9dfaf4aa8624bb2a731ef Mon Sep 17 00:00:00 2001 From: Matthias Schär Date: Thu, 28 Jul 2022 13:25:39 +0200 Subject: Renesas RX controllers: Recover the previous state of the system write protect register in functions that are called within init-code --- examples/device/cdc_msc_freertos/src/freertos_hook.c | 3 ++- examples/device/hid_composite_freertos/src/freertos_hook.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/device/cdc_msc_freertos/src/freertos_hook.c b/examples/device/cdc_msc_freertos/src/freertos_hook.c index ab885947c..4920e3fae 100644 --- a/examples/device/cdc_msc_freertos/src/freertos_hook.c +++ b/examples/device/cdc_msc_freertos/src/freertos_hook.c @@ -99,9 +99,10 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack void vApplicationSetupTimerInterrupt(void) { /* Enable CMT0 */ + unsigned short oldPRCR = SYSTEM.PRCR.WORD; SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); MSTP(CMT0) = 0; - SYSTEM.PRCR.WORD = (0xA5u<<8); + SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR; CMT0.CMCNT = 0; CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); diff --git a/examples/device/hid_composite_freertos/src/freertos_hook.c b/examples/device/hid_composite_freertos/src/freertos_hook.c index ab885947c..4920e3fae 100644 --- a/examples/device/hid_composite_freertos/src/freertos_hook.c +++ b/examples/device/hid_composite_freertos/src/freertos_hook.c @@ -99,9 +99,10 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack void vApplicationSetupTimerInterrupt(void) { /* Enable CMT0 */ + unsigned short oldPRCR = SYSTEM.PRCR.WORD; SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); MSTP(CMT0) = 0; - SYSTEM.PRCR.WORD = (0xA5u<<8); + SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR; CMT0.CMCNT = 0; CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); -- cgit v1.3.1 From 2828a56a4f858c6ad72fec3175fec5ff794e2fac Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 9 Apr 2024 17:05:25 +0700 Subject: apply oldPRCR to board_init() --- .idea/cmake.xml | 2 +- examples/build_system/make/rules.mk | 26 +++++++++++++------------- hw/bsp/rx/boards/rx65n_target/rx65n_target.c | 4 +++- 3 files changed, 17 insertions(+), 15 deletions(-) (limited to 'examples') diff --git a/.idea/cmake.xml b/.idea/cmake.xml index e4a08eaa6..ebc6a0570 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -75,7 +75,7 @@ - + diff --git a/examples/build_system/make/rules.mk b/examples/build_system/make/rules.mk index b02665cdd..78fce49d2 100644 --- a/examples/build_system/make/rules.mk +++ b/examples/build_system/make/rules.mk @@ -9,19 +9,6 @@ # ESP32-Sx and RP2040 has its own CMake build system ifeq (,$(findstring $(FAMILY),espressif rp2040)) -# --------------------------------------- -# Compiler Flags -# --------------------------------------- - -CFLAGS += $(addprefix -I,$(INC)) - -# Verbose mode -ifeq ("$(V)","1") -$(info CFLAGS $(CFLAGS) ) $(info ) -$(info LDFLAGS $(LDFLAGS)) $(info ) -$(info ASFLAGS $(ASFLAGS)) $(info ) -endif - # --------------------------------------- # Rules # --------------------------------------- @@ -39,6 +26,19 @@ vpath %.S . $(TOP) include ${TOP}/examples/build_system/make/toolchain/arm_$(TOOLCHAIN)_rules.mk +# --------------------------------------- +# Compiler Flags +# --------------------------------------- + +CFLAGS += $(addprefix -I,$(INC)) + +# Verbose mode +ifeq ("$(V)","1") +$(info CFLAGS $(CFLAGS) ) $(info ) +$(info LDFLAGS $(LDFLAGS)) $(info ) +$(info ASFLAGS $(ASFLAGS)) $(info ) +endif + OBJ_DIRS = $(sort $(dir $(OBJ))) $(OBJ): | $(OBJ_DIRS) diff --git a/hw/bsp/rx/boards/rx65n_target/rx65n_target.c b/hw/bsp/rx/boards/rx65n_target/rx65n_target.c index 032dac810..66a319541 100644 --- a/hw/bsp/rx/boards/rx65n_target/rx65n_target.c +++ b/hw/bsp/rx/boards/rx65n_target/rx65n_target.c @@ -249,9 +249,10 @@ void board_init(void) EN(SCI5, TEI5) = 1; /* Enable USB0 */ + unsigned short oldPRCR = SYSTEM.PRCR.WORD; SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY | SYSTEM_PRCR_PRC1; MSTP(USB0) = 0; - SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY; + SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY | oldPRCR; /* setup USBI0 interrupt. */ IR(USB0, USBI0) = 0; @@ -277,6 +278,7 @@ int board_uart_read(uint8_t* buf, int len) sci_buf[1].buf = buf; sci_buf[1].cnt = len; SCI5.SCR.BYTE |= SCI_SCR_RE | SCI_SCR_RIE; + // TODO change to non blocking, return -1 immediately if no data while (SCI5.SCR.BIT.RE) ; return len - sci_buf[1].cnt; } -- cgit v1.3.1 From 455a2879fbb293b85c4e8d9ec3d4f172cf77803e Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 9 Apr 2024 12:34:36 +0200 Subject: Fix typo. --- examples/device/video_capture_2ch/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/device/video_capture_2ch/src/main.c b/examples/device/video_capture_2ch/src/main.c index 82bc7d6ca..eb1cf2580 100644 --- a/examples/device/video_capture_2ch/src/main.c +++ b/examples/device/video_capture_2ch/src/main.c @@ -184,7 +184,7 @@ size_t get_framebuf(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, size_t fnum, voi if (idx == 0) { // stream 0 use uncompressed YUY2 frame #if defined(CFG_EXAMPLE_VIDEO_READONLY) - *fb = (void*)(uintptr_t ) framebuf_yuy2_readonly[(fnum % (FRAME_WIDTH / 2)) * 4]; + *fb = (void*)(uintptr_t ) &framebuf_yuy2_readonly[(fnum % (FRAME_WIDTH / 2)) * 4]; #else fill_color_bar(framebuf_yuy2, frame_num[idx]); *fb = framebuf_yuy2; -- cgit v1.3.1 From 68b973aa9f64ad03210e5fb669f997a12965525f Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 5 Apr 2024 15:20:13 +0200 Subject: Reduce uac2_headset max sample rate for better compatibility. --- examples/device/uac2_headset/src/main.c | 6 +----- examples/device/uac2_headset/src/tusb_config.h | 8 +++----- 2 files changed, 4 insertions(+), 10 deletions(-) (limited to 'examples') diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 35b7ac94b..fbd7ffe22 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -35,11 +35,7 @@ //--------------------------------------------------------------------+ // List of supported sample rates -#if defined(__RX__) - const uint32_t sample_rates[] = {44100, 48000}; -#else - const uint32_t sample_rates[] = {44100, 48000, 88200, 96000}; -#endif +const uint32_t sample_rates[] = {44100, 48000}; uint32_t current_sample_rate = 44100; diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index 4b08fa676..328e35f52 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -114,11 +114,9 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_N_FORMATS 2 // Audio format type I specifications -#if defined(__RX__) -#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 48000 // 16bit/48kHz is the best quality for Renesas RX -#else -#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 96000 // 24bit/96kHz is the best quality for full-speed, high-speed is needed beyond this -#endif +/* 24bit/48kHz is the best quality for headset or 24bit/96kHz for 2ch speaker, + high-speed is needed beyond this */ +#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 48000 #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2 -- cgit v1.3.1 From 0d4465a0983dc6eda1aa59efe4d4b0414aba97ff Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 9 Apr 2024 23:11:43 +0200 Subject: Optimize audio_4_channel_mic waveform data. --- examples/device/audio_4_channel_mic/src/main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'examples') diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 1de4f9dac..10e6fe88a 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -104,39 +104,39 @@ int main(void) // Generate dummy data #if CFG_TUD_AUDIO_ENABLE_ENCODING uint16_t * p_buff = i2s_dummy_buffer[0]; - uint16_t dataVal = 1; + uint16_t dataVal = 0; for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) { // CH0 saw wave *p_buff++ = dataVal; // CH1 inverted saw wave - *p_buff++ = 60 + AUDIO_SAMPLE_RATE/1000 - dataVal; - dataVal++; + *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; + dataVal+= 32; } p_buff = i2s_dummy_buffer[1]; for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) { // CH3 square wave - *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 120:170; + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; // CH4 sinus wave float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); - *p_buff++ = (uint16_t)(sinf(t) * 25) + 200; + *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); } #else uint16_t * p_buff = i2s_dummy_buffer; - uint16_t dataVal = 1; + uint16_t dataVal = 0; for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) { // CH0 saw wave *p_buff++ = dataVal; // CH1 inverted saw wave - *p_buff++ = 60 + AUDIO_SAMPLE_RATE/1000 - dataVal; - dataVal++; + *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; + dataVal+= 32; // CH3 square wave - *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 120:170; + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; // CH4 sinus wave float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); - *p_buff++ = (uint16_t)(sinf(t) * 25) + 200; + *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); } #endif -- cgit v1.3.1 From abddc850ac8bc1377d8c1785a76bbba22405c5e8 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Apr 2024 21:49:55 +0700 Subject: add cmake support for msp430 --- .idea/cmake.xml | 12 ++-- examples/build_system/cmake/cpu/msp430.cmake | 7 ++ .../build_system/cmake/toolchain/msp430_gcc.cmake | 52 ++++++++++++++ hw/bsp/family_support.cmake | 15 ++++ hw/bsp/msp430/boards/msp_exp430f5529lp/board.cmake | 9 +++ hw/bsp/msp430/family.cmake | 84 ++++++++++++++++++++++ hw/bsp/msp430/family.mk | 9 +-- 7 files changed, 180 insertions(+), 8 deletions(-) create mode 100644 examples/build_system/cmake/cpu/msp430.cmake create mode 100644 examples/build_system/cmake/toolchain/msp430_gcc.cmake create mode 100644 hw/bsp/msp430/boards/msp_exp430f5529lp/board.cmake create mode 100644 hw/bsp/msp430/family.cmake (limited to 'examples') diff --git a/.idea/cmake.xml b/.idea/cmake.xml index ebc6a0570..c361e237d 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -2,8 +2,9 @@ - - + + + @@ -44,7 +45,7 @@ - + @@ -57,8 +58,10 @@ - + + + @@ -82,6 +85,7 @@ + \ No newline at end of file diff --git a/examples/build_system/cmake/cpu/msp430.cmake b/examples/build_system/cmake/cpu/msp430.cmake new file mode 100644 index 000000000..b4b47a2e8 --- /dev/null +++ b/examples/build_system/cmake/cpu/msp430.cmake @@ -0,0 +1,7 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(FREERTOS_PORT GCC_MSP430F449 CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "iar") + set(FREERTOS_PORT IAR_MSP430 CACHE INTERNAL "") + +endif () diff --git a/examples/build_system/cmake/toolchain/msp430_gcc.cmake b/examples/build_system/cmake/toolchain/msp430_gcc.cmake new file mode 100644 index 000000000..6291ce5a4 --- /dev/null +++ b/examples/build_system/cmake/toolchain/msp430_gcc.cmake @@ -0,0 +1,52 @@ +set(CMAKE_SYSTEM_NAME Generic) + +if (NOT DEFINED CMAKE_C_COMPILER) + set(CMAKE_C_COMPILER "msp430-elf-gcc") +endif () + +if (NOT DEFINED CMAKE_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "msp430-elf-g++") +endif () + +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) + +set(CMAKE_SIZE "msp430-elf-size" CACHE FILEPATH "") +set(CMAKE_OBJCOPY "msp430-elf-objcopy" CACHE FILEPATH "") +set(CMAKE_OBJDUMP "msp430-elf-objdump" CACHE FILEPATH "") + +set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) + +# Look for includes and libraries only in the target system prefix. +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# pass TOOLCHAIN_CPU to +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_SYSTEM_PROCESSOR) + +include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_PROCESSOR}.cmake) + +# enable all possible warnings for building examples +list(APPEND TOOLCHAIN_COMMON_FLAGS + -fdata-sections + -ffunction-sections + -fsingle-precision-constant + -fno-strict-aliasing + ) + +list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS + -Wl,--print-memory-usage + -Wl,--gc-sections + -Wl,--cref + ) + +include(${CMAKE_CURRENT_LIST_DIR}/set_flags.cmake) + +# try_compile is cmake test compiling its own example, +# pass -nostdlib to skip stdlib linking +get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) +if (IS_IN_TRY_COMPILE) + set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib") + set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib") +endif () diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 4ccd6e4f2..d4f355e0c 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -460,6 +460,21 @@ function(family_flash_dfu_util TARGET OPTION) ) endfunction() +function(family_flash_msp430flasher TARGET) + if (NOT DEFINED MSP430Flasher) + set(MSP430FLASHER MSP430Flasher) + endif () + + # set LD_LIBRARY_PATH to find libmsp430.so (directory containing MSP430Flasher) + find_program(MSP430FLASHER_PATH MSP430Flasher) + get_filename_component(MSP430FLASHER_PARENT_DIR "${MSP430FLASHER_PATH}" DIRECTORY) + add_custom_target(${TARGET}-msp430flasher + DEPENDS ${TARGET} + COMMAND ${CMAKE_COMMAND} -E env LD_LIBRARY_PATH=${MSP430FLASHER_PARENT_DIR} + ${MSP430FLASHER} -w $/${TARGET}.hex -z [VCC] + ) +endfunction() + #---------------------------------- # Family specific #---------------------------------- diff --git a/hw/bsp/msp430/boards/msp_exp430f5529lp/board.cmake b/hw/bsp/msp430/boards/msp_exp430f5529lp/board.cmake new file mode 100644 index 000000000..59f591263 --- /dev/null +++ b/hw/bsp/msp430/boards/msp_exp430f5529lp/board.cmake @@ -0,0 +1,9 @@ +set(MCU_VARIANT msp430f5529) +set(LD_FILE_GNU ${SDK_DIR}/msp430f5529.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} INTERFACE + __MSP430F5529__ + ) + +endfunction() diff --git a/hw/bsp/msp430/family.cmake b/hw/bsp/msp430/family.cmake new file mode 100644 index 000000000..e0b4ed28a --- /dev/null +++ b/hw/bsp/msp430/family.cmake @@ -0,0 +1,84 @@ +include_guard() + +set(SDK_DIR ${TOP}/hw/mcu/ti/msp430/msp430-gcc-support-files/include) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR msp430 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/msp430_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS MSP430x5xx CACHE INTERNAL "") + + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (NOT TARGET ${BOARD_TARGET}) + add_library(${BOARD_TARGET} INTERFACE) + target_compile_definitions(${BOARD_TARGET} INTERFACE + CFG_TUD_ENDPOINT0_SIZE=8 + CFG_EXAMPLE_VIDEO_READONLY + CFG_EXAMPLE_MSC_READONLY + ) + target_include_directories(${BOARD_TARGET} INTERFACE + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${SDK_DIR} + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} INTERFACE + "LINKER:--script=${LD_FILE_GNU}" + -L${SDK_DIR} + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} INTERFACE + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_MSP430x5xx ${RTOS}) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_msp430flasher(${TARGET}) +endfunction() diff --git a/hw/bsp/msp430/family.mk b/hw/bsp/msp430/family.mk index ceafa6ec1..f1c6f9cf2 100644 --- a/hw/bsp/msp430/family.mk +++ b/hw/bsp/msp430/family.mk @@ -2,6 +2,8 @@ CROSS_COMPILE = msp430-elf- DEPS_SUBMODULES += hw/mcu/ti SKIP_NANOLIB = 1 +SDK_DIR = hw/mcu/ti/msp430/msp430-gcc-support-files/include + CFLAGS += \ -D__MSP430F5529__ \ -DCFG_TUSB_MCU=OPT_MCU_MSP430x5xx \ @@ -9,14 +11,13 @@ CFLAGS += \ -DCFG_TUD_ENDPOINT0_SIZE=8 # All source paths should be relative to the top level. -LD_FILE = hw/mcu/ti/msp430/msp430-gcc-support-files/include/msp430f5529.ld -LDINC += $(TOP)/hw/mcu/ti/msp430/msp430-gcc-support-files/include -LDFLAGS += $(addprefix -L,$(LDINC)) +LD_FILE = ${SDK_DIR}/msp430f5529.ld +LDFLAGS += -L${TOP}/${SDK_DIR} SRC_C += src/portable/ti/msp430x5xx/dcd_msp430x5xx.c INC += \ - $(TOP)/hw/mcu/ti/msp430/msp430-gcc-support-files/include \ + ${TOP}/${SDK_DIR} \ $(TOP)/$(BOARD_PATH) # export for libmsp430.so to same installation -- cgit v1.3.1 From afb66a955c51f6ef36d0e544c44ee06a88eb2b2b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Apr 2024 22:49:08 +0700 Subject: update msp430 make build --- examples/build_system/make/cpu/msp430.mk | 8 ++++++++ hw/bsp/msp430/boards/msp_exp430f5529lp/board.mk | 4 ++++ hw/bsp/msp430/family.mk | 5 ++--- 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 examples/build_system/make/cpu/msp430.mk create mode 100644 hw/bsp/msp430/boards/msp_exp430f5529lp/board.mk (limited to 'examples') diff --git a/examples/build_system/make/cpu/msp430.mk b/examples/build_system/make/cpu/msp430.mk new file mode 100644 index 000000000..06340d23b --- /dev/null +++ b/examples/build_system/make/cpu/msp430.mk @@ -0,0 +1,8 @@ +ifeq ($(TOOLCHAIN),gcc) + # nothing to add +else ifeq ($(TOOLCHAIN),iar) + # nothing to add +endif + +# For freeRTOS port source +FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/GCC_MSP430F449 diff --git a/hw/bsp/msp430/boards/msp_exp430f5529lp/board.mk b/hw/bsp/msp430/boards/msp_exp430f5529lp/board.mk new file mode 100644 index 000000000..b45c62e83 --- /dev/null +++ b/hw/bsp/msp430/boards/msp_exp430f5529lp/board.mk @@ -0,0 +1,4 @@ +CFLAGS += \ + -D__MSP430F5529__ \ + +LD_FILE = ${SDK_DIR}/msp430f5529.ld diff --git a/hw/bsp/msp430/family.mk b/hw/bsp/msp430/family.mk index f1c6f9cf2..06508ab2c 100644 --- a/hw/bsp/msp430/family.mk +++ b/hw/bsp/msp430/family.mk @@ -4,14 +4,13 @@ SKIP_NANOLIB = 1 SDK_DIR = hw/mcu/ti/msp430/msp430-gcc-support-files/include +include $(TOP)/$(BOARD_PATH)/board.mk + CFLAGS += \ - -D__MSP430F5529__ \ -DCFG_TUSB_MCU=OPT_MCU_MSP430x5xx \ -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_TUD_ENDPOINT0_SIZE=8 -# All source paths should be relative to the top level. -LD_FILE = ${SDK_DIR}/msp430f5529.ld LDFLAGS += -L${TOP}/${SDK_DIR} SRC_C += src/portable/ti/msp430x5xx/dcd_msp430x5xx.c -- cgit v1.3.1 From 7545c40003d5f143cd7cb21037e4dd63b882d7f7 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 16 Apr 2024 22:17:29 +0700 Subject: cmake detect toolchain based on -DCMAKE_C_COMPILER --- examples/build_system/cmake/toolchain/arm_iar.cmake | 14 +++++++++++--- hw/bsp/family_support.cmake | 19 +++++++++++++++++-- 2 files changed, 28 insertions(+), 5 deletions(-) (limited to 'examples') diff --git a/examples/build_system/cmake/toolchain/arm_iar.cmake b/examples/build_system/cmake/toolchain/arm_iar.cmake index 1482624e5..c22685112 100644 --- a/examples/build_system/cmake/toolchain/arm_iar.cmake +++ b/examples/build_system/cmake/toolchain/arm_iar.cmake @@ -1,8 +1,16 @@ set(CMAKE_SYSTEM_NAME Generic) -set(CMAKE_C_COMPILER "iccarm") -set(CMAKE_CXX_COMPILER "iccarm") -set(CMAKE_ASM_COMPILER "iasmarm") +if (NOT DEFINED CMAKE_C_COMPILER) + set(CMAKE_C_COMPILER "iccarm") +endif() + +if (NOT DEFINED CMAKE_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "iccarm") +endif() + +if (NOT DEFINED CMAKE_ASM_COMPILER) + set(CMAKE_ASM_COMPILER "iasmarm") +endif() set(CMAKE_SIZE "size" CACHE FILEPATH "") set(CMAKE_OBJCOPY "ielftool" CACHE FILEPATH "") diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index d4f355e0c..7f4dda172 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -6,12 +6,24 @@ include(CMakePrintHelpers) set(TOP "${CMAKE_CURRENT_LIST_DIR}/../..") get_filename_component(TOP ${TOP} ABSOLUTE) -# Default to gcc +#------------------------------------------------------------- +# Toolchain +# Can be changed via -DTOOLCHAIN=gcc|iar or -DCMAKE_C_COMPILER= +#------------------------------------------------------------- +if (DEFINED CMAKE_C_COMPILER) + string(FIND ${CMAKE_C_COMPILER} "iccarm" IS_IAR) + if (NOT IS_IAR EQUAL -1) + set(TOOLCHAIN iar) + endif () +endif () + if (NOT DEFINED TOOLCHAIN) set(TOOLCHAIN gcc) endif () -# FAMILY not defined, try to detect it from BOARD +#------------------------------------------------------------- +# FAMILY and BOARD +#------------------------------------------------------------- if (NOT DEFINED FAMILY) if (NOT DEFINED BOARD) message(FATAL_ERROR "You must set a FAMILY variable for the build (e.g. rp2040, espressif). @@ -74,6 +86,9 @@ set(WARNING_FLAGS_GNU set(WARNING_FLAGS_IAR "") +#------------------------------------------------------------- +# Functions +#------------------------------------------------------------- # Filter example based on only.txt and skip.txt function(family_filter RESULT DIR) -- cgit v1.3.1 From 632a00195569126959836b7950cd9a62e4bb2dde Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 17 Apr 2024 11:38:33 +0700 Subject: update cmake build --- .../build_system/cmake/toolchain/arm_gcc.cmake | 35 +------------- .../build_system/cmake/toolchain/arm_iar.cmake | 25 +--------- examples/build_system/cmake/toolchain/common.cmake | 53 ++++++++++++++++++++++ .../build_system/cmake/toolchain/msp430_gcc.cmake | 39 +--------------- .../build_system/cmake/toolchain/set_flags.cmake | 17 ------- 5 files changed, 57 insertions(+), 112 deletions(-) create mode 100644 examples/build_system/cmake/toolchain/common.cmake delete mode 100644 examples/build_system/cmake/toolchain/set_flags.cmake (limited to 'examples') diff --git a/examples/build_system/cmake/toolchain/arm_gcc.cmake b/examples/build_system/cmake/toolchain/arm_gcc.cmake index d3fd5b557..d3d73c629 100644 --- a/examples/build_system/cmake/toolchain/arm_gcc.cmake +++ b/examples/build_system/cmake/toolchain/arm_gcc.cmake @@ -1,5 +1,3 @@ -set(CMAKE_SYSTEM_NAME Generic) - if (NOT DEFINED CMAKE_C_COMPILER) set(CMAKE_C_COMPILER "arm-none-eabi-gcc") endif () @@ -9,44 +7,15 @@ if (NOT DEFINED CMAKE_CXX_COMPILER) endif () set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) - set(CMAKE_SIZE "arm-none-eabi-size" CACHE FILEPATH "") set(CMAKE_OBJCOPY "arm-none-eabi-objcopy" CACHE FILEPATH "") set(CMAKE_OBJDUMP "arm-none-eabi-objdump" CACHE FILEPATH "") -set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) - -# Look for includes and libraries only in the target system prefix. -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - -# pass TOOLCHAIN_CPU to -set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_SYSTEM_PROCESSOR) - -include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_PROCESSOR}.cmake) - -# enable all possible warnings for building examples -list(APPEND TOOLCHAIN_COMMON_FLAGS - -fdata-sections - -ffunction-sections - -fsingle-precision-constant - -fno-strict-aliasing - ) - -list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS - -Wl,--print-memory-usage - -Wl,--gc-sections - -Wl,--cref - ) - -include(${CMAKE_CURRENT_LIST_DIR}/set_flags.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) -# try_compile is cmake test compiling its own example, -# pass -nostdlib to skip stdlib linking get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) if (IS_IN_TRY_COMPILE) set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib") set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib") + cmake_print_variables(CMAKE_C_LINK_FLAGS) endif () diff --git a/examples/build_system/cmake/toolchain/arm_iar.cmake b/examples/build_system/cmake/toolchain/arm_iar.cmake index c22685112..6d2219ca8 100644 --- a/examples/build_system/cmake/toolchain/arm_iar.cmake +++ b/examples/build_system/cmake/toolchain/arm_iar.cmake @@ -1,5 +1,3 @@ -set(CMAKE_SYSTEM_NAME Generic) - if (NOT DEFINED CMAKE_C_COMPILER) set(CMAKE_C_COMPILER "iccarm") endif() @@ -16,25 +14,4 @@ set(CMAKE_SIZE "size" CACHE FILEPATH "") set(CMAKE_OBJCOPY "ielftool" CACHE FILEPATH "") set(CMAKE_OBJDUMP "iefdumparm" CACHE FILEPATH "") -set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) - -# Look for includes and libraries only in the target system prefix. -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - -# pass TOOLCHAIN_CPU to -set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_SYSTEM_PROCESSOR) - -include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_PROCESSOR}.cmake) - -# enable all possible warnings for building examples -list(APPEND TOOLCHAIN_COMMON_FLAGS - ) - -list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS - --diag_suppress=Li065 - ) - -include(${CMAKE_CURRENT_LIST_DIR}/set_flags.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) diff --git a/examples/build_system/cmake/toolchain/common.cmake b/examples/build_system/cmake/toolchain/common.cmake new file mode 100644 index 000000000..56ac3caf5 --- /dev/null +++ b/examples/build_system/cmake/toolchain/common.cmake @@ -0,0 +1,53 @@ +include(CMakePrintHelpers) + +# ---------------------------------------------------------------------------- +# Common +# ---------------------------------------------------------------------------- +set(CMAKE_SYSTEM_NAME Generic) +set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) + +# Look for includes and libraries only in the target system prefix. +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# pass TOOLCHAIN_CPU to +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_SYSTEM_PROCESSOR) +include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_PROCESSOR}.cmake) + +# ---------------------------------------------------------------------------- +# Compile flags +# ---------------------------------------------------------------------------- +if (TOOLCHAIN STREQUAL "gcc") + list(APPEND TOOLCHAIN_COMMON_FLAGS + -fdata-sections + -ffunction-sections + -fsingle-precision-constant + -fno-strict-aliasing + ) + list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS + -Wl,--print-memory-usage + -Wl,--gc-sections + -Wl,--cref + ) +elseif (TOOLCHAIN STREQUAL "iar") + #list(APPEND TOOLCHAIN_COMMON_FLAGS) + list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS + --diag_suppress=Li065 + ) +elseif (TOOLCHAIN STREQUAL "clang") + message(FATAL_ERROR "Clang not supported") +endif () + +# join the toolchain flags into a single string +list(JOIN TOOLCHAIN_COMMON_FLAGS " " TOOLCHAIN_COMMON_FLAGS) +foreach (LANG IN ITEMS C CXX ASM) + set(CMAKE_${LANG}_FLAGS_INIT ${TOOLCHAIN_COMMON_FLAGS}) + # optimization flags for LOG, LOGGER ? + #set(CMAKE_${LANG}_FLAGS_RELEASE_INIT "-Os") + #set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-O0") +endforeach () + +# Linker +list(JOIN TOOLCHAIN_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS_INIT) diff --git a/examples/build_system/cmake/toolchain/msp430_gcc.cmake b/examples/build_system/cmake/toolchain/msp430_gcc.cmake index 6291ce5a4..73368adba 100644 --- a/examples/build_system/cmake/toolchain/msp430_gcc.cmake +++ b/examples/build_system/cmake/toolchain/msp430_gcc.cmake @@ -1,5 +1,3 @@ -set(CMAKE_SYSTEM_NAME Generic) - if (NOT DEFINED CMAKE_C_COMPILER) set(CMAKE_C_COMPILER "msp430-elf-gcc") endif () @@ -14,39 +12,4 @@ set(CMAKE_SIZE "msp430-elf-size" CACHE FILEPATH "") set(CMAKE_OBJCOPY "msp430-elf-objcopy" CACHE FILEPATH "") set(CMAKE_OBJDUMP "msp430-elf-objdump" CACHE FILEPATH "") -set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) - -# Look for includes and libraries only in the target system prefix. -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - -# pass TOOLCHAIN_CPU to -set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_SYSTEM_PROCESSOR) - -include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_PROCESSOR}.cmake) - -# enable all possible warnings for building examples -list(APPEND TOOLCHAIN_COMMON_FLAGS - -fdata-sections - -ffunction-sections - -fsingle-precision-constant - -fno-strict-aliasing - ) - -list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS - -Wl,--print-memory-usage - -Wl,--gc-sections - -Wl,--cref - ) - -include(${CMAKE_CURRENT_LIST_DIR}/set_flags.cmake) - -# try_compile is cmake test compiling its own example, -# pass -nostdlib to skip stdlib linking -get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) -if (IS_IN_TRY_COMPILE) - set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib") - set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib") -endif () +include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) diff --git a/examples/build_system/cmake/toolchain/set_flags.cmake b/examples/build_system/cmake/toolchain/set_flags.cmake deleted file mode 100644 index 44930ef4d..000000000 --- a/examples/build_system/cmake/toolchain/set_flags.cmake +++ /dev/null @@ -1,17 +0,0 @@ -include(CMakePrintHelpers) - -# join the toolchain flags into a single string -list(JOIN TOOLCHAIN_COMMON_FLAGS " " TOOLCHAIN_COMMON_FLAGS) - -foreach (LANG IN ITEMS C CXX ASM) - set(CMAKE_${LANG}_FLAGS_INIT ${TOOLCHAIN_COMMON_FLAGS}) - - #cmake_print_variables(CMAKE_${LANG}_FLAGS_INIT) - - # optimization flags for LOG, LOGGER ? - #set(CMAKE_${LANG}_FLAGS_RELEASE_INIT "-Os") - #set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-O0") -endforeach () - -# Linker -list(JOIN TOOLCHAIN_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS_INIT) -- cgit v1.3.1 From 96f7ca02bff64021b14ed84544df873a0d694a79 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 17 Apr 2024 13:00:07 +0700 Subject: clang build board test with h743 --- examples/build_system/cmake/cpu/cortex-m7.cmake | 11 +++++++++-- .../build_system/cmake/toolchain/arm_clang.cmake | 21 +++++++++++++++++++++ examples/build_system/cmake/toolchain/common.cmake | 11 ++++++++++- hw/bsp/family_support.cmake | 9 +++++++++ hw/bsp/stm32h7/family.cmake | 5 +++++ 5 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 examples/build_system/cmake/toolchain/arm_clang.cmake (limited to 'examples') diff --git a/examples/build_system/cmake/cpu/cortex-m7.cmake b/examples/build_system/cmake/cpu/cortex-m7.cmake index 3e5f7f44b..f7684af84 100644 --- a/examples/build_system/cmake/cpu/cortex-m7.cmake +++ b/examples/build_system/cmake/cpu/cortex-m7.cmake @@ -5,7 +5,6 @@ if (TOOLCHAIN STREQUAL "gcc") -mfloat-abi=hard -mfpu=fpv5-d16 ) - set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "iar") @@ -13,7 +12,15 @@ elseif (TOOLCHAIN STREQUAL "iar") --cpu cortex-m7 --fpu VFPv5_D16 ) - set(FREERTOS_PORT IAR_ARM_CM7 CACHE INTERNAL "") +elseif (TOOLCHAIN STREQUAL "clang") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-m7 + -mfloat-abi=hard + -mfpu=fpv5-d16 + ) + set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "") + endif () diff --git a/examples/build_system/cmake/toolchain/arm_clang.cmake b/examples/build_system/cmake/toolchain/arm_clang.cmake new file mode 100644 index 000000000..754d672fd --- /dev/null +++ b/examples/build_system/cmake/toolchain/arm_clang.cmake @@ -0,0 +1,21 @@ +if (NOT DEFINED CMAKE_C_COMPILER) + set(CMAKE_C_COMPILER "clang") +endif () + +if (NOT DEFINED CMAKE_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "clang++") +endif () + +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +set(CMAKE_SIZE "llvm-size" CACHE FILEPATH "") +set(CMAKE_OBJCOPY "llvm-objcopy" CACHE FILEPATH "") +set(CMAKE_OBJDUMP "llvm-objdump" CACHE FILEPATH "") + +include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) + +get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) +if (IS_IN_TRY_COMPILE) + set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib") + set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib") + cmake_print_variables(CMAKE_C_LINK_FLAGS) +endif () diff --git a/examples/build_system/cmake/toolchain/common.cmake b/examples/build_system/cmake/toolchain/common.cmake index 56ac3caf5..6c6d54c74 100644 --- a/examples/build_system/cmake/toolchain/common.cmake +++ b/examples/build_system/cmake/toolchain/common.cmake @@ -37,7 +37,16 @@ elseif (TOOLCHAIN STREQUAL "iar") --diag_suppress=Li065 ) elseif (TOOLCHAIN STREQUAL "clang") - message(FATAL_ERROR "Clang not supported") + list(APPEND TOOLCHAIN_COMMON_FLAGS + -fdata-sections + -ffunction-sections + -fno-strict-aliasing + ) + list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS + -Wl,--print-memory-usage + -Wl,--gc-sections + -Wl,--cref + ) endif () # join the toolchain flags into a single string diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 7f4dda172..8dd61b91c 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -10,13 +10,22 @@ get_filename_component(TOP ${TOP} ABSOLUTE) # Toolchain # Can be changed via -DTOOLCHAIN=gcc|iar or -DCMAKE_C_COMPILER= #------------------------------------------------------------- +# Detect toolchain based on CMAKE_C_COMPILER if (DEFINED CMAKE_C_COMPILER) string(FIND ${CMAKE_C_COMPILER} "iccarm" IS_IAR) + string(FIND ${CMAKE_C_COMPILER} "clang" IS_CLANG) + string(FIND ${CMAKE_C_COMPILER} "gcc" IS_GCC) + if (NOT IS_IAR EQUAL -1) set(TOOLCHAIN iar) + elseif (NOT IS_CLANG EQUAL -1) + set(TOOLCHAIN clang) + elseif (NOT IS_GCC EQUAL -1) + set(TOOLCHAIN gcc) endif () endif () +# default to gcc if (NOT DEFINED TOOLCHAIN) set(TOOLCHAIN gcc) endif () diff --git a/hw/bsp/stm32h7/family.cmake b/hw/bsp/stm32h7/family.cmake index 6174dfda3..d852ce21c 100644 --- a/hw/bsp/stm32h7/family.cmake +++ b/hw/bsp/stm32h7/family.cmake @@ -29,6 +29,7 @@ function(add_board_target BOARD_TARGET) if (NOT TARGET ${BOARD_TARGET}) # Startup & Linker script set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) if(NOT DEFINED LD_FILE_IAR) @@ -72,6 +73,10 @@ function(add_board_target BOARD_TARGET) target_link_options(${BOARD_TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}" ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + ) endif () endif () endfunction() -- cgit v1.3.1 From 3442a87d5b52112a8bc4672322d488703e4ee23e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 17 Apr 2024 20:06:13 +0700 Subject: - clang h743 build and run cdc_msc ok - switch unit test back to gcc, since path to clang conflict on local setup (x86 and arm) --- examples/build_system/cmake/cpu/cortex-m7.cmake | 1 - examples/build_system/cmake/toolchain/common.cmake | 2 +- hw/bsp/board.c | 19 +++++++++++++++++++ hw/bsp/stm32h7/family.cmake | 7 +++---- src/common/tusb_common.h | 1 + src/portable/synopsys/dwc2/dcd_dwc2.c | 6 +++--- test/unit-test/project.yml | 12 ++++++------ 7 files changed, 33 insertions(+), 15 deletions(-) (limited to 'examples') diff --git a/examples/build_system/cmake/cpu/cortex-m7.cmake b/examples/build_system/cmake/cpu/cortex-m7.cmake index f7684af84..b0f84b76b 100644 --- a/examples/build_system/cmake/cpu/cortex-m7.cmake +++ b/examples/build_system/cmake/cpu/cortex-m7.cmake @@ -18,7 +18,6 @@ elseif (TOOLCHAIN STREQUAL "clang") set(TOOLCHAIN_COMMON_FLAGS --target=arm-none-eabi -mcpu=cortex-m7 - -mfloat-abi=hard -mfpu=fpv5-d16 ) set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "") diff --git a/examples/build_system/cmake/toolchain/common.cmake b/examples/build_system/cmake/toolchain/common.cmake index 6c6d54c74..bbd670b65 100644 --- a/examples/build_system/cmake/toolchain/common.cmake +++ b/examples/build_system/cmake/toolchain/common.cmake @@ -45,7 +45,7 @@ elseif (TOOLCHAIN STREQUAL "clang") list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS -Wl,--print-memory-usage -Wl,--gc-sections - -Wl,--cref + #-Wl,--cref ) endif () diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 23b4b6628..996ac9263 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -108,6 +108,25 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) { // st->st_mode = S_IFCHR; //} +// Clang use picolibc +#if defined(__clang__) +static int cl_putc(char c, FILE *f) { + (void) f; + return sys_write(0, &c, 1); +} + +static int cl_getc(FILE* f) { + (void) f; + char c; + return sys_read(0, &c, 1) > 0 ? c : -1; +} + +static FILE __stdio = FDEV_SETUP_STREAM(cl_putc, cl_getc, NULL, _FDEV_SETUP_RW); +FILE *const stdin = &__stdio; +__strong_reference(stdin, stdout); +__strong_reference(stdin, stderr); +#endif + int board_getchar(void) { char c; return (sys_read(0, &c, 1) > 0) ? (int) c : (-1); diff --git a/hw/bsp/stm32h7/family.cmake b/hw/bsp/stm32h7/family.cmake index d852ce21c..ab9ba3fbb 100644 --- a/hw/bsp/stm32h7/family.cmake +++ b/hw/bsp/stm32h7/family.cmake @@ -56,10 +56,8 @@ function(add_board_target BOARD_TARGET) ${ST_CMSIS}/Include ${ST_HAL_DRIVER}/Inc ) - target_compile_options(${BOARD_TARGET} PUBLIC - ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - ) + #target_compile_options(${BOARD_TARGET} PUBLIC) + #target_compile_definitions(${BOARD_TARGET} PUBLIC) update_board(${BOARD_TARGET}) @@ -75,6 +73,7 @@ function(add_board_target BOARD_TARGET) ) elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") target_link_options(${BOARD_TARGET} PUBLIC + #-ldummyhost "LINKER:--script=${LD_FILE_GNU}" ) endif () diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 1f08ce4ed..0d4082c03 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -65,6 +65,7 @@ // Standard Headers #include #include +#include #include #include #include diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index a824226c7..f17d30f06 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -174,7 +174,7 @@ static bool fifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { // Check if free space is available TU_ASSERT(_allocated_fifo_words_tx + fifo_size + dwc2->grxfsiz <= _dwc2_controller[rhport].ep_fifo_size / 4); _allocated_fifo_words_tx += fifo_size; - TU_LOG(DWC2_DEBUG, " Allocated %u bytes at offset %lu", fifo_size * 4, + TU_LOG(DWC2_DEBUG, " Allocated %u bytes at offset %" PRIu32, fifo_size * 4, _dwc2_controller[rhport].ep_fifo_size - _allocated_fifo_words_tx * 4); // DIEPTXF starts at FIFO #1. @@ -419,9 +419,9 @@ void print_dwc2_info(dwc2_regs_t* dwc2) { volatile uint32_t const* p = (volatile uint32_t const*) &dwc2->guid; TU_LOG(DWC2_DEBUG, "guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4\r\n"); for (size_t i = 0; i < 5; i++) { - TU_LOG(DWC2_DEBUG, "0x%08lX, ", p[i]); + TU_LOG(DWC2_DEBUG, "0x%08" PRIX32 ", ", p[i]); } - TU_LOG(DWC2_DEBUG, "0x%08lX\r\n", p[5]); + TU_LOG(DWC2_DEBUG, "0x%08" PRIX32 "\r\n", p[5]); } #endif diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index 82528f68c..7fbbabfe6 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -81,20 +81,20 @@ :tools: :test_compiler: - :executable: clang - :name: 'clang compiler' + :executable: gcc + :name: 'gcc compiler' :arguments: - -I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE #expands to -I search paths - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR #expands to -I search paths - -D$: COLLECTION_DEFINES_TEST_AND_VENDOR #expands to all -D defined symbols - - -fsanitize=address + #- -fsanitize=address - -c ${1} #source code input file (Ruby method call param list sub) - -o ${2} #object file output (Ruby method call param list sub) :test_linker: - :executable: clang - :name: 'clang linker' + :executable: gcc + :name: 'gcc linker' :arguments: - - -fsanitize=address + #- -fsanitize=address - ${1} #list of object files to link (Ruby method call param list sub) - -o ${2} #executable file output (Ruby method call param list sub) -- cgit v1.3.1 From 824e39ddeb762a0876702304ac95ea3b1d40cb5a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 17 Apr 2024 23:08:06 +0700 Subject: more clang update --- examples/build_system/cmake/cpu/cortex-m0.cmake | 5 +++-- examples/build_system/cmake/cpu/cortex-m0plus.cmake | 5 +++-- examples/build_system/cmake/cpu/cortex-m23.cmake | 5 +++-- examples/build_system/cmake/cpu/cortex-m3.cmake | 5 +++-- .../build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake | 5 +++-- examples/build_system/cmake/cpu/cortex-m33.cmake | 5 +++-- examples/build_system/cmake/cpu/cortex-m4.cmake | 9 +++++++++ examples/build_system/cmake/cpu/cortex-m7.cmake | 14 +++++++------- examples/build_system/cmake/cpu/msp430.cmake | 3 +++ examples/device/cdc_msc/src/main.c | 4 ---- hw/bsp/board_api.h | 3 +++ hw/bsp/stm32h7/family.cmake | 9 ++++----- 12 files changed, 44 insertions(+), 28 deletions(-) (limited to 'examples') diff --git a/examples/build_system/cmake/cpu/cortex-m0.cmake b/examples/build_system/cmake/cpu/cortex-m0.cmake index bc2257048..2438ca96a 100644 --- a/examples/build_system/cmake/cpu/cortex-m0.cmake +++ b/examples/build_system/cmake/cpu/cortex-m0.cmake @@ -4,14 +4,15 @@ if (TOOLCHAIN STREQUAL "gcc") -mcpu=cortex-m0plus -mfloat-abi=soft ) - set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") +elseif (TOOLCHAIN STREQUAL "clang") + message(FATAL_ERROR "Clang is not supported for this target") + elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS --cpu cortex-m0 ) - set(FREERTOS_PORT IAR_ARM_CM0 CACHE INTERNAL "") endif () diff --git a/examples/build_system/cmake/cpu/cortex-m0plus.cmake b/examples/build_system/cmake/cpu/cortex-m0plus.cmake index bc2257048..2438ca96a 100644 --- a/examples/build_system/cmake/cpu/cortex-m0plus.cmake +++ b/examples/build_system/cmake/cpu/cortex-m0plus.cmake @@ -4,14 +4,15 @@ if (TOOLCHAIN STREQUAL "gcc") -mcpu=cortex-m0plus -mfloat-abi=soft ) - set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") +elseif (TOOLCHAIN STREQUAL "clang") + message(FATAL_ERROR "Clang is not supported for this target") + elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS --cpu cortex-m0 ) - set(FREERTOS_PORT IAR_ARM_CM0 CACHE INTERNAL "") endif () diff --git a/examples/build_system/cmake/cpu/cortex-m23.cmake b/examples/build_system/cmake/cpu/cortex-m23.cmake index c7ce1d242..a7eb82684 100644 --- a/examples/build_system/cmake/cpu/cortex-m23.cmake +++ b/examples/build_system/cmake/cpu/cortex-m23.cmake @@ -4,14 +4,15 @@ if (TOOLCHAIN STREQUAL "gcc") -mcpu=cortex-m23 -mfloat-abi=soft ) - set(FREERTOS_PORT GCC_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "") +elseif (TOOLCHAIN STREQUAL "clang") + message(FATAL_ERROR "Clang is not supported for this target") + elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS --cpu cortex-m23 ) - set(FREERTOS_PORT IAR_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "") endif () diff --git a/examples/build_system/cmake/cpu/cortex-m3.cmake b/examples/build_system/cmake/cpu/cortex-m3.cmake index f6f5a62f8..90982f415 100644 --- a/examples/build_system/cmake/cpu/cortex-m3.cmake +++ b/examples/build_system/cmake/cpu/cortex-m3.cmake @@ -3,14 +3,15 @@ if (TOOLCHAIN STREQUAL "gcc") -mthumb -mcpu=cortex-m3 ) - set(FREERTOS_PORT GCC_ARM_CM3 CACHE INTERNAL "") +elseif (TOOLCHAIN STREQUAL "clang") + message(FATAL_ERROR "Clang is not supported for this target") + elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS --cpu cortex-m3 ) - set(FREERTOS_PORT IAR_ARM_CM3 CACHE INTERNAL "") endif () diff --git a/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake b/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake index 01e6b979a..51fd70b0e 100644 --- a/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake +++ b/examples/build_system/cmake/cpu/cortex-m33-nodsp-nofp.cmake @@ -4,14 +4,15 @@ if (TOOLCHAIN STREQUAL "gcc") -mcpu=cortex-m33+nodsp -mfloat-abi=soft ) - set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "") +elseif (TOOLCHAIN STREQUAL "clang") + message(FATAL_ERROR "Clang is not supported for this target") + elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS --cpu cortex-m33+nodsp ) - set(FREERTOS_PORT IAR_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "") endif () diff --git a/examples/build_system/cmake/cpu/cortex-m33.cmake b/examples/build_system/cmake/cpu/cortex-m33.cmake index 94c29099d..c38d05376 100644 --- a/examples/build_system/cmake/cpu/cortex-m33.cmake +++ b/examples/build_system/cmake/cpu/cortex-m33.cmake @@ -5,15 +5,16 @@ if (TOOLCHAIN STREQUAL "gcc") -mfloat-abi=hard -mfpu=fpv5-sp-d16 ) - set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "") +elseif (TOOLCHAIN STREQUAL "clang") + message(FATAL_ERROR "Clang is not supported for this target") + elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS --cpu cortex-m33 --fpu VFPv5-SP ) - set(FREERTOS_PORT IAR_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "") endif () diff --git a/examples/build_system/cmake/cpu/cortex-m4.cmake b/examples/build_system/cmake/cpu/cortex-m4.cmake index db308aa83..9cdadc6f8 100644 --- a/examples/build_system/cmake/cpu/cortex-m4.cmake +++ b/examples/build_system/cmake/cpu/cortex-m4.cmake @@ -5,7 +5,16 @@ if (TOOLCHAIN STREQUAL "gcc") -mfloat-abi=hard -mfpu=fpv4-sp-d16 ) + if (NOT DEFINED FREERTOS_PORT) + set(FREERTOS_PORT GCC_ARM_CM4F CACHE INTERNAL "") + endif () +elseif (TOOLCHAIN STREQUAL "clang") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-m4 + -mfpu=fpv4-sp-d16 + ) if (NOT DEFINED FREERTOS_PORT) set(FREERTOS_PORT GCC_ARM_CM4F CACHE INTERNAL "") endif () diff --git a/examples/build_system/cmake/cpu/cortex-m7.cmake b/examples/build_system/cmake/cpu/cortex-m7.cmake index b0f84b76b..b41dfded5 100644 --- a/examples/build_system/cmake/cpu/cortex-m7.cmake +++ b/examples/build_system/cmake/cpu/cortex-m7.cmake @@ -7,13 +7,6 @@ if (TOOLCHAIN STREQUAL "gcc") ) set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "") -elseif (TOOLCHAIN STREQUAL "iar") - set(TOOLCHAIN_COMMON_FLAGS - --cpu cortex-m7 - --fpu VFPv5_D16 - ) - set(FREERTOS_PORT IAR_ARM_CM7 CACHE INTERNAL "") - elseif (TOOLCHAIN STREQUAL "clang") set(TOOLCHAIN_COMMON_FLAGS --target=arm-none-eabi @@ -22,4 +15,11 @@ elseif (TOOLCHAIN STREQUAL "clang") ) set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "") +elseif (TOOLCHAIN STREQUAL "iar") + set(TOOLCHAIN_COMMON_FLAGS + --cpu cortex-m7 + --fpu VFPv5_D16 + ) + set(FREERTOS_PORT IAR_ARM_CM7 CACHE INTERNAL "") + endif () diff --git a/examples/build_system/cmake/cpu/msp430.cmake b/examples/build_system/cmake/cpu/msp430.cmake index b4b47a2e8..584ec5741 100644 --- a/examples/build_system/cmake/cpu/msp430.cmake +++ b/examples/build_system/cmake/cpu/msp430.cmake @@ -1,6 +1,9 @@ if (TOOLCHAIN STREQUAL "gcc") set(FREERTOS_PORT GCC_MSP430F449 CACHE INTERNAL "") +elseif (TOOLCHAIN STREQUAL "clang") + message(FATAL_ERROR "Clang is not supported for this target") + elseif (TOOLCHAIN STREQUAL "iar") set(FREERTOS_PORT IAR_MSP430 CACHE INTERNAL "") diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index 0d3f97c8f..4581a3bab 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -23,10 +23,6 @@ * */ -#include -#include -#include - #include "bsp/board_api.h" #include "tusb.h" diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 3b9f211a2..418ce3551 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -32,7 +32,10 @@ extern "C" { #endif #include +#include #include +#include + #include "tusb.h" #if CFG_TUSB_OS == OPT_OS_FREERTOS diff --git a/hw/bsp/stm32h7/family.cmake b/hw/bsp/stm32h7/family.cmake index ab9ba3fbb..a4123dda7 100644 --- a/hw/bsp/stm32h7/family.cmake +++ b/hw/bsp/stm32h7/family.cmake @@ -67,15 +67,14 @@ function(add_board_target BOARD_TARGET) -nostartfiles --specs=nosys.specs --specs=nano.specs ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") target_link_options(${BOARD_TARGET} PUBLIC - #-ldummyhost "LINKER:--script=${LD_FILE_GNU}" ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) endif () endif () endfunction() -- cgit v1.3.1 From be0d62ba6c84e6c44416f5a837d830000f316505 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Apr 2024 13:40:42 +0700 Subject: clang samd51 compile but does not run, rom is correct, but ram is lacking bss. Got stkerr -> hardfault --- examples/build_system/cmake/cpu/cortex-m0.cmake | 6 ++++- examples/build_system/cmake/cpu/cortex-m23.cmake | 6 ++++- examples/build_system/cmake/cpu/cortex-m3.cmake | 6 ++++- examples/build_system/cmake/cpu/cortex-m33.cmake | 7 ++++- examples/build_system/cmake/toolchain/common.cmake | 4 ++- hw/bsp/family_support.cmake | 5 ++-- hw/bsp/samd51/family.cmake | 31 +++++++++++++--------- 7 files changed, 45 insertions(+), 20 deletions(-) (limited to 'examples') diff --git a/examples/build_system/cmake/cpu/cortex-m0.cmake b/examples/build_system/cmake/cpu/cortex-m0.cmake index 2438ca96a..ddf0f16af 100644 --- a/examples/build_system/cmake/cpu/cortex-m0.cmake +++ b/examples/build_system/cmake/cpu/cortex-m0.cmake @@ -7,7 +7,11 @@ if (TOOLCHAIN STREQUAL "gcc") set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "clang") - message(FATAL_ERROR "Clang is not supported for this target") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-m0plus + ) + set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS diff --git a/examples/build_system/cmake/cpu/cortex-m23.cmake b/examples/build_system/cmake/cpu/cortex-m23.cmake index a7eb82684..00382ed9b 100644 --- a/examples/build_system/cmake/cpu/cortex-m23.cmake +++ b/examples/build_system/cmake/cpu/cortex-m23.cmake @@ -7,7 +7,11 @@ if (TOOLCHAIN STREQUAL "gcc") set(FREERTOS_PORT GCC_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "clang") - message(FATAL_ERROR "Clang is not supported for this target") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-m23 + ) + set(FREERTOS_PORT GCC_ARM_CM23_NTZ_NONSECURE CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS diff --git a/examples/build_system/cmake/cpu/cortex-m3.cmake b/examples/build_system/cmake/cpu/cortex-m3.cmake index 90982f415..27888604e 100644 --- a/examples/build_system/cmake/cpu/cortex-m3.cmake +++ b/examples/build_system/cmake/cpu/cortex-m3.cmake @@ -6,7 +6,11 @@ if (TOOLCHAIN STREQUAL "gcc") set(FREERTOS_PORT GCC_ARM_CM3 CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "clang") - message(FATAL_ERROR "Clang is not supported for this target") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-m3 + ) + set(FREERTOS_PORT GCC_ARM_CM3 CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS diff --git a/examples/build_system/cmake/cpu/cortex-m33.cmake b/examples/build_system/cmake/cpu/cortex-m33.cmake index c38d05376..d56d07ebc 100644 --- a/examples/build_system/cmake/cpu/cortex-m33.cmake +++ b/examples/build_system/cmake/cpu/cortex-m33.cmake @@ -8,7 +8,12 @@ if (TOOLCHAIN STREQUAL "gcc") set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "clang") - message(FATAL_ERROR "Clang is not supported for this target") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-m33 + -mfpu=fpv5-sp-d16 + ) + set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS diff --git a/examples/build_system/cmake/toolchain/common.cmake b/examples/build_system/cmake/toolchain/common.cmake index bbd670b65..688715914 100644 --- a/examples/build_system/cmake/toolchain/common.cmake +++ b/examples/build_system/cmake/toolchain/common.cmake @@ -31,11 +31,13 @@ if (TOOLCHAIN STREQUAL "gcc") -Wl,--gc-sections -Wl,--cref ) + elseif (TOOLCHAIN STREQUAL "iar") #list(APPEND TOOLCHAIN_COMMON_FLAGS) list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS --diag_suppress=Li065 ) + elseif (TOOLCHAIN STREQUAL "clang") list(APPEND TOOLCHAIN_COMMON_FLAGS -fdata-sections @@ -45,7 +47,7 @@ elseif (TOOLCHAIN STREQUAL "clang") list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS -Wl,--print-memory-usage -Wl,--gc-sections - #-Wl,--cref + -Wl,--cref ) endif () diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 8dd61b91c..d86ecc0a2 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -219,8 +219,9 @@ function(family_configure_common TARGET RTOS) if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0) target_link_options(${TARGET} PUBLIC "LINKER:--no-warn-rwx-segments") endif () - endif() - if (CMAKE_C_COMPILER_ID STREQUAL "IAR") + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC "LINKER:-Map=$.map") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") target_link_options(${TARGET} PUBLIC "LINKER:--map=$.map") endif() diff --git a/hw/bsp/samd51/family.cmake b/hw/bsp/samd51/family.cmake index 4d91bf1a6..08f03f727 100644 --- a/hw/bsp/samd51/family.cmake +++ b/hw/bsp/samd51/family.cmake @@ -1,6 +1,7 @@ include_guard() set(SDK_DIR ${TOP}/hw/mcu/microchip/samd51) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) # include board specific include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) @@ -18,6 +19,16 @@ set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -c \"transport select swd\" -c \" # only need to be built ONCE for all examples function(add_board_target BOARD_TARGET) if (NOT TARGET ${BOARD_TARGET}) + set(LD_FILE_Clang ${LD_FILE_GNU}) + if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) + message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") + endif () + + if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) + set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_samd51.c) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + endif () + add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/gcc/system_samd51.c ${SDK_DIR}/hpl/gclk/hpl_gclk.c @@ -25,6 +36,7 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/hpl/osc32kctrl/hpl_osc32kctrl.c ${SDK_DIR}/hpl/oscctrl/hpl_oscctrl.c ${SDK_DIR}/hal/src/hal_atomic.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_DIR}/ @@ -34,29 +46,22 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/hal/utils/include ${SDK_DIR}/hpl/port ${SDK_DIR}/hri - ${SDK_DIR}/CMSIS/Include + ${CMSIS_5}/CMSIS/Core/Include ) update_board(${BOARD_TARGET}) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") - endif () - - if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) - set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_samd51.c) - endif () - - target_sources(${BOARD_TARGET} PRIVATE - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") target_link_options(${BOARD_TARGET} PUBLIC "LINKER:--script=${LD_FILE_GNU}" -nostartfiles --specs=nosys.specs --specs=nano.specs ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + #"LINKER:-lcrt0" + ) elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") target_link_options(${BOARD_TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}" -- cgit v1.3.1 From d157abe77c03c2d058c79585e4700fc1d1d06f9f Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Apr 2024 14:13:48 +0700 Subject: clang samd21 build but has issue as samd51 --- examples/build_system/cmake/cpu/cortex-m0.cmake | 2 +- .../build_system/cmake/cpu/cortex-m0plus.cmake | 6 ++++- hw/bsp/samd21/family.cmake | 27 ++++++++++++---------- hw/bsp/samd51/family.cmake | 1 - 4 files changed, 21 insertions(+), 15 deletions(-) (limited to 'examples') diff --git a/examples/build_system/cmake/cpu/cortex-m0.cmake b/examples/build_system/cmake/cpu/cortex-m0.cmake index ddf0f16af..62019d90d 100644 --- a/examples/build_system/cmake/cpu/cortex-m0.cmake +++ b/examples/build_system/cmake/cpu/cortex-m0.cmake @@ -9,7 +9,7 @@ if (TOOLCHAIN STREQUAL "gcc") elseif (TOOLCHAIN STREQUAL "clang") set(TOOLCHAIN_COMMON_FLAGS --target=arm-none-eabi - -mcpu=cortex-m0plus + -mcpu=cortex-m0 ) set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") diff --git a/examples/build_system/cmake/cpu/cortex-m0plus.cmake b/examples/build_system/cmake/cpu/cortex-m0plus.cmake index 2438ca96a..ddf0f16af 100644 --- a/examples/build_system/cmake/cpu/cortex-m0plus.cmake +++ b/examples/build_system/cmake/cpu/cortex-m0plus.cmake @@ -7,7 +7,11 @@ if (TOOLCHAIN STREQUAL "gcc") set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "clang") - message(FATAL_ERROR "Clang is not supported for this target") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-m0plus + ) + set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") elseif (TOOLCHAIN STREQUAL "iar") set(TOOLCHAIN_COMMON_FLAGS diff --git a/hw/bsp/samd21/family.cmake b/hw/bsp/samd21/family.cmake index a79a25b54..616c8ae45 100644 --- a/hw/bsp/samd21/family.cmake +++ b/hw/bsp/samd21/family.cmake @@ -18,12 +18,23 @@ set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -c \"transport select swd\" -f ta # only need to be built ONCE for all examples function(add_board_target BOARD_TARGET) if (NOT TARGET ${BOARD_TARGET}) + set(LD_FILE_Clang ${LD_FILE_GNU}) + if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) + message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") + endif () + + if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) + set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_samd21.c) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + endif () + add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/gcc/system_samd21.c ${SDK_DIR}/hpl/gclk/hpl_gclk.c ${SDK_DIR}/hpl/pm/hpl_pm.c ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c ${SDK_DIR}/hal/src/hal_atomic.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_DIR} @@ -40,24 +51,16 @@ function(add_board_target BOARD_TARGET) update_board(${BOARD_TARGET}) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") - endif () - - if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) - set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_samd21.c) - endif () - - target_sources(${BOARD_TARGET} PRIVATE - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") target_link_options(${BOARD_TARGET} PUBLIC "LINKER:--script=${LD_FILE_GNU}" -nostartfiles --specs=nosys.specs --specs=nano.specs ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") target_link_options(${BOARD_TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}" diff --git a/hw/bsp/samd51/family.cmake b/hw/bsp/samd51/family.cmake index 08f03f727..8d88cf947 100644 --- a/hw/bsp/samd51/family.cmake +++ b/hw/bsp/samd51/family.cmake @@ -60,7 +60,6 @@ function(add_board_target BOARD_TARGET) elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") target_link_options(${BOARD_TARGET} PUBLIC "LINKER:--script=${LD_FILE_Clang}" - #"LINKER:-lcrt0" ) elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") target_link_options(${BOARD_TARGET} PUBLIC -- cgit v1.3.1 From c8e533e61222aa3ccdda291709abd6215e685d95 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 22 Apr 2024 14:54:35 +0700 Subject: fix build with nrfx v3, though max3421e spi does not seem to work well. --- examples/host/cdc_msc_hid/src/cdc_app.c | 4 +-- hw/bsp/nrf/family.c | 52 ++++++++++++++++++++++++++++----- hw/bsp/nrf/linker/nrf52840_s140_v6.ld | 10 +++++-- hw/bsp/nrf/linker/nrf52840_xxaa.ld | 8 ++--- hw/bsp/nrf/nrfx_config.h | 1 + 5 files changed, 60 insertions(+), 15 deletions(-) (limited to 'examples') diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index e275e7943..4a13f8b27 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -72,7 +72,7 @@ void tuh_cdc_rx_cb(uint8_t idx) { uint32_t count = tuh_cdc_read(idx, buf, bufsize); buf[count] = 0; - printf((char*) buf); + printf("%s", (char*) buf); } // Invoked when a device with CDC interface is mounted @@ -89,7 +89,7 @@ void tuh_cdc_mount_cb(uint8_t idx) { // while eneumerating new cdc device cdc_line_coding_t line_coding = {0}; if (tuh_cdc_get_local_line_coding(idx, &line_coding)) { - printf(" Baudrate: %lu, Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); + printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits); } #else diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 897d27c59..deae64f05 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -107,6 +107,11 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 static void max3421_init(void); static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1); + +#if NRFX_VER > 2 +static nrfx_gpiote_t _gpiote = NRFX_GPIOTE_INSTANCE(0); +#endif + #endif //--------------------------------------------------------------------+ @@ -141,7 +146,7 @@ void board_init(void) { SysTick_Config(SystemCoreClock / 1000); // UART - #if NRFX_VER == 2 + #if NRFX_VER <= 2 nrfx_uarte_config_t uart_cfg = { .pseltxd = UART_TX_PIN, .pselrxd = UART_RX_PIN, @@ -155,7 +160,7 @@ void board_init(void) { .parity = NRF_UARTE_PARITY_EXCLUDED, } }; - #elif NRFX_VER == 3 + #else nrfx_uarte_config_t uart_cfg = { .txd_pin = UART_TX_PIN, .rxd_pin = UART_RX_PIN, @@ -263,7 +268,7 @@ int board_uart_read(uint8_t* buf, int len) { int board_uart_write(void const* buf, int len) { nrfx_err_t err = nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len - #if NRFX_VER == 3 + #if NRFX_VER > 2 ,0 #endif ); @@ -324,8 +329,16 @@ void nrf_error_cb(uint32_t id, uint32_t pc, uint32_t info) { //--------------------------------------------------------------------+ #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 -void max3421_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { - if (!(pin == MAX3421_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO)) return; +#if NRFX_VER <= 2 +void max3421_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action ) { + if (action != NRF_GPIOTE_POLARITY_HITOLO) return; +#else +void max3421_int_handler(nrfx_gpiote_pin_t pin, nrfx_gpiote_trigger_t action, void* p_context) { + (void) p_context; + if (action != NRFX_GPIOTE_TRIGGER_HITOLO) return; +#endif + + if (pin != MAX3421_INTR_PIN) return; tuh_int_handler(1, true); } @@ -341,7 +354,11 @@ static void max3421_init(void) { .sck_pin = MAX3421_SCK_PIN, .mosi_pin = MAX3421_MOSI_PIN, .miso_pin = MAX3421_MISO_PIN, + #if NRFX_VER <= 2 .ss_pin = NRFX_SPIM_PIN_NOT_USED, + #else + .ss_pin = NRF_SPIM_PIN_NOT_CONNECTED, + #endif .ss_active_high = false, .irq_priority = 3, .orc = 0xFF, @@ -355,14 +372,35 @@ static void max3421_init(void) { nrfx_spim_init(&_spi, &cfg, NULL, NULL); // max3421e interrupt pin + #if NRFX_VER <= 2 nrfx_gpiote_init(1); nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true); in_config.pull = NRF_GPIO_PIN_PULLUP; - NVIC_SetPriority(GPIOTE_IRQn, 2); - nrfx_gpiote_in_init(MAX3421_INTR_PIN, &in_config, max3421_int_handler); nrfx_gpiote_trigger_enable(MAX3421_INTR_PIN, true); + #else + nrf_gpio_pin_pull_t intr_pull = NRF_GPIO_PIN_PULLUP; + nrfx_gpiote_trigger_config_t intr_trigger = { + .trigger = NRFX_GPIOTE_TRIGGER_HITOLO, + .p_in_channel = NULL, // sensing mechanism + }; + nrfx_gpiote_handler_config_t intr_handler = { + .handler = max3421_int_handler, + .p_context = NULL, + }; + nrfx_gpiote_input_pin_config_t intr_config = { + .p_pull_config = &intr_pull, + .p_trigger_config = &intr_trigger, + .p_handler_config = &intr_handler, + }; + + nrfx_gpiote_init(&_gpiote, 1); + NVIC_SetPriority(GPIOTE_IRQn, 2); + + nrfx_gpiote_input_configure(&_gpiote, MAX3421_INTR_PIN, &intr_config); + nrfx_gpiote_trigger_enable(&_gpiote, MAX3421_INTR_PIN, true); + #endif } // API to enable/disable MAX3421 INTR pin interrupt diff --git a/hw/bsp/nrf/linker/nrf52840_s140_v6.ld b/hw/bsp/nrf/linker/nrf52840_s140_v6.ld index 7cc94a405..037a14196 100644 --- a/hw/bsp/nrf/linker/nrf52840_s140_v6.ld +++ b/hw/bsp/nrf/linker/nrf52840_s140_v6.ld @@ -5,7 +5,7 @@ SEARCH_DIR(.) MEMORY { - FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0xED000 - 0x26000 + FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0xED000 - 0x26000 /* SRAM required by S132 depend on * - Attribute Table Size @@ -14,7 +14,7 @@ MEMORY * - Concurrent connection peripheral + central + secure links * - Event Len, HVN queue, Write CMD queue */ - RAM (rwx) : ORIGIN = 0x20003400, LENGTH = 0x20040000 - 0x20003400 + RAM (rwx) : ORIGIN = 0x20003400, LENGTH = 0x20040000 - 0x20003400 } SECTIONS @@ -36,3 +36,9 @@ SECTIONS } INSERT AFTER .data; INCLUDE "nrf_common.ld" + +/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ +__tbss_start__ = __tbss_start; +__tbss_end__ = __tbss_end; +__sbss_start__ = __sbss_start; +__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/linker/nrf52840_xxaa.ld b/hw/bsp/nrf/linker/nrf52840_xxaa.ld index 377c248bb..2d20ba7ac 100644 --- a/hw/bsp/nrf/linker/nrf52840_xxaa.ld +++ b/hw/bsp/nrf/linker/nrf52840_xxaa.ld @@ -14,7 +14,7 @@ MEMORY INCLUDE "nrf_common.ld" /* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ -/*__tbss_start__ = __tbss_start;*/ -/*__tbss_end__ = __tbss_end;*/ -/*__sbss_start__ = __sbss_start;*/ -/*__sbss_end__ = __sbss_end;*/ +__tbss_start__ = __tbss_start; +__tbss_end__ = __tbss_end; +__sbss_start__ = __sbss_start; +__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/nrfx_config.h b/hw/bsp/nrf/nrfx_config.h index 95ef33ce4..fbec4192b 100644 --- a/hw/bsp/nrf/nrfx_config.h +++ b/hw/bsp/nrf/nrfx_config.h @@ -6,6 +6,7 @@ #define NRFX_CLOCK_ENABLED 0 #define NRFX_GPIOTE_ENABLED 1 +#define NRFX_GPIOTE0_ENABLED 1 #define NRFX_UARTE_ENABLED 1 #define NRFX_UARTE0_ENABLED 1 -- cgit v1.3.1 From 62331f02070bdb1bec2890885008e9f88b06bdb6 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 22 Apr 2024 15:55:50 +0700 Subject: fix nrfx v3 spim freq when init fix clang build with nrf --- examples/host/cdc_msc_hid/src/msc_app.c | 4 ++-- hw/bsp/nrf/boards/pca10059/pca10059.ld | 8 +++++++- hw/bsp/nrf/boards/pca10095/board.cmake | 1 - hw/bsp/nrf/boards/pca10100/board.cmake | 1 - hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake | 1 - hw/bsp/nrf/family.c | 6 ++++-- hw/bsp/nrf/family.cmake | 18 +++++++++--------- hw/bsp/nrf/linker/nrf52833_xxaa.ld | 20 ++++++++++++++++++++ hw/bsp/nrf/linker/nrf5340_xxaa_application.ld | 21 +++++++++++++++++++++ src/class/cdc/cdc_host.c | 4 ++-- src/host/usbh.c | 2 +- 11 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 hw/bsp/nrf/linker/nrf52833_xxaa.ld create mode 100644 hw/bsp/nrf/linker/nrf5340_xxaa_application.ld (limited to 'examples') diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index e9c9676b8..1d7e18e6e 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -48,8 +48,8 @@ bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_da uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun); - printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size)); - printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); + printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024*1024)/block_size)); + printf("Block Count = %" PRIu32 ", Block Size: %" PRIu32 "\r\n", block_count, block_size); return true; } diff --git a/hw/bsp/nrf/boards/pca10059/pca10059.ld b/hw/bsp/nrf/boards/pca10059/pca10059.ld index 510bfdd8c..adc80f3c4 100644 --- a/hw/bsp/nrf/boards/pca10059/pca10059.ld +++ b/hw/bsp/nrf/boards/pca10059/pca10059.ld @@ -1,7 +1,7 @@ /* Linker script to configure memory regions. */ SEARCH_DIR(.) -GROUP(-lgcc -lc -lnosys) +/*GROUP(-lgcc -lc -lnosys) not compatible with clang*/ MEMORY { @@ -11,3 +11,9 @@ MEMORY INCLUDE "nrf_common.ld" + +/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ +__tbss_start__ = __tbss_start; +__tbss_end__ = __tbss_end; +__sbss_start__ = __sbss_start; +__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/boards/pca10095/board.cmake b/hw/bsp/nrf/boards/pca10095/board.cmake index ca5399a3a..95dd30969 100644 --- a/hw/bsp/nrf/boards/pca10095/board.cmake +++ b/hw/bsp/nrf/boards/pca10095/board.cmake @@ -1,5 +1,4 @@ set(MCU_VARIANT nrf5340_application) -set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf5340_xxaa_application.ld) function(update_board TARGET) target_sources(${TARGET} PRIVATE diff --git a/hw/bsp/nrf/boards/pca10100/board.cmake b/hw/bsp/nrf/boards/pca10100/board.cmake index c30026815..a925dae80 100644 --- a/hw/bsp/nrf/boards/pca10100/board.cmake +++ b/hw/bsp/nrf/boards/pca10100/board.cmake @@ -1,5 +1,4 @@ set(MCU_VARIANT nrf52833) -set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52833_xxaa.ld) function(update_board TARGET) endfunction() diff --git a/hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake b/hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake index 693d7beed..cc370aac8 100644 --- a/hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake +++ b/hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake @@ -1,5 +1,4 @@ set(MCU_VARIANT nrf52840) -set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) function(update_board TARGET) endfunction() diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index deae64f05..aff851ddc 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -356,20 +356,22 @@ static void max3421_init(void) { .miso_pin = MAX3421_MISO_PIN, #if NRFX_VER <= 2 .ss_pin = NRFX_SPIM_PIN_NOT_USED, + .frequency = NRF_SPIM_FREQ_4M, #else .ss_pin = NRF_SPIM_PIN_NOT_CONNECTED, + .frequency = 4000000u, #endif .ss_active_high = false, .irq_priority = 3, .orc = 0xFF, // default setting 4 Mhz, Mode 0, MSB first - .frequency = NRF_SPIM_FREQ_4M, .mode = NRF_SPIM_MODE_0, .bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST, + .miso_pull = NRF_GPIO_PIN_NOPULL, }; // no handler --> blocking - nrfx_spim_init(&_spi, &cfg, NULL, NULL); + TU_ASSERT(NRFX_SUCCESS == nrfx_spim_init(&_spi, &cfg, NULL, NULL), ); // max3421e interrupt pin #if NRFX_VER <= 2 diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 52a6fc196..56ff62bc4 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -30,8 +30,14 @@ set(FAMILY_MCUS NRF5X CACHE INTERNAL "") # only need to be built ONCE for all examples function(add_board_target BOARD_TARGET) if (NOT TARGET ${BOARD_TARGET}) + if (MCU_VARIANT STREQUAL "nrf5340_application") + set(MCU_VARIANT_XXAA "nrf5340_xxaa_application") + else () + set(MCU_VARIANT_XXAA "${MCU_VARIANT}_xxaa") + endif () + if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT}_xxaa.ld) + set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT_XXAA}.ld) endif () set(LD_FILE_Clang ${LD_FILE_GNU}) @@ -50,19 +56,13 @@ function(add_board_target BOARD_TARGET) ${NRFX_DIR}/soc/nrfx_atomic.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) + string(TOUPPER "${MCU_VARIANT_XXAA}" MCU_VARIANT_XXAA_UPPER) target_compile_definitions(${BOARD_TARGET} PUBLIC __STARTUP_CLEAR_BSS CONFIG_GPIO_AS_PINRESET + ${MCU_VARIANT_XXAA_UPPER} ) - if (MCU_VARIANT STREQUAL "nrf52840") - target_compile_definitions(${BOARD_TARGET} PUBLIC NRF52840_XXAA) - elseif (MCU_VARIANT STREQUAL "nrf52833") - target_compile_definitions(${BOARD_TARGET} PUBLIC NRF52833_XXAA) - elseif (MCU_VARIANT STREQUAL "nrf5340_application") - target_compile_definitions(${BOARD_TARGET} PUBLIC NRF5340_XXAA NRF5340_XXAA_APPLICATION) - endif () - if (TRACE_ETM STREQUAL "1") # ENABLE_TRACE will cause system_nrf5x.c to set up ETM trace target_compile_definitions(${BOARD_TARGET} PUBLIC ENABLE_TRACE) diff --git a/hw/bsp/nrf/linker/nrf52833_xxaa.ld b/hw/bsp/nrf/linker/nrf52833_xxaa.ld new file mode 100644 index 000000000..ae4d0e5b3 --- /dev/null +++ b/hw/bsp/nrf/linker/nrf52833_xxaa.ld @@ -0,0 +1,20 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +/*GROUP(-lgcc -lc -lnosys) not compatible with clang*/ + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x20000 + CODE_RAM (rwx) : ORIGIN = 0x800000, LENGTH = 0x20000 +} + + +INCLUDE "nrf_common.ld" + +/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ +__tbss_start__ = __tbss_start; +__tbss_end__ = __tbss_end; +__sbss_start__ = __sbss_start; +__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/linker/nrf5340_xxaa_application.ld b/hw/bsp/nrf/linker/nrf5340_xxaa_application.ld new file mode 100644 index 000000000..31762d0b2 --- /dev/null +++ b/hw/bsp/nrf/linker/nrf5340_xxaa_application.ld @@ -0,0 +1,21 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +/*GROUP(-lgcc -lc) not compatible with clang*/ + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x100000 + EXTFLASH (rx) : ORIGIN = 0x10000000, LENGTH = 0x8000000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x40000 + RAM1 (rwx) : ORIGIN = 0x20040000, LENGTH = 0x3F000 +} + + +INCLUDE "nrf_common.ld" + +/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ +__tbss_start__ = __tbss_start; +__tbss_end__ = __tbss_end; +__sbss_start__ = __sbss_start; +__sbss_end__ = __sbss_end; diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 5bdd41f1f..133a10f6e 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -1079,7 +1079,7 @@ static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) { static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate); - TU_LOG_DRV("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\r\n", baudrate, divisor); + TU_LOG_DRV("CDC FTDI Set BaudRate = %" PRIu32 ", divisor = 0x%04x\r\n", baudrate, divisor); p_cdc->user_control_cb = complete_cb; p_cdc->requested_line_coding.bit_rate = baudrate; @@ -1222,7 +1222,7 @@ static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t co } static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_DRV("CDC CP210x Set BaudRate = %lu\r\n", baudrate); + TU_LOG_DRV("CDC CP210x Set BaudRate = %" PRIu32 "\r\n", baudrate); uint32_t baud_le = tu_htole32(baudrate); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, diff --git a/src/host/usbh.c b/src/host/usbh.c index f8fddf394..7a47f5056 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -704,7 +704,7 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t tusb_control_request_t const * request = &_ctrl_xfer.request; if (XFER_RESULT_SUCCESS != result) { - TU_LOG_USBH("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, daddr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); + TU_LOG_USBH("[%u:%u] Control %s, xferred_bytes = %" PRIu32 "\r\n", rhport, daddr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); TU_LOG_BUF_USBH(request, 8); // terminate transfer if any stage failed -- cgit v1.3.1 From c097c85dcf8e0ef3ea052c146c5f514101827251 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 22 Apr 2024 16:17:22 +0700 Subject: fix print lu format warnings with clang --- examples/device/audio_test_multi_rate/src/main.c | 2 +- examples/device/cdc_uac2/src/uac2_app.c | 4 ++-- examples/device/uac2_headset/src/main.c | 4 ++-- examples/host/bare_api/src/main.c | 2 +- examples/host/cdc_msc_hid_freertos/src/cdc_app.c | 4 ++-- examples/host/cdc_msc_hid_freertos/src/msc_app.c | 4 ++-- examples/host/msc_file_explorer/src/msc_app.c | 6 +++--- src/CMakeLists.txt | 2 +- src/class/cdc/cdc_device.c | 13 ++++++------- src/class/usbtmc/usbtmc_device.c | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 2 +- tools/get_deps.py | 3 ++- 12 files changed, 24 insertions(+), 24 deletions(-) (limited to 'examples') diff --git a/examples/device/audio_test_multi_rate/src/main.c b/examples/device/audio_test_multi_rate/src/main.c index 3e7f40dac..2ff7f10bd 100644 --- a/examples/device/audio_test_multi_rate/src/main.c +++ b/examples/device/audio_test_multi_rate/src/main.c @@ -272,7 +272,7 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * sampFreq = (uint32_t)((audio_control_cur_4_t *)pBuff)->bCur; - TU_LOG2("Clock set current freq: %lu\r\n", sampFreq); + TU_LOG2("Clock set current freq: %" PRIu32 "\r\n", sampFreq); return true; break; diff --git a/examples/device/cdc_uac2/src/uac2_app.c b/examples/device/cdc_uac2/src/uac2_app.c index 98659ea68..c57d98a1a 100644 --- a/examples/device/cdc_uac2/src/uac2_app.c +++ b/examples/device/cdc_uac2/src/uac2_app.c @@ -69,7 +69,7 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t { if (request->bRequest == AUDIO_CS_REQ_CUR) { - TU_LOG1("Clock get current freq %lu\r\n", current_sample_rate); + TU_LOG1("Clock get current freq %" PRIu32 "\r\n", current_sample_rate); audio_control_cur_4_t curf = { (int32_t) tu_htole32(current_sample_rate) }; return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf)); @@ -118,7 +118,7 @@ static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *)buf)->bCur; - TU_LOG1("Clock set current freq: %ld\r\n", current_sample_rate); + TU_LOG1("Clock set current freq: %" PRIu32 "\r\n", current_sample_rate); return true; } diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index fbd7ffe22..0ea6e7025 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -157,7 +157,7 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t { if (request->bRequest == AUDIO_CS_REQ_CUR) { - TU_LOG1("Clock get current freq %lu\r\n", current_sample_rate); + TU_LOG1("Clock get current freq %" PRIu32 "\r\n", current_sample_rate); audio_control_cur_4_t curf = { (int32_t) tu_htole32(current_sample_rate) }; return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf)); @@ -206,7 +206,7 @@ static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *)buf)->bCur; - TU_LOG1("Clock set current freq: %ld\r\n", current_sample_rate); + TU_LOG1("Clock set current freq: %" PRIu32 "\r\n", current_sample_rate); return true; } diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 14725996d..940840a30 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -420,5 +420,5 @@ static void print_utf16(uint16_t *temp_buf, size_t buf_len) { _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); ((uint8_t*) temp_buf)[utf8_len] = '\0'; - printf((char*)temp_buf); + printf("%s", (char*)temp_buf); } diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c index 6ff513be1..7d246af67 100644 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -117,7 +117,7 @@ void tuh_cdc_rx_cb(uint8_t idx) { uint32_t count = tuh_cdc_read(idx, buf, bufsize); buf[count] = 0; - printf((char *) buf); + printf("%s", (char *) buf); } void tuh_cdc_mount_cb(uint8_t idx) { @@ -131,7 +131,7 @@ void tuh_cdc_mount_cb(uint8_t idx) { // otherwise you need to call tuh_cdc_set_line_coding() first cdc_line_coding_t line_coding = { 0 }; if (tuh_cdc_get_local_line_coding(idx, &line_coding)) { - printf(" Baudrate: %lu, Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); + printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits); } #endif diff --git a/examples/host/cdc_msc_hid_freertos/src/msc_app.c b/examples/host/cdc_msc_hid_freertos/src/msc_app.c index ee02ba917..9ffd5d965 100644 --- a/examples/host/cdc_msc_hid_freertos/src/msc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/msc_app.c @@ -47,8 +47,8 @@ bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_dat uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun); - printf("Disk Size: %lu MB\r\n", block_count / ((1024 * 1024) / block_size)); - printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); + printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024 * 1024) / block_size)); + printf("Block Count = %" PRIu32 ", Block Size: %" PRIu32 "\r\n", block_count, block_size); return true; } diff --git a/examples/host/msc_file_explorer/src/msc_app.c b/examples/host/msc_file_explorer/src/msc_app.c index ecea614a2..f323e30f0 100644 --- a/examples/host/msc_file_explorer/src/msc_app.c +++ b/examples/host/msc_file_explorer/src/msc_app.c @@ -114,7 +114,7 @@ bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_da uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun); - printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size)); + printf("Disk Size: %" PRIu32 " MB\r\n", block_count / ((1024*1024)/block_size)); // printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); // For simplicity: we only mount 1 LUN per device @@ -541,10 +541,10 @@ void cli_cmd_ls(EmbeddedCli *cli, char *args, void *context) printf("%-40s", fno.fname); if (fno.fsize < 1024) { - printf("%lu B\r\n", fno.fsize); + printf("%" PRIu32 " B\r\n", fno.fsize); }else { - printf("%lu KB\r\n", fno.fsize / 1024); + printf("%" PRIu32 " KB\r\n", fno.fsize / 1024); } } } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 076e1e1eb..272962332 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -41,7 +41,7 @@ function(add_tinyusb TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../lib/networking ) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") target_compile_options(${TARGET} PRIVATE -Wall -Wextra diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 7ef0530ec..2e0a0c30d 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -43,10 +43,7 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -enum -{ - BULK_PACKET_SIZE = (TUD_OPT_HIGH_SPEED ? 512 : 64) -}; +#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) typedef struct { @@ -176,9 +173,11 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); // flush if queue more than packet size - // may need to suppress -Wunreachable-code since most of the time CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE - if ( (tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE) || ((CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE) && tu_fifo_full(&p_cdc->tx_ff)) ) - { + if ( tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE + #if CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE + || tu_fifo_full(&p_cdc->tx_ff) // check full if fifo size is less than packet size + #endif + ) { tud_cdc_n_write_flush(itf); } diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 286cbe108..f6cddfbd7 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -360,7 +360,7 @@ uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, // processing a command (such as a clear). Returns true if it was // in the NAK state and successfully transitioned to the ACK wait // state. -bool tud_usbtmc_start_bus_read() +bool tud_usbtmc_start_bus_read(void) { usbtmcd_state_enum oldState = usbtmc_state.state; switch(oldState) diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 56e7f39a0..2fe721d6b 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -147,7 +147,7 @@ static void start_dma(volatile uint32_t* reg_startep) { static void edpt_dma_start(volatile uint32_t* reg_startep) { if (atomic_flag_test_and_set(&_dcd.dma_running)) { - usbd_defer_func((osal_task_func_t) edpt_dma_start, (void*) (uintptr_t) reg_startep, true); + usbd_defer_func((osal_task_func_t)(uintptr_t ) edpt_dma_start, (void*) (uintptr_t) reg_startep, true); } else { start_dma(reg_startep); } diff --git a/tools/get_deps.py b/tools/get_deps.py index cfa60002a..e08246178 100644 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -177,7 +177,8 @@ deps_optional = { '20285262657d1b482d132d20d755c8c330d55c1f', 'imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf ra saml2x' 'stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5' - 'stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb'], + 'stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb' + 'sam3x samd11 samd21 samd51 same5x same7x saml2x samg'], 'lib/sct_neopixel': ['https://github.com/gsteiert/sct_neopixel.git', 'e73e04ca63495672d955f9268e003cffe168fcd8', 'lpc55'], -- cgit v1.3.1 From db30eee0fcacda2b2f3f208ddf5ab9be723129d8 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 22 Apr 2024 18:08:41 +0700 Subject: clang tested with mcb1800, add heap to lpc18 linker --- examples/host/msc_file_explorer/src/main.c | 17 +++++------- examples/host/msc_file_explorer/src/msc_app.c | 1 - hw/bsp/lpc18/boards/lpcxpresso18s37/lpc1837.ld | 34 ++++++++++++++++------- hw/bsp/lpc18/boards/mcb1800/lpc1857.ld | 37 ++++++++++++++++++-------- hw/bsp/lpc18/family.cmake | 8 +++--- hw/bsp/nrf/family.cmake | 3 +-- src/portable/ehci/ehci.c | 2 +- 7 files changed, 64 insertions(+), 38 deletions(-) (limited to 'examples') diff --git a/examples/host/msc_file_explorer/src/main.c b/examples/host/msc_file_explorer/src/main.c index 73f3e9eb5..f6b6810f5 100644 --- a/examples/host/msc_file_explorer/src/main.c +++ b/examples/host/msc_file_explorer/src/main.c @@ -72,8 +72,7 @@ extern bool msc_app_init(void); extern void msc_app_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); printf("TinyUSB Host MassStorage Explorer Example\r\n"); @@ -87,8 +86,7 @@ int main(void) msc_app_init(); - while (1) - { + while (1) { // tinyusb host task tuh_task(); @@ -103,28 +101,25 @@ int main(void) // TinyUSB Callbacks //--------------------------------------------------------------------+ -void tuh_mount_cb(uint8_t dev_addr) -{ +void tuh_mount_cb(uint8_t dev_addr) { (void) dev_addr; } -void tuh_umount_cb(uint8_t dev_addr) -{ +void tuh_umount_cb(uint8_t dev_addr) { (void) dev_addr; } //--------------------------------------------------------------------+ // Blinking Task //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { const uint32_t interval_ms = 1000; static uint32_t start_ms = 0; static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < interval_ms) return; // not enough time + if (board_millis() - start_ms < interval_ms) return; // not enough time start_ms += interval_ms; board_led_write(led_state); diff --git a/examples/host/msc_file_explorer/src/msc_app.c b/examples/host/msc_file_explorer/src/msc_app.c index f323e30f0..ddd39c674 100644 --- a/examples/host/msc_file_explorer/src/msc_app.c +++ b/examples/host/msc_file_explorer/src/msc_app.c @@ -95,7 +95,6 @@ void msc_app_task(void) // //--------------------------------------------------------------------+ - bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) { msc_cbw_t const* cbw = cb_data->cbw; diff --git a/hw/bsp/lpc18/boards/lpcxpresso18s37/lpc1837.ld b/hw/bsp/lpc18/boards/lpcxpresso18s37/lpc1837.ld index f1a3add8f..8562a6e71 100644 --- a/hw/bsp/lpc18/boards/lpcxpresso18s37/lpc1837.ld +++ b/hw/bsp/lpc18/boards/lpcxpresso18s37/lpc1837.ld @@ -311,6 +311,20 @@ SECTIONS PROVIDE(end = .); } > RamLoc40 AT> RamLoc40 /* > RamLoc32 AT> RamLoc32 */ + .heap (NOLOAD): { + __heap_start = .; + __HeapBase = .; + __heap_base = .; + __end = .; + PROVIDE(end = .); + PROVIDE(_end = .); + PROVIDE(__end__ = .); + KEEP(*(.heap*)) + __HeapLimit = .; + __heap_limit = .; + __heap_end = .; + } > RamLoc40 + /* NOINIT section for RamLoc40 */ .noinit_RAM2 (NOLOAD) : ALIGN(4) { @@ -383,15 +397,17 @@ SECTIONS PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RamLoc32 - 0); /* ## Create checksum value (used in startup) ## */ - PROVIDE(__valid_user_code_checksum = 0 - - (_vStackTop - + (ResetISR + 1) - + (NMI_Handler + 1) - + (HardFault_Handler + 1) - + (( DEFINED(MemManage_Handler) ? MemManage_Handler : 0 ) + 1) /* MemManage_Handler may not be defined */ - + (( DEFINED(BusFault_Handler) ? BusFault_Handler : 0 ) + 1) /* BusFault_Handler may not be defined */ - + (( DEFINED(UsageFault_Handler) ? UsageFault_Handler : 0 ) + 1) /* UsageFault_Handler may not be defined */ - ) ); + /* This cause issue with clang linker, so it is disabled */ + /* MemManage_Handler, BusFault_Handler, UsageFault_Handler may not be defined */ +/* PROVIDE(__valid_user_code_checksum = 0 -*/ +/* (_vStackTop*/ +/* + (ResetISR + 1)*/ +/* + (NMI_Handler + 1)*/ +/* + (HardFault_Handler + 1)*/ +/* + (( DEFINED(MemManage_Handler) ? MemManage_Handler : 0 ) + 1)*/ +/* + (( DEFINED(BusFault_Handler) ? BusFault_Handler : 0 ) + 1)*/ +/* + (( DEFINED(UsageFault_Handler) ? UsageFault_Handler : 0 ) + 1)*/ +/* ) );*/ /* Provide basic symbols giving location and size of main text * block, including initial values of RW data sections. Note that diff --git a/hw/bsp/lpc18/boards/mcb1800/lpc1857.ld b/hw/bsp/lpc18/boards/mcb1800/lpc1857.ld index 837dec364..02ea1088e 100644 --- a/hw/bsp/lpc18/boards/mcb1800/lpc1857.ld +++ b/hw/bsp/lpc18/boards/mcb1800/lpc1857.ld @@ -255,7 +255,6 @@ SECTIONS *(COMMON) . = ALIGN(4) ; _ebss = .; - PROVIDE(end = .); } > RamLoc40 /* RamLoc32 */ /* NOINIT section for RamLoc40 */ @@ -266,6 +265,20 @@ SECTIONS . = ALIGN(4) ; } > RamLoc40 + .heap (NOLOAD): { + __heap_start = .; + __HeapBase = .; + __heap_base = .; + __end = .; + PROVIDE(end = .); + PROVIDE(_end = .); + PROVIDE(__end__ = .); + KEEP(*(.heap*)) + __HeapLimit = .; + __heap_limit = .; + __heap_end = .; + } > RamLoc40 + /* NOINIT section for RamAHB32 */ .noinit_RAM3 (NOLOAD) : ALIGN(4) { @@ -298,19 +311,21 @@ SECTIONS . = ALIGN(4) ; _end_noinit = .; } > RamLoc32 - PROVIDE(_pvHeapStart = DEFINED(__user_heap_base) ? __user_heap_base : .); + PROVIDE(_vStackTop = DEFINED(__user_stack_top) ? __user_stack_top : __top_RamLoc32 - 0); /* ## Create checksum value (used in startup) ## */ - PROVIDE(__valid_user_code_checksum = 0 - - (_vStackTop - + (ResetISR + 1) - + (NMI_Handler + 1) - + (HardFault_Handler + 1) - + (( DEFINED(MemManage_Handler) ? MemManage_Handler : 0 ) + 1) /* MemManage_Handler may not be defined */ - + (( DEFINED(BusFault_Handler) ? BusFault_Handler : 0 ) + 1) /* BusFault_Handler may not be defined */ - + (( DEFINED(UsageFault_Handler) ? UsageFault_Handler : 0 ) + 1) /* UsageFault_Handler may not be defined */ - ) ); + /* This cause issue with clang linker, so it is disabled */ + /* MemManage_Handler, BusFault_Handler, UsageFault_Handler may not be defined */ +/* PROVIDE(__valid_user_code_checksum = 0 -*/ +/* (_vStackTop*/ +/* + (ResetISR + 1)*/ +/* + (NMI_Handler + 1)*/ +/* + (HardFault_Handler + 1)*/ +/* + (( DEFINED(MemManage_Handler) ? MemManage_Handler : 0 ) + 1)*/ +/* + (( DEFINED(BusFault_Handler) ? BusFault_Handler : 0 ) + 1)*/ +/* + (( DEFINED(UsageFault_Handler) ? UsageFault_Handler : 0 ) + 1)*/ +/* ) );*/ /* Provide basic symbols giving location and size of main text * block, including initial values of RW data sections. Note that diff --git a/hw/bsp/lpc18/family.cmake b/hw/bsp/lpc18/family.cmake index 78f4c510b..bf8efabba 100644 --- a/hw/bsp/lpc18/family.cmake +++ b/hw/bsp/lpc18/family.cmake @@ -47,9 +47,11 @@ function(add_board_target BOARD_TARGET) if (CMAKE_C_COMPILER_ID STREQUAL "GNU") target_link_options(${BOARD_TARGET} PUBLIC "LINKER:--script=${LD_FILE_GNU}" - # nanolib - --specs=nosys.specs - --specs=nano.specs + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" ) elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") target_link_options(${BOARD_TARGET} PUBLIC diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 56ff62bc4..1d6702720 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -39,7 +39,6 @@ function(add_board_target BOARD_TARGET) if (NOT DEFINED LD_FILE_GNU) set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT_XXAA}.ld) endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) set(STARTUP_FILE_GNU ${NRFX_DIR}/mdk/gcc_startup_${MCU_VARIANT}.S) @@ -89,7 +88,7 @@ function(add_board_target BOARD_TARGET) ) elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" + "LINKER:--script=${LD_FILE_GNU}" -L${NRFX_DIR}/mdk ) elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index e145cbb1b..01bbf62bf 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -92,7 +92,7 @@ CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data; //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ -#if CFG_TUSB_DEBUG >= (EHCI_DBG + 1) +#if 0 && CFG_TUSB_DEBUG >= (EHCI_DBG + 1) static inline void print_portsc(ehci_registers_t* regs) { TU_LOG_HEX(EHCI_DBG, regs->portsc); TU_LOG(EHCI_DBG, " Connect Status : %u\r\n", regs->portsc_bm.current_connect_status); -- cgit v1.3.1 From 3fd82cfe225cb05c106eccac830bbcf19206bdb1 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Apr 2024 10:57:45 +0700 Subject: clang work with lpc55 --- examples/device/msc_dual_lun/src/main.c | 25 ++++------ hw/bsp/family_support.cmake | 2 +- hw/bsp/lpc55/family.c | 66 +++++++++++++++----------- hw/bsp/lpc55/family.cmake | 69 +++++++++++++--------------- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 2 +- 5 files changed, 83 insertions(+), 81 deletions(-) (limited to 'examples') diff --git a/examples/device/msc_dual_lun/src/main.c b/examples/device/msc_dual_lun/src/main.c index de402d3da..aabd0bf8a 100644 --- a/examples/device/msc_dual_lun/src/main.c +++ b/examples/device/msc_dual_lun/src/main.c @@ -39,7 +39,7 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -50,8 +50,7 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; void led_blinking_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port @@ -61,8 +60,7 @@ int main(void) board_init_after_tusb(); } - while (1) - { + while (1) { tud_task(); // tinyusb device task led_blinking_task(); } @@ -73,42 +71,37 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index d86ecc0a2..5f0653646 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -239,7 +239,7 @@ function(family_configure_common TARGET RTOS) if (NOT TARGET segger_rtt) add_library(segger_rtt STATIC ${TOP}/lib/SEGGER_RTT/RTT/SEGGER_RTT.c) target_include_directories(segger_rtt PUBLIC ${TOP}/lib/SEGGER_RTT/RTT) - #target_compile_definitions(segger_rtt PUBLIC SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) +# target_compile_definitions(segger_rtt PUBLIC SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) endif() target_link_libraries(${TARGET} PUBLIC segger_rtt) endif () diff --git a/hw/bsp/lpc55/family.c b/hw/bsp/lpc55/family.c index 0fd85988a..cfd5b7032 100644 --- a/hw/bsp/lpc55/family.c +++ b/hw/bsp/lpc55/family.c @@ -72,13 +72,11 @@ //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void USB0_IRQHandler(void) -{ +void USB0_IRQHandler(void) { tud_int_handler(0); } -void USB1_IRQHandler(void) -{ +void USB1_IRQHandler(void) { tud_int_handler(1); } @@ -92,8 +90,7 @@ settings: sources: - {id: SYSCON.fro_hf.outFreq, value: 96 MHz} ******************************************************************/ -void BootClockFROHF96M(void) -{ +void BootClockFROHF96M(void) { /*!< Set up the clock sources */ /*!< Set up FRO */ POWER_DisablePD(kPDRUNCFG_PD_FRO192M); /*!< Ensure FRO is on */ @@ -116,8 +113,7 @@ void BootClockFROHF96M(void) SystemCoreClock = 96000000U; } -void board_init(void) -{ +void board_init(void) { // Enable IOCON clock CLOCK_EnableClock(kCLOCK_Iocon); @@ -138,7 +134,7 @@ void board_init(void) // LED IOCON_PinMuxSet(IOCON, LED_PORT, LED_PIN, IOCON_PIO_DIG_FUNC0_EN); - gpio_pin_config_t const led_config = { kGPIO_DigitalOutput, 1}; + gpio_pin_config_t const led_config = {kGPIO_DigitalOutput, 1}; GPIO_PinInit(GPIO, LED_PORT, LED_PIN, &led_config); board_led_write(0); @@ -157,7 +153,7 @@ void board_init(void) // Button IOCON_PinMuxSet(IOCON, BUTTON_PORT, BUTTON_PIN, IOCON_PIO_DIG_FUNC0_EN); - gpio_pin_config_t const button_config = { kGPIO_DigitalInput, 0}; + gpio_pin_config_t const button_config = {kGPIO_DigitalInput, 0}; GPIO_PinInit(GPIO, BUTTON_PORT, BUTTON_PIN, &button_config); #ifdef UART_DEV @@ -170,8 +166,8 @@ void board_init(void) usart_config_t uart_config; USART_GetDefaultConfig(&uart_config); uart_config.baudRate_Bps = CFG_BOARD_UART_BAUDRATE; - uart_config.enableTx = true; - uart_config.enableRx = true; + uart_config.enableTx = true; + uart_config.enableRx = true; USART_Init(UART_DEV, &uart_config, 12000000); #endif @@ -250,9 +246,8 @@ void board_init(void) // Board porting API //--------------------------------------------------------------------+ -void board_led_write(bool state) -{ - GPIO_PinWrite(GPIO, LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +void board_led_write(bool state) { + GPIO_PinWrite(GPIO, LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); #ifdef NEOPIXEL_PIN if (state) { @@ -266,33 +261,50 @@ void board_led_write(bool state) #endif } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { // active low return BUTTON_STATE_ACTIVE == GPIO_PinRead(GPIO, BUTTON_PORT, BUTTON_PIN); } -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; +int board_uart_read(uint8_t* buf, int len) { + (void) buf; + (void) len; return 0; } -int board_uart_write(void const * buf, int len) -{ - USART_WriteBlocking(UART_DEV, (uint8_t const *) buf, len); +int board_uart_write(void const* buf, int len) { + USART_WriteBlocking(UART_DEV, (uint8_t const*) buf, len); return len; } #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -void SysTick_Handler(void) -{ + +void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) -{ +uint32_t board_millis(void) { return system_ticks; } #endif + + +#ifndef __ICCARM__ +// Implement _start() since we use linker flag '-nostartfiles'. +// Requires defined __STARTUP_CLEAR_BSS, +extern int main(void); + +TU_ATTR_UNUSED void _start(void) { + // called by startup code + main(); + while (1) {} +} + +#ifdef __clang__ +void _exit (int __status) { + while (1) {} +} +#endif + +#endif diff --git a/hw/bsp/lpc55/family.cmake b/hw/bsp/lpc55/family.cmake index 75dabfe5a..21c57fc1f 100644 --- a/hw/bsp/lpc55/family.cmake +++ b/hw/bsp/lpc55/family.cmake @@ -1,9 +1,5 @@ include_guard() -if (NOT BOARD) - message(FATAL_ERROR "BOARD not specified") -endif () - set(SDK_DIR ${TOP}/hw/mcu/nxp/mcux-sdk) set(CMSIS_DIR ${TOP}/lib/CMSIS_5) @@ -30,9 +26,20 @@ set(HOST_PORT $) function(add_board_target BOARD_TARGET) if (TARGET ${BOARD_TARGET}) return() + endif() + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + + if (NOT DEFINED STARTUP_FILE_GNU) + set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) + endif () + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) add_library(${BOARD_TARGET} STATIC + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} # driver ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c ${SDK_DIR}/drivers/common/fsl_common_arm.c @@ -44,12 +51,27 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_power.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_reset.c ) - + target_include_directories(${BOARD_TARGET} PUBLIC + ${TOP}/lib/sct_neopixel + # driver + ${SDK_DIR}/drivers/common + ${SDK_DIR}/drivers/flexcomm + ${SDK_DIR}/drivers/lpc_iocon + ${SDK_DIR}/drivers/lpc_gpio + ${SDK_DIR}/drivers/lpuart + ${SDK_DIR}/drivers/sctimer + # mcu + ${SDK_DIR}/devices/${MCU_VARIANT} + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers + ${CMSIS_DIR}/CMSIS/Core/Include + ) target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUSB_MEM_ALIGN=TU_ATTR_ALIGNED\(64\) BOARD_TUD_RHPORT=${PORT} BOARD_TUH_RHPORT=${HOST_PORT} + __STARTUP_CLEAR_BSS ) + # Port 0 is Fullspeed, Port 1 is Highspeed. Port1 controller can only access USB_SRAM if (PORT EQUAL 1) target_compile_definitions(${BOARD_TARGET} PUBLIC @@ -65,42 +87,17 @@ function(add_board_target BOARD_TARGET) ) endif () - target_include_directories(${BOARD_TARGET} PUBLIC - ${TOP}/lib/sct_neopixel - # driver - ${SDK_DIR}/drivers/common - ${SDK_DIR}/drivers/flexcomm - ${SDK_DIR}/drivers/lpc_iocon - ${SDK_DIR}/drivers/lpc_gpio - ${SDK_DIR}/drivers/lpuart - ${SDK_DIR}/drivers/sctimer - # mcu - ${CMSIS_DIR}/CMSIS/Core/Include - ${SDK_DIR}/devices/${MCU_VARIANT} - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers - ) - update_board(${BOARD_TARGET}) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) - endif () - - if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) - set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) - endif () - - target_sources(${BOARD_TARGET} PUBLIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") target_link_options(${BOARD_TARGET} PUBLIC - # linker file "LINKER:--script=${LD_FILE_GNU}" - # nanolib - --specs=nosys.specs - --specs=nano.specs + --specs=nosys.specs --specs=nano.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" ) elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") target_link_options(${BOARD_TARGET} PUBLIC diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index f4ed09d83..022904a3a 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -239,7 +239,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(ep_cmd_sts_t* ep_cs, bool is_ return is_highspeed ? (ep_cs[0].cmd_sts.type && !ep_cs[0].cmd_sts.rf_tv) : ep_cs->cmd_sts.type; } -TU_ATTR_ALWAYS_INLINE static inline bool ep_is_bulk(ep_cmd_sts_t* ep_cs) { +TU_ATTR_ALWAYS_INLINE TU_ATTR_UNUSED static inline bool ep_is_bulk(ep_cmd_sts_t* ep_cs) { return (ep_cs[0].cmd_sts.type == 0) && (ep_cs[0].cmd_sts.rf_tv == 0); } -- cgit v1.3.1 From b67cb26e51c7f31db0cf71c6c1ce5430bbbbb7f5 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Apr 2024 16:17:33 +0700 Subject: change hil board s3 devkitm (devkitc seems to have usb issue with cp2104) --- .github/workflows/build_aarch64.yml | 2 +- .github/workflows/build_cmake.yml | 4 +- .github/workflows/build_esp.yml | 6 +-- .github/workflows/build_renesas.yml | 2 +- .github/workflows/build_riscv.yml | 2 +- examples/build_system/make/make.mk | 60 ++++++++++++------------- examples/build_system/make/toolchain/arm_gcc.mk | 3 ++ examples/build_system/make/toolchain/arm_iar.mk | 2 + examples/device/cdc_msc_freertos/Makefile | 2 +- examples/device/hid_composite_freertos/Makefile | 2 +- examples/host/cdc_msc_hid_freertos/Makefile | 2 +- hw/bsp/board.c | 13 +++--- hw/bsp/board_api.h | 1 + test/hil/hil_pi4.json | 6 +-- 14 files changed, 56 insertions(+), 51 deletions(-) (limited to 'examples') diff --git a/.github/workflows/build_aarch64.yml b/.github/workflows/build_aarch64.yml index e5dbf9494..237692498 100644 --- a/.github/workflows/build_aarch64.yml +++ b/.github/workflows/build_aarch64.yml @@ -47,7 +47,7 @@ jobs: run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz - name: Cache Toolchain - uses: actions/cache@v3 + uses: actions/cache@v4 id: cache-toolchain with: path: ~/cache/ diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index 1f74bda70..65de47e8d 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -168,7 +168,7 @@ jobs: run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-17.0.1/LLVMEmbeddedToolchainForArm-17.0.1-Linux-x86_64.tar.xz - name: Cache Toolchain - uses: actions/cache@v3 + uses: actions/cache@v4 id: cache-toolchain with: path: ~/cache/ @@ -216,7 +216,7 @@ jobs: run: echo >> $GITHUB_ENV TOOLCHAIN_URL=http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2 - name: Cache Toolchain - uses: actions/cache@v3 + uses: actions/cache@v4 id: cache-toolchain with: path: ~/cache/ diff --git a/.github/workflows/build_esp.yml b/.github/workflows/build_esp.yml index d283c6535..4108a58a5 100644 --- a/.github/workflows/build_esp.yml +++ b/.github/workflows/build_esp.yml @@ -34,7 +34,7 @@ jobs: # ESP32-S2 - 'espressif_kaluga_1' # ESP32-S3 - - 'espressif_s3_devkitc' + - 'espressif_s3_devkitm' steps: - name: Setup Python uses: actions/setup-python@v5 @@ -51,7 +51,7 @@ jobs: run: docker run --rm -v $PWD:/project -w /project espressif/idf:v5.1.1 python3 tools/build_esp32.py ${{ matrix.board }} - name: Upload Artifacts for Hardware Testing - if: matrix.board == 'espressif_s3_devkitc' && github.repository_owner == 'hathach' + if: matrix.board == 'espressif_s3_devkitm' && github.repository_owner == 'hathach' uses: actions/upload-artifact@v4 with: name: ${{ matrix.board }} @@ -75,7 +75,7 @@ jobs: fail-fast: false matrix: board: - - 'espressif_s3_devkitc' + - 'espressif_s3_devkitm' steps: - name: Clean workspace run: | diff --git a/.github/workflows/build_renesas.yml b/.github/workflows/build_renesas.yml index ec06c9426..fbc12d285 100644 --- a/.github/workflows/build_renesas.yml +++ b/.github/workflows/build_renesas.yml @@ -46,7 +46,7 @@ jobs: run: echo >> $GITHUB_ENV TOOLCHAIN_URL=http://gcc-renesas.com/downloads/get.php?f=rx/8.3.0.202004-gnurx/gcc-8.3.0.202004-GNURX-ELF.run - name: Cache Toolchain - uses: actions/cache@v3 + uses: actions/cache@v4 id: cache-toolchain with: path: ~/cache/ diff --git a/.github/workflows/build_riscv.yml b/.github/workflows/build_riscv.yml index e891a3a51..7f5031ff1 100644 --- a/.github/workflows/build_riscv.yml +++ b/.github/workflows/build_riscv.yml @@ -48,7 +48,7 @@ jobs: run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v10.1.0-1.1/xpack-riscv-none-embed-gcc-10.1.0-1.1-linux-x64.tar.gz - name: Cache Toolchain - uses: actions/cache@v3 + uses: actions/cache@v4 id: cache-toolchain with: path: ~/cache/ diff --git a/examples/build_system/make/make.mk b/examples/build_system/make/make.mk index 772befca4..2437b8766 100644 --- a/examples/build_system/make/make.mk +++ b/examples/build_system/make/make.mk @@ -15,6 +15,8 @@ TOP = $(abspath $(subst make.mk,../../..,$(THIS_MAKEFILE))) # Set CURRENT_PATH to the relative path from TOP to the current directory, ie examples/device/cdc_msc_freertos CURRENT_PATH = $(subst $(TOP)/,,$(abspath .)) +#-------------- Linux/Windows ------------ + # Detect whether shell style is windows or not # https://stackoverflow.com/questions/714100/os-detecting-makefile/52062069#52062069 ifeq '$(findstring ;,$(PATH))' ';' @@ -26,13 +28,18 @@ CMDEXE := 1 SHELL := cmd.exe endif -# Handy check parameter function -check_defined = \ - $(strip $(foreach 1,$1, \ - $(call __check_defined,$1,$(strip $(value 2))))) -__check_defined = \ - $(if $(value $1),, \ - $(error Undefined make flag: $1$(if $2, ($2)))) +ifeq ($(CMDEXE),1) + CP = copy + RM = del + MKDIR = mkdir + PYTHON = python +else + CP = cp + RM = rm + MKDIR = mkdir + PYTHON = python3 +endif + # Build directory BUILD := _build/$(BOARD) @@ -44,8 +51,8 @@ BIN := $(TOP)/_bin/$(BOARD)/$(notdir $(CURDIR)) # Board without family ifneq ($(wildcard $(TOP)/hw/bsp/$(BOARD)/board.mk),) -BOARD_PATH := hw/bsp/$(BOARD) -FAMILY := + BOARD_PATH := hw/bsp/$(BOARD) + FAMILY := endif # Board within family @@ -68,31 +75,12 @@ else SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c)) endif -#-------------- Toolchain ------------ - -# Supported toolchain: gcc, iar +#------------------------------------------------------------- +# Toolchain +# Can be changed via TOOLCHAIN=gcc|iar or CC=arm-none-eabi-gcc|iccarm|clang +#------------------------------------------------------------- TOOLCHAIN ?= gcc -# Can be set by board, default to ARM GCC -CROSS_COMPILE ?= arm-none-eabi- - -ifeq ($(TOOLCHAIN),iar) -CC := iccarm -USE_IAR = 1 -endif - -ifeq ($(CMDEXE),1) - CP = copy - RM = del - MKDIR = mkdir - PYTHON = python -else - CP = cp - RM = rm - MKDIR = mkdir - PYTHON = python3 -endif - #-------------- Source files and compiler flags -------------- # tinyusb makefile include $(TOP)/src/tinyusb.mk @@ -143,3 +131,11 @@ endif # toolchain specific include ${TOP}/examples/build_system/make/toolchain/arm_$(TOOLCHAIN).mk + +# Handy check parameter function +check_defined = \ + $(strip $(foreach 1,$1, \ + $(call __check_defined,$1,$(strip $(value 2))))) +__check_defined = \ + $(if $(value $1),, \ + $(error Undefined make flag: $1$(if $2, ($2)))) diff --git a/examples/build_system/make/toolchain/arm_gcc.mk b/examples/build_system/make/toolchain/arm_gcc.mk index ed5ddc970..c34581ae2 100644 --- a/examples/build_system/make/toolchain/arm_gcc.mk +++ b/examples/build_system/make/toolchain/arm_gcc.mk @@ -1,5 +1,8 @@ # makefile for arm gcc toolchain +# Can be set by family, default to ARM GCC +CROSS_COMPILE ?= arm-none-eabi- + CC = $(CROSS_COMPILE)gcc CXX = $(CROSS_COMPILE)g++ AS = $(CC) -x assembler-with-cpp diff --git a/examples/build_system/make/toolchain/arm_iar.mk b/examples/build_system/make/toolchain/arm_iar.mk index 04c9f22b3..17967b41a 100644 --- a/examples/build_system/make/toolchain/arm_iar.mk +++ b/examples/build_system/make/toolchain/arm_iar.mk @@ -1,4 +1,6 @@ # makefile for arm iar toolchain + +CC = iccarm AS = iasmarm LD = ilinkarm OBJCOPY = ielftool --silent diff --git a/examples/device/cdc_msc_freertos/Makefile b/examples/device/cdc_msc_freertos/Makefile index 13f336f99..fe3fb6482 100644 --- a/examples/device/cdc_msc_freertos/Makefile +++ b/examples/device/cdc_msc_freertos/Makefile @@ -1,7 +1,7 @@ include ../../build_system/make/make.mk FREERTOS_SRC = lib/FreeRTOS-Kernel -FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(USE_IAR),IAR,GCC) +FREERTOS_PORTABLE_PATH = $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC) INC += \ src \ diff --git a/examples/device/hid_composite_freertos/Makefile b/examples/device/hid_composite_freertos/Makefile index add9e9814..88d602393 100644 --- a/examples/device/hid_composite_freertos/Makefile +++ b/examples/device/hid_composite_freertos/Makefile @@ -3,7 +3,7 @@ DEPS_SUBMODULES += lib/FreeRTOS-Kernel include ../../build_system/make/make.mk FREERTOS_SRC = lib/FreeRTOS-Kernel -FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(USE_IAR),IAR,GCC) +FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC) INC += \ src \ diff --git a/examples/host/cdc_msc_hid_freertos/Makefile b/examples/host/cdc_msc_hid_freertos/Makefile index 5351a6248..bf4725f47 100644 --- a/examples/host/cdc_msc_hid_freertos/Makefile +++ b/examples/host/cdc_msc_hid_freertos/Makefile @@ -1,7 +1,7 @@ include ../../build_system/make/make.mk FREERTOS_SRC = lib/FreeRTOS-Kernel -FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(USE_IAR),IAR,GCC) +FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC) INC += \ src \ diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 996ac9263..cdef5e1e5 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -25,6 +25,14 @@ #include "board_api.h" +//--------------------------------------------------------------------+ +// Board API +//--------------------------------------------------------------------+ +int board_getchar(void) { + char c; + return (sys_read(0, &c, 1) > 0) ? (int) c : (-1); +} + //--------------------------------------------------------------------+ // newlib read()/write() retarget //--------------------------------------------------------------------+ @@ -126,8 +134,3 @@ FILE *const stdin = &__stdio; __strong_reference(stdin, stdout); __strong_reference(stdin, stderr); #endif - -int board_getchar(void) { - char c; - return (sys_read(0, &c, 1) > 0) ? (int) c : (-1); -} diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 418ce3551..f21a32371 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -142,6 +142,7 @@ static inline size_t board_usb_get_serial(uint16_t desc_str1[], size_t max_chars uint8_t uid[16] TU_ATTR_ALIGNED(4); size_t uid_len; + // TODO work with make, but not working with esp32s3 cmake if ( board_get_unique_id ) { uid_len = board_get_unique_id(uid, sizeof(uid)); }else { diff --git a/test/hil/hil_pi4.json b/test/hil/hil_pi4.json index 17d9ff1fa..8aff81910 100644 --- a/test/hil/hil_pi4.json +++ b/test/hil/hil_pi4.json @@ -8,13 +8,13 @@ "flasher_args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\"" }, { - "name": "espressif_s3_devkitc", - "uid": "7CDFA1E073CC", + "name": "espressif_s3_devkitm", + "uid": "84F703C084E4", "tests": [ "cdc_msc_freertos", "hid_composite_freertos" ], "flasher": "esptool", - "flasher_sn": "461cb8d7decdeb119be9b506e93fd3f1", + "flasher_sn": "3ea619acd1cdeb11a0a0b806e93fd3f1", "flasher_args": "-b 1500000" }, { -- cgit v1.3.1 From a7bf0e3e7f7799c28e370826710810033c117744 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Apr 2024 19:21:26 +0700 Subject: clang make work for samd21 --- examples/build_system/make/cpu/cortex-m0.mk | 8 +++ examples/build_system/make/cpu/cortex-m0plus.mk | 8 +++ examples/build_system/make/cpu/cortex-m23.mk | 8 +++ examples/build_system/make/cpu/cortex-m3.mk | 13 ++-- .../build_system/make/cpu/cortex-m33-nodsp-nofp.mk | 14 +++- examples/build_system/make/cpu/cortex-m33.mk | 12 +++- examples/build_system/make/cpu/cortex-m4.mk | 9 +++ examples/build_system/make/cpu/cortex-m7.mk | 8 +++ examples/build_system/make/cpu/msp430.mk | 4 ++ examples/build_system/make/make.mk | 28 ++++++-- examples/build_system/make/rules.mk | 2 +- examples/build_system/make/toolchain/arm_clang.mk | 10 +++ examples/build_system/make/toolchain/arm_gcc.mk | 68 +------------------ .../build_system/make/toolchain/arm_gcc_rules.mk | 75 --------------------- .../build_system/make/toolchain/arm_iar_rules.mk | 44 ------------- .../build_system/make/toolchain/clang_rules.mk | 1 + examples/build_system/make/toolchain/gcc_common.mk | 71 ++++++++++++++++++++ examples/build_system/make/toolchain/gcc_rules.mk | 76 ++++++++++++++++++++++ examples/build_system/make/toolchain/iar_rules.mk | 44 +++++++++++++ hw/bsp/samd21/family.mk | 7 +- 20 files changed, 306 insertions(+), 204 deletions(-) create mode 100644 examples/build_system/make/toolchain/arm_clang.mk delete mode 100644 examples/build_system/make/toolchain/arm_gcc_rules.mk delete mode 100644 examples/build_system/make/toolchain/arm_iar_rules.mk create mode 100644 examples/build_system/make/toolchain/clang_rules.mk create mode 100644 examples/build_system/make/toolchain/gcc_common.mk create mode 100644 examples/build_system/make/toolchain/gcc_rules.mk create mode 100644 examples/build_system/make/toolchain/iar_rules.mk (limited to 'examples') diff --git a/examples/build_system/make/cpu/cortex-m0.mk b/examples/build_system/make/cpu/cortex-m0.mk index feb0f395b..c2c33a2ee 100644 --- a/examples/build_system/make/cpu/cortex-m0.mk +++ b/examples/build_system/make/cpu/cortex-m0.mk @@ -4,10 +4,18 @@ ifeq ($(TOOLCHAIN),gcc) -mcpu=cortex-m0 \ -mfloat-abi=soft \ +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + --target=arm-none-eabi \ + -mcpu=cortex-m0 \ + else ifeq ($(TOOLCHAIN),iar) # IAR Flags CFLAGS += --cpu cortex-m0 ASFLAGS += --cpu cortex-m0 + +else + $(error "TOOLCHAIN is not supported") endif # For freeRTOS port source diff --git a/examples/build_system/make/cpu/cortex-m0plus.mk b/examples/build_system/make/cpu/cortex-m0plus.mk index b416b7a4a..fe8feb227 100644 --- a/examples/build_system/make/cpu/cortex-m0plus.mk +++ b/examples/build_system/make/cpu/cortex-m0plus.mk @@ -4,10 +4,18 @@ ifeq ($(TOOLCHAIN),gcc) -mcpu=cortex-m0plus \ -mfloat-abi=soft \ +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + --target=arm-none-eabi \ + -mcpu=cortex-m0plus \ + else ifeq ($(TOOLCHAIN),iar) # IAR Flags CFLAGS += --cpu cortex-m0+ ASFLAGS += --cpu cortex-m0+ + +else + $(error "TOOLCHAIN is not supported") endif # For freeRTOS port source diff --git a/examples/build_system/make/cpu/cortex-m23.mk b/examples/build_system/make/cpu/cortex-m23.mk index 29542d8e8..7ab758352 100644 --- a/examples/build_system/make/cpu/cortex-m23.mk +++ b/examples/build_system/make/cpu/cortex-m23.mk @@ -4,10 +4,18 @@ ifeq ($(TOOLCHAIN),gcc) -mcpu=cortex-m23 \ -mfloat-abi=soft \ +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + --target=arm-none-eabi \ + -mcpu=cortex-m23 \ + else ifeq ($(TOOLCHAIN),iar) # IAR Flags CFLAGS += --cpu cortex-m23 ASFLAGS += --cpu cortex-m23 + +else + $(error "TOOLCHAIN is not supported") endif # For freeRTOS port source diff --git a/examples/build_system/make/cpu/cortex-m3.mk b/examples/build_system/make/cpu/cortex-m3.mk index 7a34b9e04..b6325313f 100644 --- a/examples/build_system/make/cpu/cortex-m3.mk +++ b/examples/build_system/make/cpu/cortex-m3.mk @@ -4,13 +4,18 @@ ifeq ($(TOOLCHAIN),gcc) -mcpu=cortex-m3 \ -mfloat-abi=soft \ +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + --target=arm-none-eabi \ + -mcpu=cortex-m3 \ + else ifeq ($(TOOLCHAIN),iar) # IAR Flags - CFLAGS += \ - --cpu cortex-m3 \ + CFLAGS += --cpu cortex-m3 + ASFLAGS += --cpu cortex-m3 - ASFLAGS += \ - --cpu cortex-m3 +else + $(error "TOOLCHAIN is not supported") endif # For freeRTOS port source diff --git a/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk index c65f24376..405053dd0 100644 --- a/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk +++ b/examples/build_system/make/cpu/cortex-m33-nodsp-nofp.mk @@ -1,16 +1,24 @@ ifeq ($(TOOLCHAIN),gcc) - CFLAGS += \ + CFLAGS += \ -mthumb \ -mcpu=cortex-m33+nodsp \ -mfloat-abi=soft \ +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + --target=arm-none-eabi \ + -mcpu=cortex-m33 \ + -mfpu=softvp \ + else ifeq ($(TOOLCHAIN),iar) - CFLAGS += \ + CFLAGS += \ --cpu cortex-m33+nodsp \ - ASFLAGS += \ + ASFLAGS += \ --cpu cortex-m33+nodsp \ +else + $(error "TOOLCHAIN is not supported") endif FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure diff --git a/examples/build_system/make/cpu/cortex-m33.mk b/examples/build_system/make/cpu/cortex-m33.mk index fe5b7b380..47b0eaecd 100644 --- a/examples/build_system/make/cpu/cortex-m33.mk +++ b/examples/build_system/make/cpu/cortex-m33.mk @@ -5,15 +5,23 @@ ifeq ($(TOOLCHAIN),gcc) -mfloat-abi=hard \ -mfpu=fpv5-sp-d16 \ +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + --target=arm-none-eabi \ + -mcpu=cortex-m33 \ + -mfpu=fpv5-sp-d16 \ + else ifeq ($(TOOLCHAIN),iar) - CFLAGS += \ + CFLAGS += \ --cpu cortex-m33 \ --fpu VFPv5-SP \ - ASFLAGS += \ + ASFLAGS += \ --cpu cortex-m33 \ --fpu VFPv5-SP \ +else + $(error "TOOLCHAIN is not supported") endif FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure diff --git a/examples/build_system/make/cpu/cortex-m4.mk b/examples/build_system/make/cpu/cortex-m4.mk index d8776b5d8..4e16819d1 100644 --- a/examples/build_system/make/cpu/cortex-m4.mk +++ b/examples/build_system/make/cpu/cortex-m4.mk @@ -5,9 +5,18 @@ ifeq ($(TOOLCHAIN),gcc) -mfloat-abi=hard \ -mfpu=fpv4-sp-d16 \ +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + --target=arm-none-eabi \ + -mcpu=cortex-m4 \ + -mfpu=fpv4-sp-d16 \ + else ifeq ($(TOOLCHAIN),iar) CFLAGS += --cpu cortex-m4 --fpu VFPv4 ASFLAGS += --cpu cortex-m4 --fpu VFPv4 + +else + $(error "TOOLCHAIN is not supported") endif FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM4F diff --git a/examples/build_system/make/cpu/cortex-m7.mk b/examples/build_system/make/cpu/cortex-m7.mk index 0e3461787..3e6116179 100644 --- a/examples/build_system/make/cpu/cortex-m7.mk +++ b/examples/build_system/make/cpu/cortex-m7.mk @@ -5,6 +5,12 @@ ifeq ($(TOOLCHAIN),gcc) -mfloat-abi=hard \ -mfpu=fpv5-d16 \ +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + --target=arm-none-eabi \ + -mcpu=cortex-m7 \ + -mfpu=fpv5-d16 \ + else ifeq ($(TOOLCHAIN),iar) CFLAGS += \ --cpu cortex-m7 \ @@ -14,6 +20,8 @@ else ifeq ($(TOOLCHAIN),iar) --cpu cortex-m7 \ --fpu VFPv5_D16 \ +else + $(error "TOOLCHAIN is not supported") endif FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM7/r0p1 diff --git a/examples/build_system/make/cpu/msp430.mk b/examples/build_system/make/cpu/msp430.mk index 06340d23b..6daa2c38d 100644 --- a/examples/build_system/make/cpu/msp430.mk +++ b/examples/build_system/make/cpu/msp430.mk @@ -1,7 +1,11 @@ ifeq ($(TOOLCHAIN),gcc) # nothing to add +else ifeq ($(TOOLCHAIN),clang) + # nothing to add else ifeq ($(TOOLCHAIN),iar) # nothing to add +else + $(error "TOOLCHAIN is not supported") endif # For freeRTOS port source diff --git a/examples/build_system/make/make.mk b/examples/build_system/make/make.mk index 2437b8766..1ec42cb50 100644 --- a/examples/build_system/make/make.mk +++ b/examples/build_system/make/make.mk @@ -2,6 +2,26 @@ # Common make definition for all examples # --------------------------------------- +#------------------------------------------------------------- +# Toolchain +# Can be changed via TOOLCHAIN=gcc|iar or CC=arm-none-eabi-gcc|iccarm|clang +#------------------------------------------------------------- + +ifneq (,$(findstring clang,$(CC))) + TOOLCHAIN = clang +else ifneq (,$(findstring iccarm,$(CC))) + TOOLCHAIN = iar +else ifneq (,$(findstring gcc,$(CC))) + TOOLCHAIN = gcc +endif + +# Default to GCC +ifndef TOOLCHAIN + TOOLCHAIN = gcc +endif + +$(info TOOLCHAIN: $(TOOLCHAIN)) + #-------------- TOP and CURRENT_PATH ------------ # Set TOP to be the path to get from the current directory (where make was invoked) to the top of the tree. @@ -75,12 +95,6 @@ else SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c)) endif -#------------------------------------------------------------- -# Toolchain -# Can be changed via TOOLCHAIN=gcc|iar or CC=arm-none-eabi-gcc|iccarm|clang -#------------------------------------------------------------- -TOOLCHAIN ?= gcc - #-------------- Source files and compiler flags -------------- # tinyusb makefile include $(TOP)/src/tinyusb.mk @@ -112,7 +126,7 @@ endif # Logger: default is uart, can be set to rtt or swo ifneq ($(LOGGER),) - CMAKE_DEFSYM += -DLOGGER=$(LOGGER) + CMAKE_DEFSYM += -DLOGGER=$(LOGGER) endif ifeq ($(LOGGER),rtt) diff --git a/examples/build_system/make/rules.mk b/examples/build_system/make/rules.mk index 78fce49d2..7b6b339ed 100644 --- a/examples/build_system/make/rules.mk +++ b/examples/build_system/make/rules.mk @@ -24,7 +24,7 @@ vpath %.c . $(TOP) vpath %.s . $(TOP) vpath %.S . $(TOP) -include ${TOP}/examples/build_system/make/toolchain/arm_$(TOOLCHAIN)_rules.mk +include ${TOP}/examples/build_system/make/toolchain/$(TOOLCHAIN)_rules.mk # --------------------------------------- # Compiler Flags diff --git a/examples/build_system/make/toolchain/arm_clang.mk b/examples/build_system/make/toolchain/arm_clang.mk new file mode 100644 index 000000000..97face39c --- /dev/null +++ b/examples/build_system/make/toolchain/arm_clang.mk @@ -0,0 +1,10 @@ +CC = clang +CXX = clang++ +AS = $(CC) -x assembler-with-cpp +LD = $(CC) + +GDB = $(CROSS_COMPILE)gdb +OBJCOPY = llvm-objcopy +SIZE = llvm-size + +include ${TOP}/examples/build_system/make/toolchain/gcc_common.mk diff --git a/examples/build_system/make/toolchain/arm_gcc.mk b/examples/build_system/make/toolchain/arm_gcc.mk index c34581ae2..a8576f8ee 100644 --- a/examples/build_system/make/toolchain/arm_gcc.mk +++ b/examples/build_system/make/toolchain/arm_gcc.mk @@ -12,73 +12,9 @@ GDB = $(CROSS_COMPILE)gdb OBJCOPY = $(CROSS_COMPILE)objcopy SIZE = $(CROSS_COMPILE)size -CC_VERSION := $(shell $(CC) -dumpversion) -CC_VERSION_MAJOR = $(firstword $(subst ., ,$(CC_VERSION))) - -# --------------------------------------- -# Compiler Flags -# --------------------------------------- CFLAGS += \ - -MD \ - -ggdb \ - -fdata-sections \ - -ffunction-sections \ -fsingle-precision-constant \ - -fno-strict-aliasing \ - -Wall \ - -Wextra \ - -Werror \ - -Wfatal-errors \ - -Wdouble-promotion \ - -Wstrict-prototypes \ - -Wstrict-overflow \ - -Werror-implicit-function-declaration \ - -Wfloat-equal \ - -Wundef \ - -Wshadow \ - -Wwrite-strings \ - -Wsign-compare \ - -Wmissing-format-attribute \ - -Wunreachable-code \ - -Wcast-align \ - -Wcast-function-type \ - -Wcast-qual \ - -Wnull-dereference \ - -Wuninitialized \ - -Wunused \ - -Wreturn-type \ - -Wredundant-decls \ - -# conversion is too strict for most mcu driver, may be disable sign/int/arith-conversion -# -Wconversion - -# Size Optimization as default -CFLAGS_OPTIMIZED ?= -Os - -# Debugging/Optimization -ifeq ($(DEBUG), 1) - CFLAGS += -O0 - NO_LTO = 1 -else - CFLAGS += $(CFLAGS_OPTIMIZED) -endif - -# --------------------------------------- -# Linker Flags -# --------------------------------------- -LDFLAGS += \ - -Wl,-Map=$@.map \ - -Wl,-cref \ - -Wl,-gc-sections \ -# renesas rx does not support --print-memory-usage flags -ifneq ($(FAMILY),rx) -LDFLAGS += -Wl,--print-memory-usage -endif +LIBS += -lgcc -lm -lnosys -# from version 12 -ifeq ($(strip $(if $(CMDEXE),\ - $(shell if $(CC_VERSION_MAJOR) geq 12 (echo 1) else (echo 0)),\ - $(shell expr $(CC_VERSION_MAJOR) \>= 12))), 1) -LDFLAGS += -Wl,--no-warn-rwx-segment -endif +include ${TOP}/examples/build_system/make/toolchain/gcc_common.mk diff --git a/examples/build_system/make/toolchain/arm_gcc_rules.mk b/examples/build_system/make/toolchain/arm_gcc_rules.mk deleted file mode 100644 index d295879d9..000000000 --- a/examples/build_system/make/toolchain/arm_gcc_rules.mk +++ /dev/null @@ -1,75 +0,0 @@ -SRC_S += $(SRC_S_GCC) - -# Assembly files can be name with upper case .S, convert it to .s -SRC_S := $(SRC_S:.S=.s) - -# Due to GCC LTO bug https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966 -# assembly file should be placed first in linking order -# '_asm' suffix is added to object of assembly file -OBJ += $(addprefix $(BUILD)/obj/, $(SRC_S:.s=_asm.o)) -OBJ += $(addprefix $(BUILD)/obj/, $(SRC_C:.c=.o)) - -CFLAGS += $(CFLAGS_GCC) -MD - -# LTO makes it difficult to analyze map file for optimizing size purpose -# We will run this option in ci -ifeq ($(NO_LTO),1) -CFLAGS := $(filter-out -flto,$(CFLAGS)) -endif - -ifneq ($(CFLAGS_SKIP),) -CFLAGS := $(filter-out $(CFLAGS_SKIP),$(CFLAGS)) -endif - -LDFLAGS += $(CFLAGS) $(LDFLAGS_GCC) - -ifdef LD_FILE -LDFLAGS += -Wl,-T,$(TOP)/$(LD_FILE) -endif - -ifdef LD_FILE_GCC -LDFLAGS += -Wl,-T,$(TOP)/$(LD_FILE_GCC) -endif - -ASFLAGS += $(CFLAGS) - -LIBS_GCC ?= -lgcc -lm -lnosys - -# libc -LIBS += $(LIBS_GCC) - -ifneq ($(BOARD), spresense) -LIBS += -lc -endif - -# --------------------------------------- -# Rules -# --------------------------------------- - -# Compile .c file -$(BUILD)/obj/%.o: %.c - @echo CC $(notdir $@) - @$(CC) $(CFLAGS) -c -o $@ $< - -# ASM sources lower case .s -$(BUILD)/obj/%_asm.o: %.s - @echo AS $(notdir $@) - @$(AS) $(ASFLAGS) -c -o $@ $< - -# ASM sources upper case .S -$(BUILD)/obj/%_asm.o: %.S - @echo AS $(notdir $@) - @$(AS) $(ASFLAGS) -c -o $@ $< - -OBJCOPY_BIN_OPTION ?= -$(BUILD)/$(PROJECT).bin: $(BUILD)/$(PROJECT).elf - @echo CREATE $@ - $(OBJCOPY) -O binary $(OBJCOPY_BIN_OPTION) $^ $@ - -$(BUILD)/$(PROJECT).hex: $(BUILD)/$(PROJECT).elf - @echo CREATE $@ - @$(OBJCOPY) -O ihex $^ $@ - -$(BUILD)/$(PROJECT).elf: $(OBJ) - @echo LINK $@ - @$(LD) -o $@ $(LDFLAGS) $^ -Wl,--start-group $(LIBS) -Wl,--end-group diff --git a/examples/build_system/make/toolchain/arm_iar_rules.mk b/examples/build_system/make/toolchain/arm_iar_rules.mk deleted file mode 100644 index 2c066f6da..000000000 --- a/examples/build_system/make/toolchain/arm_iar_rules.mk +++ /dev/null @@ -1,44 +0,0 @@ -SRC_S += $(SRC_S_IAR) - -# Assembly files can be name with upper case .S, convert it to .s -SRC_S := $(SRC_S:.S=.s) - -# Due to GCC LTO bug https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966 -# assembly file should be placed first in linking order -# '_asm' suffix is added to object of assembly file -OBJ += $(addprefix $(BUILD)/obj/, $(SRC_S:.s=_asm.o)) -OBJ += $(addprefix $(BUILD)/obj/, $(SRC_C:.c=.o)) - -# Linker script -LDFLAGS += --config $(TOP)/$(LD_FILE_IAR) - -# --------------------------------------- -# Rules -# --------------------------------------- - -# Compile .c file -$(BUILD)/obj/%.o: %.c - @echo CC $(notdir $@) - @$(CC) $(CFLAGS) -c -o $@ $< - -# ASM sources lower case .s -$(BUILD)/obj/%_asm.o: %.s - @echo AS $(notdir $@) - @$(AS) $(ASFLAGS) -c -o $@ $< - -# ASM sources upper case .S -$(BUILD)/obj/%_asm.o: %.S - @echo AS $(notdir $@) - @$(AS) $(ASFLAGS) -c -o $@ $< - -$(BUILD)/$(PROJECT).bin: $(BUILD)/$(PROJECT).elf - @echo CREATE $@ - @$(OBJCOPY) --bin $^ $@ - -$(BUILD)/$(PROJECT).hex: $(BUILD)/$(PROJECT).elf - @echo CREATE $@ - @$(OBJCOPY) --ihex $^ $@ - -$(BUILD)/$(PROJECT).elf: $(OBJ) - @echo LINK $@ - @$(LD) -o $@ $(LDFLAGS) $^ diff --git a/examples/build_system/make/toolchain/clang_rules.mk b/examples/build_system/make/toolchain/clang_rules.mk new file mode 100644 index 000000000..341f705b1 --- /dev/null +++ b/examples/build_system/make/toolchain/clang_rules.mk @@ -0,0 +1 @@ +include ${TOP}/examples/build_system/make/toolchain/gcc_rules.mk diff --git a/examples/build_system/make/toolchain/gcc_common.mk b/examples/build_system/make/toolchain/gcc_common.mk new file mode 100644 index 000000000..6986d8bba --- /dev/null +++ b/examples/build_system/make/toolchain/gcc_common.mk @@ -0,0 +1,71 @@ +# --------------------------------------- +# Compiler Flags +# --------------------------------------- +CFLAGS += \ + -MD \ + -ggdb \ + -fdata-sections \ + -ffunction-sections \ + -fno-strict-aliasing \ + -Wall \ + -Wextra \ + -Werror \ + -Wfatal-errors \ + -Wdouble-promotion \ + -Wstrict-prototypes \ + -Wstrict-overflow \ + -Werror-implicit-function-declaration \ + -Wfloat-equal \ + -Wundef \ + -Wshadow \ + -Wwrite-strings \ + -Wsign-compare \ + -Wmissing-format-attribute \ + -Wunreachable-code \ + -Wcast-align \ + -Wcast-function-type \ + -Wcast-qual \ + -Wnull-dereference \ + -Wuninitialized \ + -Wunused \ + -Wreturn-type \ + -Wredundant-decls \ + +# conversion is too strict for most mcu driver, may be disable sign/int/arith-conversion +# -Wconversion + +# Size Optimization as default +CFLAGS_OPTIMIZED ?= -Os + +# Debugging/Optimization +ifeq ($(DEBUG), 1) + CFLAGS += -O0 + NO_LTO = 1 +else + CFLAGS += $(CFLAGS_OPTIMIZED) +endif + +# --------------------------------------- +# Linker Flags +# --------------------------------------- +LDFLAGS += \ + -Wl,-Map=$@.map \ + -Wl,--cref \ + -Wl,-gc-sections \ + +# renesas rx does not support --print-memory-usage flags +ifneq ($(FAMILY),rx) +LDFLAGS += -Wl,--print-memory-usage +endif + +ifeq ($(TOOLCHAIN),gcc) +CC_VERSION := $(shell $(CC) -dumpversion) +CC_VERSION_MAJOR = $(firstword $(subst ., ,$(CC_VERSION))) + +# from version 12 +ifeq ($(strip $(if $(CMDEXE),\ + $(shell if $(CC_VERSION_MAJOR) geq 12 (echo 1) else (echo 0)),\ + $(shell expr $(CC_VERSION_MAJOR) \>= 12))), 1) +LDFLAGS += -Wl,--no-warn-rwx-segment +endif +endif diff --git a/examples/build_system/make/toolchain/gcc_rules.mk b/examples/build_system/make/toolchain/gcc_rules.mk new file mode 100644 index 000000000..3cd87db64 --- /dev/null +++ b/examples/build_system/make/toolchain/gcc_rules.mk @@ -0,0 +1,76 @@ +SRC_S += $(SRC_S_GCC) + +# Assembly files can be name with upper case .S, convert it to .s +SRC_S := $(SRC_S:.S=.s) + +# Due to GCC LTO bug https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966 +# assembly file should be placed first in linking order +# '_asm' suffix is added to object of assembly file +OBJ += $(addprefix $(BUILD)/obj/, $(SRC_S:.s=_asm.o)) +OBJ += $(addprefix $(BUILD)/obj/, $(SRC_C:.c=.o)) + +CFLAGS += $(CFLAGS_GCC) -MD + +# LTO makes it difficult to analyze map file for optimizing size purpose +# We will run this option in ci +ifeq ($(NO_LTO),1) +CFLAGS := $(filter-out -flto,$(CFLAGS)) +endif + +ifneq ($(CFLAGS_SKIP),) +CFLAGS := $(filter-out $(CFLAGS_SKIP),$(CFLAGS)) +endif + +ifeq ($(TOOLCHAIN),clang) +LDFLAGS += $(CFLAGS) $(LDFLAGS_CLANG) +else +LDFLAGS += $(CFLAGS) $(LDFLAGS_GCC) +endif + +# TODO should be removed after all examples are updated +ifdef LD_FILE +LDFLAGS += -Wl,-T,$(TOP)/$(LD_FILE) +endif + +ifdef LD_FILE_GCC +LDFLAGS += -Wl,-T,$(TOP)/$(LD_FILE_GCC) +endif + +ASFLAGS += $(CFLAGS) + +# libc +ifneq ($(BOARD), spresense) +LIBS += -lc +endif + +# --------------------------------------- +# Rules +# --------------------------------------- + +# Compile .c file +$(BUILD)/obj/%.o: %.c + @echo CC $(notdir $@) + @$(CC) $(CFLAGS) -c -o $@ $< + +# ASM sources lower case .s +$(BUILD)/obj/%_asm.o: %.s + @echo AS $(notdir $@) + @$(AS) $(ASFLAGS) -c -o $@ $< + +# ASM sources upper case .S +$(BUILD)/obj/%_asm.o: %.S + @echo AS $(notdir $@) + @$(AS) $(ASFLAGS) -c -o $@ $< + +OBJCOPY_BIN_OPTION ?= +$(BUILD)/$(PROJECT).bin: $(BUILD)/$(PROJECT).elf + @echo CREATE $@ + $(OBJCOPY) -O binary $(OBJCOPY_BIN_OPTION) $^ $@ + +$(BUILD)/$(PROJECT).hex: $(BUILD)/$(PROJECT).elf + @echo CREATE $@ + @$(OBJCOPY) -O ihex $^ $@ + +$(BUILD)/$(PROJECT).elf: $(OBJ) + @echo LINK $@ + @$(LD) -o $@ $(LDFLAGS) $^ -Wl,--start-group $(LIBS) -Wl,--end-group diff --git a/examples/build_system/make/toolchain/iar_rules.mk b/examples/build_system/make/toolchain/iar_rules.mk new file mode 100644 index 000000000..2c066f6da --- /dev/null +++ b/examples/build_system/make/toolchain/iar_rules.mk @@ -0,0 +1,44 @@ +SRC_S += $(SRC_S_IAR) + +# Assembly files can be name with upper case .S, convert it to .s +SRC_S := $(SRC_S:.S=.s) + +# Due to GCC LTO bug https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966 +# assembly file should be placed first in linking order +# '_asm' suffix is added to object of assembly file +OBJ += $(addprefix $(BUILD)/obj/, $(SRC_S:.s=_asm.o)) +OBJ += $(addprefix $(BUILD)/obj/, $(SRC_C:.c=.o)) + +# Linker script +LDFLAGS += --config $(TOP)/$(LD_FILE_IAR) + +# --------------------------------------- +# Rules +# --------------------------------------- + +# Compile .c file +$(BUILD)/obj/%.o: %.c + @echo CC $(notdir $@) + @$(CC) $(CFLAGS) -c -o $@ $< + +# ASM sources lower case .s +$(BUILD)/obj/%_asm.o: %.s + @echo AS $(notdir $@) + @$(AS) $(ASFLAGS) -c -o $@ $< + +# ASM sources upper case .S +$(BUILD)/obj/%_asm.o: %.S + @echo AS $(notdir $@) + @$(AS) $(ASFLAGS) -c -o $@ $< + +$(BUILD)/$(PROJECT).bin: $(BUILD)/$(PROJECT).elf + @echo CREATE $@ + @$(OBJCOPY) --bin $^ $@ + +$(BUILD)/$(PROJECT).hex: $(BUILD)/$(PROJECT).elf + @echo CREATE $@ + @$(OBJCOPY) --ihex $^ $@ + +$(BUILD)/$(PROJECT).elf: $(OBJ) + @echo LINK $@ + @$(LD) -o $@ $(LDFLAGS) $^ diff --git a/hw/bsp/samd21/family.mk b/hw/bsp/samd21/family.mk index 3302aade5..309df58fe 100644 --- a/hw/bsp/samd21/family.mk +++ b/hw/bsp/samd21/family.mk @@ -6,7 +6,6 @@ CPU_CORE ?= cortex-m0plus CFLAGS += \ -flto \ - -nostdlib -nostartfiles \ -DCONF_DFLL_OVERWRITE_CALIBRATION=0 \ -DCFG_TUSB_MCU=OPT_MCU_SAMD21 @@ -16,7 +15,11 @@ CFLAGS += -Wno-error=redundant-decls # SAM driver is flooded with -Wcast-qual which slow down complication significantly CFLAGS_SKIP += -Wcast-qual -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + -specs=nosys.specs -specs=nano.specs \ + +LDFLAGS_CLANG += SRC_C += \ src/portable/microchip/samd/dcd_samd.c \ -- cgit v1.3.1 From eab42d90d42234997ea55c01b1a510c9bb6434aa Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Apr 2024 22:11:08 +0700 Subject: update clang make build for stm32: f0 f1 f2 f3 f4 f7 h7 g0 g4 l0 l4 samd21 samd51 nrf --- examples/build_system/make/toolchain/gcc_rules.mk | 1 + hw/bsp/nrf/family.mk | 21 ++++++++++++++------- hw/bsp/samd21/family.mk | 2 +- hw/bsp/samd51/family.mk | 7 ++++--- hw/bsp/stm32f0/family.mk | 5 +++-- hw/bsp/stm32f1/family.mk | 5 +++-- hw/bsp/stm32f2/family.mk | 5 +++-- hw/bsp/stm32f3/family.mk | 5 +++-- hw/bsp/stm32f4/family.mk | 5 +++-- hw/bsp/stm32f7/family.mk | 5 +++-- hw/bsp/stm32g0/family.mk | 5 +++-- hw/bsp/stm32g4/family.mk | 5 +++-- hw/bsp/stm32h5/family.mk | 10 +++++++--- hw/bsp/stm32h7/family.mk | 9 ++++++--- hw/bsp/stm32l0/family.mk | 15 +++++++++++---- hw/bsp/stm32l4/family.mk | 11 +++++++---- hw/bsp/stm32u5/boards/stm32u575eval/board.mk | 2 +- hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk | 2 +- hw/bsp/stm32u5/family.mk | 17 +++++++++++++---- tools/build_make.py | 10 +++++----- 20 files changed, 95 insertions(+), 52 deletions(-) (limited to 'examples') diff --git a/examples/build_system/make/toolchain/gcc_rules.mk b/examples/build_system/make/toolchain/gcc_rules.mk index 3cd87db64..fc5225503 100644 --- a/examples/build_system/make/toolchain/gcc_rules.mk +++ b/examples/build_system/make/toolchain/gcc_rules.mk @@ -22,6 +22,7 @@ CFLAGS := $(filter-out $(CFLAGS_SKIP),$(CFLAGS)) endif ifeq ($(TOOLCHAIN),clang) +CFLAGS += $(CFLAGS_CLANG) LDFLAGS += $(CFLAGS) $(LDFLAGS_CLANG) else LDFLAGS += $(CFLAGS) $(LDFLAGS_GCC) diff --git a/hw/bsp/nrf/family.mk b/hw/bsp/nrf/family.mk index 29802dc37..b3c05e6db 100644 --- a/hw/bsp/nrf/family.mk +++ b/hw/bsp/nrf/family.mk @@ -8,25 +8,31 @@ include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m4 CFLAGS += \ - -flto \ -DCFG_TUSB_MCU=OPT_MCU_NRF5X \ - -DCONFIG_GPIO_AS_PINRESET + -DCONFIG_GPIO_AS_PINRESET \ + -D__STARTUP_CLEAR_BSS #CFLAGS += -nostdlib #CFLAGS += -D__START=main # suppress warning caused by vendor mcu driver -CFLAGS += \ +CFLAGS_GCC += \ + -flto \ -Wno-error=undef \ -Wno-error=unused-parameter \ + -Wno-error=unused-variable \ -Wno-error=cast-align \ -Wno-error=cast-qual \ - -Wno-error=redundant-decls + -Wno-error=redundant-decls \ -LDFLAGS += \ - -specs=nosys.specs -specs=nano.specs \ +LDFLAGS_GCC += \ + -nostartfiles \ + --specs=nosys.specs --specs=nano.specs \ -L$(TOP)/${NRFX_DIR}/mdk +LDFLAGS_CLANG += \ + -L$(TOP)/${NRFX_DIR}/mdk \ + SRC_C += \ src/portable/nordic/nrf5x/dcd_nrf5x.c \ ${NRFX_DIR}/helpers/nrfx_flag32_allocator.c \ @@ -34,7 +40,8 @@ SRC_C += \ ${NRFX_DIR}/drivers/src/nrfx_power.c \ ${NRFX_DIR}/drivers/src/nrfx_spim.c \ ${NRFX_DIR}/drivers/src/nrfx_uarte.c \ - ${NRFX_DIR}/mdk/system_$(MCU_VARIANT).c + ${NRFX_DIR}/mdk/system_$(MCU_VARIANT).c \ + ${NRFX_DIR}/soc/nrfx_atomic.c INC += \ $(TOP)/$(BOARD_PATH) \ diff --git a/hw/bsp/samd21/family.mk b/hw/bsp/samd21/family.mk index 309df58fe..aabcff4a2 100644 --- a/hw/bsp/samd21/family.mk +++ b/hw/bsp/samd21/family.mk @@ -17,7 +17,7 @@ CFLAGS_SKIP += -Wcast-qual LDFLAGS_GCC += \ -nostdlib -nostartfiles \ - -specs=nosys.specs -specs=nano.specs \ + --specs=nosys.specs --specs=nano.specs \ LDFLAGS_CLANG += diff --git a/hw/bsp/samd51/family.mk b/hw/bsp/samd51/family.mk index 94ca68705..7b90efad0 100644 --- a/hw/bsp/samd51/family.mk +++ b/hw/bsp/samd51/family.mk @@ -6,13 +6,14 @@ CPU_CORE ?= cortex-m4 CFLAGS += \ -flto \ - -nostdlib -nostartfiles \ -DCFG_TUSB_MCU=OPT_MCU_SAMD51 # SAM driver is flooded with -Wcast-qual which slow down complication significantly CFLAGS_SKIP += -Wcast-qual -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/microchip/samd/dcd_samd.c \ @@ -33,7 +34,7 @@ INC += \ $(TOP)/hw/mcu/microchip/samd51/hal/utils/include \ $(TOP)/hw/mcu/microchip/samd51/hpl/port \ $(TOP)/hw/mcu/microchip/samd51/hri \ - $(TOP)/hw/mcu/microchip/samd51/CMSIS/Include + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ # flash using bossac at least version 1.8 # can be found in arduino15/packages/arduino/tools/bossac/ diff --git a/hw/bsp/stm32f0/family.mk b/hw/bsp/stm32f0/family.mk index 537df4d7b..431709de0 100644 --- a/hw/bsp/stm32f0/family.mk +++ b/hw/bsp/stm32f0/family.mk @@ -18,12 +18,13 @@ CFLAGS += \ # GCC Flags CFLAGS_GCC += \ -flto \ - -nostdlib -nostartfiles \ # suppress warning caused by vendor mcu driver CFLAGS_GCC += -Wno-error=unused-parameter -Wno-error=cast-align -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs # ------------------------ # All source paths should be relative to the top level. diff --git a/hw/bsp/stm32f1/family.mk b/hw/bsp/stm32f1/family.mk index 8a5625551..03fbf4010 100644 --- a/hw/bsp/stm32f1/family.mk +++ b/hw/bsp/stm32f1/family.mk @@ -16,12 +16,13 @@ CFLAGS += \ # GCC Flags CFLAGS_GCC += \ -flto \ - -nostdlib -nostartfiles \ # mcu driver cause following warnings CFLAGS_GCC += -Wno-error=cast-align -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + -specs=nosys.specs -specs=nano.specs # ------------------------ # All source paths should be relative to the top level. diff --git a/hw/bsp/stm32f2/family.mk b/hw/bsp/stm32f2/family.mk index c6ef1ec1d..7e71f6eed 100644 --- a/hw/bsp/stm32f2/family.mk +++ b/hw/bsp/stm32f2/family.mk @@ -16,12 +16,13 @@ CFLAGS += \ CFLAGS_GCC += \ -flto \ - -nostdlib -nostartfiles \ # mcu driver cause following warnings CFLAGS_GCC += -Wno-error=sign-compare -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ diff --git a/hw/bsp/stm32f3/family.mk b/hw/bsp/stm32f3/family.mk index be8271d96..4fe3aa99d 100644 --- a/hw/bsp/stm32f3/family.mk +++ b/hw/bsp/stm32f3/family.mk @@ -13,13 +13,14 @@ CPU_CORE ?= cortex-m4 CFLAGS += \ -flto \ - -nostdlib -nostartfiles \ -DCFG_TUSB_MCU=OPT_MCU_STM32F3 # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ diff --git a/hw/bsp/stm32f4/family.mk b/hw/bsp/stm32f4/family.mk index ecbbff417..523a1cb04 100644 --- a/hw/bsp/stm32f4/family.mk +++ b/hw/bsp/stm32f4/family.mk @@ -20,12 +20,13 @@ CFLAGS += \ # GCC Flags CFLAGS_GCC += \ -flto \ - -nostdlib -nostartfiles # suppress warning caused by vendor mcu driver CFLAGS_GCC += -Wno-error=cast-align -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs # ----------------- # Sources & Include diff --git a/hw/bsp/stm32f7/family.mk b/hw/bsp/stm32f7/family.mk index 1cdf23c6b..cc21bd64e 100644 --- a/hw/bsp/stm32f7/family.mk +++ b/hw/bsp/stm32f7/family.mk @@ -30,12 +30,13 @@ endif # GCC Flags CFLAGS_GCC += \ -flto \ - -nostdlib -nostartfiles # mcu driver cause following warnings CFLAGS_GCC += -Wno-error=cast-align -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs # ----------------- # Sources & Include diff --git a/hw/bsp/stm32g0/family.mk b/hw/bsp/stm32g0/family.mk index fb382b56a..95b8e537d 100644 --- a/hw/bsp/stm32g0/family.mk +++ b/hw/bsp/stm32g0/family.mk @@ -16,12 +16,13 @@ CFLAGS += \ # GCC Flags CFLAGS_GCC += \ -flto \ - -nostdlib -nostartfiles # suppress warning caused by vendor mcu driver CFLAGS_GCC += -Wno-error=cast-align -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs # ----------------- # Sources & Include diff --git a/hw/bsp/stm32g4/family.mk b/hw/bsp/stm32g4/family.mk index 95cd84dbd..0abd73532 100644 --- a/hw/bsp/stm32g4/family.mk +++ b/hw/bsp/stm32g4/family.mk @@ -15,12 +15,13 @@ CFLAGS += \ # GCC Flags CFLAGS_GCC += \ -flto \ - -nostdlib -nostartfiles \ # suppress warning caused by vendor mcu driver CFLAGS_GCC += -Wno-error=cast-align -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs # ----------------- # Sources & Include diff --git a/hw/bsp/stm32h5/family.mk b/hw/bsp/stm32h5/family.mk index 270b1c465..792edb2bb 100644 --- a/hw/bsp/stm32h5/family.mk +++ b/hw/bsp/stm32h5/family.mk @@ -16,7 +16,6 @@ CFLAGS += \ # GCC Flags CFLAGS_GCC += \ -flto \ - -nostdlib -nostartfiles \ # suppress warning caused by vendor mcu driver CFLAGS_GCC += \ @@ -24,7 +23,12 @@ CFLAGS_GCC += \ -Wno-error=undef \ -Wno-error=unused-parameter \ -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +CFLAGS_CLANG += \ + -Wno-error=parentheses-equality + +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs # ----------------- # Sources & Include @@ -56,7 +60,7 @@ SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT).s # Linker LD_FILE_IAR = $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash.icf -LD_FILE_GCC = $(ST_CMSIS)/Source/Templates/gcc/linker/$(MCU_VARIANT_UPPER)_FLASH.ld +LD_FILE_GCC = $(FAMILY_PATH)/linker/$(MCU_VARIANT_UPPER)_FLASH.ld # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32h7/family.mk b/hw/bsp/stm32h7/family.mk index 0777bb9c2..40df190db 100644 --- a/hw/bsp/stm32h7/family.mk +++ b/hw/bsp/stm32h7/family.mk @@ -30,12 +30,15 @@ endif # GCC Flags CFLAGS_GCC += \ -flto \ - -nostdlib -nostartfiles # suppress warning caused by vendor mcu driver -CFLAGS_GCC += -Wno-error=maybe-uninitialized -Wno-error=cast-align -Wno-error=unused-parameter +CFLAGS_GCC += \ + -Wno-error=cast-align \ + -Wno-error=unused-parameter \ -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs # ----------------- # Sources & Include diff --git a/hw/bsp/stm32l0/family.mk b/hw/bsp/stm32l0/family.mk index a811e1823..fe7561fc2 100644 --- a/hw/bsp/stm32l0/family.mk +++ b/hw/bsp/stm32l0/family.mk @@ -12,19 +12,26 @@ CPU_CORE ?= cortex-m0plus CFLAGS += \ -flto \ - -nostdlib -nostartfiles \ -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_EXAMPLE_VIDEO_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_STM32L0 # mcu driver cause following warnings -CFLAGS += \ +CFLAGS_GCC += \ -Wno-error=unused-parameter \ -Wno-error=redundant-decls \ -Wno-error=cast-align \ - -Wno-error=maybe-uninitialized -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +ifeq ($(TOOLCHAIN),gcc) +CFLAGS_GCC += -Wno-error=maybe-uninitialized +endif + +CFLAGS_CLANG += \ + -Wno-error=parentheses-equality + +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ diff --git a/hw/bsp/stm32l4/family.mk b/hw/bsp/stm32l4/family.mk index 956f82263..411436cf6 100644 --- a/hw/bsp/stm32l4/family.mk +++ b/hw/bsp/stm32l4/family.mk @@ -16,12 +16,15 @@ CFLAGS += \ # GCC Flags CFLAGS_GCC += \ -flto \ - -nostdlib -nostartfiles + -Wno-error=cast-align \ -# suppress warning caused by vendor mcu driver -CFLAGS_GCC += -Wno-error=maybe-uninitialized -Wno-error=cast-align +ifeq ($(TOOLCHAIN),gcc) +CFLAGS_GCC += -Wno-error=maybe-uninitialized +endif -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs # ----------------- # Sources & Include diff --git a/hw/bsp/stm32u5/boards/stm32u575eval/board.mk b/hw/bsp/stm32u5/boards/stm32u575eval/board.mk index 37d59023f..922d67f83 100644 --- a/hw/bsp/stm32u5/boards/stm32u575eval/board.mk +++ b/hw/bsp/stm32u5/boards/stm32u575eval/board.mk @@ -2,7 +2,7 @@ CFLAGS += \ -DSTM32U575xx \ # All source paths should be relative to the top level. -LD_FILE = ${ST_CMSIS}/Source/Templates/gcc/linker/STM32U575xx_FLASH.ld +LD_FILE = ${FAMILY_PATH}/linker/STM32U575xx_FLASH.ld SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s diff --git a/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk b/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk index f07157801..1dd157a68 100644 --- a/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk +++ b/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk @@ -2,7 +2,7 @@ CFLAGS += \ -DSTM32U575xx \ # All source paths should be relative to the top level. -LD_FILE = ${ST_CMSIS}/Source/Templates/gcc/linker/STM32U575xx_FLASH.ld +LD_FILE = ${FAMILY_PATH}/linker/STM32U575xx_FLASH.ld SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk index 2144ef37b..be5809340 100644 --- a/hw/bsp/stm32u5/family.mk +++ b/hw/bsp/stm32u5/family.mk @@ -8,14 +8,23 @@ include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m33 CFLAGS += \ - -flto \ - -nostdlib -nostartfiles \ -DCFG_TUSB_MCU=OPT_MCU_STM32U5 # suppress warning caused by vendor mcu driver -CFLAGS += -Wno-error=maybe-uninitialized -Wno-error=cast-align -Wno-error=undef -Wno-error=unused-parameter +CFLAGS_GCC += \ + -flto \ + -Wno-error=cast-align \ + -Wno-error=undef \ + -Wno-error=unused-parameter \ + -Wno-error=type-limits \ -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +ifeq ($(TOOLCHAIN),gcc) +CFLAGS_GCC += -Wno-error=maybe-uninitialized +endif + +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ diff --git a/tools/build_make.py b/tools/build_make.py index f79a452e4..240fc8d64 100644 --- a/tools/build_make.py +++ b/tools/build_make.py @@ -11,7 +11,6 @@ SKIPPED = "\033[33mskipped\033[0m" build_separator = '-' * 106 -make_iar_option = 'TOOLCHAIN=iar' def filter_with_input(mylist): if len(sys.argv) > 1: @@ -36,9 +35,10 @@ def build_family(example, family, make_option): if __name__ == '__main__': - # IAR CC - if make_iar_option not in sys.argv: - make_iar_option = '' + make_option = '' + for a in sys.argv: + if 'TOOLCHAIN=' in sys.argv: + make_option += ' ' + a # If examples are not specified in arguments, build all all_examples = [] @@ -67,7 +67,7 @@ if __name__ == '__main__': for example in all_examples: print(build_separator) for family in all_families: - fret = build_family(example, family, make_iar_option) + fret = build_family(example, family, make_option) if len(fret) == len(total_result): total_result = [total_result[i] + fret[i] for i in range(len(fret))] -- cgit v1.3.1 From 19f1080e381a81d5c56a0494b20c5c06475ffe42 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Apr 2024 22:41:22 +0700 Subject: fix make build due to clang changes --- examples/build_system/make/make.mk | 2 -- hw/bsp/imxrt/family.mk | 5 ++++- hw/bsp/kinetis_k/family.mk | 3 +++ hw/bsp/kinetis_kl/family.mk | 2 ++ hw/bsp/lpc17/family.mk | 3 ++- hw/bsp/lpc18/family.mk | 5 +++-- hw/bsp/lpc40/family.mk | 3 ++- hw/bsp/lpc43/family.mk | 5 +++-- hw/bsp/lpc54/family.mk | 5 ++++- hw/bsp/lpc55/family.mk | 7 +++++-- 10 files changed, 28 insertions(+), 12 deletions(-) (limited to 'examples') diff --git a/examples/build_system/make/make.mk b/examples/build_system/make/make.mk index 1ec42cb50..a78f4130d 100644 --- a/examples/build_system/make/make.mk +++ b/examples/build_system/make/make.mk @@ -20,8 +20,6 @@ ifndef TOOLCHAIN TOOLCHAIN = gcc endif -$(info TOOLCHAIN: $(TOOLCHAIN)) - #-------------- TOP and CURRENT_PATH ------------ # Set TOP to be the path to get from the current directory (where make was invoked) to the top of the tree. diff --git a/hw/bsp/imxrt/family.mk b/hw/bsp/imxrt/family.mk index c6adcba5a..bde4c4ba6 100644 --- a/hw/bsp/imxrt/family.mk +++ b/hw/bsp/imxrt/family.mk @@ -11,6 +11,7 @@ MCU_DIR = $(SDK_DIR)/devices/$(MCU_VARIANT) CFLAGS += \ -D__ARMVFP__=0 \ -D__ARMFPV5__=0 \ + -D__STARTUP_CLEAR_BSS \ -DXIP_EXTERNAL_FLASH=1 \ -DXIP_BOOT_HEADER_ENABLE=1 \ -DCFG_TUSB_MCU=OPT_MCU_MIMXRT1XXX @@ -26,7 +27,9 @@ endif # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter -Wno-error=implicit-fallthrough -Wno-error=redundant-decls -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostartfiles \ + --specs=nosys.specs --specs=nano.specs # All source paths should be relative to the top level. LD_FILE ?= $(MCU_DIR)/gcc/$(MCU_VARIANT)xxxxx${MCU_CORE}_flexspi_nor.ld diff --git a/hw/bsp/kinetis_k/family.mk b/hw/bsp/kinetis_k/family.mk index 995873eec..844ce332e 100644 --- a/hw/bsp/kinetis_k/family.mk +++ b/hw/bsp/kinetis_k/family.mk @@ -6,9 +6,12 @@ include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m4 CFLAGS += \ + -D__STARTUP_CLEAR_BSS \ -DCFG_TUSB_MCU=OPT_MCU_KINETIS_K \ LDFLAGS += \ + -nostartfiles \ + --specs=nosys.specs --specs=nano.specs \ -Wl,--defsym,__stack_size__=0x400 \ -Wl,--defsym,__heap_size__=0 diff --git a/hw/bsp/kinetis_kl/family.mk b/hw/bsp/kinetis_kl/family.mk index e331d82b7..1fdce981a 100644 --- a/hw/bsp/kinetis_kl/family.mk +++ b/hw/bsp/kinetis_kl/family.mk @@ -6,9 +6,11 @@ include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m0plus CFLAGS += \ + -D__STARTUP_CLEAR_BSS \ -DCFG_TUSB_MCU=OPT_MCU_KINETIS_KL \ LDFLAGS += \ + -nostartfiles \ -specs=nosys.specs -specs=nano.specs \ -Wl,--defsym,__stack_size__=0x400 \ -Wl,--defsym,__heap_size__=0 diff --git a/hw/bsp/lpc17/family.mk b/hw/bsp/lpc17/family.mk index 694b6cccf..84ed95648 100644 --- a/hw/bsp/lpc17/family.mk +++ b/hw/bsp/lpc17/family.mk @@ -18,7 +18,7 @@ CFLAGS += -Wno-error=strict-prototypes -Wno-error=cast-qual # caused by freeRTOS port !! CFLAGS += -Wno-error=maybe-uninitialized -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/nxp/lpc17_40/dcd_lpc17_40.c \ @@ -36,3 +36,4 @@ SRC_C += \ INC += \ $(TOP)/$(BOARD_PATH) \ $(TOP)/$(MCU_DIR)/inc \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ diff --git a/hw/bsp/lpc18/family.mk b/hw/bsp/lpc18/family.mk index c36c903ae..f625e926a 100644 --- a/hw/bsp/lpc18/family.mk +++ b/hw/bsp/lpc18/family.mk @@ -14,7 +14,7 @@ CFLAGS += \ # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter -Wno-error=strict-prototypes -Wno-error=cast-qual -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/chipidea/ci_hs/dcd_ci_hs.c \ @@ -30,4 +30,5 @@ SRC_C += \ INC += \ $(TOP)/$(BOARD_PATH) \ $(TOP)/$(MCU_DIR)/inc \ - $(TOP)/$(MCU_DIR)/inc/config_18xx + $(TOP)/$(MCU_DIR)/inc/config_18xx \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ diff --git a/hw/bsp/lpc40/family.mk b/hw/bsp/lpc40/family.mk index fa76789e3..79d868f35 100644 --- a/hw/bsp/lpc40/family.mk +++ b/hw/bsp/lpc40/family.mk @@ -15,7 +15,7 @@ CFLAGS += \ # mcu driver cause following warnings CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=cast-qual -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs # All source paths should be relative to the top level. SRC_C += \ @@ -32,4 +32,5 @@ SRC_C += \ INC += \ $(TOP)/$(MCU_DIR)/inc \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(BOARD_PATH) diff --git a/hw/bsp/lpc43/family.mk b/hw/bsp/lpc43/family.mk index f24385139..84e7c30b3 100644 --- a/hw/bsp/lpc43/family.mk +++ b/hw/bsp/lpc43/family.mk @@ -18,7 +18,7 @@ CFLAGS += \ -Wno-error=cast-qual \ -Wno-error=incompatible-pointer-types \ -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/chipidea/ci_hs/dcd_ci_hs.c \ @@ -36,4 +36,5 @@ SRC_C += \ INC += \ $(TOP)/$(BOARD_PATH) \ ${TOP}/${SDK_DIR}/inc \ - ${TOP}/${SDK_DIR}/inc/config_43xx + ${TOP}/${SDK_DIR}/inc/config_43xx \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ diff --git a/hw/bsp/lpc54/family.mk b/hw/bsp/lpc54/family.mk index 9b5eac18d..ea4c9c39c 100644 --- a/hw/bsp/lpc54/family.mk +++ b/hw/bsp/lpc54/family.mk @@ -7,6 +7,7 @@ MCU_DIR = $(SDK_DIR)/devices/$(MCU_VARIANT) CFLAGS += \ -flto \ + -D__STARTUP_CLEAR_BSS \ -DCFG_TUSB_MCU=OPT_MCU_LPC54XXX \ -DCFG_TUSB_MEM_ALIGN='__attribute__((aligned(64)))' \ @@ -23,7 +24,9 @@ endif # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostartfiles \ + --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c \ diff --git a/hw/bsp/lpc55/family.mk b/hw/bsp/lpc55/family.mk index 1b97c43e4..d82e85904 100644 --- a/hw/bsp/lpc55/family.mk +++ b/hw/bsp/lpc55/family.mk @@ -11,9 +11,10 @@ PORT ?= 1 CFLAGS += \ -flto \ + -D__STARTUP_CLEAR_BSS \ -DCFG_TUSB_MCU=OPT_MCU_LPC55XX \ -DCFG_TUSB_MEM_ALIGN='__attribute__((aligned(64)))' \ - -DBOARD_TUD_RHPORT=$(PORT) + -DBOARD_TUD_RHPORT=$(PORT) \ ifeq ($(PORT), 1) $(info "PORT1 High Speed") @@ -28,7 +29,9 @@ endif # mcu driver cause following warnings CFLAGS += -Wno-error=unused-parameter -Wno-error=float-equal -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostartfiles \ + --specs=nosys.specs --specs=nano.specs \ # All source paths should be relative to the top level. LD_FILE ?= $(MCU_DIR)/gcc/$(MCU_CORE)_flash.ld -- cgit v1.3.1 From 1e7091dae98ea3eeba4789364c290199b157c368 Mon Sep 17 00:00:00 2001 From: tyustli <43946994+tyustli@users.noreply.github.com> Date: Thu, 25 Apr 2024 19:47:12 +0800 Subject: fix ci error --- examples/host/bare_api/src/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'examples') diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index 14725996d..b1d388bf9 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -34,6 +34,7 @@ #include "bsp/board_api.h" #include "tusb.h" +#include "class/hid/hid.h" // English #define LANGUAGE_ID 0x0409 -- cgit v1.3.1 From 2e995d7cf4b2971e3ca7167a097b99832c8d61ce Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 25 Apr 2024 20:23:40 +0700 Subject: adding support for esp32 for use with max3421e host --- examples/device/board_test/src/tusb_config.h | 2 +- examples/device/cdc_msc_freertos/src/main.c | 6 +-- examples/device/cdc_msc_freertos/src/tusb_config.h | 2 +- examples/device/hid_composite_freertos/src/main.c | 6 +-- .../hid_composite_freertos/src/tusb_config.h | 2 +- examples/device/video_capture/src/main.c | 4 +- examples/device/video_capture/src/tusb_config.h | 2 +- examples/device/video_capture_2ch/src/main.c | 4 +- .../device/video_capture_2ch/src/tusb_config.h | 2 +- examples/host/cdc_msc_hid_freertos/src/cdc_app.c | 2 +- examples/host/cdc_msc_hid_freertos/src/main.c | 6 +-- .../host/cdc_msc_hid_freertos/src/tusb_config.h | 2 +- hw/bsp/board_api.h | 2 +- .../boards/adafruit_feather_esp32_v2/board.cmake | 2 + .../boards/adafruit_feather_esp32_v2/board.h | 53 ++++++++++++++++++++++ hw/bsp/espressif/boards/family.c | 19 ++++---- .../components/tinyusb_src/CMakeLists.txt | 12 +---- hw/bsp/espressif/family.cmake | 6 +-- src/common/tusb_mcu.h | 5 +- src/portable/analog/max3421/hcd_max3421.c | 2 +- src/tusb_option.h | 2 + 21 files changed, 94 insertions(+), 49 deletions(-) create mode 100644 hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.cmake create mode 100644 hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.h (limited to 'examples') diff --git a/examples/device/board_test/src/tusb_config.h b/examples/device/board_test/src/tusb_config.h index 1a27cc87f..36eafe807 100644 --- a/examples/device/board_test/src/tusb_config.h +++ b/examples/device/board_test/src/tusb_config.h @@ -49,7 +49,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index e94e8eaec..607d40270 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -30,7 +30,7 @@ #include "bsp/board_api.h" #include "tusb.h" -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" @@ -111,14 +111,14 @@ int main(void) { #endif // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 -#if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if !TUP_MCU_ESPRESSIF vTaskStartScheduler(); #endif return 0; } -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF void app_main(void) { main(); } diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index 91efe7d40..e743c9148 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -59,7 +59,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index ff2cb635e..2bd545bc2 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -31,7 +31,7 @@ #include "tusb.h" #include "usb_descriptors.h" -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" @@ -113,14 +113,14 @@ int main(void) 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) +#if !TUP_MCU_ESPRESSIF vTaskStartScheduler(); #endif return 0; } -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF void app_main(void) { main(); diff --git a/examples/device/hid_composite_freertos/src/tusb_config.h b/examples/device/hid_composite_freertos/src/tusb_config.h index 3ba9bf311..0689e0f23 100644 --- a/examples/device/hid_composite_freertos/src/tusb_config.h +++ b/examples/device/hid_composite_freertos/src/tusb_config.h @@ -59,7 +59,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c index 2a2b0961f..ddb51e03a 100644 --- a/examples/device/video_capture/src/main.c +++ b/examples/device/video_capture/src/main.c @@ -288,7 +288,7 @@ void led_blinking_task(void* param) { #define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE #define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4) -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF #define USBD_STACK_SIZE 4096 int main(void); void app_main(void) { @@ -344,7 +344,7 @@ void freertos_init_task(void) { #endif // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 - #if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + #if !TUP_MCU_ESPRESSIF vTaskStartScheduler(); #endif } diff --git a/examples/device/video_capture/src/tusb_config.h b/examples/device/video_capture/src/tusb_config.h index bdfc37d87..21483a2da 100644 --- a/examples/device/video_capture/src/tusb_config.h +++ b/examples/device/video_capture/src/tusb_config.h @@ -58,7 +58,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/video_capture_2ch/src/main.c b/examples/device/video_capture_2ch/src/main.c index eb1cf2580..e8c2ec6b0 100644 --- a/examples/device/video_capture_2ch/src/main.c +++ b/examples/device/video_capture_2ch/src/main.c @@ -296,7 +296,7 @@ void led_blinking_task(void* param) { #define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE #define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4) -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF #define USBD_STACK_SIZE 4096 int main(void); void app_main(void) { @@ -352,7 +352,7 @@ void freertos_init_task(void) { #endif // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 - #if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + #if !TUP_MCU_ESPRESSIF vTaskStartScheduler(); #endif } diff --git a/examples/device/video_capture_2ch/src/tusb_config.h b/examples/device/video_capture_2ch/src/tusb_config.h index fe66d63b5..43c7dfc90 100644 --- a/examples/device/video_capture_2ch/src/tusb_config.h +++ b/examples/device/video_capture_2ch/src/tusb_config.h @@ -58,7 +58,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c index 7d246af67..f3495ab28 100644 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -27,7 +27,7 @@ #include "tusb.h" #include "bsp/board_api.h" -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c index 069cbdc90..a6cb4d460 100644 --- a/examples/host/cdc_msc_hid_freertos/src/main.c +++ b/examples/host/cdc_msc_hid_freertos/src/main.c @@ -30,7 +30,7 @@ #include "bsp/board_api.h" #include "tusb.h" -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" @@ -107,14 +107,14 @@ int main(void) { 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) +#if !TUP_MCU_ESPRESSIF vTaskStartScheduler(); #endif return 0; } -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF void app_main(void) { main(); } diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index 35de5ee50..0aab2cd2f 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -44,7 +44,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index f21a32371..eee9ed9c5 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -39,7 +39,7 @@ extern "C" { #include "tusb.h" #if CFG_TUSB_OS == OPT_OS_FREERTOS -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TUP_MCU_ESPRESSIF // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" diff --git a/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.cmake b/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.cmake new file mode 100644 index 000000000..18c956714 --- /dev/null +++ b/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.cmake @@ -0,0 +1,2 @@ +# Apply board specific content here +set(IDF_TARGET "esp32") diff --git a/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.h b/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.h new file mode 100644 index 000000000..0c53df06b --- /dev/null +++ b/hw/bsp/espressif/boards/adafruit_feather_esp32_v2/board.h @@ -0,0 +1,53 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define NEOPIXEL_PIN 0 +#define NEOPIXEL_POWER_PIN 2 +#define NEOPIXEL_POWER_STATE 1 + +#define BUTTON_PIN 38 +#define BUTTON_STATE_ACTIVE 0 + +// SPI for USB host shield +#define MAX3421_SPI_HOST SPI3_HOST +#define MAX3421_SCK_PIN 5 +#define MAX3421_MOSI_PIN 19 +#define MAX3421_MISO_PIN 21 +#define MAX3421_CS_PIN 33 +#define MAX3421_INTR_PIN 15 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index 5599d1504..02e478a0c 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -30,8 +30,12 @@ #include "esp_rom_gpio.h" #include "esp_mac.h" #include "hal/gpio_ll.h" + +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) #include "hal/usb_hal.h" #include "soc/usb_periph.h" +static void configure_pins(usb_hal_context_t* usb); +#endif #include "driver/gpio.h" #include "driver/uart.h" @@ -56,7 +60,6 @@ static led_strip_handle_t led_strip; static void max3421_init(void); #endif -static void configure_pins(usb_hal_context_t* usb); //--------------------------------------------------------------------+ // Implementation @@ -100,7 +103,6 @@ void board_init(void) { }; ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip)); - led_strip_clear(led_strip); // off #endif @@ -109,6 +111,7 @@ void board_init(void) { gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) // USB Controller Hal init periph_module_reset(PERIPH_USB_MODULE); periph_module_enable(PERIPH_USB_MODULE); @@ -118,12 +121,14 @@ void board_init(void) { }; usb_hal_init(&hal); configure_pins(&hal); +#endif #if CFG_TUH_ENABLED && CFG_TUH_MAX3421 max3421_init(); #endif } +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) static void configure_pins(usb_hal_context_t* usb) { /* usb_periph_iopins currently configures USB_OTG as USB Device. * Introduce additional parameters in usb_hal_context_t when adding support @@ -153,6 +158,7 @@ static void configure_pins(usb_hal_context_t* usb) { gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); } } +#endif //--------------------------------------------------------------------+ // Board porting API @@ -208,15 +214,12 @@ SemaphoreHandle_t max3421_intr_sem; static void IRAM_ATTR max3421_isr_handler(void* arg) { (void) arg; // arg is gpio num - gpio_set_level(13, 1); BaseType_t xHigherPriorityTaskWoken = pdFALSE; xSemaphoreGiveFromISR(max3421_intr_sem, &xHigherPriorityTaskWoken); if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(); } - - gpio_set_level(13, 0); } static void max3421_intr_task(void* param) { @@ -250,16 +253,12 @@ static void max3421_init(void) { spi_device_interface_config_t max3421_cfg = { .mode = 0, - .clock_speed_hz = 26000000, + .clock_speed_hz = 20000000, // S2/S3 can work with 26 Mhz, but esp32 seems only work up to 20 Mhz .spics_io_num = -1, // manual control CS .queue_size = 1 }; ESP_ERROR_CHECK(spi_bus_add_device(MAX3421_SPI_HOST, &max3421_cfg, &max3421_spi)); - // debug - gpio_set_direction(13, GPIO_MODE_OUTPUT); - gpio_set_level(13, 0); - // Interrupt pin max3421_intr_sem = xSemaphoreCreateBinary(); xTaskCreate(max3421_intr_task, "max3421 intr", 2048, NULL, configMAX_PRIORITIES - 2, NULL); diff --git a/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt b/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt index abe276910..8bdb3802e 100644 --- a/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt +++ b/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt @@ -5,17 +5,7 @@ set(includes_public) set(compile_options) set(tusb_src "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src") -if(target STREQUAL "esp32s3") - set(tusb_mcu "OPT_MCU_ESP32S3") -elseif(target STREQUAL "esp32s2") - set(tusb_mcu "OPT_MCU_ESP32S2") -else() - # CONFIG_TINYUSB dependency has been guaranteed by Kconfig logic, - # So it's not possible that cmake goes here - message(FATAL_ERROR "TinyUSB is not support on ${target}.") - return() -endif() - +string(TOUPPER OPT_MCU_${target} tusb_mcu) list(APPEND compile_definitions CFG_TUSB_MCU=${tusb_mcu} CFG_TUSB_OS=OPT_OS_FREERTOS diff --git a/hw/bsp/espressif/family.cmake b/hw/bsp/espressif/family.cmake index 92a9bcb04..eb97401c3 100644 --- a/hw/bsp/espressif/family.cmake +++ b/hw/bsp/espressif/family.cmake @@ -3,11 +3,7 @@ cmake_minimum_required(VERSION 3.5) # Apply board specific content i.e IDF_TARGET must be set before project.cmake is included include("${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake") -if(IDF_TARGET STREQUAL "esp32s2") - set(FAMILY_MCUS ESP32S2) -elseif(IDF_TARGET STREQUAL "esp32s3") - set(FAMILY_MCUS ESP32S3) -endif() +string(TOUPPER ${IDF_TARGET} FAMILY_MCUS) # Add example src and bsp directories set(EXTRA_COMPONENT_DIRS "src" "${CMAKE_CURRENT_LIST_DIR}/boards" "${CMAKE_CURRENT_LIST_DIR}/components") diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 0ae2573cd..2c4d7461d 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -329,6 +329,9 @@ #define TUP_USBIP_DWC2 #define TUP_DCD_ENDPOINT_MAX 6 +#elif TU_CHECK_MCU(OPT_MCU_ESP32) && (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)) + #error "MCUs are only supported with CFG_TUH_MAX3421 enabled" + //--------------------------------------------------------------------+ // Dialog //--------------------------------------------------------------------+ @@ -426,7 +429,7 @@ #define TUP_MCU_MULTIPLE_CORE 0 #endif -#ifndef TUP_DCD_ENDPOINT_MAX +#if CFG_TUD_ENABLED && !defined(TUP_DCD_ENDPOINT_MAX) #warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" #define TUP_DCD_ENDPOINT_MAX 8 #endif diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 39afb7505..053169bf2 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -484,8 +484,8 @@ bool hcd_init(uint8_t rhport) { // v1 is 0x01, v2 is 0x12, v3 is 0x13 uint8_t const revision = reg_read(rhport, REVISION_ADDR, false); - TU_ASSERT(revision == 0x01 || revision == 0x12 || revision == 0x13, false); TU_LOG2_HEX(revision); + TU_ASSERT(revision == 0x01 || revision == 0x12 || revision == 0x13, false); // reset reg_write(rhport, USBCTL_ADDR, USBCTL_CHIPRES, false); diff --git a/src/tusb_option.h b/src/tusb_option.h index cbcb69edd..25412d432 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -119,6 +119,8 @@ // Espressif #define OPT_MCU_ESP32S2 900 ///< Espressif ESP32-S2 #define OPT_MCU_ESP32S3 901 ///< Espressif ESP32-S3 +#define OPT_MCU_ESP32 902 ///< Espressif ESP32 (for host max3421e) +#define TUP_MCU_ESPRESSIF (CFG_TUSB_MCU >= 900 && CFG_TUSB_MCU < 1000) // check if Espressif MCU // Dialog #define OPT_MCU_DA1469X 1000 ///< Dialog Semiconductor DA1469x -- cgit v1.3.1 From 223ce56625474764dc00229c44731858abcf4f29 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 26 Apr 2024 00:10:57 +0700 Subject: - add esp32 c3, c6 mcu option - skip breakpoint for espressif riscv --- examples/host/cdc_msc_hid_freertos/src/main.c | 5 ++++- src/common/tusb_mcu.h | 4 ++-- src/common/tusb_verify.h | 2 +- src/portable/analog/max3421/hcd_max3421.c | 2 ++ src/tusb_option.h | 2 ++ 5 files changed, 11 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c index a6cb4d460..fa799aede 100644 --- a/examples/host/cdc_msc_hid_freertos/src/main.c +++ b/examples/host/cdc_msc_hid_freertos/src/main.c @@ -126,7 +126,10 @@ static void usb_host_task(void *param) { (void) param; // init host stack on configured roothub port - tuh_init(BOARD_TUH_RHPORT); + if (!tuh_init(BOARD_TUH_RHPORT)) { + printf("Failed to init USB Host Stack\r\n"); + vTaskSuspend(NULL); + } if (board_init_after_tusb) { board_init_after_tusb(); diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 00526bdba..5a567f2d5 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -429,8 +429,8 @@ #define TUP_MCU_MULTIPLE_CORE 0 #endif -#if !defined(TUP_DCD_ENDPOINT_MAX) - #warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" +#if !defined(TUP_DCD_ENDPOINT_MAX) && defined(CFG_TUD_ENABLED) && CFG_TUD_ENABLED +#warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" #define TUP_DCD_ENDPOINT_MAX 8 #endif diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 71406dacf..0a9549c99 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -84,7 +84,7 @@ if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ } while(0) -#elif defined(__riscv) +#elif defined(__riscv) && !TUP_MCU_ESPRESSIF #define TU_BREAKPOINT() do { __asm("ebreak\n"); } while(0) #elif defined(_mips) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 053169bf2..4dc93d2d8 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -479,6 +479,8 @@ bool hcd_init(uint8_t rhport) { _hcd_data.spi_mutex = osal_mutex_create(&_hcd_data.spi_mutexdef); #endif + // NOTE: driver does not seem to work without nRST pin signal + // full duplex, interrupt negative edge reg_write(rhport, PINCTL_ADDR, _tuh_cfg.pinctl | PINCTL_FDUPSPI, false); diff --git a/src/tusb_option.h b/src/tusb_option.h index 25412d432..3ead20ee7 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -120,6 +120,8 @@ #define OPT_MCU_ESP32S2 900 ///< Espressif ESP32-S2 #define OPT_MCU_ESP32S3 901 ///< Espressif ESP32-S3 #define OPT_MCU_ESP32 902 ///< Espressif ESP32 (for host max3421e) +#define OPT_MCU_ESP32C3 903 ///< Espressif ESP32-C3 +#define OPT_MCU_ESP32C6 904 ///< Espressif ESP32-C6 #define TUP_MCU_ESPRESSIF (CFG_TUSB_MCU >= 900 && CFG_TUSB_MCU < 1000) // check if Espressif MCU // Dialog -- cgit v1.3.1 From c917d47e71d9cef3f6cf096cf9606913ef7020fd Mon Sep 17 00:00:00 2001 From: Kasper Nyhus Kaae Date: Mon, 7 Mar 2022 21:30:33 +0100 Subject: audio_test_freertos & audio_4_channel_mic_freertos --- .../audio_4_channel_mic_freertos/CMakeLists.txt | 22 + .../device/audio_4_channel_mic_freertos/Makefile | 37 ++ .../device/audio_4_channel_mic_freertos/README.md | 18 + .../device/audio_4_channel_mic_freertos/skip.txt | 3 + .../src/CMakeLists.txt | 27 ++ .../src/FreeRTOSConfig/FreeRTOSConfig.h | 191 ++++++++ .../device/audio_4_channel_mic_freertos/src/main.c | 488 +++++++++++++++++++++ .../src/plot_audio_samples.py | 34 ++ .../audio_4_channel_mic_freertos/src/tusb_config.h | 128 ++++++ .../src/usb_descriptors.c | 165 +++++++ examples/device/audio_test_freertos/CMakeLists.txt | 22 + examples/device/audio_test_freertos/Makefile | 38 ++ examples/device/audio_test_freertos/README.md | 18 + examples/device/audio_test_freertos/skip.txt | 3 + .../device/audio_test_freertos/src/CMakeLists.txt | 27 ++ .../src/FreeRTOSConfig/FreeRTOSConfig.h | 191 ++++++++ examples/device/audio_test_freertos/src/main.c | 486 ++++++++++++++++++++ .../audio_test_freertos/src/plot_audio_samples.py | 34 ++ .../device/audio_test_freertos/src/tusb_config.h | 121 +++++ .../audio_test_freertos/src/usb_descriptors.c | 165 +++++++ 20 files changed, 2218 insertions(+) create mode 100644 examples/device/audio_4_channel_mic_freertos/CMakeLists.txt create mode 100644 examples/device/audio_4_channel_mic_freertos/Makefile create mode 100644 examples/device/audio_4_channel_mic_freertos/README.md create mode 100644 examples/device/audio_4_channel_mic_freertos/skip.txt create mode 100644 examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt create mode 100644 examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 examples/device/audio_4_channel_mic_freertos/src/main.c create mode 100644 examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py create mode 100644 examples/device/audio_4_channel_mic_freertos/src/tusb_config.h create mode 100644 examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c create mode 100644 examples/device/audio_test_freertos/CMakeLists.txt create mode 100644 examples/device/audio_test_freertos/Makefile create mode 100644 examples/device/audio_test_freertos/README.md create mode 100644 examples/device/audio_test_freertos/skip.txt create mode 100644 examples/device/audio_test_freertos/src/CMakeLists.txt create mode 100644 examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 examples/device/audio_test_freertos/src/main.c create mode 100644 examples/device/audio_test_freertos/src/plot_audio_samples.py create mode 100644 examples/device/audio_test_freertos/src/tusb_config.h create mode 100644 examples/device/audio_test_freertos/src/usb_descriptors.c (limited to 'examples') diff --git a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt new file mode 100644 index 000000000..639dde99a --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.5) + +# TOP is absolute path to root directory of TinyUSB git repo +# needed for esp32sx build. TOOD could be removed later on +set(TOP "../../..") +get_filename_component(TOP "${TOP}" REALPATH) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. -) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT}) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +# Check for -DFAMILY= +if(FAMILY MATCHES "^esp32s[2-3]") +else() + message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}") +endif() diff --git a/examples/device/audio_4_channel_mic_freertos/Makefile b/examples/device/audio_4_channel_mic_freertos/Makefile new file mode 100644 index 000000000..6c8c43ddd --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/Makefile @@ -0,0 +1,37 @@ +DEPS_SUBMODULES += lib/FreeRTOS-Kernel + +include ../../../tools/top.mk +include ../../make.mk + +FREERTOS_SRC = lib/FreeRTOS-Kernel + +INC += \ + src \ + src/FreeRTOSConfig \ + $(TOP)/hw \ + $(TOP)/$(FREERTOS_SRC)/include \ + $(TOP)/$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT) + +# Example source +EXAMPLE_SOURCE = \ + src/freertos_hook.c \ + src/main.c \ + src/usb_descriptors.c + +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +# FreeRTOS source, all files in port folder +SRC_C += \ + $(FREERTOS_SRC)/list.c \ + $(FREERTOS_SRC)/queue.c \ + $(FREERTOS_SRC)/tasks.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 + +# FreeRTOS (lto + Os) linker issue +LDFLAGS += -Wl,--undefined=vTaskSwitchContext + +include ../../rules.mk diff --git a/examples/device/audio_4_channel_mic_freertos/README.md b/examples/device/audio_4_channel_mic_freertos/README.md new file mode 100644 index 000000000..a35c16195 --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/README.md @@ -0,0 +1,18 @@ +# How to build example for Esp32s3 +1. Load idf environment variables (eg. using the esp-idf alias `get_idf` if configured) + +2. cd into examples directory +``` +$ cd /tinyusb/examples/device/audio_4_channel_mic_freertos +``` + +3. Run make in project directory specifying the board +``` +$ make BOARD=espressif_s3_devkitc all +``` + +4. Flash the binary onto the esp32-s3 by copy-paste of the full command output by the esp-idf build system replacing **(PORT)** with eg. /dev/ttyUSB0 + +eg. + +> /home/kaspernyhus/.espressif/python_env/idf4.4_py3.8_env/bin/python ../../../../esp-idf/components/esptool_py/esptool/esptool.py -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 _build/espressif_s3_devkitc/bootloader/bootloader.bin 0x8000 _build/espressif_s3_devkitc/partition_table/partition-table.bin 0x10000 _build/espressif_s3_devkitc/audio_4_channel_mic_freertos.bin diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt new file mode 100644 index 000000000..ae9b57f1f --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -0,0 +1,3 @@ +mcu:SAMD11 +mcu:SAME5X +mcu:SAMG \ No newline at end of file diff --git a/examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt b/examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt new file mode 100644 index 000000000..29e46d979 --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt @@ -0,0 +1,27 @@ +idf_component_register(SRCS "main.c" "usb_descriptors.c" + INCLUDE_DIRS "." + REQUIRES freertos soc) + +file(TO_NATIVE_PATH "${TOP}/hw/bsp/${FAMILY}/boards/${BOARD}/board.cmake" board_cmake) + +if(EXISTS ${board_cmake}) + include(${board_cmake}) +endif() + +target_include_directories(${COMPONENT_TARGET} PUBLIC + "${TOP}/hw" + "${TOP}/src" +) + +target_compile_definitions(${COMPONENT_TARGET} PUBLIC + ESP_PLATFORM +) + +target_sources(${COMPONENT_TARGET} PUBLIC + "${TOP}/src/tusb.c" + "${TOP}/src/common/tusb_fifo.c" + "${TOP}/src/device/usbd.c" + "${TOP}/src/device/usbd_control.c" + "${TOP}/src/class/audio/audio_device.c" + "${TOP}/src/portable/espressif/esp32sx/dcd_esp32sx.c" +) \ No newline at end of file diff --git a/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..ccb620720 --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,191 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// Include MCU header +#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" +#endif + +// TODO fix later +#if CFG_TUSB_MCU == OPT_MCU_MM32F327X + extern u32 SystemCoreClock; +#else + extern uint32_t SystemCoreClock; +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE ( 1024 ) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#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 configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 2 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 0 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +#ifdef __RX__ +/* Renesas RX series */ +#define vSoftwareInterruptISR INT_Excep_ICU_SWINT +#define vTickISR INT_Excep_CMT0_CMI0 +#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) +#define configKERNEL_INTERRUPT_PRIORITY 1 +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 + +#else + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ +#if defined(__NVIC_PRIO_BITS) + // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h + #define configPRIO_BITS __NVIC_PRIO_BITS +#elif defined(__ECLIC_INTCTLBITS) + // RISC-V Bumblebee core from nuclei + #define configPRIO_BITS __ECLIC_INTCTLBITS +#else + #error "FreeRTOS configPRIO_BITS to be defined" +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +// ESP-IDF need "freertos/" prefix in include path. +// CFG_TUSB_OS_INC_PATH should be defined accordingly. +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/timers.h" + +#define USBD_STACK_SIZE 4096 + + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +#ifndef AUDIO_SAMPLE_RATE +#define AUDIO_SAMPLE_RATE 48000 +#endif + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +// static timer +StaticTimer_t blinky_tmdef; +TimerHandle_t blinky_tm; +StackType_t usb_device_stack[USBD_STACK_SIZE]; +StaticTask_t usb_device_taskdef; + + +// Audio controls +// Current states +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint32_t sampFreq; +uint8_t clkValid; + +// Range states +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state +audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state + +// Audio test data +uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_EP_SZ_IN/2]; // Ensure half word aligned +uint16_t samples[] = {0, 0, 0, 0}; + +void led_blinky_cb(TimerHandle_t xTimer); +void usb_device_task(void* param); +void audio_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + // 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); + + // Init values + sampFreq = AUDIO_SAMPLE_RATE; + clkValid = 1; + + sampleFreqRng.wNumSubRanges = 1; + sampleFreqRng.subrange[0].bMin = AUDIO_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; + sampleFreqRng.subrange[0].bRes = 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); + + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 + #if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + vTaskStartScheduler(); + #endif + + return 0; +} + +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +void app_main(void) +{ + main(); +} +#endif + +// USB Device Driver task +// This top level thread process all usb events and invoke callbacks +void usb_device_task(void* param) +{ + (void) param; + + // This should be called after scheduler/kernel is started. + // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tusb_init(); + + // RTOS forever loop + while (1) + { + // tinyusb device task + tud_task(); + } +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0); +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); +} + +//--------------------------------------------------------------------+ +// AUDIO Task +//--------------------------------------------------------------------+ + +void audio_task(void) +{ + // Yet to be filled - e.g. put meas data into TX FIFOs etc. + // asm("nop"); +} + +//--------------------------------------------------------------------+ +// Application Callback API Implementations +//--------------------------------------------------------------------+ + +// Invoked when audio class specific set request received for an EP +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + (void) pBuff; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) ep; + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an interface +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + (void) pBuff; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) itf; + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an entity +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + (void) itf; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // If request is for our feature unit + if ( entityID == 2 ) + { + switch ( ctrlSel ) + { + case AUDIO_FU_CTRL_MUTE: + // Request uses format layout 1 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + + mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; + + TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + return true; + + case AUDIO_FU_CTRL_VOLUME: + // Request uses format layout 2 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + + volume[channelNum] = ((audio_control_cur_2_t*) pBuff)->bCur; + + TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + return true; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an EP +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) ep; + + // return tud_control_xfer(rhport, p_request, &tmp, 1); + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an interface +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) itf; + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an entity +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + // uint8_t itf = TU_U16_LOW(p_request->wIndex); // Since we have only one audio function implemented, we do not need the itf value + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Input terminal (Microphone input) + if (entityID == 1) + { + switch ( ctrlSel ) + { + case AUDIO_TE_CTRL_CONNECTOR: + { + // The terminal connector control only has a get request with only the CUR attribute. + audio_desc_channel_cluster_t ret; + + // Those are dummy values for now + ret.bNrChannels = 1; + ret.bmChannelConfig = 0; + ret.iChannelNames = 0; + + TU_LOG2(" Get terminal connector\r\n"); + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + } + break; + + // Unknown/Unsupported control selector + default: + TU_BREAKPOINT(); + return false; + } + } + + // Feature unit + if (entityID == 2) + { + switch ( ctrlSel ) + { + case AUDIO_FU_CTRL_MUTE: + // Audio control mute cur parameter block consists of only one byte - we thus can send it right away + // There does not exist a range parameter block for mute + TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); + + case AUDIO_FU_CTRL_VOLUME: + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); + + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); + + // Copy values - only for testing - better is version below + audio_control_range_2_n_t(1) + ret; + + ret.wNumSubRanges = 1; + ret.subrange[0].bMin = -90; // -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + // Clock Source unit + if ( entityID == 4 ) + { + switch ( ctrlSel ) + { + case AUDIO_CS_CTRL_SAM_FREQ: + // channelNum is always zero in this case + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Sample Freq.\r\n"); + return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Sample Freq. range\r\n"); + return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + case AUDIO_CS_CTRL_CLK_VALID: + // Only cur attribute exists for this request + TU_LOG2(" Get Sample Freq. valid\r\n"); + return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + TU_LOG2(" Unsupported entity: %d\r\n", entityID); + return false; // Yet not implemented +} + +bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) +{ + (void) rhport; + (void) itf; + (void) ep_in; + (void) cur_alt_setting; + + tud_audio_write((uint8_t*)i2s_dummy_buffer, CFG_TUD_AUDIO_EP_SZ_IN); + + return true; +} + +bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) +{ + (void) rhport; + (void) n_bytes_copied; + (void) itf; + (void) ep_in; + (void) cur_alt_setting; + + uint16_t* p_buff = i2s_dummy_buffer; + for (int samples_num = 0; samples_num < AUDIO_SAMPLE_RATE/1000; samples_num++) { + for (int ch=0; ch < CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX; ch++) { + *p_buff++ = samples[ch]; + samples[ch] = samples[ch]+(ch+1); + } + } + + return true; +} + +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + (void) p_request; + + return true; +} + +///--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinky_cb(TimerHandle_t xTimer) +{ + (void) xTimer; + static bool led_state = false; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py b/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py new file mode 100644 index 000000000..9ab15135d --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py @@ -0,0 +1,34 @@ +import sounddevice as sd +import matplotlib.pyplot as plt +import numpy as np +import platform + +if __name__ == '__main__': + + # If you got "ValueError: No input device matching", that is because your PC name example device + # differently from tested list below. Uncomment the next line to see full list and try to pick correct one + # print(sd.query_devices()) + + fs = 48000 # Sample rate + duration = 100e-3 # Duration of recording + + if platform.system() == 'Windows': + # WDM-KS is needed since there are more than one MicNode device APIs (at least in Windows) + device = 'Microphone (MicNode_4_Ch), Windows WDM-KS' + elif platform.system() == 'Darwin': + device = 'MicNode_4_Ch' + else: + device ='default' + + myrecording = sd.rec(int(duration * fs), samplerate=fs, channels=4, dtype='int16', device=device) + print('Waiting...') + sd.wait() # Wait until recording is finished + print('Done!') + + time = np.arange(0, duration, 1 / fs) # time vector + plt.plot(time, myrecording) + plt.xlabel('Time [s]') + plt.ylabel('Amplitude') + plt.title('MicNode 4 Channel') + plt.show() + \ No newline at end of file diff --git a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h new file mode 100644 index 000000000..f13865084 --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h @@ -0,0 +1,128 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined +#endif + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_DEVICE_RHPORT_NUM + #define BOARD_DEVICE_RHPORT_NUM 0 +#endif + +#ifndef BOARD_DEVICE_RHPORT_SPEED + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED +#endif + +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + +#ifndef CFG_TUSB_OS + #define CFG_TUSB_OS OPT_OS_FREERTOS +#endif + +// Espressif IDF requires "freertos/" prefix in include path +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + #define CFG_TUSB_OS_INC_PATH freertos/ +#endif + +#ifndef CFG_TUSB_DEBUG + #define CFG_TUSB_DEBUG 0 +#endif + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_AUDIO 1 +#define CFG_TUD_VENDOR 0 + +//-------------------------------------------------------------------- +// AUDIO CLASS DRIVER CONFIGURATION +//-------------------------------------------------------------------- + +// Have a look into audio_device.h for all configurations + +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_FOUR_CH_DESC_LEN + +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 + +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup +#define CFG_TUD_AUDIO_EP_SZ_IN 48 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x CFG_TUD_AUDIO_N_CHANNELS_TX Channels - the Windows driver always needs an extra sample per channel of space more, otherwise it complains... found by trial and error +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN + +#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 +#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0 +#define CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX 2 // One I2S stream contains two channels, each stream is saved within one support FIFO - this value is currently fixed, the driver does not support a changing value +#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX) +#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c new file mode 100644 index 000000000..16355a7fc --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c @@ -0,0 +1,165 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "tusb.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ +enum +{ + ITF_NUM_AUDIO_CONTROL = 0, + ITF_NUM_AUDIO_STREAMING, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_FOUR_CH_DESC_LEN) + +#if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_AUDIO 0x03 + +#elif TU_CHECK_MCU(OPT_MCU_NRF5X) + // nRF5x ISO can only be endpoint 8 + #define EPNUM_AUDIO 0x08 + +#else + #define EPNUM_AUDIO 0x01 +#endif + +uint8_t const desc_configuration[] = +{ + // Interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) +}; + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + return desc_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "PaniRCorp", // 1: Manufacturer + "MicNode_4_Ch", // 2: Product + "123458", // 3: Serials, should use chip ID + "UAC2", // 4: Audio Interface +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void) langid; + + uint8_t chr_count; + + if ( index == 0) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + }else + { + // Convert ASCII string into UTF-16 + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) chr_count = 31; + + for(uint8_t i=0; i-) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT}) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +# Check for -DFAMILY= +if(FAMILY MATCHES "^esp32s[2-3]") +else() + message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}") +endif() diff --git a/examples/device/audio_test_freertos/Makefile b/examples/device/audio_test_freertos/Makefile new file mode 100644 index 000000000..e5b88df5e --- /dev/null +++ b/examples/device/audio_test_freertos/Makefile @@ -0,0 +1,38 @@ +DEPS_SUBMODULES += lib/FreeRTOS-Kernel + +include ../../../tools/top.mk +include ../../make.mk + +FREERTOS_SRC = lib/FreeRTOS-Kernel + +INC += \ + src \ + src/FreeRTOSConfig \ + $(TOP)/hw \ + $(TOP)/$(FREERTOS_SRC)/include \ + $(TOP)/$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT) + +# Example source +EXAMPLE_SOURCE = \ + src/freertos_hook.c \ + src/main.c \ + src/msc_disk.c \ + src/usb_descriptors.c + +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +# FreeRTOS source, all files in port folder +SRC_C += \ + $(FREERTOS_SRC)/list.c \ + $(FREERTOS_SRC)/queue.c \ + $(FREERTOS_SRC)/tasks.c \ + $(FREERTOS_SRC)/timers.c \ + $(subst ../../../,,$(wildcard ../../../$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT)/*.c)) + +# Suppress FreeRTOS warnings +CFLAGS += -Wno-error=cast-qual + +# FreeRTOS (lto + Os) linker issue +LDFLAGS += -Wl,--undefined=vTaskSwitchContext + +include ../../rules.mk \ No newline at end of file diff --git a/examples/device/audio_test_freertos/README.md b/examples/device/audio_test_freertos/README.md new file mode 100644 index 000000000..077a2a1b6 --- /dev/null +++ b/examples/device/audio_test_freertos/README.md @@ -0,0 +1,18 @@ +# How to build example for Esp32s3 +1. Load idf environment variables (eg. using the esp-idf alias `get_idf` if configured) + +2. cd into examples directory +``` +$ cd /tinyusb/examples/device/audio_test_freertos +``` + +3. Run make in project directory specifying the board +``` +$ make BOARD=espressif_s3_devkitc all +``` + +4. Flash the binary onto the esp32-s3 by copy-paste of the full command output by the esp-idf build system replacing **(PORT)** with eg. /dev/ttyUSB0 + +eg. + +> /home/kaspernyhus/.espressif/python_env/idf4.4_py3.8_env/bin/python ../../../../esp-idf/components/esptool_py/esptool/esptool.py -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 _build/espressif_s3_devkitc/bootloader/bootloader.bin 0x8000 _build/espressif_s3_devkitc/partition_table/partition-table.bin 0x10000 _build/espressif_s3_devkitc/audio_test_freertos.bin \ No newline at end of file diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt new file mode 100644 index 000000000..ae9b57f1f --- /dev/null +++ b/examples/device/audio_test_freertos/skip.txt @@ -0,0 +1,3 @@ +mcu:SAMD11 +mcu:SAME5X +mcu:SAMG \ No newline at end of file diff --git a/examples/device/audio_test_freertos/src/CMakeLists.txt b/examples/device/audio_test_freertos/src/CMakeLists.txt new file mode 100644 index 000000000..29e46d979 --- /dev/null +++ b/examples/device/audio_test_freertos/src/CMakeLists.txt @@ -0,0 +1,27 @@ +idf_component_register(SRCS "main.c" "usb_descriptors.c" + INCLUDE_DIRS "." + REQUIRES freertos soc) + +file(TO_NATIVE_PATH "${TOP}/hw/bsp/${FAMILY}/boards/${BOARD}/board.cmake" board_cmake) + +if(EXISTS ${board_cmake}) + include(${board_cmake}) +endif() + +target_include_directories(${COMPONENT_TARGET} PUBLIC + "${TOP}/hw" + "${TOP}/src" +) + +target_compile_definitions(${COMPONENT_TARGET} PUBLIC + ESP_PLATFORM +) + +target_sources(${COMPONENT_TARGET} PUBLIC + "${TOP}/src/tusb.c" + "${TOP}/src/common/tusb_fifo.c" + "${TOP}/src/device/usbd.c" + "${TOP}/src/device/usbd_control.c" + "${TOP}/src/class/audio/audio_device.c" + "${TOP}/src/portable/espressif/esp32sx/dcd_esp32sx.c" +) \ No newline at end of file diff --git a/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..ccb620720 --- /dev/null +++ b/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,191 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// Include MCU header +#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" +#endif + +// TODO fix later +#if CFG_TUSB_MCU == OPT_MCU_MM32F327X + extern u32 SystemCoreClock; +#else + extern uint32_t SystemCoreClock; +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE ( 1024 ) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#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 configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 2 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 0 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +#ifdef __RX__ +/* Renesas RX series */ +#define vSoftwareInterruptISR INT_Excep_ICU_SWINT +#define vTickISR INT_Excep_CMT0_CMI0 +#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) +#define configKERNEL_INTERRUPT_PRIORITY 1 +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 + +#else + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ +#if defined(__NVIC_PRIO_BITS) + // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h + #define configPRIO_BITS __NVIC_PRIO_BITS +#elif defined(__ECLIC_INTCTLBITS) + // RISC-V Bumblebee core from nuclei + #define configPRIO_BITS __ECLIC_INTCTLBITS +#else + #error "FreeRTOS configPRIO_BITS to be defined" +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +// ESP-IDF need "freertos/" prefix in include path. +// CFG_TUSB_OS_INC_PATH should be defined accordingly. +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/timers.h" + +#define USBD_STACK_SIZE 4096 + + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +#ifndef AUDIO_SAMPLE_RATE +#define AUDIO_SAMPLE_RATE 48000 +#endif + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +// static timer +StaticTimer_t blinky_tmdef; +TimerHandle_t blinky_tm; +StackType_t usb_device_stack[USBD_STACK_SIZE]; +StaticTask_t usb_device_taskdef; + + +// Audio controls +// Current states +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint32_t sampFreq; +uint8_t clkValid; + +// Range states +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state +audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state + +// Audio test data +uint16_t test_buffer_audio[CFG_TUD_AUDIO_EP_SZ_IN/2]; +uint16_t startVal = 0; + +void led_blinky_cb(TimerHandle_t xTimer); +void usb_device_task(void* param); +void audio_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + // 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); + + // Init values + sampFreq = AUDIO_SAMPLE_RATE; + clkValid = 1; + + sampleFreqRng.wNumSubRanges = 1; + sampleFreqRng.subrange[0].bMin = AUDIO_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; + sampleFreqRng.subrange[0].bRes = 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); + + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 + #if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + vTaskStartScheduler(); + #endif + + return 0; +} + +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +void app_main(void) +{ + main(); +} +#endif + +// USB Device Driver task +// This top level thread process all usb events and invoke callbacks +void usb_device_task(void* param) +{ + (void) param; + + // This should be called after scheduler/kernel is started. + // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. + tusb_init(); + + // RTOS forever loop + while (1) + { + // tinyusb device task + tud_task(); + } +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0); +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); +} + +//--------------------------------------------------------------------+ +// AUDIO Task +//--------------------------------------------------------------------+ + +void audio_task(void) +{ + // Yet to be filled - e.g. put meas data into TX FIFOs etc. + // asm("nop"); +} + +//--------------------------------------------------------------------+ +// Application Callback API Implementations +//--------------------------------------------------------------------+ + +// Invoked when audio class specific set request received for an EP +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + (void) pBuff; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) ep; + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an interface +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + (void) pBuff; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) itf; + + return false; // Yet not implemented +} + +// Invoked when audio class specific set request received for an entity +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + (void) itf; + + // We do not support any set range requests here, only current value requests + TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + + // If request is for our feature unit + if ( entityID == 2 ) + { + switch ( ctrlSel ) + { + case AUDIO_FU_CTRL_MUTE: + // Request uses format layout 1 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + + mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; + + TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + return true; + + case AUDIO_FU_CTRL_VOLUME: + // Request uses format layout 2 + TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + + volume[channelNum] = ((audio_control_cur_2_t*) pBuff)->bCur; + + TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + return true; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an EP +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t ep = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) ep; + + // return tud_control_xfer(rhport, p_request, &tmp, 1); + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an interface +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t itf = TU_U16_LOW(p_request->wIndex); + + (void) channelNum; (void) ctrlSel; (void) itf; + + return false; // Yet not implemented +} + +// Invoked when audio class specific get request received for an entity +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + + // Page 91 in UAC2 specification + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + // uint8_t itf = TU_U16_LOW(p_request->wIndex); // Since we have only one audio function implemented, we do not need the itf value + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // Input terminal (Microphone input) + if (entityID == 1) + { + switch ( ctrlSel ) + { + case AUDIO_TE_CTRL_CONNECTOR: + { + // The terminal connector control only has a get request with only the CUR attribute. + audio_desc_channel_cluster_t ret; + + // Those are dummy values for now + ret.bNrChannels = 1; + ret.bmChannelConfig = 0; + ret.iChannelNames = 0; + + TU_LOG2(" Get terminal connector\r\n"); + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + } + break; + + // Unknown/Unsupported control selector + default: + TU_BREAKPOINT(); + return false; + } + } + + // Feature unit + if (entityID == 2) + { + switch ( ctrlSel ) + { + case AUDIO_FU_CTRL_MUTE: + // Audio control mute cur parameter block consists of only one byte - we thus can send it right away + // There does not exist a range parameter block for mute + TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); + + case AUDIO_FU_CTRL_VOLUME: + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); + + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); + + // Copy values - only for testing - better is version below + audio_control_range_2_n_t(1) + ret; + + ret.wNumSubRanges = 1; + ret.subrange[0].bMin = -90; // -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps + + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + // Clock Source unit + if ( entityID == 4 ) + { + switch ( ctrlSel ) + { + case AUDIO_CS_CTRL_SAM_FREQ: + // channelNum is always zero in this case + switch ( p_request->bRequest ) + { + case AUDIO_CS_REQ_CUR: + TU_LOG2(" Get Sample Freq.\r\n"); + return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + + case AUDIO_CS_REQ_RANGE: + TU_LOG2(" Get Sample Freq. range\r\n"); + return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + case AUDIO_CS_CTRL_CLK_VALID: + // Only cur attribute exists for this request + TU_LOG2(" Get Sample Freq. valid\r\n"); + return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + TU_LOG2(" Unsupported entity: %d\r\n", entityID); + return false; // Yet not implemented +} + +bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) +{ + (void) rhport; + (void) itf; + (void) ep_in; + (void) cur_alt_setting; + + tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_EP_SZ_IN); + + return true; +} + +bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) +{ + (void) rhport; + (void) n_bytes_copied; + (void) itf; + (void) ep_in; + (void) cur_alt_setting; + + for (size_t cnt = 0; cnt < CFG_TUD_AUDIO_EP_SZ_IN/2; cnt++) + { + test_buffer_audio[cnt] = startVal++; + } + + return true; +} + +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) +{ + (void) rhport; + (void) p_request; + startVal = 0; + + return true; +} + +///--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinky_cb(TimerHandle_t xTimer) +{ + (void) xTimer; + static bool led_state = false; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/device/audio_test_freertos/src/plot_audio_samples.py b/examples/device/audio_test_freertos/src/plot_audio_samples.py new file mode 100644 index 000000000..6e3c4978e --- /dev/null +++ b/examples/device/audio_test_freertos/src/plot_audio_samples.py @@ -0,0 +1,34 @@ +import sounddevice as sd +import matplotlib.pyplot as plt +import numpy as np +import platform + +if __name__ == '__main__': + + # If you got "ValueError: No input device matching", that is because your PC name example device + # differently from tested list below. Uncomment the next line to see full list and try to pick correct one + # print(sd.query_devices()) + + fs = 48000 # Sample rate + duration = 100e-3 # Duration of recording + + if platform.system() == 'Windows': + # MME is needed since there are more than one MicNode device APIs (at least in Windows) + device = 'Microphone (MicNode) MME' + elif platform.system() == 'Darwin': + device = 'MicNode' + else: + device ='default' + + myrecording = sd.rec(int(duration * fs), samplerate=fs, channels=1, dtype='int16', device=device) + print('Waiting...') + sd.wait() # Wait until recording is finished + print('Done!') + + time = np.arange(0, duration, 1 / fs) # time vector + plt.plot(time, myrecording) + plt.xlabel('Time [s]') + plt.ylabel('Amplitude') + plt.title('MicNode') + plt.show() + \ No newline at end of file diff --git a/examples/device/audio_test_freertos/src/tusb_config.h b/examples/device/audio_test_freertos/src/tusb_config.h new file mode 100644 index 000000000..598706e78 --- /dev/null +++ b/examples/device/audio_test_freertos/src/tusb_config.h @@ -0,0 +1,121 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_DEVICE_RHPORT_NUM + #define BOARD_DEVICE_RHPORT_NUM 0 +#endif + +#ifndef BOARD_DEVICE_RHPORT_SPEED + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED +#endif + +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + +#ifndef CFG_TUSB_OS + #define CFG_TUSB_OS OPT_OS_FREERTOS +#endif + +// Espressif IDF requires "freertos/" prefix in include path +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + #define CFG_TUSB_OS_INC_PATH freertos/ +#endif + +#ifndef CFG_TUSB_DEBUG + #define CFG_TUSB_DEBUG 0 +#endif + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION + #define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN + #define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_AUDIO 1 +#define CFG_TUD_VENDOR 0 + +//-------------------------------------------------------------------- +// AUDIO CLASS DRIVER CONFIGURATION +//-------------------------------------------------------------------- + +// Have a look into audio_device.h for all configurations + +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_DESC_LEN +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 // Size of control request buffer + +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! +#define CFG_TUD_AUDIO_EP_SZ_IN 48 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channel +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN // Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN + 1 + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_test_freertos/src/usb_descriptors.c b/examples/device/audio_test_freertos/src/usb_descriptors.c new file mode 100644 index 000000000..b8df75e71 --- /dev/null +++ b/examples/device/audio_test_freertos/src/usb_descriptors.c @@ -0,0 +1,165 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "tusb.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ +enum +{ + ITF_NUM_AUDIO_CONTROL = 0, + ITF_NUM_AUDIO_STREAMING, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_ONE_CH_DESC_LEN) + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_AUDIO 0x03 + +#elif TU_CHECK_MCU(OPT_MCU_NRF5X) + // nRF5x ISO can only be endpoint 8 + #define EPNUM_AUDIO 0x08 + +#else + #define EPNUM_AUDIO 0x01 +#endif + +uint8_t const desc_configuration[] = +{ + // Interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) +}; + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + return desc_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "PaniRCorp", // 1: Manufacturer + "MicNode", // 2: Product + "123456", // 3: Serials, should use chip ID + "UAC2", // 4: Audio Interface +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void) langid; + + uint8_t chr_count; + + if ( index == 0) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + }else + { + // Convert ASCII string into UTF-16 + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) chr_count = 31; + + for(uint8_t i=0; i Date: Sat, 27 Apr 2024 21:44:25 +0200 Subject: Update build system. --- .../audio_4_channel_mic_freertos/CMakeLists.txt | 34 ++++-- .../device/audio_4_channel_mic_freertos/Makefile | 17 +-- .../device/audio_4_channel_mic_freertos/README.md | 5 +- .../sdkconfig.defaults | 3 + .../device/audio_4_channel_mic_freertos/skip.txt | 3 +- .../src/CMakeLists.txt | 29 +----- .../src/FreeRTOSConfig/FreeRTOSConfig.h | 45 ++++---- .../src/freertos_hook.c | 115 +++++++++++++++++++++ .../device/audio_4_channel_mic_freertos/src/main.c | 46 ++++++--- .../audio_4_channel_mic_freertos/src/tusb_config.h | 45 ++++---- examples/device/audio_test_freertos/CMakeLists.txt | 34 ++++-- examples/device/audio_test_freertos/Makefile | 20 ++-- examples/device/audio_test_freertos/README.md | 5 +- .../device/audio_test_freertos/sdkconfig.defaults | 3 + .../device/audio_test_freertos/src/CMakeLists.txt | 29 +----- .../src/FreeRTOSConfig/FreeRTOSConfig.h | 45 ++++---- .../device/audio_test_freertos/src/freertos_hook.c | 115 +++++++++++++++++++++ examples/device/audio_test_freertos/src/main.c | 102 +++++++++++------- .../audio_test_freertos/src/plot_audio_samples.py | 2 +- 19 files changed, 484 insertions(+), 213 deletions(-) create mode 100644 examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults create mode 100644 examples/device/audio_4_channel_mic_freertos/src/freertos_hook.c create mode 100644 examples/device/audio_test_freertos/sdkconfig.defaults create mode 100644 examples/device/audio_test_freertos/src/freertos_hook.c (limited to 'examples') diff --git a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt index 639dde99a..eb22014fb 100644 --- a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt +++ b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt @@ -1,22 +1,34 @@ -cmake_minimum_required(VERSION 3.5) - -# TOP is absolute path to root directory of TinyUSB git repo -# needed for esp32sx build. TOOD could be removed later on -set(TOP "../../..") -get_filename_component(TOP "${TOP}" REALPATH) +cmake_minimum_required(VERSION 3.17) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) # gets PROJECT name for the example (e.g. -) family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) -project(${PROJECT}) +project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) -# Check for -DFAMILY= -if(FAMILY MATCHES "^esp32s[2-3]") -else() - message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}") +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() endif() + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Configure compilation flags and libraries for the example with FreeRTOS. +# See the corresponding function in hw/bsp/FAMILY/family.cmake for details. +family_configure_device_example(${PROJECT} freertos) diff --git a/examples/device/audio_4_channel_mic_freertos/Makefile b/examples/device/audio_4_channel_mic_freertos/Makefile index 6c8c43ddd..48a3148f8 100644 --- a/examples/device/audio_4_channel_mic_freertos/Makefile +++ b/examples/device/audio_4_channel_mic_freertos/Makefile @@ -1,23 +1,21 @@ -DEPS_SUBMODULES += lib/FreeRTOS-Kernel - -include ../../../tools/top.mk -include ../../make.mk +include ../../build_system/make/make.mk FREERTOS_SRC = lib/FreeRTOS-Kernel +FREERTOS_PORTABLE_PATH = $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC) INC += \ src \ src/FreeRTOSConfig \ $(TOP)/hw \ $(TOP)/$(FREERTOS_SRC)/include \ - $(TOP)/$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT) + $(TOP)/$(FREERTOS_PORTABLE_SRC) \ # Example source EXAMPLE_SOURCE = \ src/freertos_hook.c \ src/main.c \ src/usb_descriptors.c - + SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) # FreeRTOS source, all files in port folder @@ -26,7 +24,10 @@ SRC_C += \ $(FREERTOS_SRC)/queue.c \ $(FREERTOS_SRC)/tasks.c \ $(FREERTOS_SRC)/timers.c \ - $(subst ../../../,,$(wildcard ../../../$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT)/*.c)) + $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c)) + +SRC_S += \ + $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s)) # Suppress FreeRTOS warnings CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls @@ -34,4 +35,4 @@ CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls # FreeRTOS (lto + Os) linker issue LDFLAGS += -Wl,--undefined=vTaskSwitchContext -include ../../rules.mk +include ../../build_system/make/rules.mk \ No newline at end of file diff --git a/examples/device/audio_4_channel_mic_freertos/README.md b/examples/device/audio_4_channel_mic_freertos/README.md index a35c16195..a99f28bc3 100644 --- a/examples/device/audio_4_channel_mic_freertos/README.md +++ b/examples/device/audio_4_channel_mic_freertos/README.md @@ -6,9 +6,10 @@ $ cd /tinyusb/examples/device/audio_4_channel_mic_freertos ``` -3. Run make in project directory specifying the board +3. Run cmake in project directory specifying the board ``` -$ make BOARD=espressif_s3_devkitc all +$ cmake -DBOARD=espressif_s3_devkitc -B build -G Ninja . +$ ninja.exe -C build ``` 4. Flash the binary onto the esp32-s3 by copy-paste of the full command output by the esp-idf build system replacing **(PORT)** with eg. /dev/ttyUSB0 diff --git a/examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults b/examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults new file mode 100644 index 000000000..83871619e --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_IDF_CMAKE=y +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index ae9b57f1f..83babce12 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -1,3 +1,4 @@ mcu:SAMD11 mcu:SAME5X -mcu:SAMG \ No newline at end of file +mcu:SAMG +family:broadcom_64bit \ No newline at end of file diff --git a/examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt b/examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt index 29e46d979..cef2b46ee 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt +++ b/examples/device/audio_4_channel_mic_freertos/src/CMakeLists.txt @@ -1,27 +1,4 @@ +# This file is for ESP-IDF only idf_component_register(SRCS "main.c" "usb_descriptors.c" - INCLUDE_DIRS "." - REQUIRES freertos soc) - -file(TO_NATIVE_PATH "${TOP}/hw/bsp/${FAMILY}/boards/${BOARD}/board.cmake" board_cmake) - -if(EXISTS ${board_cmake}) - include(${board_cmake}) -endif() - -target_include_directories(${COMPONENT_TARGET} PUBLIC - "${TOP}/hw" - "${TOP}/src" -) - -target_compile_definitions(${COMPONENT_TARGET} PUBLIC - ESP_PLATFORM -) - -target_sources(${COMPONENT_TARGET} PUBLIC - "${TOP}/src/tusb.c" - "${TOP}/src/common/tusb_fifo.c" - "${TOP}/src/device/usbd.c" - "${TOP}/src/device/usbd_control.c" - "${TOP}/src/class/audio/audio_device.c" - "${TOP}/src/portable/espressif/esp32sx/dcd_esp32sx.c" -) \ No newline at end of file + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h index ccb620720..6cc7a6577 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h +++ b/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h @@ -42,6 +42,9 @@ * See http://www.freertos.org/a00110.html. *----------------------------------------------------------*/ +// skip if included from IAR assembler +#ifndef __IASMARM__ + // Include MCU header #include "bsp/board_mcu.h" @@ -53,9 +56,12 @@ #if CFG_TUSB_MCU == OPT_MCU_MM32F327X extern u32 SystemCoreClock; #else + // FIXME cause redundant-decls warnings extern uint32_t SystemCoreClock; #endif +#endif + /* Cortex M23/M33 port configuration. */ #define configENABLE_MPU 0 #define configENABLE_FPU 1 @@ -68,14 +74,14 @@ #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 #define configUSE_MUTEXES 1 #define configUSE_RECURSIVE_MUTEXES 1 #define configUSE_COUNTING_SEMAPHORES 1 -#define configQUEUE_REGISTRY_SIZE 2 +#define configQUEUE_REGISTRY_SIZE 4 #define configUSE_QUEUE_SETS 0 #define configUSE_TIME_SLICING 0 #define configUSE_NEWLIB_REENTRANT 0 @@ -90,6 +96,7 @@ #define configUSE_TICK_HOOK 0 #define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning #define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 /* Run time and task stats gathering related definitions. */ #define configGENERATE_RUN_TIME_STATS 0 @@ -124,29 +131,12 @@ #define INCLUDE_xEventGroupSetBitFromISR 0 #define INCLUDE_xTimerPendFunctionCall 0 -/* Define to trap errors during development. */ -// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 -#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) - #define configASSERT(_exp) \ - do {\ - if ( !(_exp) ) { \ - volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ - if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ - taskDISABLE_INTERRUPTS(); \ - __asm("BKPT #0\n"); \ - }\ - }\ - } while(0) -#else - #define configASSERT( x ) -#endif - #ifdef __RX__ /* Renesas RX series */ -#define vSoftwareInterruptISR INT_Excep_ICU_SWINT -#define vTickISR INT_Excep_CMT0_CMI0 -#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) -#define configKERNEL_INTERRUPT_PRIORITY 1 +#define vSoftwareInterruptISR INT_Excep_ICU_SWINT +#define vTickISR INT_Excep_CMT0_CMI0 +#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) +#define configKERNEL_INTERRUPT_PRIORITY 1 #define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 #else @@ -162,9 +152,18 @@ #if defined(__NVIC_PRIO_BITS) // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h #define configPRIO_BITS __NVIC_PRIO_BITS + #elif defined(__ECLIC_INTCTLBITS) // RISC-V Bumblebee core from nuclei #define configPRIO_BITS __ECLIC_INTCTLBITS + +#elif defined(__IASMARM__) + // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS. + // Therefore we will hard coded it to minimum value of 2 to get pass ci build. + // IAR user must update this to correct value of the target MCU + #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU" + #define configPRIO_BITS 2 + #else #error "FreeRTOS configPRIO_BITS to be defined" #endif diff --git a/examples/device/audio_4_channel_mic_freertos/src/freertos_hook.c b/examples/device/audio_4_channel_mic_freertos/src/freertos_hook.c new file mode 100644 index 000000000..4920e3fae --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/freertos_hook.c @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "FreeRTOS.h" +#include "task.h" +#include "common/tusb_common.h" + + +void vApplicationMallocFailedHook(void) +{ + taskDISABLE_INTERRUPTS(); + TU_ASSERT(false, ); +} + +void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName) +{ + (void) pxTask; + (void) pcTaskName; + + taskDISABLE_INTERRUPTS(); + TU_ASSERT(false, ); +} + +/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an + * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is + * used by the Idle task. */ +void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) +{ + /* If the buffers to be provided to the Idle task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} + +/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the + * application must provide an implementation of vApplicationGetTimerTaskMemory() + * to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) +{ + /* If the buffers to be provided to the Timer task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} + +#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X +#include "iodefine.h" +void vApplicationSetupTimerInterrupt(void) +{ + /* Enable CMT0 */ + unsigned short oldPRCR = SYSTEM.PRCR.WORD; + SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); + MSTP(CMT0) = 0; + SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR; + + CMT0.CMCNT = 0; + CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); + CMT0.CMCR.WORD = TU_BIT(6) | 2; + IR(CMT0, CMI0) = 0; + IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY; + IEN(CMT0, CMI0) = 1; + CMT.CMSTR0.BIT.STR0 = 1; +} +#endif diff --git a/examples/device/audio_4_channel_mic_freertos/src/main.c b/examples/device/audio_4_channel_mic_freertos/src/main.c index 3b9795946..980b9540b 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/main.c +++ b/examples/device/audio_4_channel_mic_freertos/src/main.c @@ -35,19 +35,30 @@ #include #include -#include "bsp/board.h" +#include "bsp/board_api.h" #include "tusb.h" -// ESP-IDF need "freertos/" prefix in include path. -// CFG_TUSB_OS_INC_PATH should be defined accordingly. -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "freertos/task.h" -#include "freertos/timers.h" - -#define USBD_STACK_SIZE 4096 - +#if TUP_MCU_ESPRESSIF + // ESP-IDF need "freertos/" prefix in include path. + // CFG_TUSB_OS_INC_PATH should be defined accordingly. + #include "freertos/FreeRTOS.h" + #include "freertos/semphr.h" + #include "freertos/queue.h" + #include "freertos/task.h" + #include "freertos/timers.h" + + #define USBD_STACK_SIZE 4096 +#else + + #include "FreeRTOS.h" + #include "semphr.h" + #include "queue.h" + #include "task.h" + #include "timers.h" + + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE (4*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) +#endif //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES @@ -112,8 +123,12 @@ int main(void) sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; +#if configSUPPORT_STATIC_ALLOCATION // 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); +#else + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); +#endif // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 #if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) @@ -136,9 +151,14 @@ void usb_device_task(void* param) { (void) param; + // init device stack on configured roothub port // This should be called after scheduler/kernel is started. // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. - tusb_init(); + tud_init(BOARD_TUD_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } // RTOS forever loop while (1) diff --git a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h index f13865084..010315c27 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h @@ -30,6 +30,20 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 +#endif + +// RHPort max operational speed can defined by board.mk +#ifndef BOARD_TUD_MAX_SPEED +#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + //-------------------------------------------------------------------- // COMMON CONFIGURATION //-------------------------------------------------------------------- @@ -39,32 +53,25 @@ extern "C" { #error CFG_TUSB_MCU must be defined #endif -// RHPort number used for device can be defined by board.mk, default to port 0 -#ifndef BOARD_DEVICE_RHPORT_NUM - #define BOARD_DEVICE_RHPORT_NUM 0 -#endif - -#ifndef BOARD_DEVICE_RHPORT_SPEED - #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED -#endif - -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE - +// This examples use FreeRTOS #ifndef CFG_TUSB_OS - #define CFG_TUSB_OS OPT_OS_FREERTOS +#define CFG_TUSB_OS OPT_OS_FREERTOS #endif // Espressif IDF requires "freertos/" prefix in include path -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - #define CFG_TUSB_OS_INC_PATH freertos/ +#if TUP_MCU_ESPRESSIF +#define CFG_TUSB_OS_INC_PATH freertos/ #endif #ifndef CFG_TUSB_DEBUG - #define CFG_TUSB_DEBUG 0 +#define CFG_TUSB_DEBUG 0 #endif -// CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 +// Enable Device stack +#define CFG_TUD_ENABLED 1 + +// Default is max speed that hardware controller could support with on-chip PHY +#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put @@ -78,7 +85,7 @@ extern "C" { #endif #ifndef CFG_TUSB_MEM_ALIGN -#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) #endif //-------------------------------------------------------------------- @@ -90,11 +97,11 @@ extern "C" { #endif //------------- CLASS -------------// +#define CFG_TUD_AUDIO 1 #define CFG_TUD_CDC 0 #define CFG_TUD_MSC 0 #define CFG_TUD_HID 0 #define CFG_TUD_MIDI 0 -#define CFG_TUD_AUDIO 1 #define CFG_TUD_VENDOR 0 //-------------------------------------------------------------------- diff --git a/examples/device/audio_test_freertos/CMakeLists.txt b/examples/device/audio_test_freertos/CMakeLists.txt index 639dde99a..eb22014fb 100644 --- a/examples/device/audio_test_freertos/CMakeLists.txt +++ b/examples/device/audio_test_freertos/CMakeLists.txt @@ -1,22 +1,34 @@ -cmake_minimum_required(VERSION 3.5) - -# TOP is absolute path to root directory of TinyUSB git repo -# needed for esp32sx build. TOOD could be removed later on -set(TOP "../../..") -get_filename_component(TOP "${TOP}" REALPATH) +cmake_minimum_required(VERSION 3.17) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) # gets PROJECT name for the example (e.g. -) family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) -project(${PROJECT}) +project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) -# Check for -DFAMILY= -if(FAMILY MATCHES "^esp32s[2-3]") -else() - message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}") +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() endif() + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Configure compilation flags and libraries for the example with FreeRTOS. +# See the corresponding function in hw/bsp/FAMILY/family.cmake for details. +family_configure_device_example(${PROJECT} freertos) diff --git a/examples/device/audio_test_freertos/Makefile b/examples/device/audio_test_freertos/Makefile index e5b88df5e..48a3148f8 100644 --- a/examples/device/audio_test_freertos/Makefile +++ b/examples/device/audio_test_freertos/Makefile @@ -1,22 +1,19 @@ -DEPS_SUBMODULES += lib/FreeRTOS-Kernel - -include ../../../tools/top.mk -include ../../make.mk +include ../../build_system/make/make.mk FREERTOS_SRC = lib/FreeRTOS-Kernel +FREERTOS_PORTABLE_PATH = $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC) INC += \ src \ src/FreeRTOSConfig \ $(TOP)/hw \ $(TOP)/$(FREERTOS_SRC)/include \ - $(TOP)/$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT) - + $(TOP)/$(FREERTOS_PORTABLE_SRC) \ + # Example source EXAMPLE_SOURCE = \ src/freertos_hook.c \ src/main.c \ - src/msc_disk.c \ src/usb_descriptors.c SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) @@ -27,12 +24,15 @@ SRC_C += \ $(FREERTOS_SRC)/queue.c \ $(FREERTOS_SRC)/tasks.c \ $(FREERTOS_SRC)/timers.c \ - $(subst ../../../,,$(wildcard ../../../$(FREERTOS_SRC)/portable/GCC/$(FREERTOS_PORT)/*.c)) + $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c)) + +SRC_S += \ + $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s)) # Suppress FreeRTOS warnings -CFLAGS += -Wno-error=cast-qual +CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls # FreeRTOS (lto + Os) linker issue LDFLAGS += -Wl,--undefined=vTaskSwitchContext -include ../../rules.mk \ No newline at end of file +include ../../build_system/make/rules.mk \ No newline at end of file diff --git a/examples/device/audio_test_freertos/README.md b/examples/device/audio_test_freertos/README.md index 077a2a1b6..dd70af44b 100644 --- a/examples/device/audio_test_freertos/README.md +++ b/examples/device/audio_test_freertos/README.md @@ -6,9 +6,10 @@ $ cd /tinyusb/examples/device/audio_test_freertos ``` -3. Run make in project directory specifying the board +3. Run cmake in project directory specifying the board ``` -$ make BOARD=espressif_s3_devkitc all +$ cmake -DBOARD=espressif_s3_devkitc -B build -G Ninja . +$ ninja.exe -C build ``` 4. Flash the binary onto the esp32-s3 by copy-paste of the full command output by the esp-idf build system replacing **(PORT)** with eg. /dev/ttyUSB0 diff --git a/examples/device/audio_test_freertos/sdkconfig.defaults b/examples/device/audio_test_freertos/sdkconfig.defaults new file mode 100644 index 000000000..83871619e --- /dev/null +++ b/examples/device/audio_test_freertos/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_IDF_CMAKE=y +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y diff --git a/examples/device/audio_test_freertos/src/CMakeLists.txt b/examples/device/audio_test_freertos/src/CMakeLists.txt index 29e46d979..cef2b46ee 100644 --- a/examples/device/audio_test_freertos/src/CMakeLists.txt +++ b/examples/device/audio_test_freertos/src/CMakeLists.txt @@ -1,27 +1,4 @@ +# This file is for ESP-IDF only idf_component_register(SRCS "main.c" "usb_descriptors.c" - INCLUDE_DIRS "." - REQUIRES freertos soc) - -file(TO_NATIVE_PATH "${TOP}/hw/bsp/${FAMILY}/boards/${BOARD}/board.cmake" board_cmake) - -if(EXISTS ${board_cmake}) - include(${board_cmake}) -endif() - -target_include_directories(${COMPONENT_TARGET} PUBLIC - "${TOP}/hw" - "${TOP}/src" -) - -target_compile_definitions(${COMPONENT_TARGET} PUBLIC - ESP_PLATFORM -) - -target_sources(${COMPONENT_TARGET} PUBLIC - "${TOP}/src/tusb.c" - "${TOP}/src/common/tusb_fifo.c" - "${TOP}/src/device/usbd.c" - "${TOP}/src/device/usbd_control.c" - "${TOP}/src/class/audio/audio_device.c" - "${TOP}/src/portable/espressif/esp32sx/dcd_esp32sx.c" -) \ No newline at end of file + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h index ccb620720..6cc7a6577 100644 --- a/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h +++ b/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h @@ -42,6 +42,9 @@ * See http://www.freertos.org/a00110.html. *----------------------------------------------------------*/ +// skip if included from IAR assembler +#ifndef __IASMARM__ + // Include MCU header #include "bsp/board_mcu.h" @@ -53,9 +56,12 @@ #if CFG_TUSB_MCU == OPT_MCU_MM32F327X extern u32 SystemCoreClock; #else + // FIXME cause redundant-decls warnings extern uint32_t SystemCoreClock; #endif +#endif + /* Cortex M23/M33 port configuration. */ #define configENABLE_MPU 0 #define configENABLE_FPU 1 @@ -68,14 +74,14 @@ #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 #define configUSE_MUTEXES 1 #define configUSE_RECURSIVE_MUTEXES 1 #define configUSE_COUNTING_SEMAPHORES 1 -#define configQUEUE_REGISTRY_SIZE 2 +#define configQUEUE_REGISTRY_SIZE 4 #define configUSE_QUEUE_SETS 0 #define configUSE_TIME_SLICING 0 #define configUSE_NEWLIB_REENTRANT 0 @@ -90,6 +96,7 @@ #define configUSE_TICK_HOOK 0 #define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning #define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 /* Run time and task stats gathering related definitions. */ #define configGENERATE_RUN_TIME_STATS 0 @@ -124,29 +131,12 @@ #define INCLUDE_xEventGroupSetBitFromISR 0 #define INCLUDE_xTimerPendFunctionCall 0 -/* Define to trap errors during development. */ -// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 -#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) - #define configASSERT(_exp) \ - do {\ - if ( !(_exp) ) { \ - volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ - if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ - taskDISABLE_INTERRUPTS(); \ - __asm("BKPT #0\n"); \ - }\ - }\ - } while(0) -#else - #define configASSERT( x ) -#endif - #ifdef __RX__ /* Renesas RX series */ -#define vSoftwareInterruptISR INT_Excep_ICU_SWINT -#define vTickISR INT_Excep_CMT0_CMI0 -#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) -#define configKERNEL_INTERRUPT_PRIORITY 1 +#define vSoftwareInterruptISR INT_Excep_ICU_SWINT +#define vTickISR INT_Excep_CMT0_CMI0 +#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) +#define configKERNEL_INTERRUPT_PRIORITY 1 #define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 #else @@ -162,9 +152,18 @@ #if defined(__NVIC_PRIO_BITS) // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h #define configPRIO_BITS __NVIC_PRIO_BITS + #elif defined(__ECLIC_INTCTLBITS) // RISC-V Bumblebee core from nuclei #define configPRIO_BITS __ECLIC_INTCTLBITS + +#elif defined(__IASMARM__) + // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS. + // Therefore we will hard coded it to minimum value of 2 to get pass ci build. + // IAR user must update this to correct value of the target MCU + #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU" + #define configPRIO_BITS 2 + #else #error "FreeRTOS configPRIO_BITS to be defined" #endif diff --git a/examples/device/audio_test_freertos/src/freertos_hook.c b/examples/device/audio_test_freertos/src/freertos_hook.c new file mode 100644 index 000000000..4920e3fae --- /dev/null +++ b/examples/device/audio_test_freertos/src/freertos_hook.c @@ -0,0 +1,115 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "FreeRTOS.h" +#include "task.h" +#include "common/tusb_common.h" + + +void vApplicationMallocFailedHook(void) +{ + taskDISABLE_INTERRUPTS(); + TU_ASSERT(false, ); +} + +void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName) +{ + (void) pxTask; + (void) pcTaskName; + + taskDISABLE_INTERRUPTS(); + TU_ASSERT(false, ); +} + +/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an + * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is + * used by the Idle task. */ +void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) +{ + /* If the buffers to be provided to the Idle task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} + +/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the + * application must provide an implementation of vApplicationGetTimerTaskMemory() + * to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) +{ + /* If the buffers to be provided to the Timer task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} + +#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X +#include "iodefine.h" +void vApplicationSetupTimerInterrupt(void) +{ + /* Enable CMT0 */ + unsigned short oldPRCR = SYSTEM.PRCR.WORD; + SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); + MSTP(CMT0) = 0; + SYSTEM.PRCR.WORD = (0xA5u<<8) | oldPRCR; + + CMT0.CMCNT = 0; + CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); + CMT0.CMCR.WORD = TU_BIT(6) | 2; + IR(CMT0, CMI0) = 0; + IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY; + IEN(CMT0, CMI0) = 1; + CMT.CMSTR0.BIT.STR0 = 1; +} +#endif diff --git a/examples/device/audio_test_freertos/src/main.c b/examples/device/audio_test_freertos/src/main.c index 5744b1b48..f32e3e5a6 100644 --- a/examples/device/audio_test_freertos/src/main.c +++ b/examples/device/audio_test_freertos/src/main.c @@ -35,19 +35,32 @@ #include #include -#include "bsp/board.h" +#include "bsp/board_api.h" #include "tusb.h" -// ESP-IDF need "freertos/" prefix in include path. -// CFG_TUSB_OS_INC_PATH should be defined accordingly. -#include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "freertos/task.h" -#include "freertos/timers.h" - -#define USBD_STACK_SIZE 4096 +#if TUP_MCU_ESPRESSIF + // ESP-IDF need "freertos/" prefix in include path. + // CFG_TUSB_OS_INC_PATH should be defined accordingly. + #include "freertos/FreeRTOS.h" + #include "freertos/semphr.h" + #include "freertos/queue.h" + #include "freertos/task.h" + #include "freertos/timers.h" + + #define USBD_STACK_SIZE 4096 +#else + + #include "FreeRTOS.h" + #include "semphr.h" + #include "queue.h" + #include "task.h" + #include "timers.h" + + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE (4*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) +#endif +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES @@ -68,12 +81,16 @@ enum { BLINK_SUSPENDED = 2500, }; -// static timer -StaticTimer_t blinky_tmdef; -TimerHandle_t blinky_tm; +// static task +#if configSUPPORT_STATIC_ALLOCATION +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; + StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; +#endif +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states @@ -90,7 +107,7 @@ audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range stat uint16_t test_buffer_audio[CFG_TUD_AUDIO_EP_SZ_IN/2]; uint16_t startVal = 0; -void led_blinky_cb(TimerHandle_t xTimer); +void led_blinking_task(void* param); void usb_device_task(void* param); void audio_task(void); @@ -99,10 +116,6 @@ int main(void) { board_init(); - // 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); - // Init values sampFreq = AUDIO_SAMPLE_RATE; clkValid = 1; @@ -112,8 +125,16 @@ int main(void) sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; +#if configSUPPORT_STATIC_ALLOCATION + // blinky task + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); + // 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); +#else + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); +#endif // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 #if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) @@ -136,9 +157,14 @@ void usb_device_task(void* param) { (void) param; + // init device stack on configured roothub port // This should be called after scheduler/kernel is started. // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. - tusb_init(); + tud_init(BOARD_TUD_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } // RTOS forever loop while (1) @@ -153,30 +179,26 @@ void usb_device_task(void* param) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); +void tud_mount_cb(void) { + blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); +void tud_umount_cb(void) { + blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0); + blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); +void tud_resume_cb(void) { + blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } //--------------------------------------------------------------------+ @@ -476,11 +498,17 @@ bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const ///--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinky_cb(TimerHandle_t xTimer) -{ - (void) xTimer; +void led_blinking_task(void* param) { + (void) param; + static uint32_t start_ms = 0; static bool led_state = false; - board_led_write(led_state); - led_state = 1 - led_state; // toggle + while (1) { + // Blink every interval ms + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } } diff --git a/examples/device/audio_test_freertos/src/plot_audio_samples.py b/examples/device/audio_test_freertos/src/plot_audio_samples.py index 6e3c4978e..6f1518be5 100644 --- a/examples/device/audio_test_freertos/src/plot_audio_samples.py +++ b/examples/device/audio_test_freertos/src/plot_audio_samples.py @@ -10,7 +10,7 @@ if __name__ == '__main__': # print(sd.query_devices()) fs = 48000 # Sample rate - duration = 100e-3 # Duration of recording + duration = 1000e-3 # Duration of recording if platform.system() == 'Windows': # MME is needed since there are more than one MicNode device APIs (at least in Windows) -- cgit v1.3.1 From 7dd26877de2ed85a608190a76acf960e256c88bf Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 27 Apr 2024 22:16:30 +0200 Subject: Update audio_test & audio_test_freertos examples to work with high-speed. --- examples/device/audio_test/src/main.c | 10 +++------- examples/device/audio_test/src/tusb_config.h | 7 ++++--- examples/device/audio_test_freertos/src/main.c | 10 +++------- examples/device/audio_test_freertos/src/tusb_config.h | 7 ++++--- 4 files changed, 14 insertions(+), 20 deletions(-) (limited to 'examples') diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 06783ccfb..f79bb4468 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -42,10 +42,6 @@ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -#ifndef AUDIO_SAMPLE_RATE -#define AUDIO_SAMPLE_RATE 48000 -#endif - /* Blink pattern * - 250 ms : device not mounted * - 1000 ms : device mounted @@ -90,12 +86,12 @@ int main(void) } // Init values - sampFreq = AUDIO_SAMPLE_RATE; + sampFreq = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; clkValid = 1; sampleFreqRng.wNumSubRanges = 1; - sampleFreqRng.subrange[0].bMin = AUDIO_SAMPLE_RATE; - sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMin = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMax = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; while (1) diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 9f38612a9..8c021e23c 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -106,6 +106,7 @@ extern "C" { //-------------------------------------------------------------------- // Have a look into audio_device.h for all configurations +#define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_DESC_LEN #define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) @@ -114,9 +115,9 @@ extern "C" { #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! -#define CFG_TUD_AUDIO_EP_SZ_IN (48 + 1) * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x CFG_TUD_AUDIO_N_CHANNELS_TX Channels - One extra sample is needed for asynchronous transfer adjustment, see feedback EP -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN // Maximum EP IN size for all AS alternate settings used -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN + 1 +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 8 : 1) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device #ifdef __cplusplus } diff --git a/examples/device/audio_test_freertos/src/main.c b/examples/device/audio_test_freertos/src/main.c index f32e3e5a6..cf1c336a9 100644 --- a/examples/device/audio_test_freertos/src/main.c +++ b/examples/device/audio_test_freertos/src/main.c @@ -66,10 +66,6 @@ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -#ifndef AUDIO_SAMPLE_RATE -#define AUDIO_SAMPLE_RATE 48000 -#endif - /* Blink pattern * - 250 ms : device not mounted * - 1000 ms : device mounted @@ -117,12 +113,12 @@ int main(void) board_init(); // Init values - sampFreq = AUDIO_SAMPLE_RATE; + sampFreq = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; clkValid = 1; sampleFreqRng.wNumSubRanges = 1; - sampleFreqRng.subrange[0].bMin = AUDIO_SAMPLE_RATE; - sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMin = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; + sampleFreqRng.subrange[0].bMax = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; #if configSUPPORT_STATIC_ALLOCATION diff --git a/examples/device/audio_test_freertos/src/tusb_config.h b/examples/device/audio_test_freertos/src/tusb_config.h index 598706e78..61ddadb9f 100644 --- a/examples/device/audio_test_freertos/src/tusb_config.h +++ b/examples/device/audio_test_freertos/src/tusb_config.h @@ -102,6 +102,7 @@ extern "C" { //-------------------------------------------------------------------- // Have a look into audio_device.h for all configurations +#define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_DESC_LEN #define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) @@ -110,9 +111,9 @@ extern "C" { #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! -#define CFG_TUD_AUDIO_EP_SZ_IN 48 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x 1 Channel -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN // Maximum EP IN size for all AS alternate settings used -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN + 1 +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 8 : 1) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device #ifdef __cplusplus } -- cgit v1.3.1 From bb89a5a5bf0cb13f895675f4480801e52d822203 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 27 Apr 2024 22:17:10 +0200 Subject: audio_test_freertos : merge changes from audio_test. --- examples/device/audio_test_freertos/src/main.c | 12 ++-- .../device/audio_test_freertos/src/tusb_config.h | 48 +++++++------ .../audio_test_freertos/src/usb_descriptors.c | 78 +++++++++++++--------- 3 files changed, 82 insertions(+), 56 deletions(-) (limited to 'examples') diff --git a/examples/device/audio_test_freertos/src/main.c b/examples/device/audio_test_freertos/src/main.c index cf1c336a9..903c97d20 100644 --- a/examples/device/audio_test_freertos/src/main.c +++ b/examples/device/audio_test_freertos/src/main.c @@ -100,7 +100,7 @@ audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data -uint16_t test_buffer_audio[CFG_TUD_AUDIO_EP_SZ_IN/2]; +uint16_t test_buffer_audio[(CFG_TUD_AUDIO_EP_SZ_IN - 2) / 2]; uint16_t startVal = 0; void led_blinking_task(void* param); @@ -283,7 +283,7 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * // Request uses format layout 2 TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); - volume[channelNum] = ((audio_control_cur_2_t*) pBuff)->bCur; + volume[channelNum] = (uint16_t) ((audio_control_cur_2_t*) pBuff)->bCur; TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); return true; @@ -352,7 +352,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * // Those are dummy values for now ret.bNrChannels = 1; - ret.bmChannelConfig = 0; + ret.bmChannelConfig = (audio_channel_config_t) 0; ret.iChannelNames = 0; TU_LOG2(" Get terminal connector\r\n"); @@ -461,7 +461,7 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u (void) ep_in; (void) cur_alt_setting; - tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_EP_SZ_IN); + tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_EP_SZ_IN - 2); return true; } @@ -474,7 +474,7 @@ bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uin (void) ep_in; (void) cur_alt_setting; - for (size_t cnt = 0; cnt < CFG_TUD_AUDIO_EP_SZ_IN/2; cnt++) + for (size_t cnt = 0; cnt < (CFG_TUD_AUDIO_EP_SZ_IN - 2) / 2; cnt++) { test_buffer_audio[cnt] = startVal++; } @@ -491,7 +491,7 @@ bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const return true; } -///--------------------------------------------------------------------+ +//--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ void led_blinking_task(void* param) { diff --git a/examples/device/audio_test_freertos/src/tusb_config.h b/examples/device/audio_test_freertos/src/tusb_config.h index 61ddadb9f..8b376a4c3 100644 --- a/examples/device/audio_test_freertos/src/tusb_config.h +++ b/examples/device/audio_test_freertos/src/tusb_config.h @@ -30,39 +30,49 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 +#endif + +// RHPort max operational speed can defined by board.mk +#ifndef BOARD_TUD_MAX_SPEED +#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + //-------------------------------------------------------------------- // COMMON CONFIGURATION //-------------------------------------------------------------------- // defined by compiler flags for flexibility #ifndef CFG_TUSB_MCU - #error CFG_TUSB_MCU must be defined -#endif - -// RHPort number used for device can be defined by board.mk, default to port 0 -#ifndef BOARD_DEVICE_RHPORT_NUM - #define BOARD_DEVICE_RHPORT_NUM 0 -#endif - -#ifndef BOARD_DEVICE_RHPORT_SPEED - #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED +#error CFG_TUSB_MCU must be defined #endif -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE - +// This examples use FreeRTOS #ifndef CFG_TUSB_OS - #define CFG_TUSB_OS OPT_OS_FREERTOS +#define CFG_TUSB_OS OPT_OS_FREERTOS #endif // Espressif IDF requires "freertos/" prefix in include path -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - #define CFG_TUSB_OS_INC_PATH freertos/ +#if TUP_MCU_ESPRESSIF +#define CFG_TUSB_OS_INC_PATH freertos/ #endif #ifndef CFG_TUSB_DEBUG - #define CFG_TUSB_DEBUG 0 +#define CFG_TUSB_DEBUG 0 #endif +// Enable Device stack +#define CFG_TUD_ENABLED 1 + +// Default is max speed that hardware controller could support with on-chip PHY +#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED + // CFG_TUSB_DEBUG is defined by compiler in DEBUG build // #define CFG_TUSB_DEBUG 0 @@ -74,11 +84,11 @@ extern "C" { * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) */ #ifndef CFG_TUSB_MEM_SECTION - #define CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION #endif #ifndef CFG_TUSB_MEM_ALIGN - #define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) #endif //-------------------------------------------------------------------- @@ -90,11 +100,11 @@ extern "C" { #endif //------------- CLASS -------------// +#define CFG_TUD_AUDIO 1 #define CFG_TUD_CDC 0 #define CFG_TUD_MSC 0 #define CFG_TUD_HID 0 #define CFG_TUD_MIDI 0 -#define CFG_TUD_AUDIO 1 #define CFG_TUD_VENDOR 0 //-------------------------------------------------------------------- diff --git a/examples/device/audio_test_freertos/src/usb_descriptors.c b/examples/device/audio_test_freertos/src/usb_descriptors.c index b8df75e71..9864377f6 100644 --- a/examples/device/audio_test_freertos/src/usb_descriptors.c +++ b/examples/device/audio_test_freertos/src/usb_descriptors.c @@ -23,6 +23,7 @@ * */ +#include "bsp/board_api.h" #include "tusb.h" /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. @@ -44,7 +45,7 @@ tusb_desc_device_t const desc_device = .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, - // Use Interface Association Descriptor (IAD) for CDC + // Use Interface Association Descriptor (IAD) for Audio // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) .bDeviceClass = TUSB_CLASS_MISC, .bDeviceSubClass = MISC_SUBCLASS_COMMON, @@ -96,11 +97,11 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), - // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) + // Interface number, string index, EP Out & EP In address, EP size + TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR @@ -116,50 +117,65 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) // String Descriptors //--------------------------------------------------------------------+ +// String Descriptor Index +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, +}; + // array of pointer to string descriptors char const* string_desc_arr [] = { - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "PaniRCorp", // 1: Manufacturer - "MicNode", // 2: Product - "123456", // 3: Serials, should use chip ID - "UAC2", // 4: Audio Interface + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "PaniRCorp", // 1: Manufacturer + "MicNode", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "UAC2", // 4: Audio Interface + }; -static uint16_t _desc_str[32]; +static uint16_t _desc_str[32 + 1]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) -{ +uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void) langid; + size_t chr_count; + + switch ( index ) { + case STRID_LANGID: + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + break; - uint8_t chr_count; + case STRID_SERIAL: + chr_count = board_usb_get_serial(_desc_str + 1, 32); + break; - if ( index == 0) - { - memcpy(&_desc_str[1], string_desc_arr[0], 2); - chr_count = 1; - }else - { - // Convert ASCII string into UTF-16 + default: + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; - const char* str = string_desc_arr[index]; + const char *str = string_desc_arr[index]; - // Cap at max char - chr_count = strlen(str); - if ( chr_count > 31 ) chr_count = 31; + // Cap at max char + chr_count = strlen(str); + size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type + if ( chr_count > max_count ) chr_count = max_count; - for(uint8_t i=0; i Date: Sun, 28 Apr 2024 00:09:06 +0200 Subject: audio_4_channel_mic_freertos : merge changes from audio_4_channel_mic. --- .../audio_4_channel_mic_freertos/CMakeLists.txt | 5 + .../sdkconfig.defaults | 1 + .../device/audio_4_channel_mic_freertos/src/main.c | 150 +++++++++++++++------ .../audio_4_channel_mic_freertos/src/tusb_config.h | 41 ++++-- .../src/usb_descriptors.c | 74 +++++----- 5 files changed, 189 insertions(+), 82 deletions(-) (limited to 'examples') diff --git a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt index eb22014fb..e8ca3751d 100644 --- a/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt +++ b/examples/device/audio_4_channel_mic_freertos/CMakeLists.txt @@ -29,6 +29,11 @@ target_include_directories(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) +# Add libm for GCC +if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_libraries(${PROJECT} PUBLIC m) +endif() + # Configure compilation flags and libraries for the example with FreeRTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. family_configure_device_example(${PROJECT} freertos) diff --git a/examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults b/examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults index 83871619e..eaa9fb902 100644 --- a/examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults +++ b/examples/device/audio_4_channel_mic_freertos/sdkconfig.defaults @@ -1,3 +1,4 @@ CONFIG_IDF_CMAKE=y +CONFIG_FREERTOS_HZ=1000 CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y diff --git a/examples/device/audio_4_channel_mic_freertos/src/main.c b/examples/device/audio_4_channel_mic_freertos/src/main.c index 980b9540b..7d953e71c 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/main.c +++ b/examples/device/audio_4_channel_mic_freertos/src/main.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "bsp/board_api.h" #include "tusb.h" @@ -60,13 +61,13 @@ #define USBD_STACK_SIZE (4*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) #endif +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define AUDIO_STACK_SIZE configMINIMAL_STACK_SIZE + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ - -#ifndef AUDIO_SAMPLE_RATE -#define AUDIO_SAMPLE_RATE 48000 -#endif +#define AUDIO_SAMPLE_RATE CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE /* Blink pattern * - 250 ms : device not mounted @@ -79,12 +80,19 @@ enum { BLINK_SUSPENDED = 2500, }; -// static timer -StaticTimer_t blinky_tmdef; -TimerHandle_t blinky_tm; +// static task +#if configSUPPORT_STATIC_ALLOCATION +StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StaticTask_t blinky_taskdef; + StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; +StackType_t audio_stack[AUDIO_STACK_SIZE]; +StaticTask_t audio_taskdef; +#endif + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states @@ -97,23 +105,23 @@ uint8_t clkValid; audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state -// Audio test data -uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_EP_SZ_IN/2]; // Ensure half word aligned -uint16_t samples[] = {0, 0, 0, 0}; +#if CFG_TUD_AUDIO_ENABLE_ENCODING +// Audio test data, each buffer contains 2 channels, buffer[0] for CH0-1, buffer[1] for CH1-2 +uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000/CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; +#else +// Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 +uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000]; +#endif -void led_blinky_cb(TimerHandle_t xTimer); +void led_blinking_task(void* param); void usb_device_task(void* param); -void audio_task(void); +void audio_task(void* param); /*------------- MAIN -------------*/ int main(void) { board_init(); - // 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); - // Init values sampFreq = AUDIO_SAMPLE_RATE; clkValid = 1; @@ -123,11 +131,58 @@ int main(void) sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; + // Generate dummy data +#if CFG_TUD_AUDIO_ENABLE_ENCODING + uint16_t * p_buff = i2s_dummy_buffer[0]; + uint16_t dataVal = 0; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH0 saw wave + *p_buff++ = dataVal; + // CH1 inverted saw wave + *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; + dataVal+= 32; + } + p_buff = i2s_dummy_buffer[1]; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH3 square wave + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; + // CH4 sinus wave + float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); + *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); + } +#else + uint16_t * p_buff = i2s_dummy_buffer; + uint16_t dataVal = 0; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH0 saw wave + *p_buff++ = dataVal; + // CH1 inverted saw wave + *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; + dataVal+= 32; + // CH3 square wave + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; + // CH4 sinus wave + float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); + *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); + } +#endif + #if configSUPPORT_STATIC_ALLOCATION + // blinky task + xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); + // Create a task for tinyusb device stack xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); + + // Create a task for audio + xTaskCreateStatic(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES-1, audio_stack, &audio_taskdef); #else + xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); #endif // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 @@ -175,13 +230,13 @@ void usb_device_task(void* param) // Invoked when device is mounted void tud_mount_cb(void) { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); + blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted void tud_umount_cb(void) { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); + blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended @@ -190,23 +245,36 @@ void tud_umount_cb(void) void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0); + blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed void tud_resume_cb(void) { - xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); + blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } //--------------------------------------------------------------------+ // AUDIO Task //--------------------------------------------------------------------+ -void audio_task(void) +void audio_task(void* param) { - // Yet to be filled - e.g. put meas data into TX FIFOs etc. - // asm("nop"); + (void) param; + // Yet to be filled - e.g. read audio from I2S buffer. + // Here we simulate a I2S receive callback every 1ms. + while (1) { + vTaskDelay(1); +#if CFG_TUD_AUDIO_ENABLE_ENCODING + // Write I2S buffer into FIFO + for (uint8_t cnt=0; cnt < 2; cnt++) + { + tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX); + } +#else + tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); +#endif + } } //--------------------------------------------------------------------+ @@ -427,7 +495,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * { case AUDIO_CS_REQ_CUR: TU_LOG2(" Get Sample Freq.\r\n"); - return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + // Buffered control transfer is needed for IN flow control to work + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); case AUDIO_CS_REQ_RANGE: TU_LOG2(" Get Sample Freq. range\r\n"); @@ -463,7 +532,14 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u (void) ep_in; (void) cur_alt_setting; - tud_audio_write((uint8_t*)i2s_dummy_buffer, CFG_TUD_AUDIO_EP_SZ_IN); + + // In read world application data flow is driven by I2S clock, + // both tud_audio_tx_done_pre_load_cb() & tud_audio_tx_done_post_load_cb() are hardly used. + // For example in your I2S receive callback: + // void I2S_Rx_Callback(int channel, const void* data, uint16_t samples) + // { + // tud_audio_write_support_ff(channel, data, samples * N_BYTES_PER_SAMPLE * N_CHANNEL_PER_FIFO); + // } return true; } @@ -476,14 +552,6 @@ bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uin (void) ep_in; (void) cur_alt_setting; - uint16_t* p_buff = i2s_dummy_buffer; - for (int samples_num = 0; samples_num < AUDIO_SAMPLE_RATE/1000; samples_num++) { - for (int ch=0; ch < CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX; ch++) { - *p_buff++ = samples[ch]; - samples[ch] = samples[ch]+(ch+1); - } - } - return true; } @@ -498,11 +566,17 @@ bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const ///--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinky_cb(TimerHandle_t xTimer) -{ - (void) xTimer; +void led_blinking_task(void* param) { + (void) param; + static uint32_t start_ms = 0; static bool led_state = false; - board_led_write(led_state); - led_state = 1 - led_state; // toggle + while (1) { + // Blink every interval ms + vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle + } } diff --git a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h index 010315c27..88f20278b 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h @@ -109,24 +109,37 @@ extern "C" { //-------------------------------------------------------------------- // Have a look into audio_device.h for all configurations +#define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_FOUR_CH_DESC_LEN +#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_FOUR_CH_DESC_LEN -#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 -#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 +#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1 +#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 -#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 -#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup -#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup -#define CFG_TUD_AUDIO_EP_SZ_IN 48 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x CFG_TUD_AUDIO_N_CHANNELS_TX Channels - the Windows driver always needs an extra sample per channel of space more, otherwise it complains... found by trial and error -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0 -#define CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX 2 // One I2S stream contains two channels, each stream is saved within one support FIFO - this value is currently fixed, the driver does not support a changing value -#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX) -#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) +#define CFG_TUD_AUDIO_ENABLE_ENCODING 1 +#define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1 + +#if CFG_TUD_AUDIO_ENABLE_ENCODING + +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN + +#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 1 +#define CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX 2 // One I2S stream contains two channels, each stream is saved within one support FIFO - this value is currently fixed, the driver does not support a changing value +#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX) +#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) // Example write FIFO every 1ms, so it should be 8 times larger for HS device + +#else + +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device + +#endif #ifdef __cplusplus } diff --git a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c index 16355a7fc..728a5f9ce 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c +++ b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c @@ -23,6 +23,7 @@ * */ +#include "bsp/board_api.h" #include "tusb.h" /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. @@ -44,7 +45,7 @@ tusb_desc_device_t const desc_device = .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, - // Use Interface Association Descriptor (IAD) for CDC + // Use Interface Association Descriptor (IAD) for Audio // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) .bDeviceClass = TUSB_CLASS_MISC, .bDeviceSubClass = MISC_SUBCLASS_COMMON, @@ -96,7 +97,7 @@ enum uint8_t const desc_configuration[] = { - // Interface count, string index, total length, attribute, power in mA + // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP Out & EP In address, EP size @@ -116,50 +117,63 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) // String Descriptors //--------------------------------------------------------------------+ +// String Descriptor Index +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, +}; + // array of pointer to string descriptors -char const* string_desc_arr [] = -{ - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "PaniRCorp", // 1: Manufacturer - "MicNode_4_Ch", // 2: Product - "123458", // 3: Serials, should use chip ID - "UAC2", // 4: Audio Interface +char const* string_desc_arr [] = { + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "PaniRCorp", // 1: Manufacturer + "MicNode_4_Ch", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "UAC2", // 4: Audio Interface }; -static uint16_t _desc_str[32]; +static uint16_t _desc_str[32 + 1]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) -{ +uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void) langid; + size_t chr_count; + + switch ( index ) { + case STRID_LANGID: + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + break; - uint8_t chr_count; + case STRID_SERIAL: + chr_count = board_usb_get_serial(_desc_str + 1, 32); + break; - if ( index == 0) - { - memcpy(&_desc_str[1], string_desc_arr[0], 2); - chr_count = 1; - }else - { - // Convert ASCII string into UTF-16 + default: + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; - const char* str = string_desc_arr[index]; + const char *str = string_desc_arr[index]; - // Cap at max char - chr_count = strlen(str); - if ( chr_count > 31 ) chr_count = 31; + // Cap at max char + chr_count = strlen(str); + size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type + if ( chr_count > max_count ) chr_count = max_count; - for(uint8_t i=0; i Date: Sun, 28 Apr 2024 00:29:19 +0200 Subject: Build STM32F7 with single-point FPU. --- .../build_system/cmake/cpu/cortex-m7-fpsp.cmake | 25 ++++++++++++++++++++ examples/build_system/make/cpu/cortex-m7-fpsp.mk | 27 ++++++++++++++++++++++ hw/bsp/stm32f7/family.cmake | 2 +- hw/bsp/stm32f7/family.mk | 2 +- 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 examples/build_system/cmake/cpu/cortex-m7-fpsp.cmake create mode 100644 examples/build_system/make/cpu/cortex-m7-fpsp.mk (limited to 'examples') diff --git a/examples/build_system/cmake/cpu/cortex-m7-fpsp.cmake b/examples/build_system/cmake/cpu/cortex-m7-fpsp.cmake new file mode 100644 index 000000000..b10f00fc2 --- /dev/null +++ b/examples/build_system/cmake/cpu/cortex-m7-fpsp.cmake @@ -0,0 +1,25 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -mthumb + -mcpu=cortex-m7 + -mfloat-abi=hard + -mfpu=fpv5-sp-d16 + ) + set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "clang") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-m7 + -mfpu=fpv5-sp-d16 + ) + set(FREERTOS_PORT GCC_ARM_CM7 CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "iar") + set(TOOLCHAIN_COMMON_FLAGS + --cpu cortex-m7 + --fpu VFPv5_sp + ) + set(FREERTOS_PORT IAR_ARM_CM7 CACHE INTERNAL "") + +endif () diff --git a/examples/build_system/make/cpu/cortex-m7-fpsp.mk b/examples/build_system/make/cpu/cortex-m7-fpsp.mk new file mode 100644 index 000000000..cd42c6fb8 --- /dev/null +++ b/examples/build_system/make/cpu/cortex-m7-fpsp.mk @@ -0,0 +1,27 @@ +ifeq ($(TOOLCHAIN),gcc) + CFLAGS += \ + -mthumb \ + -mcpu=cortex-m7 \ + -mfloat-abi=hard \ + -mfpu=fpv5-sp-d16 \ + +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + --target=arm-none-eabi \ + -mcpu=cortex-m7 \ + -mfpu=fpv5-sp-d16 \ + +else ifeq ($(TOOLCHAIN),iar) + CFLAGS += \ + --cpu cortex-m7 \ + --fpu VFPv5_sp \ + + ASFLAGS += \ + --cpu cortex-m7 \ + --fpu VFPv5_sp \ + +else + $(error "TOOLCHAIN is not supported") +endif + +FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM7/r0p1 diff --git a/hw/bsp/stm32f7/family.cmake b/hw/bsp/stm32f7/family.cmake index be566f2eb..17e632c40 100644 --- a/hw/bsp/stm32f7/family.cmake +++ b/hw/bsp/stm32f7/family.cmake @@ -11,7 +11,7 @@ set(CMSIS_5 ${TOP}/lib/CMSIS_5) include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) # toolchain set up -set(CMAKE_SYSTEM_PROCESSOR cortex-m7 CACHE INTERNAL "System Processor") +set(CMAKE_SYSTEM_PROCESSOR cortex-m7-fpsp CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) set(FAMILY_MCUS STM32F7 CACHE INTERNAL "") diff --git a/hw/bsp/stm32f7/family.mk b/hw/bsp/stm32f7/family.mk index cc21bd64e..e261b0467 100644 --- a/hw/bsp/stm32f7/family.mk +++ b/hw/bsp/stm32f7/family.mk @@ -6,7 +6,7 @@ ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver include $(TOP)/$(BOARD_PATH)/board.mk -CPU_CORE ?= cortex-m7 +CPU_CORE ?= cortex-m7-fpsp # -------------- # Compiler Flags -- cgit v1.3.1 From ef7be4c2ffa0061aec2ea32f530a4037f7309f1e Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 28 Apr 2024 00:40:36 +0200 Subject: Fix CI. --- examples/device/CMakeLists.txt | 2 ++ examples/device/audio_4_channel_mic_freertos/Makefile | 2 +- examples/device/audio_4_channel_mic_freertos/skip.txt | 16 +++++++++++++--- examples/device/audio_4_channel_mic_freertos/src/main.c | 2 -- .../src/plot_audio_samples.py | 1 - examples/device/audio_test_freertos/Makefile | 2 +- examples/device/audio_test_freertos/README.md | 2 +- examples/device/audio_test_freertos/skip.txt | 14 ++++++++++++-- examples/device/audio_test_freertos/src/main.c | 2 -- .../device/audio_test_freertos/src/plot_audio_samples.py | 1 - examples/device/cdc_msc_freertos/skip.txt | 1 + examples/device/video_capture_2ch/skip.txt | 1 + hw/bsp/stm32l0/FreeRTOSConfig/FreeRTOSConfig.h | 2 +- 13 files changed, 33 insertions(+), 15 deletions(-) (limited to 'examples') diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt index c3671da69..638440795 100644 --- a/examples/device/CMakeLists.txt +++ b/examples/device/CMakeLists.txt @@ -8,6 +8,8 @@ family_initialize_project(tinyusb_device_examples ${CMAKE_CURRENT_LIST_DIR}) # family_add_subdirectory will filter what to actually add based on selected FAMILY family_add_subdirectory(audio_4_channel_mic) family_add_subdirectory(audio_test) +family_add_subdirectory(audio_4_channel_mic_freertos) +family_add_subdirectory(audio_test_freertos) family_add_subdirectory(audio_test_multi_rate) family_add_subdirectory(board_test) family_add_subdirectory(cdc_dual_ports) diff --git a/examples/device/audio_4_channel_mic_freertos/Makefile b/examples/device/audio_4_channel_mic_freertos/Makefile index 48a3148f8..df2cdef4e 100644 --- a/examples/device/audio_4_channel_mic_freertos/Makefile +++ b/examples/device/audio_4_channel_mic_freertos/Makefile @@ -35,4 +35,4 @@ CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls # FreeRTOS (lto + Os) linker issue LDFLAGS += -Wl,--undefined=vTaskSwitchContext -include ../../build_system/make/rules.mk \ No newline at end of file +include ../../build_system/make/rules.mk diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index 83babce12..eb434c23b 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -1,4 +1,14 @@ +mcu:CH32V307 +mcu:CXD56 +mcu:F1C100S +mcu:GD32VF103 +mcu:MKL25ZXX +mcu:MSP430x5xx +mcu:RP2040 mcu:SAMD11 -mcu:SAME5X -mcu:SAMG -family:broadcom_64bit \ No newline at end of file +mcu:SAMX7X +mcu:VALENTYUSB_EPTRI +mcu:RAXXX +mcu:STM32L0 +family:broadcom_32bit +family:broadcom_64bit diff --git a/examples/device/audio_4_channel_mic_freertos/src/main.c b/examples/device/audio_4_channel_mic_freertos/src/main.c index 7d953e71c..08f49326c 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/main.c +++ b/examples/device/audio_4_channel_mic_freertos/src/main.c @@ -379,8 +379,6 @@ bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re (void) channelNum; (void) ctrlSel; (void) ep; - // return tud_control_xfer(rhport, p_request, &tmp, 1); - return false; // Yet not implemented } diff --git a/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py b/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py index 9ab15135d..8312b4e28 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py +++ b/examples/device/audio_4_channel_mic_freertos/src/plot_audio_samples.py @@ -31,4 +31,3 @@ if __name__ == '__main__': plt.ylabel('Amplitude') plt.title('MicNode 4 Channel') plt.show() - \ No newline at end of file diff --git a/examples/device/audio_test_freertos/Makefile b/examples/device/audio_test_freertos/Makefile index 48a3148f8..df2cdef4e 100644 --- a/examples/device/audio_test_freertos/Makefile +++ b/examples/device/audio_test_freertos/Makefile @@ -35,4 +35,4 @@ CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls # FreeRTOS (lto + Os) linker issue LDFLAGS += -Wl,--undefined=vTaskSwitchContext -include ../../build_system/make/rules.mk \ No newline at end of file +include ../../build_system/make/rules.mk diff --git a/examples/device/audio_test_freertos/README.md b/examples/device/audio_test_freertos/README.md index dd70af44b..9477fcd78 100644 --- a/examples/device/audio_test_freertos/README.md +++ b/examples/device/audio_test_freertos/README.md @@ -16,4 +16,4 @@ $ ninja.exe -C build eg. -> /home/kaspernyhus/.espressif/python_env/idf4.4_py3.8_env/bin/python ../../../../esp-idf/components/esptool_py/esptool/esptool.py -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 _build/espressif_s3_devkitc/bootloader/bootloader.bin 0x8000 _build/espressif_s3_devkitc/partition_table/partition-table.bin 0x10000 _build/espressif_s3_devkitc/audio_test_freertos.bin \ No newline at end of file +> /home/kaspernyhus/.espressif/python_env/idf4.4_py3.8_env/bin/python ../../../../esp-idf/components/esptool_py/esptool/esptool.py -p /dev/ttyUSB0 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 _build/espressif_s3_devkitc/bootloader/bootloader.bin 0x8000 _build/espressif_s3_devkitc/partition_table/partition-table.bin 0x10000 _build/espressif_s3_devkitc/audio_test_freertos.bin diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt index ae9b57f1f..a6f96b288 100644 --- a/examples/device/audio_test_freertos/skip.txt +++ b/examples/device/audio_test_freertos/skip.txt @@ -1,3 +1,13 @@ +mcu:CH32V307 +mcu:CXD56 +mcu:F1C100S +mcu:GD32VF103 +mcu:MKL25ZXX +mcu:MSP430x5xx +mcu:RP2040 mcu:SAMD11 -mcu:SAME5X -mcu:SAMG \ No newline at end of file +mcu:SAMX7X +mcu:VALENTYUSB_EPTRI +mcu:RAXXX +family:broadcom_32bit +family:broadcom_64bit diff --git a/examples/device/audio_test_freertos/src/main.c b/examples/device/audio_test_freertos/src/main.c index 903c97d20..a3751da40 100644 --- a/examples/device/audio_test_freertos/src/main.c +++ b/examples/device/audio_test_freertos/src/main.c @@ -309,8 +309,6 @@ bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re (void) channelNum; (void) ctrlSel; (void) ep; - // return tud_control_xfer(rhport, p_request, &tmp, 1); - return false; // Yet not implemented } diff --git a/examples/device/audio_test_freertos/src/plot_audio_samples.py b/examples/device/audio_test_freertos/src/plot_audio_samples.py index 6f1518be5..304b2d5de 100644 --- a/examples/device/audio_test_freertos/src/plot_audio_samples.py +++ b/examples/device/audio_test_freertos/src/plot_audio_samples.py @@ -31,4 +31,3 @@ if __name__ == '__main__': plt.ylabel('Amplitude') plt.title('MicNode') plt.show() - \ No newline at end of file diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt index a6f96b288..eb434c23b 100644 --- a/examples/device/cdc_msc_freertos/skip.txt +++ b/examples/device/cdc_msc_freertos/skip.txt @@ -9,5 +9,6 @@ mcu:SAMD11 mcu:SAMX7X mcu:VALENTYUSB_EPTRI mcu:RAXXX +mcu:STM32L0 family:broadcom_32bit family:broadcom_64bit diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt index b36abf721..15c176a2a 100644 --- a/examples/device/video_capture_2ch/skip.txt +++ b/examples/device/video_capture_2ch/skip.txt @@ -3,6 +3,7 @@ mcu:NUC121 mcu:SAMD11 mcu:GD32VF103 mcu:CH32V307 +mcu:STM32L0 family:espressif board:curiosity_nano board:kuiic diff --git a/hw/bsp/stm32l0/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32l0/FreeRTOSConfig/FreeRTOSConfig.h index 37e7e0943..40146e73a 100644 --- a/hw/bsp/stm32l0/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/stm32l0/FreeRTOSConfig/FreeRTOSConfig.h @@ -44,7 +44,7 @@ // skip if included from IAR assembler #ifndef __IASMARM__ - #include "stm32f0xx.h" + #include "stm32l0xx.h" #endif /* Cortex M23/M33 port configuration. */ -- cgit v1.3.1 From ea3f1d39e8bfc82facc7b3e503d7c71f9119de2b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 2 May 2024 13:29:29 +0700 Subject: add cmake for pi zero (renamed from pi zero_w), build but the flash size seem wrong (only 24 bytes for text) --- .clang-format | 6 -- examples/build_system/cmake/cpu/arm1176jzf-s.cmake | 19 ++++ examples/build_system/make/cpu/arm1176.mk | 9 -- examples/build_system/make/cpu/arm1176jzf-s.mk | 9 ++ .../boards/raspberrypi_zero/board.cmake | 8 ++ .../broadcom_32bit/boards/raspberrypi_zero/board.h | 38 ++++++++ .../boards/raspberrypi_zero/board.mk | 5 + .../boards/raspberrypi_zero_w/board.h | 38 -------- .../boards/raspberrypi_zero_w/board.mk | 5 - hw/bsp/broadcom_32bit/family.c | 11 +++ hw/bsp/broadcom_32bit/family.cmake | 107 +++++++++++++++++++++ hw/bsp/broadcom_32bit/family.mk | 5 +- src/common/tusb_fifo.h | 12 +-- src/common/tusb_mcu.h | 2 +- src/common/tusb_verify.h | 3 +- 15 files changed, 206 insertions(+), 71 deletions(-) delete mode 100644 .clang-format create mode 100644 examples/build_system/cmake/cpu/arm1176jzf-s.cmake delete mode 100644 examples/build_system/make/cpu/arm1176.mk create mode 100644 examples/build_system/make/cpu/arm1176jzf-s.mk create mode 100644 hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.cmake create mode 100644 hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.h create mode 100644 hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.mk delete mode 100644 hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.h delete mode 100644 hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.mk create mode 100644 hw/bsp/broadcom_32bit/family.cmake (limited to 'examples') diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 4369c29fe..000000000 --- a/.clang-format +++ /dev/null @@ -1,6 +0,0 @@ ---- -BreakBeforeBraces: Linux -ColumnLimit: '200' -ReflowComments: 'true' - -... diff --git a/examples/build_system/cmake/cpu/arm1176jzf-s.cmake b/examples/build_system/cmake/cpu/arm1176jzf-s.cmake new file mode 100644 index 000000000..11bb52f30 --- /dev/null +++ b/examples/build_system/cmake/cpu/arm1176jzf-s.cmake @@ -0,0 +1,19 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -mcpu=arm1176jzf-s + ) + # set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "clang") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=arm1176jzf-s + -mfpu=none + -mfloat-abi=soft + ) + #set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "iar") + message(FATAL_ERROR "IAR not supported") + +endif () diff --git a/examples/build_system/make/cpu/arm1176.mk b/examples/build_system/make/cpu/arm1176.mk deleted file mode 100644 index 022ccf7ad..000000000 --- a/examples/build_system/make/cpu/arm1176.mk +++ /dev/null @@ -1,9 +0,0 @@ -ifeq ($(TOOLCHAIN),gcc) - CFLAGS += \ - -mcpu=arm1176jzf-s \ - -else ifeq ($(TOOLCHAIN),iar) - #CFLAGS += --cpu cortex-a53 - #ASFLAGS += --cpu cortex-a53 - -endif diff --git a/examples/build_system/make/cpu/arm1176jzf-s.mk b/examples/build_system/make/cpu/arm1176jzf-s.mk new file mode 100644 index 000000000..022ccf7ad --- /dev/null +++ b/examples/build_system/make/cpu/arm1176jzf-s.mk @@ -0,0 +1,9 @@ +ifeq ($(TOOLCHAIN),gcc) + CFLAGS += \ + -mcpu=arm1176jzf-s \ + +else ifeq ($(TOOLCHAIN),iar) + #CFLAGS += --cpu cortex-a53 + #ASFLAGS += --cpu cortex-a53 + +endif diff --git a/hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.cmake b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.cmake new file mode 100644 index 000000000..2b8cc19e0 --- /dev/null +++ b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.cmake @@ -0,0 +1,8 @@ +set(CMAKE_SYSTEM_PROCESSOR arm1176jzf-s CACHE INTERNAL "System Processor") +#set(SUFFIX "") + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + BCM_VERSION=2835 + ) +endfunction() diff --git a/hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.h b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.h new file mode 100644 index 000000000..84a106346 --- /dev/null +++ b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.h @@ -0,0 +1,38 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.mk b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.mk new file mode 100644 index 000000000..7a248ed24 --- /dev/null +++ b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero/board.mk @@ -0,0 +1,5 @@ +CPU_CORE = arm1176jzf-s +CFLAGS += -DBCM_VERSION=2835 \ + -DCFG_TUSB_MCU=OPT_MCU_BCM2835 + +SUFFIX = diff --git a/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.h b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.h deleted file mode 100644 index 84a106346..000000000 --- a/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.mk b/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.mk deleted file mode 100644 index 052033230..000000000 --- a/hw/bsp/broadcom_32bit/boards/raspberrypi_zero_w/board.mk +++ /dev/null @@ -1,5 +0,0 @@ -CPU_CORE = arm1176 -CFLAGS += -DBCM_VERSION=2835 \ - -DCFG_TUSB_MCU=OPT_MCU_BCM2835 - -SUFFIX = diff --git a/hw/bsp/broadcom_32bit/family.c b/hw/bsp/broadcom_32bit/family.c index 664b4dcaf..626565e34 100644 --- a/hw/bsp/broadcom_32bit/family.c +++ b/hw/bsp/broadcom_32bit/family.c @@ -27,6 +27,13 @@ #include "bsp/board_api.h" #include "board.h" +// Suppress warning caused by mcu driver +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include "broadcom/cpu.h" #include "broadcom/gpio.h" #include "broadcom/interrupts.h" @@ -34,6 +41,10 @@ #include "broadcom/caches.h" #include "broadcom/vcmailbox.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + // LED #define LED_PIN 18 #define LED_STATE_ON 1 diff --git a/hw/bsp/broadcom_32bit/family.cmake b/hw/bsp/broadcom_32bit/family.cmake new file mode 100644 index 000000000..223c85e48 --- /dev/null +++ b/hw/bsp/broadcom_32bit/family.cmake @@ -0,0 +1,107 @@ +include_guard() + +set(MCU_DIR ${TOP}/hw/mcu/broadcom) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS BCM2835 CACHE INTERNAL "") + + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${MCU_DIR}/broadcom/link.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + + if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) + set(STARTUP_FILE_GNU ${MCU_DIR}/broadcom/boot.s) + endif () + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${MCU_DIR}/broadcom/gen/interrupt_handlers.c + ${MCU_DIR}/broadcom/gpio.c + ${MCU_DIR}/broadcom/interrupts.c + ${MCU_DIR}/broadcom/mmu.c + ${MCU_DIR}/broadcom/caches.c + ${MCU_DIR}/broadcom/vcmailbox.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_compile_options(${BOARD_TARGET} PUBLIC + -O0 + -ffreestanding + -mgeneral-regs-only + -fno-exceptions + -std=c17 + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${MCU_DIR} + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostdlib -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_BCM2835 ${RTOS}) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/broadcom_32bit/family.mk b/hw/bsp/broadcom_32bit/family.mk index cf68e21ee..e15bd93f7 100644 --- a/hw/bsp/broadcom_32bit/family.mk +++ b/hw/bsp/broadcom_32bit/family.mk @@ -1,5 +1,4 @@ MCU_DIR = hw/mcu/broadcom -DEPS_SUBMODULES += $(MCU_DIR) include $(TOP)/$(BOARD_PATH)/board.mk @@ -27,15 +26,13 @@ SRC_C += \ $(MCU_DIR)/broadcom/caches.c \ $(MCU_DIR)/broadcom/vcmailbox.c -SKIP_NANOLIB = 1 - LD_FILE = $(MCU_DIR)/broadcom/link$(SUFFIX).ld INC += \ $(TOP)/$(BOARD_PATH) \ $(TOP)/$(MCU_DIR) -SRC_S += $(MCU_DIR)/broadcom/boot$(SUFFIX).S +SRC_S += $(MCU_DIR)/broadcom/boot$(SUFFIX).s $(BUILD)/kernel$(SUFFIX).img: $(BUILD)/$(PROJECT).elf $(OBJCOPY) -O binary $^ $@ diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 2d9f5e667..0de576601 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -145,13 +145,13 @@ 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); diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 5a567f2d5..8d58be2a1 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -430,7 +430,7 @@ #endif #if !defined(TUP_DCD_ENDPOINT_MAX) && defined(CFG_TUD_ENABLED) && CFG_TUD_ENABLED -#warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" + #warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" #define TUP_DCD_ENDPOINT_MAX 8 #endif diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 0a9549c99..dde0550d3 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -78,8 +78,7 @@ // Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33. M55 #if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__) || \ defined(__ARM7M__) || defined (__ARM7EM__) || defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) - #define TU_BREAKPOINT() do \ - { \ + #define TU_BREAKPOINT() do { \ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ } while(0) -- cgit v1.3.1 From 980f5992c8bc9b66e13cd409ae782a588053ec3e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 2 May 2024 16:57:50 +0700 Subject: add cmake for broadcom 64-bit, like 32-bit it compiles but text is only 8 bytes (incorrect) --- examples/build_system/cmake/cpu/cortex-a53.cmake | 17 ++++ examples/build_system/cmake/cpu/cortex-a72.cmake | 17 ++++ .../build_system/cmake/toolchain/aarch64_gcc.cmake | 21 ++++ .../boards/raspberrypi_cm4/board.cmake | 5 + .../boards/raspberrypi_zero2/board.cmake | 5 + .../boards/raspberrypi_zero2/board.h | 38 +++++++ .../boards/raspberrypi_zero2/board.mk | 3 + .../boards/raspberrypi_zero2w/board.h | 38 ------- .../boards/raspberrypi_zero2w/board.mk | 3 - hw/bsp/broadcom_64bit/family.c | 11 +++ hw/bsp/broadcom_64bit/family.cmake | 110 +++++++++++++++++++++ hw/bsp/broadcom_64bit/family.mk | 6 +- 12 files changed, 228 insertions(+), 46 deletions(-) create mode 100644 examples/build_system/cmake/cpu/cortex-a53.cmake create mode 100644 examples/build_system/cmake/cpu/cortex-a72.cmake create mode 100644 examples/build_system/cmake/toolchain/aarch64_gcc.cmake create mode 100644 hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.cmake create mode 100644 hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.cmake create mode 100644 hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.h create mode 100644 hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.mk delete mode 100644 hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.h delete mode 100644 hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.mk create mode 100644 hw/bsp/broadcom_64bit/family.cmake (limited to 'examples') diff --git a/examples/build_system/cmake/cpu/cortex-a53.cmake b/examples/build_system/cmake/cpu/cortex-a53.cmake new file mode 100644 index 000000000..dde8c0a0c --- /dev/null +++ b/examples/build_system/cmake/cpu/cortex-a53.cmake @@ -0,0 +1,17 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -mcpu=cortex-a53 + ) + # set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "clang") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-a53 + ) + #set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "iar") + message(FATAL_ERROR "IAR not supported") + +endif () diff --git a/examples/build_system/cmake/cpu/cortex-a72.cmake b/examples/build_system/cmake/cpu/cortex-a72.cmake new file mode 100644 index 000000000..a44324234 --- /dev/null +++ b/examples/build_system/cmake/cpu/cortex-a72.cmake @@ -0,0 +1,17 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -mcpu=cortex-a72 + ) + # set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "clang") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-a72 + ) + #set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "iar") + message(FATAL_ERROR "IAR not supported") + +endif () diff --git a/examples/build_system/cmake/toolchain/aarch64_gcc.cmake b/examples/build_system/cmake/toolchain/aarch64_gcc.cmake new file mode 100644 index 000000000..2d30a0b71 --- /dev/null +++ b/examples/build_system/cmake/toolchain/aarch64_gcc.cmake @@ -0,0 +1,21 @@ +if (NOT DEFINED CMAKE_C_COMPILER) + set(CMAKE_C_COMPILER "aarch64-none-elf-gcc") +endif () + +if (NOT DEFINED CMAKE_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "aarch64-none-elf-g++") +endif () + +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +set(CMAKE_SIZE "aarch64-none-elf-size" CACHE FILEPATH "") +set(CMAKE_OBJCOPY "aarch64-none-elf-objcopy" CACHE FILEPATH "") +set(CMAKE_OBJDUMP "aarch64-none-elf-objdump" CACHE FILEPATH "") + +include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) + +get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) +if (IS_IN_TRY_COMPILE) + set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib") + set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib") + cmake_print_variables(CMAKE_C_LINK_FLAGS) +endif () diff --git a/hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.cmake b/hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.cmake new file mode 100644 index 000000000..919068f1d --- /dev/null +++ b/hw/bsp/broadcom_64bit/boards/raspberrypi_cm4/board.cmake @@ -0,0 +1,5 @@ +set(CMAKE_SYSTEM_PROCESSOR cortex-a72 CACHE INTERNAL "System Processor") +set(BCM_VERSION 2711) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.cmake b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.cmake new file mode 100644 index 000000000..85f84e947 --- /dev/null +++ b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.cmake @@ -0,0 +1,5 @@ +set(CMAKE_SYSTEM_PROCESSOR cortex-a53 CACHE INTERNAL "System Processor") +set(BCM_VERSION 2837) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.h b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.h new file mode 100644 index 000000000..84a106346 --- /dev/null +++ b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.h @@ -0,0 +1,38 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.mk b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.mk new file mode 100644 index 000000000..da3fe17bc --- /dev/null +++ b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2/board.mk @@ -0,0 +1,3 @@ +CPU_CORE = cortex-a53 +CFLAGS += -DBCM_VERSION=2837 \ + -DCFG_TUSB_MCU=OPT_MCU_BCM2837 diff --git a/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.h b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.h deleted file mode 100644 index 84a106346..000000000 --- a/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#ifndef BOARD_H_ -#define BOARD_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* BOARD_H_ */ diff --git a/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.mk b/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.mk deleted file mode 100644 index da3fe17bc..000000000 --- a/hw/bsp/broadcom_64bit/boards/raspberrypi_zero2w/board.mk +++ /dev/null @@ -1,3 +0,0 @@ -CPU_CORE = cortex-a53 -CFLAGS += -DBCM_VERSION=2837 \ - -DCFG_TUSB_MCU=OPT_MCU_BCM2837 diff --git a/hw/bsp/broadcom_64bit/family.c b/hw/bsp/broadcom_64bit/family.c index 664b4dcaf..626565e34 100644 --- a/hw/bsp/broadcom_64bit/family.c +++ b/hw/bsp/broadcom_64bit/family.c @@ -27,6 +27,13 @@ #include "bsp/board_api.h" #include "board.h" +// Suppress warning caused by mcu driver +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include "broadcom/cpu.h" #include "broadcom/gpio.h" #include "broadcom/interrupts.h" @@ -34,6 +41,10 @@ #include "broadcom/caches.h" #include "broadcom/vcmailbox.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + // LED #define LED_PIN 18 #define LED_STATE_ON 1 diff --git a/hw/bsp/broadcom_64bit/family.cmake b/hw/bsp/broadcom_64bit/family.cmake new file mode 100644 index 000000000..b534e29be --- /dev/null +++ b/hw/bsp/broadcom_64bit/family.cmake @@ -0,0 +1,110 @@ +include_guard() + +set(MCU_DIR ${TOP}/hw/mcu/broadcom) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/aarch64_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS BCM2711 BCM2835 CACHE INTERNAL "") + + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${MCU_DIR}/broadcom/link8.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + + if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) + set(STARTUP_FILE_GNU ${MCU_DIR}/broadcom/boot8.s) + endif () + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${MCU_DIR}/broadcom/gen/interrupt_handlers.c + ${MCU_DIR}/broadcom/gpio.c + ${MCU_DIR}/broadcom/interrupts.c + ${MCU_DIR}/broadcom/mmu.c + ${MCU_DIR}/broadcom/caches.c + ${MCU_DIR}/broadcom/vcmailbox.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_compile_options(${BOARD_TARGET} PUBLIC + -O0 + -ffreestanding + -mgeneral-regs-only + -fno-exceptions + -std=c17 + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + BCM_VERSION=${BCM_VERSION} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${MCU_DIR} + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostdlib -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_BCM${BCM_VERSION} ${RTOS}) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/broadcom_64bit/family.mk b/hw/bsp/broadcom_64bit/family.mk index 97af6d64a..80eff1d36 100644 --- a/hw/bsp/broadcom_64bit/family.mk +++ b/hw/bsp/broadcom_64bit/family.mk @@ -1,6 +1,4 @@ MCU_DIR = hw/mcu/broadcom -DEPS_SUBMODULES += $(MCU_DIR) - include $(TOP)/$(BOARD_PATH)/board.mk CFLAGS += \ @@ -26,8 +24,6 @@ SRC_C += \ $(MCU_DIR)/broadcom/caches.c \ $(MCU_DIR)/broadcom/vcmailbox.c -SKIP_NANOLIB = 1 - LD_FILE = $(MCU_DIR)/broadcom/link8.ld INC += \ @@ -35,7 +31,7 @@ INC += \ $(TOP)/$(MCU_DIR) \ $(TOP)/lib/CMSIS_5/CMSIS/Core_A/Include -SRC_S += $(MCU_DIR)/broadcom/boot8.S +SRC_S += $(MCU_DIR)/broadcom/boot8.s $(BUILD)/kernel8.img: $(BUILD)/$(PROJECT).elf $(OBJCOPY) -O binary $^ $@ -- cgit v1.3.1 From c717e52ab2453f7672b16f2d63cd70558950ef33 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 2 May 2024 17:54:44 +0700 Subject: add cmake for lpc11 --- .../device/audio_4_channel_mic_freertos/skip.txt | 1 + .../kinetis_k32l2/FreeRTOSConfig/FreeRTOSConfig.h | 2 +- hw/bsp/lpc11/FreeRTOSConfig/FreeRTOSConfig.h | 178 ++++++++++++++++++ hw/bsp/lpc11/boards/lpcxpresso11u37/board.cmake | 19 ++ hw/bsp/lpc11/boards/lpcxpresso11u37/board.h | 98 ++++++++++ .../lpc11/boards/lpcxpresso11u37/lpcxpresso11u37.c | 208 --------------------- hw/bsp/lpc11/boards/lpcxpresso11u68/board.cmake | 12 ++ hw/bsp/lpc11/boards/lpcxpresso11u68/board.h | 27 +++ hw/bsp/lpc11/boards/lpcxpresso11u68/board.mk | 1 - .../lpc11/boards/lpcxpresso11u68/lpcxpresso11u68.c | 135 ------------- hw/bsp/lpc11/family.c | 120 ++++++++++++ hw/bsp/lpc11/family.cmake | 104 +++++++++++ hw/bsp/lpc11/family.mk | 5 +- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 10 + 14 files changed, 572 insertions(+), 348 deletions(-) create mode 100644 hw/bsp/lpc11/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/lpc11/boards/lpcxpresso11u37/board.cmake create mode 100644 hw/bsp/lpc11/boards/lpcxpresso11u37/board.h delete mode 100644 hw/bsp/lpc11/boards/lpcxpresso11u37/lpcxpresso11u37.c create mode 100644 hw/bsp/lpc11/boards/lpcxpresso11u68/board.cmake create mode 100644 hw/bsp/lpc11/boards/lpcxpresso11u68/board.h delete mode 100644 hw/bsp/lpc11/boards/lpcxpresso11u68/lpcxpresso11u68.c create mode 100644 hw/bsp/lpc11/family.c create mode 100644 hw/bsp/lpc11/family.cmake (limited to 'examples') diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index eb434c23b..21683518c 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -10,5 +10,6 @@ mcu:SAMX7X mcu:VALENTYUSB_EPTRI mcu:RAXXX mcu:STM32L0 +board:lpcxpresso11u37 family:broadcom_32bit family:broadcom_64bit diff --git a/hw/bsp/kinetis_k32l2/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/kinetis_k32l2/FreeRTOSConfig/FreeRTOSConfig.h index 133728596..e6604d360 100644 --- a/hw/bsp/kinetis_k32l2/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/kinetis_k32l2/FreeRTOSConfig/FreeRTOSConfig.h @@ -147,7 +147,7 @@ //--------------------------------------------------------------------+ // For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header -#define configPRIO_BITS 4 +#define configPRIO_BITS 2 /* The lowest interrupt priority that can be used in a call to a "set priority" function. */ #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<= 4 + #define configENABLE_FPU 1 +#else + #define configENABLE_FPU 0 +#endif +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#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 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 2 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 2 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< Date: Thu, 2 May 2024 18:13:53 +0700 Subject: add cmake to lpc1347 --- .../device/audio_4_channel_mic_freertos/skip.txt | 1 + hw/bsp/lpc13/FreeRTOSConfig/FreeRTOSConfig.h | 178 +++++++++++++++++++++ hw/bsp/lpc13/boards/lpcxpresso1347/board.cmake | 11 ++ hw/bsp/lpc13/boards/lpcxpresso1347/board.h | 46 ++++++ .../lpc13/boards/lpcxpresso1347/lpcxpresso1347.c | 152 ------------------ hw/bsp/lpc13/family.c | 105 ++++++++++++ hw/bsp/lpc13/family.cmake | 102 ++++++++++++ hw/bsp/lpc13/family.mk | 3 +- 8 files changed, 445 insertions(+), 153 deletions(-) create mode 100644 hw/bsp/lpc13/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/lpc13/boards/lpcxpresso1347/board.cmake create mode 100644 hw/bsp/lpc13/boards/lpcxpresso1347/board.h delete mode 100644 hw/bsp/lpc13/boards/lpcxpresso1347/lpcxpresso1347.c create mode 100644 hw/bsp/lpc13/family.c create mode 100644 hw/bsp/lpc13/family.cmake (limited to 'examples') diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index 21683518c..0b689192d 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -11,5 +11,6 @@ mcu:VALENTYUSB_EPTRI mcu:RAXXX mcu:STM32L0 board:lpcxpresso11u37 +board:lpcxpresso1347 family:broadcom_32bit family:broadcom_64bit diff --git a/hw/bsp/lpc13/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/lpc13/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..a56028d5d --- /dev/null +++ b/hw/bsp/lpc13/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,178 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-parameter" + #endif + + #include "chip.h" + + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#if defined(__ARM_FP) && __ARM_FP >= 4 + #define configENABLE_FPU 1 +#else + #define configENABLE_FPU 0 +#endif +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#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 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 2 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< Date: Sat, 4 May 2024 12:36:40 +0700 Subject: add cmake for f1c100s --- examples/build_system/cmake/cpu/arm1176jzf-s.cmake | 2 + examples/build_system/cmake/cpu/arm926ej-s.cmake | 21 ++++ examples/build_system/make/cpu/arm926ej-s.mk | 9 ++ hw/bsp/f1c100s/board.h | 1 - hw/bsp/f1c100s/board.mk | 52 --------- hw/bsp/f1c100s/boards/f1c100s/board.cmake | 3 + hw/bsp/f1c100s/boards/f1c100s/board.h | 6 + hw/bsp/f1c100s/boards/f1c100s/board.mk | 1 + hw/bsp/f1c100s/f1c100s.c | 130 --------------------- hw/bsp/f1c100s/family.c | 126 ++++++++++++++++++++ hw/bsp/f1c100s/family.cmake | 114 ++++++++++++++++++ hw/bsp/f1c100s/family.mk | 58 +++++++++ src/portable/sunxi/dcd_sunxi_musb.c | 14 ++- 13 files changed, 348 insertions(+), 189 deletions(-) create mode 100644 examples/build_system/cmake/cpu/arm926ej-s.cmake create mode 100644 examples/build_system/make/cpu/arm926ej-s.mk delete mode 100644 hw/bsp/f1c100s/board.h delete mode 100644 hw/bsp/f1c100s/board.mk create mode 100644 hw/bsp/f1c100s/boards/f1c100s/board.cmake create mode 100644 hw/bsp/f1c100s/boards/f1c100s/board.h create mode 100644 hw/bsp/f1c100s/boards/f1c100s/board.mk delete mode 100644 hw/bsp/f1c100s/f1c100s.c create mode 100644 hw/bsp/f1c100s/family.c create mode 100644 hw/bsp/f1c100s/family.cmake create mode 100644 hw/bsp/f1c100s/family.mk (limited to 'examples') diff --git a/examples/build_system/cmake/cpu/arm1176jzf-s.cmake b/examples/build_system/cmake/cpu/arm1176jzf-s.cmake index 11bb52f30..8029e3987 100644 --- a/examples/build_system/cmake/cpu/arm1176jzf-s.cmake +++ b/examples/build_system/cmake/cpu/arm1176jzf-s.cmake @@ -1,6 +1,7 @@ if (TOOLCHAIN STREQUAL "gcc") set(TOOLCHAIN_COMMON_FLAGS -mcpu=arm1176jzf-s + -ffreestanding ) # set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") @@ -10,6 +11,7 @@ elseif (TOOLCHAIN STREQUAL "clang") -mcpu=arm1176jzf-s -mfpu=none -mfloat-abi=soft + -ffreestanding ) #set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") diff --git a/examples/build_system/cmake/cpu/arm926ej-s.cmake b/examples/build_system/cmake/cpu/arm926ej-s.cmake new file mode 100644 index 000000000..c19b9f8a8 --- /dev/null +++ b/examples/build_system/cmake/cpu/arm926ej-s.cmake @@ -0,0 +1,21 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -mcpu=arm926ej-s + -ffreestanding + ) + # set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "clang") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=arm926ej-s + -mfpu=none + -mfloat-abi=soft + -ffreestanding + ) + #set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "iar") + message(FATAL_ERROR "IAR not supported") + +endif () diff --git a/examples/build_system/make/cpu/arm926ej-s.mk b/examples/build_system/make/cpu/arm926ej-s.mk new file mode 100644 index 000000000..5b84f514f --- /dev/null +++ b/examples/build_system/make/cpu/arm926ej-s.mk @@ -0,0 +1,9 @@ +ifeq ($(TOOLCHAIN),gcc) + CFLAGS += \ + -mcpu=arm926ej-s \ + +else ifeq ($(TOOLCHAIN),iar) + #CFLAGS += --cpu cortex-a53 + #ASFLAGS += --cpu cortex-a53 + +endif diff --git a/hw/bsp/f1c100s/board.h b/hw/bsp/f1c100s/board.h deleted file mode 100644 index 0ef9a1700..000000000 --- a/hw/bsp/f1c100s/board.h +++ /dev/null @@ -1 +0,0 @@ -// Nothing valuable here diff --git a/hw/bsp/f1c100s/board.mk b/hw/bsp/f1c100s/board.mk deleted file mode 100644 index 3596e5414..000000000 --- a/hw/bsp/f1c100s/board.mk +++ /dev/null @@ -1,52 +0,0 @@ -MCU_DIR = hw/mcu/allwinner/f1c100s -DEPS_SUBMODULES += hw/mcu/allwinner -DEFINES += -D__ARM32_ARCH__=5 -D__ARM926EJS__ - -CFLAGS += \ - -ffreestanding \ - -std=gnu99 \ - -march=armv5te \ - -mtune=arm926ej-s \ - -mfloat-abi=soft \ - -marm \ - -mno-thumb-interwork \ - -Wno-unused-parameter \ - -Wno-float-equal \ - -DCFG_TUSB_MCU=OPT_MCU_F1C100S \ - -Wno-error=cast-align \ - -Wno-error=address-of-packed-member \ - $(DEFINES) - -LD_FILE = hw/mcu/allwinner/f1c100s/f1c100s.ld -# TODO may skip nanolib -LDFLAGS += -nostdlib -lgcc -specs=nosys.specs -specs=nano.specs - -SRC_C += \ - src/portable/sunxi/dcd_sunxi_musb.c \ - $(MCU_DIR)/machine/sys-uart.c \ - $(MCU_DIR)/machine/exception.c \ - $(MCU_DIR)/machine/sys-clock.c \ - $(MCU_DIR)/machine/sys-copyself.c \ - $(MCU_DIR)/machine/sys-dram.c \ - $(MCU_DIR)/machine/sys-mmu.c \ - $(MCU_DIR)/machine/sys-spi-flash.c \ - $(MCU_DIR)/machine/f1c100s-intc.c \ - $(MCU_DIR)/lib/malloc.c \ - $(MCU_DIR)/lib/printf.c - -SRC_S += \ - $(MCU_DIR)/machine/start.S \ - $(MCU_DIR)/lib/memcpy.S \ - $(MCU_DIR)/lib/memset.S - -INC += \ - $(TOP)/$(MCU_DIR)/include \ - $(TOP)/$(BOARD_PATH) - -# flash target using xfel -flash: flash-xfel - -exec: $(BUILD)/$(PROJECT).bin - xfel ddr - xfel write 0x80000000 $< - xfel exec 0x80000000 diff --git a/hw/bsp/f1c100s/boards/f1c100s/board.cmake b/hw/bsp/f1c100s/boards/f1c100s/board.cmake new file mode 100644 index 000000000..98ed56c57 --- /dev/null +++ b/hw/bsp/f1c100s/boards/f1c100s/board.cmake @@ -0,0 +1,3 @@ +function(update_board TARGET) + # nothing to do +endfunction() diff --git a/hw/bsp/f1c100s/boards/f1c100s/board.h b/hw/bsp/f1c100s/boards/f1c100s/board.h new file mode 100644 index 000000000..3b56a3a57 --- /dev/null +++ b/hw/bsp/f1c100s/boards/f1c100s/board.h @@ -0,0 +1,6 @@ +#ifndef BOARD_H +#define BOARD_H + +// Nothing valuable here + +#endif diff --git a/hw/bsp/f1c100s/boards/f1c100s/board.mk b/hw/bsp/f1c100s/boards/f1c100s/board.mk new file mode 100644 index 000000000..be830bd8c --- /dev/null +++ b/hw/bsp/f1c100s/boards/f1c100s/board.mk @@ -0,0 +1 @@ +# nothing to do diff --git a/hw/bsp/f1c100s/f1c100s.c b/hw/bsp/f1c100s/f1c100s.c deleted file mode 100644 index 272b756f2..000000000 --- a/hw/bsp/f1c100s/f1c100s.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include -#include -#include -#include -#include "bsp/board_api.h" -#include "board.h" - -extern void sys_uart_putc(char c); - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -static void timer_init(void); - -void board_init(void) -{ - arch_local_irq_disable(); - do_init_mem_pool(); - f1c100s_intc_init(); - timer_init(); - printf("Timer INIT done\n"); - arch_local_irq_enable(); -} - -// No LED, no button -void board_led_write(bool state) -{ - -} - -uint32_t board_button_read(void) -{ - return 0; -} - -int board_uart_read(uint8_t* buf, int len) -{ - return 0; -} - -int board_uart_write(void const * buf, int len) -{ - int txsize = len; - while (txsize--) { - sys_uart_putc(*(uint8_t const*)buf); - buf++; - } - return len; -} - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; - -uint32_t board_millis(void) -{ - return system_ticks; -} - -static void timer_handler(void) -{ - volatile uint32_t *temp_addr = (uint32_t *)(0x01C20C00 + 0x04); - - /* clear timer */ - *temp_addr |= 0x01; - - system_ticks++; -} - -static void timer_init(void) { - uint32_t temp; - volatile uint32_t *temp_addr; - - /* reload value */ - temp = 12000000 / 1000; - temp_addr = (uint32_t *)(0x01C20C00 + 0x14); - *temp_addr = temp; - - /* continuous | /2 | 24Mhz | reload*/ - temp = (0x00 << 7) | (0x01 << 4) | (0x01 << 2) | (0x00 << 1); - temp_addr = (uint32_t *)(0x01C20C00 + 0x10); - *temp_addr &= 0xffffff00; - *temp_addr |= temp; - - /* open timer irq */ - temp = 0x01 << 0; - temp_addr = (uint32_t *)(0x01C20C00); - *temp_addr |= temp; - - /* set init value */ - temp_addr = (uint32_t *)(0x01C20C00 + 0x18); - *temp_addr = 0; - - /* begin run timer */ - temp = 0x01 << 0; - temp_addr = (uint32_t *)(0x01C20C00 + 0x10); - *temp_addr |= temp; - - f1c100s_intc_set_isr(F1C100S_IRQ_TIMER0, timer_handler); - f1c100s_intc_enable_irq(F1C100S_IRQ_TIMER0); -} -#else -static void timer_init(void) { } -#endif diff --git a/hw/bsp/f1c100s/family.c b/hw/bsp/f1c100s/family.c new file mode 100644 index 000000000..6df4a0ed8 --- /dev/null +++ b/hw/bsp/f1c100s/family.c @@ -0,0 +1,126 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include +#include +#include +#include +#include "bsp/board_api.h" +#include "board.h" + +extern void sys_uart_putc(char c); + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +static void timer_init(void); + +void board_init(void) { + arch_local_irq_disable(); + do_init_mem_pool(); + f1c100s_intc_init(); + timer_init(); + printf("Timer INIT done\n"); + arch_local_irq_enable(); +} + +// No LED, no button +void board_led_write(bool state) { + (void) state; +} + +uint32_t board_button_read(void) { + return 0; +} + +int board_uart_read(uint8_t* buf, int len) { + (void) buf; + (void) len; + return 0; +} + +int board_uart_write(void const* buf, int len) { + int txsize = len; + while (txsize--) { + sys_uart_putc(*(uint8_t const*) buf); + buf++; + } + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +uint32_t board_millis(void) { + return system_ticks; +} + +static void timer_handler(void) { + volatile uint32_t* temp_addr = (uint32_t*) (0x01C20C00 + 0x04); + + /* clear timer */ + *temp_addr |= 0x01; + + system_ticks++; +} + +static void timer_init(void) { + uint32_t temp; + volatile uint32_t* temp_addr; + + /* reload value */ + temp = 12000000 / 1000; + temp_addr = (uint32_t*) (0x01C20C00 + 0x14); + *temp_addr = temp; + + /* continuous | /2 | 24Mhz | reload*/ + temp = (0x00 << 7) | (0x01 << 4) | (0x01 << 2) | (0x00 << 1); + temp_addr = (uint32_t*) (0x01C20C00 + 0x10); + *temp_addr &= 0xffffff00; + *temp_addr |= temp; + + /* open timer irq */ + temp = 0x01 << 0; + temp_addr = (uint32_t*) (0x01C20C00); + *temp_addr |= temp; + + /* set init value */ + temp_addr = (uint32_t*) (0x01C20C00 + 0x18); + *temp_addr = 0; + + /* begin run timer */ + temp = 0x01 << 0; + temp_addr = (uint32_t*) (0x01C20C00 + 0x10); + *temp_addr |= temp; + + f1c100s_intc_set_isr(F1C100S_IRQ_TIMER0, timer_handler); + f1c100s_intc_enable_irq(F1C100S_IRQ_TIMER0); +} + +#else +static void timer_init(void) { } +#endif diff --git a/hw/bsp/f1c100s/family.cmake b/hw/bsp/f1c100s/family.cmake new file mode 100644 index 000000000..0903a0143 --- /dev/null +++ b/hw/bsp/f1c100s/family.cmake @@ -0,0 +1,114 @@ +include_guard() + +set(SDK_DIR ${TOP}/hw/mcu/allwinner/f1c100s) + +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR arm926ej-s CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS F1C100S CACHE INTERNAL "") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + # LD_FILE and STARTUP_FILE can be defined in board.cmake + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${SDK_DIR}/f1c100s.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + + if (NOT DEFINED STARTUP_FILE_GNU) + set(STARTUP_FILE_GNU ${SDK_DIR}/machine/start.S) + endif () + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/lib/malloc.c + ${SDK_DIR}/lib/printf.c + ${SDK_DIR}/lib/memcpy.S + ${SDK_DIR}/lib/memset.S + ${SDK_DIR}/machine/sys-uart.c + ${SDK_DIR}/machine/exception.c + ${SDK_DIR}/machine/sys-clock.c + ${SDK_DIR}/machine/sys-copyself.c + ${SDK_DIR}/machine/sys-dram.c + ${SDK_DIR}/machine/sys-mmu.c + ${SDK_DIR}/machine/sys-spi-flash.c + ${SDK_DIR}/machine/f1c100s-intc.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + + target_compile_definitions(${BOARD_TARGET} PUBLIC + __ARM32_ARCH__=5 + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/include + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -lgcc + --specs=nosys.specs --specs=nano.specs + "LINKER:--defsym=__bss_end__=__bss_end" + "LINKER:--defsym=__bss_start__=__bss_start" + "LINKER:--defsym=end=__bss_end" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_F1C100S ${RTOS}) + target_sources(${TARGET}-tinyusb PRIVATE + ${TOP}/src/portable/sunxi/dcd_sunxi_musb.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/f1c100s/family.mk b/hw/bsp/f1c100s/family.mk new file mode 100644 index 000000000..be416e72e --- /dev/null +++ b/hw/bsp/f1c100s/family.mk @@ -0,0 +1,58 @@ +SDK_DIR = hw/mcu/allwinner/f1c100s + +include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= arm926ej-s + +#CFLAGS += \ +# -march=armv5te \ +# -mtune=arm926ej-s \ +# -mfloat-abi=soft \ +# -marm \ + +CFLAGS += \ + -ffreestanding \ + -std=gnu99 \ + -mno-thumb-interwork \ + -D__ARM32_ARCH__=5 \ + -D__ARM926EJS__ \ + -Wno-float-equal \ + -Wno-unused-parameter \ + -DCFG_TUSB_MCU=OPT_MCU_F1C100S \ + -Wno-error=array-bounds \ + +LD_FILE = ${SDK_DIR}/f1c100s.ld + +# TODO may skip nanolib +LDFLAGS += \ + -nostdlib -lgcc \ + --specs=nosys.specs --specs=nano.specs \ + +SRC_C += \ + src/portable/sunxi/dcd_sunxi_musb.c \ + ${SDK_DIR}/machine/sys-uart.c \ + ${SDK_DIR}/machine/exception.c \ + ${SDK_DIR}/machine/sys-clock.c \ + ${SDK_DIR}/machine/sys-copyself.c \ + ${SDK_DIR}/machine/sys-dram.c \ + ${SDK_DIR}/machine/sys-mmu.c \ + ${SDK_DIR}/machine/sys-spi-flash.c \ + ${SDK_DIR}/machine/f1c100s-intc.c \ + ${SDK_DIR}/lib/malloc.c \ + ${SDK_DIR}/lib/printf.c + +SRC_S += \ + ${SDK_DIR}/machine/start.S \ + ${SDK_DIR}/lib/memcpy.S \ + ${SDK_DIR}/lib/memset.S + +INC += \ + $(TOP)/${SDK_DIR}/include \ + $(TOP)/$(BOARD_PATH) + +# flash target using xfel +flash: flash-xfel + +exec: $(BUILD)/$(PROJECT).bin + xfel ddr + xfel write 0x80000000 $< + xfel exec 0x80000000 diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index 6cc1975a8..6f36ad441 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -35,7 +35,9 @@ #include #include #include "musb_def.h" -#include "bsp/board.h" + +//#include "bsp/board_api.h" +extern uint32_t board_millis(void); // TODO remove typedef uint32_t u32; typedef uint16_t u16; @@ -58,7 +60,7 @@ typedef struct TU_ATTR_PACKED typedef struct { - tusb_control_request_t setup_packet; + CFG_TUD_MEM_ALIGN tusb_control_request_t setup_packet; uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */ int8_t status_out; pipe_state_t pipe0; @@ -350,7 +352,7 @@ static void USBC_INT_DisableRxEp(u8 ep_index) * INTERNAL FUNCTION DECLARATION *------------------------------------------------------------------*/ -static dcd_data_t _dcd; +CFG_TUD_MEM_ALIGN static dcd_data_t _dcd; static inline free_block_t *find_containing_block(free_block_t *beg, free_block_t *end, uint_fast16_t addr) { @@ -560,7 +562,7 @@ static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigne static void process_setup_packet(uint8_t rhport) { - uint32_t *p = (uint32_t*)&_dcd.setup_packet; + uint32_t *p = (uint32_t*)(uintptr_t) &_dcd.setup_packet; p[0] = USBC_Readl(USBC_REG_EPFIFO0(USBC0_BASE)); p[1] = USBC_Readl(USBC_REG_EPFIFO0(USBC0_BASE)); @@ -594,7 +596,7 @@ static bool handle_xfer_in(uint_fast8_t ep_addr) if (len) { volatile void* addr = (volatile void*)(USBC_REG_EPFIFO1(USBC0_BASE) + (epnum_minus1 << 2)); if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) { - pipe_read_write_packet_ff((tu_fifo_t *)buf, addr, len, TUSB_DIR_IN); + pipe_read_write_packet_ff((tu_fifo_t *)(uintptr_t) buf, addr, len, TUSB_DIR_IN); } else { pipe_write_packet(buf, addr, len); pipe->buf = buf + len; @@ -622,7 +624,7 @@ static bool handle_xfer_out(uint_fast8_t ep_addr) if (len) { volatile void* addr = (volatile void*)(USBC_REG_EPFIFO1(USBC0_BASE) + (epnum_minus1 << 2)); if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) { - pipe_read_write_packet_ff((tu_fifo_t *)buf, addr, len, TUSB_DIR_OUT); + pipe_read_write_packet_ff((tu_fifo_t *)(uintptr_t )buf, addr, len, TUSB_DIR_OUT); } else { pipe_read_packet(buf, addr, len); pipe->buf = buf + len; -- cgit v1.3.1 From d25ee82d3f689dcf22e44246b61f58756195581d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 7 May 2024 00:17:09 +0200 Subject: Reformat net_lwip_webserver example. --- examples/device/net_lwip_webserver/src/main.c | 113 +++++++++------------ .../device/net_lwip_webserver/src/tusb_config.h | 50 +++++---- 2 files changed, 78 insertions(+), 85 deletions(-) (limited to 'examples') diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 7d98aacbc..e6f5faeb6 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -48,12 +48,13 @@ try changing the first byte of tud_network_mac_address[] below from 0x02 to 0x00 #include "dhserver.h" #include "dnserver.h" +#include "httpd.h" +#include "lwip/ethip6.h" #include "lwip/init.h" #include "lwip/timeouts.h" -#include "lwip/ethip6.h" -#include "httpd.h" -#define INIT_IP4(a,b,c,d) { PP_HTONL(LWIP_MAKEU32(a,b,c,d)) } +#define INIT_IP4(a, b, c, d) \ + { PP_HTONL(LWIP_MAKEU32(a, b, c, d)) } /* lwip context */ static struct netif netif_data; @@ -64,44 +65,40 @@ static struct pbuf *received_frame; /* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ /* ideally speaking, this should be generated from the hardware's unique ID (if available) */ /* it is suggested that the first byte is 0x02 to indicate a link-local address */ -uint8_t tud_network_mac_address[6] = {0x02,0x02,0x84,0x6A,0x96,0x00}; +uint8_t tud_network_mac_address[6] = {0x02, 0x02, 0x84, 0x6A, 0x96, 0x00}; /* network parameters of this MCU */ -static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 1); +static const ip4_addr_t ipaddr = INIT_IP4(192, 168, 7, 1); static const ip4_addr_t netmask = INIT_IP4(255, 255, 255, 0); static const ip4_addr_t gateway = INIT_IP4(0, 0, 0, 0); /* database IP addresses that can be offered to the host; this must be in RAM to store assigned MAC addresses */ -static dhcp_entry_t entries[] = -{ - /* mac ip address lease time */ - { {0}, INIT_IP4(192, 168, 7, 2), 24 * 60 * 60 }, - { {0}, INIT_IP4(192, 168, 7, 3), 24 * 60 * 60 }, - { {0}, INIT_IP4(192, 168, 7, 4), 24 * 60 * 60 }, +static dhcp_entry_t entries[] = { + /* mac ip address lease time */ + {{0}, INIT_IP4(192, 168, 7, 2), 24 * 60 * 60}, + {{0}, INIT_IP4(192, 168, 7, 3), 24 * 60 * 60}, + {{0}, INIT_IP4(192, 168, 7, 4), 24 * 60 * 60}, }; -static const dhcp_config_t dhcp_config = -{ - .router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */ - .port = 67, /* listen port */ - .dns = INIT_IP4(192, 168, 7, 1), /* dns server (if any) */ - "usb", /* dns suffix */ - TU_ARRAY_SIZE(entries), /* num entry */ - entries /* entries */ +static const dhcp_config_t dhcp_config = { + .router = INIT_IP4(0, 0, 0, 0), /* router address (if any) */ + .port = 67, /* listen port */ + .dns = INIT_IP4(192, 168, 7, 1), /* dns server (if any) */ + "usb", /* dns suffix */ + TU_ARRAY_SIZE(entries), /* num entry */ + entries /* entries */ }; -static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) -{ - (void)netif; - for (;;) - { +static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) { + (void) netif; + + for (;;) { /* if TinyUSB isn't ready, we must signal back to lwip that there is nothing we can do */ if (!tud_ready()) return ERR_USE; /* if the network driver can accept another packet, we make it happen */ - if (tud_network_can_xmit(p->tot_len)) - { + if (tud_network_can_xmit(p->tot_len)) { tud_network_xmit(p, 0 /* unused for this example */); return ERR_OK; } @@ -111,20 +108,17 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) } } -static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) -{ +static err_t ip4_output_fn(struct netif *netif, struct pbuf *p, const ip4_addr_t *addr) { return etharp_output(netif, p, addr); } #if LWIP_IPV6 -static err_t ip6_output_fn(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) -{ +static err_t ip6_output_fn(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) { return ethip6_output(netif, p, addr); } #endif -static err_t netif_init_cb(struct netif *netif) -{ +static err_t netif_init_cb(struct netif *netif) { LWIP_ASSERT("netif != NULL", (netif != NULL)); netif->mtu = CFG_TUD_NET_MTU; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; @@ -139,8 +133,7 @@ static err_t netif_init_cb(struct netif *netif) return ERR_OK; } -static void init_lwip(void) -{ +static void init_lwip(void) { struct netif *netif = &netif_data; lwip_init(); @@ -158,28 +151,23 @@ static void init_lwip(void) } /* handle any DNS requests from dns-server */ -bool dns_query_proc(const char *name, ip4_addr_t *addr) -{ - if (0 == strcmp(name, "tiny.usb")) - { +bool dns_query_proc(const char *name, ip4_addr_t *addr) { + if (0 == strcmp(name, "tiny.usb")) { *addr = ipaddr; return true; } return false; } -bool tud_network_recv_cb(const uint8_t *src, uint16_t size) -{ +bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { /* this shouldn't happen, but if we get another packet before parsing the previous, we must signal our inability to accept it */ if (received_frame) return false; - if (size) - { + if (size) { struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); - if (p) - { + if (p) { /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ memcpy(p->payload, src, size); @@ -191,20 +179,17 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size) return true; } -uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) -{ - struct pbuf *p = (struct pbuf *)ref; +uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) { + struct pbuf *p = (struct pbuf *) ref; - (void)arg; /* unused for this example */ + (void) arg; /* unused for this example */ return pbuf_copy_partial(p, dst, p->tot_len, 0); } -static void service_traffic(void) -{ +static void service_traffic(void) { /* handle any packet received by tud_network_recv_cb() */ - if (received_frame) - { + if (received_frame) { ethernet_input(received_frame, &netif_data); pbuf_free(received_frame); received_frame = NULL; @@ -214,18 +199,15 @@ static void service_traffic(void) sys_check_timeouts(); } -void tud_network_init_cb(void) -{ +void tud_network_init_cb(void) { /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ - if (received_frame) - { + if (received_frame) { pbuf_free(received_frame); received_frame = NULL; } } -int main(void) -{ +int main(void) { /* initialize TinyUSB */ board_init(); @@ -243,8 +225,8 @@ int main(void) while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK); httpd_init(); - while (1) - { + + while (1) { tud_task(); service_traffic(); } @@ -253,17 +235,14 @@ int main(void) } /* lwip has provision for using a mutex, when applicable */ -sys_prot_t sys_arch_protect(void) -{ +sys_prot_t sys_arch_protect(void) { return 0; } -void sys_arch_unprotect(sys_prot_t pval) -{ - (void)pval; +void sys_arch_unprotect(sys_prot_t pval) { + (void) pval; } /* lwip needs a millisecond time source, and the TinyUSB board support code has one available */ -uint32_t sys_now(void) -{ +uint32_t sys_now(void) { return board_millis(); } diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index 841525cad..e0db3113c 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -27,21 +27,23 @@ #define _TUSB_CONFIG_H_ #ifdef __cplusplus - extern "C" { +extern "C" { #endif +#include "lwipopts.h" + //--------------------------------------------------------------------+ // Board Specific Configuration //--------------------------------------------------------------------+ // RHPort number used for device can be defined by board.mk, default to port 0 #ifndef BOARD_TUD_RHPORT -#define BOARD_TUD_RHPORT 0 + #define BOARD_TUD_RHPORT 0 #endif // RHPort max operational speed can defined by board.mk #ifndef BOARD_TUD_MAX_SPEED -#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED + #define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED #endif //-------------------------------------------------------------------- @@ -50,22 +52,22 @@ // defined by compiler flags for flexibility #ifndef CFG_TUSB_MCU -#error CFG_TUSB_MCU must be defined + #error CFG_TUSB_MCU must be defined #endif #ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_NONE + #define CFG_TUSB_OS OPT_OS_NONE #endif #ifndef CFG_TUSB_DEBUG -#define CFG_TUSB_DEBUG 0 + #define CFG_TUSB_DEBUG 0 #endif // Enable Device stack -#define CFG_TUD_ENABLED 1 +#define CFG_TUD_ENABLED 1 // Default is max speed that hardware controller could support with on-chip PHY -#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED +#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put @@ -75,21 +77,33 @@ * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) */ #ifndef CFG_TUSB_MEM_SECTION -#define CFG_TUSB_MEM_SECTION + #define CFG_TUSB_MEM_SECTION #endif #ifndef CFG_TUSB_MEM_ALIGN -#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) + #define CFG_TUSB_MEM_ALIGN __attribute__((aligned(4))) #endif -// number of NCM transfer blocks for reception side (only valid if NCM is selected below) +//-------------------------------------------------------------------- +// NCM CLASS CONFIGURATION, SEE "ncm.h" FOR PERFORMANCE TUNNING +//-------------------------------------------------------------------- + +// Must be >> MTU +// Can be set to 2048 without impact +#define CFG_TUD_NCM_IN_NTB_MAX_SIZE (2 * TCP_MSS + 100) + +// Must be >> MTU +// Can be set to smaller values if wNtbOutMaxDatagrams==1 +#define CFG_TUD_NCM_OUT_NTB_MAX_SIZE (2 * TCP_MSS + 100) + +// Number of NCM transfer blocks for reception side #ifndef CFG_TUD_NCM_OUT_NTB_N -#define CFG_TUD_NCM_OUT_NTB_N 2 + #define CFG_TUD_NCM_OUT_NTB_N 1 #endif -// number of NCM transfer blocks for transmission side (only valid if NCM is selected below) +// Number of NCM transfer blocks for transmission side #ifndef CFG_TUD_NCM_IN_NTB_N -#define CFG_TUD_NCM_IN_NTB_N 3 + #define CFG_TUD_NCM_IN_NTB_N 1 #endif //-------------------------------------------------------------------- @@ -97,18 +111,18 @@ //-------------------------------------------------------------------- #ifndef CFG_TUD_ENDPOINT0_SIZE -#define CFG_TUD_ENDPOINT0_SIZE 64 + #define CFG_TUD_ENDPOINT0_SIZE 64 #endif //------------- CLASS -------------// // Network class has 2 drivers: ECM/RNDIS and NCM. // Only one of the drivers can be enabled -#define CFG_TUD_ECM_RNDIS 1 -#define CFG_TUD_NCM (1-CFG_TUD_ECM_RNDIS) +#define CFG_TUD_ECM_RNDIS 1 +#define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS) #ifdef __cplusplus - } +} #endif #endif /* _TUSB_CONFIG_H_ */ -- cgit v1.3.1 From 63d5103f42f5da11e08566a107c85b358e3d11aa Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 7 May 2024 00:18:31 +0200 Subject: Increase TCP_WND for better performance. --- examples/device/net_lwip_webserver/src/lwipopts.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/device/net_lwip_webserver/src/lwipopts.h b/examples/device/net_lwip_webserver/src/lwipopts.h index 336c9243d..41e8f0d67 100644 --- a/examples/device/net_lwip_webserver/src/lwipopts.h +++ b/examples/device/net_lwip_webserver/src/lwipopts.h @@ -48,8 +48,8 @@ #define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) #define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) -#define TCP_SND_BUF (2 * TCP_MSS) -#define TCP_WND (TCP_MSS) +#define TCP_SND_BUF (4 * TCP_MSS) +#define TCP_WND (4 * TCP_MSS) #define ETHARP_SUPPORT_STATIC_ENTRIES 1 @@ -59,7 +59,7 @@ #define LWIP_SINGLE_NETIF 1 -#define PBUF_POOL_SIZE 2 +#define PBUF_POOL_SIZE 4 #define HTTPD_USE_CUSTOM_FSDATA 0 -- cgit v1.3.1 From 0f4ea8e9182c3f1f526e2ff5447ca31c5c7d8709 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 7 May 2024 00:23:50 +0200 Subject: Enable NCM + iperf for MCU with bigger RAM. --- examples/device/net_lwip_webserver/CMakeLists.txt | 1 + examples/device/net_lwip_webserver/Makefile | 1 + examples/device/net_lwip_webserver/src/main.c | 8 ++++++++ examples/device/net_lwip_webserver/src/tusb_config.h | 14 +++++++++++++- 4 files changed, 23 insertions(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/device/net_lwip_webserver/CMakeLists.txt b/examples/device/net_lwip_webserver/CMakeLists.txt index a16b8bd71..c39fd32c5 100644 --- a/examples/device/net_lwip_webserver/CMakeLists.txt +++ b/examples/device/net_lwip_webserver/CMakeLists.txt @@ -74,6 +74,7 @@ target_sources(${PROJECT} PUBLIC ${LWIP}/src/netif/slipif.c ${LWIP}/src/apps/http/httpd.c ${LWIP}/src/apps/http/fs.c + ${LWIP}/src/apps/lwiperf/lwiperf.c ) # due to warnings from other net source, we need to prevent error from some of the warnings options diff --git a/examples/device/net_lwip_webserver/Makefile b/examples/device/net_lwip_webserver/Makefile index 22426ba0d..141532466 100644 --- a/examples/device/net_lwip_webserver/Makefile +++ b/examples/device/net_lwip_webserver/Makefile @@ -63,6 +63,7 @@ SRC_C += \ lib/lwip/src/netif/slipif.c \ lib/lwip/src/apps/http/httpd.c \ lib/lwip/src/apps/http/fs.c \ + lib/lwip/src/apps/lwiperf/lwiperf.c \ lib/networking/dhserver.c \ lib/networking/dnserver.c \ lib/networking/rndis_reports.c diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index e6f5faeb6..791e09b4f 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -53,6 +53,10 @@ try changing the first byte of tud_network_mac_address[] below from 0x02 to 0x00 #include "lwip/init.h" #include "lwip/timeouts.h" +#ifdef INCLUDE_IPERF + #include "lwip/apps/lwiperf.h" +#endif + #define INIT_IP4(a, b, c, d) \ { PP_HTONL(LWIP_MAKEU32(a, b, c, d)) } @@ -225,6 +229,10 @@ int main(void) { while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK); httpd_init(); +#ifdef INCLUDE_IPERF + // test with: iperf -c 192.168.7.1 -e -i 1 -M 5000 -l 8192 -r + lwiperf_start_tcp_server_default(NULL, NULL); +#endif while (1) { tud_task(); diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index e0db3113c..ae5e67513 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -84,6 +84,18 @@ extern "C" { #define CFG_TUSB_MEM_ALIGN __attribute__((aligned(4))) #endif +// Use different configurations to test all net devices (also due to resource limitations) +#if TU_CHECK_MCU(OPT_MCU_LPC15XX, OPT_MCU_LPC40XX, OPT_MCU_LPC51UXX, OPT_MCU_LPC54) + #define USE_ECM 1 +#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAML21, OPT_MCU_SAML22) + #define USE_ECM 1 +#elif TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F1) + #define USE_ECM 1 +#else + #define USE_ECM 0 + #define INCLUDE_IPERF +#endif + //-------------------------------------------------------------------- // NCM CLASS CONFIGURATION, SEE "ncm.h" FOR PERFORMANCE TUNNING //-------------------------------------------------------------------- @@ -118,7 +130,7 @@ extern "C" { // Network class has 2 drivers: ECM/RNDIS and NCM. // Only one of the drivers can be enabled -#define CFG_TUD_ECM_RNDIS 1 +#define CFG_TUD_ECM_RNDIS USE_ECM #define CFG_TUD_NCM (1 - CFG_TUD_ECM_RNDIS) #ifdef __cplusplus -- cgit v1.3.1 From e5d92c4ea736669445d728d6374f0e1b00c9eb15 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 7 May 2024 00:37:57 +0200 Subject: Fix CI. --- examples/device/net_lwip_webserver/skip.txt | 2 ++ examples/device/net_lwip_webserver/src/tusb_config.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index 75aa2ef14..bb3ff7885 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -1,9 +1,11 @@ mcu:LPC11UXX mcu:LPC13XX +mcu:LPC15XX mcu:MSP430x5xx mcu:NUC121 mcu:SAMD11 mcu:STM32L0 +mcu:STM32F0 mcu:KINETIS_KL family:broadcom_64bit family:broadcom_32bit diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index ae5e67513..d3e094517 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -97,7 +97,7 @@ extern "C" { #endif //-------------------------------------------------------------------- -// NCM CLASS CONFIGURATION, SEE "ncm.h" FOR PERFORMANCE TUNNING +// NCM CLASS CONFIGURATION, SEE "ncm.h" FOR PERFORMANCE TUNING //-------------------------------------------------------------------- // Must be >> MTU -- cgit v1.3.1 From ba6babf570752a28379aab51d9c27e7b9efe872d Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Thu, 9 May 2024 20:43:46 +0700 Subject: Rework ci (#2631) * add name field to usbd_class_driver_t * ci: use set matrix py script * add riscv32 and cmake support for ch32v307, fomu, gd32vf103 * update build_cmake.py to take --family --board --toolchain * separate hil test to its own workflow * move esp32 board into separated hil json * add make build to ci * remov build_make.py * build.py support esp32 board * setup toolchain support esp-idf * fix missing click * merge family in matrix build to reduce jobs * skip cifuzz since it still has issue with get_deps and click --- .github/actions/prepare_build/action.yml | 30 +++ .github/actions/setup_toolchain/action.yml | 31 +++ .../actions/setup_toolchain/download/action.yml | 29 ++ .github/workflows/build_aarch64.yml | 70 ----- .github/workflows/build_arm.yml | 57 ---- .github/workflows/build_cmake.yml | 295 ++++----------------- .github/workflows/build_esp.yml | 19 +- .github/workflows/build_family.yml | 64 +++++ .github/workflows/build_iar.yml | 4 +- .github/workflows/build_renesas.yml | 6 +- .github/workflows/build_riscv.yml | 71 ----- .github/workflows/build_win_mac.yml | 6 +- .github/workflows/ci_set_matrix.py | 51 ++++ .github/workflows/cifuzz.yml | 3 + .github/workflows/codeql-buildscript.sh | 3 +- .github/workflows/hil_test.yml | 125 +++++++++ .github/workflows/pre-commit.yml | 1 + .idea/cmake.xml | 8 +- examples/build_system/cmake/cpu/rv32i-ilp32.cmake | 19 ++ .../build_system/cmake/cpu/rv32imac-ilp32.cmake | 18 ++ .../build_system/cmake/toolchain/riscv_gcc.cmake | 21 ++ examples/build_system/make/cpu/rv32i-ilp32.mk | 13 + examples/build_system/make/cpu/rv32imac-ilp32.mk | 13 + examples/build_system/make/toolchain/riscv_gcc.mk | 20 ++ examples/device/video_capture/skip.txt | 1 - .../ch32v307/boards/ch32v307v_r1_1v0/board.cmake | 4 + .../ch32v307/boards/ch32v307v_r1_1v0/debug_uart.c | 110 -------- .../ch32v307/boards/ch32v307v_r1_1v0/debug_uart.h | 31 --- hw/bsp/ch32v307/debug_uart.c | 110 ++++++++ hw/bsp/ch32v307/debug_uart.h | 31 +++ hw/bsp/ch32v307/family.cmake | 114 ++++++++ hw/bsp/ch32v307/family.mk | 12 +- .../led_strip_rmt_ws2812/dependencies.lock | 15 -- hw/bsp/family_support.cmake | 24 +- hw/bsp/fomu/boards/fomu/board.cmake | 4 + hw/bsp/fomu/family.c | 121 +++++++++ hw/bsp/fomu/family.cmake | 91 +++++++ hw/bsp/fomu/family.mk | 9 +- hw/bsp/fomu/fomu.c | 120 --------- .../boards/sipeed_longan_nano/board.cmake | 13 + .../gd32vf103/boards/sipeed_longan_nano/board.mk | 1 - hw/bsp/gd32vf103/family.c | 4 +- hw/bsp/gd32vf103/family.cmake | 119 +++++++++ hw/bsp/gd32vf103/family.mk | 10 +- hw/bsp/lpc51/family.cmake | 1 - src/device/usbd.c | 28 +- src/device/usbd_pvt.h | 7 +- test/hil/hfp.json | 25 ++ test/hil/hil_hfp.json | 25 -- test/hil/hil_pi4.json | 37 --- test/hil/hil_test.py | 69 +++-- test/hil/pi4.json | 27 ++ test/hil/pi4_esp32.json | 14 + tools/build.py | 177 +++++++++++++ tools/build_board.py | 69 ----- tools/build_cmake.py | 105 -------- tools/build_make.py | 80 ------ tools/get_deps.py | 54 ++-- 58 files changed, 1482 insertions(+), 1157 deletions(-) create mode 100644 .github/actions/prepare_build/action.yml create mode 100644 .github/actions/setup_toolchain/action.yml create mode 100644 .github/actions/setup_toolchain/download/action.yml delete mode 100644 .github/workflows/build_aarch64.yml delete mode 100644 .github/workflows/build_arm.yml create mode 100644 .github/workflows/build_family.yml delete mode 100644 .github/workflows/build_riscv.yml create mode 100644 .github/workflows/ci_set_matrix.py create mode 100644 .github/workflows/hil_test.yml create mode 100644 examples/build_system/cmake/cpu/rv32i-ilp32.cmake create mode 100644 examples/build_system/cmake/cpu/rv32imac-ilp32.cmake create mode 100644 examples/build_system/cmake/toolchain/riscv_gcc.cmake create mode 100644 examples/build_system/make/cpu/rv32i-ilp32.mk create mode 100644 examples/build_system/make/cpu/rv32imac-ilp32.mk create mode 100644 examples/build_system/make/toolchain/riscv_gcc.mk create mode 100644 hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/board.cmake delete mode 100644 hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.c delete mode 100644 hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.h create mode 100644 hw/bsp/ch32v307/debug_uart.c create mode 100644 hw/bsp/ch32v307/debug_uart.h create mode 100644 hw/bsp/ch32v307/family.cmake delete mode 100644 hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/dependencies.lock create mode 100644 hw/bsp/fomu/boards/fomu/board.cmake create mode 100644 hw/bsp/fomu/family.c create mode 100644 hw/bsp/fomu/family.cmake delete mode 100644 hw/bsp/fomu/fomu.c create mode 100644 hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.cmake create mode 100644 hw/bsp/gd32vf103/family.cmake create mode 100644 test/hil/hfp.json delete mode 100644 test/hil/hil_hfp.json delete mode 100644 test/hil/hil_pi4.json create mode 100644 test/hil/pi4.json create mode 100644 test/hil/pi4_esp32.json create mode 100644 tools/build.py delete mode 100644 tools/build_board.py delete mode 100644 tools/build_cmake.py delete mode 100644 tools/build_make.py (limited to 'examples') diff --git a/.github/actions/prepare_build/action.yml b/.github/actions/prepare_build/action.yml new file mode 100644 index 000000000..5f2c544c1 --- /dev/null +++ b/.github/actions/prepare_build/action.yml @@ -0,0 +1,30 @@ +name: Prepare to build + +inputs: + family: + required: true + type: string + +runs: + using: "composite" + steps: + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Checkout pico-sdk for rp2040 + if: contains(inputs.family, 'rp2040') + uses: actions/checkout@v4 + with: + repository: raspberrypi/pico-sdk + ref: develop + path: pico-sdk + + - name: Get Dependencies + run: | + sudo apt install -y ninja-build + pip install click + python3 tools/get_deps.py ${{ inputs.family }} + echo >> $GITHUB_ENV "PICO_SDK_PATH=$GITHUB_WORKSPACE/pico-sdk" + shell: bash diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml new file mode 100644 index 000000000..b59ece116 --- /dev/null +++ b/.github/actions/setup_toolchain/action.yml @@ -0,0 +1,31 @@ +name: Setup Toolchain + +inputs: + toolchain: + required: true + type: string + toolchain_url: + required: false + type: string + +runs: + using: "composite" + steps: + - name: Install ARM GCC + if: inputs.toolchain == 'arm-gcc' + uses: carlosperate/arm-none-eabi-gcc-action@v1 + with: + release: '12.3.Rel1' + + - name: Pull ESP-IDF docker + if: inputs.toolchain == 'esp-idf' + run: docker pull espressif/idf:latest + shell: bash + + - name: Download Toolchain + if: >- + inputs.toolchain != 'arm-gcc' && + inputs.toolchain != 'esp-idf' + uses: ./.github/actions/setup_toolchain/download + with: + toolchain_url: ${{ inputs.toolchain_url }} diff --git a/.github/actions/setup_toolchain/download/action.yml b/.github/actions/setup_toolchain/download/action.yml new file mode 100644 index 000000000..db85e9027 --- /dev/null +++ b/.github/actions/setup_toolchain/download/action.yml @@ -0,0 +1,29 @@ +name: Download Toolchain + +inputs: + toolchain_url: + required: true + type: string + +runs: + using: "composite" + steps: + - name: Cache Toolchain + uses: actions/cache@v4 + id: cache-toolchain + with: + path: ~/cache/toolchain + key: ${{ runner.os }}-${{ inputs.toolchain_url }} + + - name: Install Toolchain + if: steps.cache-toolchain.outputs.cache-hit != 'true' + run: | + mkdir -p ~/cache/toolchain + wget --progress=dot:mega ${{ inputs.toolchain_url }} -O toolchain.tar.gz + tar -C ~/cache/toolchain -xaf toolchain.tar.gz + shell: bash + + - name: Set Toolchain Path + run: | + echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin` + shell: bash diff --git a/.github/workflows/build_aarch64.yml b/.github/workflows/build_aarch64.yml deleted file mode 100644 index 237692498..000000000 --- a/.github/workflows/build_aarch64.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Build AArch64 - -on: - workflow_dispatch: - push: - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - '.github/workflows/build_aarch64.yml' - pull_request: - branches: [ master ] - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - '.github/workflows/build_aarch64.yml' - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - # --------------------------------------- - # Build AARCH64 family - # --------------------------------------- - build-arm: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - family: - # Alphabetical order - - 'broadcom_64bit' - steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Set Toolchain URL - run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz - - - name: Cache Toolchain - uses: actions/cache@v4 - id: cache-toolchain - with: - path: ~/cache/ - key: ${{ runner.os }}-21-11-02-${{ env.TOOLCHAIN_URL }} - - - name: Install Toolchain - if: steps.cache-toolchain.outputs.cache-hit != 'true' - run: | - mkdir -p ~/cache/toolchain - wget --progress=dot:mega $TOOLCHAIN_URL -O toolchain.tar.gz - tar -C ~/cache/toolchain -xaf toolchain.tar.gz - - - name: Set Toolchain Path - run: echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin` - - - name: Get Dependencies - run: python3 tools/get_deps.py ${{ matrix.family }} - - - name: Build - run: python3 tools/build_make.py ${{ matrix.family }} diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml deleted file mode 100644 index 14c6d519c..000000000 --- a/.github/workflows/build_arm.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Build ARM - -on: - workflow_dispatch: - push: - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'tools/get_deps.py' - - '.github/workflows/build_arm.yml' - pull_request: - branches: [ master ] - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'tools/get_deps.py' - - '.github/workflows/build_arm.yml' - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - # --------------------------------------- - # Build ARM family - # --------------------------------------- - build-arm: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - family: - # Alphabetical order - - 'mm32' - steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - - name: Install ARM GCC - uses: carlosperate/arm-none-eabi-gcc-action@v1 - with: - release: '11.2-2022.02' - - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Get Dependencies - run: python3 tools/get_deps.py ${{ matrix.family }} - - - name: Build - run: python3 tools/build_make.py ${{ matrix.family }} diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index c1f85ad9c..b62a0e9bd 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -1,4 +1,4 @@ -name: Build CMake +name: Build on: workflow_dispatch: @@ -8,9 +8,11 @@ on: - 'examples/**' - 'lib/**' - 'hw/**' - - 'test/hil/**' - 'tools/get_deps.py' + - 'tools/build.py' + - '.github/actions/**' - '.github/workflows/build_cmake.yml' + - '.github/workflows/ci_set_matrix.py' pull_request: branches: [ master ] paths: @@ -18,141 +20,20 @@ on: - 'examples/**' - 'lib/**' - 'hw/**' - - 'test/hil/**' - 'tools/get_deps.py' + - 'tools/build.py' + - '.github/actions/**' - '.github/workflows/build_cmake.yml' - + - '.github/workflows/ci_set_matrix.py' concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: - # --------------------------------------- - # Build ARM with GCC - # --------------------------------------- - arm-gcc: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - family: - # Alphabetical order - - 'broadcom_32bit' - - 'imxrt' - - 'kinetis_k kinetis_kl kinetis_k32l2' - - 'lpc11 lpc13 lpc15' - - 'lpc17 lpc18 lpc40 lpc43' - - 'lpc51 lpc54 lpc55' - - 'mcx' - - 'msp432e4' - - 'mm32' - - 'nrf' - - 'ra' - - 'rp2040' - - 'samd11 samd21 saml2x samd5x_e5x samg' - - 'stm32f0' - - 'stm32f1' - - 'stm32f2' - - 'stm32f3' - - 'stm32f4' - - 'stm32f7' - - 'stm32g0' - - 'stm32g4' - - 'stm32h5' - - 'stm32h7' - - 'stm32l4' - - 'stm32u5' - - 'stm32wb' - - 'tm4c' - - 'xmc4000' - steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - - name: Install ARM GCC - uses: carlosperate/arm-none-eabi-gcc-action@v1 - with: - release: '12.3.Rel1' - - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Checkout pico-sdk for rp2040 - if: matrix.family == 'rp2040' - uses: actions/checkout@v4 - with: - repository: raspberrypi/pico-sdk - ref: develop - path: pico-sdk - - - name: Get Dependencies - run: | - sudo apt install -y ninja-build - python3 tools/get_deps.py ${{ matrix.family }} - - - name: Build - run: python tools/build_cmake.py ${{ matrix.family }} - env: - PICO_SDK_PATH: ${{ github.workspace }}/pico-sdk - - - name: Upload Artifacts for Hardware Testing (rp2040) - if: contains(matrix.family, 'rp2040') && github.repository_owner == 'hathach' - uses: actions/upload-artifact@v4 - with: - name: raspberry_pi_pico - path: | - cmake-build/cmake-build-raspberry_pi_pico/*/*/*.elf - - - name: Upload Artifacts for Hardware Testing (nRF) - if: contains(matrix.family, 'nrf') && github.repository_owner == 'hathach' - uses: actions/upload-artifact@v4 - with: - name: feather_nrf52840_express - path: | - cmake-build/cmake-build-feather_nrf52840_express/*/*/*.elf - - - name: Upload Artifacts for Hardware Testing (samd51) - if: contains(matrix.family, 'samd5x_e5x') && github.repository_owner == 'hathach' - uses: actions/upload-artifact@v4 - with: - name: itsybitsy_m4 - path: | - cmake-build/cmake-build-itsybitsy_m4/*/*/*.bin - - # --------------------------------------- - # Build ARM with Clang - # --------------------------------------- - arm-clang: + set-matrix: runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - family: - # Alphabetical order - - 'imxrt' - - 'kinetis_k kinetis_kl' - - 'lpc17 lpc18 lpc40 lpc43' - - 'lpc54 lpc55' - #- 'mcx' not working with gcc anymore, need to fix this first - - 'nrf' - #- 'ra' port later - #- 'rp2040' port later - - 'samd21' - - 'samd5x_e5x' - - 'stm32f0' - - 'stm32f1' - - 'stm32f2' - - 'stm32f3' - - 'stm32f4' - - 'stm32f7' - - 'stm32g0' - - 'stm32g4' - - 'stm32h5' - - 'stm32h7' - - 'stm32l4' - - 'stm32u5' + outputs: + json: ${{ steps.set-matrix-json.outputs.matrix }} steps: - name: Setup Python uses: actions/setup-python@v5 @@ -162,137 +43,51 @@ jobs: - name: Checkout TinyUSB uses: actions/checkout@v4 - - name: Checkout pico-sdk for rp2040 - if: matrix.family == 'rp2040' - uses: actions/checkout@v4 - with: - repository: raspberrypi/pico-sdk - ref: develop - path: pico-sdk - - - name: Set Toolchain URL - run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-17.0.1/LLVMEmbeddedToolchainForArm-17.0.1-Linux-x86_64.tar.xz - - - name: Cache Toolchain - uses: actions/cache@v4 - id: cache-toolchain - with: - path: ~/cache/ - key: ${{ runner.os }}-24-04-17-${{ env.TOOLCHAIN_URL }} - - - name: Install Toolchain - if: steps.cache-toolchain.outputs.cache-hit != 'true' - run: | - mkdir -p ~/cache/toolchain - wget --progress=dot:mega $TOOLCHAIN_URL -O toolchain.tar.xz - tar -C ~/cache/toolchain -xaf toolchain.tar.xz - - - name: Prepare to build + - name: Generate matrix json + id: set-matrix-json run: | - echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin` - sudo apt install -y ninja-build - python3 tools/get_deps.py ${{ matrix.family }} - - - name: Build - run: python tools/build_cmake.py ${{ matrix.family }} -DTOOLCHAIN=clang - env: - PICO_SDK_PATH: ${{ github.workspace }}/pico-sdk + MATRIX_JSON=$(python .github/workflows/ci_set_matrix.py) + echo "matrix=$MATRIX_JSON" + echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT # --------------------------------------- - # Build MSP430 with GCC + # Build CMake # --------------------------------------- - msp430-gcc: - runs-on: ubuntu-latest + cmake: + needs: set-matrix + uses: ./.github/workflows/build_family.yml strategy: fail-fast: false matrix: - family: - # Alphabetical order - - 'msp430' - steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Set Toolchain URL - run: echo >> $GITHUB_ENV TOOLCHAIN_URL=http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2 - - - name: Cache Toolchain - uses: actions/cache@v4 - id: cache-toolchain - with: - path: ~/cache/ - key: ${{ runner.os }}-24-04-17-${{ env.TOOLCHAIN_URL }} - - - name: Install Toolchain - if: steps.cache-toolchain.outputs.cache-hit != 'true' - run: | - mkdir -p ~/cache/toolchain - wget --progress=dot:mega $TOOLCHAIN_URL -O toolchain.tar.bz2 - tar -C ~/cache/toolchain -xaf toolchain.tar.bz2 - - - name: Prepare to build - run: | - echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin` - sudo apt install -y ninja-build - python3 tools/get_deps.py ${{ matrix.family }} - - - name: Build - run: python tools/build_cmake.py ${{ matrix.family }} + toolchain: + - 'aarch64-gcc' + - 'arm-clang' + - 'arm-gcc' + - 'msp430-gcc' + - 'riscv-gcc' + with: + build-system: 'cmake' + toolchain: ${{ matrix.toolchain }} + toolchain_url: ${{ fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].toolchain_url }} + build-family: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].family) }} # --------------------------------------- - # Hardware in the loop (HIL) - # Current self-hosted instance is running on an RPI4. For attached hardware checkout hil_pi4.json + # Build Make # --------------------------------------- - hil-test: - # run only with hathach's commit due to limited resource on RPI4 - if: github.repository_owner == 'hathach' - needs: arm-gcc - runs-on: [self-hosted, rp2040, nrf52840, hardware-in-the-loop] + make: + needs: set-matrix + uses: ./.github/workflows/build_family.yml strategy: fail-fast: false matrix: - board: - - 'feather_nrf52840_express' - - 'itsybitsy_m4' - - 'raspberry_pi_pico' - steps: - - name: Clean workspace - run: | - echo "Cleaning up previous run" - rm -rf "${{ github.workspace }}" - mkdir -p "${{ github.workspace }}" - - # USB bus on rpi4 is not stable, reset it before testing - - name: Reset USB bus - run: | - lsusb - lsusb -t - # reset VIA Labs 2.0 hub - sudo usbreset 001/002 - - # legacy code - #for port in $(lspci | grep USB | cut -d' ' -f1); do - # echo -n "0000:${port}"| sudo tee /sys/bus/pci/drivers/xhci_hcd/unbind; - # sleep 0.1; - # echo -n "0000:${port}" | sudo tee /sys/bus/pci/drivers/xhci_hcd/bind; - #done - - - name: Checkout test/hil - uses: actions/checkout@v4 - with: - sparse-checkout: test/hil - - - name: Download Artifacts - uses: actions/download-artifact@v4 - with: - name: ${{ matrix.board }} - path: cmake-build/cmake-build-${{ matrix.board }} - - - name: Test on actual hardware - run: | - python3 test/hil/hil_test.py --board ${{ matrix.board }} hil_pi4.json + toolchain: + - 'aarch64-gcc' + #- 'arm-clang' + - 'arm-gcc' + - 'msp430-gcc' + - 'riscv-gcc' + with: + build-system: 'make' + toolchain: ${{ matrix.toolchain }} + toolchain_url: ${{ fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].toolchain_url }} + build-family: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].family) }} diff --git a/.github/workflows/build_esp.yml b/.github/workflows/build_esp.yml index 4108a58a5..66fa8548e 100644 --- a/.github/workflows/build_esp.yml +++ b/.github/workflows/build_esp.yml @@ -41,14 +41,16 @@ jobs: with: python-version: '3.x' - - name: Pull ESP-IDF docker - run: docker pull espressif/idf:latest - - name: Checkout TinyUSB uses: actions/checkout@v4 + - name: Setup Toolchain + uses: ./.github/actions/setup_toolchain + with: + toolchain: 'esp-idf' + - name: Build - run: docker run --rm -v $PWD:/project -w /project espressif/idf:v5.1.1 python3 tools/build_esp32.py ${{ matrix.board }} + run: docker run --rm -v $PWD:/project -w /project espressif/idf:v5.1.1 python3 tools/build.py -b ${{ matrix.board }} - name: Upload Artifacts for Hardware Testing if: matrix.board == 'espressif_s3_devkitm' && github.repository_owner == 'hathach' @@ -91,13 +93,6 @@ jobs: # reset VIA Labs 2.0 hub sudo usbreset 001/002 - # legacy code - #for port in $(lspci | grep USB | cut -d' ' -f1); do - # echo -n "0000:${port}"| sudo tee /sys/bus/pci/drivers/xhci_hcd/unbind; - # sleep 0.1; - # echo -n "0000:${port}" | sudo tee /sys/bus/pci/drivers/xhci_hcd/bind; - #done - - name: Checkout test/hil uses: actions/checkout@v4 with: @@ -111,4 +106,4 @@ jobs: - name: Test on actual hardware run: | - python3 test/hil/hil_test.py --board ${{ matrix.board }} hil_pi4.json + python3 test/hil/hil_test.py --board ${{ matrix.board }} pi4_esp32.json diff --git a/.github/workflows/build_family.yml b/.github/workflows/build_family.yml new file mode 100644 index 000000000..2e89267a3 --- /dev/null +++ b/.github/workflows/build_family.yml @@ -0,0 +1,64 @@ +name: Build family + +on: + workflow_call: + inputs: + build-system: + required: true + type: string + toolchain: + required: true + type: string + toolchain_url: + required: true + type: string + build-family: + required: true + type: string + +jobs: + family: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + family: ${{ fromJSON(inputs.build-family) }} + steps: + - name: Checkout TinyUSB + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Setup Toolchain + uses: ./.github/actions/setup_toolchain + with: + toolchain: ${{ inputs.toolchain }} + toolchain_url: ${{ inputs.toolchain_url }} + + - name: Checkout pico-sdk for rp2040 + if: contains(matrix.family, 'rp2040') + uses: actions/checkout@v4 + with: + repository: raspberrypi/pico-sdk + ref: develop + path: pico-sdk + + - name: Get Dependencies + run: | + sudo apt install -y ninja-build + pip install click + python3 tools/get_deps.py ${{ matrix.family }} + + - name: Build + run: | + OPTION="" + if [[ "${{ inputs.toolchain }}" == *"clang"* ]]; then + OPTION="--toolchain clang" + fi + echo "OPTION=$OPTION" + python tools/build.py -s ${{ inputs.build-system }} $OPTION ${{ matrix.family }} + env: + PICO_SDK_PATH: ${{ github.workspace }}/pico-sdk diff --git a/.github/workflows/build_iar.yml b/.github/workflows/build_iar.yml index 6b1493a97..c4a7f96b7 100644 --- a/.github/workflows/build_iar.yml +++ b/.github/workflows/build_iar.yml @@ -52,8 +52,8 @@ jobs: run: python3 tools/get_deps.py ${{ matrix.family }} - name: Build - run: python3 tools/build_cmake.py ${{ matrix.family }} -DTOOLCHAIN=iar + run: python3 tools/build.py --toolchain iar ${{ matrix.family }} - name: Test on actual hardware (hardware in the loop) run: | - python3 test/hil/hil_test.py hil_hfp.json + python3 test/hil/hil_test.py hfp.json diff --git a/.github/workflows/build_renesas.yml b/.github/workflows/build_renesas.yml index fbc12d285..8c83bdbbf 100644 --- a/.github/workflows/build_renesas.yml +++ b/.github/workflows/build_renesas.yml @@ -64,7 +64,9 @@ jobs: run: echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin` - name: Get Dependencies - run: python3 tools/get_deps.py ${{ matrix.family }} + run: | + pip install click + python3 tools/get_deps.py ${{ matrix.family }} - name: Build - run: python3 tools/build_make.py ${{ matrix.family }} + run: python3 tools/build.py -s make ${{ matrix.family }} diff --git a/.github/workflows/build_riscv.yml b/.github/workflows/build_riscv.yml deleted file mode 100644 index 7f5031ff1..000000000 --- a/.github/workflows/build_riscv.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Build RISC-V - -on: - workflow_dispatch: - push: - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'tools/get_deps.py' - - '.github/workflows/build_riscv.yml' - pull_request: - branches: [ master ] - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'tools/get_deps.py' - - '.github/workflows/build_riscv.yml' - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - build-riscv: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - family: - # Alphabetical order - - 'ch32v307' - - 'fomu' - - 'gd32vf103' - steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Set Toolchain URL - run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v10.1.0-1.1/xpack-riscv-none-embed-gcc-10.1.0-1.1-linux-x64.tar.gz - - - name: Cache Toolchain - uses: actions/cache@v4 - id: cache-toolchain - with: - path: ~/cache/ - key: ${{ runner.os }}-21-03-04-${{ env.TOOLCHAIN_URL }} - - - name: Install Toolchain - if: steps.cache-toolchain.outputs.cache-hit != 'true' - run: | - mkdir -p ~/cache/toolchain - wget --progress=dot:mega $TOOLCHAIN_URL -O toolchain.tar.gz - tar -C ~/cache/toolchain -xaf toolchain.tar.gz - - - name: Set Toolchain Path - run: echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin` - - - name: Get Dependencies - run: python3 tools/get_deps.py ${{ matrix.family }} - - - name: Build - run: python3 tools/build_make.py ${{ matrix.family }} diff --git a/.github/workflows/build_win_mac.yml b/.github/workflows/build_win_mac.yml index b33b5b593..35328aa32 100644 --- a/.github/workflows/build_win_mac.yml +++ b/.github/workflows/build_win_mac.yml @@ -48,7 +48,9 @@ jobs: uses: actions/checkout@v4 - name: Get Dependencies - run: python3 tools/get_deps.py stm32f4 + run: | + pip install click + python3 tools/get_deps.py stm32f4 - name: Build - run: python3 tools/build_make.py stm32f4 stm32f411disco + run: python3 tools/build.py -s make stm32f2 diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py new file mode 100644 index 000000000..2a17be6a1 --- /dev/null +++ b/.github/workflows/ci_set_matrix.py @@ -0,0 +1,51 @@ +import json + +# toolchain, url +toolchain_list = { + "aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz", + "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-17.0.1/LLVMEmbeddedToolchainForArm-17.0.1-Linux-x86_64.tar.xz", + "arm-gcc": "", + "msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2", + "riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v10.1.0-1.1/xpack-riscv-none-embed-gcc-10.1.0-1.1-linux-x64.tar.gz", +} + +# family: [supported toolchain] +family_list = { + "broadcom_32bit": ["arm-gcc"], + "broadcom_64bit": ["aarch64-gcc"], + "ch32v307 fomu gd32vf103": ["riscv-gcc"], + "imxrt": ["arm-gcc", "arm-clang"], + "kinetis_k kinetis_kl kinetis_k32l2": ["arm-gcc", "arm-clang"], + "lpc11 lpc13 lpc15": ["arm-gcc"], + "lpc17 lpc18 lpc40 lpc43": ["arm-gcc", "arm-clang"], + "lpc51 lpc54 lpc55": ["arm-gcc", "arm-clang"], + "mcx": ["arm-gcc"], + "mm32": ["arm-gcc"], + "msp430": ["msp430-gcc"], + "msp432e4 tm4c": ["arm-gcc"], + "nrf": ["arm-gcc", "arm-clang"], + "ra": ["arm-gcc"], + "rp2040": ["arm-gcc"], + "samd11 samd21 saml2x": ["arm-gcc", "arm-clang"], + "samd5x_e5x samg": ["arm-gcc", "arm-clang"], + "stm32f0 stm32f1 stm32f2 stm32f3": ["arm-gcc", "arm-clang"], + "stm32f4": ["arm-gcc", "arm-clang"], + "stm32f7": ["arm-gcc", "arm-clang"], + "stm32g0 stm32g4 stm32h5": ["arm-gcc", "arm-clang"], + "stm32h7": ["arm-gcc", "arm-clang"], + "stm32l4 stm32u5 stm32wb": ["arm-gcc", "arm-clang"], + "xmc4000": ["arm-gcc"], +} + + +def set_matrix_json(): + matrix = {} + for toolchain in toolchain_list.keys(): + filtered_families = [family for family, supported_toolchain in family_list.items() if + toolchain in supported_toolchain] + matrix[toolchain] = {"family": filtered_families, "toolchain_url": toolchain_list[toolchain]} + print(json.dumps(matrix)) + + +if __name__ == '__main__': + set_matrix_json() diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index 5dc0f2764..faa0f911c 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -12,6 +12,7 @@ on: - '**.h' jobs: Fuzzing: + if: false runs-on: ubuntu-latest steps: - name: Build Fuzzers @@ -20,12 +21,14 @@ jobs: with: oss-fuzz-project-name: 'tinyusb' language: c++ + - name: Run Fuzzers uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master with: oss-fuzz-project-name: 'tinyusb' language: c++ fuzz-seconds: 600 + - name: Upload Crash uses: actions/upload-artifact@v4 if: failure() && steps.build.outcome == 'success' diff --git a/.github/workflows/codeql-buildscript.sh b/.github/workflows/codeql-buildscript.sh index 35e029922..272b55d22 100644 --- a/.github/workflows/codeql-buildscript.sh +++ b/.github/workflows/codeql-buildscript.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash FAMILY=stm32l4 +pip install click python3 tools/get_deps.py $FAMILY -python3 tools/build_make.py $FAMILY +python3 tools/build.py -s make $FAMILY diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml new file mode 100644 index 000000000..024ab969d --- /dev/null +++ b/.github/workflows/hil_test.yml @@ -0,0 +1,125 @@ +name: Hardware Test + +on: + workflow_dispatch: + push: + paths: + - 'src/**' + - 'examples/**' + - 'lib/**' + - 'hw/**' + - 'test/hil/**' + - 'tools/get_deps.py' + - '.github/actions/**' + - '.github/workflows/hil_test.yml' + pull_request: + branches: [ master ] + paths: + - 'src/**' + - 'examples/**' + - 'lib/**' + - 'hw/**' + - 'test/hil/**' + - 'tools/get_deps.py' + - '.github/actions/**' + - '.github/workflows/hil_test.yml' +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + build: + if: github.repository_owner == 'hathach' + runs-on: ubuntu-latest + outputs: + BOARD_LIST: ${{ steps.parse_hil_json.outputs.BOARD_LIST }} + steps: + - name: Checkout TinyUSB + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install ARM GCC + uses: carlosperate/arm-none-eabi-gcc-action@v1 + with: + release: '12.3.Rel1' + + - name: Parse HIL json + id: parse_hil_json + run: | + sudo apt install -y jq + BOARD_LIST=$(jq -r '.boards[] | "-b " + .name' test/hil/pi4.json | tr '\n' ' ') + echo "BOARD_LIST=$BOARD_LIST" + echo >> $GITHUB_ENV "BOARD_LIST=$BOARD_LIST" + echo >> $GITHUB_OUTPUT "BOARD_LIST=$BOARD_LIST" + + - name: Checkout pico-sdk for rp2040 + uses: actions/checkout@v4 + with: + repository: raspberrypi/pico-sdk + ref: develop + path: pico-sdk + + - name: Get Dependencies + run: | + pip install click + sudo apt install -y ninja-build + python3 tools/get_deps.py $BOARD_LIST + + - name: Build + run: | + python tools/build.py $BOARD_LIST + env: + PICO_SDK_PATH: ${{ github.workspace }}/pico-sdk + + - name: Upload Artifacts for Hardware Testing + uses: actions/upload-artifact@v4 + with: + name: hil_pi4 + path: | + cmake-build/cmake-build-*/*/*/*.elf + cmake-build/cmake-build-*/*/*/*.bin + + # --------------------------------------- + # Hardware in the loop (HIL) + # Current self-hosted instance is running on an RPI4. For attached hardware checkout hil_pi4.json + # --------------------------------------- + hil-pi4: + if: github.repository_owner == 'hathach' + needs: build + runs-on: [self-hosted, rp2040, nrf52840, hardware-in-the-loop] + env: + BOARD_LIST: ${{ needs.build.outputs.BOARD_LIST }} + steps: + - name: Clean workspace + run: | + echo "Cleaning up previous run" + rm -rf "${{ github.workspace }}" + mkdir -p "${{ github.workspace }}" + + # USB bus on rpi4 is not stable, reset it before testing + - name: Reset USB bus + run: | + lsusb + lsusb -t + # reset VIA Labs 2.0 hub + sudo usbreset 001/002 + + - name: Checkout TinyUSB + uses: actions/checkout@v4 + with: + sparse-checkout: test/hil + + - name: Download Artifacts + uses: actions/download-artifact@v4 + with: + name: hil_pi4 + path: cmake-build + + - name: Test on actual hardware + run: | + echo "BOARD_LIST=$BOARD_LIST" + python3 test/hil/hil_test.py $BOARD_LIST pi4.json diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index e36259daa..6b3151702 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -38,6 +38,7 @@ jobs: - name: Build Fuzzer run: | + pip install click export CC=clang export CXX=clang++ fuzz_harness=$(ls -d test/fuzz/device/*/) diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 0e2ca61e4..bb13a0466 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -117,7 +117,7 @@ - + @@ -125,7 +125,11 @@ - + + + + + \ No newline at end of file diff --git a/examples/build_system/cmake/cpu/rv32i-ilp32.cmake b/examples/build_system/cmake/cpu/rv32i-ilp32.cmake new file mode 100644 index 000000000..b4889e6ff --- /dev/null +++ b/examples/build_system/cmake/cpu/rv32i-ilp32.cmake @@ -0,0 +1,19 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -march=rv32i + -mabi=ilp32 + ) + set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "clang") + set(TOOLCHAIN_COMMON_FLAGS + -march=rv32i + -mabi=ilp32 + ) + set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "iar") + message(FATAL_ERROR "IAR not supported") + set(FREERTOS_PORT IAR_RISC_V CACHE INTERNAL "") + +endif () diff --git a/examples/build_system/cmake/cpu/rv32imac-ilp32.cmake b/examples/build_system/cmake/cpu/rv32imac-ilp32.cmake new file mode 100644 index 000000000..dd1bc0af7 --- /dev/null +++ b/examples/build_system/cmake/cpu/rv32imac-ilp32.cmake @@ -0,0 +1,18 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -march=rv32imac + -mabi=ilp32 + ) + set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "clang") + set(TOOLCHAIN_COMMON_FLAGS + -march=rv32imac + -mabi=ilp32 + ) + set(FREERTOS_PORT GCC_RISC_V CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "iar") + message(FATAL_ERROR "IAR not supported") + set(FREERTOS_PORT IAR_RISC_V CACHE INTERNAL "") +endif () diff --git a/examples/build_system/cmake/toolchain/riscv_gcc.cmake b/examples/build_system/cmake/toolchain/riscv_gcc.cmake new file mode 100644 index 000000000..904b27294 --- /dev/null +++ b/examples/build_system/cmake/toolchain/riscv_gcc.cmake @@ -0,0 +1,21 @@ +if (NOT DEFINED CMAKE_C_COMPILER) + set(CMAKE_C_COMPILER "riscv-none-embed-gcc") +endif () + +if (NOT DEFINED CMAKE_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "riscv-none-embed-g++") +endif () + +set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +set(CMAKE_SIZE "riscv-none-embed-size" CACHE FILEPATH "") +set(CMAKE_OBJCOPY "riscv-none-embed-objcopy" CACHE FILEPATH "") +set(CMAKE_OBJDUMP "riscv-none-embed-objdump" CACHE FILEPATH "") + +include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) + +get_property(IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE) +if (IS_IN_TRY_COMPILE) + set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -nostdlib") + set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib") + cmake_print_variables(CMAKE_C_LINK_FLAGS) +endif () diff --git a/examples/build_system/make/cpu/rv32i-ilp32.mk b/examples/build_system/make/cpu/rv32i-ilp32.mk new file mode 100644 index 000000000..a465baf4c --- /dev/null +++ b/examples/build_system/make/cpu/rv32i-ilp32.mk @@ -0,0 +1,13 @@ +ifeq ($(TOOLCHAIN),gcc) + CFLAGS += \ + -march=rv32i \ + -mabi=ilp32 \ + +else ifeq ($(TOOLCHAIN),iar) + #CFLAGS += --cpu cortex-a53 + #ASFLAGS += --cpu cortex-a53 + +endif + +# For freeRTOS port source +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V diff --git a/examples/build_system/make/cpu/rv32imac-ilp32.mk b/examples/build_system/make/cpu/rv32imac-ilp32.mk new file mode 100644 index 000000000..2b6493e48 --- /dev/null +++ b/examples/build_system/make/cpu/rv32imac-ilp32.mk @@ -0,0 +1,13 @@ +ifeq ($(TOOLCHAIN),gcc) + CFLAGS += \ + -march=rv32imac \ + -mabi=ilp32 \ + +else ifeq ($(TOOLCHAIN),iar) + #CFLAGS += --cpu cortex-a53 + #ASFLAGS += --cpu cortex-a53 + +endif + +# For freeRTOS port source +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V diff --git a/examples/build_system/make/toolchain/riscv_gcc.mk b/examples/build_system/make/toolchain/riscv_gcc.mk new file mode 100644 index 000000000..843aff38c --- /dev/null +++ b/examples/build_system/make/toolchain/riscv_gcc.mk @@ -0,0 +1,20 @@ +# makefile for arm gcc toolchain + +# Can be set by family, default to ARM GCC +CROSS_COMPILE ?= riscv-none-embed- + +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +AS = $(CC) -x assembler-with-cpp +LD = $(CC) + +GDB = $(CROSS_COMPILE)gdb +OBJCOPY = $(CROSS_COMPILE)objcopy +SIZE = $(CROSS_COMPILE)size + +CFLAGS += \ + -fsingle-precision-constant \ + +LIBS += -lgcc -lm -lnosys + +include ${TOP}/examples/build_system/make/toolchain/gcc_common.mk diff --git a/examples/device/video_capture/skip.txt b/examples/device/video_capture/skip.txt index db64cc639..5898664a2 100644 --- a/examples/device/video_capture/skip.txt +++ b/examples/device/video_capture/skip.txt @@ -1,4 +1,3 @@ mcu:MSP430x5xx mcu:NUC121 mcu:SAMD11 -family:espressif diff --git a/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/board.cmake b/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/board.cmake new file mode 100644 index 000000000..9f5682042 --- /dev/null +++ b/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/board.cmake @@ -0,0 +1,4 @@ +function(update_board TARGET) +# target_compile_definitions(${TARGET} PUBLIC +# ) +endfunction() diff --git a/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.c b/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.c deleted file mode 100644 index db3551ca7..000000000 --- a/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2022 Greg Davill - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "debug_uart.h" -#include - - -#define UART_RINGBUFFER_SIZE_TX 64 -#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1) - -static char tx_buf[UART_RINGBUFFER_SIZE_TX]; -static unsigned int tx_produce; -static volatile unsigned int tx_consume; - -void USART1_IRQHandler(void) __attribute__((naked)); -void USART1_IRQHandler(void) { - __asm volatile ("call USART1_IRQHandler_impl; mret"); -} - -__attribute__((used)) void USART1_IRQHandler_impl(void) -{ - if(USART_GetITStatus(USART1, USART_IT_TC) != RESET) - { - USART_ClearITPendingBit(USART1, USART_IT_TC); - - if(tx_consume != tx_produce) { - USART_SendData(USART1, tx_buf[tx_consume]); - tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX; - } - } - -} - -void uart_write(char c) -{ - unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX; - - NVIC_DisableIRQ(USART1_IRQn); - if((tx_consume != tx_produce) || (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)) { - tx_buf[tx_produce] = c; - tx_produce = tx_produce_next; - } else { - USART_SendData(USART1, c); - } - NVIC_EnableIRQ(USART1_IRQn); -} - - -void uart_sync(void) -{ - while(tx_consume != tx_produce); -} - - -void usart_printf_init(uint32_t baudrate) -{ - GPIO_InitTypeDef GPIO_InitStructure; - USART_InitTypeDef USART_InitStructure; - - tx_produce = 0; - tx_consume = 0; - - RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); - - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; - GPIO_Init(GPIOA, &GPIO_InitStructure); - - USART_InitStructure.USART_BaudRate = baudrate; - USART_InitStructure.USART_WordLength = USART_WordLength_8b; - USART_InitStructure.USART_StopBits = USART_StopBits_1; - USART_InitStructure.USART_Parity = USART_Parity_No; - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; - USART_InitStructure.USART_Mode = USART_Mode_Tx; - - USART_Init(USART1, &USART_InitStructure); - USART_ITConfig(USART1, USART_IT_TC, ENABLE); - USART_Cmd(USART1, ENABLE); - - NVIC_InitTypeDef NVIC_InitStructure = { 0 }; - NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); -} diff --git a/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.h b/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.h deleted file mode 100644 index a7e070585..000000000 --- a/hw/bsp/ch32v307/boards/ch32v307v_r1_1v0/debug_uart.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2022 Greg Davill - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include - -void uart_write(char c); -void uart_sync(void); -void usart_printf_init(uint32_t baudrate); diff --git a/hw/bsp/ch32v307/debug_uart.c b/hw/bsp/ch32v307/debug_uart.c new file mode 100644 index 000000000..db3551ca7 --- /dev/null +++ b/hw/bsp/ch32v307/debug_uart.c @@ -0,0 +1,110 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022 Greg Davill + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "debug_uart.h" +#include + + +#define UART_RINGBUFFER_SIZE_TX 64 +#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1) + +static char tx_buf[UART_RINGBUFFER_SIZE_TX]; +static unsigned int tx_produce; +static volatile unsigned int tx_consume; + +void USART1_IRQHandler(void) __attribute__((naked)); +void USART1_IRQHandler(void) { + __asm volatile ("call USART1_IRQHandler_impl; mret"); +} + +__attribute__((used)) void USART1_IRQHandler_impl(void) +{ + if(USART_GetITStatus(USART1, USART_IT_TC) != RESET) + { + USART_ClearITPendingBit(USART1, USART_IT_TC); + + if(tx_consume != tx_produce) { + USART_SendData(USART1, tx_buf[tx_consume]); + tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX; + } + } + +} + +void uart_write(char c) +{ + unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX; + + NVIC_DisableIRQ(USART1_IRQn); + if((tx_consume != tx_produce) || (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)) { + tx_buf[tx_produce] = c; + tx_produce = tx_produce_next; + } else { + USART_SendData(USART1, c); + } + NVIC_EnableIRQ(USART1_IRQn); +} + + +void uart_sync(void) +{ + while(tx_consume != tx_produce); +} + + +void usart_printf_init(uint32_t baudrate) +{ + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; + + tx_produce = 0; + tx_consume = 0; + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + USART_InitStructure.USART_BaudRate = baudrate; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Tx; + + USART_Init(USART1, &USART_InitStructure); + USART_ITConfig(USART1, USART_IT_TC, ENABLE); + USART_Cmd(USART1, ENABLE); + + NVIC_InitTypeDef NVIC_InitStructure = { 0 }; + NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); +} diff --git a/hw/bsp/ch32v307/debug_uart.h b/hw/bsp/ch32v307/debug_uart.h new file mode 100644 index 000000000..a7e070585 --- /dev/null +++ b/hw/bsp/ch32v307/debug_uart.h @@ -0,0 +1,31 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022 Greg Davill + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include + +void uart_write(char c); +void uart_sync(void); +void usart_printf_init(uint32_t baudrate); diff --git a/hw/bsp/ch32v307/family.cmake b/hw/bsp/ch32v307/family.cmake new file mode 100644 index 000000000..87a0f2eba --- /dev/null +++ b/hw/bsp/ch32v307/family.cmake @@ -0,0 +1,114 @@ +include_guard() + +set(SDK_DIR ${TOP}/hw/mcu/wch/ch32v307/EVT/EXAM/SRC) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR rv32imac-ilp32 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS CH32V307 CACHE INTERNAL "") +set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") +set(OPENOCD_OPTION2 "-c wlink_reset_resume") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif() + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ch32v307.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + + if (NOT DEFINED STARTUP_FILE_GNU) + set(STARTUP_FILE_GNU ${SDK_DIR}/Startup/startup_ch32v30x_D8C.S) + endif () + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/Core/core_riscv.c + ${SDK_DIR}/Peripheral/src/ch32v30x_gpio.c + ${SDK_DIR}/Peripheral/src/ch32v30x_misc.c + ${SDK_DIR}/Peripheral/src/ch32v30x_rcc.c + ${SDK_DIR}/Peripheral/src/ch32v30x_usart.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/ch32v30x_it.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_ch32v30x.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/Peripheral/inc + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(${BOARD_TARGET} PUBLIC + -msmall-data-limit=8 + -mno-save-restore + -fmessage-length=0 + -fsigned-char + ) + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported for MSP432E4") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/debug_uart.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_CH32V307 ${RTOS}) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/wch/dcd_ch32_usbhs.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_openocd_wch(${TARGET}) +endfunction() diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index 07e57f04c..003b90539 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -6,29 +6,28 @@ CROSS_COMPILE ?= riscv-none-embed- # Submodules CH32V307_SDK = hw/mcu/wch/ch32v307 -DEPS_SUBMODULES += $(CH32V307_SDK) # WCH-SDK paths CH32V307_SDK_SRC = $(CH32V307_SDK)/EVT/EXAM/SRC include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= rv32imac-ilp32 CFLAGS += \ -flto \ - -march=rv32imac \ - -mabi=ilp32 \ -msmall-data-limit=8 \ -mno-save-restore -Os \ -fmessage-length=0 \ -fsigned-char \ -ffunction-sections \ -fdata-sections \ - -nostdlib -nostartfiles \ -DCFG_TUSB_MCU=OPT_MCU_CH32V307 \ -Xlinker --gc-sections \ -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/wch/dcd_ch32_usbhs.c \ @@ -62,5 +61,6 @@ FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V # openocd binaries will be generated in riscv-openocd-wch/src # flash target ROM bootloader +OPENOCD_WCH = /home/${USER}/app/riscv-openocd-wch/src/openocd flash: $(BUILD)/$(PROJECT).elf - openocd -f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -c init -c halt -c "program $<" -c wlink_reset_resume -c exit + $(OPENOCD_WCH) -f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg -c init -c halt -c "program $<" -c wlink_reset_resume -c exit diff --git a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/dependencies.lock b/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/dependencies.lock deleted file mode 100644 index 97840a153..000000000 --- a/hw/bsp/espressif/components/led_strip/examples/led_strip_rmt_ws2812/dependencies.lock +++ /dev/null @@ -1,15 +0,0 @@ -dependencies: - espressif/led_strip: - component_hash: null - source: - path: /home/hathach/code/idf-extra-components/led_strip - type: local - version: 2.5.2 - idf: - component_hash: null - source: - type: idf - version: 5.1.1 -manifest_hash: 47d47762be26168b388cb0e6cbfee6b22c68d630ebf4b27a49c47c4c54191590 -target: esp32s3 -version: 1.0.0 diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index bac1ecb5f..df4f616ef 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -385,6 +385,10 @@ function(family_flash_jlink TARGET) set(JLINKEXE JLinkExe) endif () + if (NOT DEFINED JLINK_IF) + set(JLINK_IF swd) + endif () + file(GENERATE OUTPUT $/${TARGET}.jlink CONTENT "halt @@ -396,7 +400,7 @@ exit" add_custom_target(${TARGET}-jlink DEPENDS ${TARGET} - COMMAND ${JLINKEXE} -device ${JLINK_DEVICE} -if swd -JTAGConf -1,-1 -speed auto -CommandFile $/${TARGET}.jlink + COMMAND ${JLINKEXE} -device ${JLINK_DEVICE} -if ${JLINK_IF} -JTAGConf -1,-1 -speed auto -CommandFile $/${TARGET}.jlink ) endfunction() @@ -420,16 +424,30 @@ function(family_flash_openocd TARGET) set(OPENOCD openocd) endif () - separate_arguments(OPENOCD_OPTION_LIST UNIX_COMMAND ${OPENOCD_OPTION}) + if (NOT DEFINED OPENOCD_OPTION2) + set(OPENOCD_OPTION2 "") + endif () + + separate_arguments(OPTION_LIST UNIX_COMMAND ${OPENOCD_OPTION}) + separate_arguments(OPTION_LIST2 UNIX_COMMAND ${OPENOCD_OPTION2}) # note skip verify since it has issue with rp2040 add_custom_target(${TARGET}-openocd DEPENDS ${TARGET} - COMMAND ${OPENOCD} ${OPENOCD_OPTION_LIST} -c "program $ reset exit" + COMMAND ${OPENOCD} ${OPTION_LIST} -c "program $ reset" ${OPTION_LIST2} -c exit VERBATIM ) endfunction() +# Add flash openocd-wch target +function(family_flash_openocd_wch TARGET) + if (NOT DEFINED OPENOCD) + set(OPENOCD $ENV{HOME}/app/riscv-openocd-wch/src/openocd) + endif () + + family_flash_openocd(${TARGET}) +endfunction() + # Add flash pycod target function(family_flash_pyocd TARGET) if (NOT DEFINED PYOC) diff --git a/hw/bsp/fomu/boards/fomu/board.cmake b/hw/bsp/fomu/boards/fomu/board.cmake new file mode 100644 index 000000000..9f5682042 --- /dev/null +++ b/hw/bsp/fomu/boards/fomu/board.cmake @@ -0,0 +1,4 @@ +function(update_board TARGET) +# target_compile_definitions(${TARGET} PUBLIC +# ) +endfunction() diff --git a/hw/bsp/fomu/family.c b/hw/bsp/fomu/family.c new file mode 100644 index 000000000..ccf2b12f4 --- /dev/null +++ b/hw/bsp/fomu/family.c @@ -0,0 +1,121 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include +#include +#include "csr.h" +#include "irq.h" + +#include "bsp/board_api.h" + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void fomu_error(uint32_t line) +{ + (void)line; + TU_BREAKPOINT(); +} + +volatile uint32_t system_ticks = 0; +static void timer_init(void) +{ + int t; + + timer0_en_write(0); + t = CONFIG_CLOCK_FREQUENCY / 1000; // 1000 kHz tick + timer0_reload_write(t); + timer0_load_write(t); + timer0_en_write(1); + timer0_ev_enable_write(1); + timer0_ev_pending_write(1); + irq_setmask(irq_getmask() | (1 << TIMER0_INTERRUPT)); +} + +void isr(void) +{ + unsigned int irqs; + + irqs = irq_pending() & irq_getmask(); + +#if CFG_TUD_ENABLED + if (irqs & (1 << USB_INTERRUPT)) { + tud_int_handler(0); + } +#endif + if (irqs & (1 << TIMER0_INTERRUPT)) { + system_ticks++; + timer0_ev_pending_write(1); + } +} + +void board_init(void) +{ + irq_setmask(0); + irq_setie(1); + timer_init(); + return; +} + +void board_led_write(bool state) +{ + rgb_ctrl_write(0xff); + rgb_raw_write(state); +} + +uint32_t board_button_read(void) +{ + return 0; +} + +int board_uart_read(uint8_t* buf, int len) +{ + (void) buf; + (void) len; + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + int32_t offset = 0; + uint8_t const* buf8 = (uint8_t const*) buf; + for (offset = 0; offset < len; offset++) + { + if (!(messible_status_read() & CSR_MESSIBLE_STATUS_FULL_OFFSET)) + { + messible_in_write(buf8[offset]); + } + } + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +uint32_t board_millis(void) +{ + return system_ticks; +} +#endif diff --git a/hw/bsp/fomu/family.cmake b/hw/bsp/fomu/family.cmake new file mode 100644 index 000000000..8d5ab144c --- /dev/null +++ b/hw/bsp/fomu/family.cmake @@ -0,0 +1,91 @@ +include_guard() + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR rv32i-ilp32 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS VALENTYUSB_EPTRI CACHE INTERNAL "") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif() + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/fomu.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + + if (NOT DEFINED STARTUP_FILE_GNU) + set(STARTUP_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/crt0-vexriscv.S) + endif () + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/include + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported for MSP432E4") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_VALENTYUSB_EPTRI ${RTOS}) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/valentyusb/eptri/dcd_eptri.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_add_bin_hex(${TARGET}) +endfunction() diff --git a/hw/bsp/fomu/family.mk b/hw/bsp/fomu/family.mk index f8a3c9ebf..d4b6eaea6 100644 --- a/hw/bsp/fomu/family.mk +++ b/hw/bsp/fomu/family.mk @@ -1,14 +1,15 @@ # Toolchain from https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack CROSS_COMPILE = riscv-none-embed- +CPU_CORE ?= rv32i-ilp32 + CFLAGS += \ -flto \ - -march=rv32i \ - -mabi=ilp32 \ - -nostdlib \ -DCFG_TUSB_MCU=OPT_MCU_VALENTYUSB_EPTRI -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + -nostdlib \ + --specs=nosys.specs --specs=nano.specs \ # All source paths should be relative to the top level. LD_FILE = $(FAMILY_PATH)/fomu.ld diff --git a/hw/bsp/fomu/fomu.c b/hw/bsp/fomu/fomu.c deleted file mode 100644 index d155b743d..000000000 --- a/hw/bsp/fomu/fomu.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include -#include -#include "../board_api.h" -#include "csr.h" -#include "irq.h" - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void fomu_error(uint32_t line) -{ - (void)line; - TU_BREAKPOINT(); -} - -volatile uint32_t system_ticks = 0; -static void timer_init(void) -{ - int t; - - timer0_en_write(0); - t = CONFIG_CLOCK_FREQUENCY / 1000; // 1000 kHz tick - timer0_reload_write(t); - timer0_load_write(t); - timer0_en_write(1); - timer0_ev_enable_write(1); - timer0_ev_pending_write(1); - irq_setmask(irq_getmask() | (1 << TIMER0_INTERRUPT)); -} - -void isr(void) -{ - unsigned int irqs; - - irqs = irq_pending() & irq_getmask(); - -#if CFG_TUD_ENABLED - if (irqs & (1 << USB_INTERRUPT)) { - tud_int_handler(0); - } -#endif - if (irqs & (1 << TIMER0_INTERRUPT)) { - system_ticks++; - timer0_ev_pending_write(1); - } -} - -void board_init(void) -{ - irq_setmask(0); - irq_setie(1); - timer_init(); - return; -} - -void board_led_write(bool state) -{ - rgb_ctrl_write(0xff); - rgb_raw_write(state); -} - -uint32_t board_button_read(void) -{ - return 0; -} - -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; - (void) len; - return 0; -} - -int board_uart_write(void const * buf, int len) -{ - int32_t offset = 0; - uint8_t const* buf8 = (uint8_t const*) buf; - for (offset = 0; offset < len; offset++) - { - if (!(messible_status_read() & CSR_MESSIBLE_STATUS_FULL_OFFSET)) - { - messible_in_write(buf8[offset]); - } - } - return len; -} - -#if CFG_TUSB_OS == OPT_OS_NONE -uint32_t board_millis(void) -{ - return system_ticks; -} -#endif diff --git a/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.cmake b/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.cmake new file mode 100644 index 000000000..403ac08cf --- /dev/null +++ b/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.cmake @@ -0,0 +1,13 @@ +set(JLINK_DEVICE gd32vf103cbt6) + +set(SDK_BSP_DIR ${SOC_DIR}/Board/gd32vf103c_longan_nano) +set(LD_FILE_GNU ${SDK_BSP_DIR}/Source/GCC/gcc_gd32vf103xb_flashxip.ld) + +function(update_board TARGET) + target_sources(${TARGET} PUBLIC + ${SDK_BSP_DIR}/Source/gd32vf103c_longan_nano.c + ) + target_include_directories(${TARGET} PUBLIC + ${SDK_BSP_DIR}/Include + ) +endfunction() diff --git a/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.mk b/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.mk index 3b8944452..fc49b7317 100644 --- a/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.mk +++ b/hw/bsp/gd32vf103/boards/sipeed_longan_nano/board.mk @@ -10,4 +10,3 @@ INC += $(TOP)/$(LONGAN_NANO_SDK_BSP)/Include # Longan Nano 128k ROM 32k RAM JLINK_DEVICE = gd32vf103cbt6 -#JLINK_DEVICE = gd32vf103c8t6 # Longan Nano Lite 64k ROM 20k RAM diff --git a/hw/bsp/gd32vf103/family.c b/hw/bsp/gd32vf103/family.c index 27d7e87bb..d4a819fb3 100644 --- a/hw/bsp/gd32vf103/family.c +++ b/hw/bsp/gd32vf103/family.c @@ -24,11 +24,11 @@ * This file is part of the TinyUSB stack. */ -#include "board.h" #include "drv_usb_hw.h" #include "drv_usb_dev.h" -#include "../board_api.h" +#include "bsp/board_api.h" +#include "board.h" //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler diff --git a/hw/bsp/gd32vf103/family.cmake b/hw/bsp/gd32vf103/family.cmake new file mode 100644 index 000000000..5f4a3da8d --- /dev/null +++ b/hw/bsp/gd32vf103/family.cmake @@ -0,0 +1,119 @@ +include_guard() + +set(SDK_DIR ${TOP}/hw/mcu/gd/nuclei-sdk) +set(SOC_DIR ${SDK_DIR}/SoC/gd32vf103) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR rv32imac-ilp32 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS GD32VF103 CACHE INTERNAL "") + +set(JLINK_IF jtag) + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif() + + if (NOT DEFINED LD_FILE_GNU) + message(FATAL_ERROR "LD_FILE_GNU is not defined") + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + + if (NOT DEFINED STARTUP_FILE_GNU) + set(STARTUP_FILE_GNU + ${SOC_DIR}/Common/Source/GCC/startup_gd32vf103.S + ${SOC_DIR}/Common/Source/GCC/intexc_gd32vf103.S + ) + endif () + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_gd32vf103.c + ${SOC_DIR}/Common/Source/Drivers/gd32vf103_rcu.c + ${SOC_DIR}/Common/Source/Drivers/gd32vf103_gpio.c + ${SOC_DIR}/Common/Source/Drivers/Usb/gd32vf103_usb_hw.c + ${SOC_DIR}/Common/Source/Drivers/gd32vf103_usart.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/NMSIS/Core/Include + ${SOC_DIR}/Common/Include + ${SOC_DIR}/Common/Include/Usb + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + DOWNLOAD_MODE=DOWNLOAD_MODE_FLASHXIP + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(${BOARD_TARGET} PUBLIC + -mcmodel=medlow + -mstrict-align + ) + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported for MSP432E4") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${SOC_DIR}/Common/Source/Stubs/sbrk.c + ${SOC_DIR}/Common/Source/Stubs/close.c + ${SOC_DIR}/Common/Source/Stubs/isatty.c + ${SOC_DIR}/Common/Source/Stubs/fstat.c + ${SOC_DIR}/Common/Source/Stubs/lseek.c + ${SOC_DIR}/Common/Source/Stubs/read.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_GD32VF103 ${RTOS}) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/gd32vf103/family.mk b/hw/bsp/gd32vf103/family.mk index 1725559c4..28e48a6b5 100644 --- a/hw/bsp/gd32vf103/family.mk +++ b/hw/bsp/gd32vf103/family.mk @@ -9,7 +9,6 @@ CROSS_COMPILE ?= riscv-none-embed- # Submodules NUCLEI_SDK = hw/mcu/gd/nuclei-sdk -DEPS_SUBMODULES += $(NUCLEI_SDK) # Nuclei-SDK paths GD32VF103_SDK_SOC = $(NUCLEI_SDK)/SoC/gd32vf103 @@ -18,12 +17,9 @@ LIBC_STUBS = $(GD32VF103_SDK_SOC)/Common/Source/Stubs STARTUP_ASM = $(GD32VF103_SDK_SOC)/Common/Source/GCC include $(TOP)/$(BOARD_PATH)/board.mk - -SKIP_NANOLIB = 1 +CPU_CORE ?= rv32imac-ilp32 CFLAGS += \ - -march=rv32imac \ - -mabi=ilp32 \ -mcmodel=medlow \ -mstrict-align \ -nostdlib -nostartfiles \ @@ -35,10 +31,10 @@ CFLAGS += -Wno-error=unused-parameter SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ - $(GD32VF103_SDK_DRIVER)/gd32vf103_rcu.c \ $(GD32VF103_SDK_DRIVER)/gd32vf103_gpio.c \ - $(GD32VF103_SDK_DRIVER)/Usb/gd32vf103_usb_hw.c \ + $(GD32VF103_SDK_DRIVER)/gd32vf103_rcu.c \ $(GD32VF103_SDK_DRIVER)/gd32vf103_usart.c \ + $(GD32VF103_SDK_DRIVER)/Usb/gd32vf103_usb_hw.c \ $(LIBC_STUBS)/sbrk.c \ $(LIBC_STUBS)/close.c \ $(LIBC_STUBS)/isatty.c \ diff --git a/hw/bsp/lpc51/family.cmake b/hw/bsp/lpc51/family.cmake index dd0ef6d1b..b9dd8829e 100644 --- a/hw/bsp/lpc51/family.cmake +++ b/hw/bsp/lpc51/family.cmake @@ -34,7 +34,6 @@ function(add_board_target BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} # driver - ${SDK_DIR}/drivers/common/fsl_common_arm.c ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c ${SDK_DIR}/drivers/flexcomm/fsl_flexcomm.c ${SDK_DIR}/drivers/flexcomm/fsl_usart.c diff --git a/src/device/usbd.c b/src/device/usbd.c index e51aa0fc4..6aeaa699f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -90,16 +90,16 @@ tu_static usbd_device_t _usbd_dev; // Class Driver //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL - #define DRIVER_NAME(_name) .name = _name, + #define DRIVER_NAME(_name) _name #else - #define DRIVER_NAME(_name) + #define DRIVER_NAME(_name) NULL #endif // Built-in class drivers tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_CDC { - DRIVER_NAME("CDC") + .name = DRIVER_NAME("CDC"), .init = cdcd_init, .deinit = cdcd_deinit, .reset = cdcd_reset, @@ -112,7 +112,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_MSC { - DRIVER_NAME("MSC") + .name = DRIVER_NAME("MSC"), .init = mscd_init, .deinit = NULL, .reset = mscd_reset, @@ -125,7 +125,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_HID { - DRIVER_NAME("HID") + .name = DRIVER_NAME("HID"), .init = hidd_init, .deinit = hidd_deinit, .reset = hidd_reset, @@ -138,7 +138,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_AUDIO { - DRIVER_NAME("AUDIO") + .name = DRIVER_NAME("AUDIO"), .init = audiod_init, .deinit = audiod_deinit, .reset = audiod_reset, @@ -151,7 +151,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_VIDEO { - DRIVER_NAME("VIDEO") + .name = DRIVER_NAME("VIDEO"), .init = videod_init, .deinit = videod_deinit, .reset = videod_reset, @@ -164,7 +164,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_MIDI { - DRIVER_NAME("MIDI") + .name = DRIVER_NAME("MIDI"), .init = midid_init, .deinit = midid_deinit, .open = midid_open, @@ -177,7 +177,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_VENDOR { - DRIVER_NAME("VENDOR") + .name = DRIVER_NAME("VENDOR"), .init = vendord_init, .deinit = vendord_deinit, .reset = vendord_reset, @@ -190,7 +190,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_USBTMC { - DRIVER_NAME("TMC") + .name = DRIVER_NAME("TMC"), .init = usbtmcd_init_cb, .deinit = usbtmcd_deinit, .reset = usbtmcd_reset_cb, @@ -203,7 +203,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_DFU_RUNTIME { - DRIVER_NAME("DFU-RUNTIME") + .name = DRIVER_NAME("DFU-RUNTIME"), .init = dfu_rtd_init, .deinit = dfu_rtd_deinit, .reset = dfu_rtd_reset, @@ -216,7 +216,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_DFU { - DRIVER_NAME("DFU") + .name = DRIVER_NAME("DFU"), .init = dfu_moded_init, .deinit = dfu_moded_deinit, .reset = dfu_moded_reset, @@ -229,7 +229,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_ECM_RNDIS || CFG_TUD_NCM { - DRIVER_NAME("NET") + .name = DRIVER_NAME("NET"), .init = netd_init, .deinit = netd_deinit, .reset = netd_reset, @@ -242,7 +242,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { #if CFG_TUD_BTH { - DRIVER_NAME("BTH") + .name = DRIVER_NAME("BTH"), .init = btd_init, .deinit = btd_deinit, .reset = btd_reset, diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 47752f32c..7eb504246 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -23,8 +23,8 @@ * * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_USBD_PVT_H_ -#define _TUSB_USBD_PVT_H_ +#ifndef TUSB_USBD_PVT_H_ +#define TUSB_USBD_PVT_H_ #include "osal/osal.h" #include "common/tusb_fifo.h" @@ -40,10 +40,7 @@ //--------------------------------------------------------------------+ typedef struct { - #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL char const* name; - #endif - void (* init ) (void); bool (* deinit ) (void); void (* reset ) (uint8_t rhport); diff --git a/test/hil/hfp.json b/test/hil/hfp.json new file mode 100644 index 000000000..e79a3cfc9 --- /dev/null +++ b/test/hil/hfp.json @@ -0,0 +1,25 @@ +{ + "boards": [ + { + "name": "stm32l412nucleo", + "uid": "41003B000E504E5457323020", + "flasher": "jlink", + "flasher_sn": "774470029", + "flasher_args": "-device STM32L412KB" + }, + { + "name": "stm32f746disco", + "uid": "210041000C51343237303334", + "flasher": "jlink", + "flasher_sn": "770935966", + "flasher_args": "-device STM32F746NG" + }, + { + "name": "lpcxpresso43s67", + "uid": "08F000044528BAAA8D858F58C50700F5", + "flasher": "jlink", + "flasher_sn": "728973776", + "flasher_args": "-device LPC43S67_M4" + } + ] +} diff --git a/test/hil/hil_hfp.json b/test/hil/hil_hfp.json deleted file mode 100644 index e79a3cfc9..000000000 --- a/test/hil/hil_hfp.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "boards": [ - { - "name": "stm32l412nucleo", - "uid": "41003B000E504E5457323020", - "flasher": "jlink", - "flasher_sn": "774470029", - "flasher_args": "-device STM32L412KB" - }, - { - "name": "stm32f746disco", - "uid": "210041000C51343237303334", - "flasher": "jlink", - "flasher_sn": "770935966", - "flasher_args": "-device STM32F746NG" - }, - { - "name": "lpcxpresso43s67", - "uid": "08F000044528BAAA8D858F58C50700F5", - "flasher": "jlink", - "flasher_sn": "728973776", - "flasher_args": "-device LPC43S67_M4" - } - ] -} diff --git a/test/hil/hil_pi4.json b/test/hil/hil_pi4.json deleted file mode 100644 index 8aff81910..000000000 --- a/test/hil/hil_pi4.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "boards": [ - { - "name": "raspberry_pi_pico", - "uid": "E6614C311B764A37", - "flasher": "openocd", - "flasher_sn": "E6614103E72C1D2F", - "flasher_args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\"" - }, - { - "name": "espressif_s3_devkitm", - "uid": "84F703C084E4", - "tests": [ - "cdc_msc_freertos", "hid_composite_freertos" - ], - "flasher": "esptool", - "flasher_sn": "3ea619acd1cdeb11a0a0b806e93fd3f1", - "flasher_args": "-b 1500000" - }, - { - "name": "feather_nrf52840_express", - "uid": "1F0479CD0F764471", - "flasher": "jlink", - "flasher_sn": "000682804350", - "flasher_args": "-device nrf52840_xxaa" - }, - { - "name": "itsybitsy_m4", - "uid": "D784B28C5338533335202020FF044726", - "flasher": "bossac", - "flashser_vendor": "Adafruit Industries", - "flasher_product": "ItsyBitsy M4 Express", - "flasher_reset_pin": "2", - "flasher_args": "--offset 0x4000" - } - ] -} diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 7f03ce43f..dffb81765 100644 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -33,12 +33,14 @@ import serial import subprocess import json import glob +import platform # for RPI double reset -try: - import gpiozero -except ImportError: - pass +if platform.machine() == 'aarch64': + try: + import gpiozero + except ImportError: + pass ENUM_TIMEOUT = 10 @@ -111,27 +113,39 @@ def read_disk_file(id, fname): # ------------------------------------------------------------- # Flashing firmware # ------------------------------------------------------------- +def run_cmd(cmd): + # print(cmd) + r = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + title = 'command error' + if r.returncode != 0: + # print build output if failed + if os.getenv('CI'): + print(f"::group::{title}") + print(r.stdout.decode("utf-8")) + print(f"::endgroup::") + else: + print(title) + print(r.stdout.decode("utf-8")) + return r + + def flash_jlink(board, firmware): - script = ['halt', 'r', f'loadfile {firmware}', 'r', 'go', 'exit'] + script = ['halt', 'r', f'loadfile {firmware}.elf', 'r', 'go', 'exit'] with open('flash.jlink', 'w') as f: f.writelines(f'{s}\n' for s in script) - ret = subprocess.run( - f'JLinkExe -USB {board["flasher_sn"]} {board["flasher_args"]} -if swd -JTAGConf -1,-1 -speed auto -NoGui 1 -ExitOnError 1 -CommandFile flash.jlink', - shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + ret = run_cmd(f'JLinkExe -USB {board["flasher_sn"]} {board["flasher_args"]} -if swd -JTAGConf -1,-1 -speed auto -NoGui 1 -ExitOnError 1 -CommandFile flash.jlink') os.remove('flash.jlink') return ret def flash_openocd(board, firmware): - ret = subprocess.run( - f'openocd -c "adapter serial {board["flasher_sn"]}" {board["flasher_args"]} -c "program {firmware} reset exit"', - shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + ret = run_cmd(f'openocd -c "adapter serial {board["flasher_sn"]}" {board["flasher_args"]} -c "program {firmware}.elf reset exit"') return ret def flash_esptool(board, firmware): port = get_serial_dev(board["flasher_sn"], None, None, 0) - dir = os.path.dirname(firmware) + dir = os.path.dirname(f'{firmware}.bin') with open(f'{dir}/config.env') as f: IDF_TARGET = json.load(f)['IDF_TARGET'] with open(f'{dir}/flash_args') as f: @@ -154,9 +168,11 @@ def doublereset_with_rpi_gpio(board): time.sleep(0.1) led.on() + def flash_bossac(board, firmware): # double reset to enter bootloader - doublereset_with_rpi_gpio(board) + if platform.machine() == 'aarch64': + doublereset_with_rpi_gpio(board) port = get_serial_dev(board["uid"], board["flashser_vendor"], board["flasher_product"], 0) timeout = ENUM_TIMEOUT @@ -169,8 +185,7 @@ def flash_bossac(board, firmware): assert timeout, 'bossac bootloader is not available' # sleep a bit more for bootloader to be ready time.sleep(0.5) - ret = subprocess.run(f'bossac --port {port} {board["flasher_args"]} -U -i -R -e -w {firmware}', shell=True, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + ret = run_cmd(f'bossac --port {port} {board["flasher_args"]} -U -i -R -e -w {firmware}.bin') return ret # ------------------------------------------------------------- @@ -325,7 +340,8 @@ def main(config_file, board): config_boards = [e for e in config['boards'] if e['name'] in board] for item in config_boards: - print(f'Testing board:{item["name"]}') + name = item['name'] + print(f'Testing board:{name}') flasher = item['flasher'].lower() # default to all tests @@ -344,29 +360,12 @@ def main(config_file, board): test_list.remove(skip) for test in test_list: - fw_list = [ - # cmake: esp32 & samd51 use .bin file - f'cmake-build/cmake-build-{item["name"]}/device/{test}/{test}.elf', - f'cmake-build/cmake-build-{item["name"]}/device/{test}/{test}.bin', - # make - f'examples/device/{test}/_build/{item["name"]}/{test}.elf' - ] - - fw = None - for f in fw_list: - if os.path.isfile(f): - fw = f - break - - if fw is None: - print(f'Cannot find binary file for {test}') - sys.exit(-1) - + fw_name = f'cmake-build/cmake-build-{name}/device/{test}/{test}' print(f' {test} ...', end='') # flash firmware. It may fail randomly, retry a few times for i in range(3): - ret = globals()[f'flash_{flasher}'](item, fw) + ret = globals()[f'flash_{flasher}'](item, fw_name) if ret.returncode == 0: break else: diff --git a/test/hil/pi4.json b/test/hil/pi4.json new file mode 100644 index 000000000..04329bb64 --- /dev/null +++ b/test/hil/pi4.json @@ -0,0 +1,27 @@ +{ + "boards": [ + { + "name": "raspberry_pi_pico", + "uid": "E6614C311B764A37", + "flasher": "openocd", + "flasher_sn": "E6614103E72C1D2F", + "flasher_args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\"" + }, + { + "name": "feather_nrf52840_express", + "uid": "1F0479CD0F764471", + "flasher": "jlink", + "flasher_sn": "000682804350", + "flasher_args": "-device nrf52840_xxaa" + }, + { + "name": "itsybitsy_m4", + "uid": "D784B28C5338533335202020FF044726", + "flasher": "bossac", + "flashser_vendor": "Adafruit Industries", + "flasher_product": "ItsyBitsy M4 Express", + "flasher_reset_pin": "2", + "flasher_args": "--offset 0x4000" + } + ] +} diff --git a/test/hil/pi4_esp32.json b/test/hil/pi4_esp32.json new file mode 100644 index 000000000..c95dd2d4e --- /dev/null +++ b/test/hil/pi4_esp32.json @@ -0,0 +1,14 @@ +{ + "boards": [ + { + "name": "espressif_s3_devkitm", + "uid": "84F703C084E4", + "tests": [ + "cdc_msc_freertos", "hid_composite_freertos" + ], + "flasher": "esptool", + "flasher_sn": "3ea619acd1cdeb11a0a0b806e93fd3f1", + "flasher_args": "-b 1500000" + } + ] +} diff --git a/tools/build.py b/tools/build.py new file mode 100644 index 000000000..884cd56f4 --- /dev/null +++ b/tools/build.py @@ -0,0 +1,177 @@ +import os +import sys +import time +import subprocess +import click +from pathlib import Path +from multiprocessing import Pool + +import build_utils + +SUCCEEDED = "\033[32msucceeded\033[0m" +FAILED = "\033[31mfailed\033[0m" + +build_separator = '-' * 106 + + +def run_cmd(cmd): + #print(cmd) + r = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + title = 'command error' + if r.returncode != 0: + # print build output if failed + if os.getenv('CI'): + print(f"::group::{title}") + print(r.stdout.decode("utf-8")) + print(f"::endgroup::") + else: + print(title) + print(r.stdout.decode("utf-8")) + return r + +def find_family(board): + bsp_dir = Path("hw/bsp") + for family_dir in bsp_dir.iterdir(): + if family_dir.is_dir(): + board_dir = family_dir / 'boards' / board + if board_dir.exists(): + return family_dir.name + return None + + +def get_examples(family): + all_examples = [] + for d in os.scandir("examples"): + if d.is_dir() and 'cmake' not in d.name and 'build_system' not in d.name: + for entry in os.scandir(d.path): + if entry.is_dir() and 'cmake' not in entry.name: + if family != 'espressif' or 'freertos' in entry.name: + all_examples.append(d.name + '/' + entry.name) + + if family == 'espressif': + all_examples.append('device/board_test') + all_examples.append('device/video_capture') + all_examples.sort() + return all_examples + + +def build_board_cmake(board, toolchain): + start_time = time.monotonic() + ret = [0, 0, 0] + + build_dir = f"cmake-build/cmake-build-{board}" + family = find_family(board) + if family == 'espressif': + # for espressif, we have to build example individually + all_examples = get_examples(family) + for example in all_examples: + r = run_cmd(f'cmake examples/{example} -B {build_dir}/{example} -G "Ninja" -DBOARD={board} -DMAX3421_HOST=1') + if r.returncode == 0: + r = run_cmd(f'cmake --build {build_dir}/{example}') + if r.returncode == 0: + ret[0] += 1 + else: + ret[1] += 1 + else: + r = run_cmd(f'cmake examples -B {build_dir} -G "Ninja" -DBOARD={board} -DCMAKE_BUILD_TYPE=MinSizeRel -DTOOLCHAIN={toolchain}') + if r.returncode == 0: + r = run_cmd(f"cmake --build {build_dir}") + if r.returncode == 0: + ret[0] += 1 + else: + ret[1] += 1 + + duration = time.monotonic() - start_time + + if ret[1] == 0: + status = SUCCEEDED + else: + status = FAILED + + flash_size = "-" + sram_size = "-" + example = 'all' + title = build_utils.build_format.format(example, board, status, "{:.2f}s".format(duration), flash_size, sram_size) + print(title) + return ret + + +def build_family(family, toolchain, build_system): + all_boards = [] + for entry in os.scandir(f"hw/bsp/{family}/boards"): + if entry.is_dir() and entry.name != 'pico_sdk': + all_boards.append(entry.name) + all_boards.sort() + + # success, failed, skipped + ret = [0, 0, 0] + if build_system == 'cmake': + for board in all_boards: + if build_board_cmake(board, toolchain): + ret[0] += 1 + else: + ret[1] += 1 + elif build_system == 'make': + all_examples = get_examples(family) + for example in all_examples: + with Pool(processes=os.cpu_count()) as pool: + pool_args = list((map(lambda b, e=example, o=f"TOOLCHAIN={toolchain}": [e, b, o], all_boards))) + r = pool.starmap(build_utils.build_example, pool_args) + # sum all element of same index (column sum) + rsum = list(map(sum, list(zip(*r)))) + ret[0] += rsum[0] + ret[1] += rsum[1] + ret[2] += rsum[2] + return ret + + +@click.command() +@click.argument('families', nargs=-1, required=False) +@click.option('-b', '--board', multiple=True, default=None, help='Boards to build') +@click.option('-t', '--toolchain', default='gcc', help='Toolchain to use, default is gcc') +@click.option('-s', '--build-system', default='cmake', help='Build system to use, default is cmake') +def main(families, board, toolchain, build_system): + if len(families) == 0 and len(board) == 0: + print("Please specify families or board to build") + return 1 + + print(build_separator) + print(build_utils.build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) + total_time = time.monotonic() + total_result = [0, 0, 0] + + # build families: cmake, make + if families is not None: + all_families = [] + if 'all' in families: + for entry in os.scandir("hw/bsp"): + if entry.is_dir() and entry.name != 'espressif' and os.path.isfile(entry.path + "/family.cmake"): + all_families.append(entry.name) + else: + all_families = list(families) + all_families.sort() + + # succeeded, failed + for f in all_families: + fret = build_family(f, toolchain, build_system) + total_result[0] += fret[0] + total_result[1] += fret[1] + total_result[2] += fret[2] + + # build board (only cmake) + if board is not None: + for b in board: + r = build_board_cmake(b, toolchain) + total_result[0] += r[0] + total_result[1] += r[1] + total_result[2] += r[2] + + total_time = time.monotonic() - total_time + print(build_separator) + print(f"Build Summary: {total_result[0]} {SUCCEEDED}, {total_result[1]} {FAILED} and took {total_time:.2f}s") + print(build_separator) + return total_result[1] + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/build_board.py b/tools/build_board.py deleted file mode 100644 index 13376d126..000000000 --- a/tools/build_board.py +++ /dev/null @@ -1,69 +0,0 @@ -import os -import sys -import time -import subprocess -from multiprocessing import Pool - -import build_utils - -SUCCEEDED = "\033[32msucceeded\033[0m" -FAILED = "\033[31mfailed\033[0m" -SKIPPED = "\033[33mskipped\033[0m" - -build_separator = '-' * 106 - - -def filter_with_input(mylist): - if len(sys.argv) > 1: - input_args = list(set(mylist).intersection(sys.argv)) - if len(input_args) > 0: - mylist[:] = input_args - - -if __name__ == '__main__': - # If examples are not specified in arguments, build all - all_examples = [] - for dir1 in os.scandir("examples"): - if dir1.is_dir(): - for entry in os.scandir(dir1.path): - if entry.is_dir(): - all_examples.append(dir1.name + '/' + entry.name) - filter_with_input(all_examples) - all_examples.sort() - - # If boards are not specified in arguments, build all - all_boards = [] - for entry in os.scandir("hw/bsp"): - if entry.is_dir() and os.path.exists(entry.path + "/board.mk"): - all_boards.append(entry.name) - filter_with_input(all_boards) - all_boards.sort() - - # Get dependencies - for b in all_boards: - subprocess.run("make -C examples/device/board_test BOARD={} get-deps".format(b), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - print(build_separator) - print(build_utils.build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) - total_time = time.monotonic() - - # succeeded, failed, skipped - total_result = [0, 0, 0] - for example in all_examples: - print(build_separator) - with Pool(processes=os.cpu_count()) as pool: - pool_args = list((map(lambda b, e=example, o='': [e, b, o], all_boards))) - result = pool.starmap(build_utils.build_example, pool_args) - # sum all element of same index (column sum) - result = list(map(sum, list(zip(*result)))) - - # add to total result - total_result = list(map(lambda x, y: x + y, total_result, result)) - - total_time = time.monotonic() - total_time - print(build_separator) - print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(total_result[0], SUCCEEDED, total_result[1], - FAILED, total_result[2], SKIPPED, total_time)) - print(build_separator) - - sys.exit(total_result[1]) diff --git a/tools/build_cmake.py b/tools/build_cmake.py deleted file mode 100644 index 2eda3f90f..000000000 --- a/tools/build_cmake.py +++ /dev/null @@ -1,105 +0,0 @@ -import os -import sys -import time -import subprocess -import pathlib -from multiprocessing import Pool - -import build_utils - -SUCCEEDED = "\033[32msucceeded\033[0m" -FAILED = "\033[31mfailed\033[0m" -SKIPPED = "\033[33mskipped\033[0m" - -build_separator = '-' * 106 - -def filter_with_input(mylist): - if len(sys.argv) > 1: - input_args = list(set(mylist).intersection(sys.argv)) - if len(input_args) > 0: - mylist[:] = input_args - - -def build_family(family, cmake_option): - all_boards = [] - for entry in os.scandir("hw/bsp/{}/boards".format(family)): - if entry.is_dir() and entry.name != 'pico_sdk': - all_boards.append(entry.name) - all_boards.sort() - - # success, failed, skipped - ret = [0, 0, 0] - for board in all_boards: - start_time = time.monotonic() - - build_dir = f"cmake-build/cmake-build-{board}" - - # Generate build - r = subprocess.run(f"cmake examples -B {build_dir} -G \"Ninja\" -DFAMILY={family} -DBOARD" - f"={board} -DCMAKE_BUILD_TYPE=MinSizeRel {cmake_option}", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - # Build - if r.returncode == 0: - r = subprocess.run(f"cmake --build {build_dir}", shell=True, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - - duration = time.monotonic() - start_time - - if r.returncode == 0: - status = SUCCEEDED - ret[0] += 1 - else: - status = FAILED - ret[1] += 1 - - flash_size = "-" - sram_size = "-" - example = 'all' - title = build_utils.build_format.format(example, board, status, "{:.2f}s".format(duration), flash_size, sram_size) - - if os.getenv('CI'): - # always print build output if in CI - print(f"::group::{title}") - print(r.stdout.decode("utf-8")) - print(f"::endgroup::") - else: - # print build output if failed - print(title) - if r.returncode != 0: - print(r.stdout.decode("utf-8")) - - return ret - - -if __name__ == '__main__': - cmake_options = '' - for a in sys.argv[1:]: - if a.startswith('-'): - cmake_options += ' ' + a - - # If family are not specified in arguments, build all supported - all_families = [] - for entry in os.scandir("hw/bsp"): - if entry.is_dir() and entry.name != 'espressif' and os.path.isfile(entry.path + "/family.cmake"): - all_families.append(entry.name) - filter_with_input(all_families) - all_families.sort() - - print(build_separator) - print(build_utils.build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) - total_time = time.monotonic() - - # succeeded, failed, skipped - total_result = [0, 0, 0] - for family in all_families: - fret = build_family(family, cmake_options) - if len(fret) == len(total_result): - total_result = [total_result[i] + fret[i] for i in range(len(fret))] - - total_time = time.monotonic() - total_time - print(build_separator) - print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(total_result[0], SUCCEEDED, total_result[1], - FAILED, total_result[2], SKIPPED, total_time)) - print(build_separator) - - sys.exit(total_result[1]) diff --git a/tools/build_make.py b/tools/build_make.py deleted file mode 100644 index 240fc8d64..000000000 --- a/tools/build_make.py +++ /dev/null @@ -1,80 +0,0 @@ -import os -import sys -import time -from multiprocessing import Pool - -import build_utils - -SUCCEEDED = "\033[32msucceeded\033[0m" -FAILED = "\033[31mfailed\033[0m" -SKIPPED = "\033[33mskipped\033[0m" - -build_separator = '-' * 106 - - -def filter_with_input(mylist): - if len(sys.argv) > 1: - input_args = list(set(mylist).intersection(sys.argv)) - if len(input_args) > 0: - mylist[:] = input_args - - -def build_family(example, family, make_option): - all_boards = [] - for entry in os.scandir("hw/bsp/{}/boards".format(family)): - if entry.is_dir() and entry.name != 'pico_sdk': - all_boards.append(entry.name) - filter_with_input(all_boards) - all_boards.sort() - - with Pool(processes=os.cpu_count()) as pool: - pool_args = list((map(lambda b, e=example, o=make_option: [e, b, o], all_boards))) - result = pool.starmap(build_utils.build_example, pool_args) - # sum all element of same index (column sum) - return list(map(sum, list(zip(*result)))) - - -if __name__ == '__main__': - make_option = '' - for a in sys.argv: - if 'TOOLCHAIN=' in sys.argv: - make_option += ' ' + a - - # If examples are not specified in arguments, build all - all_examples = [] - for d in os.scandir("examples"): - if d.is_dir() and 'cmake' not in d.name and 'build_system' not in d.name: - for entry in os.scandir(d.path): - if entry.is_dir() and 'cmake' not in entry.name: - all_examples.append(d.name + '/' + entry.name) - filter_with_input(all_examples) - all_examples.sort() - - # If family are not specified in arguments, build all - all_families = [] - for entry in os.scandir("hw/bsp"): - if entry.is_dir() and os.path.isdir(entry.path + "/boards") and entry.name != 'espressif': - all_families.append(entry.name) - filter_with_input(all_families) - all_families.sort() - - print(build_separator) - print(build_utils.build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) - total_time = time.monotonic() - - # succeeded, failed, skipped - total_result = [0, 0, 0] - for example in all_examples: - print(build_separator) - for family in all_families: - fret = build_family(example, family, make_option) - if len(fret) == len(total_result): - total_result = [total_result[i] + fret[i] for i in range(len(fret))] - - total_time = time.monotonic() - total_time - print(build_separator) - print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(total_result[0], SUCCEEDED, total_result[1], - FAILED, total_result[2], SKIPPED, total_time)) - print(build_separator) - - sys.exit(total_result[1]) diff --git a/tools/get_deps.py b/tools/get_deps.py index cdb5dafe1..bca38fc80 100644 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -1,3 +1,4 @@ +import click import sys import subprocess from pathlib import Path @@ -227,27 +228,46 @@ def get_a_dep(d): return 0 -# Arguments can be -# - family name -# - specific deps path -# - all -if __name__ == "__main__": +def find_family(board): + bsp_dir = Path(TOP / "hw/bsp") + for family_dir in bsp_dir.iterdir(): + if family_dir.is_dir(): + board_dir = family_dir / 'boards' / board + if board_dir.exists(): + return family_dir.name + return None + + +@click.command() +@click.argument('family', nargs=-1, required=False) +@click.option('-b', '--board', multiple=True, default=None, help='Boards to fetch') +def main(family, board): + if len(family) == 0 and len(board) == 0: + print("Please specify family or board to fetch") + return + status = 0 deps = list(deps_mandatory.keys()) - # get all if 'all' is argument - if len(sys.argv) == 2 and sys.argv[1] == 'all': + + if 'all' in family: deps += deps_optional.keys() else: - for arg in sys.argv[1:]: - if arg in deps_all.keys(): - # if arg is a dep, add it - deps.append(arg) - else: - # arg is a family name, add all deps of that family - for d in deps_optional: - if arg in deps_optional[d][2]: - deps.append(d) + family = list(family) + if board is not None: + for b in board: + f = find_family(b) + if f is not None: + family.append(f) + + for f in family: + for d in deps_optional: + if f in deps_optional[d][2]: + deps.append(d) with Pool() as pool: status = sum(pool.map(get_a_dep, deps)) - sys.exit(status) + return status + + +if __name__ == "__main__": + sys.exit(main()) -- cgit v1.3.1 From 3e2ea7750681b27238043c7158ff5508f01914a3 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Fri, 10 May 2024 18:55:43 +0700 Subject: More ci tweak (#2636) * change concurrency group to ${{ github.workflow }}-${{ github.ref }} * use argparse for build.py hil_test.py, remove the need to install click * move ci win/mac to build_cmake.yml * rename build_family.yml to build_util.yml * build_util.yml support esp32 * integrate build-espressif into build.yml * build.py support make with --board option * add get_deps action * update hil test to reuse action --- .github/actions/get_deps/action.yml | 29 +++++++ .github/actions/prepare_build/action.yml | 30 ------- .github/actions/setup_toolchain/action.yml | 18 ++++- .github/workflows/build_cmake.yml | 46 +++++++++-- .github/workflows/build_esp.yml | 109 ------------------------- .github/workflows/build_family.yml | 64 --------------- .github/workflows/build_iar.yml | 2 +- .github/workflows/build_renesas.yml | 3 +- .github/workflows/build_util.yml | 59 ++++++++++++++ .github/workflows/build_win_mac.yml | 56 ------------- .github/workflows/ci_set_matrix.py | 2 +- .github/workflows/hil_test.yml | 121 ++++++++++++++++++++-------- .github/workflows/pre-commit.yml | 3 +- examples/device/net_lwip_webserver/skip.txt | 4 +- examples/device/video_capture_2ch/skip.txt | 2 + examples/host/cdc_msc_hid_freertos/only.txt | 1 - hw/bsp/lpc17/family.mk | 2 +- hw/bsp/lpc40/family.mk | 2 + src/class/net/ncm_device.c | 16 ++-- test/hil/hil_test.py | 19 +++-- test/hil/pi4.json | 10 +++ test/hil/pi4_esp32.json | 14 ---- tools/build.py | 46 +++++++---- tools/build_esp32.py | 106 ------------------------ tools/get_deps.py | 11 ++- 25 files changed, 314 insertions(+), 461 deletions(-) create mode 100644 .github/actions/get_deps/action.yml delete mode 100644 .github/actions/prepare_build/action.yml delete mode 100644 .github/workflows/build_esp.yml delete mode 100644 .github/workflows/build_family.yml create mode 100644 .github/workflows/build_util.yml delete mode 100644 .github/workflows/build_win_mac.yml delete mode 100644 test/hil/pi4_esp32.json delete mode 100644 tools/build_esp32.py (limited to 'examples') diff --git a/.github/actions/get_deps/action.yml b/.github/actions/get_deps/action.yml new file mode 100644 index 000000000..38b44a70e --- /dev/null +++ b/.github/actions/get_deps/action.yml @@ -0,0 +1,29 @@ +name: Get dependencies + +inputs: + arg: + required: true + type: string + +runs: + using: "composite" + steps: + - name: Checkout pico-sdk for rp2040 + if: contains(inputs.arg, 'rp2040') || contains(inputs.arg, 'raspberry_pi_pico') + uses: actions/checkout@v4 + with: + repository: raspberrypi/pico-sdk + ref: develop + path: pico-sdk + + - name: Linux dependencies + if: runner.os == 'Linux' + run: | + sudo apt install -y ninja-build + shell: bash + + - name: Get Dependencies + run: | + python3 tools/get_deps.py ${{ inputs.arg }} + echo "PICO_SDK_PATH=${{ github.workspace }}/pico-sdk" >> $GITHUB_ENV + shell: bash diff --git a/.github/actions/prepare_build/action.yml b/.github/actions/prepare_build/action.yml deleted file mode 100644 index 5f2c544c1..000000000 --- a/.github/actions/prepare_build/action.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Prepare to build - -inputs: - family: - required: true - type: string - -runs: - using: "composite" - steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - - name: Checkout pico-sdk for rp2040 - if: contains(inputs.family, 'rp2040') - uses: actions/checkout@v4 - with: - repository: raspberrypi/pico-sdk - ref: develop - path: pico-sdk - - - name: Get Dependencies - run: | - sudo apt install -y ninja-build - pip install click - python3 tools/get_deps.py ${{ inputs.family }} - echo >> $GITHUB_ENV "PICO_SDK_PATH=$GITHUB_WORKSPACE/pico-sdk" - shell: bash diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml index b59ece116..e6c79e7dd 100644 --- a/.github/actions/setup_toolchain/action.yml +++ b/.github/actions/setup_toolchain/action.yml @@ -8,6 +8,11 @@ inputs: required: false type: string +outputs: + build_option: + description: 'Build option for the toolchain e.g --toolchain clang' + value: ${{ steps.set-toolchain-option.outputs.build_option }} + runs: using: "composite" steps: @@ -19,7 +24,7 @@ runs: - name: Pull ESP-IDF docker if: inputs.toolchain == 'esp-idf' - run: docker pull espressif/idf:latest + run: docker pull espressif/idf:${{ inputs.toolchain_url }} shell: bash - name: Download Toolchain @@ -29,3 +34,14 @@ runs: uses: ./.github/actions/setup_toolchain/download with: toolchain_url: ${{ inputs.toolchain_url }} + + - name: Set toolchain option + id: set-toolchain-option + run: | + BUILD_OPTION="" + if [[ "${{ inputs.toolchain }}" == *"clang"* ]]; then + BUILD_OPTION="--toolchain clang" + fi + echo "build_option=$BUILD_OPTION" + echo "build_option=$BUILD_OPTION" >> $GITHUB_OUTPUT + shell: bash diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index b62a0e9bd..4723cf8d9 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -12,6 +12,7 @@ on: - 'tools/build.py' - '.github/actions/**' - '.github/workflows/build_cmake.yml' + - '.github/workflows/build_util.yml' - '.github/workflows/ci_set_matrix.py' pull_request: branches: [ master ] @@ -24,9 +25,10 @@ on: - 'tools/build.py' - '.github/actions/**' - '.github/workflows/build_cmake.yml' + - '.github/workflows/build_util.yml' - '.github/workflows/ci_set_matrix.py' concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: @@ -55,7 +57,7 @@ jobs: # --------------------------------------- cmake: needs: set-matrix - uses: ./.github/workflows/build_family.yml + uses: ./.github/workflows/build_util.yml strategy: fail-fast: false matrix: @@ -69,14 +71,14 @@ jobs: build-system: 'cmake' toolchain: ${{ matrix.toolchain }} toolchain_url: ${{ fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].toolchain_url }} - build-family: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].family) }} + build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].family) }} # --------------------------------------- # Build Make # --------------------------------------- make: needs: set-matrix - uses: ./.github/workflows/build_family.yml + uses: ./.github/workflows/build_util.yml strategy: fail-fast: false matrix: @@ -90,4 +92,38 @@ jobs: build-system: 'make' toolchain: ${{ matrix.toolchain }} toolchain_url: ${{ fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].toolchain_url }} - build-family: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].family) }} + build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain].family) }} + + # --------------------------------------- + # Build Make on Windows/MacOS + # --------------------------------------- + make-os: + uses: ./.github/workflows/build_util.yml + strategy: + fail-fast: false + matrix: + os: [windows-latest, macos-latest] + with: + os: ${{ matrix.os }} + build-system: 'make' + toolchain: 'arm-gcc' + build-args: '["-bstm32f411disco"]' + + # --------------------------------------- + # Build Espressif + # --------------------------------------- + espressif: + uses: ./.github/workflows/build_util.yml + strategy: + fail-fast: false + matrix: + board: + # ESP32-S2 + - 'espressif_kaluga_1' + # ESP32-S3 skip since devkitm is also compiled in hil-test workflow + #- 'espressif_s3_devkitm' + with: + build-system: 'cmake' + toolchain: 'esp-idf' + toolchain_url: 'v5.1.1' + build-args: '["-b${{ matrix.board }}"]' diff --git a/.github/workflows/build_esp.yml b/.github/workflows/build_esp.yml deleted file mode 100644 index 66fa8548e..000000000 --- a/.github/workflows/build_esp.yml +++ /dev/null @@ -1,109 +0,0 @@ -name: Build ESP - -on: - workflow_dispatch: - push: - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'test/hil/**' - - '.github/workflows/build_esp.yml' - pull_request: - branches: [ master ] - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'test/hil/**' - - '.github/workflows/build_esp.yml' - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - build-esp: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - board: - # ESP32-S2 - - 'espressif_kaluga_1' - # ESP32-S3 - - 'espressif_s3_devkitm' - steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Setup Toolchain - uses: ./.github/actions/setup_toolchain - with: - toolchain: 'esp-idf' - - - name: Build - run: docker run --rm -v $PWD:/project -w /project espressif/idf:v5.1.1 python3 tools/build.py -b ${{ matrix.board }} - - - name: Upload Artifacts for Hardware Testing - if: matrix.board == 'espressif_s3_devkitm' && github.repository_owner == 'hathach' - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.board }} - path: | - cmake-build/cmake-build-${{ matrix.board }}/*/*/bootloader/bootloader.bin - cmake-build/cmake-build-${{ matrix.board }}/*/*/*.bin - cmake-build/cmake-build-${{ matrix.board }}/*/*/partition_table/partition-table.bin - cmake-build/cmake-build-${{ matrix.board }}/*/*/config.env - cmake-build/cmake-build-${{ matrix.board }}/*/*/flash_args - - # --------------------------------------- - # Hardware in the loop (HIL) - # Current self-hosted instance is running on an RPI4. For attached hardware checkout hil_pi4.json - # --------------------------------------- - hil-test: - # run only with hathach's commit due to limited resource on RPI4 - if: github.repository_owner == 'hathach' - needs: build-esp - runs-on: [self-hosted, esp32s3, hardware-in-the-loop] - strategy: - fail-fast: false - matrix: - board: - - 'espressif_s3_devkitm' - steps: - - name: Clean workspace - run: | - echo "Cleaning up previous run" - rm -rf "${{ github.workspace }}" - mkdir -p "${{ github.workspace }}" - - # USB bus on rpi4 is not stable, reset it before testing - - name: Reset USB bus - run: | - lsusb - lsusb -t - # reset VIA Labs 2.0 hub - sudo usbreset 001/002 - - - name: Checkout test/hil - uses: actions/checkout@v4 - with: - sparse-checkout: test/hil - - - name: Download Artifacts - uses: actions/download-artifact@v4 - with: - name: ${{ matrix.board }} - path: cmake-build/cmake-build-${{ matrix.board }} - - - name: Test on actual hardware - run: | - python3 test/hil/hil_test.py --board ${{ matrix.board }} pi4_esp32.json diff --git a/.github/workflows/build_family.yml b/.github/workflows/build_family.yml deleted file mode 100644 index 2e89267a3..000000000 --- a/.github/workflows/build_family.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: Build family - -on: - workflow_call: - inputs: - build-system: - required: true - type: string - toolchain: - required: true - type: string - toolchain_url: - required: true - type: string - build-family: - required: true - type: string - -jobs: - family: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - family: ${{ fromJSON(inputs.build-family) }} - steps: - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - - name: Setup Toolchain - uses: ./.github/actions/setup_toolchain - with: - toolchain: ${{ inputs.toolchain }} - toolchain_url: ${{ inputs.toolchain_url }} - - - name: Checkout pico-sdk for rp2040 - if: contains(matrix.family, 'rp2040') - uses: actions/checkout@v4 - with: - repository: raspberrypi/pico-sdk - ref: develop - path: pico-sdk - - - name: Get Dependencies - run: | - sudo apt install -y ninja-build - pip install click - python3 tools/get_deps.py ${{ matrix.family }} - - - name: Build - run: | - OPTION="" - if [[ "${{ inputs.toolchain }}" == *"clang"* ]]; then - OPTION="--toolchain clang" - fi - echo "OPTION=$OPTION" - python tools/build.py -s ${{ inputs.build-system }} $OPTION ${{ matrix.family }} - env: - PICO_SDK_PATH: ${{ github.workspace }}/pico-sdk diff --git a/.github/workflows/build_iar.yml b/.github/workflows/build_iar.yml index c4a7f96b7..34dbda192 100644 --- a/.github/workflows/build_iar.yml +++ b/.github/workflows/build_iar.yml @@ -23,7 +23,7 @@ on: - '.github/workflows/build_iar.yml' concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: diff --git a/.github/workflows/build_renesas.yml b/.github/workflows/build_renesas.yml index 8c83bdbbf..1be49344f 100644 --- a/.github/workflows/build_renesas.yml +++ b/.github/workflows/build_renesas.yml @@ -21,7 +21,7 @@ on: - '.github/workflows/build_renesas.yml' concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: @@ -65,7 +65,6 @@ jobs: - name: Get Dependencies run: | - pip install click python3 tools/get_deps.py ${{ matrix.family }} - name: Build diff --git a/.github/workflows/build_util.yml b/.github/workflows/build_util.yml new file mode 100644 index 000000000..f8ad1900c --- /dev/null +++ b/.github/workflows/build_util.yml @@ -0,0 +1,59 @@ +name: Reusable build util + +on: + workflow_call: + inputs: + build-system: + required: true + type: string + toolchain: + required: true + type: string + toolchain_url: + required: false + type: string + build-args: + required: true + type: string + os: + required: false + type: string + default: 'ubuntu-latest' + +jobs: + family: + runs-on: ${{ inputs.os }} + strategy: + fail-fast: false + matrix: + arg: ${{ fromJSON(inputs.build-args) }} + steps: + - name: Checkout TinyUSB + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Setup Toolchain + id: setup-toolchain + uses: ./.github/actions/setup_toolchain + with: + toolchain: ${{ inputs.toolchain }} + toolchain_url: ${{ inputs.toolchain_url }} + + - name: Get Dependencies + uses: ./.github/actions/get_deps + with: + arg: ${{ matrix.arg }} + + - name: Build + if: inputs.toolchain != 'esp-idf' + run: | + python tools/build.py -s ${{ inputs.build-system }} ${{ steps.setup-toolchain.outputs.build_option }} ${{ matrix.arg }} + + - name: Build using ESP-IDF docker + if: inputs.toolchain == 'esp-idf' + run: | + docker run --rm -v $PWD:/project -w /project espressif/idf:${{ inputs.toolchain_url }} python3 tools/build.py ${{ matrix.arg }} diff --git a/.github/workflows/build_win_mac.yml b/.github/workflows/build_win_mac.yml deleted file mode 100644 index 35328aa32..000000000 --- a/.github/workflows/build_win_mac.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Build Windows/MacOS - -on: - workflow_dispatch: - push: - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - '.github/workflows/build_win_mac.yml' - pull_request: - branches: [ master ] - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - '.github/workflows/build_win_mac.yml' - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - # --------------------------------------- - # Build ARM family - # --------------------------------------- - build-arm: - strategy: - fail-fast: false - matrix: - os: [windows-latest, macos-latest] - runs-on: ${{ matrix.os }} - - steps: - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - - name: Install ARM GCC - uses: carlosperate/arm-none-eabi-gcc-action@v1 - with: - release: '10.3-2021.10' - - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Get Dependencies - run: | - pip install click - python3 tools/get_deps.py stm32f4 - - - name: Build - run: python3 tools/build.py -s make stm32f2 diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index 2a17be6a1..ea758d917 100644 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -16,7 +16,7 @@ family_list = { "ch32v307 fomu gd32vf103": ["riscv-gcc"], "imxrt": ["arm-gcc", "arm-clang"], "kinetis_k kinetis_kl kinetis_k32l2": ["arm-gcc", "arm-clang"], - "lpc11 lpc13 lpc15": ["arm-gcc"], + "lpc11 lpc13 lpc15": ["arm-gcc", "arm-clang"], "lpc17 lpc18 lpc40 lpc43": ["arm-gcc", "arm-clang"], "lpc51 lpc54 lpc55": ["arm-gcc", "arm-clang"], "mcx": ["arm-gcc"], diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml index 024ab969d..796ff32dc 100644 --- a/.github/workflows/hil_test.yml +++ b/.github/workflows/hil_test.yml @@ -24,15 +24,18 @@ on: - '.github/actions/**' - '.github/workflows/hil_test.yml' concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: + # --------------------------------------- + # Build Non Espressif + # --------------------------------------- build: if: github.repository_owner == 'hathach' runs-on: ubuntu-latest outputs: - BOARD_LIST: ${{ steps.parse_hil_json.outputs.BOARD_LIST }} + BOARDS_LIST: ${{ steps.parse_hil_json.outputs.BOARDS_LIST }} steps: - name: Checkout TinyUSB uses: actions/checkout@v4 @@ -42,38 +45,29 @@ jobs: with: python-version: '3.x' - - name: Install ARM GCC - uses: carlosperate/arm-none-eabi-gcc-action@v1 - with: - release: '12.3.Rel1' - - name: Parse HIL json id: parse_hil_json run: | sudo apt install -y jq - BOARD_LIST=$(jq -r '.boards[] | "-b " + .name' test/hil/pi4.json | tr '\n' ' ') - echo "BOARD_LIST=$BOARD_LIST" - echo >> $GITHUB_ENV "BOARD_LIST=$BOARD_LIST" - echo >> $GITHUB_OUTPUT "BOARD_LIST=$BOARD_LIST" - - name: Checkout pico-sdk for rp2040 - uses: actions/checkout@v4 + # Non-Espresif boards + BOARDS_LIST=$(jq -r '.boards[] | select(.flasher != "esptool") | "-b " + .name' test/hil/pi4.json | tr '\n' ' ') + echo "BOARDS_LIST=$BOARDS_LIST" + echo "BOARDS_LIST=$BOARDS_LIST" >> $GITHUB_ENV + echo "BOARDS_LIST=$BOARDS_LIST" >> $GITHUB_OUTPUT + + - name: Setup ARM Toolchain + uses: ./.github/actions/setup_toolchain with: - repository: raspberrypi/pico-sdk - ref: develop - path: pico-sdk + toolchain: 'arm-gcc' - name: Get Dependencies - run: | - pip install click - sudo apt install -y ninja-build - python3 tools/get_deps.py $BOARD_LIST + uses: ./.github/actions/get_deps + with: + arg: ${{ env.BOARDS_LIST }} - name: Build - run: | - python tools/build.py $BOARD_LIST - env: - PICO_SDK_PATH: ${{ github.workspace }}/pico-sdk + run: python tools/build.py $BOARDS_LIST - name: Upload Artifacts for Hardware Testing uses: actions/upload-artifact@v4 @@ -83,16 +77,71 @@ jobs: cmake-build/cmake-build-*/*/*/*.elf cmake-build/cmake-build-*/*/*/*.bin + # --------------------------------------- + # Build Espressif + # --------------------------------------- + build-esp: + runs-on: ubuntu-latest + outputs: + BOARDS_LIST: ${{ steps.parse_hil_json.outputs.BOARDS_LIST }} + steps: + - name: Checkout TinyUSB + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Parse HIL json + id: parse_hil_json + run: | + sudo apt install -y jq + # Espressif boards + BOARDS_LIST=$(jq -r '.boards[] | select(.flasher == "esptool") | "-b " + .name' test/hil/pi4.json | tr '\n' ' ') + echo "BOARDS_LIST=$BOARDS_LIST" + echo "BOARDS_LIST=$BOARDS_LIST" >> $GITHUB_ENV + echo "BOARDS_LIST=$BOARDS_LIST" >> $GITHUB_OUTPUT + + - name: Setup ESP-IDF + if: env.BOARDS_LIST != '' + uses: ./.github/actions/setup_toolchain + with: + toolchain: 'esp-idf' + toolchain_url: 'v5.1.1' + + - name: Get Dependencies + uses: ./.github/actions/get_deps + with: + arg: ${{ env.BOARDS_LIST }} + + - name: Build Espressif + if: env.BOARDS_LIST != '' + run: docker run --rm -v $PWD:/project -w /project espressif/idf:v5.1.1 python3 tools/build.py $BOARDS_LIST + + - name: Upload Artifacts for Hardware Testing + uses: actions/upload-artifact@v4 + with: + name: hil_pi4_esp + path: | + cmake-build/cmake-build-*/*/*/*.bin + cmake-build/cmake-build-*/*/*/bootloader/bootloader.bin + cmake-build/cmake-build-*/*/*/partition_table/partition-table.bin + cmake-build/cmake-build-*/*/*/config.env + cmake-build/cmake-build-*/*/*/flash_args + # --------------------------------------- # Hardware in the loop (HIL) - # Current self-hosted instance is running on an RPI4. For attached hardware checkout hil_pi4.json + # Current self-hosted instance is running on an RPI4. For attached hardware checkout test/hil/pi4.json # --------------------------------------- hil-pi4: if: github.repository_owner == 'hathach' - needs: build - runs-on: [self-hosted, rp2040, nrf52840, hardware-in-the-loop] + needs: + - build + - build-esp + runs-on: [self-hosted, rp2040, nrf52840, esp32s3, hardware-in-the-loop] env: - BOARD_LIST: ${{ needs.build.outputs.BOARD_LIST }} + BOARDS_LIST: "${{ needs.build.outputs.BOARDS_LIST }} ${{ needs.build-esp.outputs.BOARDS_LIST }}" steps: - name: Clean workspace run: | @@ -103,8 +152,7 @@ jobs: # USB bus on rpi4 is not stable, reset it before testing - name: Reset USB bus run: | - lsusb - lsusb -t + # lsusb -t # reset VIA Labs 2.0 hub sudo usbreset 001/002 @@ -119,7 +167,16 @@ jobs: name: hil_pi4 path: cmake-build + - name: Download Artifacts + uses: actions/download-artifact@v4 + with: + name: hil_pi4_esp + path: cmake-build + - name: Test on actual hardware run: | - echo "BOARD_LIST=$BOARD_LIST" - python3 test/hil/hil_test.py $BOARD_LIST pi4.json + echo "BOARDS_LIST=$BOARDS_LIST" + echo "::group::{cmake-build contents}" + tree cmake-build + echo "::endgroup::" + python3 test/hil/hil_test.py $BOARDS_LIST pi4.json diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 6b3151702..d1ffe6ca1 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -7,7 +7,7 @@ on: branches: [ master ] concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: @@ -38,7 +38,6 @@ jobs: - name: Build Fuzzer run: | - pip install click export CC=clang export CXX=clang++ fuzz_harness=$(ls -d test/fuzz/device/*/) diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index bb3ff7885..43cdab71a 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -9,6 +9,8 @@ mcu:STM32F0 mcu:KINETIS_KL family:broadcom_64bit family:broadcom_32bit +family:espressif board:curiosity_nano board:frdm_kl25z -family:espressif +# lpc55 has weird error 'ncm_interface' causes a section type conflict with 'ntb_parameters' +family:lpc55 diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt index 15c176a2a..86697899b 100644 --- a/examples/device/video_capture_2ch/skip.txt +++ b/examples/device/video_capture_2ch/skip.txt @@ -12,3 +12,5 @@ board:lpcxpresso11u68 board:stm32f303disco board:stm32l412nucleo board:ek_tm4c123gxl +board:uno_r4 +board:ra4m1_ek diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index 81d993ffa..1e0e60075 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -8,5 +8,4 @@ mcu:MIMXRT10XX mcu:MIMXRT11XX mcu:MSP432E4 mcu:RX65X -mcu:RAXXX mcu:MAX3421 diff --git a/hw/bsp/lpc17/family.mk b/hw/bsp/lpc17/family.mk index 84ed95648..d719a47b7 100644 --- a/hw/bsp/lpc17/family.mk +++ b/hw/bsp/lpc17/family.mk @@ -22,8 +22,8 @@ LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/nxp/lpc17_40/dcd_lpc17_40.c \ - src/portable/ohci/ohci.c \ src/portable/nxp/lpc17_40/hcd_lpc17_40.c \ + src/portable/ohci/ohci.c \ $(MCU_DIR)/../gcc/cr_startup_lpc175x_6x.c \ $(MCU_DIR)/src/chip_17xx_40xx.c \ $(MCU_DIR)/src/clock_17xx_40xx.c \ diff --git a/hw/bsp/lpc40/family.mk b/hw/bsp/lpc40/family.mk index 79d868f35..ef9fe57b2 100644 --- a/hw/bsp/lpc40/family.mk +++ b/hw/bsp/lpc40/family.mk @@ -20,6 +20,8 @@ LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs # All source paths should be relative to the top level. SRC_C += \ src/portable/nxp/lpc17_40/dcd_lpc17_40.c \ + src/portable/nxp/lpc17_40/hcd_lpc17_40.c \ + src/portable/ohci/ohci.c \ $(MCU_DIR)/../gcc/cr_startup_lpc40xx.c \ $(MCU_DIR)/src/chip_17xx_40xx.c \ $(MCU_DIR)/src/clock_17xx_40xx.c \ diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index 4b237e4cf..64aba011a 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -112,7 +112,7 @@ typedef struct { bool notification_xmit_is_running; // notification is currently transmitted } ncm_interface_t; -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static ncm_interface_t ncm_interface; +CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN tu_static ncm_interface_t ncm_interface; /** * This is the NTB parameter structure @@ -120,7 +120,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static ncm_interface_t ncm_interface; * \attention * We are lucky, that byte order is correct */ -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN tu_static const ntb_parameters_t ntb_parameters = { +CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN tu_static const ntb_parameters_t ntb_parameters = { .wLength = sizeof(ntb_parameters_t), .bmNtbFormatsSupported = 0x01,// 16-bit NTB supported .dwNtbInMaxSize = CFG_TUD_NCM_IN_NTB_MAX_SIZE, @@ -285,7 +285,7 @@ static xmit_ntb_t *xmit_get_next_ready_ntb(void) { * This must be called from netd_xfer_cb() so that ep_in is ready */ static bool xmit_insert_required_zlp(uint8_t rhport, uint32_t xferred_bytes) { - TU_LOG_DRV("xmit_insert_required_zlp(%d,%d)\n", rhport, xferred_bytes); + TU_LOG_DRV("xmit_insert_required_zlp(%d,%ld)\n", rhport, xferred_bytes); if (xferred_bytes == 0 || xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE != 0) { return false; @@ -521,11 +521,11 @@ static bool recv_validate_datagram(const recv_ntb_t *ntb, uint32_t len) { return false; } if (len < sizeof(nth16_t) + sizeof(ndp16_t) + 2 * sizeof(ndp16_datagram_t)) { - TU_LOG_DRV("(EE) ill min len: %d\n", len); + TU_LOG_DRV("(EE) ill min len: %lu\n", len); return false; } if (nth16->wBlockLength > len) { - TU_LOG_DRV("(EE) ill block length: %d > %d\n", nth16->wBlockLength, len); + TU_LOG_DRV("(EE) ill block length: %d > %lu\n", nth16->wBlockLength, len); return false; } if (nth16->wBlockLength > CFG_TUD_NCM_OUT_NTB_MAX_SIZE) { @@ -533,7 +533,7 @@ static bool recv_validate_datagram(const recv_ntb_t *ntb, uint32_t len) { return false; } if (nth16->wNdpIndex < sizeof(nth16) || nth16->wNdpIndex > len - (sizeof(ndp16_t) + 2 * sizeof(ndp16_datagram_t))) { - TU_LOG_DRV("(EE) ill position of first ndp: %d (%d)\n", nth16->wNdpIndex, len); + TU_LOG_DRV("(EE) ill position of first ndp: %d (%lu)\n", nth16->wNdpIndex, len); return false; } @@ -567,11 +567,11 @@ static bool recv_validate_datagram(const recv_ntb_t *ntb, uint32_t len) { while (ndp16_datagram[ndx].wDatagramIndex != 0 && ndp16_datagram[ndx].wDatagramLength != 0) { TU_LOG_DRV(" << %d %d\n", ndp16_datagram[ndx].wDatagramIndex, ndp16_datagram[ndx].wDatagramLength); if (ndp16_datagram[ndx].wDatagramIndex > len) { - TU_LOG_DRV("(EE) ill start of datagram[%d]: %d (%d)\n", ndx, ndp16_datagram[ndx].wDatagramIndex, len); + TU_LOG_DRV("(EE) ill start of datagram[%d]: %d (%lu)\n", ndx, ndp16_datagram[ndx].wDatagramIndex, len); return false; } if (ndp16_datagram[ndx].wDatagramIndex + ndp16_datagram[ndx].wDatagramLength > len) { - TU_LOG_DRV("(EE) ill end of datagram[%d]: %d (%d)\n", ndx, ndp16_datagram[ndx].wDatagramIndex + ndp16_datagram[ndx].wDatagramLength, len); + TU_LOG_DRV("(EE) ill end of datagram[%d]: %d (%lu)\n", ndx, ndp16_datagram[ndx].wDatagramIndex + ndp16_datagram[ndx].wDatagramLength, len); return false; } ++ndx; diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index dffb81765..c2699cc6f 100644 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -25,10 +25,10 @@ # ACTION=="add", SUBSYSTEM=="tty", SUBSYSTEMS=="usb", MODE="0666", PROGRAM="/bin/sh -c 'echo $$ID_SERIAL_SHORT | rev | cut -c -8 | rev'", SYMLINK+="ttyUSB_%c.%s{bInterfaceNumber}" # ACTION=="add", SUBSYSTEM=="block", SUBSYSTEMS=="usb", ENV{ID_FS_USAGE}=="filesystem", MODE="0666", PROGRAM="/bin/sh -c 'echo $$ID_SERIAL_SHORT | rev | cut -c -8 | rev'", RUN{program}+="/usr/bin/systemd-mount --no-block --automount=yes --collect $devnode /media/blkUSB_%c.%s{bInterfaceNumber}" +import argparse import os import sys import time -import click import serial import subprocess import json @@ -318,13 +318,18 @@ def test_hid_composite_freertos(id): # ------------------------------------------------------------- # Main # ------------------------------------------------------------- -@click.command() -@click.argument('config_file') -@click.option('-b', '--board', multiple=True, default=None, help='Boards to test, all if not specified') -def main(config_file, board): +def main(): """ Hardware test on specified boards """ + parser = argparse.ArgumentParser() + parser.add_argument('config_file', help='Configuration JSON file') + parser.add_argument('-b', '--board', action='append', default=[], help='Boards to test, all if not specified') + args = parser.parse_args() + + config_file = args.config_file + boards = args.board + config_file = os.path.join(os.path.dirname(__file__), config_file) with open(config_file) as f: config = json.load(f) @@ -334,10 +339,10 @@ def main(config_file, board): 'cdc_dual_ports', 'cdc_msc', 'dfu', 'dfu_runtime', 'hid_boot_interface', ] - if len(board) == 0: + if len(boards) == 0: config_boards = config['boards'] else: - config_boards = [e for e in config['boards'] if e['name'] in board] + config_boards = [e for e in config['boards'] if e['name'] in boards] for item in config_boards: name = item['name'] diff --git a/test/hil/pi4.json b/test/hil/pi4.json index 04329bb64..bdb8a5fa5 100644 --- a/test/hil/pi4.json +++ b/test/hil/pi4.json @@ -22,6 +22,16 @@ "flasher_product": "ItsyBitsy M4 Express", "flasher_reset_pin": "2", "flasher_args": "--offset 0x4000" + }, + { + "name": "espressif_s3_devkitm", + "uid": "84F703C084E4", + "tests": [ + "cdc_msc_freertos", "hid_composite_freertos" + ], + "flasher": "esptool", + "flasher_sn": "3ea619acd1cdeb11a0a0b806e93fd3f1", + "flasher_args": "-b 1500000" } ] } diff --git a/test/hil/pi4_esp32.json b/test/hil/pi4_esp32.json deleted file mode 100644 index c95dd2d4e..000000000 --- a/test/hil/pi4_esp32.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "boards": [ - { - "name": "espressif_s3_devkitm", - "uid": "84F703C084E4", - "tests": [ - "cdc_msc_freertos", "hid_composite_freertos" - ], - "flasher": "esptool", - "flasher_sn": "3ea619acd1cdeb11a0a0b806e93fd3f1", - "flasher_args": "-b 1500000" - } - ] -} diff --git a/tools/build.py b/tools/build.py index 884cd56f4..967f7c95e 100644 --- a/tools/build.py +++ b/tools/build.py @@ -1,8 +1,8 @@ +import argparse import os import sys import time import subprocess -import click from pathlib import Path from multiprocessing import Pool @@ -125,13 +125,20 @@ def build_family(family, toolchain, build_system): return ret -@click.command() -@click.argument('families', nargs=-1, required=False) -@click.option('-b', '--board', multiple=True, default=None, help='Boards to build') -@click.option('-t', '--toolchain', default='gcc', help='Toolchain to use, default is gcc') -@click.option('-s', '--build-system', default='cmake', help='Build system to use, default is cmake') -def main(families, board, toolchain, build_system): - if len(families) == 0 and len(board) == 0: +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('families', nargs='*', default=[], help='Families to build') + parser.add_argument('-b', '--board', action='append', default=[], help='Boards to build') + parser.add_argument('-t', '--toolchain', default='gcc', help='Toolchain to use, default is gcc') + parser.add_argument('-s', '--build-system', default='cmake', help='Build system to use, default is cmake') + args = parser.parse_args() + + families = args.families + boards = args.board + toolchain = args.toolchain + build_system = args.build_system + + if len(families) == 0 and len(boards) == 0: print("Please specify families or board to build") return 1 @@ -159,12 +166,23 @@ def main(families, board, toolchain, build_system): total_result[2] += fret[2] # build board (only cmake) - if board is not None: - for b in board: - r = build_board_cmake(b, toolchain) - total_result[0] += r[0] - total_result[1] += r[1] - total_result[2] += r[2] + if boards is not None: + for b in boards: + if build_system == 'cmake': + r = build_board_cmake(b, toolchain) + total_result[0] += r[0] + total_result[1] += r[1] + total_result[2] += r[2] + elif build_system == 'make': + all_examples = get_examples(find_family(b)) + with Pool(processes=os.cpu_count()) as pool: + pool_args = list((map(lambda e, bb=b, o=f"TOOLCHAIN={toolchain}": [e, bb, o], all_examples))) + r = pool.starmap(build_utils.build_example, pool_args) + # sum all element of same index (column sum) + rsum = list(map(sum, list(zip(*r)))) + total_result[0] += rsum[0] + total_result[1] += rsum[1] + total_result[2] += rsum[2] total_time = time.monotonic() - total_time print(build_separator) diff --git a/tools/build_esp32.py b/tools/build_esp32.py deleted file mode 100644 index 951467c23..000000000 --- a/tools/build_esp32.py +++ /dev/null @@ -1,106 +0,0 @@ -import os -import glob -import sys -import subprocess -import time - -import build_utils - -SUCCEEDED = "\033[32msucceeded\033[0m" -FAILED = "\033[31mfailed\033[0m" -SKIPPED = "\033[33mskipped\033[0m" - -success_count = 0 -fail_count = 0 -skip_count = 0 -exit_status = 0 - -total_time = time.monotonic() - -build_format = '| {:30} | {:30} | {:18} | {:7} | {:6} | {:6} |' -build_separator = '-' * 107 - -def filter_with_input(mylist): - if len(sys.argv) > 1: - input_args = list(set(mylist).intersection(sys.argv)) - if len(input_args) > 0: - mylist[:] = input_args - - -# Build all examples if not specified -all_examples = [entry.replace('examples/', '') for entry in glob.glob("examples/*/*_freertos")] -filter_with_input(all_examples) -all_examples.append('device/board_test') -all_examples.sort() - -# Build all boards if not specified -all_boards = [] -for entry in os.scandir("hw/bsp/espressif/boards"): - if entry.is_dir(): - all_boards.append(entry.name) -filter_with_input(all_boards) -all_boards.sort() - -def build_board(example, board): - global success_count, fail_count, skip_count, exit_status - start_time = time.monotonic() - - # Check if board is skipped - build_dir = f"cmake-build/cmake-build-{board}/{example}" - - # Generate and build - r = subprocess.run(f"cmake examples/{example} -B {build_dir} -G \"Ninja\" -DBOARD={board} -DMAX3421_HOST=1", - shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - if r.returncode == 0: - r = subprocess.run(f"cmake --build {build_dir}", shell=True, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - build_duration = time.monotonic() - start_time - flash_size = "-" - sram_size = "-" - - if r.returncode == 0: - success = SUCCEEDED - success_count += 1 - #(flash_size, sram_size) = build_size(example, board) - else: - exit_status = r.returncode - success = FAILED - fail_count += 1 - - title = build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size) - if os.getenv('CI'): - # always print build output if in CI - print(f"::group::{title}") - print(r.stdout.decode("utf-8")) - print(f"::endgroup::") - else: - # print build output if failed - print(title) - if r.returncode != 0: - print(r.stdout.decode("utf-8")) - - -def build_size(example, board): - #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) - elf_file = 'examples/device/{}/_build/{}/*.elf'.format(example, board) - size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8") - size_list = size_output.split('\n')[1].split('\t') - flash_size = int(size_list[0]) - sram_size = int(size_list[1]) + int(size_list[2]) - return (flash_size, sram_size) - - -print(build_separator) -print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) -print(build_separator) - -for example in all_examples: - for board in all_boards: - build_board(example, board) - -total_time = time.monotonic() - total_time -print(build_separator) -print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time)) -print(build_separator) - -sys.exit(exit_status) diff --git a/tools/get_deps.py b/tools/get_deps.py index 2359b4bd0..20cbe64c7 100644 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -245,11 +245,10 @@ def main(): args = parser.parse_args() families = args.families - board = args.board + boards = args.board - if len(families) == 0 and len(board) == 0: - print("Please specify family or board to fetch") - return + if len(families) == 0 and len(boards) == 0: + print("Warning: family and board are not specified, only fetching mandatory dependencies.") status = 0 deps = list(deps_mandatory.keys()) @@ -258,8 +257,8 @@ def main(): deps += deps_optional.keys() else: families = list(families) - if board is not None: - for b in board: + if boards is not None: + for b in boards: f = find_family(b) if f is not None: families.append(f) -- cgit v1.3.1