-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
17091: USBUS: Add URB support r=benpicco a=bergzand ### Contribution description This commit adds support for URBs (USB Request/Response Blocks). These allow for submitting multi-transfer sized buffers with USBUS handling the individual usbdev xmits. Multiple URBs can be queued at once for a single endpoint and USBUS will handle them in the order of submission. OUT endpoint URBs must always consist of a whole number of full-sized transfers (N x MaxEndpointSize). They will automatically finish after the endpoint received a transfer less than the endpoint size. IN endpoints can be arbitrary-sized and do not have to consist of a whole number of full-sized transmissions. They support a flag to indicate that the last transfer in the sequence must be less than a full sized transfer (USBUS_URB_FLAG_AUTO_ZLP) and this adds a zero length transfer at the end of the transmissions if the last transfer was equal to the maximum transfer size. URBs can be cancelled, but if the URB is already being processed it will be cancelled after the current transmission within the URB is finished. If it is still in the queue it will immediately be removed from the queue. ### Testing procedure - `tests/usbus_cdc_ecm` should still work. Testing one of the usbdev-supported platform should be sufficient here. ### Issues/PRs references Needs #17064 18148: sys/flash_utils: helpers to store data in flash r=benpicco a=maribu ### Contribution description This helpers that allow storing, accessing, and working with data in flash that works for both classical Harvard architectures (which do not map flash also into the address space) as well as modern Harvard architectures and von-Neumann architectures. With this, `examples/default` again runs on the Arduino Uno / Nano. Since this board is still the "entry kit" for many people to embedded hardware, it would be nice to support it with our default example. ### Testing procedure `examples/default` should run and work on ATmega boards (especially ATmega328P and ATmega32U4 based boards) as well on all other boards now. ### Issues/PRs references None Co-authored-by: Koen Zandberg <koen@bergzand.net> Co-authored-by: Marian Buschsieweke <marian.buschsieweke@ovgu.de>
- Loading branch information
Showing
201 changed files
with
1,356 additions
and
879 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup cpu_avr8_common | ||
* @{ | ||
* | ||
* @file | ||
* @brief Implementation of flash_utils | ||
* | ||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de> | ||
* | ||
*/ | ||
|
||
#ifndef FLASH_UTILS_ARCH_H | ||
#define FLASH_UTILS_ARCH_H | ||
|
||
#include <stdio.h> | ||
#include <string.h> | ||
#include <avr/pgmspace.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/* this is documented in sys/include/flash_utils.h - let's not confuse | ||
* Doxygen */ | ||
#ifndef DOXYGEN | ||
|
||
#define FLASH_ATTR __flash | ||
#define PRIsflash "S" | ||
#define TO_FLASH(x) __extension__({static FLASH_ATTR const char __c[] = (x); &__c[0];}) | ||
#define flash_strcmp strcmp_P | ||
#define flash_strncmp strncmp_P | ||
#define flash_strlen strlen_P | ||
#define flash_strcpy strcpy_P | ||
#define flash_strncpy strncpy_P | ||
#define flash_printf printf_P | ||
/* avrlibc seemingly forgot to provide fprintf(), but vfprintf() is there */ | ||
#define flash_vprintf(fmt, arglist) vfprintf_P(stdout, fmt, arglist) | ||
#define flash_fprintf fprintf_P | ||
#define flash_vfprintf vfprintf_P | ||
#define flash_snprintf snprintf_P | ||
#define flash_vsnprintf vsnprintf_P | ||
#define flash_puts puts_P | ||
#define flash_memcpy memcpy_P | ||
|
||
#endif /* Doxygen */ | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
/** @} */ | ||
#endif /* FLASH_UTILS_ARCH_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/* | ||
* Copyright (C) 2023 Otto-von-Guericke-Universität Magdeburg | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser General | ||
* Public License v2.1. See the file LICENSE in the top level directory for more | ||
* details. | ||
*/ | ||
|
||
/** | ||
* @defgroup cpu_avr8_common_stdio_wrapper stdio wrapper for AVR8 | ||
* @ingroup cpu_avr8_common | ||
* | ||
* This module a wrapper for the stdio.h header intended to make use of | ||
* flash_utils.h in printf() automatically | ||
* | ||
* @{ | ||
* | ||
* @file | ||
* @brief stdio wrapper to extend the C libs stdio | ||
* | ||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de> | ||
*/ | ||
|
||
#ifndef STDIO_H | ||
#define STDIO_H | ||
#include_next "stdio.h" | ||
|
||
/* C++ does not support __flash. Hence, only wrap printf() and friends for | ||
* C and let C++ use them unmodified. */ | ||
#ifdef __cplusplus | ||
extern "C" { | ||
} | ||
#else | ||
|
||
#include "flash_utils.h" | ||
|
||
#ifdef DOXYGEN | ||
/** | ||
* @brief A wrapper for the `printf()` function that passes arguments through | ||
* unmodified, but fails to compile if the first argument is not a | ||
* string literal. | ||
* | ||
* See e.g. `man 3 printf` or https://linux.die.net/man/3/printf for | ||
* documentation the printf function. This applies fully here, as it passes | ||
* through the arguments unmodified. | ||
* | ||
* The motivation for enforcing the first argument to be a string literal is | ||
* three-fold: | ||
* | ||
* 1. It prevents security issues due format strings controlled by adversaries. | ||
* 2. It makes sure that modern C compilers that do understand format | ||
* specifiers have knowledge of the format string and can verify that the | ||
* other arguments match what is given via format string specifiers | ||
* 3. It allows to force the format string to flash even for Harvard | ||
* architectures transparently | ||
* | ||
* Similar wrappers are also in place for `vprintf()`, `fprintf()`, | ||
* `vfprintf()`, `snprintf()`, `vsnprintf()`. | ||
*/ | ||
#define printf(...) /* implementation details */ | ||
#else | ||
/* this helper function-like macro takes at least 65 arguments and will | ||
* "return" the 65 argument unmodified. It is not useful by itself, but | ||
* needed to implement _SINGLEARG_OR_MULTIARG(). */ | ||
#define _TAKE_65TH_TOKEN( _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ | ||
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ | ||
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ | ||
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ | ||
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ | ||
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ | ||
_61, _62, _63, _64, N, ...) N | ||
|
||
#define _EXPAND_HELPER(x) x | ||
/* this function-like macro expands its argument */ | ||
#define _EXPAND(x) _EXPAND_HELPER(x) | ||
|
||
/* This function-like macro will expand to `SINGLEARG` if called with one | ||
* argument and `MULTIARG` if called with more than one. | ||
* | ||
* (Implementation detail: It will not work with more than 64 arguments. But | ||
* 64 arguments to one printf call ought to be enough for everyone...) | ||
*/ | ||
#define _SINGLEARG_OR_MULTIARG(...) \ | ||
_TAKE_65TH_TOKEN(__VA_ARGS__, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, MULTIARG, \ | ||
MULTIARG, MULTIARG, MULTIARG, SINGLEARG) | ||
#define _CONCAT_HELPER(a, b) a ## b | ||
#define _CONCAT(a, b) _CONCAT_HELPER(a, b) | ||
|
||
/* Implementation for `printf(fmt)` */ | ||
#define _PRINTF_SINGLEARG(x) \ | ||
flash_printf(TO_FLASH(x)) | ||
/* Implementation for `printf(fmt, ...)` */ | ||
#define _PRINTF_MULTIARG(x, ...) \ | ||
flash_printf(TO_FLASH(x), __VA_ARGS__) | ||
/* Dispatch to _PRINTF_SINGLEARG() and _PRINTF_MULTIARG() depending on the | ||
* number of arguments. Special handling for `printf(fmt)` compared to | ||
* `printf(fmt, ...)` is needed because the `__VA_ARGS__` part must contain | ||
* at least one argument, which in case of `printf(fmt)` is not the case. */ | ||
#define printf(...) \ | ||
_EXPAND(_CONCAT(_PRINTF_, _SINGLEARG_OR_MULTIARG(__VA_ARGS__))(__VA_ARGS__)) | ||
|
||
/* And now all other printf variants. For the v*printf() versions we do not | ||
* need to differentiate, because they have always the same number of arguments | ||
* (with the last being va_list). For the other printf variants, we again need | ||
* to dispatch to a _SINGLEARG and a _MULTIARG version. */ | ||
#define vprintf(fmt, args) flash_vprintf(TO_FLASH(fmt), args) | ||
|
||
#define _FPRINTF_SINGLEARG(stream, x) \ | ||
flash_fprintf(stream, TO_FLASH(x)) | ||
#define _FPRINTF_MULTIARG(stream, x, ...) \ | ||
flash_fprintf(stream, TO_FLASH(x), __VA_ARGS__) | ||
#define fprintf(stream, ...) \ | ||
_EXPAND(_CONCAT(_FPRINTF_, _SINGLEARG_OR_MULTIARG(__VA_ARGS__))(stream, __VA_ARGS__)) | ||
|
||
#define vfprintf(stream, fmt, args) flash_vfprintf(stream, TO_FLASH(fmt), args) | ||
|
||
#define _SNPRINTF_SINGLEARG(buf, buf_len, fmt) \ | ||
flash_snprintf(buf, buf_len, TO_FLASH(fmt)) | ||
#define _SNPRINTF_MULTIARG(buf, buf_len, fmt, ...) \ | ||
flash_snprintf(buf, buf_len, TO_FLASH(fmt), __VA_ARGS__) | ||
#define snprintf(buf, buf_len, ...) \ | ||
_EXPAND(_CONCAT(_SNPRINTF_, _SINGLEARG_OR_MULTIARG(__VA_ARGS__))(buf, buf_len, __VA_ARGS__)) | ||
|
||
#define vsnprintf(buf, buf_len, fmt, args) flash_vsnprintf(buf, buf_len, TO_FLASH(fmt), args) | ||
#endif | ||
|
||
#endif | ||
|
||
#endif /* STDIO_H */ | ||
/** @} */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.