Compare commits

...

22 Commits

Author SHA1 Message Date
King Kévin 6370f153f0 Merge tag '0.14.0' 2023-01-06 00:26:57 +01:00
Ha Thach 9e91b02ec7
Merge pull request #1609 from hathach/release-0.14.0-p2
update repository.yml
2022-08-23 13:15:11 +07:00
hathach 3e815c709c
update repository.yml 2022-08-23 12:00:20 +07:00
Ha Thach 05e19b7848
Update feature_request.yml 2022-08-19 23:57:39 +07:00
Ha Thach f6c1ce5b1c
Merge pull request #1569 from hathach/release-0.14.0
increase version to 0.14.0 for release
2022-08-19 21:13:09 +07:00
hathach 961e83e083
more docs update 2022-08-19 17:14:53 +07:00
Ha Thach 792b2fb956
Merge pull request #1603 from Ryzee119/hub_improv
Host hub clear port and device interrupts
2022-08-17 15:03:48 +07:00
Ryzee119 2b2354d302 Hub: Clear other port feature changes 2022-08-16 18:25:46 +09:30
Ryzee119 3c7b5dcaff Hub: Handle hub device status change interrupt 2022-08-16 18:25:43 +09:30
Ha Thach 585f37a797
Merge pull request #1489 from kasjer/kasjer/fix-nrf5x-dma-access
nrf5x: Fix DMA access
2022-08-15 21:30:39 +07:00
Ryzee119 aafea8ef5d Hub: Rename port status callback to be more generic 2022-08-15 17:43:04 +09:30
Ryzee119 5efef4393c Hub: Expand hub helpers to handle device events 2022-08-15 17:42:56 +09:30
Ha Thach 8a28e7cd75
Merge pull request #1597 from kasjer/kasjer/dfu-coexistence
dfu: Allow DFU coexistence with other interfaces (BTH, RNDIS, future one)
2022-08-10 12:45:22 +07:00
Ha Thach 7ade0d0ce4
Merge pull request #1588 from majbthrd/stm32l052
add 'stm32l052dap52' (STM32L052K8 MCU) board target
2022-08-10 12:41:29 +07:00
Jerzy Kasenberg c7469ce986 dfu: Allow DFU coexistence with other interfaces
dfu_moded_open() only works correct when its called on DFU interface
descriptor. It means that DFU is the only one interface in configuration
or driver is called after all others interface drivers were tried and
gave up.

If other interface is supported and but driver for DFU is called first
(this is the case for BTH and RNDIS).
Code after while loop (that was not entered) has an TU_ASSERT that will
make set_configuration to fail.

Now TU_VERIFY is called first to make sure open code is called for DFU
only and not other interface descriptors like in other drivers.
2022-08-09 10:42:30 +02:00
Peter Lawrence d1c61e33a6 add 'stm32l052dap52' (STM32L052K8 MCU) board target
'dap52' is Olimex's name of their STM32L052-based fork of 'dap42'
2022-08-03 12:31:37 -05:00
Ha Thach 251ce98990
Merge pull request #1586 from hathach/fix-TUD_OPT_HIGH_SPEED
fix issue with TUD_OPT_HIGH_SPEED
2022-08-01 15:51:54 +07:00
hathach a219ba86ea
fix issue with TUD_OPT_HIGH_SPEED 2022-08-01 14:52:29 +07:00
hathach d36ea6ddc1
update issue template 2022-07-28 12:23:01 +07:00
hathach 23ea8d1e25 update doc 2022-07-25 22:27:33 +07:00
hathach b0b155c949
increase version for release
along with minor doc update
2022-07-19 12:28:52 +07:00
Jerzy Kasenberg 8b37aa1579 nrf5x: Fix DMA access
There were two problems:
- dma_running flag could be checked in USB interrupt (not set yet) then higher priority
  interrupt could start transfer, check dma_running (not set yet) set it to true start
  DMA; then when USB interrupt continues it starts another DMA that is not allowed
- when DMA is started some registers can't be safely accessed, read can yield invalid
  values (SIZE.EPOUT, SIZE.EPISO)
  current implementation could start DMA for one OUT endpoint then check that another
  endpoint also has data and while DMA was not started right away, SIZE.EPOUT was copied
  already to MAXCNT register. Later on when DMA was started not all data was read from
  endpoint due to incorrect DMA size previously set.

To prevent both cases dma_running is changed in atomic way.
Only code that actually set this value to true starts DMA, code that tried and
had dma_running flag already set simply defers DMA start to USB task.
This eliminates also need to have mutex that was there to limit access to dma_running flag
to one task only.
transfer also now has started flag that is set only after dcd_edpt_xfer() sets up total_len
and actua_len. Previously USB interrupt was disabled when total_len and actual_len were
setup to prevent race condition when data arrived to ednpoint before transfer was setup
was finished.
2022-06-02 17:23:35 +02:00
19 changed files with 1105 additions and 103 deletions

View File

@ -76,3 +76,11 @@ body:
description: If applicable, add screenshots to help explain your problem.
validations:
required: false
- type: checkboxes
attributes:
label: I have checked existing issues, dicussion and documentation
description: You agree to check all the resources above before opening a new issue.
options:
- label: I confirm I have checked existing issues, dicussion and documentation.
required: true

View File

@ -1,14 +0,0 @@
---
name: Feature Request
about: Suggest an idea for this project
title: ''
labels: Feature 💡
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.

View File

@ -0,0 +1,49 @@
name: Feature Request
description: Suggest an idea for this project
labels: 'Feature 💡'
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this request!
It's okay to leave some blank if it doesn't apply to your request.
- type: input
attributes:
label: Related area
description: Please briefly explain the area of your Feature Request.
placeholder: eg. new port support, device stack, class driver ...
validations:
required: true
- type: input
attributes:
label: Hardware specification
description: Please provide if your proposal depends on specific Hardware.
placeholder: eg. rp2040, samd51 ...
validations:
required: true
- type: textarea
attributes:
label: Is your feature request related to a problem?
description: Please provide a clear and concise description of what the problem is. Add relevant issue link.
placeholder: ex. I'm facing the issue/missing function...
validations:
required: true
- type: textarea
attributes:
label: Describe the solution you'd like
description: Please provide a clear and concise description of what you want to happen.
placeholder: ex. When using this function...
validations:
required: true
- type: checkboxes
attributes:
label: I have checked existing issues, dicussion and documentation
description: You agree to check all the resources above before opening a new issue.
options:
- label: I confirm I have checked existing issues, dicussion and documentation.
required: true

View File

@ -43,7 +43,7 @@ The stack supports the following MCUs:
- **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505
- **NXP:**
- iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064
- iMX RT Series: RT10xx, RT11xx
- Kinetis: KL25, K32L2
- LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55
@ -51,7 +51,7 @@ The stack supports the following MCUs:
- **Renesas:** RX63N, RX65N, RX72N
- **Silabs:** EFM32GG
- **Sony:** CXD56
- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, G4, L0, L1, L4, L4+
- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, G4, L0, L1, L4, L4+, WB
- **TI:** MSP430, MSP432E4, TM4C123
- **ValentyUSB:** eptri
@ -94,8 +94,8 @@ TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR)
- `RT-Thread <https://github.com/RT-Thread/rt-thread>`_: `repo <https://github.com/RT-Thread-packages/tinyusb>`_
- **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its `own repo <https://github.com/hathach/mynewt-tinyusb-example>`_
Local Docs
==========
Docs
====
- Info

View File

@ -2,6 +2,64 @@
Changelog
*********
0.14.0
======
- Improve compiler support for CCRX and IAR
- Add timeout to osal_queue_receive()
- Add tud_task_ext(timeout, in_isr) as generic version of tud_task(). Same as tuh_task_ext(), tuh_task()
- Enable more warnings -Wnull-dereference -Wuninitialized -Wunused -Wredundant-decls -Wconversion
- Add new examples
- host/bare_api to demonstrate generic (app-level) enumeration and endpoint transfer
- dual/host_hid_to_device_cdc to run both device and host stack concurrently, get HID report from host and print out to device CDC. This example only work with multiple-controller MCUs and rp2040 with the help of pio-usb as added controller.
Controller Driver (DCD & HCD)
-----------------------------
- Enhance rhports management to better support dual roles
- CFG_TUD_ENABLED/CFG_TUH_ENABLED, CFG_TUD_MAX_SPEED/CFG_TUH_MAX_SPEED can be used to replace CFG_TUSB_RHPORT0_MODE/CFG_TUSB_RHPORT1_MODE
- tud_init(rphort), tuh_init(rhport) can be used to init stack on specified roothub port (controller) instead of tusb_init(void)
- Add dcd/hcd port specific defines TUP_ (stand for tinyusb port-specific)
- [dwc2]
- Update to support stm32 h72x, h73x with only 1 otg controller
- Fix overwrite with grstctl when disable endpoint
- [EHCI] Fix an issue with EHCI driver
- [msp430] Fix for possible bug in msp430-elf-gcc 9.3.0
- [nrf5x] Fix DMA access race condition using atomic function
- [pic32] Fix PIC32 santiy
- [rp2040]
- Add PICO-PIO-USB as controller (device/host) support for rp2040
- Use shared IRQ handlers, so user can also hook the USB IRQ
- Fix resumed signal not reported to device stack
- [stm32fsdev] Add support for stm32wb55
Device Stack
------------
- [Audio] Add support for feedback endpoint computation
- New API tud_audio_feedback_params_cb(), tud_audio_feedback_interval_isr().
- Supported computation method are: frequency with fixed/float or power of 2. Feedback with fifo count is not yet supported.
- Fix nitfs (should be 3) in TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR
- Fix typo in audiod_rx_done_cb()
- [DFU] Fix coexistence with other interfaces BTH, RNDIS
- [MSC] Fix inquiry response additional length field
- [Venndor] Improve write performance
Host Stack
----------
- Add new API tuh_configure(rhport, cfg_id, cfg_param) for dynamnic port specific behavior configuration
- [HID] Open OUT endpoint if available
- [Hub] hub clear port and device interrupts
- [USBH] Major improvement
- Rework usbh control transfer with complete callback. New API tuh_control_xfer() though still only carry 1 usbh (no queueing) at a time.
- Add generic endpoint transfer with tuh_edpt_open(), tuh_edpt_xfer(). Require `CFG_TUH_API_EDPT_XFER=1`
- Support app-level enumeration with new APIs
- tuh_descriptor_get(), tuh_descriptor_get_device(), tuh_descriptor_get_configuration(), tuh_descriptor_get_hid_report()
- tuh_descriptor_get_string(), tuh_descriptor_get_manufacturer_string(), tuh_descriptor_get_product_string(), tuh_descriptor_get_serial_string()
- Also add _sync() as sync/blocking version for above APIs
0.13.0
======

View File

@ -50,16 +50,7 @@ Some TinyUSB examples also requires external submodule libraries in ``/lib`` suc
$ git submodule update --init lib
In addition, MCU driver submodule is also needed to provide low-level MCU peripheral's driver. To download these depencies for your board, run the ``get-dpes`` as follow.
.. code-block::
$ make BOARD=feather_nrf52840_express get-deps
Some modules will also require a module-specific SDK (e.g. RP2040) or binary (e.g. Sony Spresense) to build examples.
Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``/examples/device/99-tinyusb.rules`` file to /etc/udev/rules.d/ then run ``sudo udevadm control --reload-rules && sudo udevadm trigger`` is good enough.
Some ports will also require a port-specific SDK (e.g. RP2040) or binary (e.g. Sony Spresense) to build examples. They are out of scope for tinyusb, you should download/install it first according to its manufacturer guide.
Build
^^^^^
@ -70,6 +61,13 @@ To build example, first change directory to an example folder.
$ cd examples/device/cdc_msc
Before building, we need to download MCU driver submodule to provide low-level MCU peripheral's driver first. Run the ``get-dpes`` target in one of the example folder as follow. You only need to do this once per mcu
.. code-block::
$ make BOARD=feather_nrf52840_express get-deps
Some modules (e.g. RP2040 and ESP32s2) require the project makefiles to be customized using CMake. If necessary apply any setup steps for the platform's SDK.
Then compile with ``make BOARD=[board_name] all``\ , for example
@ -79,6 +77,7 @@ Then compile with ``make BOARD=[board_name] all``\ , for example
$ make BOARD=feather_nrf52840_express all
Note: ``BOARD`` can be found as directory name in ``hw/bsp``\ , either in its family/boards or directly under bsp (no family).
Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``/examples/device/99-tinyusb.rules`` file to /etc/udev/rules.d/ then run ``sudo udevadm control --reload-rules && sudo udevadm trigger`` is good enough.
Port Selection
~~~~~~~~~~~~~~

View File

@ -41,6 +41,8 @@ Supported MCUs
| | NUC505 | ✔ | | ✔ | | |
+--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
| NXP | iMXRT | RT10xx | ✔ | ✔ | ✔ | ci_hs | |
| | +-------------+--------+------+-----------+-------------------+--------------+
| | | RT11xx | ✔ | ✔ | ✔ | ci_hs | |
| +---------+-------------+--------+------+-----------+-------------------+--------------+
| | Kinetis | KL25 | ✔ | ⚠ | ✖ | | |
| | +-------------+--------+------+-----------+-------------------+--------------+
@ -58,7 +60,7 @@ Supported MCUs
| | +-------------+--------+------+-----------+-------------------+--------------+
| | | 55 | ✔ | | ✔ | lpc_ip3511 | |
+--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
| Raspberry Pi | RP2040 | ✔ | ✔ | ✖ | rp2040 | |
| Raspberry Pi | RP2040 | ✔ | ✔ | ✖ | rp2040, pio_usb | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
| Renesas | RX 63N, 65N, 72N | ✔ | ✔ | ✖ | usba | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
@ -93,6 +95,8 @@ Supported MCUs
| | L4+ | ✔ | | | dwc2 | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
| | U5 | ⚠ | | | dwc2 | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
| | WBx5 | ✔ | | | stm32_fsdev | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
| TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
@ -239,6 +243,7 @@ iMX RT
- `MIMX RT1060 Evaluation Kit <https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/mimxrt1060-evk-i.mx-rt1060-evaluation-kit:MIMXRT1060-EVK>`__
- `MIMX RT1064 Evaluation Kit <https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/mimxrt1064-evk-i.mx-rt1064-evaluation-kit:MIMXRT1064-EVK>`__
- `Teensy 4.0 Development Board <https://www.pjrc.com/store/teensy40.html>`__
- `Teensy 4.1 Development Board <https://www.pjrc.com/store/teensy41.html>`__
Kinetis
^^^^^^^
@ -377,6 +382,10 @@ L4
- `STM32 L4P5zg Nucleo <https://www.st.com/en/evaluation-tools/nucleo-l4p5zg.html>`__
- `STM32 L4R5zi Nucleo <https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html>`__
WB
^^
- `STM32 WB55 Nucleo <https://www.st.com/en/evaluation-tools/p-nucleo-wb55.html>`__
TI
--

View File

@ -3,4 +3,5 @@ mcu:LPC13XX
mcu:NUC121
mcu:SAMD11
mcu:SAME5X
mcu:SAMG
mcu:SAMG
board:stm32l052dap52

View File

@ -0,0 +1,169 @@
/*
*****************************************************************************
**
** File : LinkerScript.ld
**
** Abstract : Linker script for STM32L052K8Ux Device with
** 64KByte FLASH, 8KByte RAM
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used.
**
** Target : STMicroelectronics STM32
**
**
** Distribution: The file is distributed as is, without any warranty
** of any kind.
**
** (c)Copyright Ac6.
** You may use this file as-is or modify it according to the needs of your
** project. Distribution of this file (unmodified or modified) is not
** permitted. Ac6 permit registered System Workbench for MCU users the
** rights to distribute the assembled, compiled & linked contents of this
** file as part of an application binary file, provided that it is built
** using the System Workbench for MCU toolchain.
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20002000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = 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
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}

View File

@ -0,0 +1,109 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2020, Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#ifndef BOARD_H_
#define BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
// LED
#define LED_PORT GPIOB
#define LED_PIN GPIO_PIN_4
#define LED_STATE_ON 1
// Button
#define BUTTON_PORT GPIOA
#define BUTTON_PIN GPIO_PIN_6
#define BUTTON_STATE_ACTIVE 0
// UART
#define UART_DEV USART2
#define UART_CLK_EN __HAL_RCC_USART2_CLK_ENABLE
#define UART_GPIO_PORT GPIOA
#define UART_GPIO_AF GPIO_AF4_USART2
#define UART_TX_PIN GPIO_PIN_2
#define UART_RX_PIN GPIO_PIN_3
//--------------------------------------------------------------------+
// RCC Clock
//--------------------------------------------------------------------+
static inline void board_stm32l0_clock_init(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
static RCC_CRSInitTypeDef RCC_CRSInitStruct;
/* Enable HSI Oscillator to be used as System clock source
Enable HSI48 Oscillator to be used as USB clock source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSI48;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
/* Select HSI48 as USB clock source */
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
/* Select HSI as system clock source and configure the HCLK, PCLK1 and PCLK2
clock dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
/*Configure the clock recovery system (CRS)**********************************/
/*Enable CRS Clock*/
__HAL_RCC_CRS_CLK_ENABLE();
/* Default Synchro Signal division factor (not divided) */
RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1;
/* Set the SYNCSRC[1:0] bits according to CRS_Source value */
RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB;
/* HSI48 is synchronized with USB SOF at 1KHz rate */
RCC_CRSInitStruct.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000);
RCC_CRSInitStruct.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT;
/* Set the TRIM[5:0] to the default value*/
RCC_CRSInitStruct.HSI48CalibrationValue = 0x20;
/* Start automatic synchronization */
HAL_RCCEx_CRSConfig (&RCC_CRSInitStruct);
}
static inline void board_vbus_sense_init(void)
{
}
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H_ */

View File

@ -0,0 +1,11 @@
CFLAGS += -DSTM32L052xx -DCFG_EXAMPLE_VIDEO_READONLY
LD_FILE = $(BOARD_PATH)/STM32L052K8Ux_FLASH.ld
SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l052xx.s
# For flash-jlink target
JLINK_DEVICE = stm32l052k8
# flash target using on-board stlink
flash: flash-stlink

181
hw/bsp/stm32l0/family.c Normal file
View File

@ -0,0 +1,181 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This file is part of the TinyUSB stack.
*/
#include "stm32l0xx_hal.h"
#include "bsp/board.h"
#include "board.h"
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
void USB_IRQHandler(void)
{
tud_int_handler(0);
}
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
UART_HandleTypeDef UartHandle;
void board_init(void)
{
board_stm32l0_clock_init();
// Enable All GPIOs clocks
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
// Enable UART Clock
UART_CLK_EN();
#if CFG_TUSB_OS == OPT_OS_NONE
// 1ms tick timer
SysTick_Config(SystemCoreClock / 1000);
#elif CFG_TUSB_OS == OPT_OS_FREERTOS
// Explicitly disable systick to prevent its ISR runs before scheduler start
SysTick->CTRL &= ~1U;
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
#endif
// LED
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);
// Button
GPIO_InitStruct.Pin = BUTTON_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);
// Uart
GPIO_InitStruct.Pin = UART_TX_PIN | UART_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = UART_GPIO_AF;
HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct);
UartHandle.Instance = UART_DEV;
UartHandle.Init.BaudRate = CFG_BOARD_UART_BAUDRATE;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&UartHandle);
// USB Pins
// Configure USB DM and DP pins. This is optional, and maintained only for user guidance.
GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// USB Clock enable
__HAL_RCC_USB_CLK_ENABLE();
}
//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
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)
{
return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);
}
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);
return len;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler (void)
{
system_ticks++;
}
uint32_t board_millis(void)
{
return system_ticks;
}
#endif
void HardFault_Handler (void)
{
asm("bkpt");
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
(void) file; (void) line;
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void)
{
}

40
hw/bsp/stm32l0/family.mk Normal file
View File

@ -0,0 +1,40 @@
ST_FAMILY = l0
DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
include $(TOP)/$(BOARD_PATH)/board.mk
CFLAGS += \
-flto \
-mthumb \
-mabi=aapcs \
-mcpu=cortex-m0plus \
-mfloat-abi=soft \
-nostdlib -nostartfiles \
-DCFG_EXAMPLE_MSC_READONLY \
-DCFG_EXAMPLE_VIDEO_READONLY \
-DCFG_TUSB_MCU=OPT_MCU_STM32L0
# suppress warning caused by vendor mcu driver
CFLAGS += -Wno-error=unused-parameter -Wno-error=redundant-decls -Wno-error=cast-align -Wno-error=maybe-uninitialized
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.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_uart.c
INC += \
$(TOP)/$(BOARD_PATH) \
$(TOP)/lib/CMSIS_5/CMSIS/Core/Include \
$(TOP)/$(ST_CMSIS)/Include \
$(TOP)/$(ST_HAL_DRIVER)/Inc
# For freeRTOS port source
FREERTOS_PORT = ARM_CM0

View File

@ -0,0 +1,338 @@
/**
******************************************************************************
* @file stm32l0xx_hal_conf.h
* @author MCD Application Team
* @brief HAL configuration template file.
* This file should be copied to the application folder and renamed
* to stm32l0xx_hal_conf.h.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32L0xx_HAL_CONF_H
#define __STM32L0xx_HAL_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* ########################## Module Selection ############################## */
/**
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_MODULE_ENABLED
/*#define HAL_ADC_MODULE_ENABLED */
/*#define HAL_COMP_MODULE_ENABLED */
/*#define HAL_CRC_MODULE_ENABLED */
/*#define HAL_CRYP_MODULE_ENABLED */
/*#define HAL_DAC_MODULE_ENABLED */
#define HAL_DMA_MODULE_ENABLED
/*#define HAL_FIREWALL_MODULE_ENABLED */
#define HAL_FLASH_MODULE_ENABLED
#define HAL_GPIO_MODULE_ENABLED
/*#define HAL_I2C_MODULE_ENABLED */
/*#define HAL_I2S_MODULE_ENABLED */
/*#define HAL_IWDG_MODULE_ENABLED */
/*#define HAL_LCD_MODULE_ENABLED */
/*#define HAL_LPTIM_MODULE_ENABLED */
#define HAL_PWR_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
/*#define HAL_RNG_MODULE_ENABLED */
/*#define HAL_RTC_MODULE_ENABLED */
/*#define HAL_SPI_MODULE_ENABLED */
/*#define HAL_TIM_MODULE_ENABLED */
/*#define HAL_TSC_MODULE_ENABLED */
#define HAL_UART_MODULE_ENABLED
/*#define HAL_USART_MODULE_ENABLED */
/*#define HAL_IRDA_MODULE_ENABLED */
/*#define HAL_SMARTCARD_MODULE_ENABLED */
/*#define HAL_SMBUS_MODULE_ENABLED */
/*#define HAL_WWDG_MODULE_ENABLED */
#define HAL_CORTEX_MODULE_ENABLED
#define HAL_PCD_MODULE_ENABLED
/* ########################## Oscillator Values adaptation ####################*/
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief Internal Multiple Speed oscillator (MSI) default value.
* This value is the default MSI range value after Reset.
*/
#if !defined (MSI_VALUE)
#define MSI_VALUE ((uint32_t)2097152U) /*!< Value of the Internal oscillator in Hz*/
#endif /* MSI_VALUE */
/**
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL).
*/
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @brief Internal High Speed oscillator for USB (HSI48) value.
*/
#if !defined (HSI48_VALUE)
#define HSI48_VALUE ((uint32_t)48000000U) /*!< Value of the Internal High Speed oscillator for USB in Hz.
The real value may vary depending on the variations
in voltage and temperature. */
#endif /* HSI48_VALUE */
/**
* @brief Internal Low Speed oscillator (LSI) value.
*/
#if !defined (LSI_VALUE)
#define LSI_VALUE ((uint32_t)37000U) /*!< LSI Typical Value in Hz*/
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
in voltage and temperature.*/
/**
* @brief External Low Speed oscillator (LSE) value.
* This value is used by the UART, RTC HAL module to compute the system frequency
*/
#if !defined (LSE_VALUE)
#define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External oscillator in Hz*/
#endif /* LSE_VALUE */
/**
* @brief Time out for LSE start up value in ms.
*/
#if !defined (LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */
/* Tip: To avoid modifying this file each time you need to use different HSE,
=== you can define the HSE value in your toolchain compiler preprocessor. */
/* ########################### System Configuration ######################### */
/**
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY (((uint32_t)1U<<__NVIC_PRIO_BITS) - 1U) /*!< tick interrupt priority */
#define USE_RTOS 0U
#define PREFETCH_ENABLE 1U
#define PREREAD_ENABLE 0U
#define BUFFER_CACHE_DISABLE 0U
/* ########################## Assert Selection ############################## */
/**
* @brief Uncomment the line below to expanse the "assert_param" macro in the
* HAL drivers code
*/
/* #define USE_FULL_ASSERT 1U */
/* ################## Register callback feature configuration ############### */
/**
* @brief Set below the peripheral configuration to "1U" to add the support
* of HAL callback registration/deregistration feature for the HAL
* driver(s). This allows user application to provide specific callback
* functions thanks to HAL_PPP_RegisterCallback() rather than overwriting
* the default weak callback functions (see each stm32l0xx_hal_ppp.h file
* for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef
* for each PPP peripheral).
*/
#define USE_HAL_ADC_REGISTER_CALLBACKS 0U
#define USE_HAL_COMP_REGISTER_CALLBACKS 0U
#define USE_HAL_DAC_REGISTER_CALLBACKS 0U
#define USE_HAL_I2C_REGISTER_CALLBACKS 0U
#define USE_HAL_I2S_REGISTER_CALLBACKS 0U
#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U
#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U
#define USE_HAL_PCD_REGISTER_CALLBACKS 0U
#define USE_HAL_RNG_REGISTER_CALLBACKS 0U
#define USE_HAL_RTC_REGISTER_CALLBACKS 0U
#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U
#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U
#define USE_HAL_SPI_REGISTER_CALLBACKS 0U
#define USE_HAL_TIM_REGISTER_CALLBACKS 0U
#define USE_HAL_TSC_REGISTER_CALLBACKS 0U
#define USE_HAL_UART_REGISTER_CALLBACKS 0U
#define USE_HAL_USART_REGISTER_CALLBACKS 0U
#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U
/* ################## SPI peripheral configuration ########################## */
/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
* Activated: CRC code is present inside driver
* Deactivated: CRC code cleaned from driver
*/
#define USE_SPI_CRC 1U
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include module's header file
*/
#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32l0xx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */
#ifdef HAL_GPIO_MODULE_ENABLED
#include "stm32l0xx_hal_gpio.h"
#endif /* HAL_GPIO_MODULE_ENABLED */
#ifdef HAL_DMA_MODULE_ENABLED
#include "stm32l0xx_hal_dma.h"
#endif /* HAL_DMA_MODULE_ENABLED */
#ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32l0xx_hal_cortex.h"
#endif /* HAL_CORTEX_MODULE_ENABLED */
#ifdef HAL_ADC_MODULE_ENABLED
#include "stm32l0xx_hal_adc.h"
#endif /* HAL_ADC_MODULE_ENABLED */
#ifdef HAL_COMP_MODULE_ENABLED
#include "stm32l0xx_hal_comp.h"
#endif /* HAL_COMP_MODULE_ENABLED */
#ifdef HAL_CRC_MODULE_ENABLED
#include "stm32l0xx_hal_crc.h"
#endif /* HAL_CRC_MODULE_ENABLED */
#ifdef HAL_CRYP_MODULE_ENABLED
#include "stm32l0xx_hal_cryp.h"
#endif /* HAL_CRYP_MODULE_ENABLED */
#ifdef HAL_DAC_MODULE_ENABLED
#include "stm32l0xx_hal_dac.h"
#endif /* HAL_DAC_MODULE_ENABLED */
#ifdef HAL_FIREWALL_MODULE_ENABLED
#include "stm32l0xx_hal_firewall.h"
#endif /* HAL_FIREWALL_MODULE_ENABLED */
#ifdef HAL_FLASH_MODULE_ENABLED
#include "stm32l0xx_hal_flash.h"
#endif /* HAL_FLASH_MODULE_ENABLED */
#ifdef HAL_I2C_MODULE_ENABLED
#include "stm32l0xx_hal_i2c.h"
#endif /* HAL_I2C_MODULE_ENABLED */
#ifdef HAL_I2S_MODULE_ENABLED
#include "stm32l0xx_hal_i2s.h"
#endif /* HAL_I2S_MODULE_ENABLED */
#ifdef HAL_IWDG_MODULE_ENABLED
#include "stm32l0xx_hal_iwdg.h"
#endif /* HAL_IWDG_MODULE_ENABLED */
#ifdef HAL_LCD_MODULE_ENABLED
#include "stm32l0xx_hal_lcd.h"
#endif /* HAL_LCD_MODULE_ENABLED */
#ifdef HAL_LPTIM_MODULE_ENABLED
#include "stm32l0xx_hal_lptim.h"
#endif /* HAL_LPTIM_MODULE_ENABLED */
#ifdef HAL_PWR_MODULE_ENABLED
#include "stm32l0xx_hal_pwr.h"
#endif /* HAL_PWR_MODULE_ENABLED */
#ifdef HAL_RNG_MODULE_ENABLED
#include "stm32l0xx_hal_rng.h"
#endif /* HAL_RNG_MODULE_ENABLED */
#ifdef HAL_RTC_MODULE_ENABLED
#include "stm32l0xx_hal_rtc.h"
#endif /* HAL_RTC_MODULE_ENABLED */
#ifdef HAL_SPI_MODULE_ENABLED
#include "stm32l0xx_hal_spi.h"
#endif /* HAL_SPI_MODULE_ENABLED */
#ifdef HAL_TIM_MODULE_ENABLED
#include "stm32l0xx_hal_tim.h"
#endif /* HAL_TIM_MODULE_ENABLED */
#ifdef HAL_TSC_MODULE_ENABLED
#include "stm32l0xx_hal_tsc.h"
#endif /* HAL_TSC_MODULE_ENABLED */
#ifdef HAL_UART_MODULE_ENABLED
#include "stm32l0xx_hal_uart.h"
#endif /* HAL_UART_MODULE_ENABLED */
#ifdef HAL_USART_MODULE_ENABLED
#include "stm32l0xx_hal_usart.h"
#endif /* HAL_USART_MODULE_ENABLED */
#ifdef HAL_IRDA_MODULE_ENABLED
#include "stm32l0xx_hal_irda.h"
#endif /* HAL_IRDA_MODULE_ENABLED */
#ifdef HAL_SMARTCARD_MODULE_ENABLED
#include "stm32l0xx_hal_smartcard.h"
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
#ifdef HAL_SMBUS_MODULE_ENABLED
#include "stm32l0xx_hal_smbus.h"
#endif /* HAL_SMBUS_MODULE_ENABLED */
#ifdef HAL_WWDG_MODULE_ENABLED
#include "stm32l0xx_hal_wwdg.h"
#endif /* HAL_WWDG_MODULE_ENABLED */
#ifdef HAL_PCD_MODULE_ENABLED
#include "stm32l0xx_hal_pcd.h"
#endif /* HAL_PCD_MODULE_ENABLED */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* __STM32L0xx_HAL_CONF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -11,7 +11,8 @@ repo.versions:
"0.11.0": "0.11.0"
"0.12.0": "0.12.0"
"0.13.0": "0.13.0"
"0.14.0": "0.14.0"
"0-dev": "0.0.0" # master
"0-latest": "0.13.0" # latest stable release
"0-latest": "0.14.0" # latest stable release

View File

@ -167,6 +167,8 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc,
uint8_t alt_count = 0;
uint16_t drv_len = 0;
TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU, 0);
while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU)
{
TU_ASSERT(max_len > drv_len, 0);

View File

@ -44,6 +44,7 @@ typedef struct
uint8_t status_change; // data from status change interrupt endpoint
hub_port_status_response_t port_status;
hub_status_response_t hub_status;
} hub_interface_t;
CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB];
@ -85,7 +86,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
{
.bmRequestType_bit =
{
.recipient = TUSB_REQ_RCPT_OTHER,
.recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_OUT
},
@ -117,7 +118,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
{
.bmRequestType_bit =
{
.recipient = TUSB_REQ_RCPT_OTHER,
.recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_OUT
},
@ -149,7 +150,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp,
{
.bmRequestType_bit =
{
.recipient = TUSB_REQ_RCPT_OTHER,
.recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_IN
},
@ -313,7 +314,8 @@ static void config_port_power_complete (tuh_xfer_t* xfer)
// Connection Changes
//--------------------------------------------------------------------+
static void connection_get_status_complete (tuh_xfer_t* xfer);
static void hub_port_get_status_complete (tuh_xfer_t* xfer);
static void hub_get_status_complete (tuh_xfer_t* xfer);
static void connection_clear_conn_change_complete (tuh_xfer_t* xfer);
static void connection_port_reset_complete (tuh_xfer_t* xfer);
@ -326,19 +328,31 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32
hub_interface_t* p_hub = get_itf(dev_addr);
TU_LOG2(" Port Status Change = 0x%02X\r\n", p_hub->status_change);
TU_LOG2(" Hub Status Change = 0x%02X\r\n", p_hub->status_change);
// Hub ignore bit0 in status change
for (uint8_t port=1; port <= p_hub->port_count; port++)
// Hub bit 0 is for the hub device events
if (tu_bit_test(p_hub->status_change, 0))
{
if ( tu_bit_test(p_hub->status_change, port) )
if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false)
{
if (hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete, 0) == false)
//Hub status control transfer failed, retry
hub_edpt_status_xfer(dev_addr);
}
}
else
{
// Hub bits 1 to n are hub port events
for (uint8_t port=1; port <= p_hub->port_count; port++)
{
if ( tu_bit_test(p_hub->status_change, port) )
{
//Hub status control transfer failed, retry
hub_edpt_status_xfer(dev_addr);
if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false)
{
//Hub status control transfer failed, retry
hub_edpt_status_xfer(dev_addr);
}
break;
}
break;
}
}
@ -347,7 +361,36 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32
return true;
}
static void connection_get_status_complete (tuh_xfer_t* xfer)
static void hub_clear_feature_complete_stub(tuh_xfer_t* xfer)
{
TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
hub_edpt_status_xfer(xfer->daddr);
}
static void hub_get_status_complete (tuh_xfer_t* xfer)
{
TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
uint8_t const daddr = xfer->daddr;
hub_interface_t* p_hub = get_itf(daddr);
uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
TU_ASSERT(port_num == 0 , );
TU_LOG2("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, p_hub->hub_status.change.value);
if (p_hub->hub_status.change.local_power_source)
{
TU_LOG2("HUB Local Power Change, addr = %u\r\n", daddr);
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, hub_clear_feature_complete_stub, 0);
}
else if (p_hub->hub_status.change.over_current)
{
TU_LOG1("HUB Over Current, addr = %u\r\n", daddr);
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, hub_clear_feature_complete_stub, 0);
}
}
static void hub_port_get_status_complete (tuh_xfer_t* xfer)
{
TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
@ -365,7 +408,24 @@ static void connection_get_status_complete (tuh_xfer_t* xfer)
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0);
}else
{
// Other changes are: Enable, Suspend, Over Current, Reset, L1 state
// Clear other port status change interrupts. TODO Not currently handled - just cleared.
if (p_hub->port_status.change.port_enable)
{
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_ENABLE_CHANGE, hub_clear_feature_complete_stub, 0);
}
else if (p_hub->port_status.change.suspend)
{
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_SUSPEND_CHANGE, hub_clear_feature_complete_stub, 0);
}
else if (p_hub->port_status.change.over_current)
{
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, hub_clear_feature_complete_stub, 0);
}
else if (p_hub->port_status.change.reset)
{
hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, hub_clear_feature_complete_stub, 0);
}
// Other changes are: L1 state
// TODO clear change
// prepare for next hub status

View File

@ -28,6 +28,7 @@
#if CFG_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_NRF5X
#include <stdatomic.h>
#include "nrf.h"
#include "nrf_clock.h"
#include "nrf_power.h"
@ -72,6 +73,7 @@ typedef struct
// nRF will auto accept OUT packet after DMA is done
// indicate packet is already ACK
volatile bool data_received;
volatile bool started;
// Set to true when data was transferred from RAM to ISO IN output buffer.
// New data can be put in ISO IN output buffer after SOF.
@ -79,9 +81,6 @@ typedef struct
} xfer_td_t;
static osal_mutex_def_t dcd_mutex_def;
static osal_mutex_t dcd_mutex;
// Data for managing dcd
static struct
{
@ -90,7 +89,7 @@ static struct
xfer_td_t xfer[EP_CBI_COUNT + 1][2];
// nRF can only carry one DMA at a time, this is used to guard the access to EasyDMA
volatile bool dma_running;
atomic_bool dma_running;
}_dcd;
/*------------------------------------------------------------------*/
@ -121,8 +120,6 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void)
// helper to start DMA
static void start_dma(volatile uint32_t* reg_startep)
{
_dcd.dma_running = true;
(*reg_startep) = 1;
__ISB(); __DSB();
@ -131,50 +128,18 @@ static void start_dma(volatile uint32_t* reg_startep)
// Therefore dma_pending is corrected right away
if ( (reg_startep == &NRF_USBD->TASKS_EP0STATUS) || (reg_startep == &NRF_USBD->TASKS_EP0RCVOUT) )
{
_dcd.dma_running = false;
atomic_flag_clear(&_dcd.dma_running);
}
}
// only 1 EasyDMA can be active at any time
// TODO use Cortex M4 LDREX and STREX command (atomic) to have better mutex access to EasyDMA
// since current implementation does not 100% guarded against race condition
static void edpt_dma_start(volatile uint32_t* reg_startep)
{
// Called in critical section i.e within USB ISR, or USB/Global interrupt disabled
if ( is_in_isr() || __get_PRIMASK() || !NVIC_GetEnableIRQ(USBD_IRQn) )
if ( atomic_flag_test_and_set(&_dcd.dma_running) )
{
if (_dcd.dma_running)
{
//use usbd task to defer later
usbd_defer_func((osal_task_func_t) edpt_dma_start, (void*) (uintptr_t) reg_startep, true);
}else
{
start_dma(reg_startep);
}
usbd_defer_func((osal_task_func_t) edpt_dma_start, (void*) (uintptr_t) reg_startep, true);
}else
{
// Called in non-critical thread-mode, should be 99% of the time.
// Should be safe to blocking wait until previous DMA transfer complete
uint8_t const rhport = 0;
bool started = false;
osal_mutex_lock(dcd_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
while(!started)
{
// LDREX/STREX may be needed in form of std atomic (required C11) or
// use osal mutex to guard against multiple core MCUs such as nRF53
dcd_int_disable(rhport);
if ( !_dcd.dma_running )
{
start_dma(reg_startep);
started = true;
}
dcd_int_enable(rhport);
// osal_yield();
}
osal_mutex_unlock(dcd_mutex);
start_dma(reg_startep);
}
}
@ -182,7 +147,7 @@ static void edpt_dma_start(volatile uint32_t* reg_startep)
static void edpt_dma_end(void)
{
TU_ASSERT(_dcd.dma_running, );
_dcd.dma_running = false;
atomic_flag_clear(&_dcd.dma_running);
}
// helper getting td
@ -191,12 +156,26 @@ static inline xfer_td_t* get_td(uint8_t epnum, uint8_t dir)
return &_dcd.xfer[epnum][dir];
}
static void xact_out_dma(uint8_t epnum);
// Function wraps xact_out_dma which wants uint8_t while usbd_defer_func wants void (*)(void *)
static void xact_out_dma_wrapper(void *epnum)
{
xact_out_dma((uint8_t)((uintptr_t)epnum));
}
// Start DMA to move data from Endpoint -> RAM
static void xact_out_dma(uint8_t epnum)
{
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
uint32_t xact_len;
// DMA can't be active during read of SIZE.EPOUT or SIZE.ISOOUT, so try to lock,
// If already running deffer call regardless if it was called from ISR or task,
if ( atomic_flag_test_and_set(&_dcd.dma_running) )
{
usbd_defer_func((osal_task_func_t)xact_out_dma_wrapper, (void *)(uint32_t)epnum, is_in_isr());
return;
}
if (epnum == EP_ISO_NUM)
{
xact_len = NRF_USBD->SIZE.ISOOUT;
@ -204,6 +183,7 @@ static void xact_out_dma(uint8_t epnum)
if (xact_len & USBD_SIZE_ISOOUT_ZERO_Msk)
{
xact_len = 0;
atomic_flag_clear(&_dcd.dma_running);
}
else
{
@ -211,7 +191,7 @@ static void xact_out_dma(uint8_t epnum)
NRF_USBD->ISOOUT.PTR = (uint32_t) xfer->buffer;
NRF_USBD->ISOOUT.MAXCNT = xact_len;
edpt_dma_start(&NRF_USBD->TASKS_STARTISOOUT);
start_dma(&NRF_USBD->TASKS_STARTISOOUT);
}
}
else
@ -223,7 +203,7 @@ static void xact_out_dma(uint8_t epnum)
NRF_USBD->EPOUT[epnum].PTR = (uint32_t) xfer->buffer;
NRF_USBD->EPOUT[epnum].MAXCNT = xact_len;
edpt_dma_start(&NRF_USBD->TASKS_STARTEPOUT[epnum]);
start_dma(&NRF_USBD->TASKS_STARTEPOUT[epnum]);
}
}
@ -248,7 +228,6 @@ static void xact_in_dma(uint8_t epnum)
void dcd_init (uint8_t rhport)
{
TU_LOG1("dcd init\r\n");
dcd_mutex = osal_mutex_create(&dcd_mutex_def);
(void) rhport;
}
@ -471,17 +450,10 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
xfer_td_t* xfer = get_td(epnum, dir);
if (!is_in_isr()) {
osal_mutex_lock(dcd_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
dcd_int_disable(rhport);
}
TU_ASSERT(!xfer->started);
xfer->buffer = buffer;
xfer->total_len = total_bytes;
xfer->actual_len = 0;
if (!is_in_isr()) {
dcd_int_enable(rhport);
osal_mutex_unlock(dcd_mutex);
}
// Control endpoint with zero-length packet and opposite direction to 1st request byte --> status stage
bool const control_status = (epnum == 0 && total_bytes == 0 && dir != tu_edpt_dir(NRF_USBD->BMREQUESTTYPE));
@ -496,13 +468,20 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
}
else if ( dir == TUSB_DIR_OUT )
{
xfer->started = true;
if ( epnum == 0 )
{
// Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
edpt_dma_start(&NRF_USBD->TASKS_EP0RCVOUT);
}else
{
if ( xfer->data_received && xfer->total_len > xfer->actual_len)
// started just set, it could start DMA transfer if interrupt was trigger after this line
// code only needs to start transfer (from Endpoint to RAM) when data_received was set
// before started was set. If started is NOT set but data_received is, it means that
// current transfer was already finished and next data is already present in endpoint and
// can be consumed by future transfer
__ISB(); __DSB();
if ( xfer->data_received && xfer->started )
{
// Data is already received previously
// start DMA to copy to SRAM
@ -804,7 +783,9 @@ void dcd_int_handler(uint8_t rhport)
}
}else
{
TU_ASSERT(xfer->started,);
xfer->total_len = xfer->actual_len;
xfer->started = false;
// CBI OUT complete
dcd_event_xfer_complete(0, epnum, xfer->actual_len, XFER_RESULT_SUCCESS, true);
@ -857,7 +838,7 @@ void dcd_int_handler(uint8_t rhport)
{
xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
if (xfer->actual_len < xfer->total_len)
if ( xfer->started && xfer->actual_len < xfer->total_len )
{
xact_out_dma(epnum);
}else

View File

@ -33,7 +33,7 @@ typedef int make_iso_compilers_happy;
#include "common/tusb_compiler.h"
#define TUSB_VERSION_MAJOR 0
#define TUSB_VERSION_MINOR 13
#define TUSB_VERSION_MINOR 14
#define TUSB_VERSION_REVISION 0
#define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION)
@ -223,7 +223,7 @@ typedef int make_iso_compilers_happy;
#define TUSB_OPT_DEVICE_ENABLED CFG_TUD_ENABLED
// highspeed support indicator
#define TUD_OPT_HIGH_SPEED (CFG_TUD_MAX_SPEED ? CFG_TUD_MAX_SPEED : TUP_RHPORT_HIGHSPEED)
#define TUD_OPT_HIGH_SPEED (CFG_TUD_MAX_SPEED ? (CFG_TUD_MAX_SPEED & OPT_MODE_HIGH_SPEED) : TUP_RHPORT_HIGHSPEED)
//------------- Roothub as Host -------------//