1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
19371: sys/usbus: check for the number of required and provided EPs in static configurations r=dylad a=gschorcht

### Contribution description

This PR provides a static check at compile time whether the number of EPs required in a static configuration does not exceed the number of EPs provided by the USB device.

#### Background

In issue #19359 the problem was reported that `usbus_cdc_ecm` didn't work together with `stdio_cdc_acm` on some STM32 boards. The reason for some of the boards was simply that the application tried to allocate more EPs than available and simply ignored this and just didn't work.

#### Solution

Since `auto_init_usb` uses a static configuration with exactly one USBUS stack instance and one USB device, at least in case `auto_init` is used a static check can be carried out to make sure that the number of EPs required by the application doesn't exceed the number of EPs provided by the USB device. For this purpose, each `usbus_*` module defines the number of IN and OUT EPs required by that module. Each USB device driver defines the number of EPs provided by USB device if it differs from the default of 8 EPs. During the auto initialization the total number of required IN and OUT EPs is then compared with the number of EPs provided by the USB device using a static assert.

### Testing procedure

1. Green CI
2. Compilation of
   ```python
   USEMODULE='stdio_cdc_acm' BOARD=nucleo-f439zi make -j8 -C tests/usbus_cdc_ecm
   ```
   should lead to compilation error
   ```python
   sys/auto_init/usb/auto_init_usb.c:81:1: error: static assertion failed: "Number of required IN endpoints exceeded"
    _Static_assert(USBUS_EP_IN_REQUIRED_NUMOF <= USBDEV_NUM_ENDPOINTS,
    ^~~~~~~~~~~~~~
   Makefile.base:146: recipe for target 'tests/usbus_cdc_ecm/bin/nucleo-f439zi/auto_init_usbus/auto_init_usb.o' failed
   ```
   while compilation of
   ```
   USEMODULE='stdio_cdc_acm' BOARD=nucleo-f767zi make -j8 -C tests/usbus_cdc_ecm
   ```
   should work.

### Issues/PRs references

Fixes issue #19359 partially.

19382: tests/pkg_nanors: use static allocation r=benpicco a=benpicco



Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
Co-authored-by: Benjamin Valentin <benpicco@beuth-hochschule.de>
This commit is contained in:
bors[bot] 2023-03-15 08:41:57 +00:00 committed by GitHub
commit fd38db6b38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 206 additions and 28 deletions

View File

@ -682,6 +682,13 @@ typedef struct {
#define WDT_HAS_STOP (1U)
/** @} */
/**
* @name USB device definitions
* @{
*/
#define USBDEV_NUM_ENDPOINTS 7 /**< Number of USB OTG FS endpoints including EP0 */
/** @} */
/* GPIO_LL's overrides */
#ifndef DOXYGEN

View File

@ -270,6 +270,11 @@ extern "C" {
* @brief Buffers have to be word aligned for DMA
*/
#define USBDEV_CPU_DMA_ALIGNMENT (4)
/**
* @brief Number of USB IN and OUT endpoints available
*/
#define USBDEV_NUM_ENDPOINTS DWC2_USB_OTG_FS_NUM_EP
/** @} */

View File

@ -271,6 +271,11 @@ extern "C" {
* @brief Buffers have to be word aligned for DMA
*/
#define USBDEV_CPU_DMA_ALIGNMENT (4)
/**
* @brief Number of USB IN and OUT endpoints available
*/
#define USBDEV_NUM_ENDPOINTS DWC2_USB_OTG_FS_NUM_EP
/** @} */
#ifdef __cplusplus

View File

@ -458,6 +458,13 @@ typedef struct {
#define RTT_MIN_FREQUENCY (1U) /**< minimum RTT frequency in Hz */
/** @} */
/**
* @name USB device definitions
* @{
*/
#define USBDEV_NUM_ENDPOINTS 4 /**< Number of USB OTG FS endpoints including EP0 */
/** @} */
/**
* @brief Enable the given peripheral clock
*

View File

@ -113,6 +113,57 @@ typedef struct {
#define HAVE_PTP_TIMER_SET_ABSOLUTE 1 /**< Native implementation available */
/** @} */
#if !DOXYGEN /* hide implementation details */
/**
* @name USB device definitions
* @{
*/
/* Detect the IP version based on the available register define */
#if defined(USB_OTG_GCCFG_NOVBUSSENS)
#define STM32_USB_OTG_CID_1x /**< USB OTG FS version 0x00001200 */
#elif defined(USB_OTG_GCCFG_VBDEN)
#define STM32_USB_OTG_CID_2x /**< USB OTG FS version 0x00002000 */
#elif defined(USB)
#define STM32_USB_FS_CID_1x /**< USB FS version 0x00001200 */
#endif
/**
* @brief Number of endpoints available with the OTG FS peripheral
* including the control endpoint
*/
#ifdef STM32_USB_OTG_CID_1x
#define STM32_USB_OTG_FS_NUM_EP (4) /**< OTG FS with 4 endpoints */
#elif defined(STM32_USB_OTG_CID_2x)
#define STM32_USB_OTG_FS_NUM_EP (6) /**< OTG FS with 6 endpoints */
#endif
/**
* @brief Number of endpoints available with the OTG HS peripheral
* including the control endpoint
*/
#ifdef STM32_USB_OTG_CID_1x
#define STM32_USB_OTG_HS_NUM_EP (6) /**< OTG HS with 6 endpoints */
#elif defined(STM32_USB_OTG_CID_2x)
#define STM32_USB_OTG_HS_NUM_EP (9) /**< OTG HS with 9 endpoints */
#endif
/**
* @brief Number of IN/OUT endpoints including EP0 as used by USBUS
*
* @note Since only a single number of EPs can be defined for USBUS that is
* valid for all devices, the smallest number of EPs must be used for
* multiple USB devices.
*/
#if defined(STM32_USB_OTG_FS_NUM_EP)
#define USBDEV_NUM_ENDPOINTS STM32_USB_OTG_FS_NUM_EP
#elif defined(STM32_USB_OTG_HS_NUM_EP)
#define USBDEV_NUM_ENDPOINTS STM32_USB_OTG_HS_NUM_EP
#else
#define USBDEV_NUM_ENDPOINTS 8
#endif
#endif /* !DOXYGEN */
#ifdef __cplusplus
}
#endif

View File

@ -41,42 +41,22 @@
#include <stdint.h>
#include <stdlib.h>
#include "periph_cpu.h"
#include "periph/usbdev.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Detect the IP version based on the available register define */
#if defined(USB_OTG_GCCFG_NOVBUSSENS)
#define STM32_USB_OTG_CID_1x /**< USB OTG FS version 0x00001200 */
#elif defined(USB_OTG_GCCFG_VBDEN)
#define STM32_USB_OTG_CID_2x /**< USB OTG FS version 0x00002000 */
#elif defined(USB)
#define STM32_USB_FS_CID_1x /**< USB FS version 0x00001200 */
#else
#error Unknown USB peripheral version
#endif
/**
* @brief Number of endpoints available with the OTG FS peripheral
* including the control endpoint
*/
#ifdef STM32_USB_OTG_CID_1x
#define DWC2_USB_OTG_FS_NUM_EP (4) /**< OTG FS with 4 endpoints */
#elif defined(STM32_USB_OTG_CID_2x)
#define DWC2_USB_OTG_FS_NUM_EP (6) /**< OTG FS with 6 endpoints */
#endif
#define DWC2_USB_OTG_FS_NUM_EP STM32_USB_OTG_FS_NUM_EP
/**
* @brief Number of endpoints available with the OTG HS peripheral
* including the control endpoint
*/
#ifdef STM32_USB_OTG_CID_1x
#define DWC2_USB_OTG_HS_NUM_EP (6) /**< OTG HS with 6 endpoints */
#elif defined(STM32_USB_OTG_CID_2x)
#define DWC2_USB_OTG_HS_NUM_EP (9) /**< OTG HS with 9 endpoints */
#endif
#define DWC2_USB_OTG_HS_NUM_EP STM32_USB_OTG_HS_NUM_EP
/**
* @brief USB OTG FS FIFO reception buffer space in 32-bit words
@ -144,6 +124,9 @@ extern "C" {
#endif
#endif
/* periph/usbdev.h is included after the definitions above by intention */
#include "periph/usbdev.h"
/**
* @brief stm32 USB Device FS only peripheral device context
*/

View File

@ -1,6 +1,6 @@
PKG_NAME=nanors
PKG_URL=https://github.com/sleepybishop/nanors.git
PKG_VERSION=395e5ada44dd8d5974eaf6bb6b17f23406e3ca72
PKG_VERSION=e9e242e98e27037830490b2a752895ca68f75f8b
PKG_LICENSE=MIT
include $(RIOTBASE)/pkg/pkg.mk

View File

@ -27,6 +27,7 @@
#include <assert.h>
#include "usb/usbus.h"
#include "usb/usbus/control.h"
#ifdef MODULE_USBUS_CDC_ECM
#include "usb/usbus/cdc/ecm.h"
@ -39,11 +40,52 @@ usbus_cdcecm_device_t cdcecm;
#include "usb/usbus/dfu.h"
static usbus_dfu_device_t dfu;
#endif
#ifdef MODULE_USBUS_HID
#include "usb/usbus/hid.h"
#endif
#ifdef MODULE_USBUS_MSC
#include "usb/usbus/msc.h"
static usbus_msc_device_t msc;
#endif
#ifndef MODULE_USBUS_CDC_ACM
#define USBUS_CDC_ACM_EP_IN_REQUIRED_NUMOF 0
#define USBUS_CDC_ACM_EP_OUT_REQUIRED_NUMOF 0
#endif
#ifndef MODULE_USBUS_CDC_ECM
#define USBUS_CDC_ECM_EP_IN_REQUIRED_NUMOF 0
#define USBUS_CDC_ECM_EP_OUT_REQUIRED_NUMOF 0
#endif
#ifndef MODULE_USBUS_HID
#define USBUS_HID_EP_IN_REQUIRED_NUMOF 0
#define USBUS_HID_EP_OUT_REQUIRED_NUMOF 0
#endif
#ifndef MODULE_USBUS_MSC
#define USBUS_MSC_EP_IN_REQUIRED_NUMOF 0
#define USBUS_MSC_EP_OUT_REQUIRED_NUMOF 0
#endif
#define USBUS_EP_IN_REQUIRED_NUMOF (USBUS_CONTROL_EP_IN_REQUIRED_NUMOF + \
USBUS_CDC_ACM_EP_IN_REQUIRED_NUMOF + \
USBUS_CDC_ECM_EP_IN_REQUIRED_NUMOF + \
USBUS_HID_EP_IN_REQUIRED_NUMOF + \
USBUS_MSC_EP_IN_REQUIRED_NUMOF)
#define USBUS_EP_OUT_REQUIRED_NUMOF (USBUS_CONTROL_EP_OUT_REQUIRED_NUMOF + \
USBUS_CDC_ACM_EP_OUT_REQUIRED_NUMOF + \
USBUS_CDC_ECM_EP_OUT_REQUIRED_NUMOF + \
USBUS_HID_EP_OUT_REQUIRED_NUMOF + \
USBUS_MSC_EP_OUT_REQUIRED_NUMOF)
static_assert(USBUS_EP_IN_REQUIRED_NUMOF <= USBDEV_NUM_ENDPOINTS,
"Number of required IN endpoints exceeded");
static_assert(USBUS_EP_OUT_REQUIRED_NUMOF <= USBDEV_NUM_ENDPOINTS,
"Number of required OUT endpoints exceeded");
static char _stack[USBUS_STACKSIZE];
static usbus_t usbus;

View File

@ -83,6 +83,16 @@ extern "C" {
#define USB_HID_REQUEST_SET_PROTOCOL 0x0b
/** @} */
/**
* @brief Number of IN EPs required for the HID interface
*/
#define USBUS_HID_EP_IN_REQUIRED_NUMOF 1
/**
* @brief Number of Out EPs required for the HID interface
*/
#define USBUS_HID_EP_OUT_REQUIRED_NUMOF 1
/**
* @brief USB HID descriptor struct
*

View File

@ -89,6 +89,16 @@ extern "C" {
*/
#define USBUS_CDC_ACM_INT_EP_SIZE (8)
/**
* @brief Number of IN EPs required for the CDC ACM interface
*/
#define USBUS_CDC_ACM_EP_IN_REQUIRED_NUMOF 2
/**
* @brief Number of Out EPs required for the CDC ACM interface
*/
#define USBUS_CDC_ACM_EP_OUT_REQUIRED_NUMOF 1
/**
* @brief CDC ACM line state as reported by the host computer
*/

View File

@ -87,6 +87,16 @@ extern "C" {
*/
#define USBUS_ETHERNET_FRAME_BUF MATH_ALIGN(ETHERNET_FRAME_LEN, USBUS_CDCECM_EP_DATA_SIZE)
/**
* @brief Number of IN EPs required for the CDC ECM interface
*/
#define USBUS_CDC_ECM_EP_IN_REQUIRED_NUMOF 2
/**
* @brief Number of Out EPs required for the CDC ECM interface
*/
#define USBUS_CDC_ECM_EP_OUT_REQUIRED_NUMOF 1
/**
* @brief notification state, used to track which information must be send to
* the host

View File

@ -21,6 +21,16 @@
#ifndef USB_USBUS_CONTROL_H
#define USB_USBUS_CONTROL_H
/**
* @brief Number of IN EPs required for the control interface
*/
#define USBUS_CONTROL_EP_IN_REQUIRED_NUMOF 1
/**
* @brief Number of IN EPs required for the control interface
*/
#define USBUS_CONTROL_EP_OUT_REQUIRED_NUMOF 1
#include "usb/usbus.h"
#ifdef __cplusplus

View File

@ -31,6 +31,16 @@
extern "C" {
#endif
/**
* @brief Number of IN EPs required for the MSC interface
*/
#define USBUS_MSC_EP_IN_REQUIRED_NUMOF 1
/**
* @brief Number of Out EPs required for the MSC interface
*/
#define USBUS_MSC_EP_OUT_REQUIRED_NUMOF 1
/**
* @brief USBUS MSC Number of exported MTD device through USB
*/

View File

@ -36,10 +36,14 @@ int main(void)
static uint8_t data[(DATA_SHARDS + RECOVERY_SHARDS) * SHARD_SIZE];
/* copy of data for comparison */
static uint8_t data_cmp[DATA_SHARDS * SHARD_SIZE];
/* nanors work buffer */
static uint8_t rs_buf[reed_solomon_bufsize(DATA_SHARDS, RECOVERY_SHARDS)];
/* pointer to shards */
static uint8_t *shards[DATA_SHARDS + RECOVERY_SHARDS];
uint8_t *shards[DATA_SHARDS + RECOVERY_SHARDS];
/* map of missing shards */
static uint8_t marks[DATA_SHARDS + RECOVERY_SHARDS];
uint8_t marks[DATA_SHARDS + RECOVERY_SHARDS];
memset(marks, 0, sizeof(marks));
/* generate random data */
random_bytes(data, sizeof(data_cmp));
@ -51,8 +55,7 @@ int main(void)
}
puts("START");
reed_solomon_init();
rs_t *rs = reed_solomon_new(DATA_SHARDS, RECOVERY_SHARDS);
rs_t *rs = reed_solomon_new_static(rs_buf, sizeof(rs_buf), DATA_SHARDS, RECOVERY_SHARDS);
if (!rs) {
puts("failed to init codec");
return -1;
@ -79,7 +82,6 @@ int main(void)
} else {
puts("done.");
}
reed_solomon_release(rs);
if (memcmp(data, data_cmp, sizeof(data_cmp))) {
puts("FAILED");

View File

@ -9,4 +9,30 @@ USEMODULE += shell
USEMODULE += shell_cmds_default
USEMODULE += ps
# Boards that don't have enough endpoints to use CDC ACM together with CDC ECM
ifeq (,$(filter stdio_%,$(filter-out stdio_cdc_acm,$(USEMODULE))))
BOARD_BLACKLIST += \
stm32f429i-disco \
stm32f4discovery \
weact-f401cc \
weact-f401ce \
weact-f411ce \
#
endif
define _usbus_cdc_ecm_blacklist_info
Warning:
The board is blacklisted because it uses `stdio_cdc_acm` as STDIO, which needs
a CDC ACM interface in addition to the CDC ECM interface, but the number of
available endpoints is not sufficient for this. To use this application you
have to use `stdio_uart` or any other `stdio_*` module, for example:
USEMODULE=stdio_uart BOARD=$(BOARD) make -C tests/usbus_cdc_ecm
endef
ifneq (,$(filter $(BOARD),$(BOARD_BLACKLIST)))
$(info $(_usbus_cdc_ecm_blacklist_info))
endif
include $(RIOTBASE)/Makefile.include