Merge branch 'master' of https://github.com/hathach/tinyusb into uac_interl

This commit is contained in:
HiFiPhile 2023-10-10 15:02:25 +02:00
commit b5c839f739
91 changed files with 2884 additions and 1045 deletions

View File

@ -36,11 +36,11 @@ jobs:
- 'broadcom_32bit'
- 'kinetis_k32l2'
- 'lpc11 lpc13 lpc15 lpc17'
- 'lpc51 lpc54'
- 'lpc51'
- 'mm32 msp432e4'
- 'samd11 same5x saml2x'
- 'stm32f2 stm32f3'
- 'stm32l0 stm32u5 stm32wb'
- 'stm32l0 stm32wb'
- 'tm4c123 xmc4000'
steps:
- name: Setup Python

View File

@ -29,12 +29,10 @@ jobs:
fail-fast: false
matrix:
board:
# Alphabetical order
# ESP32-S2
- 'espressif_saola_1'
- 'espressif_kaluga_1'
# ESP32-S3
#- 'espressif_s3_devkitm'
# S3 compile error with "dangerous relocation: call8: call target out of range: memcpy"
- 'espressif_s3_devkitm'
steps:
- name: Setup Python
@ -48,20 +46,5 @@ jobs:
- name: Checkout TinyUSB
uses: actions/checkout@v3
- name: Checkout hathach/linkermap
uses: actions/checkout@v3
with:
repository: hathach/linkermap
path: linkermap
- name: Build
run: docker run --rm -v $PWD:/project -w /project espressif/idf:latest python3 tools/build_esp32.py ${{ matrix.board }}
- name: Linker Map
run: |
pip install linkermap/
# find -quit to only print linkermap of 1 board per example
for ex in `ls -d examples/device/*/`
do
find ${ex} -maxdepth 3 -name *.map -print -quit | xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'
done

View File

@ -36,7 +36,7 @@ jobs:
- 'imxrt'
- 'kinetis_kl'
- 'lpc18 lpc40 lpc43'
- 'lpc55'
- 'lpc54 lpc55'
- 'mcx'
- 'nrf'
- 'ra'
@ -51,6 +51,7 @@ jobs:
- 'stm32g4'
- 'stm32h7'
- 'stm32l4'
- 'stm32u5'
steps:
- name: Setup Python
uses: actions/setup-python@v4

25
.idea/cmake.xml generated
View File

@ -2,23 +2,24 @@
<project version="4">
<component name="CMakeSharedSettings">
<configurations>
<configuration PROFILE_NAME="esp32s2" ENABLED="false" GENERATION_OPTIONS="-DBOARD=espressif_saola_1 -DIDF_TARGET=esp32s2">
<configuration PROFILE_NAME="esp32s2" ENABLED="false" TOOLCHAIN_NAME="ESP-IDF" GENERATION_OPTIONS="-DBOARD=espressif_saola_1">
<ADDITIONAL_GENERATION_ENVIRONMENT>
<envs>
<env name="ESPBAUD" value="1500000" />
<env name="ESPPORT" value="/dev/ttyUSB0" />
<env name="IDF_PATH" value="$PROJECT_DIR$/../esp-idf" />
<env name="PATH" value="$PROJECT_DIR$/../esp-idf/components/esptool_py/esptool:/home/hathach/code/esp-idf/components/espcoredump:/home/hathach/code/esp-idf/components/partition_table:/home/hathach/code/esp-idf/components/app_update:/home/hathach/.espressif/tools/xtensa-esp-elf-gdb/11.2_20220823/xtensa-esp-elf-gdb/bin:/home/hathach/.espressif/tools/riscv32-esp-elf-gdb/11.2_20220823/riscv32-esp-elf-gdb/bin:/home/hathach/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32-elf/bin:/home/hathach/.espressif/tools/xtensa-esp32s2-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32s2-elf/bin:/home/hathach/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32s3-elf/bin:/home/hathach/.espressif/tools/riscv32-esp-elf/esp-2021r2-patch5-8.4.0/riscv32-esp-elf/bin:/home/hathach/.espressif/tools/esp32ulp-elf/2.35_20220830/esp32ulp-elf/bin:/home/hathach/.espressif/tools/openocd-esp32/v0.11.0-esp32-20221026/openocd-esp32/bin:/home/hathach/.espressif/python_env/idf4.4_py3.10_env/bin:/home/hathach/code/esp-idf/tools:/home/hathach/app/riscv-openocd-wch/src:/home/hathach/app/arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi/bin:/home/hathach/.local/bin:/home/hathach/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/opt/SEGGER/JLink:/home/hathach/app/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin:/home/hathach/.local/xPacks/@xpack-dev-tools/riscv-none-embed-gcc/10.2.0-1.2.1/.content/bin:/home/hathach/.local/xPacks/@xpack-dev-tools/openocd/*/.content/bin:/home/hathach/ti/msp430-gcc/bin:/home/hathach/ti/MSPFlasher_1.3.20:/home/hathach/ti/uniflash_7.0.0:/home/hathach/app/gcc_8.3.0.202102_gnurx-elf/bin:/home/hathach/app/RFP_CLI_Linux_V31101_x64/linux-x64:/home/hathach/app/fomu-toolchain-linux_x86_64-v1.5.5/bin:/home/hathach/app/nuclei_riscv_newlibc_prebuilt_linux64_2020.08/gcc/bin:/home/hathach/app/riscv32-embecosm-ubuntu2004-gcc11.1.0/bin:/home/hathach/app/cov-analysis-linux64-2019.03/bin:/opt/iarsystems/bxarm/arm/bin:/home/hathach/.local/bin" />
</envs>
</ADDITIONAL_GENERATION_ENVIRONMENT>
</configuration>
<configuration PROFILE_NAME="esp32s3" ENABLED="false" GENERATION_OPTIONS="-DBOARD=espressif_s3_devkitm -DIDF_TARGET=esp32s3">
<configuration PROFILE_NAME="kaluga" ENABLED="false" TOOLCHAIN_NAME="ESP-IDF" GENERATION_OPTIONS="-DBOARD=espressif_kaluga_1 -DMAX3421_HOST=1 -DLOG=2">
<ADDITIONAL_GENERATION_ENVIRONMENT>
<envs>
<env name="ESPBAUD" value="1500000" />
</envs>
</ADDITIONAL_GENERATION_ENVIRONMENT>
</configuration>
<configuration PROFILE_NAME="esp32s3" ENABLED="false" TOOLCHAIN_NAME="ESP-IDF" GENERATION_OPTIONS="-DBOARD=espressif_s3_devkitm">
<ADDITIONAL_GENERATION_ENVIRONMENT>
<envs>
<env name="ESPBAUD" value="1500000" />
<env name="ESPPORT" value="/dev/ttyUSB0" />
<env name="IDF_PATH" value="$PROJECT_DIR$/../esp-idf" />
<env name="PATH" value="$PROJECT_DIR$/../esp-idf/components/esptool_py/esptool:/home/hathach/code/esp-idf/components/espcoredump:/home/hathach/code/esp-idf/components/partition_table:/home/hathach/code/esp-idf/components/app_update:/home/hathach/.espressif/tools/xtensa-esp-elf-gdb/11.2_20220823/xtensa-esp-elf-gdb/bin:/home/hathach/.espressif/tools/riscv32-esp-elf-gdb/11.2_20220823/riscv32-esp-elf-gdb/bin:/home/hathach/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32-elf/bin:/home/hathach/.espressif/tools/xtensa-esp32s2-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32s2-elf/bin:/home/hathach/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32s3-elf/bin:/home/hathach/.espressif/tools/riscv32-esp-elf/esp-2021r2-patch5-8.4.0/riscv32-esp-elf/bin:/home/hathach/.espressif/tools/esp32ulp-elf/2.35_20220830/esp32ulp-elf/bin:/home/hathach/.espressif/tools/openocd-esp32/v0.11.0-esp32-20221026/openocd-esp32/bin:/home/hathach/.espressif/python_env/idf4.4_py3.10_env/bin:/home/hathach/code/esp-idf/tools:/home/hathach/app/riscv-openocd-wch/src:/home/hathach/app/arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi/bin:/home/hathach/.local/bin:/home/hathach/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/opt/SEGGER/JLink:/home/hathach/app/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin:/home/hathach/.local/xPacks/@xpack-dev-tools/riscv-none-embed-gcc/10.2.0-1.2.1/.content/bin:/home/hathach/.local/xPacks/@xpack-dev-tools/openocd/*/.content/bin:/home/hathach/ti/msp430-gcc/bin:/home/hathach/ti/MSPFlasher_1.3.20:/home/hathach/ti/uniflash_7.0.0:/home/hathach/app/gcc_8.3.0.202102_gnurx-elf/bin:/home/hathach/app/RFP_CLI_Linux_V31101_x64/linux-x64:/home/hathach/app/fomu-toolchain-linux_x86_64-v1.5.5/bin:/home/hathach/app/nuclei_riscv_newlibc_prebuilt_linux64_2020.08/gcc/bin:/home/hathach/app/riscv32-embecosm-ubuntu2004-gcc11.1.0/bin:/home/hathach/app/cov-analysis-linux64-2019.03/bin:/opt/iarsystems/bxarm/arm/bin:/home/hathach/.local/bin" />
</envs>
</ADDITIONAL_GENERATION_ENVIRONMENT>
</configuration>
@ -55,6 +56,14 @@
<configuration PROFILE_NAME="portenta_c33" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=portenta_c33 -DLOG=3" />
<configuration PROFILE_NAME="metro_m4_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m4_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" />
<configuration PROFILE_NAME="metro_m0_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m0_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" />
<configuration PROFILE_NAME="stm32u5" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32u575eval" />
<configuration PROFILE_NAME="metro esp32s2" ENABLED="false" TOOLCHAIN_NAME="ESP-IDF" GENERATION_OPTIONS="-DBOARD=adafruit_metro_esp32s2 -DMAX3421_HOST=1 -DLOG=2">
<ADDITIONAL_GENERATION_ENVIRONMENT>
<envs>
<env name="ESPBAUD" value="1500000" />
</envs>
</ADDITIONAL_GENERATION_ENVIRONMENT>
</configuration>
</configurations>
</component>
</project>

View File

@ -1,5 +1,3 @@
DEPS_SUBMODULES += lib/FreeRTOS-Kernel
include ../../make.mk
FREERTOS_SRC = lib/FreeRTOS-Kernel
@ -10,7 +8,7 @@ INC += \
src/FreeRTOSConfig \
$(TOP)/hw \
$(TOP)/$(FREERTOS_SRC)/include \
$(TOP)/$(FREERTOS_PORTABLE_SRC)
$(TOP)/$(FREERTOS_PORTABLE_SRC) \
# Example source
EXAMPLE_SOURCE = \

View File

@ -41,6 +41,7 @@
#define USBD_STACK_SIZE 4096
#else
#include "FreeRTOS.h"
#include "semphr.h"
#include "queue.h"
@ -54,7 +55,7 @@
#define CDC_STACK_SZIE configMINIMAL_STACK_SIZE
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
// MACRO CONSTANT TYPEDEF PROTOTYPES
//--------------------------------------------------------------------+
/* Blink pattern
@ -62,7 +63,7 @@
* - 1000 ms : device mounted
* - 2500 ms : device is suspended
*/
enum {
enum {
BLINK_NOT_MOUNTED = 250,
BLINK_MOUNTED = 1000,
BLINK_SUSPENDED = 2500,
@ -81,16 +82,15 @@ StaticTask_t cdc_taskdef;
TimerHandle_t blinky_tm;
void led_blinky_cb(TimerHandle_t xTimer);
void usb_device_task(void* param);
void cdc_task(void* params);
static void led_blinky_cb(TimerHandle_t xTimer);
static void usb_device_task(void *param);
void cdc_task(void *params);
//--------------------------------------------------------------------+
// Main
//--------------------------------------------------------------------+
int main(void)
{
int main(void) {
board_init();
#if configSUPPORT_STATIC_ALLOCATION
@ -104,8 +104,8 @@ int main(void)
xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef);
#else
blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb);
xTaskCreate( usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL);
xTaskCreate( cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL);
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);
@ -119,16 +119,14 @@ int main(void)
}
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
void app_main(void)
{
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)
{
static void usb_device_task(void *param) {
(void) param;
// init device stack on configured roothub port
@ -141,8 +139,7 @@ void usb_device_task(void* param)
}
// RTOS forever loop
while (1)
{
while (1) {
// put this thread to waiting state until there is new events
tud_task();
@ -156,35 +153,28 @@ void usb_device_task(void* param)
//--------------------------------------------------------------------+
// Invoked when device is mounted
void tud_mount_cb(void)
{
void tud_mount_cb(void) {
xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0);
}
// Invoked when device is unmounted
void tud_umount_cb(void)
{
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 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)
{
if (tud_mounted())
{
void tud_resume_cb(void) {
if (tud_mounted()) {
xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0);
}
else
{
} else {
xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0);
}
}
@ -192,20 +182,17 @@ void tud_resume_cb(void)
//--------------------------------------------------------------------+
// USB CDC
//--------------------------------------------------------------------+
void cdc_task(void* params)
{
void cdc_task(void *params) {
(void) params;
// RTOS forever loop
while ( 1 )
{
while (1) {
// connected() check for DTR bit
// Most but not all terminal client set this when making connection
// if ( tud_cdc_connected() )
{
// There are data available
while ( tud_cdc_available() )
{
while (tud_cdc_available()) {
uint8_t buf[64];
// read and echo back
@ -228,32 +215,27 @@ void cdc_task(void* params)
}
// Invoked when cdc when line state changed e.g connected/disconnected
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
{
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
(void) itf;
(void) rts;
// TODO set some indicator
if ( dtr )
{
if (dtr) {
// Terminal connected
}else
{
} else {
// Terminal disconnected
}
}
// Invoked when CDC interface received data from host
void tud_cdc_rx_cb(uint8_t itf)
{
void tud_cdc_rx_cb(uint8_t itf) {
(void) itf;
}
//--------------------------------------------------------------------+
// BLINKING TASK
//--------------------------------------------------------------------+
void led_blinky_cb(TimerHandle_t xTimer)
{
static void led_blinky_cb(TimerHandle_t xTimer) {
(void) xTimer;
static bool led_state = false;

View File

@ -10,6 +10,11 @@ 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})
# Example source

View File

@ -10,14 +10,4 @@ EXAMPLE_SOURCE += \
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
# TinyUSB Host Stack source
SRC_C += \
src/class/cdc/cdc_host.c \
src/class/hid/hid_host.c \
src/class/msc/msc_host.c \
src/host/hub.c \
src/host/usbh.c \
src/portable/ohci/ohci.c \
src/portable/nxp/lpc17_40/hcd_lpc17_40.c
include ../../rules.mk

View File

@ -1,3 +1,4 @@
mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX

View File

@ -10,6 +10,11 @@ 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})
# Example source

View File

@ -13,14 +13,4 @@ EXAMPLE_SOURCE = \
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
# TinyUSB Host Stack source
SRC_C += \
src/class/cdc/cdc_host.c \
src/class/hid/hid_host.c \
src/class/msc/msc_host.c \
src/host/hub.c \
src/host/usbh.c \
src/portable/ohci/ohci.c \
src/portable/nxp/lpc17_40/hcd_lpc17_40.c
include ../../rules.mk

View File

@ -1,3 +1,4 @@
mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX

View File

@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.17)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
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})
# Example source
target_sources(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c
${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c
${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.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_host_example(${PROJECT} freertos)

View File

@ -0,0 +1,34 @@
include ../../make.mk
FREERTOS_SRC = lib/FreeRTOS-Kernel
FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(USE_IAR),IAR,GCC)
INC += \
src \
src/FreeRTOSConfig \
$(TOP)/hw \
$(TOP)/$(FREERTOS_SRC)/include \
$(TOP)/$(FREERTOS_PORTABLE_SRC) \
# Example source
EXAMPLE_SOURCE = \
src/cdc_app.c \
src/freertos_hook.c \
src/hid_app.c \
src/main.c \
src/msc_app.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 $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c))
SRC_S += \
$(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s))
include ../../rules.mk

View File

@ -0,0 +1,13 @@
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
mcu:MIMXRT1XXX
mcu:MIMXRT10XX
mcu:MIMXRT11XX
mcu:RP2040
mcu:MSP432E4
mcu:RX65X
mcu:RAXXX
mcu:MAX3421

View File

@ -0,0 +1,6 @@
# This file is for ESP-IDF only
idf_component_register(SRCS "cdc_app.c" "hid_app.c" "main.c" "msc_app.c"
INCLUDE_DIRS "."
REQUIRES boards tinyusb_src)
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format)

View File

@ -0,0 +1,215 @@
/*
* 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__
// 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
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
// TODO fix later
// FIXME cause redundant-decls warnings
#if CFG_TUSB_MCU == OPT_MCU_MM32F327X
extern u32 SystemCoreClock;
#else
extern uint32_t SystemCoreClock;
#endif
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#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 ( 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 4
#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
#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
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<<configPRIO_BITS) - 1)
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#endif
#endif /* __FREERTOS_CONFIG__H */

View File

@ -0,0 +1,145 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2022, 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 "tusb.h"
#include "bsp/board_api.h"
#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"
#define CDC_STACK_SZIE 2048
#else
#include "FreeRTOS.h"
#include "semphr.h"
#include "queue.h"
#include "task.h"
#include "timers.h"
#define CDC_STACK_SZIE (3*configMINIMAL_STACK_SIZE/2)
#endif
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
#if configSUPPORT_STATIC_ALLOCATION
StackType_t cdc_stack[CDC_STACK_SZIE];
StaticTask_t cdc_taskdef;
#endif
static void cdc_app_task(void* param);
void cdc_app_init(void) {
#if configSUPPORT_STATIC_ALLOCATION
xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef);
#else
xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL);
#endif
}
// helper
size_t get_console_inputs(uint8_t *buf, size_t bufsize) {
size_t count = 0;
while (count < bufsize) {
int ch = board_getchar();
if (ch <= 0) break;
buf[count] = (uint8_t) ch;
count++;
}
return count;
}
static void cdc_app_task(void* param) {
(void) param;
uint8_t buf[64 + 1]; // +1 for extra null character
uint32_t const bufsize = sizeof(buf) - 1;
while (1) {
uint32_t count = get_console_inputs(buf, bufsize);
buf[count] = 0;
if (count) {
// loop over all mounted interfaces
for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) {
if (tuh_cdc_mounted(idx)) {
// console --> cdc interfaces
tuh_cdc_write(idx, buf, count);
tuh_cdc_write_flush(idx);
}
}
}
vTaskDelay(1);
}
}
//--------------------------------------------------------------------+
// 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;
// forward cdc interfaces -> console
uint32_t count = tuh_cdc_read(idx, buf, bufsize);
buf[count] = 0;
printf((char *) buf);
}
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);
#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)) {
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);
}
#endif
}
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);
}

View File

@ -0,0 +1,111 @@
/*
* 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 */
SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1);
MSTP(CMT0) = 0;
SYSTEM.PRCR.WORD = (0xA5u<<8);
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

View File

@ -0,0 +1,267 @@
/*
* 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.
*
*/
#include "bsp/board_api.h"
#include "tusb.h"
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
// If your host terminal support ansi escape code such as TeraTerm
// it can be use to simulate mouse cursor movement within terminal
#define USE_ANSI_ESCAPE 0
#define MAX_REPORT 4
static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
// Each HID instance can has multiple reports
static struct {
uint8_t report_count;
tuh_hid_report_info_t report_info[MAX_REPORT];
} hid_info[CFG_TUH_HID];
static void process_kbd_report(hid_keyboard_report_t const *report);
static void process_mouse_report(hid_mouse_report_t const *report);
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len);
void hid_app_init(void) {
// nothing to do
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
// Invoked when device with hid interface is mounted
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
// can be used to parse common/simple enough descriptor.
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
// therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
// Interface protocol (hid_interface_protocol_enum_t)
const char *protocol_str[] = { "None", "Keyboard", "Mouse" };
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]);
// By default host stack will use activate boot protocol on supported interface.
// Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser)
if (itf_protocol == HID_ITF_PROTOCOL_NONE) {
hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT,
desc_report, desc_len);
printf("HID has %u reports \r\n", hid_info[instance].report_count);
}
// request to receive report
// tuh_hid_report_received_cb() will be invoked when report is available
if (!tuh_hid_receive_report(dev_addr, instance)) {
printf("Error: cannot request to receive report\r\n");
}
}
// Invoked when device with hid interface is un-mounted
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
}
// Invoked when received report from device via interrupt endpoint
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
switch (itf_protocol) {
case HID_ITF_PROTOCOL_KEYBOARD:
TU_LOG2("HID receive boot keyboard report\r\n");
process_kbd_report((hid_keyboard_report_t const *) report);
break;
case HID_ITF_PROTOCOL_MOUSE:
TU_LOG2("HID receive boot mouse report\r\n");
process_mouse_report((hid_mouse_report_t const *) report);
break;
default:
// Generic report requires matching ReportID and contents with previous parsed report info
process_generic_report(dev_addr, instance, report, len);
break;
}
// continue to request to receive report
if (!tuh_hid_receive_report(dev_addr, instance)) {
printf("Error: cannot request to receive report\r\n");
}
}
//--------------------------------------------------------------------+
// Keyboard
//--------------------------------------------------------------------+
// look up new key in previous keys
static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) {
for (uint8_t i = 0; i < 6; i++) {
if (report->keycode[i] == keycode) return true;
}
return false;
}
static void process_kbd_report(hid_keyboard_report_t const *report) {
static hid_keyboard_report_t prev_report = { 0, 0, { 0 } }; // previous report to check key released
//------------- example code ignore control (non-printable) key affects -------------//
for (uint8_t i = 0; i < 6; i++) {
if (report->keycode[i]) {
if (find_key_in_report(&prev_report, report->keycode[i])) {
// exist in previous report means the current key is holding
} else {
// not existed in previous report means the current key is pressed
bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0];
putchar(ch);
if (ch == '\r') putchar('\n'); // added new line for enter key
#ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
fflush(stdout); // flush right away, else nanolib will wait for newline
#endif
}
}
// TODO example skips key released
}
prev_report = *report;
}
//--------------------------------------------------------------------+
// Mouse
//--------------------------------------------------------------------+
void cursor_movement(int8_t x, int8_t y, int8_t wheel) {
#if USE_ANSI_ESCAPE
// Move X using ansi escape
if ( x < 0) {
printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left
}else if ( x > 0) {
printf(ANSI_CURSOR_FORWARD(%d), x); // move right
}
// Move Y using ansi escape
if ( y < 0) {
printf(ANSI_CURSOR_UP(%d), (-y)); // move up
}else if ( y > 0) {
printf(ANSI_CURSOR_DOWN(%d), y); // move down
}
// Scroll using ansi escape
if (wheel < 0) {
printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up
}else if (wheel > 0) {
printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down
}
printf("\r\n");
#else
printf("(%d %d %d)\r\n", x, y, wheel);
#endif
}
static void process_mouse_report(hid_mouse_report_t const *report) {
static hid_mouse_report_t prev_report = { 0 };
//------------- button state -------------//
uint8_t button_changed_mask = report->buttons ^ prev_report.buttons;
if (button_changed_mask & report->buttons) {
printf(" %c%c%c ",
report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-',
report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-',
report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-');
}
//------------- cursor movement -------------//
cursor_movement(report->x, report->y, report->wheel);
}
//--------------------------------------------------------------------+
// Generic Report
//--------------------------------------------------------------------+
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
(void) dev_addr;
uint8_t const rpt_count = hid_info[instance].report_count;
tuh_hid_report_info_t *rpt_info_arr = hid_info[instance].report_info;
tuh_hid_report_info_t *rpt_info = NULL;
if (rpt_count == 1 && rpt_info_arr[0].report_id == 0) {
// Simple report without report ID as 1st byte
rpt_info = &rpt_info_arr[0];
} else {
// Composite report, 1st byte is report ID, data starts from 2nd byte
uint8_t const rpt_id = report[0];
// Find report id in the array
for (uint8_t i = 0; i < rpt_count; i++) {
if (rpt_id == rpt_info_arr[i].report_id) {
rpt_info = &rpt_info_arr[i];
break;
}
}
report++;
len--;
}
if (!rpt_info) {
printf("Couldn't find report info !\r\n");
return;
}
// For complete list of Usage Page & Usage checkout src/class/hid/hid.h. For examples:
// - Keyboard : Desktop, Keyboard
// - Mouse : Desktop, Mouse
// - Gamepad : Desktop, Gamepad
// - Consumer Control (Media Key) : Consumer, Consumer Control
// - System Control (Power key) : Desktop, System Control
// - Generic (vendor) : 0xFFxx, xx
if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) {
switch (rpt_info->usage) {
case HID_USAGE_DESKTOP_KEYBOARD:
TU_LOG1("HID receive keyboard report\r\n");
// Assume keyboard follow boot report layout
process_kbd_report((hid_keyboard_report_t const *) report);
break;
case HID_USAGE_DESKTOP_MOUSE:
TU_LOG1("HID receive mouse report\r\n");
// Assume mouse follow boot report layout
process_mouse_report((hid_mouse_report_t const *) report);
break;
default:
break;
}
}
}

View File

@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "bsp/board_api.h"
#include "tusb.h"
#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"
#define USBH_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 USBH_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
#endif
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF 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 timer & task
#if configSUPPORT_STATIC_ALLOCATION
StaticTimer_t blinky_tmdef;
StackType_t usb_host_stack[USBH_STACK_SIZE];
StaticTask_t usb_host_taskdef;
#endif
TimerHandle_t blinky_tm;
static void led_blinky_cb(TimerHandle_t xTimer);
static void usb_host_task(void* param);
extern void cdc_app_init(void);
extern void hid_app_init(void);
extern void msc_app_init(void);
/*------------- MAIN -------------*/
int main(void) {
board_init();
printf("TinyUSB Host CDC MSC HID with FreeRTOS Example\r\n");
// Create soft timer for blinky, task for tinyusb stack
#if configSUPPORT_STATIC_ALLOCATION
blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef);
xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef);
#else
blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb);
xTaskCreate(usb_host_task, "usbd", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, 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();
#endif
return 0;
}
#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)
void app_main(void) {
main();
}
#endif
// USB Host task
// This top level thread process all usb events and invoke callbacks
static void usb_host_task(void *param) {
(void) param;
// init host stack on configured roothub port
tuh_init(BOARD_TUH_RHPORT);
if (board_init_after_tusb) {
board_init_after_tusb();
}
cdc_app_init();
hid_app_init();
msc_app_init();
// RTOS forever loop
while (1) {
// put this thread to waiting state until there is new events
tuh_task();
// following code only run if tuh_task() process at least 1 event
}
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
void tuh_mount_cb(uint8_t dev_addr) {
// application set-up
printf("A device with address %d is mounted\r\n", dev_addr);
}
void tuh_umount_cb(uint8_t dev_addr) {
// application tear-down
printf("A device with address %d is unmounted \r\n", dev_addr);
}
//--------------------------------------------------------------------+
// BLINKING TASK
//--------------------------------------------------------------------+
static 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
}

View File

@ -0,0 +1,67 @@
/*
* 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"
static scsi_inquiry_resp_t inquiry_resp;
void msc_app_init(void) {
// nothing to do
}
bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) {
msc_cbw_t const *cbw = cb_data->cbw;
msc_csw_t const *csw = cb_data->csw;
if (csw->status != 0) {
printf("Inquiry failed\r\n");
return false;
}
// Print out Vendor ID, Product ID and Rev
printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev);
// Get capacity of device
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);
return true;
}
//------------- IMPLEMENTATION -------------//
void tuh_msc_mount_cb(uint8_t dev_addr) {
printf("A MassStorage device is mounted\r\n");
uint8_t const lun = 0;
tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb, 0);
}
void tuh_msc_umount_cb(uint8_t dev_addr) {
(void) dev_addr;
printf("A MassStorage device is unmounted\r\n");
}

View File

@ -0,0 +1,133 @@
/*
* 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
//--------------------------------------------------------------------+
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// change to 1 if using pico-pio-usb as host controller for raspberry rp2040
#define CFG_TUH_RPI_PIO_USB 0
#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB
#endif
// RHPort number used for host can be defined by board.mk, default to port 0
#ifndef BOARD_TUH_RHPORT
#define BOARD_TUH_RHPORT 0
#endif
// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUH_MAX_SPEED
#define BOARD_TUH_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_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
// Enable Host stack
#define CFG_TUH_ENABLED 1
// Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUH_MAX_SPEED BOARD_TUH_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_TUH_MEM_SECTION
#define CFG_TUH_MEM_SECTION
#endif
#ifndef CFG_TUH_MEM_ALIGN
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
#endif
//--------------------------------------------------------------------
// CONFIGURATION
//--------------------------------------------------------------------
// Size of buffer to hold descriptors and other data used for enumeration
#define CFG_TUH_ENUMERATION_BUFSIZE 256
#define CFG_TUH_HUB 1 // number of supported hubs
#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_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
// max device support (excluding hub device): 1 hub typically has 4 ports
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
//------------- HID -------------//
#define CFG_TUH_HID_EPIN_BUFSIZE 64
#define CFG_TUH_HID_EPOUT_BUFSIZE 64
//------------- CDC -------------//
// Set Line Control state on enumeration/mounted:
// DTR ( bit 0), RTS (bit 1)
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0x03
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
// bit rate = 115200, 1 stop bit, no parity, 8 bit data width
#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_CONFIG_H_ */

View File

@ -10,6 +10,11 @@ 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})
# Example source

View File

@ -11,14 +11,4 @@ EXAMPLE_SOURCE += \
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
# TinyUSB Host Stack source
SRC_C += \
src/class/cdc/cdc_host.c \
src/class/hid/hid_host.c \
src/class/msc/msc_host.c \
src/host/hub.c \
src/host/usbh.c \
src/portable/ohci/ohci.c \
src/portable/nxp/lpc17_40/hcd_lpc17_40.c
include ../../rules.mk

View File

@ -1,3 +1,4 @@
mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX

View File

@ -10,6 +10,11 @@ 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})
# Example source

View File

@ -24,14 +24,4 @@ SRC_C += \
# suppress warning caused by fatfs
CFLAGS += -Wno-error=cast-qual
# TinyUSB Host Stack source
SRC_C += \
src/class/cdc/cdc_host.c \
src/class/hid/hid_host.c \
src/class/msc/msc_host.c \
src/host/hub.c \
src/host/usbh.c \
src/portable/ohci/ohci.c \
src/portable/nxp/lpc17_40/hcd_lpc17_40.c
include ../../rules.mk

View File

@ -1,3 +1,4 @@
mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX

View File

@ -26,9 +26,6 @@ ifeq '$(findstring ;,$(PATH))' ';'
CMDEXE := 1
# makefile shell commands should use syntax for DOS CMD, not unix sh
# Unfortunately, SHELL may point to sh or bash, which can't accept DOS syntax.
# We can't just use sh, because while sh and/or bash shell may be available,
# many Windows environments won't have utilities like realpath used below, so...
# Force DOS command shell on Windows.
SHELL := cmd.exe
endif

View File

@ -4,3 +4,5 @@ idf_component_register(SRCS family.c
INCLUDE_DIRS "." ${BOARD} ${hw_dir}
PRIV_REQUIRES "driver"
REQUIRES led_strip src tinyusb_src)
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format)

View File

@ -36,6 +36,14 @@
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 36
#define MAX3421_MOSI_PIN 35
#define MAX3421_MISO_PIN 37
#define MAX3421_CS_PIN 15
#define MAX3421_INTR_PIN 14
#ifdef __cplusplus
}
#endif

View File

@ -37,6 +37,14 @@
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 36
#define MAX3421_MOSI_PIN 35
#define MAX3421_MISO_PIN 37
#define MAX3421_CS_PIN 15
#define MAX3421_INTR_PIN 14
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,2 @@
# Apply board specific content here
set(IDF_TARGET "esp32s2")

View File

@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
* 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
@ -24,57 +24,22 @@
* This file is part of the TinyUSB stack.
*/
/** \ingroup Group_Common Common Files
* \defgroup Group_TimeoutTimer timeout timer
* @{ */
#ifndef _TUSB_TIMEOUT_H_
#define _TUSB_TIMEOUT_H_
#include <stdbool.h>
#include <stdint.h>
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
typedef struct {
uint32_t start;
uint32_t interval;
}tu_timeout_t;
// Note: On the production version (v1.2) WS2812 is connected to GPIO 18,
// however earlier revision v1.1 WS2812 is connected to GPIO 17
#define NEOPIXEL_PIN 18
#if 0
extern uint32_t tusb_hal_millis(void);
static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec)
{
tt->interval = msec;
tt->start = tusb_hal_millis();
}
static inline bool tu_timeout_expired(tu_timeout_t* tt)
{
return ( tusb_hal_millis() - tt->start ) >= tt->interval;
}
// For used with periodic event to prevent drift
static inline void tu_timeout_reset(tu_timeout_t* tt)
{
tt->start += tt->interval;
}
static inline void tu_timeout_restart(tu_timeout_t* tt)
{
tt->start = tusb_hal_millis();
}
#endif
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
#ifdef __cplusplus
}
#endif
#endif /* _TUSB_TIMEOUT_H_ */
/** @} */
#endif /* BOARD_H_ */

View File

@ -36,6 +36,14 @@
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
// SPI for USB host shield
#define MAX3421_SPI_HOST SPI2_HOST
#define MAX3421_SCK_PIN 36
#define MAX3421_MOSI_PIN 35
#define MAX3421_MISO_PIN 37
#define MAX3421_CS_PIN 15
#define MAX3421_INTR_PIN 14
#ifdef __cplusplus
}
#endif

View File

@ -33,27 +33,55 @@
#include "soc/usb_periph.h"
#include "driver/rmt.h"
#include "driver/uart.h"
#if ESP_IDF_VERSION_MAJOR > 4
#include "esp_private/periph_ctrl.h"
#else
#include "driver/periph_ctrl.h"
#endif
// Note; current code use UART0 can cause device to reset while monitoring
#define USE_UART 0
#define UART_ID UART_NUM_0
#ifdef NEOPIXEL_PIN
#include "led_strip.h"
static led_strip_t *strip;
static led_strip_t* strip;
#endif
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
static void configure_pins(usb_hal_context_t *usb);
#include "driver/spi_master.h"
static void max3421_init(void);
#endif
static void configure_pins(usb_hal_context_t* usb);
//--------------------------------------------------------------------+
// Implementation
//--------------------------------------------------------------------+
// Initialize on-board peripherals : led, button, uart and USB
void board_init(void)
{
void board_init(void) {
#if USE_UART
// uart init
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_driver_install(UART_ID, 1024, 0, 0, NULL, 0);
uart_param_config(UART_ID, &uart_config);
#endif
#ifdef NEOPIXEL_PIN
#ifdef NEOPIXEL_POWER_PIN
@ -84,19 +112,21 @@ void board_init(void)
periph_module_enable(PERIPH_USB_MODULE);
usb_hal_context_t hal = {
.use_external_phy = false // use built-in PHY
.use_external_phy = false // use built-in PHY
};
usb_hal_init(&hal);
configure_pins(&hal);
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
max3421_init();
#endif
}
static void configure_pins(usb_hal_context_t *usb)
{
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
* for USB Host.
*/
for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) {
* for USB Host. */
for (const usb_iopin_dsc_t* iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) {
if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) {
esp_rom_gpio_pad_select_gpio(iopin->pin);
if (iopin->is_output) {
@ -115,6 +145,7 @@ static void configure_pins(usb_hal_context_t *usb)
esp_rom_gpio_pad_unhold(iopin->pin);
}
}
if (!usb->use_external_phy) {
gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
@ -122,8 +153,7 @@ static void configure_pins(usb_hal_context_t *usb)
}
// Turn LED on or off
void board_led_write(bool state)
{
void board_led_write(bool state) {
#ifdef NEOPIXEL_PIN
strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00);
strip->refresh(strip, 100);
@ -132,21 +162,138 @@ void board_led_write(bool state)
// Get the current state of button
// a '1' means active (pressed), a '0' means inactive.
uint32_t board_button_read(void)
{
uint32_t board_button_read(void) {
return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE;
}
// Get characters from UART
int board_uart_read(uint8_t* buf, int len)
{
(void) buf; (void) len;
return 0;
int board_uart_read(uint8_t* buf, int len) {
#if USE_UART
return uart_read_bytes(UART_ID, buf, len, 0);
#else
return -1;
#endif
}
// Send characters to UART
int board_uart_write(void const * buf, int len)
{
(void) buf; (void) len;
int board_uart_write(void const* buf, int len) {
(void) buf;
(void) len;
return 0;
}
int board_getchar(void) {
uint8_t c = 0;
return board_uart_read(&c, 1) > 0 ? (int) c : (-1);
}
//--------------------------------------------------------------------+
// API: SPI transfer with MAX3421E, must be implemented by application
//--------------------------------------------------------------------+
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
static spi_device_handle_t max3421_spi;
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) {
(void) param;
while (1) {
xSemaphoreTake(max3421_intr_sem, portMAX_DELAY);
tuh_int_handler(BOARD_TUH_RHPORT, false);
}
}
static void max3421_init(void) {
// CS pin
gpio_set_direction(MAX3421_CS_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(MAX3421_CS_PIN, 1);
// SPI
spi_bus_config_t buscfg = {
.miso_io_num = MAX3421_MISO_PIN,
.mosi_io_num = MAX3421_MOSI_PIN,
.sclk_io_num = MAX3421_SCK_PIN,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.data4_io_num = -1,
.data5_io_num = -1,
.data6_io_num = -1,
.data7_io_num = -1,
.max_transfer_sz = 1024
};
ESP_ERROR_CHECK(spi_bus_initialize(MAX3421_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
spi_device_interface_config_t max3421_cfg = {
.mode = 0,
.clock_speed_hz = 26000000,
.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);
gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT);
gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE);
gpio_install_isr_service(0);
gpio_isr_handler_add(MAX3421_INTR_PIN, max3421_isr_handler, NULL);
}
void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
(void) rhport;
if (enabled) {
gpio_intr_enable(MAX3421_INTR_PIN);
} else {
gpio_intr_disable(MAX3421_INTR_PIN);
}
}
void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
(void) rhport;
gpio_set_level(MAX3421_CS_PIN, active ? 0 : 1);
}
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) {
(void) rhport;
if (tx_buf == NULL) {
// fifo read, transmit rx_buf as dummy
tx_buf = rx_buf;
}
// length in bits
size_t const len_bits = xfer_bytes << 3;
spi_transaction_t xact = {
.length = len_bits,
.rxlength = rx_buf ? len_bits : 0,
.tx_buffer = tx_buf,
.rx_buffer = rx_buf
};
ESP_ERROR_CHECK(spi_device_transmit(max3421_spi, &xact));
return true;
}
#endif

View File

@ -16,40 +16,58 @@ else()
return()
endif()
list(APPEND compile_options
"-DCFG_TUSB_MCU=${tusb_mcu}"
"-DCFG_TUSB_OS=OPT_OS_FREERTOS"
#"-DCFG_TUSB_DEBUG=1"
)
idf_component_get_property(freertos_component_dir freertos COMPONENT_DIR)
list(APPEND includes_public
"${tusb_src}"
# The FreeRTOS API include convention in tinyusb is different from esp-idf
#"${freertos_component_dir}/include/freertos"
)
list(APPEND compile_definitions
CFG_TUSB_MCU=${tusb_mcu}
CFG_TUSB_OS=OPT_OS_FREERTOS
)
list(APPEND srcs
"${tusb_src}/tusb.c"
"${tusb_src}/common/tusb_fifo.c"
"${tusb_src}/device/usbd.c"
"${tusb_src}/device/usbd_control.c"
"${tusb_src}/class/cdc/cdc_device.c"
"${tusb_src}/class/dfu/dfu_rt_device.c"
"${tusb_src}/class/hid/hid_device.c"
"${tusb_src}/class/midi/midi_device.c"
"${tusb_src}/class/msc/msc_device.c"
"${tusb_src}/class/net/ecm_rndis_device.c"
"${tusb_src}/class/net/ncm_device.c"
"${tusb_src}/class/usbtmc/usbtmc_device.c"
"${tusb_src}/class/vendor/vendor_device.c"
"${tusb_src}/portable/synopsys/dwc2/dcd_dwc2.c"
)
# common
${tusb_src}/tusb.c
${tusb_src}/common/tusb_fifo.c
# device
${tusb_src}/device/usbd.c
${tusb_src}/device/usbd_control.c
${tusb_src}/class/audio/audio_device.c
${tusb_src}/class/cdc/cdc_device.c
${tusb_src}/class/dfu/dfu_device.c
${tusb_src}/class/dfu/dfu_rt_device.c
${tusb_src}/class/hid/hid_device.c
${tusb_src}/class/midi/midi_device.c
${tusb_src}/class/msc/msc_device.c
${tusb_src}/class/net/ecm_rndis_device.c
${tusb_src}/class/net/ncm_device.c
${tusb_src}/class/usbtmc/usbtmc_device.c
${tusb_src}/class/vendor/vendor_device.c
${tusb_src}/class/video/video_device.c
${tusb_src}/portable/synopsys/dwc2/dcd_dwc2.c
# host
${tusb_src}/host/usbh.c
${tusb_src}/host/hub.c
${tusb_src}/class/cdc/cdc_host.c
${tusb_src}/class/hid/hid_host.c
${tusb_src}/class/msc/msc_host.c
${tusb_src}/class/vendor/vendor_host.c
)
# use max3421 as host controller
if (MAX3421_HOST STREQUAL "1")
list(APPEND srcs ${tusb_src}/portable/analog/max3421/hcd_max3421.c)
list(APPEND compile_definitions CFG_TUH_MAX3421=1)
endif ()
if (DEFINED LOG)
list(APPEND compile_definitions CFG_TUSB_DEBUG=${LOG})
if (LOG STREQUAL "4")
# no inline for debug level 4
list(APPEND compile_definitions TU_ATTR_ALWAYS_INLINE=)
endif ()
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${includes_public}
REQUIRES src
)
INCLUDE_DIRS ${tusb_src}
REQUIRES src
)
target_compile_options(${COMPONENT_LIB} PUBLIC ${compile_options})
target_compile_definitions(${COMPONENT_LIB} PUBLIC ${compile_definitions})
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format)

View File

@ -40,6 +40,7 @@ if (NOT FAMILY STREQUAL rp2040)
# enable LTO if supported skip rp2040
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED)
cmake_print_variables(IPO_SUPPORTED)
if (IPO_SUPPORTED)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()

View File

@ -188,7 +188,7 @@ void USB_OTG1_IRQHandler(void)
#endif
#if PORT_SUPPORT_HOST(0)
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
}
@ -199,7 +199,7 @@ void USB_OTG2_IRQHandler(void)
#endif
#if PORT_SUPPORT_HOST(1)
tuh_int_handler(1);
tuh_int_handler(1, true);
#endif
}

View File

@ -39,7 +39,7 @@
void USB0_IRQHandler(void)
{
#if CFG_TUH_ENABLED
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
#if CFG_TUD_ENABLED
tud_int_handler(0);

View File

@ -22,48 +22,47 @@ set(FAMILY_MCUS KINETIS_KL CACHE INTERNAL "")
#------------------------------------
# only need to be built ONCE for all examples
function(add_board_target BOARD_TARGET)
if (NOT TARGET ${BOARD_TARGET})
add_library(${BOARD_TARGET} STATIC
${SDK_DIR}/drivers/gpio/fsl_gpio.c
${SDK_DIR}/drivers/lpsci/fsl_lpsci.c
${SDK_DIR}/drivers/uart/fsl_uart.c
${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c
${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_VARIANT}.c
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMSIS_DIR}/CMSIS/Core/Include
${SDK_DIR}/devices/${MCU_VARIANT}
${SDK_DIR}/devices/${MCU_VARIANT}/drivers
${SDK_DIR}/drivers/common
${SDK_DIR}/drivers/gpio
${SDK_DIR}/drivers/lpsci
${SDK_DIR}/drivers/port
${SDK_DIR}/drivers/smc
${SDK_DIR}/drivers/uart
)
if (TARGET ${BOARD_TARGET})
return()
endif ()
update_board(${BOARD_TARGET})
add_library(${BOARD_TARGET} STATIC
${SDK_DIR}/drivers/gpio/fsl_gpio.c
${SDK_DIR}/drivers/lpsci/fsl_lpsci.c
${SDK_DIR}/drivers/uart/fsl_uart.c
${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c
${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_VARIANT}.c
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMSIS_DIR}/CMSIS/Core/Include
${SDK_DIR}/devices/${MCU_VARIANT}
${SDK_DIR}/devices/${MCU_VARIANT}/drivers
${SDK_DIR}/drivers/common
${SDK_DIR}/drivers/gpio
${SDK_DIR}/drivers/lpsci
${SDK_DIR}/drivers/port
${SDK_DIR}/drivers/smc
${SDK_DIR}/drivers/uart
)
update_board(${BOARD_TARGET})
# LD_FILE and STARTUP_FILE can be defined in board.cmake
# LD_FILE and STARTUP_FILE can be defined in board.cmake
target_sources(${BOARD_TARGET} PUBLIC
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
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:--script=${LD_FILE_GNU}"
# nanolib
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${BOARD_TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
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
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${BOARD_TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
endif ()
endfunction()

View File

@ -37,7 +37,7 @@ void USB_IRQHandler(void)
#endif
#if CFG_TUH_ENABLED
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
}

View File

@ -151,7 +151,7 @@ void USB_IRQHandler(void)
#endif
#if CFG_TUH_ENABLED
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
}

View File

@ -22,6 +22,8 @@ MCU_DIR = hw/mcu/nxp/lpcopen/lpc175x_6x/lpc_chip_175x_6x
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 \
$(MCU_DIR)/../gcc/cr_startup_lpc175x_6x.c \
$(MCU_DIR)/src/chip_17xx_40xx.c \
$(MCU_DIR)/src/clock_17xx_40xx.c \
@ -29,7 +31,7 @@ SRC_C += \
$(MCU_DIR)/src/iocon_17xx_40xx.c \
$(MCU_DIR)/src/sysctl_17xx_40xx.c \
$(MCU_DIR)/src/sysinit_17xx_40xx.c \
$(MCU_DIR)/src/uart_17xx_40xx.c
$(MCU_DIR)/src/uart_17xx_40xx.c \
INC += \
$(TOP)/$(MCU_DIR)/inc

View File

@ -43,25 +43,23 @@
//--------------------------------------------------------------------+
// USB Interrupt Handler
//--------------------------------------------------------------------+
void USB0_IRQHandler(void)
{
void USB0_IRQHandler(void) {
#if PORT_SUPPORT_DEVICE(0)
tud_int_handler(0);
tud_int_handler(0);
#endif
#if PORT_SUPPORT_HOST(0)
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
}
void USB1_IRQHandler(void)
{
void USB1_IRQHandler(void) {
#if PORT_SUPPORT_DEVICE(1)
tud_int_handler(1);
tud_int_handler(1);
#endif
#if PORT_SUPPORT_HOST(1)
tuh_int_handler(1);
tuh_int_handler(1, true);
#endif
}
@ -74,28 +72,26 @@ const uint32_t OscRateIn = 12000000;
const uint32_t ExtRateIn = 0;
// Invoked by startup code
void SystemInit(void)
{
void SystemInit(void) {
#ifdef __USE_LPCOPEN
extern void (* const g_pfnVectors[])(void);
extern void (*const g_pfnVectors[])(void);
unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08;
*pSCB_VTOR = (unsigned int) g_pfnVectors;
*pSCB_VTOR = (unsigned int) g_pfnVectors;
#endif
board_lpc18_pinmux();
#ifdef TRACE_ETM
#ifdef TRACE_ETM
// Trace clock is limited to 60MHz, limit CPU clock to 120MHz
Chip_SetupCoreClock(CLKIN_CRYSTAL, 120000000UL, true);
#else
#else
// CPU clock max to 180 Mhz
Chip_SetupCoreClock(CLKIN_CRYSTAL, MAX_CLOCK_FREQ, true);
#endif
#endif
}
void board_init(void)
{
void board_init(void) {
SystemCoreClockUpdate();
#if CFG_TUSB_OS == OPT_OS_NONE
@ -135,27 +131,22 @@ void board_init(void)
// Board porting API
//--------------------------------------------------------------------+
void board_led_write(bool state)
{
void board_led_write(bool state) {
Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED_PORT, LED_PIN, state);
}
uint32_t board_button_read(void)
{
uint32_t board_button_read(void) {
// active low
return Chip_GPIO_GetPinState(LPC_GPIO_PORT, BUTTON_PORT, BUTTON_PIN) ? 0 : 1;
}
int board_uart_read(uint8_t* buf, int len)
{
int board_uart_read(uint8_t *buf, int len) {
return Chip_UART_Read(UART_DEV, buf, len);
}
int board_uart_write(void const * buf, int len)
{
uint8_t const* buf8 = (uint8_t const*) buf;
for(int i=0; i<len; i++)
{
int board_uart_write(void const *buf, int len) {
uint8_t const *buf8 = (uint8_t const *) buf;
for (int i = 0; i < len; i++) {
while ((Chip_UART_ReadLineStatus(UART_DEV) & UART_LSR_THRE) == 0) {}
Chip_UART_SendByte(UART_DEV, buf8[i]);
}
@ -165,13 +156,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

View File

@ -37,7 +37,7 @@ void USB_IRQHandler(void) {
#endif
#if CFG_TUH_ENABLED
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
}

View File

@ -213,7 +213,7 @@ void USB0_IRQHandler(void)
#endif
#if PORT_SUPPORT_HOST(0)
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
}
@ -224,7 +224,7 @@ void USB1_IRQHandler(void)
#endif
#if PORT_SUPPORT_HOST(1)
tuh_int_handler(1);
tuh_int_handler(1, true);
#endif
}

View File

@ -0,0 +1,165 @@
/*
* 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__
#include "fsl_device_registers.h"
#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 ( 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 4
#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 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
/* 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<<configPRIO_BITS) - 1)
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#endif

View File

@ -0,0 +1,21 @@
set(MCU_VARIANT LPC54114)
set(MCU_CORE LPC54114_cm4)
set(JLINK_DEVICE LPC54114J256_M4)
set(PYOCD_TARGET LPC54114)
set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/LPC54114J256_cm4_flash.ld)
# Device port default to PORT1 Highspeed
if (NOT DEFINED PORT)
set(PORT 1)
endif()
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
CPU_LPC54114J256BD64_cm4
)
target_link_libraries(${TARGET} PUBLIC
${SDK_DIR}/devices/${MCU_VARIANT}/gcc/libpower_cm4_hardabi.a
)
endfunction()

View File

@ -0,0 +1,22 @@
set(MCU_VARIANT LPC54608)
set(MCU_CORE LPC54608)
set(JLINK_DEVICE LPC54608J512)
set(PYOCD_TARGET LPC54608)
set(NXPLINK_DEVICE LPC54608:LPCXpresso54608)
set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/LPC54608J512_flash.ld)
# Device port default to PORT1 Highspeed
if (NOT DEFINED PORT)
set(PORT 1)
endif()
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
CPU_LPC54608J512ET180
)
target_link_libraries(${TARGET} PUBLIC
${SDK_DIR}/devices/${MCU_VARIANT}/gcc/libpower_hardabi.a
)
endfunction()

View File

@ -28,83 +28,85 @@ set(HOST_PORT $<NOT:${PORT}>)
#------------------------------------
# only need to be built ONCE for all examples
function(add_board_target BOARD_TARGET)
if (NOT TARGET ${BOARD_TARGET})
add_library(${BOARD_TARGET} STATIC
# driver
${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c
${SDK_DIR}/drivers/common/fsl_common_arm.c
${SDK_DIR}/drivers/flexcomm/fsl_flexcomm.c
${SDK_DIR}/drivers/flexcomm/fsl_usart.c
# mcu
${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_CORE}.c
${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c
${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_power.c
${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_reset.c
)
if (TARGET ${BOARD_TARGET})
return()
endif()
add_library(${BOARD_TARGET} STATIC
# driver
${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c
${SDK_DIR}/drivers/common/fsl_common_arm.c
${SDK_DIR}/drivers/flexcomm/fsl_flexcomm.c
${SDK_DIR}/drivers/flexcomm/fsl_usart.c
# mcu
${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_CORE}.c
${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c
${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_power.c
${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_reset.c
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
CFG_TUSB_MEM_ALIGN=TU_ATTR_ALIGNED\(64\)
BOARD_TUD_RHPORT=${PORT}
BOARD_TUH_RHPORT=${HOST_PORT}
)
# 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
CFG_TUSB_MEM_ALIGN=TU_ATTR_ALIGNED\(64\)
BOARD_TUD_RHPORT=${PORT}
BOARD_TUH_RHPORT=${HOST_PORT}
BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
BOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED
CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\)
)
# 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
BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
BOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED
CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\)
)
else ()
target_compile_definitions(${BOARD_TARGET} PUBLIC
BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED
BOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED
CFG_TUH_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\)
#CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\)
)
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
else ()
target_compile_definitions(${BOARD_TARGET} PUBLIC
BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED
BOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED
CFG_TUH_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\)
#CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\)
)
endif ()
update_board(${BOARD_TARGET})
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
)
if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID})
set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld)
endif ()
update_board(${BOARD_TARGET})
if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID})
set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S)
endif ()
if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID})
set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld)
endif ()
target_sources(${BOARD_TARGET} PUBLIC
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
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
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${BOARD_TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
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
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${BOARD_TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
endif ()
endfunction()
@ -124,8 +126,6 @@ function(family_configure_example TARGET RTOS)
# BSP
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
# external driver
${TOP}/lib/sct_neopixel/sct_neopixel.c
)
# https://github.com/gsteiert/sct_neopixel/pull/1

View File

@ -34,7 +34,7 @@
void USB0_IRQHandler(void)
{
#if CFG_TUH_ENABLED
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
#if CFG_TUD_ENABLED
tud_int_handler(0);

View File

@ -214,7 +214,7 @@ void USB0_IRQHandler(void)
#endif
#if PORT_SUPPORT_HOST(0)
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
}
@ -225,7 +225,7 @@ void USB1_IRQHandler(void)
#endif
#if PORT_SUPPORT_HOST(1)
tuh_int_handler(1);
tuh_int_handler(1, true);
#endif
}

View File

@ -1,6 +1,6 @@
set(MCU_VARIANT nrf52840)
#set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld)
set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld)
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld)
#set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld)
# enable max3421 host driver for this board
set(MAX3421_HOST 1)

View File

@ -49,8 +49,8 @@
#define MAX3421_SCK_PIN 14
#define MAX3421_MOSI_PIN 13
#define MAX3421_MISO_PIN 15
#define MAX3421_CS_PIN 27
#define MAX3421_INTR_PIN 26
#define MAX3421_CS_PIN 27 // D10
#define MAX3421_INTR_PIN 26 // D9
#ifdef __cplusplus
}

View File

@ -95,13 +95,10 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) {
//------------- Host using MAX2341E -------------//
#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);
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;
tuh_int_handler(1);
}
#endif
@ -191,50 +188,7 @@ void board_init(void) {
#endif
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// MAX3421 need 3.3v signal (may not be needed)
#if defined(UICR_REGOUT0_VOUT_Msk) && 0
if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != UICR_REGOUT0_VOUT_3V3) {
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~UICR_REGOUT0_VOUT_Msk) | UICR_REGOUT0_VOUT_3V3;
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
NVIC_SystemReset();
}
#endif
// manually manage CS
nrf_gpio_cfg_output(MAX3421_CS_PIN);
nrf_gpio_pin_write(MAX3421_CS_PIN, 1);
// USB host using max3421e usb controller via SPI
nrfx_spim_config_t cfg = {
.sck_pin = MAX3421_SCK_PIN,
.mosi_pin = MAX3421_MOSI_PIN,
.miso_pin = MAX3421_MISO_PIN,
.ss_pin = NRFX_SPIM_PIN_NOT_USED,
.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,
};
// no handler --> blocking
nrfx_spim_init(&_spi, &cfg, NULL, NULL);
// max3421e interrupt pin
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;
nrfx_gpiote_in_init(MAX3421_INTR_PIN, &in_config, max3421_int_handler);
nrfx_gpiote_trigger_enable(MAX3421_INTR_PIN, true);
max3421_init();
#endif
}
@ -251,15 +205,15 @@ uint32_t board_button_read(void) {
return BUTTON_STATE_ACTIVE == nrf_gpio_pin_read(BUTTON_PIN);
}
int board_uart_read(uint8_t *buf, int len) {
int board_uart_read(uint8_t* buf, int len) {
(void) buf;
(void) len;
return 0;
// return NRFX_SUCCESS == nrfx_uart_rx(&_uart_id, buf, (size_t) len) ? len : 0;
}
int board_uart_write(void const *buf, int len) {
return (NRFX_SUCCESS == nrfx_uarte_tx(&_uart_id, (uint8_t const *) buf, (size_t) len)) ? len : 0;
int board_uart_write(void const* buf, int len) {
return (NRFX_SUCCESS == nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len)) ? len : 0;
}
#if CFG_TUSB_OS == OPT_OS_NONE
@ -317,6 +271,61 @@ 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;
tuh_int_handler(1, true);
}
static void max3421_init(void) {
// MAX3421 need 3.3v signal (may not be needed)
// #if defined(UICR_REGOUT0_VOUT_Msk)
// if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != UICR_REGOUT0_VOUT_3V3) {
// NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
// while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
//
// NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~UICR_REGOUT0_VOUT_Msk) | UICR_REGOUT0_VOUT_3V3;
//
// NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
// while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
//
// NVIC_SystemReset();
// }
// #endif
// manually manage CS
nrf_gpio_cfg_output(MAX3421_CS_PIN);
nrf_gpio_pin_write(MAX3421_CS_PIN, 1);
// USB host using max3421e usb controller via SPI
nrfx_spim_config_t cfg = {
.sck_pin = MAX3421_SCK_PIN,
.mosi_pin = MAX3421_MOSI_PIN,
.miso_pin = MAX3421_MISO_PIN,
.ss_pin = NRFX_SPIM_PIN_NOT_USED,
.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,
};
// no handler --> blocking
nrfx_spim_init(&_spi, &cfg, NULL, NULL);
// max3421e interrupt pin
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);
}
// API to enable/disable MAX3421 INTR pin interrupt
void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
(void) rhport;
@ -329,22 +338,25 @@ void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
}
}
// API to control MAX3421 SPI CS
void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
(void) rhport;
nrf_gpio_pin_write(MAX3421_CS_PIN, active ? 0 : 1);
}
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) {
// API to transfer data with MAX3421 SPI
// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) {
(void) rhport;
nrfx_spim_xfer_desc_t xfer = {
.p_tx_buffer = tx_buf,
.tx_length = tx_len,
.tx_length = tx_buf ? xfer_bytes : 0,
.p_rx_buffer = rx_buf,
.rx_length = rx_len,
.rx_length = rx_buf ? xfer_bytes : 0,
};
return (nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS);
return nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS;
}
#endif

View File

@ -188,7 +188,7 @@ void usbfs_interrupt_handler(void) {
R_BSP_IrqStatusClear(irq);
#if PORT_SUPPORT_HOST(0)
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
#if PORT_SUPPORT_DEVICE(0)
@ -201,7 +201,7 @@ void usbfs_resume_handler(void) {
R_BSP_IrqStatusClear(irq);
#if PORT_SUPPORT_HOST(0)
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
#if PORT_SUPPORT_DEVICE(0)
@ -229,7 +229,7 @@ void usbhs_interrupt_handler(void) {
R_BSP_IrqStatusClear(irq);
#if PORT_SUPPORT_HOST(1)
tuh_int_handler(1);
tuh_int_handler(1, true);
#endif
#if PORT_SUPPORT_DEVICE(1)

View File

@ -177,7 +177,7 @@ void INT_Excep_SCI5_RXI5(void)
void INT_Excep_USB0_USBI0(void)
{
#if CFG_TUH_ENABLED
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
#if CFG_TUD_ENABLED
tud_int_handler(0);

View File

@ -72,6 +72,7 @@ static void uart_init(void);
#define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID)
static void max3421_init(void);
#endif
void board_init(void) {
@ -237,13 +238,13 @@ int board_uart_write(void const * buf, int len)
static void uart_init(void) {
}
int board_uart_read(uint8_t *buf, int 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) {
(void) buf;
(void) len;
return 0;
@ -262,6 +263,8 @@ uint32_t board_millis(void) {
return system_ticks;
}
#endif
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
@ -269,15 +272,16 @@ uint32_t board_millis(void) {
static void max3421_init(void) {
//------------- SPI Init -------------//
uint32_t const baudrate = 4000000u;
// MAX3421E max SPI clock is 26MHz however SAMD can only work reliably at 12 Mhz
uint32_t const baudrate = 12000000u;
// Enable the APB clock for SERCOM
PM->APBCMASK.reg |= 1u << (PM_APBCMASK_SERCOM0_Pos + MAX3421_SERCOM_ID);
// Configure GCLK for SERCOM
// GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOM4_CORE | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN;
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val+MAX3421_SERCOM_ID) |
GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN;
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val + MAX3421_SERCOM_ID) |
GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN;
while (GCLK->STATUS.bit.SYNCBUSY);
Sercom* sercom = MAX3421_SERCOM;
@ -291,7 +295,7 @@ static void max3421_init(void) {
// Set up SPI in master mode, MSB first, SPI mode 0
sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) |
SERCOM_SPI_CTRLA_MODE(3);
SERCOM_SPI_CTRLA_MODE(3);
sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN;
while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1);
@ -343,6 +347,11 @@ static void max3421_init(void) {
EIC->CONFIG[0].reg &= ~(7 << sense_shift);
EIC->CONFIG[0].reg |= 2 << sense_shift;
#if CFG_TUSB_OS == OPT_OS_FREERTOS
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
NVIC_SetPriority(EIC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
#endif
// Enable External Interrupt
EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << MAX3421_INTR_EIC_ID);
@ -356,9 +365,10 @@ void EIC_Handler(void) {
EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << MAX3421_INTR_EIC_ID);
// Call the TinyUSB interrupt handler
tuh_int_handler(1);
tuh_int_handler(1, true);
}
// API to enable/disable MAX3421 INTR pin interrupt
void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
(void) rhport;
@ -369,24 +379,26 @@ void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
}
}
// API to control MAX3421 SPI CS
void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
(void) rhport;
gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1);
}
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) {
// API to transfer data with MAX3421 SPI
// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) {
(void) rhport;
Sercom* sercom = MAX3421_SERCOM;
size_t count = 0;
while (count < tx_len || count < rx_len) {
for (size_t count = 0; count < xfer_bytes; count++) {
// Wait for the transmit buffer to be empty
while (!sercom->SPI.INTFLAG.bit.DRE);
// Write data to be transmitted
uint8_t data = 0x00;
if (count < tx_len) {
if (tx_buf) {
data = tx_buf[count];
}
@ -397,11 +409,9 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l
// Read received data
data = (uint8_t) sercom->SPI.DATA.reg;
if (count < rx_len) {
if (rx_buf) {
rx_buf[count] = data;
}
count++;
}
// wait for bus idle and clear flags
@ -412,6 +422,3 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l
}
#endif
#endif

View File

@ -59,7 +59,7 @@
#define configTICK_RATE_HZ ( 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( 128 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*6*1024 )
#define configMAX_TASK_NAME_LEN 16
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1

View File

@ -81,6 +81,7 @@ void USB_3_Handler(void) {
#define MAX3421_EIC_Handler TU_XSTRCAT3(EIC_, MAX3421_INTR_EIC_ID, _Handler)
static void max3421_init(void);
#endif
void board_init(void) {
@ -153,13 +154,13 @@ uint32_t board_button_read(void) {
return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1;
}
int board_uart_read(uint8_t *buf, int 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) {
(void) buf;
(void) len;
return 0;
@ -176,6 +177,8 @@ uint32_t board_millis(void) {
return system_ticks;
}
#endif
//--------------------------------------------------------------------+
// API: SPI transfer with MAX3421E, must be implemented by application
//--------------------------------------------------------------------+
@ -183,10 +186,12 @@ uint32_t board_millis(void) {
static void max3421_init(void) {
//------------- SPI Init -------------//
uint32_t const baudrate = 4000000u;
// MAX3421E max SPI clock is 26MHz however SAMD can only work reliably at 12 Mhz
uint32_t const baudrate = 12000000u;
struct {
volatile uint32_t *mck_apb;
volatile uint32_t* mck_apb;
uint32_t mask;
uint8_t gclk_id_core;
uint8_t gclk_id_slow;
@ -211,8 +216,10 @@ static void max3421_init(void) {
*sercom_clock[MAX3421_SERCOM_ID].mck_apb |= sercom_clock[MAX3421_SERCOM_ID].mask;
// Configure GCLK for SERCOM
GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_core].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_slow].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_core].reg =
GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_slow].reg =
GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
// Disable the SPI module
sercom->SPI.CTRLA.bit.ENABLE = 0;
@ -223,13 +230,18 @@ static void max3421_init(void) {
// Set up SPI in master mode, MSB first, SPI mode 0
sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) |
SERCOM_SPI_CTRLA_MODE(3);
SERCOM_SPI_CTRLA_MODE(3);
sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN;
while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1);
// Set the baud rate
sercom->SPI.BAUD.reg = (uint8_t) (SystemCoreClock / (2 * baudrate) - 1);
uint8_t baud_reg = (uint8_t) (SystemCoreClock / (2 * baudrate));
if (baud_reg) {
baud_reg--;
}
sercom->SPI.BAUD.reg = baud_reg;
// Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2), function C (sercom)
gpio_set_pin_direction(MAX3421_SCK_PIN, GPIO_DIRECTION_OUT);
@ -270,9 +282,9 @@ static void max3421_init(void) {
while (EIC->SYNCBUSY.bit.ENABLE);
// Configure EIC to trigger on falling edge
volatile uint32_t * eic_config;
volatile uint32_t* eic_config;
uint8_t sense_shift;
if ( MAX3421_INTR_EIC_ID < 8 ) {
if (MAX3421_INTR_EIC_ID < 8) {
eic_config = &EIC->CONFIG[0].reg;
sense_shift = MAX3421_INTR_EIC_ID * 4;
} else {
@ -283,6 +295,11 @@ static void max3421_init(void) {
*eic_config &= ~(7 << sense_shift);
*eic_config |= 2 << sense_shift;
#if CFG_TUSB_OS == OPT_OS_FREERTOS
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
NVIC_SetPriority(EIC_0_IRQn + MAX3421_INTR_EIC_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
#endif
// Enable External Interrupt
EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << MAX3421_INTR_EIC_ID);
@ -296,9 +313,10 @@ void MAX3421_EIC_Handler(void) {
EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << MAX3421_INTR_EIC_ID);
// Call the TinyUSB interrupt handler
tuh_int_handler(1);
tuh_int_handler(1, true);
}
// API to enable/disable MAX3421 INTR pin interrupt
void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
(void) rhport;
@ -310,24 +328,26 @@ void tuh_max3421_int_api(uint8_t rhport, bool enabled) {
}
}
// API to control MAX3421 SPI CS
void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) {
(void) rhport;
gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1);
}
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) {
// API to transfer data with MAX3421 SPI
// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) {
(void) rhport;
Sercom* sercom = MAX3421_SERCOM;
size_t count = 0;
while (count < tx_len || count < rx_len) {
for (size_t count = 0; count < xfer_bytes; count++) {
// Wait for the transmit buffer to be empty
while (!sercom->SPI.INTFLAG.bit.DRE);
// Write data to be transmitted
uint8_t data = 0x00;
if (count < tx_len) {
if (tx_buf) {
data = tx_buf[count];
}
@ -338,11 +358,9 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l
// Read received data
data = (uint8_t) sercom->SPI.DATA.reg;
if (count < rx_len) {
if (rx_buf) {
rx_buf[count] = data;
}
count++;
}
// wait for bus idle and clear flags
@ -353,5 +371,3 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l
}
#endif
#endif

View File

@ -26,50 +26,46 @@ set(FAMILY_MCUS STM32G4 CACHE INTERNAL "")
#------------------------------------
# only need to be built ONCE for all examples
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_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s)
set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf)
if (TARGET ${BOARD_TARGET})
return()
endif ()
add_library(${BOARD_TARGET} STATIC
${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMSIS_5}/CMSIS/Core/Include
${ST_CMSIS}/Include
${ST_HAL_DRIVER}/Inc
)
target_compile_options(${BOARD_TARGET} PUBLIC
)
target_compile_definitions(${BOARD_TARGET} PUBLIC
)
# Startup & Linker script
set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s)
set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s)
set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf)
update_board(${BOARD_TARGET})
add_library(${BOARD_TARGET} STATIC
${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMSIS_5}/CMSIS/Core/Include
${ST_CMSIS}/Include
${ST_HAL_DRIVER}/Inc
)
update_board(${BOARD_TARGET})
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${BOARD_TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
# nanolib
--specs=nosys.specs
--specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${BOARD_TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${BOARD_TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
# nanolib
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${BOARD_TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
endfunction()

View File

@ -0,0 +1,165 @@
/*
* 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__
#include "stm32u5xx.h"
#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 ( 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 4
#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 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
/* 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 4
/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<<configPRIO_BITS) - 1)
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#endif

View File

@ -0,0 +1,10 @@
set(MCU_VARIANT stm32u575xx)
set(JLINK_DEVICE stm32u575ai)
set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/STM32U575xx_FLASH.ld)
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
STM32U575xx
)
endfunction()

View File

@ -7,4 +7,4 @@ LD_FILE = $(BOARD_PATH)/STM32U575AIIXQ_FLASH.ld
SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s
# For flash-jlink target
JLINK_DEVICE = stm32u575
JLINK_DEVICE = stm32u575ai

View File

@ -25,15 +25,25 @@
* This file is part of the TinyUSB stack.
*/
// Suppress warning caused by mcu driver
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wundef"
#endif
#include "stm32u5xx_hal.h"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "bsp/board_api.h"
#include "board.h"
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
void OTG_FS_IRQHandler(void)
{
void OTG_FS_IRQHandler(void) {
tud_int_handler(0);
}
@ -43,8 +53,7 @@ void OTG_FS_IRQHandler(void)
UART_HandleTypeDef UartHandle;
void board_init(void)
{
void board_init(void) {
board_clock_init();
@ -123,8 +132,8 @@ void board_init(void)
GPIO_InitStruct.Alternate = GPIO_AF10_USB;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
#if OTG_FS_VBUS_SENSE
// Configure VBUS Pin
#if defined(OTG_FS_VBUS_SENSE) && OTG_FS_VBUS_SENSE
// Configure VBUS Pin OTG_FS_VBUS_SENSE
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
@ -152,50 +161,44 @@ void board_init(void)
// Board porting API
//--------------------------------------------------------------------+
void board_led_write(bool state)
{
void board_led_write(bool state) {
HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON));
}
uint32_t board_button_read(void)
{
uint32_t board_button_read(void) {
return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(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)
{
HAL_UART_Transmit(&UartHandle, (uint8_t *)(uintptr_t)buf, len, 0xffff);
int board_uart_write(void const *buf, int len) {
HAL_UART_Transmit(&UartHandle, (uint8_t *) (uintptr_t) buf, len, 0xffff);
return len;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler(void)
{
void SysTick_Handler(void) {
HAL_IncTick();
system_ticks++;
}
uint32_t board_millis(void)
{
uint32_t board_millis(void) {
return system_ticks;
}
#endif
void HardFault_Handler(void)
{
void HardFault_Handler(void) {
asm("bkpt");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void)
{
void _init(void) {
}

108
hw/bsp/stm32u5/family.cmake Normal file
View File

@ -0,0 +1,108 @@
include_guard()
if (NOT BOARD)
message(FATAL_ERROR "BOARD not specified")
endif ()
set(ST_FAMILY u5)
set(ST_PREFIX stm32${ST_FAMILY}xx)
set(ST_HAL_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver)
set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis_device_${ST_FAMILY})
set(CMSIS_5 ${TOP}/lib/CMSIS_5)
# include board specific
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
# toolchain set up
set(CMAKE_SYSTEM_PROCESSOR cortex-m33 CACHE INTERNAL "System Processor")
set(CMAKE_TOOLCHAIN_FILE ${TOP}/tools/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
set(FAMILY_MCUS STM32U5 CACHE INTERNAL "")
#------------------------------------
# BOARD_TARGET
#------------------------------------
# only need to be built ONCE for all examples
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_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s)
set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf)
add_library(${BOARD_TARGET} STATIC
${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${CMSIS_5}/CMSIS/Core/Include
${ST_CMSIS}/Include
${ST_HAL_DRIVER}/Inc
)
update_board(${BOARD_TARGET})
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${BOARD_TARGET} PUBLIC
"LINKER:--script=${LD_FILE_GNU}"
-nostartfiles
# nanolib
--specs=nosys.specs --specs=nano.specs
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${BOARD_TARGET} PUBLIC
"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_STM32U5 ${RTOS})
target_sources(${TARGET}-tinyusb PUBLIC
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
#${TOP}/src/portable/st/typec/typec_stm32.c
)
target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD})
# Link dependencies
target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb)
# Flashing
family_flash_stlink(${TARGET})
family_flash_jlink(${TARGET})
endfunction()

View File

@ -20,11 +20,11 @@ SRC_C += \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c
INC += \

View File

@ -8,7 +8,7 @@
void USB0_Handler(void)
{
#if CFG_TUH_ENABLED
tuh_int_handler(0);
tuh_int_handler(0, true);
#endif
#if CFG_TUD_ENABLED

View File

@ -43,16 +43,14 @@
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
enum
{
enum {
MSC_STAGE_IDLE = 0,
MSC_STAGE_CMD,
MSC_STAGE_DATA,
MSC_STAGE_STATUS,
};
typedef struct
{
typedef struct {
uint8_t itf_num;
uint8_t ep_in;
uint8_t ep_out;
@ -69,13 +67,13 @@ typedef struct
//------------- SCSI -------------//
uint8_t stage;
void* buffer;
void* buffer;
tuh_msc_complete_cb_t complete_cb;
uintptr_t complete_arg;
CFG_TUH_MEM_ALIGN msc_cbw_t cbw;
CFG_TUH_MEM_ALIGN msc_csw_t csw;
}msch_interface_t;
} msch_interface_t;
CFG_TUH_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX];
@ -86,40 +84,34 @@ static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)];
// FIXME potential nul reference
TU_ATTR_ALWAYS_INLINE
static inline msch_interface_t* get_itf(uint8_t dev_addr)
{
return &_msch_itf[dev_addr-1];
static inline msch_interface_t* get_itf(uint8_t dev_addr) {
return &_msch_itf[dev_addr - 1];
}
//--------------------------------------------------------------------+
// PUBLIC API
//--------------------------------------------------------------------+
uint8_t tuh_msc_get_maxlun(uint8_t dev_addr)
{
uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) {
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->max_lun;
}
uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun)
{
uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) {
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->capacity[lun].block_count;
}
uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun)
{
uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) {
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->capacity[lun].block_size;
}
bool tuh_msc_mounted(uint8_t dev_addr)
{
bool tuh_msc_mounted(uint8_t dev_addr) {
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->mounted;
}
bool tuh_msc_ready(uint8_t dev_addr)
{
bool tuh_msc_ready(uint8_t dev_addr) {
msch_interface_t* p_msc = get_itf(dev_addr);
return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in) && !usbh_edpt_busy(dev_addr, p_msc->ep_out);
}
@ -127,20 +119,20 @@ bool tuh_msc_ready(uint8_t dev_addr)
//--------------------------------------------------------------------+
// PUBLIC API: SCSI COMMAND
//--------------------------------------------------------------------+
static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun)
{
static inline void cbw_init(msc_cbw_t* cbw, uint8_t lun) {
tu_memclr(cbw, sizeof(msc_cbw_t));
cbw->signature = MSC_CBW_SIGNATURE;
cbw->tag = 0x54555342; // TUSB
cbw->lun = lun;
}
bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
{
msch_interface_t* p_msc = get_itf(dev_addr);
bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const* cbw, void* data,
tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msch_interface_t* p_msc = get_itf(daddr);
TU_VERIFY(p_msc->configured);
// TODO claim endpoint
// claim endpoint
TU_VERIFY(usbh_edpt_claim(daddr, p_msc->ep_out));
p_msc->cbw = *cbw;
p_msc->stage = MSC_STAGE_CMD;
@ -148,15 +140,18 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu
p_msc->complete_cb = complete_cb;
p_msc->complete_arg = arg;
TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)));
if (!usbh_edpt_xfer(daddr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))) {
usbh_edpt_release(daddr, p_msc->ep_out);
return false;
}
return true;
}
bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
{
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->configured);
bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response,
tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->configured);
msc_cbw_t cbw;
cbw_init(&cbw, lun);
@ -169,8 +164,8 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r
return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg);
}
bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
{
bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response,
tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->mounted);
@ -181,18 +176,16 @@ bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* respons
cbw.dir = TUSB_DIR_IN_MASK;
cbw.cmd_len = sizeof(scsi_inquiry_t);
scsi_inquiry_t const cmd_inquiry =
{
.cmd_code = SCSI_CMD_INQUIRY,
.alloc_length = sizeof(scsi_inquiry_resp_t)
scsi_inquiry_t const cmd_inquiry = {
.cmd_code = SCSI_CMD_INQUIRY,
.alloc_length = sizeof(scsi_inquiry_resp_t)
};
memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len);
return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg);
}
bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
{
bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->configured);
@ -200,16 +193,16 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_
cbw_init(&cbw, lun);
cbw.total_bytes = 0;
cbw.dir = TUSB_DIR_OUT;
cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
cbw.command[0] = SCSI_CMD_TEST_UNIT_READY;
cbw.command[1] = lun; // according to wiki TODO need verification
cbw.dir = TUSB_DIR_OUT;
cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
cbw.command[0] = SCSI_CMD_TEST_UNIT_READY;
cbw.command[1] = lun; // according to wiki TODO need verification
return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb, arg);
}
bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
{
bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void* response,
tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msc_cbw_t cbw;
cbw_init(&cbw, lun);
@ -217,73 +210,64 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_ms
cbw.dir = TUSB_DIR_IN_MASK;
cbw.cmd_len = sizeof(scsi_request_sense_t);
scsi_request_sense_t const cmd_request_sense =
{
.cmd_code = SCSI_CMD_REQUEST_SENSE,
.alloc_length = 18
scsi_request_sense_t const cmd_request_sense = {
.cmd_code = SCSI_CMD_REQUEST_SENSE,
.alloc_length = 18
};
memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len);
return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg);
}
bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
{
bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void* buffer, uint32_t lba, uint16_t block_count,
tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->mounted);
msc_cbw_t cbw;
cbw_init(&cbw, lun);
cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
cbw.dir = TUSB_DIR_IN_MASK;
cbw.cmd_len = sizeof(scsi_read10_t);
cbw.total_bytes = block_count * p_msc->capacity[lun].block_size;
cbw.dir = TUSB_DIR_IN_MASK;
cbw.cmd_len = sizeof(scsi_read10_t);
scsi_read10_t const cmd_read10 =
{
.cmd_code = SCSI_CMD_READ_10,
.lba = tu_htonl(lba),
.block_count = tu_htons(block_count)
scsi_read10_t const cmd_read10 = {
.cmd_code = SCSI_CMD_READ_10,
.lba = tu_htonl(lba),
.block_count = tu_htons(block_count)
};
memcpy(cbw.command, &cmd_read10, cbw.cmd_len);
return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb, arg);
}
bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
{
bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const* buffer, uint32_t lba, uint16_t block_count,
tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->mounted);
msc_cbw_t cbw;
cbw_init(&cbw, lun);
cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
cbw.total_bytes = block_count * p_msc->capacity[lun].block_size;
cbw.dir = TUSB_DIR_OUT;
cbw.cmd_len = sizeof(scsi_write10_t);
scsi_write10_t const cmd_write10 =
{
.cmd_code = SCSI_CMD_WRITE_10,
.lba = tu_htonl(lba),
.block_count = tu_htons(block_count)
scsi_write10_t const cmd_write10 = {
.cmd_code = SCSI_CMD_WRITE_10,
.lba = tu_htonl(lba),
.block_count = tu_htons(block_count)
};
memcpy(cbw.command, &cmd_write10, cbw.cmd_len);
return tuh_msc_scsi_command(dev_addr, &cbw, (void*)(uintptr_t) buffer, complete_cb, arg);
return tuh_msc_scsi_command(dev_addr, &cbw, (void*) (uintptr_t) buffer, complete_cb, arg);
}
#if 0
// MSC interface Reset (not used now)
bool tuh_msc_reset(uint8_t dev_addr)
{
tusb_control_request_t const new_request =
{
.bmRequestType_bit =
{
bool tuh_msc_reset(uint8_t dev_addr) {
tusb_control_request_t const new_request = {
.bmRequestType_bit = {
.recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_OUT
@ -300,79 +284,71 @@ bool tuh_msc_reset(uint8_t dev_addr)
//--------------------------------------------------------------------+
// CLASS-USBH API
//--------------------------------------------------------------------+
void msch_init(void)
{
void msch_init(void) {
tu_memclr(_msch_itf, sizeof(_msch_itf));
}
void msch_close(uint8_t dev_addr)
{
TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, );
void msch_close(uint8_t dev_addr) {
TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX,);
msch_interface_t* p_msc = get_itf(dev_addr);
TU_VERIFY(p_msc->configured, );
TU_VERIFY(p_msc->configured,);
TU_LOG_DRV(" MSCh close addr = %d\r\n", dev_addr);
// invoke Application Callback
if (p_msc->mounted) {
if(tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr);
if (tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr);
}
tu_memclr(p_msc, sizeof(msch_interface_t));
}
bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
{
bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) {
msch_interface_t* p_msc = get_itf(dev_addr);
msc_cbw_t const * cbw = &p_msc->cbw;
msc_csw_t * csw = &p_msc->csw;
switch (p_msc->stage)
{
switch (p_msc->stage) {
case MSC_STAGE_CMD:
// Must be Command Block
TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t));
TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t));
if ( cbw->total_bytes && p_msc->buffer )
{
if (cbw->total_bytes && p_msc->buffer) {
// Data stage if any
p_msc->stage = MSC_STAGE_DATA;
uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out;
TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, (uint16_t) cbw->total_bytes));
}else
{
} else {
// Status stage
p_msc->stage = MSC_STAGE_STATUS;
TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t)));
}
break;
break;
case MSC_STAGE_DATA:
// Status stage
p_msc->stage = MSC_STAGE_STATUS;
TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t)));
break;
break;
case MSC_STAGE_STATUS:
// SCSI op is complete
p_msc->stage = MSC_STAGE_IDLE;
if (p_msc->complete_cb)
{
tuh_msc_complete_data_t const cb_data =
{
.cbw = cbw,
.csw = csw,
.scsi_data = p_msc->buffer,
.user_arg = p_msc->complete_arg
if (p_msc->complete_cb) {
tuh_msc_complete_data_t const cb_data = {
.cbw = cbw,
.csw = csw,
.scsi_data = p_msc->buffer,
.user_arg = p_msc->complete_arg
};
p_msc->complete_cb(dev_addr, &cb_data);
}
break;
break;
// unknown state
default: break;
// unknown state
default:
break;
}
return true;
@ -381,39 +357,35 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32
//--------------------------------------------------------------------+
// MSC Enumeration
//--------------------------------------------------------------------+
static void config_get_maxlun_complete (tuh_xfer_t* xfer);
static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data);
static void config_get_maxlun_complete(tuh_xfer_t* xfer);
static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data);
static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data);
static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data);
bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
{
bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len) {
(void) rhport;
TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass &&
MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol);
MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol);
// msc driver length is fixed
uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) +
desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
TU_ASSERT(drv_len <= max_len);
msch_interface_t* p_msc = get_itf(dev_addr);
tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf);
tusb_desc_endpoint_t const* ep_desc = (tusb_desc_endpoint_t const*) tu_desc_next(desc_itf);
for(uint32_t i=0; i<2; i++)
{
for (uint32_t i = 0; i < 2; i++) {
TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer);
TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc));
if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN )
{
if (TUSB_DIR_IN == tu_edpt_dir(ep_desc->bEndpointAddress)) {
p_msc->ep_in = ep_desc->bEndpointAddress;
}else
{
} else {
p_msc->ep_out = ep_desc->bEndpointAddress;
}
ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc);
ep_desc = (tusb_desc_endpoint_t const*) tu_desc_next(ep_desc);
}
p_msc->itf_num = desc_itf->bInterfaceNumber;
@ -430,32 +402,31 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) {
//------------- Get Max Lun -------------//
TU_LOG_DRV("MSC Get Max Lun\r\n");
tusb_control_request_t const request = {
.bmRequestType_bit = {
.recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_IN
},
.bRequest = MSC_REQ_GET_MAX_LUN,
.wValue = 0,
.wIndex = itf_num,
.wLength = 1
.bmRequestType_bit = {
.recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_IN
},
.bRequest = MSC_REQ_GET_MAX_LUN,
.wValue = 0,
.wIndex = itf_num,
.wLength = 1
};
tuh_xfer_t xfer = {
.daddr = dev_addr,
.ep_addr = 0,
.setup = &request,
.buffer = _msch_buffer,
.complete_cb = config_get_maxlun_complete,
.user_data = 0
.daddr = dev_addr,
.ep_addr = 0,
.setup = &request,
.buffer = _msch_buffer,
.complete_cb = config_get_maxlun_complete,
.user_data = 0
};
TU_ASSERT(tuh_control_xfer(&xfer));
return true;
}
static void config_get_maxlun_complete (tuh_xfer_t* xfer)
{
static void config_get_maxlun_complete(tuh_xfer_t* xfer) {
uint8_t const daddr = xfer->daddr;
msch_interface_t* p_msc = get_itf(daddr);
@ -471,18 +442,16 @@ static void config_get_maxlun_complete (tuh_xfer_t* xfer)
tuh_msc_test_unit_ready(daddr, lun, config_test_unit_ready_complete, 0);
}
static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data)
{
static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) {
msc_cbw_t const* cbw = cb_data->cbw;
msc_csw_t const* csw = cb_data->csw;
if (csw->status == 0)
{
if (csw->status == 0) {
// Unit is ready, read its capacity
TU_LOG_DRV("SCSI Read Capacity\r\n");
tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete, 0);
}else
{
tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer),
config_read_capacity_complete, 0);
} else {
// Note: During enumeration, some device fails Test Unit Ready and require a few retries
// with Request Sense to start working !!
// TODO limit number of retries
@ -493,8 +462,7 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_d
return true;
}
static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data)
{
static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) {
msc_cbw_t const* cbw = cb_data->cbw;
msc_csw_t const* csw = cb_data->csw;
@ -503,8 +471,7 @@ static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_dat
return true;
}
static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data)
{
static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) {
msc_cbw_t const* cbw = cb_data->cbw;
msc_csw_t const* csw = cb_data->csw;

View File

@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
#ifndef _TUSB_MSC_HOST_H_
#define _TUSB_MSC_HOST_H_
#ifndef TUSB_MSC_HOST_H_
#define TUSB_MSC_HOST_H_
#include "msc.h"
@ -73,7 +73,7 @@ uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun);
// Perform a full SCSI command (cbw, data, csw) in non-blocking manner.
// Complete callback is invoked when SCSI op is complete.
// return true if success, false if there is already pending operation.
bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg);
bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg);
// Perform SCSI Inquiry command
// Complete callback is invoked when SCSI op is complete.
@ -123,4 +123,4 @@ bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, ui
}
#endif
#endif /* _TUSB_MSC_HOST_H_ */
#endif

View File

@ -75,8 +75,6 @@
#include "tusb_types.h"
#include "tusb_debug.h"
#include "tusb_timeout.h" // TODO remove
//--------------------------------------------------------------------+
// Optional API implemented by application if needed
// TODO move to a more ovious place/file

View File

@ -56,12 +56,8 @@
* #define TU_VERIFY(cond) if(cond) return false;
* #define TU_VERIFY(cond,ret) if(cond) return ret;
*
* #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;}
* #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;}
*
* #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;}
* #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;}
*
*------------------------------------------------------------------*/
#ifdef __cplusplus
@ -97,40 +93,23 @@
#define TU_BREAKPOINT() do {} while (0)
#endif
/*------------------------------------------------------------------*/
/* Macro Generator
*------------------------------------------------------------------*/
// Helper to implement optional parameter for TU_VERIFY Macro family
#define _GET_3RD_ARG(arg1, arg2, arg3, ...) arg3
#define _GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
/*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/
#define TU_VERIFY_DEFINE(_cond, _handler, _ret) do \
{ \
if ( !(_cond) ) { _handler; return _ret; } \
} while(0)
/*------------------------------------------------------------------*/
/* TU_VERIFY
* - TU_VERIFY_1ARGS : return false if failed
* - TU_VERIFY_2ARGS : return provided value if failed
*------------------------------------------------------------------*/
#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false)
#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret)
#define TU_VERIFY_DEFINE(_cond, _ret) \
do { \
if ( !(_cond) ) { return _ret; } \
} while(0)
#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__)
#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, false)
#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _ret)
/*------------------------------------------------------------------*/
/* TU_VERIFY WITH HANDLER
* - TU_VERIFY_HDLR_2ARGS : execute handler, return false if failed
* - TU_VERIFY_HDLR_3ARGS : execute handler, return provided error if failed
*------------------------------------------------------------------*/
#define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false)
#define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret)
#define TU_VERIFY_HDLR(...) _GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__)
#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
/*------------------------------------------------------------------*/
/* ASSERT
@ -138,19 +117,20 @@
* - 1 arg : return false if failed
* - 2 arg : return error if failed
*------------------------------------------------------------------*/
#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), false)
#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret)
#define TU_ASSERT_DEFINE(_cond, _ret) \
do { \
if ( !(_cond) ) { _MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
} while(0)
#define TU_ASSERT_1ARGS(_cond) TU_ASSERT_DEFINE(_cond, false)
#define TU_ASSERT_2ARGS(_cond, _ret) TU_ASSERT_DEFINE(_cond, _ret)
#ifndef TU_ASSERT
#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__)
#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
#endif
/*------------------------------------------------------------------*/
/* ASSERT HDLR
*------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif /* TUSB_VERIFY_H_ */
#endif

View File

@ -131,7 +131,7 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) TU_AT
bool hcd_init(uint8_t rhport);
// Interrupt Handler
void hcd_int_handler(uint8_t rhport);
void hcd_int_handler(uint8_t rhport, bool in_isr);
// Enable USB interrupt
void hcd_int_enable (uint8_t rhport);

View File

@ -817,6 +817,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
}
// Submit an transfer
// TODO call usbh_edpt_release if failed
bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes,
tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
@ -1713,19 +1714,16 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
return true;
}
void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
{
void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) {
usbh_device_t* dev = get_device(dev_addr);
for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++)
{
for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) {
// continue with next valid interface
// IAD binding interface such as CDCs should return itf_num + 1 when complete
// with usbh_driver_set_config_complete()
uint8_t const drv_id = dev->itf2drv[itf_num];
usbh_class_driver_t const * driver = get_driver(drv_id);
if (driver)
{
if (driver) {
TU_LOG_USBH("%s set config: itf = %u\r\n", driver->name, itf_num);
driver->set_config(dev_addr, itf_num);
break;
@ -1733,23 +1731,19 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
}
// all interface are configured
if (itf_num == CFG_TUH_INTERFACE_MAX)
{
if (itf_num == CFG_TUH_INTERFACE_MAX) {
enum_full_complete();
if (is_hub_addr(dev_addr))
{
if (is_hub_addr(dev_addr)) {
TU_LOG(CFG_TUH_LOG_LEVEL, "HUB address = %u is mounted\r\n", dev_addr);
}else
{
}else {
// Invoke callback if available
if (tuh_mount_cb) tuh_mount_cb(dev_addr);
}
}
}
static void enum_full_complete(void)
{
static void enum_full_complete(void) {
// mark enumeration as complete
_dev0.enumerating = 0;

View File

@ -124,11 +124,16 @@ void tuh_task(void) {
bool tuh_task_event_ready(void);
#ifndef _TUSB_HCD_H_
extern void hcd_int_handler(uint8_t rhport);
extern void hcd_int_handler(uint8_t rhport, bool in_isr);
#endif
// Interrupt handler, name alias to HCD
#define tuh_int_handler hcd_int_handler
// Interrupt handler alias to HCD with in_isr as optional parameter
// - tuh_int_handler(rhport) --> hcd_int_handler(rhport, true)
// - tuh_int_handler(rhport, in_isr) --> hcd_int_handler(rhport, in_isr)
// Note: this is similar to TU_VERIFY(), _GET_3RD_ARG() is defined in tusb_verify.h
#define _tuh_int_handler_1arg(_rhport) hcd_int_handler(_rhport, true)
#define _tuh_int_hanlder_2arg(_rhport, _in_isr) hcd_int_handler(_rhport, _in_isr)
#define tuh_int_handler(...) _GET_3RD_ARG(__VA_ARGS__, _tuh_int_hanlder_2arg, _tuh_int_handler_1arg, _dummy)(__VA_ARGS__)
// Check if roothub port is initialized and active as a host
bool tuh_rhport_is_active(uint8_t rhport);

View File

@ -210,16 +210,21 @@ static max3421_data_t _hcd_data;
// API: SPI transfer with MAX3421E, must be implemented by application
//--------------------------------------------------------------------+
void tuh_max3421_spi_cs_api(uint8_t rhport, bool active);
bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len);
void tuh_max3421_int_api(uint8_t rhport, bool enabled);
// API to control MAX3421 SPI CS
extern void tuh_max3421_spi_cs_api(uint8_t rhport, bool active);
static void handle_connect_irq(uint8_t rhport, bool in_isr);
static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr);
// API to transfer data with MAX3421 SPI
// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
extern bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes);
// API to enable/disable MAX3421 INTR pin interrupt
extern void tuh_max3421_int_api(uint8_t rhport, bool enabled);
//--------------------------------------------------------------------+
// SPI Helper
//--------------------------------------------------------------------+
static void handle_connect_irq(uint8_t rhport, bool in_isr);
static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr);
static void max3421_spi_lock(uint8_t rhport, bool in_isr) {
// disable interrupt and mutex lock (for pre-emptive RTOS) if not in_isr
@ -249,9 +254,9 @@ static void fifo_write(uint8_t rhport, uint8_t reg, uint8_t const * buffer, uint
max3421_spi_lock(rhport, in_isr);
tuh_max3421_spi_xfer_api(rhport, &reg, 1, &hirq, 1);
tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, buffer, len, NULL, 0);
tuh_max3421_spi_xfer_api(rhport, buffer, NULL, len);
max3421_spi_unlock(rhport, in_isr);
@ -263,9 +268,9 @@ static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_is
max3421_spi_lock(rhport, in_isr);
tuh_max3421_spi_xfer_api(rhport, &reg, 1, &hirq, 0);
tuh_max3421_spi_xfer_api(rhport, &reg, &hirq, 1);
_hcd_data.hirq = hirq;
tuh_max3421_spi_xfer_api(rhport, NULL, 0, buffer, len);
tuh_max3421_spi_xfer_api(rhport, NULL, buffer, len);
max3421_spi_unlock(rhport, in_isr);
}
@ -276,7 +281,7 @@ static void reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr) {
max3421_spi_lock(rhport, in_isr);
tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2);
tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
max3421_spi_unlock(rhport, in_isr);
@ -290,7 +295,7 @@ static uint8_t reg_read(uint8_t rhport, uint8_t reg, bool in_isr) {
max3421_spi_lock(rhport, in_isr);
bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2);
bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2);
max3421_spi_unlock(rhport, in_isr);
@ -428,8 +433,8 @@ bool hcd_init(uint8_t rhport) {
reg_write(rhport, PINCTL_ADDR, PINCTL_FDUPSPI, false);
// V1 is 0x01, V2 is 0x12, V3 is 0x13
// uint8_t const revision = reg_read(rhport, REVISION_ADDR, false);
// TU_LOG2_HEX(revision);
// uint8_t const revision = reg_read(rhport, REVISION_ADDR, false);
// TU_LOG2_HEX(revision);
// reset
reg_write(rhport, USBCTL_ADDR, USBCTL_CHIPRES, false);
@ -693,9 +698,7 @@ static void handle_connect_irq(uint8_t rhport, bool in_isr) {
// port reset anyway, this will help to stable bus signal for next connection
reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, in_isr);
hcd_event_device_remove(rhport, in_isr);
reg_write(rhport, HCTL_ADDR, 0, in_isr);
break;
@ -721,13 +724,12 @@ static void handle_connect_irq(uint8_t rhport, bool in_isr) {
free_ep(daddr);
hcd_event_device_attach(rhport, in_isr);
break;
}
}
}
static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl) {
static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl, bool in_isr) {
uint8_t const ep_addr = tu_edpt_addr(ep->ep_num, ep->ep_dir);
// save data toggle
@ -738,20 +740,20 @@ static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t re
}
ep->xfer_pending = 0;
hcd_event_xfer_complete(ep->daddr, ep_addr, ep->xferred_len, result, true);
hcd_event_xfer_complete(ep->daddr, ep_addr, ep->xferred_len, result, in_isr);
// Find next pending endpoint
max3421_ep_t *next_ep = find_next_pending_ep(ep);
if (next_ep) {
xact_inout(rhport, next_ep, true, true);
xact_inout(rhport, next_ep, true, in_isr);
}else {
// no more pending
atomic_flag_clear(&_hcd_data.busy);
}
}
static void handle_xfer_done(uint8_t rhport) {
uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true);
static void handle_xfer_done(uint8_t rhport, bool in_isr) {
uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, in_isr);
uint8_t const hresult = hrsl & HRSL_RESULT_MASK;
uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK;
@ -774,17 +776,17 @@ static void handle_xfer_done(uint8_t rhport) {
case HRSL_NAK:
if (ep_num == 0) {
// NAK on control, retry immediately
hxfr_write(rhport, _hcd_data.hxfr, true);
hxfr_write(rhport, _hcd_data.hxfr, in_isr);
}else {
// NAK on non-control, find next pending to switch
max3421_ep_t *next_ep = find_next_pending_ep(ep);
if (ep == next_ep) {
// this endpoint is only one pending, retry immediately
hxfr_write(rhport, _hcd_data.hxfr, true);
hxfr_write(rhport, _hcd_data.hxfr, in_isr);
}else if (next_ep) {
// switch to next pending TODO could have issue with double buffered if not clear previously out data
xact_inout(rhport, next_ep, true, true);
xact_inout(rhport, next_ep, true, in_isr);
}else {
TU_ASSERT(false,);
}
@ -802,7 +804,7 @@ static void handle_xfer_done(uint8_t rhport) {
}
if (xfer_result != XFER_RESULT_SUCCESS) {
xfer_complete_isr(rhport, ep, xfer_result, hrsl);
xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr);
return;
}
@ -814,10 +816,10 @@ static void handle_xfer_done(uint8_t rhport) {
// short packet or all bytes transferred
if ( ep->xfer_complete ) {
xfer_complete_isr(rhport, ep, xfer_result, hrsl);
xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr);
}else {
// more to transfer
hxfr_write(rhport, _hcd_data.hxfr, true);
hxfr_write(rhport, _hcd_data.hxfr, in_isr);
}
} else {
// SETUP or OUT transfer
@ -835,10 +837,10 @@ static void handle_xfer_done(uint8_t rhport) {
ep->buf += xact_len;
if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) {
xfer_complete_isr(rhport, ep, xfer_result, hrsl);
xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr);
} else {
// more to transfer
xact_out(rhport, ep, false, true);
xact_out(rhport, ep, false, in_isr);
}
}
}
@ -862,9 +864,9 @@ void print_hirq(uint8_t hirq) {
#define print_hirq(hirq)
#endif
// Interrupt Handler
void hcd_int_handler(uint8_t rhport) {
uint8_t hirq = reg_read(rhport, HIRQ_ADDR, true) & _hcd_data.hien;
// Interrupt handler
void hcd_int_handler(uint8_t rhport, bool in_isr) {
uint8_t hirq = reg_read(rhport, HIRQ_ADDR, in_isr) & _hcd_data.hien;
if (!hirq) return;
// print_hirq(hirq);
@ -873,7 +875,7 @@ void hcd_int_handler(uint8_t rhport) {
}
if (hirq & HIRQ_CONDET_IRQ) {
handle_connect_irq(rhport, true);
handle_connect_irq(rhport, in_isr);
}
// queue more transfer in handle_xfer_done() can cause hirq to be set again while external IRQ may not catch and/or
@ -882,21 +884,21 @@ void hcd_int_handler(uint8_t rhport) {
if ( hirq & HIRQ_RCVDAV_IRQ ) {
uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK;
max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, 1);
uint8_t xact_len;
uint8_t xact_len = 0;
// RCVDAV_IRQ can trigger 2 times (dual buffered)
while ( hirq & HIRQ_RCVDAV_IRQ ) {
uint8_t rcvbc = reg_read(rhport, RCVBC_ADDR, true);
uint8_t rcvbc = reg_read(rhport, RCVBC_ADDR, in_isr);
xact_len = (uint8_t) tu_min16(rcvbc, ep->total_len - ep->xferred_len);
if ( xact_len ) {
fifo_read(rhport, ep->buf, xact_len, true);
fifo_read(rhport, ep->buf, xact_len, in_isr);
ep->buf += xact_len;
ep->xferred_len += xact_len;
}
// ack RCVDVAV IRQ
hirq_write(rhport, HIRQ_RCVDAV_IRQ, true);
hirq = reg_read(rhport, HIRQ_ADDR, true);
hirq_write(rhport, HIRQ_RCVDAV_IRQ, in_isr);
hirq = reg_read(rhport, HIRQ_ADDR, in_isr);
}
if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) {
@ -905,17 +907,17 @@ void hcd_int_handler(uint8_t rhport) {
}
if ( hirq & HIRQ_HXFRDN_IRQ ) {
hirq_write(rhport, HIRQ_HXFRDN_IRQ, true);
handle_xfer_done(rhport);
hirq_write(rhport, HIRQ_HXFRDN_IRQ, in_isr);
handle_xfer_done(rhport, in_isr);
}
hirq = reg_read(rhport, HIRQ_ADDR, true);
hirq = reg_read(rhport, HIRQ_ADDR, in_isr);
}
// clear all interrupt except SNDBAV_IRQ (never clear by us). Note RCVDAV_IRQ, HXFRDN_IRQ already clear while processing
hirq &= ~HIRQ_SNDBAV_IRQ;
if ( hirq ) {
hirq_write(rhport, hirq, true);
hirq_write(rhport, hirq, in_isr);
}
}

View File

@ -656,8 +656,8 @@ void process_period_xfer_isr(uint8_t rhport, uint32_t interval_ms)
}
//------------- Host Controller Driver's Interrupt Handler -------------//
void hcd_int_handler(uint8_t rhport)
{
void hcd_int_handler(uint8_t rhport, bool in_isr) {
(void) in_isr;
ehci_registers_t* regs = ehci_data.regs;
uint32_t const int_status = regs->status;

View File

@ -847,8 +847,10 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
/*-------------------------------------------------------------------
* ISR
*-------------------------------------------------------------------*/
void hcd_int_handler(uint8_t rhport)
void hcd_int_handler(uint8_t rhport, bool in_isr)
{
(void) in_isr;
uint_fast8_t is, txis, rxis;
is = USB0->IS; /* read and clear interrupt status */

View File

@ -447,6 +447,10 @@ void hcd_port_reset(uint8_t rhport)
_hcd.need_reset = false;
}
void hcd_port_reset_end(uint8_t rhport) {
(void) rhport;
}
tusb_speed_t hcd_port_speed_get(uint8_t rhport)
{
(void)rhport;
@ -583,8 +587,9 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
/*--------------------------------------------------------------------+
* ISR
*--------------------------------------------------------------------+*/
void hcd_int_handler(uint8_t rhport)
void hcd_int_handler(uint8_t rhport, bool in_isr)
{
(void) in_isr;
uint32_t is = KHCI->ISTAT;
uint32_t msk = KHCI->INTEN;

View File

@ -667,8 +667,9 @@ static void done_queue_isr(uint8_t hostid)
}
}
void hcd_int_handler(uint8_t hostid)
{
void hcd_int_handler(uint8_t hostid, bool in_isr) {
(void) in_isr;
uint32_t const int_en = OHCI_REG->interrupt_enable;
uint32_t const int_status = OHCI_REG->interrupt_status & int_en;

View File

@ -252,9 +252,9 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void)
}
}
void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport)
{
void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport, bool in_isr) {
(void) rhport;
(void) in_isr;
hcd_rp2040_irq();
}

View File

@ -771,8 +771,9 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
//--------------------------------------------------------------------+
// ISR
//--------------------------------------------------------------------+
void hcd_int_handler(uint8_t rhport)
{
void hcd_int_handler(uint8_t rhport, bool in_isr) {
(void) in_isr;
rusb2_reg_t* rusb = RUSB2_REG(rhport);
unsigned is0 = rusb->INTSTS0;
unsigned is1 = rusb->INTSTS1;

View File

@ -51,8 +51,9 @@ bool hcd_init(uint8_t rhport) {
}
// Interrupt Handler
void hcd_int_handler(uint8_t rhport) {
void hcd_int_handler(uint8_t rhport, bool in_isr) {
(void) rhport;
(void) in_isr;
}
// Enable USB interrupt

View File

@ -17,3 +17,10 @@ TINYUSB_SRC_C += \
src/class/usbtmc/usbtmc_device.c \
src/class/video/video_device.c \
src/class/vendor/vendor_device.c \
src/host/usbh.c \
src/host/hub.c \
src/class/cdc/cdc_host.c \
src/class/hid/hid_host.c \
src/class/msc/msc_host.c \
src/class/vendor/vendor_host.c \
src/typec/usbc.c \

View File

@ -66,7 +66,7 @@
#endif
#else
#ifndef tuh_int_handler
#define tuh_int_handler(_x)
#define tuh_int_handler(...)
#endif
#endif
@ -123,7 +123,7 @@
#endif
#else
#ifndef tud_int_handler
#define tud_int_handler(_x)
#define tud_int_handler(...)
#endif
#endif

View File

@ -424,11 +424,11 @@
//------------- CLASS -------------//
#ifndef CFG_TUH_HUB
#define CFG_TUH_HUB 0
#define CFG_TUH_HUB 0
#endif
#ifndef CFG_TUH_CDC
#define CFG_TUH_CDC 0
#define CFG_TUH_CDC 0
#endif
#ifndef CFG_TUH_CDC_FTDI
@ -442,34 +442,38 @@
#endif
#ifndef CFG_TUH_HID
#define CFG_TUH_HID 0
#define CFG_TUH_HID 0
#endif
#ifndef CFG_TUH_MIDI
#define CFG_TUH_MIDI 0
#define CFG_TUH_MIDI 0
#endif
#ifndef CFG_TUH_MSC
#define CFG_TUH_MSC 0
#define CFG_TUH_MSC 0
#endif
#ifndef CFG_TUH_VENDOR
#define CFG_TUH_VENDOR 0
#define CFG_TUH_VENDOR 0
#endif
#ifndef CFG_TUH_API_EDPT_XFER
#define CFG_TUH_API_EDPT_XFER 0
#define CFG_TUH_API_EDPT_XFER 0
#endif
// Enable PIO-USB software host controller
#ifndef CFG_TUH_RPI_PIO_USB
#define CFG_TUH_RPI_PIO_USB 0
#define CFG_TUH_RPI_PIO_USB 0
#endif
#ifndef CFG_TUD_RPI_PIO_USB
#define CFG_TUD_RPI_PIO_USB 0
#define CFG_TUD_RPI_PIO_USB 0
#endif
// MAX3421 Host controller option
#ifndef CFG_TUH_MAX3421
#define CFG_TUH_MAX3421 0
#endif
//--------------------------------------------------------------------+
// TypeC Options (Default)

View File

@ -17,8 +17,8 @@ exit_status = 0
total_time = time.monotonic()
build_format = '| {:23} | {:30} | {:18} | {:7} | {:6} | {:6} |'
build_separator = '-' * 100
build_format = '| {:30} | {:30} | {:18} | {:7} | {:6} | {:6} |'
build_separator = '-' * 107
def filter_with_input(mylist):
if len(sys.argv) > 1:
@ -26,12 +26,9 @@ def filter_with_input(mylist):
if len(input_args) > 0:
mylist[:] = input_args
# Build all examples if not specified
all_examples = []
for entry in os.scandir("examples/device"):
# Only includes example with CMakeLists.txt for esp32s, and skip board_test to speed up ci
if entry.is_dir() and os.path.exists(entry.path + "/sdkconfig.defaults") and entry.name != 'board_test':
all_examples.append(entry.name)
all_examples = [entry.replace('examples/', '') for entry in glob.glob("examples/*/*_freertos")]
filter_with_input(all_examples)
all_examples.sort()
@ -46,32 +43,41 @@ 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 = "-"
# Check if board is skipped
if build_utils.skip_example(example, board):
success = SKIPPED
skip_count += 1
print(build_format.format(example, board, success, '-', flash_size, sram_size))
if r.returncode == 0:
success = SUCCEEDED
success_count += 1
#(flash_size, sram_size) = build_size(example, board)
else:
subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
build_result = subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
exit_status = r.returncode
success = FAILED
fail_count += 1
if build_result.returncode == 0:
success = SUCCEEDED
success_count += 1
(flash_size, sram_size) = build_size(example, board)
else:
exit_status = build_result.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"))
build_duration = time.monotonic() - start_time
print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size))
if build_result.returncode != 0:
print(build_result.stdout.decode("utf-8"))
def build_size(example, board):
#elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board)
@ -82,6 +88,7 @@ def build_size(example, board):
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)

View File

@ -1,51 +1,84 @@
#!/usr/bin/python3
import os
import sys
import xml.dom.minidom as XML
import glob
# Read base configuration
base = ""
with open("iar_template.ipcf") as f:
base = f.read()
def Main():
# Read base configuration
base = ""
with open("iar_template.ipcf") as f:
base = f.read()
# Enumerate all device/host examples
dir_1 = os.listdir("../examples")
for dir_2 in dir_1:
if os.path.isdir("../examples/{}".format(dir_2)):
print(dir_2)
examples = os.listdir("../examples/{}".format(dir_2))
for example in examples:
if os.path.isdir("../examples/{}/{}".format(dir_2, example)):
print("../examples/{}/{}".format(dir_2, example))
conf = XML.parseString(base)
files = conf.getElementsByTagName("files")[0]
inc = conf.getElementsByTagName("includePath")[0]
# Add bsp inc
path = conf.createElement('path')
path_txt = conf.createTextNode("$TUSB_DIR$/hw")
path.appendChild(path_txt)
inc.appendChild(path)
# Add board.c/.h
grp = conf.createElement('group')
grp.setAttribute("name", "bsp")
path = conf.createElement('path')
path_txt = conf.createTextNode("$TUSB_DIR$/hw/bsp/board.c")
path.appendChild(path_txt)
grp.appendChild(path)
files.appendChild(grp)
# Add example's .c/.h
grp = conf.createElement('group')
grp.setAttribute("name", "example")
for file in os.listdir("../examples/{}/{}/src".format(dir_2, example)):
if file.endswith(".c") or file.endswith(".h"):
path = conf.createElement('path')
path.setAttribute("copyTo", "$PROJ_DIR$/{}".format(file))
path_txt = conf.createTextNode("$TUSB_DIR$/examples/{0}/{1}/src/{2}".format(dir_2, example, file))
path.appendChild(path_txt)
grp.appendChild(path)
files.appendChild(grp)
cfg_str = conf.toprettyxml()
cfg_str = '\n'.join([s for s in cfg_str.splitlines() if s.strip()])
#print(cfg_str)
with open("../examples/{0}/{1}/iar_{1}.ipcf".format(dir_2, example), 'w') as f:
f.write(cfg_str)
# Enumerate all device/host examples
dir_1 = os.listdir("../examples")
for dir_2 in dir_1:
if os.path.isdir("../examples/{}".format(dir_2)):
print(dir_2)
examples = os.listdir("../examples/{}".format(dir_2))
for example in examples:
if os.path.isdir("../examples/{}/{}".format(dir_2, example)):
print("../examples/{}/{}".format(dir_2, example))
conf = XML.parseString(base)
files = conf.getElementsByTagName("files")[0]
inc = conf.getElementsByTagName("includePath")[0]
# Add bsp inc
path = conf.createElement('path')
path_txt = conf.createTextNode("$TUSB_DIR$/hw")
path.appendChild(path_txt)
inc.appendChild(path)
# Add board.c/.h
grp = conf.createElement('group')
grp.setAttribute("name", "bsp")
path = conf.createElement('path')
path_txt = conf.createTextNode("$TUSB_DIR$/hw/bsp/board.c")
path.appendChild(path_txt)
grp.appendChild(path)
files.appendChild(grp)
# Add example's .c/.h
grp = conf.createElement('group')
grp.setAttribute("name", "example")
for file in os.listdir("../examples/{}/{}/src".format(dir_2, example)):
if file.endswith(".c") or file.endswith(".h"):
path = conf.createElement('path')
path.setAttribute("copyTo", "$PROJ_DIR$/{}".format(file))
path_txt = conf.createTextNode("$TUSB_DIR$/examples/{0}/{1}/src/{2}".format(dir_2, example, file))
path.appendChild(path_txt)
grp.appendChild(path)
files.appendChild(grp)
cfg_str = conf.toprettyxml()
cfg_str = '\n'.join([s for s in cfg_str.splitlines() if s.strip()])
#print(cfg_str)
with open("../examples/{0}/{1}/iar_{1}.ipcf".format(dir_2, example), 'w') as f:
f.write(cfg_str)
def ListPath(path, blacklist=[]):
# Get all .c files
files = glob.glob(f'../{path}/**/*.c', recursive=True)
# Filter
files = [x for x in files if all(y not in x for y in blacklist)]
# Get common dir list
dirs = []
for file in files:
dir = os.path.dirname(file)
if dir not in dirs:
dirs.append(dir)
# Print .c grouped by dir
for dir in dirs:
print('<group name="' + dir.replace('../', '').replace('\\','/') + '">')
for file in files:
if os.path.dirname(file) == dir:
print(' <path>$TUSB_DIR$/' + file.replace('../','').replace('\\','/')+'</path>')
print('</group>')
def List():
ListPath('src', [ 'template.c', 'dcd_synopsys.c', 'dcd_esp32sx.c' ])
ListPath('lib/SEGGER_RTT')
if __name__ == "__main__":
if (len(sys.argv) > 1):
if (sys.argv[1] == 'l'):
List()
else:
Main()

View File

@ -4,166 +4,176 @@
<includePath>
<path>$TUSB_DIR$/src</path>
<path>$TUSB_DIR$/lib/SEGGER_RTT/RTT</path>
<path>$TUSB_DIR$/lib/SEGGER_RTT/Config</path>
<path>$PROJ_DIR$</path>
</includePath>
<files>
<group name="src/device">
<path>$TUSB_DIR$/src/device/usbd.c</path>
<path>$TUSB_DIR$/src/device/usbd_control.c</path>
</group>
<group name="src/common">
<path>$TUSB_DIR$/src/common/tusb_fifo.c</path>
</group>
<group name="src/class/audio">
<path>$TUSB_DIR$/src/class/audio/audio_device.c</path>
</group>
<group name="src/class/bth">
<path>$TUSB_DIR$/src/class/bth/bth_device.c</path>
</group>
<group name="src/class/cdc">
<path>$TUSB_DIR$/src/class/cdc/cdc_device.c</path>
<path>$TUSB_DIR$/src/class/cdc/cdc_host.c</path>
<path>$TUSB_DIR$/src/class/cdc/cdc_rndis_host.c</path>
</group>
<group name="src/class/dfu">
<path>$TUSB_DIR$/src/class/dfu/dfu_device.c</path>
<path>$TUSB_DIR$/src/class/dfu/dfu_rt_device.c</path>
</group>
<group name="src/class/hid">
<path>$TUSB_DIR$/src/class/hid/hid_device.c</path>
<path>$TUSB_DIR$/src/class/hid/hid_host.c</path>
</group>
<group name="src/class/midi">
<path>$TUSB_DIR$/src/class/midi/midi_device.c</path>
</group>
<group name="src/class/msc">
<path>$TUSB_DIR$/src/class/msc/msc_device.c</path>
<path>$TUSB_DIR$/src/class/msc/msc_host.c</path>
</group>
<group name="src/class/net">
<path>$TUSB_DIR$/src/class/net/ecm_rndis_device.c</path>
<path>$TUSB_DIR$/src/class/net/ncm_device.c</path>
</group>
<group name="src/class/usbtmc">
<path>$TUSB_DIR$/src/class/usbtmc/usbtmc_device.c</path>
</group>
<group name="src/class/vendor">
<path>$TUSB_DIR$/src/class/vendor/vendor_device.c</path>
<path>$TUSB_DIR$/src/class/vendor/vendor_host.c</path>
</group>
<group name="src">
<path>$TUSB_DIR$/src/tusb.c</path>
</group>
<group name="src/host">
<path>$TUSB_DIR$/src/host/hub.c</path>
<path>$TUSB_DIR$/src/host/usbh.c</path>
</group>
<group name="src/portable/bridgetek/ft9xx">
<path>$TUSB_DIR$/src/portable/bridgetek/ft9xx/dcd_ft9xx.c</path>
</group>
<group name="src/portable/chipidea/ci_hs">
<path>$TUSB_DIR$/src/portable/chipidea/ci_hs/dcd_ci_hs.c</path>
<path>$TUSB_DIR$/src/portable/chipidea/ci_hs/hcd_ci_hs.c</path>
</group>
<group name="src/portable/synopsys/dwc2">
<path>$TUSB_DIR$/src/portable/synopsys/dwc2/dcd_dwc2.c</path>
</group>
<group name="src/portable/dialog/da146xx">
<path>$TUSB_DIR$/src/portable/dialog/da146xx/dcd_da146xx.c</path>
</group>
<group name="src/portable/ehci">
<path>$TUSB_DIR$/src/portable/ehci/ehci.c</path>
</group>
<group name="src/portable/espressif/esp32sx">
<path>$TUSB_DIR$/src/portable/espressif/esp32sx/dcd_esp32sx.c</path>
</group>
<group name="src/portable/mentor/musb">
<path>$TUSB_DIR$/src/portable/mentor/musb/dcd_musb.c</path>
<path>$TUSB_DIR$/src/portable/mentor/musb/hcd_musb.c</path>
</group>
<group name="src/portable/microchip/samd">
<path>$TUSB_DIR$/src/portable/microchip/samd/dcd_samd.c</path>
</group>
<group name="src/portable/microchip/samg">
<path>$TUSB_DIR$/src/portable/microchip/samg/dcd_samg.c</path>
</group>
<group name="src/portable/microchip/samx7x">
<path>$TUSB_DIR$/src/portable/microchip/samx7x/dcd_samx7x.c</path>
</group>
<group name="src/portable/microchip/pic">
<path>$TUSB_DIR$/src/portable/microchip/pic/dcd_pic.c</path>
</group>
<group name="src/portable/microchip/pic32mz">
<path>$TUSB_DIR$/src/portable/microchip/pic32mz/dcd_pic32mz.c</path>
</group>
<group name="src/portable/mindmotion/mm32">
<path>$TUSB_DIR$/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c</path>
</group>
<group name="src/portable/nordic/nrf5x">
<path>$TUSB_DIR$/src/portable/nordic/nrf5x/dcd_nrf5x.c</path>
</group>
<group name="src/portable/nuvoton/nuc120">
<path>$TUSB_DIR$/src/portable/nuvoton/nuc120/dcd_nuc120.c</path>
</group>
<group name="src/portable/nuvoton/nuc121">
<path>$TUSB_DIR$/src/portable/nuvoton/nuc121/dcd_nuc121.c</path>
</group>
<group name="src/portable/nuvoton/nuc505">
<path>$TUSB_DIR$/src/portable/nuvoton/nuc505/dcd_nuc505.c</path>
</group>
<group name="src/portable/nxp/khci">
<path>$TUSB_DIR$/src/portable/nxp/khci/dcd_khci.c</path>
<path>$TUSB_DIR$/src/portable/nxp/khci/hcd_khci.c</path>
</group>
<group name="src/portable/nxp/lpc17_40">
<path>$TUSB_DIR$/src/portable/nxp/lpc17_40/dcd_lpc17_40.c</path>
<path>$TUSB_DIR$/src/portable/nxp/lpc17_40/hcd_lpc17_40.c</path>
</group>
<group name="src/portable/nxp/lpc_ip3511">
<path>$TUSB_DIR$/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c</path>
</group>
<group name="src/portable/nxp/transdimension">
<path>$TUSB_DIR$/src/portable/nxp/transdimension/dcd_transdimension.c</path>
<path>$TUSB_DIR$/src/portable/nxp/transdimension/hcd_transdimension.c</path>
</group>
<group name="src/portable/ohci">
<path>$TUSB_DIR$/src/portable/ohci/ohci.c</path>
</group>
<group name="src/portable/raspberrypi/pio_usb">
<path>$TUSB_DIR$/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c</path>
<path>$TUSB_DIR$/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c</path>
</group>
<group name="src/portable/raspberrypi/rp2040">
<path>$TUSB_DIR$/src/portable/raspberrypi/rp2040/dcd_rp2040.c</path>
<path>$TUSB_DIR$/src/portable/raspberrypi/rp2040/hcd_rp2040.c</path>
</group>
<group name="src/portable/renesas/rusb2">
<path>$TUSB_DIR$/src/portable/renesas/rusb2/dcd_rusb2.c</path>
<path>$TUSB_DIR$/src/portable/renesas/rusb2/hcd_rusb2.c</path>
</group>
<group name="src/portable/sony/cxd56">
<path>$TUSB_DIR$/src/portable/sony/cxd56/dcd_cxd56.c</path>
</group>
<group name="src/portable/st/stm32_fsdev">
<path>$TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c</path>
</group>
<group name="src/portable/sunxi">
<path>$TUSB_DIR$/src/portable/sunxi/dcd_sunxi_musb.c</path>
</group>
<group name="src/portable/ti/msp430x5xx">
<path>$TUSB_DIR$/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c</path>
</group>
<group name="src/portable/valentyusb/eptri">
<path>$TUSB_DIR$/src/portable/valentyusb/eptri/dcd_eptri.c</path>
</group>
<group name="src/portable/wch/ch32v307">
<path>$TUSB_DIR$/src/portable/wch/ch32v307/dcd_usbhs.c</path>
</group>
<group name="lib/SEGGER_RTT">
<path>$TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT.c</path>
<group name="src/class/audio">
<path>$TUSB_DIR$/src/class/audio/audio_device.c</path>
</group>
<group name="src/class/bth">
<path>$TUSB_DIR$/src/class/bth/bth_device.c</path>
</group>
<group name="src/class/cdc">
<path>$TUSB_DIR$/src/class/cdc/cdc_device.c</path>
<path>$TUSB_DIR$/src/class/cdc/cdc_host.c</path>
<path>$TUSB_DIR$/src/class/cdc/cdc_rndis_host.c</path>
</group>
<group name="src/class/dfu">
<path>$TUSB_DIR$/src/class/dfu/dfu_device.c</path>
<path>$TUSB_DIR$/src/class/dfu/dfu_rt_device.c</path>
</group>
<group name="src/class/hid">
<path>$TUSB_DIR$/src/class/hid/hid_device.c</path>
<path>$TUSB_DIR$/src/class/hid/hid_host.c</path>
</group>
<group name="src/class/midi">
<path>$TUSB_DIR$/src/class/midi/midi_device.c</path>
</group>
<group name="src/class/msc">
<path>$TUSB_DIR$/src/class/msc/msc_device.c</path>
<path>$TUSB_DIR$/src/class/msc/msc_host.c</path>
</group>
<group name="src/class/net">
<path>$TUSB_DIR$/src/class/net/ecm_rndis_device.c</path>
<path>$TUSB_DIR$/src/class/net/ncm_device.c</path>
</group>
<group name="src/class/usbtmc">
<path>$TUSB_DIR$/src/class/usbtmc/usbtmc_device.c</path>
</group>
<group name="src/class/vendor">
<path>$TUSB_DIR$/src/class/vendor/vendor_device.c</path>
<path>$TUSB_DIR$/src/class/vendor/vendor_host.c</path>
</group>
<group name="src/class/video">
<path>$TUSB_DIR$/src/class/video/video_device.c</path>
</group>
<group name="src/common">
<path>$TUSB_DIR$/src/common/tusb_fifo.c</path>
</group>
<group name="src/device">
<path>$TUSB_DIR$/src/device/usbd.c</path>
<path>$TUSB_DIR$/src/device/usbd_control.c</path>
</group>
<group name="src/host">
<path>$TUSB_DIR$/src/host/hub.c</path>
<path>$TUSB_DIR$/src/host/usbh.c</path>
</group>
<group name="src/portable/analog/max3421">
<path>$TUSB_DIR$/src/portable/analog/max3421/hcd_max3421.c</path>
</group>
<group name="src/portable/bridgetek/ft9xx">
<path>$TUSB_DIR$/src/portable/bridgetek/ft9xx/dcd_ft9xx.c</path>
</group>
<group name="src/portable/chipidea/ci_fs">
<path>$TUSB_DIR$/src/portable/chipidea/ci_fs/dcd_ci_fs.c</path>
</group>
<group name="src/portable/chipidea/ci_hs">
<path>$TUSB_DIR$/src/portable/chipidea/ci_hs/dcd_ci_hs.c</path>
<path>$TUSB_DIR$/src/portable/chipidea/ci_hs/hcd_ci_hs.c</path>
</group>
<group name="src/portable/dialog/da146xx">
<path>$TUSB_DIR$/src/portable/dialog/da146xx/dcd_da146xx.c</path>
</group>
<group name="src/portable/ehci">
<path>$TUSB_DIR$/src/portable/ehci/ehci.c</path>
</group>
<group name="src/portable/mentor/musb">
<path>$TUSB_DIR$/src/portable/mentor/musb/dcd_musb.c</path>
<path>$TUSB_DIR$/src/portable/mentor/musb/hcd_musb.c</path>
</group>
<group name="src/portable/microchip/pic">
<path>$TUSB_DIR$/src/portable/microchip/pic/dcd_pic.c</path>
</group>
<group name="src/portable/microchip/pic32mz">
<path>$TUSB_DIR$/src/portable/microchip/pic32mz/dcd_pic32mz.c</path>
</group>
<group name="src/portable/microchip/samd">
<path>$TUSB_DIR$/src/portable/microchip/samd/dcd_samd.c</path>
</group>
<group name="src/portable/microchip/samg">
<path>$TUSB_DIR$/src/portable/microchip/samg/dcd_samg.c</path>
</group>
<group name="src/portable/microchip/samx7x">
<path>$TUSB_DIR$/src/portable/microchip/samx7x/dcd_samx7x.c</path>
</group>
<group name="src/portable/mindmotion/mm32">
<path>$TUSB_DIR$/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c</path>
</group>
<group name="src/portable/nordic/nrf5x">
<path>$TUSB_DIR$/src/portable/nordic/nrf5x/dcd_nrf5x.c</path>
</group>
<group name="src/portable/nuvoton/nuc120">
<path>$TUSB_DIR$/src/portable/nuvoton/nuc120/dcd_nuc120.c</path>
</group>
<group name="src/portable/nuvoton/nuc121">
<path>$TUSB_DIR$/src/portable/nuvoton/nuc121/dcd_nuc121.c</path>
</group>
<group name="src/portable/nuvoton/nuc505">
<path>$TUSB_DIR$/src/portable/nuvoton/nuc505/dcd_nuc505.c</path>
</group>
<group name="src/portable/nxp/khci">
<path>$TUSB_DIR$/src/portable/nxp/khci/dcd_khci.c</path>
<path>$TUSB_DIR$/src/portable/nxp/khci/hcd_khci.c</path>
</group>
<group name="src/portable/nxp/lpc17_40">
<path>$TUSB_DIR$/src/portable/nxp/lpc17_40/dcd_lpc17_40.c</path>
<path>$TUSB_DIR$/src/portable/nxp/lpc17_40/hcd_lpc17_40.c</path>
</group>
<group name="src/portable/nxp/lpc_ip3511">
<path>$TUSB_DIR$/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c</path>
</group>
<group name="src/portable/ohci">
<path>$TUSB_DIR$/src/portable/ohci/ohci.c</path>
</group>
<group name="src/portable/raspberrypi/pio_usb">
<path>$TUSB_DIR$/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c</path>
<path>$TUSB_DIR$/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c</path>
</group>
<group name="src/portable/raspberrypi/rp2040">
<path>$TUSB_DIR$/src/portable/raspberrypi/rp2040/dcd_rp2040.c</path>
<path>$TUSB_DIR$/src/portable/raspberrypi/rp2040/hcd_rp2040.c</path>
<path>$TUSB_DIR$/src/portable/raspberrypi/rp2040/rp2040_usb.c</path>
</group>
<group name="src/portable/renesas/rusb2">
<path>$TUSB_DIR$/src/portable/renesas/rusb2/dcd_rusb2.c</path>
<path>$TUSB_DIR$/src/portable/renesas/rusb2/hcd_rusb2.c</path>
<path>$TUSB_DIR$/src/portable/renesas/rusb2/rusb2_common.c</path>
</group>
<group name="src/portable/sony/cxd56">
<path>$TUSB_DIR$/src/portable/sony/cxd56/dcd_cxd56.c</path>
</group>
<group name="src/portable/st/stm32_fsdev">
<path>$TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c</path>
</group>
<group name="src/portable/st/typec">
<path>$TUSB_DIR$/src/portable/st/typec/typec_stm32.c</path>
</group>
<group name="src/portable/sunxi">
<path>$TUSB_DIR$/src/portable/sunxi/dcd_sunxi_musb.c</path>
</group>
<group name="src/portable/synopsys/dwc2">
<path>$TUSB_DIR$/src/portable/synopsys/dwc2/dcd_dwc2.c</path>
</group>
<group name="src/portable/ti/msp430x5xx">
<path>$TUSB_DIR$/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c</path>
</group>
<group name="src/portable/valentyusb/eptri">
<path>$TUSB_DIR$/src/portable/valentyusb/eptri/dcd_eptri.c</path>
</group>
<group name="src/portable/wch/ch32v307">
<path>$TUSB_DIR$/src/portable/wch/ch32v307/dcd_usbhs.c</path>
</group>
<group name="src/typec">
<path>$TUSB_DIR$/src/typec/usbc.c</path>
</group>
<group name="lib/SEGGER_RTT/RTT">
<path>$TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT.c</path>
<path>$TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c</path>
<path>$TUSB_DIR$/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c</path>
</group>
</group>
</files>
</iarProjectConnection>