mirror of
https://github.com/hathach/tinyusb.git
synced 2026-08-18 11:02:16 +00:00
1
.gitignore
vendored
1
.gitignore
vendored
@ -81,6 +81,7 @@ hw/mcu/gd/
|
||||
hw/mcu/hpmicro/
|
||||
hw/mcu/infineon/
|
||||
hw/mcu/microchip/
|
||||
hw/mcu/puya/
|
||||
hw/mcu/mindmotion/
|
||||
hw/mcu/nordic/nrfx/
|
||||
hw/mcu/nuvoton/
|
||||
|
||||
@ -259,6 +259,8 @@ Supported CPUs
|
||||
| +---------+-------------------+--------+------+-----------+------------------------+--------------------+
|
||||
| | RW61x | ✅ | ✅ | ✅ | ci_hs, ehci | |
|
||||
+--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
|
||||
| Puya | PY32F071, PY32F072 | ✅ | ❌ | ❌ | musb | 1-dir ep |
|
||||
+--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
|
||||
| Raspberry Pi | RP2040, RP2350 | ✅ | ✅ | ❌ | rp2040, pio_usb | |
|
||||
+--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+
|
||||
| Renesas | RX | 63N, 65N, 72N | ✅ | ✅ | ❌ | rusb2 | |
|
||||
|
||||
@ -33,3 +33,14 @@ Reference: `CH32V30X Reference Manual`_ USBFS/USBHS controller chapter
|
||||
Data corruption may occur on isochronous endpoints. Due to the lacking of FIFO for interrupt status registers, later completed transfer will overwrite `INT_ST` and `RX_LEN` register if previous transfer processing is not completed.
|
||||
|
||||
Other types of transfers are not affected.
|
||||
|
||||
Puya PY32F071/072
|
||||
---------------------------------
|
||||
**Severity: Very Low**
|
||||
|
||||
Reference: `PY32F07x Reference Manual` USBD chapter
|
||||
|
||||
The USB device controller (MUSB-like) has 5 application endpoints EP1-EP5 with fixed FIFO sizes
|
||||
shared between IN and OUT of the same endpoint number: EP1 = 512 B, EP2-4 = 128 B, EP5 = 64 B.
|
||||
This is much lower than the max ISO ep size of 1024 for high EP numbers.
|
||||
Place large isochronous endpoints on EP1 and size descriptors accordingly.
|
||||
|
||||
@ -109,8 +109,10 @@ extern "C" {
|
||||
#define CFG_TUD_AUDIO_FUNC_1_N_FORMATS 2
|
||||
|
||||
// Audio format type I specifications
|
||||
#if defined(__RX__)
|
||||
#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 48000 // 16bit/48kHz is the best quality for Renesas RX
|
||||
#if defined(__RX__) || (CFG_TUSB_MCU == OPT_MCU_PY32F0)
|
||||
// RX : 16bit/48kHz is the best quality for Renesas RX
|
||||
// PY32F0 : 48kHz/16bit keeps ISO packets <= 98 B so both directions fit the fixed EP FIFOs (EP1 512 B, EP2 128 B)
|
||||
#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 48000
|
||||
#else
|
||||
#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 96000 // 24bit/96kHz is the best quality for full-speed, high-speed is needed beyond this
|
||||
#endif
|
||||
@ -123,7 +125,7 @@ extern "C" {
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX 2
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX 16
|
||||
|
||||
#if defined(__RX__)
|
||||
#if defined(__RX__) || (CFG_TUSB_MCU == OPT_MCU_PY32F0)
|
||||
// 8bit in 8bit slots
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX 1
|
||||
#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX 8
|
||||
|
||||
@ -10,6 +10,7 @@ mcu:SAMD11
|
||||
mcu:STM32L0
|
||||
mcu:STM32F0
|
||||
mcu:KINETIS_KL
|
||||
mcu:PY32F0
|
||||
mcu:STM32H7RS
|
||||
mcu:STM32N6
|
||||
family:broadcom_64bit
|
||||
|
||||
@ -98,6 +98,11 @@ uint8_t const * tud_descriptor_device_cb(void)
|
||||
#define EPNUM_AUDIO_OUT 0x0A
|
||||
#define EPNUM_AUDIO_IN 0x0B
|
||||
#define EPNUM_AUDIO_INT 0x01
|
||||
#elif TU_CHECK_MCU(OPT_MCU_PY32F0)
|
||||
// Speaker OUT (196 B) only fits EP1 (512 B FIFO); mic IN (98 B) fits EP2 (128 B)
|
||||
#define EPNUM_AUDIO_OUT 0x01
|
||||
#define EPNUM_AUDIO_IN 0x02
|
||||
#define EPNUM_AUDIO_INT 0x03
|
||||
#else
|
||||
#define EPNUM_AUDIO_IN 0x01
|
||||
#define EPNUM_AUDIO_OUT 0x02
|
||||
|
||||
108
hw/bsp/py32f0/FreeRTOSConfig/FreeRTOSConfig.h
Normal file
108
hw/bsp/py32f0/FreeRTOSConfig/FreeRTOSConfig.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2026, Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_CONFIG_H_
|
||||
#define FREERTOS_CONFIG_H_
|
||||
|
||||
#ifndef __IASMARM__
|
||||
#include "py32f0xx.h"
|
||||
#endif
|
||||
|
||||
#define configENABLE_MPU 0
|
||||
#define configENABLE_FPU 0
|
||||
#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
|
||||
|
||||
#define configUSE_IDLE_HOOK 0
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configUSE_MALLOC_FAILED_HOOK 0
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 2
|
||||
#define configCHECK_HANDLER_INSTALLATION 0
|
||||
|
||||
#define configGENERATE_RUN_TIME_STATS 0
|
||||
#define configRECORD_STACK_HIGH_ADDRESS 1
|
||||
#define configUSE_TRACE_FACILITY 1
|
||||
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
|
||||
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES 2
|
||||
|
||||
#define configUSE_TIMERS 1
|
||||
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 2 )
|
||||
#define configTIMER_QUEUE_LENGTH 32
|
||||
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
|
||||
|
||||
#define INCLUDE_vTaskPrioritySet 0
|
||||
#define INCLUDE_uxTaskPriorityGet 0
|
||||
#define INCLUDE_vTaskDelete 0
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#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 xPortPendSVHandler PendSV_Handler
|
||||
#define xPortSysTickHandler SysTick_Handler
|
||||
#define vPortSVCHandler SVC_Handler
|
||||
|
||||
#define configPRIO_BITS __NVIC_PRIO_BITS
|
||||
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ( ( 1 << configPRIO_BITS ) - 1 )
|
||||
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2
|
||||
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << ( 8 - configPRIO_BITS ) )
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << ( 8 - configPRIO_BITS ) )
|
||||
|
||||
#endif
|
||||
12
hw/bsp/py32f0/boards/py32f071_dev_board/board.cmake
Normal file
12
hw/bsp/py32f0/boards/py32f071_dev_board/board.cmake
Normal file
@ -0,0 +1,12 @@
|
||||
set(PYOCD_TARGET py32f071xb)
|
||||
set(PY32_SERIES PY32F071)
|
||||
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/py32f071xb.ld)
|
||||
|
||||
function(update_board TARGET)
|
||||
target_compile_definitions(${TARGET} PUBLIC
|
||||
PY32F071xB
|
||||
CFG_EXAMPLE_MSC_READONLY
|
||||
CFG_EXAMPLE_MSC_DUAL_READONLY
|
||||
CFG_EXAMPLE_VIDEO_READONLY
|
||||
)
|
||||
endfunction()
|
||||
75
hw/bsp/py32f0/boards/py32f071_dev_board/board.h
Normal file
75
hw/bsp/py32f0/boards/py32f071_dev_board/board.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2026, Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef BOARD_H_
|
||||
#define BOARD_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LED_PORT GPIOB
|
||||
#define LED_PIN GPIO_PIN_2
|
||||
#define LED_STATE_ON 0
|
||||
|
||||
#define BUTTON_PORT GPIOB
|
||||
#define BUTTON_PIN GPIO_PIN_0
|
||||
#define BUTTON_STATE_ACTIVE 0
|
||||
|
||||
static inline void board_py32f0_clock_init(void) {
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||||
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI |
|
||||
RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
|
||||
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
|
||||
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
|
||||
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_16MHz;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.HSEFreq = RCC_HSE_16_32MHz;
|
||||
RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
|
||||
RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL2;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
|
||||
while (1) {}
|
||||
}
|
||||
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
|
||||
while (1) {}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
12
hw/bsp/py32f0/boards/py32f071_dev_board/board.mk
Normal file
12
hw/bsp/py32f0/boards/py32f071_dev_board/board.mk
Normal file
@ -0,0 +1,12 @@
|
||||
PY32_SERIES = PY32F071
|
||||
|
||||
CFLAGS += \
|
||||
-DPY32F071xB \
|
||||
-DCFG_EXAMPLE_MSC_READONLY \
|
||||
-DCFG_EXAMPLE_MSC_DUAL_READONLY \
|
||||
-DCFG_EXAMPLE_VIDEO_READONLY
|
||||
|
||||
LD_FILE = $(BOARD_PATH)/py32f071xb.ld
|
||||
PYOCD_TARGET = py32f071xb
|
||||
|
||||
flash: flash-pyocd
|
||||
105
hw/bsp/py32f0/boards/py32f071_dev_board/py32f071_hal_conf.h
Normal file
105
hw/bsp/py32f0/boards/py32f071_dev_board/py32f071_hal_conf.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2026, Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef PY32F071_HAL_CONF_H_
|
||||
#define PY32F071_HAL_CONF_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define HAL_MODULE_ENABLED
|
||||
#define HAL_RCC_MODULE_ENABLED
|
||||
#define HAL_FLASH_MODULE_ENABLED
|
||||
#define HAL_GPIO_MODULE_ENABLED
|
||||
#define HAL_PWR_MODULE_ENABLED
|
||||
#define HAL_CORTEX_MODULE_ENABLED
|
||||
|
||||
#if !defined(HSI_VALUE)
|
||||
#define HSI_VALUE ((uint32_t) 8000000)
|
||||
#endif
|
||||
|
||||
#if !defined(HSE_VALUE)
|
||||
#define HSE_VALUE ((uint32_t) 24000000)
|
||||
#endif
|
||||
|
||||
#if !defined(HSE_STARTUP_TIMEOUT)
|
||||
#define HSE_STARTUP_TIMEOUT ((uint32_t) 200)
|
||||
#endif
|
||||
|
||||
#if !defined(LSI_VALUE)
|
||||
#define LSI_VALUE ((uint32_t) 32768)
|
||||
#endif
|
||||
|
||||
#if !defined(LSE_VALUE)
|
||||
#define LSE_VALUE ((uint32_t) 32768)
|
||||
#endif
|
||||
|
||||
#if !defined(LSE_STARTUP_TIMEOUT)
|
||||
#define LSE_STARTUP_TIMEOUT ((uint32_t) 5000)
|
||||
#endif
|
||||
|
||||
#define VDD_VALUE ((uint32_t) 3300)
|
||||
#define TICK_INT_PRIORITY ((uint32_t) 3)
|
||||
#define USE_RTOS 0
|
||||
#define PREFETCH_ENABLE 0
|
||||
|
||||
#ifdef HAL_MODULE_ENABLED
|
||||
#include "py32f0xx_hal.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_RCC_MODULE_ENABLED
|
||||
#include "py32f071_hal_rcc.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_FLASH_MODULE_ENABLED
|
||||
#include "py32f071_hal_flash.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
#include "py32f071_hal_gpio.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_PWR_MODULE_ENABLED
|
||||
#include "py32f071_hal_pwr.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAL_CORTEX_MODULE_ENABLED
|
||||
#include "py32f071_hal_cortex.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
void assert_failed(uint8_t *file, uint32_t line);
|
||||
#define assert_param(expr) ((expr) ? (void) 0U : assert_failed((uint8_t *) __FILE__, __LINE__))
|
||||
#else
|
||||
#define assert_param(expr) ((void) 0U)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
122
hw/bsp/py32f0/boards/py32f071_dev_board/py32f071xb.ld
Normal file
122
hw/bsp/py32f0/boards/py32f071_dev_board/py32f071xb.ld
Normal file
@ -0,0 +1,122 @@
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_Min_Heap_Size = 0x200;
|
||||
_Min_Stack_Size = 0x400;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.isr_vector :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.isr_vector))
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text)
|
||||
*(.text*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.eh_frame)
|
||||
KEEP(*(.init))
|
||||
KEEP(*(.fini))
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
} >FLASH
|
||||
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rodata)
|
||||
*(.rodata*)
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} >FLASH
|
||||
|
||||
.ARM :
|
||||
{
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
} >FLASH
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN(__preinit_array_start = .);
|
||||
KEEP(*(.preinit_array*))
|
||||
PROVIDE_HIDDEN(__preinit_array_end = .);
|
||||
} >FLASH
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array*))
|
||||
PROVIDE_HIDDEN(__init_array_end = .);
|
||||
} >FLASH
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN(__fini_array_start = .);
|
||||
KEEP(*(SORT(.fini_array.*)))
|
||||
KEEP(*(.fini_array*))
|
||||
PROVIDE_HIDDEN(__fini_array_end = .);
|
||||
} >FLASH
|
||||
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sdata = .;
|
||||
*(.data)
|
||||
*(.data*)
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} >RAM AT> FLASH
|
||||
|
||||
. = ALIGN(4);
|
||||
.bss :
|
||||
{
|
||||
_sbss = .;
|
||||
__bss_start__ = _sbss;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
__bss_end__ = _ebss;
|
||||
} >RAM
|
||||
|
||||
._user_heap_stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE(end = .);
|
||||
PROVIDE(_end = .);
|
||||
. = . + _Min_Heap_Size;
|
||||
. = . + _Min_Stack_Size;
|
||||
. = ALIGN(8);
|
||||
} >RAM
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
libc.a(*)
|
||||
libm.a(*)
|
||||
libgcc.a(*)
|
||||
}
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
}
|
||||
133
hw/bsp/py32f0/family.c
Normal file
133
hw/bsp/py32f0/family.c
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2026, 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.
|
||||
*/
|
||||
|
||||
/* metadata:
|
||||
manufacturer: Puya
|
||||
*/
|
||||
|
||||
#include "py32f0xx_hal.h"
|
||||
#include "bsp/board_api.h"
|
||||
#include "board.h"
|
||||
|
||||
void USB_IRQHandler(void) {
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
void USBD_IRQHandler(void) {
|
||||
tud_int_handler(0);
|
||||
}
|
||||
|
||||
void HAL_MspInit(void) {
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
}
|
||||
|
||||
void board_init(void) {
|
||||
HAL_Init();
|
||||
board_py32f0_clock_init();
|
||||
|
||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_NONE
|
||||
SysTick_Config(SystemCoreClock / 1000);
|
||||
#elif CFG_TUSB_OS == OPT_OS_FREERTOS
|
||||
SysTick->CTRL &= ~1U;
|
||||
NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
|
||||
#endif
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
GPIO_InitStruct.Pin = LED_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
|
||||
board_led_write(false);
|
||||
|
||||
GPIO_InitStruct.Pin = BUTTON_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);
|
||||
|
||||
__HAL_RCC_USB_CLK_ENABLE();
|
||||
}
|
||||
|
||||
void board_led_write(bool state) {
|
||||
GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1 - LED_STATE_ON));
|
||||
HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state);
|
||||
}
|
||||
|
||||
uint32_t board_button_read(void) {
|
||||
return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);
|
||||
}
|
||||
|
||||
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
|
||||
(void) max_len;
|
||||
volatile uint32_t * py32_uuid = (volatile uint32_t *) UID_BASE;
|
||||
uint32_t* id32 = (uint32_t*) (uintptr_t) id;
|
||||
uint8_t const len = 12;
|
||||
|
||||
id32[0] = py32_uuid[0];
|
||||
id32[1] = py32_uuid[1];
|
||||
id32[2] = py32_uuid[2];
|
||||
|
||||
return 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) {
|
||||
(void) buf; (void) len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_NONE
|
||||
volatile uint32_t system_ticks = 0;
|
||||
|
||||
void SysTick_Handler(void) {
|
||||
HAL_IncTick();
|
||||
system_ticks++;
|
||||
}
|
||||
|
||||
uint32_t tusb_time_millis_api(void) {
|
||||
return system_ticks;
|
||||
}
|
||||
#endif
|
||||
|
||||
void HardFault_Handler(void) {
|
||||
__asm("BKPT #0\n");
|
||||
}
|
||||
|
||||
void _init(void);
|
||||
void _init(void) {
|
||||
}
|
||||
89
hw/bsp/py32f0/family.cmake
Normal file
89
hw/bsp/py32f0/family.cmake
Normal file
@ -0,0 +1,89 @@
|
||||
include_guard()
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
|
||||
|
||||
if (NOT DEFINED MCU_VARIANT)
|
||||
set(MCU_VARIANT PY32F071)
|
||||
endif ()
|
||||
string(TOLOWER ${MCU_VARIANT} PY32_SERIES_LOWER)
|
||||
set(PY32_SDK_NAME ${MCU_VARIANT}_Firmware)
|
||||
set(PY32_TEMPLATE ${MCU_VARIANT}xx_Templates)
|
||||
set(PY32_STARTUP startup_${PY32_SERIES_LOWER}xx.s)
|
||||
set(PY32_SYSTEM_SOURCE system_${PY32_SERIES_LOWER}.c)
|
||||
set(PY32_HAL_PREFIX ${PY32_SERIES_LOWER})
|
||||
|
||||
set(PY32_SDK ${TOP}/hw/mcu/puya/${PY32_SDK_NAME})
|
||||
set(PY32_HAL ${PY32_SDK}/Drivers/${MCU_VARIANT}_HAL_Driver)
|
||||
set(PY32_CMSIS ${PY32_SDK}/Drivers/CMSIS/Device/${MCU_VARIANT})
|
||||
|
||||
set(CMAKE_SYSTEM_CPU cortex-m0plus CACHE INTERNAL "System Processor")
|
||||
set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
|
||||
|
||||
set(FAMILY_MCUS PY32F0 CACHE INTERNAL "")
|
||||
|
||||
set(STARTUP_FILE_GNU ${PY32_SDK}/Templates/${PY32_TEMPLATE}/EIDE/${PY32_STARTUP})
|
||||
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
|
||||
set(LD_FILE_Clang ${LD_FILE_GNU})
|
||||
|
||||
function(family_add_board BOARD_TARGET)
|
||||
add_library(${BOARD_TARGET} STATIC
|
||||
${PY32_SDK}/Templates/${PY32_TEMPLATE}/Src/${PY32_SYSTEM_SOURCE}
|
||||
${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal.c
|
||||
${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_cortex.c
|
||||
${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_flash.c
|
||||
${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_gpio.c
|
||||
${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_pwr.c
|
||||
${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_rcc.c
|
||||
${PY32_HAL}/Src/${PY32_HAL_PREFIX}_hal_rcc_ex.c
|
||||
)
|
||||
target_include_directories(${BOARD_TARGET} PUBLIC
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
|
||||
${PY32_SDK}/Drivers/CMSIS/Include
|
||||
${PY32_CMSIS}/Include
|
||||
${PY32_HAL}/Inc
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
|
||||
)
|
||||
target_compile_definitions(${BOARD_TARGET} PRIVATE
|
||||
USE_HAL_DRIVER
|
||||
)
|
||||
update_board(${BOARD_TARGET})
|
||||
endfunction()
|
||||
|
||||
function(family_configure_example TARGET RTOS)
|
||||
family_configure_common(${TARGET} ${RTOS})
|
||||
family_add_tinyusb(${TARGET} OPT_MCU_PY32F0)
|
||||
|
||||
target_sources(${TARGET} PUBLIC
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
|
||||
${TOP}/src/portable/mentor/musb/dcd_musb.c
|
||||
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
|
||||
)
|
||||
target_include_directories(${TARGET} PUBLIC
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
|
||||
)
|
||||
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_options(${TARGET} PUBLIC
|
||||
"LINKER:--script=${LD_FILE_GNU}"
|
||||
-nostartfiles
|
||||
--specs=nosys.specs --specs=nano.specs
|
||||
)
|
||||
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
message(FATAL_ERROR "Clang is not supported")
|
||||
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
|
||||
message(FATAL_ERROR "IAR is not supported")
|
||||
endif ()
|
||||
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes")
|
||||
endif ()
|
||||
set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES
|
||||
SKIP_LINTING ON
|
||||
COMPILE_OPTIONS -w)
|
||||
|
||||
family_add_bin_hex(${TARGET})
|
||||
family_flash_pyocd(${TARGET})
|
||||
endfunction()
|
||||
58
hw/bsp/py32f0/family.mk
Normal file
58
hw/bsp/py32f0/family.mk
Normal file
@ -0,0 +1,58 @@
|
||||
UF2_FAMILY_ID = 0x0
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
|
||||
MCU_VARIANT ?= PY32F071
|
||||
PY32_SERIES_LOWER = $(subst PY32F,py32f,$(MCU_VARIANT))
|
||||
PY32_SDK_NAME = $(MCU_VARIANT)_Firmware
|
||||
PY32_TEMPLATE = $(MCU_VARIANT)xx_Templates
|
||||
PY32_STARTUP = startup_$(PY32_SERIES_LOWER)xx.s
|
||||
PY32_SYSTEM_SOURCE = system_$(PY32_SERIES_LOWER).c
|
||||
PY32_HAL_PREFIX = $(PY32_SERIES_LOWER)
|
||||
|
||||
SDK_DIR = hw/mcu/puya/$(PY32_SDK_NAME)
|
||||
HAL_DIR = $(SDK_DIR)/Drivers/$(MCU_VARIANT)_HAL_Driver
|
||||
CMSIS_DIR = $(SDK_DIR)/Drivers/CMSIS
|
||||
CMSIS_DEVICE_DIR = $(CMSIS_DIR)/Device/$(MCU_VARIANT)
|
||||
|
||||
DEPS_SUBMODULES += $(SDK_DIR)
|
||||
|
||||
CFLAGS += \
|
||||
-DCFG_TUSB_MCU=OPT_MCU_PY32F0 \
|
||||
-DUSE_HAL_DRIVER
|
||||
|
||||
# Puya HAL leaves some CMSIS-compatible callback parameters intentionally unused.
|
||||
CFLAGS += -Wno-error=unused-parameter
|
||||
|
||||
MCU_DIR = $(SDK_DIR)
|
||||
|
||||
SRC_C += \
|
||||
src/portable/mentor/musb/dcd_musb.c \
|
||||
hw/bsp/py32f0/family.c \
|
||||
$(SDK_DIR)/Templates/$(PY32_TEMPLATE)/Src/$(PY32_SYSTEM_SOURCE) \
|
||||
$(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal.c \
|
||||
$(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_cortex.c \
|
||||
$(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_flash.c \
|
||||
$(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_gpio.c \
|
||||
$(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_pwr.c \
|
||||
$(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_rcc.c \
|
||||
$(HAL_DIR)/Src/$(PY32_HAL_PREFIX)_hal_rcc_ex.c
|
||||
|
||||
SRC_S += $(SDK_DIR)/Templates/$(PY32_TEMPLATE)/EIDE/$(PY32_STARTUP)
|
||||
|
||||
INC += \
|
||||
$(TOP)/hw/bsp/py32f0 \
|
||||
$(TOP)/$(CMSIS_DIR)/Include \
|
||||
$(TOP)/$(CMSIS_DEVICE_DIR)/Include \
|
||||
$(TOP)/$(HAL_DIR)/Inc \
|
||||
$(TOP)/hw/bsp/py32f0/boards/$(BOARD)
|
||||
|
||||
SKIP_NANOLIB = 1
|
||||
|
||||
LDFLAGS += \
|
||||
-nostdlib -nostartfiles \
|
||||
--specs=nosys.specs --specs=nano.specs \
|
||||
-Wl,--gc-sections \
|
||||
-Wl,--print-memory-usage
|
||||
|
||||
CPU_CORE ?= cortex-m0plus
|
||||
@ -703,6 +703,17 @@
|
||||
|
||||
#define TU_ATTR_FAST_FUNC __attribute__((section(".fast")))
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Puya
|
||||
//--------------------------------------------------------------------+
|
||||
#elif TU_CHECK_MCU(OPT_MCU_PY32F0)
|
||||
#define TUP_USBIP_MUSB
|
||||
#define TUP_USBIP_MUSB_PY32
|
||||
#define TUP_DCD_ENDPOINT_MAX 6
|
||||
// PY32 shares the buffer between IN and OUT of the same endpoint number.
|
||||
// Possible to share IN/OUT if only one direction is armed at any one time
|
||||
#define CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY 1
|
||||
|
||||
#endif
|
||||
|
||||
// External USB controller
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
#include "musb_ti.h"
|
||||
#elif defined(TUP_USBIP_MUSB_ADI)
|
||||
#include "musb_max32.h"
|
||||
#elif defined(TUP_USBIP_MUSB_PY32)
|
||||
#include "musb_py32.h"
|
||||
#else
|
||||
#error "Unsupported MCU"
|
||||
#endif
|
||||
@ -45,6 +47,7 @@ typedef struct {
|
||||
};
|
||||
uint16_t length; /* the number of bytes in the buffer */
|
||||
uint16_t remaining; /* the number of bytes remaining in the buffer */
|
||||
uint16_t mps; /* maximum packet size */
|
||||
bool armed; /* true while a transfer is posted */
|
||||
bool use_fifo; /* true: buf is tu_fifo_t*; false: buf is plain byte pointer. */
|
||||
} pipe_state_t;
|
||||
@ -159,6 +162,14 @@ TU_ATTR_ALWAYS_INLINE static inline pipe_state_t* pipe_get(uint8_t epnum, tusb_d
|
||||
return &_dcd.pipe[idx];
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint16_t musb_mps_to_maxp(uint16_t mps) {
|
||||
#if defined(TUP_USBIP_MUSB_PY32)
|
||||
return (uint8_t) ((mps + 7u) / 8u);
|
||||
#else
|
||||
return mps;
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// HW FIFO Helper
|
||||
// Note: Index register is already set by caller
|
||||
@ -223,7 +234,12 @@ TU_ATTR_ALWAYS_INLINE static inline bool hwfifo_config(musb_regs_t* musb, unsign
|
||||
bool double_packet) {
|
||||
(void) mps;
|
||||
|
||||
#if defined(TUP_USBIP_MUSB_ADI)
|
||||
#if defined(TUP_USBIP_MUSB_PY32)
|
||||
(void) musb; (void) is_rx; (void) double_packet;
|
||||
// Puya FIFO sizes: EP0 = 64 B, EP1 = 512 B, EP2..4 = 128 B, EP5 = 64 B, shared between IN and OUT.
|
||||
static const uint16_t py32_fifo_size[] = { 64, 512, 128, 128, 128, 64 };
|
||||
return epnum < TU_ARRAY_SIZE(py32_fifo_size) && mps <= py32_fifo_size[epnum];
|
||||
#elif defined(TUP_USBIP_MUSB_ADI)
|
||||
// AnalogDevice FIFO sizes: EP1..7 = 512 B, EP8..9 = 2048 B, EP10..11 = 4096 B.
|
||||
// DPB requires FIFO >= 2 * MPS. For HS bulk (MPS=512) only EP >= 8 qualifies.
|
||||
// Force single-buffered on EP < 8 even if the caller requested DPB.
|
||||
@ -266,7 +282,7 @@ TU_ATTR_ALWAYS_INLINE static inline void hwfifo_flush(musb_regs_t* musb, unsigne
|
||||
// write to txfifo using pipe_state_t info
|
||||
static void pipe_write(musb_regs_t* musb_regs, pipe_state_t* pipe, uint8_t epnum) {
|
||||
musb_ep_csr_t* ep_csr = &musb_regs->indexed_csr;
|
||||
const uint16_t mps = ep_csr->tx_maxp & MUSB_TXMAXP_PACKET_SIZE_M;
|
||||
const uint16_t mps = pipe->mps;
|
||||
const uint16_t xact_len = tu_min16(mps, pipe->remaining);
|
||||
volatile void *hwfifo = &musb_regs->fifo[epnum];
|
||||
if (xact_len) {
|
||||
@ -320,7 +336,7 @@ static void process_epin_isr(uint8_t rhport, musb_regs_t *musb_regs, uint8_t epn
|
||||
// release the FIFO slot by clearing RXRDY. return true if short packet
|
||||
static bool pipe_read(musb_regs_t* musb_regs, pipe_state_t* pipe, uint8_t epnum) {
|
||||
musb_ep_csr_t* ep_csr = &musb_regs->indexed_csr; // index already set in process_epout_isr()
|
||||
const uint16_t mps = ep_csr->rx_maxp & MUSB_RXMAXP_PACKET_SIZE_M;
|
||||
const uint16_t mps = pipe->mps;
|
||||
const uint16_t rx_count = ep_csr->rx_count;
|
||||
const uint16_t xact_len = tu_min16(tu_min16(pipe->remaining, mps), rx_count);
|
||||
volatile void *hwfifo = &musb_regs->fifo[epnum];
|
||||
@ -632,7 +648,11 @@ static void process_bus_reset_isr(uint8_t rhport) {
|
||||
hwfifo_reset(musb, i, 0);
|
||||
hwfifo_reset(musb, i, 1);
|
||||
}
|
||||
#if defined(TUP_USBIP_MUSB_PY32)
|
||||
dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true);
|
||||
#else
|
||||
dcd_event_bus_reset(rhport, (musb->power & MUSB_POWER_HSMODE) ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
@ -641,6 +661,11 @@ static void process_bus_reset_isr(uint8_t rhport) {
|
||||
|
||||
#if CFG_TUSB_DEBUG >= MUSB_DEBUG
|
||||
static void print_musb_info(musb_regs_t* musb_regs) {
|
||||
#if defined(TUP_USBIP_MUSB_PY32)
|
||||
(void) musb_regs;
|
||||
// musb discovery fields not present
|
||||
TU_LOG1("musb py32 fixed full-speed configuration\r\n");
|
||||
#else
|
||||
// print version, epinfo, raminfo, config_data0, fifo_size
|
||||
TU_LOG1("musb version = %u.%u\r\n", musb_regs->hwvers_bit.major, musb_regs->hwvers_bit.minor);
|
||||
TU_LOG1("Number of endpoints: %u TX, %u RX\r\n", musb_regs->epinfo_bit.tx_ep_num, musb_regs->epinfo_bit.rx_ep_num);
|
||||
@ -657,6 +682,7 @@ static void print_musb_info(musb_regs_t* musb_regs) {
|
||||
TU_LOG1("FIFO %u Size: TX %u RX %u\r\n", i, musb_regs->indexed_csr.fifo_size_bit.tx, musb_regs->indexed_csr.fifo_size_bit.rx);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -712,6 +738,18 @@ void dcd_remote_wakeup(uint8_t rhport) {
|
||||
musb_regs->power &= ~MUSB_POWER_RESUME;
|
||||
}
|
||||
|
||||
#if defined(TUP_USBIP_MUSB_PY32)
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
(void) rhport;
|
||||
}
|
||||
#else
|
||||
|
||||
// Connect by enabling internal pull-up resistor on D+/D-
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
@ -727,6 +765,8 @@ void dcd_disconnect(uint8_t rhport)
|
||||
musb_regs->power &= ~MUSB_POWER_SOFTCONN;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void dcd_sof_enable(uint8_t rhport, bool en)
|
||||
{
|
||||
(void) rhport;
|
||||
@ -750,6 +790,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) {
|
||||
pipe->buf = NULL;
|
||||
pipe->length = 0;
|
||||
pipe->remaining = 0;
|
||||
pipe->mps = (uint16_t) mps;
|
||||
pipe->armed = false;
|
||||
|
||||
musb_regs_t* musb = MUSB_REGS(rhport);
|
||||
@ -757,7 +798,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) {
|
||||
const uint8_t is_rx = (1 - epdir);
|
||||
musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[is_rx];
|
||||
|
||||
maxp_csr->maxp = mps;
|
||||
maxp_csr->maxp = musb_mps_to_maxp((uint16_t) mps);
|
||||
maxp_csr->csrh = 0;
|
||||
#if MUSB_CFG_SHARED_FIFO
|
||||
if (epdir) {
|
||||
@ -768,7 +809,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) {
|
||||
hwfifo_flush(musb, epn, is_rx, true);
|
||||
|
||||
TU_ASSERT(hwfifo_config(musb, epn, is_rx, mps, ep_desc->bmAttributes.xfer == TUSB_XFER_BULK));
|
||||
musb->intren_ep[is_rx] |= TU_BIT(epn);
|
||||
musb->intren_ep[is_rx ^ MUSB_INTR_EP_TX_RX_SWAP] |= TU_BIT(epn);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -779,8 +820,11 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet
|
||||
musb_regs_t* musb = MUSB_REGS(rhport);
|
||||
musb_ep_csr_t* ep_csr = get_ep_csr(musb, epn);
|
||||
const uint8_t is_rx = 1 - dir_in;
|
||||
pipe_state_t *pipe = pipe_get(epn, dir_in);
|
||||
pipe->mps = largest_packet_size;
|
||||
ep_csr->maxp_csr[is_rx].csrh = 0;
|
||||
return hwfifo_config(musb, epn, is_rx, largest_packet_size, true);
|
||||
TU_ASSERT(hwfifo_config(musb, epn, is_rx, largest_packet_size, true));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc ) {
|
||||
@ -796,6 +840,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc )
|
||||
pipe->buf = NULL;
|
||||
pipe->length = 0;
|
||||
pipe->remaining = 0;
|
||||
pipe->mps = (uint16_t) mps;
|
||||
pipe->armed = false;
|
||||
|
||||
musb_regs_t* musb = MUSB_REGS(rhport);
|
||||
@ -803,7 +848,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc )
|
||||
const uint8_t is_rx = 1 - dir_in;
|
||||
musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[is_rx];
|
||||
|
||||
maxp_csr->maxp = mps;
|
||||
maxp_csr->maxp = musb_mps_to_maxp((uint16_t) mps);
|
||||
maxp_csr->csrh |= MUSB_CSRH_ISO;
|
||||
#if MUSB_CFG_SHARED_FIFO
|
||||
if (dir_in) {
|
||||
@ -818,7 +863,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *ep_desc )
|
||||
musb->fifo_size[is_rx] = hwfifo_byte2size(mps) | MUSB_FIFOSZ_DOUBLE_PACKET;
|
||||
#endif
|
||||
|
||||
musb->intren_ep[is_rx] |= TU_BIT(epn);
|
||||
musb->intren_ep[is_rx ^ MUSB_INTR_EP_TX_RX_SWAP] |= TU_BIT(epn);
|
||||
|
||||
if (ie) musb_dcd_int_enable(rhport);
|
||||
|
||||
@ -839,7 +884,7 @@ void dcd_edpt_close_all(uint8_t rhport)
|
||||
musb_ep_maxp_csr_t* maxp_csr = &ep_csr->maxp_csr[d];
|
||||
hwfifo_flush(musb, i, d, true);
|
||||
hwfifo_reset(musb, i, d);
|
||||
maxp_csr->maxp = 0;
|
||||
maxp_csr->maxp = musb_mps_to_maxp(0);
|
||||
maxp_csr->csrh = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ extern "C" {
|
||||
|
||||
#define MUSB_CFG_SHARED_FIFO 1 // shared FIFO for TX and RX endpoints
|
||||
#define MUSB_CFG_DYNAMIC_FIFO 0 // dynamic EP FIFO sizing
|
||||
#define MUSB_INTR_EP_TX_RX_SWAP 0
|
||||
|
||||
static const uintptr_t MUSB_BASES[] = { MXC_BASE_USBHS };
|
||||
|
||||
|
||||
79
src/portable/mentor/musb/musb_py32.h
Normal file
79
src/portable/mentor/musb/musb_py32.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2026, Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef TUSB_MUSB_PY32_H_
|
||||
#define TUSB_MUSB_PY32_H_
|
||||
|
||||
#include "py32f0xx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// PY32 does not expose generic MUSB shared FIFO allocation registers; this
|
||||
// selects the existing TX_MODE path required for IN endpoints.
|
||||
#define MUSB_CFG_SHARED_FIFO 1
|
||||
#define MUSB_CFG_DYNAMIC_FIFO 0
|
||||
#define MUSB_INTR_EP_TX_RX_SWAP 1
|
||||
|
||||
static const uintptr_t MUSB_BASES[] = { USBD_BASE };
|
||||
static const IRQn_Type musb_irqs[] = { USB_IRQn };
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_phy_init(uint8_t rhport) {
|
||||
musb_regs_t* musb_regs = MUSB_REGS(rhport);
|
||||
|
||||
musb_regs->index = 0;
|
||||
musb_regs->faddr = 0;
|
||||
musb_regs->intr_usben = MUSB_IE_RESET | MUSB_IE_RESUME | MUSB_IE_SUSPND;
|
||||
musb_regs->intr_txen = TU_BIT(0);
|
||||
musb_regs->intr_rxen = 0;
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_enable(uint8_t rhport) {
|
||||
NVIC_EnableIRQ(musb_irqs[rhport]);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_disable(uint8_t rhport) {
|
||||
NVIC_DisableIRQ(musb_irqs[rhport]);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_clear(uint8_t rhport) {
|
||||
NVIC_ClearPendingIRQ(musb_irqs[rhport]);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline unsigned musb_dcd_get_int_enable(uint8_t rhport) {
|
||||
return NVIC_GetEnableIRQ(musb_irqs[rhport]);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline void musb_dcd_int_handler_enter(uint8_t rhport) {
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -30,6 +30,7 @@
|
||||
#define MUSB_CFG_SHARED_FIFO 0
|
||||
#define MUSB_CFG_DYNAMIC_FIFO 1
|
||||
#define MUSB_CFG_DYNAMIC_FIFO_SIZE 4096
|
||||
#define MUSB_INTR_EP_TX_RX_SWAP 0
|
||||
|
||||
static const uintptr_t MUSB_BASES[] = { USB0_BASE };
|
||||
|
||||
|
||||
@ -64,6 +64,75 @@
|
||||
#define __R volatile const
|
||||
#endif
|
||||
|
||||
#if defined(TUP_USBIP_MUSB_PY32)
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
__IO uint8_t csrh; // 0x04, 0x08: CSRH
|
||||
__IO uint8_t csrl; // 0x05, 0x09: CSRL
|
||||
__IO uint8_t maxp; // 0x06, 0x0A: MAXP
|
||||
__I uint8_t reserved;
|
||||
} musb_ep_maxp_csr_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(musb_ep_maxp_csr_t) == 4, "size is not correct");
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
__IO uint8_t csr0l; // 0x00: CSR0
|
||||
__IO uint8_t count0; // 0x01: COUNT0
|
||||
__I uint8_t reserved_0x02[2];
|
||||
|
||||
union {
|
||||
struct {
|
||||
__IO uint8_t tx_csrh; // 0x04: TX CSRH
|
||||
__IO uint8_t tx_csrl; // 0x05: TX CSRL
|
||||
__IO uint8_t tx_maxp; // 0x06: TX MAXP
|
||||
__I uint8_t reserved_0x07;
|
||||
|
||||
__IO uint8_t rx_csrh; // 0x08: RX CSRH
|
||||
__IO uint8_t rx_csrl; // 0x09: RX CSRL
|
||||
__IO uint8_t rx_maxp; // 0x0A: RX MAXP
|
||||
__I uint8_t reserved_0x0b;
|
||||
};
|
||||
|
||||
musb_ep_maxp_csr_t maxp_csr[2];
|
||||
};
|
||||
|
||||
__IO uint16_t rx_count; // 0x0C: RX COUNT
|
||||
__I uint8_t reserved_0x0e[2];
|
||||
} musb_ep_csr_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(musb_ep_csr_t) == 16, "size is not correct");
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
__IO uint8_t faddr; // 0x00: FADDR
|
||||
__IO uint8_t power; // 0x01: POWER
|
||||
__I uint8_t reserved_0x02[2];
|
||||
|
||||
__IO uint8_t intr_usb; // 0x04: INTRUSB
|
||||
__IO uint8_t intr_rx; // 0x05: INTRRX
|
||||
__IO uint8_t intr_tx; // 0x06: INTRTX
|
||||
__I uint8_t reserved_0x07;
|
||||
|
||||
__IO uint8_t intr_usben; // 0x08: INTRUSBEN
|
||||
union {
|
||||
struct {
|
||||
__IO uint8_t intr_rxen; // 0x09: INTRRXEN
|
||||
__IO uint8_t intr_txen; // 0x0A: INTRTXEN
|
||||
};
|
||||
|
||||
__IO uint8_t intren_ep[2]; // 0x09-0x0A: RX, TX
|
||||
};
|
||||
__I uint8_t reserved_0x0b;
|
||||
|
||||
__IO uint16_t frame; // 0x0C: FRAME
|
||||
__IO uint8_t index; // 0x0E: INDEX
|
||||
__I uint8_t reserved_0x0f;
|
||||
|
||||
musb_ep_csr_t indexed_csr; // 0x10-0x1F: Indexed CSR
|
||||
__IO uint32_t fifo[16]; // 0x20-0x5F: FIFO 0-15
|
||||
} musb_regs_t;
|
||||
|
||||
#else
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
__IO uint16_t maxp; // 0x00, 0x04: MAXP
|
||||
__IO uint8_t csrl; // 0x02, 0x06: CSRL
|
||||
@ -277,6 +346,8 @@ typedef struct {
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(musb_regs_t) == 0x350, "size is not correct");
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Helper
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
@ -204,6 +204,9 @@
|
||||
// HPMicro
|
||||
#define OPT_MCU_HPM 2600 ///< HPMicro
|
||||
|
||||
// Puya
|
||||
#define OPT_MCU_PY32F0 2700 ///< Puya PY32F0
|
||||
|
||||
// Check if configured MCU is one of listed
|
||||
// Apply TU_MCU_IS_EQUAL with || as separator to list of input
|
||||
#define TU_MCU_IS_EQUAL(_m) (CFG_TUSB_MCU == (_m))
|
||||
@ -400,7 +403,9 @@
|
||||
#if defined(TUP_USBIP_MUSB)
|
||||
#define CFG_TUD_EDPT_DEDICATED_HWFIFO 1
|
||||
#define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 // 32 bit data
|
||||
#define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS // allow odd 16bit access
|
||||
#if !defined(TUP_USBIP_MUSB_PY32)
|
||||
#define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS // allow odd 16bit access
|
||||
#endif
|
||||
#define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS // allow odd 8bit access
|
||||
#define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 0 // fixed hwfifo
|
||||
#endif
|
||||
|
||||
@ -82,6 +82,12 @@ deps_optional = {
|
||||
'hw/mcu/nxp/mcux-devices-rt': ['https://github.com/nxp-mcuxpresso/mcux-devices-rt',
|
||||
'dba2b523c9df61f3330bd186242f8210a8e47c45',
|
||||
'imxrt'],
|
||||
'hw/mcu/puya/PY32F071_Firmware': ['https://github.com/OpenPuya/PY32F071_Firmware.git',
|
||||
'73e384cddce63e3019de41d9b6af17dfc96fa536',
|
||||
'py32f0'],
|
||||
'hw/mcu/puya/PY32F072_Firmware': ['https://github.com/OpenPuya/PY32F072_Firmware.git',
|
||||
'bc3a6cdbece335a27abb8b51e6fc4911f5116185',
|
||||
'py32f0'],
|
||||
'hw/mcu/raspberry_pi/FreeRTOS-Kernel': ['https://github.com/raspberrypi/FreeRTOS-Kernel.git',
|
||||
'4f7299d6ea746b27a9dd19e87af568e34bd65b15',
|
||||
'rp2040'],
|
||||
|
||||
Reference in New Issue
Block a user