1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
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>
This commit is contained in:
bors[bot] 2023-02-27 11:57:20 +00:00 committed by GitHub
commit f0b60d5a0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
201 changed files with 1302 additions and 882 deletions

View File

@ -77,6 +77,10 @@ extern "C" {
*/
#define IRQ_API_INLINED (1)
#ifndef DOXYGEN
#define HAS_FLASH_UTILS_ARCH 1
#endif
#ifdef __cplusplus
}
#endif

View File

@ -42,7 +42,7 @@
/**
* @brief Possible prescaler values, encoded as 2 ^ val
*/
static const uint8_t prescalers[] = { 0, 3, 6, 8, 10 };
static const __flash uint8_t prescalers[] = { 0, 3, 6, 8, 10 };
/**
* @brief Timer state context

View File

@ -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 */

View File

@ -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 */
/** @} */

View File

@ -48,8 +48,9 @@
#ifndef SAUL_H
#define SAUL_H
#include <stdint.h>
#include <errno.h>
#include <stdint.h>
#include <sys/types.h>
#include "phydat.h"
@ -315,11 +316,42 @@ int saul_read_notsup(const void *dev, phydat_t *dat);
*
* @param[in] class_id device class ID
*
* @return string representation of the device class
* @return NULL if class ID is not known
* @return string representation of the device class
* @retval NULL class ID is not known
*
* @deprecated Use @ref saul_class_print or @ref saul_class_write instead
*
* @warning For classic Harvard architectures a small buffer is used to store
* the string, so that subsequent (or concurrent!) calls will
* overwrite the output.
*/
const char *saul_class_to_str(const uint8_t class_id);
/**
* @brief Prints the class string of the given class ID
*
* @param[in] class_id ID of the device class to print
*/
void saul_class_print(uint8_t class_id);
/**
* @brief Write the string representation of the given device class to the
* given buffer
*
* @param[out] dest destination buffer to write to
* @param[in] max_size size of the buffer at @p dest
* @param[in] class_id ID of the device class to write
*
* @return Number of bytes written
* @retval -EOVERFLOW buffer at @p dest is too small
* @retval -EINVAL invalid unit in @p unit
*
* @warning The function will never write a terminating zero byte
* @note If you pass `NULL` for @p dest, it will return the number of bytes
* it would write (regardless of @p max_size)
*/
ssize_t saul_class_write(char *dest, size_t max_size, uint8_t class_id);
#ifdef __cplusplus
}
#endif

View File

@ -23,77 +23,206 @@
#include <stddef.h>
#include <stdint.h>
#include "flash_utils.h"
#include "saul.h"
static const char *actuators[] = {
[SAUL_ACT_ID_ANY] = "ACT_ANY",
[SAUL_ACT_ID_LED_RGB] = "ACT_LED_RGB",
[SAUL_ACT_ID_SERVO] = "ACT_SERVO",
[SAUL_ACT_ID_MOTOR] = "ACT_MOTOR",
[SAUL_ACT_ID_SWITCH] = "ACT_SWITCH",
[SAUL_ACT_ID_DIMMER] = "ACT_DIMMER",
static FLASH_ATTR const char _act_id_any[] = "ACT_ANY";
static FLASH_ATTR const char _act_id_led_rgb[] = "ACT_LED_RGB";
static FLASH_ATTR const char _act_id_servo[] = "ACT_SERVO";
static FLASH_ATTR const char _act_id_motor[] = "ACT_MOTOR";
static FLASH_ATTR const char _act_id_switch[] = "ACT_SWITCH";
static FLASH_ATTR const char _act_id_dimmer[] = "ACT_DIMMER";
static FLASH_ATTR const char * FLASH_ATTR const actuators[] = {
[SAUL_ACT_ID_ANY] = _act_id_any,
[SAUL_ACT_ID_LED_RGB] = _act_id_led_rgb,
[SAUL_ACT_ID_SERVO] = _act_id_servo,
[SAUL_ACT_ID_MOTOR] = _act_id_motor,
[SAUL_ACT_ID_SWITCH] = _act_id_switch,
[SAUL_ACT_ID_DIMMER] = _act_id_dimmer,
};
static const char *sensors[] = {
[SAUL_SENSE_ID_ANY] = "SENSE_ANY",
[SAUL_SENSE_ID_BTN] = "SENSE_BTN",
[SAUL_SENSE_ID_TEMP] = "SENSE_TEMP",
[SAUL_SENSE_ID_HUM] = "SENSE_HUM",
[SAUL_SENSE_ID_LIGHT] = "SENSE_LIGHT",
[SAUL_SENSE_ID_ACCEL] = "SENSE_ACCEL",
[SAUL_SENSE_ID_MAG] = "SENSE_MAG",
[SAUL_SENSE_ID_GYRO] = "SENSE_GYRO",
[SAUL_SENSE_ID_COLOR] = "SENSE_COLOR",
[SAUL_SENSE_ID_PRESS] = "SENSE_PRESS",
[SAUL_SENSE_ID_ANALOG] = "SENSE_ANALOG",
[SAUL_SENSE_ID_UV] = "SENSE_UV",
[SAUL_SENSE_ID_OBJTEMP] = "SENSE_OBJTEMP",
[SAUL_SENSE_ID_COUNT] = "SENSE_PULSE_COUNT",
[SAUL_SENSE_ID_DISTANCE] = "SENSE_DISTANCE",
[SAUL_SENSE_ID_CO2] = "SENSE_CO2",
[SAUL_SENSE_ID_TVOC] = "SENSE_TVOC",
[SAUL_SENSE_ID_GAS] = "SENSE_GAS",
[SAUL_SENSE_ID_PROXIMITY] = "SENSE_PROXIMITY",
[SAUL_SENSE_ID_RSSI] = "SENSE_RSSI",
[SAUL_SENSE_ID_CHARGE] = "SENSE_CHARGE",
[SAUL_SENSE_ID_CURRENT] = "SENSE_CURRENT",
[SAUL_SENSE_ID_OCCUP] = "SENSE_OCCUP",
[SAUL_SENSE_ID_PM] = "SENSE_PM",
[SAUL_SENSE_ID_CAPACITANCE] = "SENSE_CAPACITANCE",
[SAUL_SENSE_ID_VOLTAGE] = "SENSE_VOLTAGE",
[SAUL_SENSE_ID_PH] = "SENSE_PH",
[SAUL_SENSE_ID_POWER] = "SENSE_POWER",
[SAUL_SENSE_ID_SIZE] = "SENSE_SIZE",
static FLASH_ATTR const char _sense_any[] = "SENSE_ANY";
static FLASH_ATTR const char _sense_btn[] = "SENSE_BTN";
static FLASH_ATTR const char _sense_temp[] = "SENSE_TEMP";
static FLASH_ATTR const char _sense_hum[] = "SENSE_HUM";
static FLASH_ATTR const char _sense_light[] = "SENSE_LIGHT";
static FLASH_ATTR const char _sense_accel[] = "SENSE_ACCEL";
static FLASH_ATTR const char _sense_mag[] = "SENSE_MAG";
static FLASH_ATTR const char _sense_gyro[] = "SENSE_GYRO";
static FLASH_ATTR const char _sense_color[] = "SENSE_COLOR";
static FLASH_ATTR const char _sense_press[] = "SENSE_PRESS";
static FLASH_ATTR const char _sense_analog[] = "SENSE_ANALOG";
static FLASH_ATTR const char _sense_uv[] = "SENSE_UV";
static FLASH_ATTR const char _sense_objtemp[] = "SENSE_OBJTEMP";
static FLASH_ATTR const char _sense_pulse_count[] = "SENSE_PULSE_COUNT";
static FLASH_ATTR const char _sense_distance[] = "SENSE_DISTANCE";
static FLASH_ATTR const char _sense_co2[] = "SENSE_CO2";
static FLASH_ATTR const char _sense_tvoc[] = "SENSE_TVOC";
static FLASH_ATTR const char _sense_gas[] = "SENSE_GAS";
static FLASH_ATTR const char _sense_proximity[] = "SENSE_PROXIMITY";
static FLASH_ATTR const char _sense_rssi[] = "SENSE_RSSI";
static FLASH_ATTR const char _sense_charge[] = "SENSE_CHARGE";
static FLASH_ATTR const char _sense_current[] = "SENSE_CURRENT";
static FLASH_ATTR const char _sense_occup[] = "SENSE_OCCUP";
static FLASH_ATTR const char _sense_pm[] = "SENSE_PM";
static FLASH_ATTR const char _sense_capacitance[] = "SENSE_CAPACITANCE";
static FLASH_ATTR const char _sense_voltage[] = "SENSE_VOLTAGE";
static FLASH_ATTR const char _sense_ph[] = "SENSE_PH";
static FLASH_ATTR const char _sense_power[] = "SENSE_POWER";
static FLASH_ATTR const char _sense_size[] = "SENSE_SIZE";
static FLASH_ATTR const char * FLASH_ATTR const sensors[] = {
[SAUL_SENSE_ID_ANY] = _sense_any,
[SAUL_SENSE_ID_BTN] = _sense_btn,
[SAUL_SENSE_ID_TEMP] = _sense_temp,
[SAUL_SENSE_ID_HUM] = _sense_hum,
[SAUL_SENSE_ID_LIGHT] = _sense_light,
[SAUL_SENSE_ID_ACCEL] = _sense_accel,
[SAUL_SENSE_ID_MAG] = _sense_mag,
[SAUL_SENSE_ID_GYRO] = _sense_gyro,
[SAUL_SENSE_ID_COLOR] = _sense_color,
[SAUL_SENSE_ID_PRESS] = _sense_press,
[SAUL_SENSE_ID_ANALOG] = _sense_analog,
[SAUL_SENSE_ID_UV] = _sense_uv,
[SAUL_SENSE_ID_OBJTEMP] = _sense_objtemp,
[SAUL_SENSE_ID_COUNT] = _sense_pulse_count,
[SAUL_SENSE_ID_DISTANCE] = _sense_distance,
[SAUL_SENSE_ID_CO2] = _sense_co2,
[SAUL_SENSE_ID_TVOC] = _sense_tvoc,
[SAUL_SENSE_ID_GAS] = _sense_gas,
[SAUL_SENSE_ID_PROXIMITY] = _sense_proximity,
[SAUL_SENSE_ID_RSSI] = _sense_rssi,
[SAUL_SENSE_ID_CHARGE] = _sense_charge,
[SAUL_SENSE_ID_CURRENT] = _sense_current,
[SAUL_SENSE_ID_OCCUP] = _sense_occup,
[SAUL_SENSE_ID_PM] = _sense_pm,
[SAUL_SENSE_ID_CAPACITANCE] = _sense_capacitance,
[SAUL_SENSE_ID_VOLTAGE] = _sense_voltage,
[SAUL_SENSE_ID_PH] = _sense_ph,
[SAUL_SENSE_ID_POWER] = _sense_power,
[SAUL_SENSE_ID_SIZE] = _sense_size,
};
static FLASH_ATTR const char _class_undef[] = "CLASS_UNDEF";
static FLASH_ATTR const char _class_any[] = "CLASS_ANY";
static FLASH_ATTR const char _class_unknown[] = "CLASS_UNKNOWN";
const char *saul_class_to_str(const uint8_t class_id)
{
#if IS_ACTIVE(HAS_FLASH_UTILS_ARCH)
/* Yeah, this is as bad as it looks... The function is deprecated for this
* reason and it will only affect AVR users, for whom this is a good
* trade-off. */
static char buf[32]; /* yes, whopping 32 byte ... */
ssize_t len = saul_class_write(buf, sizeof(buf) - 1, class_id);
if (len < 0) {
flash_memcpy(buf, _class_unknown, sizeof(_class_unknown));
len = sizeof(_class_unknown);
}
buf[len] = '\0';
return buf;
#else
const char *result = NULL;
uint8_t id = class_id & SAUL_ID_MASK;
uint8_t cat = class_id & SAUL_CAT_MASK;
switch (cat) {
case SAUL_CAT_UNDEF:
return "CLASS_UNDEF";
case SAUL_CAT_ACT:
if (id < SAUL_ACT_NUMOF) {
result = actuators[id];
}
break;
case SAUL_CAT_SENSE:
if (id < SAUL_SENSE_NUMOF) {
result = sensors[id];
}
break;
default:
if (class_id == SAUL_CLASS_ANY) {
return "CLASS_ANY";
}
break;
case SAUL_CAT_UNDEF:
return _class_undef;
case SAUL_CAT_ACT:
if (id < SAUL_ACT_NUMOF) {
result = actuators[id];
}
break;
case SAUL_CAT_SENSE:
if (id < SAUL_SENSE_NUMOF) {
result = sensors[id];
}
break;
default:
if (class_id == SAUL_CLASS_ANY) {
return _class_any;
}
break;
}
if (result == NULL) {
result = "CLASS_UNKNOWN";
result = _class_unknown;
}
return result;
#endif
}
void saul_class_print(uint8_t class_id)
{
uint8_t id = class_id & SAUL_ID_MASK;
uint8_t cat = class_id & SAUL_CAT_MASK;
FLASH_ATTR const char *str = NULL;
switch (cat) {
case SAUL_CAT_UNDEF:
str = _class_undef;
break;
case SAUL_CAT_ACT:
if (id < SAUL_ACT_NUMOF) {
str = actuators[id];
}
break;
case SAUL_CAT_SENSE:
if (id < SAUL_SENSE_NUMOF) {
str = sensors[id];
}
break;
default:
if (class_id == SAUL_CLASS_ANY) {
str = _class_any;
}
break;
}
if (str) {
flash_print_str(str);
}
}
ssize_t saul_class_write(char *dest, size_t max_size, uint8_t class_id)
{
uint8_t id = class_id & SAUL_ID_MASK;
uint8_t cat = class_id & SAUL_CAT_MASK;
FLASH_ATTR const char *str = NULL;
switch (cat) {
case SAUL_CAT_UNDEF:
str = _class_undef;
break;
case SAUL_CAT_ACT:
if (id < SAUL_ACT_NUMOF) {
str = actuators[id];
}
break;
case SAUL_CAT_SENSE:
if (id < SAUL_SENSE_NUMOF) {
str = sensors[id];
}
break;
default:
if (class_id == SAUL_CLASS_ANY) {
str = _class_any;
}
break;
}
if (!str) {
return -EINVAL;
}
size_t len = flash_strlen(str);
if (dest) {
if (len > max_size) {
return -EOVERFLOW;
}
flash_memcpy(dest, str, len);
}
return len;
}

View File

@ -4,10 +4,8 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a1u-xpro \
atxmega-a3bu-xplained \
bluepill-stm32f030c8 \
derfmega128 \
@ -15,7 +13,6 @@ BOARD_INSUFFICIENT_MEMORY := \
ict_panhead \
im880b \
m1284p \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \

View File

@ -4,7 +4,6 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
@ -14,7 +13,6 @@ BOARD_INSUFFICIENT_MEMORY := \
hifive1b \
i-nucleo-lrwan1 \
im880b \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \

View File

@ -10,8 +10,6 @@ BOARD_INSUFFICIENT_MEMORY := \
hifive1 \
hifive1b \
i-nucleo-lrwan1 \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \
nucleo-f030r8 \

View File

@ -4,7 +4,6 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
@ -15,7 +14,6 @@ BOARD_INSUFFICIENT_MEMORY := \
hifive1b \
i-nucleo-lrwan1 \
im880b \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \

View File

@ -1,10 +1,3 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
stk3200 \
stm32f030f4-demo \
nucleo-l011k4 \
#

View File

@ -4,7 +4,6 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
@ -14,7 +13,6 @@ BOARD_INSUFFICIENT_MEMORY := \
hifive1b \
i-nucleo-lrwan1 \
im880b \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \

View File

@ -8,5 +8,4 @@ BOARD_INSUFFICIENT_MEMORY := \
nucleo-l011k4 \
samd10-xmini \
stm32f030f4-demo \
waspmote-pro \
#

View File

@ -4,14 +4,12 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
bluepill-stm32f030c8 \
derfmega128 \
i-nucleo-lrwan1 \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \

View File

@ -4,7 +4,6 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
@ -12,7 +11,6 @@ BOARD_INSUFFICIENT_MEMORY := \
derfmega128 \
i-nucleo-lrwan1 \
m1284p \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \

View File

@ -4,16 +4,14 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
blackpill-stm32f103c8 \
bluepill-stm32f103c8 \
bluepill-stm32f030c8 \
bluepill-stm32f103c8 \
derfmega128 \
i-nucleo-lrwan1 \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \

View File

@ -12,9 +12,9 @@ BOARD_INSUFFICIENT_MEMORY := \
b-l072z-lrwan1 \
blackpill-stm32f103c8 \
blackpill-stm32f103cb \
bluepill-stm32f030c8 \
bluepill-stm32f103c8 \
bluepill-stm32f103cb \
bluepill-stm32f030c8 \
calliope-mini \
cc1350-launchpad \
cc2650-launchpad \

View File

@ -1,7 +1,6 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega328p \
@ -17,6 +16,5 @@ BOARD_INSUFFICIENT_MEMORY := \
stm32f030f4-demo \
stm32f0discovery \
telosb \
waspmote-pro \
z1 \
#

View File

@ -4,16 +4,14 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
blackpill-stm32f103c8 \
bluepill-stm32f103c8 \
bluepill-stm32f030c8 \
bluepill-stm32f103c8 \
derfmega128 \
i-nucleo-lrwan1 \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \

View File

@ -4,7 +4,6 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
@ -13,7 +12,6 @@ BOARD_INSUFFICIENT_MEMORY := \
i-nucleo-lrwan1 \
ict_panhead \
m1284p \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \

View File

@ -1,9 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
nucleo-f031k6 \
nucleo-l011k4 \
stm32f030f4-demo \

View File

@ -3,8 +3,8 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p-xplained-mini \
atmega328p \
atmega328p-xplained-mini \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-l011k4 \

View File

@ -7,9 +7,7 @@ BOARD_INSUFFICIENT_MEMORY := \
atmega328p \
atmega328p-xplained-mini \
bluepill-stm32f030c8 \
derfmega128 \
i-nucleo-lrwan1 \
microduino-corerf \
msb-430 \
msb-430h \
nucleo-f030r8 \

View File

@ -4,15 +4,11 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
bluepill-stm32f030c8 \
derfmega128 \
i-nucleo-lrwan1 \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \
nucleo-f030r8 \

View File

@ -5,7 +5,6 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
@ -13,7 +12,6 @@ BOARD_INSUFFICIENT_MEMORY := \
derfmega128 \
i-nucleo-lrwan1 \
im880b \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \

View File

@ -1,9 +0,0 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
stm32f030f4-demo \
#

View File

@ -4,8 +4,8 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega328p-xplained-mini \
atmega328p \
atmega328p-xplained-mini \
bluepill-stm32f030c8 \
i-nucleo-lrwan1 \
nucleo-f030r8 \

View File

@ -3,8 +3,8 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p-xplained-mini \
atmega328p \
atmega328p-xplained-mini \
bluepill-stm32f030c8 \
i-nucleo-lrwan1 \
nucleo-f030r8 \

View File

@ -1,9 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega328p \
b-l072z-lrwan1 \
blackpill-stm32f103c8 \
blackpill-stm32f103cb \
@ -33,6 +28,5 @@ BOARD_INSUFFICIENT_MEMORY := \
stk3200 \
stm32f0discovery \
telosb \
waspmote-pro \
z1 \
#

View File

@ -4,14 +4,12 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
bluepill-stm32f030c8 \
derfmega128 \
i-nucleo-lrwan1 \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \
@ -24,8 +22,8 @@ BOARD_INSUFFICIENT_MEMORY := \
nucleo-l031k6 \
nucleo-l053r8 \
samd10-xmini \
stk3200 \
slstk3400a \
stk3200 \
stm32f030f4-demo \
stm32f0discovery \
stm32f7508-dk \

View File

@ -1,10 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-f031k6 \
nucleo-l011k4 \
samd10-xmini \

View File

@ -14,6 +14,9 @@ CFLAGS_LINK = -ffunction-sections -fdata-sections -fno-builtin -fshort-enums
CFLAGS_DBG ?= -ggdb -g3
CFLAGS_OPT ?= -Os
# Use of __flash requires gnu11 instead of c11
CFLAGS += -std=gnu11
CFLAGS += $(CFLAGS_CPU) $(CFLAGS_LINK) $(CFLAGS_DBG) $(CFLAGS_OPT)
ASFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG)

View File

@ -510,6 +510,7 @@ PSEUDOMODULES += suit_storage_%
PSEUDOMODULES += sys_bus_%
PSEUDOMODULES += tiny_strerror_as_strerror
PSEUDOMODULES += tiny_strerror_minimal
PSEUDOMODULES += usbus_urb
PSEUDOMODULES += vdd_lc_filter_%
## @defgroup pseudomodule_vfs_auto_format vfs_auto_format
## @brief Format mount points at startup unless they can be mounted

View File

@ -22,7 +22,6 @@ CFLAGS += -Wno-type-limits
CFLAGS += -Wno-unused-function
CFLAGS += -Wno-unused-parameter
CFLAGS += -Wno-unused-variable
CFLAGS += -Wno-format-nonliteral
CFLAGS += -Wno-maybe-uninitialized
TOOLCHAIN_FILE=$(PKG_SOURCE_DIR)/xcompile-toolchain.cmake

View File

@ -414,6 +414,12 @@ ifneq (,$(filter log_%,$(USEMODULE)))
USEMODULE += log
endif
ifneq (,$(filter log_color,$(USEMODULE)))
# log_color fails to compile with -Wformat-nonliteral but this is required
# for the wrapped stdio that pushes the format string into progmem
FEATURES_BLACKLIST += arch_avr8
endif
ifneq (,$(filter cpp11-compat,$(USEMODULE)))
USEMODULE += cpp_new_delete
USEMODULE += xtimer
@ -831,6 +837,7 @@ ifneq (,$(filter usbus_cdc_ecm,$(USEMODULE)))
USEMODULE += iolist
USEMODULE += fmt
USEMODULE += usbus
USEMODULE += usbus_urb
USEMODULE += netdev_eth
USEMODULE += luid
endif

255
sys/include/flash_utils.h Normal file
View File

@ -0,0 +1,255 @@
/*
* 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.
*/
/**
* @defgroup sys_flash_utils Utility functions, macros, and types for
* read-only memory
* @ingroup sys
*
* This modules adds utility functions, macros, and functions for read-only
* memory. The goal is to hide the differences between modified architectures
* that map flash into the data address space (e.g. ARM) and those which
* doesn't (e.g. most AVR, Xtensa).
*
* # Usage
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
* #include "flash_utils.h"
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* No module needs to be selected, this is a header-only implementation that
* is always available.
*
* # Porting Code to Use `flash_utils`
*
* This is mainly targeting applications developers to ease developing apps
* that work well on both legacy modified Harvard architectures (e.g. ATmega)
* and modern modified Harvard architectures (e.g. ARM, ATtiny, ...) as well
* as von-Neumann machines.
*
* The intention is to limit in-tree use to a very small number of modules that
* yield the most "bang for the buck" and not leak the use of `flash_utils`
* through the API. Specifically, reverting to not using `flash_utils` should
* not be noticed by any user (unless looking at memory consumption).
*
* @{
*
* @file
* @brief Utility functions, macros, and types for read-only memory
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*/
#ifndef FLASH_UTILS_H
#define FLASH_UTILS_H
#include <stdio.h>
#include <string.h>
#include "cpu_conf.h"
#include "kernel_defines.h"
#if IS_ACTIVE(HAS_FLASH_UTILS_ARCH)
#include "flash_utils_arch.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(DOXYGEN)
/**
* @brief C type qualifier required to place a variable in flash
*/
#define FLASH_ATTR <IMPLEMTATION_DEFINED>
/**
* @brief Format specifier for printing `FLASH CONST char *`
*
* Usage:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
* FLASH_ATTR const char fmt[] = "I am printing \"%" PRIsflash "\" from flash\n";
* FLASH_ATTR const char msg[] = "message from flash";
* flash_printf(fmt, msg);
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#define PRIsflash <IMPLEMTATION_DEFINED>
/**
* @brief Macro to allocate a string literal on flash and return a
* `FLASH_ATTR const char *` pointer to it
* Usage:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
* flash_puts(TO_FLASH("Hello world"));
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#define TO_FLASH(str_literal) <IMPLEMTATION_DEFINED>
/**
* @brief Like `strcmp()`, but the second string resides in flash
*
* @details This will be a zero-overhead wrapper on top of `strcmp()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
int flash_strcmp(const char *ram, FLASH_ATTR const char *flash);
/**
* @brief Like `strncmp()`, but the first string resides in flash
*
* @details This will be a zero-overhead wrapper on top of `strncmp()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
int flash_strncmp(const char *ram, FLASH_ATTR const char *flash, size_t n);
/**
* @brief Like `strlen()`, but the string resides in flash
*
* @details This will be a zero-overhead wrapper on top of `strlen()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
size_t flash_strlen(FLASH_ATTR const char *flash);
/**
* @brief Like `strcpy()`, but the source flash resides in flash
*
* @details This will be a zero-overhead wrapper on top of `strcpy()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
char * flash_strcpy(char *ram, FLASH_ATTR const char *flash);
/**
* @brief Like `strncpy()`, but the source flash resides in flash
*
* @details This will be a zero-overhead wrapper on top of `strncpy()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
char * flash_strncpy(char *ram, FLASH_ATTR const char *flash, size_t n);
/**
* @brief Like `printf()`, but the format string resides in flash
*
* @details This will be a zero-overhead wrapper on top of `printf()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
int flash_printf(FLASH_ATTR const char *flash, ...);
/**
* @brief Like `vprintf()`, but the format string resides in flash
*
* @details This will be a zero-overhead wrapper on top of `vprintf()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
int flash_vprintf(FLASH_ATTR const char *flash, va_list args);
/**
* @brief Like `fprintf()`, but the format string resides in flash
*
* @details This will be a zero-overhead wrapper on top of `fprintf()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
int flash_fprintf(FILE *stream, FLASH_ATTR const char *flash, ...);
/**
* @brief Like `vfprintf()`, but the format string resides in flash
*
* @details This will be a zero-overhead wrapper on top of `vfprintf()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
int flash_vfprintf(FILE *stream, FLASH_ATTR const char *flash, va_list args);
/**
* @brief Like `snprintf()`, but the format string resides in flash
*
* @details This will be a zero-overhead wrapper on top of `snprintf()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
int flash_snprintf(char *buf, size_t buf_len, FLASH_ATTR const char *flash, ...);
/**
* @brief Like `vsnprintf()`, but the format string resides in flash
*
* @details This will be a zero-overhead wrapper on top of `vsnprintf()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
int flash_vsnprintf(char *buf, size_t buf_len, FLASH_ATTR const char *flash,
va_list args);
/**
* @brief Like `puts()`, but the string resides in flash
*
* @details This will be a zero-overhead wrapper on top of `puts()` for
* von-Neumann architectures or Harvard architectures that also map
* their flash into the data address space.
*/
void flash_puts(FLASH_ATTR const char *flash);
/**
* @brief Like `memcpy()`, but @p src resides in flash
*
* @param[out] dest buffer to copy into
* @param[in] src flash data to copy
* @param[in] n number of bytes to copy
*
*/
void * flash_memcpy(void *dest, FLASH_ATTR const char *src, size_t n);
#elif !IS_ACTIVE(HAS_FLASH_UTILS_ARCH)
# define FLASH_ATTR
# define PRIsflash "s"
# define ASSERT_IS_STR_LITERAL_HELPER(x) x
# define ASSERT_IS_STR_LITERAL(x) ASSERT_IS_STR_LITERAL_HELPER("" x)
# define TO_FLASH(x) ASSERT_IS_STR_LITERAL(x)
# define flash_strcmp strcmp
# define flash_strncmp strncmp
# define flash_strlen strlen
# define flash_strcpy strcpy
# define flash_strncpy strncpy
# define flash_printf printf
# define flash_vprintf vprintf
# define flash_fprintf fprintf
# define flash_vfprintf vfprintf
# define flash_snprintf snprintf
# define flash_vsnprintf vsnprintf
# define flash_puts puts
# define flash_memcpy memcpy
#endif
/**
* @brief A convenience wrapper for `flash_puts(TO_FLASH("str literal"))`
*
* Usage:
* ```
* FLASH_PUTS("Hello world!");
* ```
*/
#define FLASH_PUTS(x) flash_puts(TO_FLASH(x))
/**
* @brief Like @ref flash_puts but without line break
*/
static inline void flash_print_str(FLASH_ATTR const char *flash)
{
printf("%" PRIsflash, flash);
}
#ifdef __cplusplus
}
#endif
#endif /* FLASH_UTILS_H */
/** @} */

View File

@ -37,6 +37,8 @@
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include "modules.h"
#ifdef __cplusplus
@ -177,30 +179,55 @@ void phydat_dump(phydat_t *data, uint8_t dim);
/**
* @brief Convert the given unit to a string
*
* @param[in] unit unit to convert
* @param[in] unit unit to convert
*
* @return string representation of given unit (e.g. V or m)
* @return NULL if unit was not recognized
*
* @deprecated Use @ref phydat_unit_print or @ref phydat_unit_write instead
*
* @warning For classic Harvard architectures a small buffer is used to store
* the string, so that subsequent (or concurrent!) calls will
* overwrite the output.
*/
const char *phydat_unit_to_str(uint8_t unit);
/**
* @brief Return a string representation for every unit, including
* non-physical units like 'none' or 'time'
* @brief Same as @ref phydat_unit_to_str
*
* This function is useful when converting phydat_t structures to non-binary
* representations like JSON or XML.
* In practise all users used the verbose function anyway. Hence,
* @ref phydat_unit_to_str just covers all units and this is just a backward
* compatibility wrapper.
*
* In practice, this function extends phydat_unit_to_str() with additional
* identifiers for non physical units.
*
* @param[in] unit unit to convert
*
* @return string representation of given unit
* @return empty string ("") if unit was not recognized
* @deprecated Use @ref phydat_unit_print or @ref phydat_unit_write instead
*/
const char *phydat_unit_to_str_verbose(uint8_t unit);
/**
* @brief Print a unit
*
* @param[in] unit unit to print
*/
void phydat_unit_print(uint8_t unit);
/**
* @brief Write the string representation of the given unit into the given
* buffer
*
* @param[out] dest destination buffer to write to
* @param[in] max_size size of the buffer at @p dest
* @param[in] unit unit to convert
*
* @return Number of bytes written
* @retval -EOVERFLOW buffer at @p dest is too small
* @retval -EINVAL invalid unit in @p unit
*
* @warning The function will never write a terminating zero byte
* @note If you pass `NULL` for @p dest, it will return the number of bytes
* it would write (regardless of @p max_size)
*/
ssize_t phydat_unit_write(char *dest, size_t max_size, uint8_t unit);
/**
* @brief Convert the given scale factor to an SI prefix
*

View File

@ -26,6 +26,10 @@
#include "modules.h"
#include "xfa.h"
#ifndef __cplusplus
#include "flash_utils.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -135,6 +139,20 @@ typedef struct shell_command_t {
shell_command_handler_t handler; /**< The callback function. */
} shell_command_t;
#ifndef __cplusplus
/**
* @brief A single command in the list of the supported commands.
*
* This type is used internally by the @ref SHELL_COMMAND macro.
*/
typedef struct {
FLASH_ATTR const char *name; /**< Name of the function */
FLASH_ATTR const char *desc; /**< Description to print in the "help"
* command. */
shell_command_handler_t handler; /**< The callback function. */
} shell_command_xfa_t;
#endif /* __cplusplus */
/**
* @brief Start a shell and exit once EOF is reached.
*
@ -179,9 +197,13 @@ static inline void shell_run(const shell_command_t *commands,
shell_run_forever(commands, line_buf, len);
}
#ifndef __cplusplus
/**
* @brief Define shell command
*
* @note This is not available from C++, but a trivial C file can easily
* hook up a `extern "C"` function implemented in C++.
*
* This macro is a helper for defining a shell command and adding it to the
* shell commands XFA (cross file array).
*
@ -205,10 +227,17 @@ static inline void shell_run(const shell_command_t *commands,
* SHELL_COMMAND(my_command, "my command help text", _my_command);
* ```
*/
#define SHELL_COMMAND(name, help, func) \
XFA_USE_CONST(shell_command_t*, shell_commands_xfa); \
static const shell_command_t _xfa_ ## name ## _cmd = { #name, help, &func }; \
XFA_ADD_PTR(shell_commands_xfa, name, name, &_xfa_ ## name ## _cmd)
#define SHELL_COMMAND(cmd, help, func) \
XFA_USE_CONST(shell_command_xfa_t*, shell_commands_xfa); \
static FLASH_ATTR const char _xfa_ ## cmd ## _cmd_name[] = #cmd; \
static FLASH_ATTR const char _xfa_ ## cmd ## _cmd_desc[] = help; \
static const shell_command_xfa_t _xfa_ ## cmd ## _cmd = { \
.name = _xfa_ ## cmd ## _cmd_name, \
.desc = _xfa_ ## cmd ## _cmd_desc, \
.handler = &func \
}; \
XFA_ADD_PTR(shell_commands_xfa, cmd, cmd, &_xfa_ ## cmd ## _cmd)
#endif /* __cplusplus */
#ifdef __cplusplus
}

View File

@ -133,6 +133,31 @@ extern "C" {
#define USBUS_HANDLER_FLAG_TR_STALL (0x0020) /**< Report transfer stall complete */
/** @} */
/**
* @name USBUS URB flags
*
* @{
*/
/**
* @brief End the URB with a zero length packet if the URB is a full number of
* USB transfers in length
*/
#define USBUS_URB_FLAG_AUTO_ZLP (0x0001)
/**
* @brief URB needs a zero length packet and it is requested
* @internal
*/
#define USBUS_URB_FLAG_NEEDS_ZLP (0x1000)
/**
* @brief URB must be cancelled after the next finished xmit
* @internal
*/
#define USBUS_URB_FLAG_CANCELLED (0x2000)
/** @} */
/**
* @brief USB handler events
*/
@ -285,12 +310,26 @@ typedef struct usbus_endpoint {
usbus_descr_gen_t *descr_gen; /**< Linked list of optional additional
descriptor generators */
usbdev_ep_t *ep; /**< ptr to the matching usbdev endpoint */
#ifdef MODULE_USBUS_URB
clist_node_t urb_list; /**< clist of urbs */
#endif
uint16_t maxpacketsize; /**< Max packet size of this endpoint */
uint8_t interval; /**< Poll interval for interrupt endpoints */
bool active; /**< If the endpoint should be activated after
reset */
} usbus_endpoint_t;
/**
* @brief USBUS USB request/response block
*/
typedef struct usbus_urb {
clist_node_t list; /**< clist block in the queue */
uint32_t flags; /**< Transfer flags */
uint8_t *buf; /**< Pointer to the (aligned) buffer */
size_t len; /**< Length of the data */
size_t transferred; /**< amount transferred, only valid for OUT */
} usbus_urb_t;
/**
* @brief USBUS interface alternative setting
*
@ -552,6 +591,65 @@ void usbus_init(usbus_t *usbus, usbdev_t *usbdev);
void usbus_create(char *stack, int stacksize, char priority,
const char *name, usbus_t *usbus);
/**
* @brief Initialize a new URB.
*
* Must be called before submitting an URB to an endpoint.
*
* @note When using this for OUT endpoints, the buffer size and the @p len
* argument must allow for a whole number of max length transfers.
*
* @note Requires the `usbus_urb` module.
*
* @param[in] urb URB to submit
* @param[in] buf Buffer to store or transmit the data from
* @param[in] len Length of @p buf in bytes
* @param[in] flags Flags to set for the URB such as @ref USBUS_URB_FLAG_AUTO_ZLP
*/
static inline void usbus_urb_init(usbus_urb_t *urb,
uint8_t *buf,
size_t len,
uint32_t flags)
{
urb->buf = buf;
urb->len = len;
urb->flags = flags;
urb->transferred = 0;
}
/**
* @brief Submit an URB to an endpoint.
*
* @note Requires the `usbus_urb` module.
*
* @param[in] usbus USBUS context
* @param[in] endpoint USBUS endpoint the URB is queued to
* @param[in] urb URB to submit
*/
void usbus_urb_submit(usbus_t *usbus, usbus_endpoint_t *endpoint, usbus_urb_t *urb);
/**
* @brief Cancel and already queued URB.
*
* The URB will be cancelled after the next transmission if the URB is already
* partially completed. It is up to the handler code to gracefully handle the
* partially aborted transfer on the endpoint pipe.
*
* The callback will be called if the URB was already started and cancelled
* while (partially) transferred
*
* @note Requires the `usbus_urb` module.
*
* @param[in] usbus USBUS context
* @param[in] endpoint USBUS endpoint the URB is queued to
* @param[in] urb URB to cancel
*
* @returns 0 if the URB is partially completed
* 1 if the URB was not yet started
* -1 if the URB was not found in the endpoint queue
*/
int usbus_urb_cancel(usbus_t *usbus, usbus_endpoint_t *endpoint, usbus_urb_t *urb);
/**
* @brief Enable an endpoint
*
@ -614,6 +712,44 @@ static inline bool usbus_handler_isset_flag(usbus_handler_t *handler,
return handler->flags & flag;
}
/**
* @brief enable an URB flag
*
* @param[in] urb URB to enable the flag for
* @param[in] flag flag to enable
*/
static inline void usbus_urb_set_flag(usbus_urb_t *urb,
uint32_t flag)
{
urb->flags |= flag;
}
/**
* @brief disable an URB flag
*
* @param[in] urb URB to disable the flag for
* @param[in] flag flag to disable
*/
static inline void usbus_urb_remove_flag(usbus_urb_t *urb,
uint32_t flag)
{
urb->flags &= ~flag;
}
/**
* @brief check if an URB flag is set
*
* @param[in] urb URB to check for flag
* @param[in] flag flag to check
*
* @return true if the flag is set for this URB
*/
static inline bool usbus_urb_isset_flag(usbus_urb_t *urb,
uint32_t flag)
{
return urb->flags & flag;
}
#ifdef __cplusplus
}
#endif

View File

@ -29,6 +29,7 @@
#include "usb/descriptor.h"
#include "usb/usbus.h"
#include "usb/usbus/control.h"
#include "macros/math.h"
#include "net/netdev.h"
#include "mutex.h"
@ -77,6 +78,11 @@ extern "C" {
*/
#define USBUS_CDCECM_EP_DATA_SIZE 64
/**
* @brief Full ethernet frame rounded up to a whole number of transfers
*/
#define USBUS_ETHERNET_FRAME_BUF MATH_ALIGN(ETHERNET_FRAME_LEN, USBUS_CDCECM_EP_DATA_SIZE)
/**
* @brief notification state, used to track which information must be send to
* the host
@ -108,14 +114,13 @@ typedef struct usbus_cdcecm_device {
usbus_t *usbus; /**< Ptr to the USBUS context */
mutex_t out_lock; /**< mutex used for locking netif/USBUS send */
size_t tx_len; /**< Length of the current tx frame */
size_t len; /**< Length of the current rx frame */
usbus_cdcecm_notif_t notif; /**< Startup message notification tracker */
unsigned active_iface; /**< Current active data interface */
/**
* @brief Buffer for received frames from the host
*/
usbdev_ep_buf_t data_out[ETHERNET_FRAME_LEN];
usbdev_ep_buf_t data_out[USBUS_ETHERNET_FRAME_BUF];
/**
* @brief Host in device out data buffer
@ -126,6 +131,10 @@ typedef struct usbus_cdcecm_device {
* @brief Host out device in control buffer
*/
usbdev_ep_buf_t control_in[USBUS_CDCECM_EP_CTRL_SIZE];
/**
* @brief Host out device in reception URB
*/
usbus_urb_t out_urb;
} usbus_cdcecm_device_t;
/**

View File

@ -10,6 +10,9 @@ choice LOG
config MODULE_LOG_COLOR
bool "log_color: colored log output"
select MODULE_LOG
# log_color fails to compile with -Wformat-nonliteral but this is required
# for the wrapped stdio that pushes the format string into progmem
depends on !CPU_ARCH_AVR8
help
Implements a logging module with colored output.

View File

@ -20,8 +20,9 @@
#include <string.h>
#include "fmt.h"
#include "assert.h"
#include "flash_utils.h"
#include "fmt.h"
#include "phydat.h"
#define STATIC_LEN (14U)
@ -32,11 +33,11 @@
static size_t _bool_to_str(int16_t val, char *buf)
{
if (val) {
memcpy(buf, "true", 4);
flash_memcpy(buf, TO_FLASH("true"), 4);
return 4;
}
else {
memcpy(buf, "false", 5);
flash_memcpy(buf, TO_FLASH("false"), 5);
return 5;
}
}
@ -60,10 +61,10 @@ size_t phydat_to_json(const phydat_t *data, size_t dim, char *buf)
pos += (data->val[i]) ? 4 : 5; /* true: 4, false: 5 */
}
}
pos += strlen(phydat_unit_to_str_verbose(data->unit));
pos += phydat_unit_write(NULL, 0, data->unit);
}
else {
memcpy(buf, "{\"d\":", 5);
flash_memcpy(buf, TO_FLASH("{\"d\":"), 5);
pos += 5;
/* write data */
if (dim > 1) {
@ -84,13 +85,11 @@ size_t phydat_to_json(const phydat_t *data, size_t dim, char *buf)
buf[pos++] = ',';
}
/* add unit */
memcpy(&buf[pos], "\"u\":\"", 5);
flash_memcpy(&buf[pos], TO_FLASH("\"u\":\""), 5);
pos += 5;
const char *u = phydat_unit_to_str_verbose(data->unit);
strcpy(&buf[pos], u);
pos += strlen(u);
pos += phydat_unit_write(&buf[pos], SIZE_MAX, data->unit);
/* terminate the JSON string */
memcpy(&buf[pos], "\"}", 2);
flash_memcpy(&buf[pos], TO_FLASH("\"}"), 2);
pos += 2;
buf[pos++] = '\0';
}

View File

@ -18,17 +18,19 @@
* @}
*/
#include <stdio.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include "assert.h"
#include "flash_utils.h"
#include "fmt.h"
#include "phydat.h"
void phydat_dump(phydat_t *data, uint8_t dim)
{
if (data == NULL || dim > PHYDAT_DIM) {
puts("Unable to display data object");
printf("Unable to display data object\n");
return;
}
printf("Data:");
@ -50,19 +52,19 @@ void phydat_dump(phydat_t *data, uint8_t dim)
char scale_prefix;
switch (data->unit) {
case UNIT_UNDEF:
case UNIT_NONE:
case UNIT_M2:
case UNIT_M3:
case UNIT_PERCENT:
case UNIT_TEMP_C:
case UNIT_TEMP_F:
case UNIT_DBM:
/* no string conversion */
scale_prefix = '\0';
break;
default:
scale_prefix = phydat_prefix_from_scale(data->scale);
case UNIT_UNDEF:
case UNIT_NONE:
case UNIT_M2:
case UNIT_M3:
case UNIT_PERCENT:
case UNIT_TEMP_C:
case UNIT_TEMP_F:
case UNIT_DBM:
/* no string conversion */
scale_prefix = '\0';
break;
default:
scale_prefix = phydat_prefix_from_scale(data->scale);
}
printf("\t");
@ -92,75 +94,158 @@ void phydat_dump(phydat_t *data, uint8_t dim)
printf("%11s ", num);
}
printf("%s\n", phydat_unit_to_str(data->unit));
if ((data->unit != UNIT_NONE) && (data->unit != UNIT_UNDEF)
&& (data->unit != UNIT_BOOL)) {
phydat_unit_print(data->unit);
}
puts("");
}
}
static FLASH_ATTR const char _unit_celsius[] = "°C";
static FLASH_ATTR const char _unit_fahrenheit[] = "°F";
static FLASH_ATTR const char _unit_kelvin[] = "K";
static FLASH_ATTR const char _unit_lux[] = "lx";
static FLASH_ATTR const char _unit_metre[] = "m";
static FLASH_ATTR const char _unit_square_metre[] = "m^2";
static FLASH_ATTR const char _unit_cubic_metre[] = "m^3";
static FLASH_ATTR const char _unit_g_force[] = "gₙ";
static FLASH_ATTR const char _unit_degree_per_second[] = "dps";
static FLASH_ATTR const char _unit_gram[] = "g";
static FLASH_ATTR const char _unit_ampere[] = "A";
static FLASH_ATTR const char _unit_volt[] = "V";
static FLASH_ATTR const char _unit_watt[] = "W";
static FLASH_ATTR const char _unit_decibel_milliwatts[] = "dBm";
static FLASH_ATTR const char _unit_gauss[] = "Gs";
static FLASH_ATTR const char _unit_tesla[] = "T";
static FLASH_ATTR const char _unit_bar[] = "Bar";
static FLASH_ATTR const char _unit_pascal[] = "Pa";
static FLASH_ATTR const char _unit_permille[] = "permille";
static FLASH_ATTR const char _unit_parts_per_million[] = "ppm";
static FLASH_ATTR const char _unit_parts_per_billion[] = "ppb";
static FLASH_ATTR const char _unit_candela[] = "cd";
static FLASH_ATTR const char _unit_percent[] = "%";
static FLASH_ATTR const char _unit_counts[] = "cts";
static FLASH_ATTR const char _unit_coulomb[] = "C";
static FLASH_ATTR const char _unit_gram_per_cubic_metre[] = "g/m^3";
static FLASH_ATTR const char _unit_farad[] = "F";
static FLASH_ATTR const char _unit_potential_of_hydrogen[] = "pH";
static FLASH_ATTR const char _unit_count_per_cubic_metre[] = "#/m^3";
static FLASH_ATTR const char _unit_ohm[] = "ohm";
static FLASH_ATTR const char _unit_undefined[] = "undefined";
static FLASH_ATTR const char _unit_none[] = "none";
static FLASH_ATTR const char _unit_time[] = "time";
static FLASH_ATTR const char _unit_date[] = "date";
static FLASH_ATTR const char * FLASH_ATTR const _unit_to_str[] = {
[UNIT_TEMP_C] = _unit_celsius,
[UNIT_TEMP_F] = _unit_fahrenheit,
[UNIT_TEMP_K] = _unit_kelvin,
[UNIT_LUX] = _unit_lux,
[UNIT_M] = _unit_metre,
[UNIT_M2] = _unit_square_metre,
[UNIT_M3] = _unit_cubic_metre,
[UNIT_G_FORCE] = _unit_g_force,
[UNIT_DPS] = _unit_degree_per_second,
[UNIT_GRAM] = _unit_gram,
[UNIT_A] = _unit_ampere,
[UNIT_V] = _unit_volt,
[UNIT_W] = _unit_watt,
[UNIT_DBM] = _unit_decibel_milliwatts,
[UNIT_GS] = _unit_gauss,
[UNIT_T] = _unit_tesla,
[UNIT_BAR] = _unit_bar,
[UNIT_PA] = _unit_pascal,
[UNIT_PERMILL] = _unit_permille,
[UNIT_PPM] = _unit_parts_per_million,
[UNIT_PPB] = _unit_parts_per_billion,
[UNIT_CD] = _unit_candela,
[UNIT_PERCENT] = _unit_percent,
[UNIT_CTS] = _unit_counts,
[UNIT_COULOMB] = _unit_coulomb,
[UNIT_GPM3] = _unit_gram_per_cubic_metre,
[UNIT_F] = _unit_farad,
[UNIT_PH] = _unit_potential_of_hydrogen,
[UNIT_CPM3] = _unit_count_per_cubic_metre,
[UNIT_OHM] = _unit_ohm,
[UNIT_UNDEF] = _unit_undefined,
[UNIT_NONE] = _unit_none,
[UNIT_BOOL] = _unit_none,
[UNIT_TIME] = _unit_time,
[UNIT_DATE] = _unit_date,
};
ssize_t phydat_unit_write(char *dest, size_t max_size, uint8_t unit)
{
if ((unit >= ARRAY_SIZE(_unit_to_str)) || (_unit_to_str[unit]) == NULL) {
return -EINVAL;
}
size_t len = flash_strlen(_unit_to_str[unit]);
if (dest) {
if (max_size < len) {
return -EOVERFLOW;
}
flash_memcpy(dest, _unit_to_str[unit], len);
}
return len;
}
const char *phydat_unit_to_str(uint8_t unit)
{
switch (unit) {
case UNIT_TEMP_C: return "°C";
case UNIT_TEMP_F: return "°F";
case UNIT_TEMP_K: return "K";
case UNIT_LUX: return "lx";
case UNIT_M: return "m";
case UNIT_M2: return "m^2";
case UNIT_M3: return "m^3";
case UNIT_G_FORCE: return "gₙ";
case UNIT_DPS: return "dps";
case UNIT_GRAM: return "g";
case UNIT_A: return "A";
case UNIT_V: return "V";
case UNIT_W: return "W";
case UNIT_DBM: return "dBm";
case UNIT_GAUSS: return "Gs";
case UNIT_T: return "T";
case UNIT_BAR: return "Bar";
case UNIT_PA: return "Pa";
case UNIT_PERMILL: return "permille";
case UNIT_PPM: return "ppm";
case UNIT_PPB: return "ppb";
case UNIT_CD: return "cd";
case UNIT_PERCENT: return "%";
case UNIT_CTS: return "cts";
case UNIT_COULOMB: return "C";
case UNIT_GPM3: return "g/m^3";
case UNIT_F: return "F";
case UNIT_PH: return "pH";
case UNIT_CPM3: return "#/m^3";
case UNIT_OHM: return "ohm";
default: return "";
#if IS_ACTIVE(HAS_FLASH_UTILS_ARCH)
/* Yeah, this is as bad as it looks... The function is deprecated for this
* reason and it will only affect AVR users, for whom this is a good
* trade-off. */
static char buf[8];
ssize_t pos = phydat_unit_write(buf, sizeof(buf) - 1, unit);
assert(pos >= 0);
if (pos < 0) {
pos = 0;
}
buf[pos] = '\0';
return buf;
#else
if ((unit < ARRAY_SIZE(_unit_to_str)) && (_unit_to_str[unit])) {
return _unit_to_str[unit];
}
return "";
#endif
}
const char *phydat_unit_to_str_verbose(uint8_t unit)
{
switch (unit) {
case UNIT_UNDEF: return "undefined";
case UNIT_NONE: /* fall through */
case UNIT_BOOL:
return "none";
case UNIT_TIME: return "time";
case UNIT_DATE: return "date";
default: return phydat_unit_to_str(unit);
return phydat_unit_to_str(unit);
}
void phydat_unit_print(uint8_t unit)
{
if ((unit < ARRAY_SIZE(_unit_to_str)) && (_unit_to_str[unit]) != NULL) {
flash_print_str(_unit_to_str[unit]);
}
}
char phydat_prefix_from_scale(int8_t scale)
{
switch (scale) {
case -3: return 'm';
case -6: return 'u';
case -9: return 'n';
case -12: return 'p';
case -15: return 'f';
case 2: return 'h';
case 3: return 'k';
case 6: return 'M';
case 9: return 'G';
case 12: return 'T';
case 15: return 'P';
default: return '\0';
static FLASH_ATTR const char _prefix[] = {
'f', '\0', '\0',
'p', '\0', '\0',
'n', '\0', '\0',
'u', '\0', '\0',
'm', '\0', '\0',
'\0', '\0', 'h',
'k', '\0', '\0',
'M', '\0', '\0',
'G', '\0', '\0',
'T', '\0', '\0',
'P',
};
int8_t idx = scale + ARRAY_SIZE(_prefix) / 2;
if ((idx < 0) || (idx >= (int8_t)ARRAY_SIZE(_prefix))) {
return '\0';
}
return _prefix[idx];
}

View File

@ -24,6 +24,7 @@
#include <string.h>
#include <stdlib.h>
#include "flash_utils.h"
#include "saul_reg.h"
#include "shell.h"
@ -47,8 +48,9 @@ static void probe(int num, saul_reg_t *dev)
return;
}
/* print results */
printf("Reading from #%i (%s|%s)\n", num, _devname(dev),
saul_class_to_str(dev->driver->type));
printf("Reading from #%i (%s|", num, _devname(dev));
saul_class_print(dev->driver->type);
printf(")\n");
phydat_dump(&res, dim);
}
@ -70,14 +72,15 @@ static void list(void)
int i = 0;
if (dev) {
puts("ID\tClass\t\tName");
printf("ID\tClass\t\tName\n");
}
else {
puts("No devices found");
printf("No devices found\n");
}
while (dev) {
printf("#%i\t%s\t%s\n",
i++, saul_class_to_str(dev->driver->type), _devname(dev));
printf("#%i\t", i++);
saul_class_print(dev->driver->type);
printf("\t%s\n", _devname(dev));
dev = dev->next;
}
}
@ -88,10 +91,11 @@ static void read(int argc, char **argv)
saul_reg_t *dev;
if (argc < 3) {
printf("usage: %s %s <device id>|all\n", argv[0], argv[1]);
printf("usage: %s %s <device id>|all\n",
argv[0], argv[1]);
return;
}
if (strcmp(argv[2], "all") == 0) {
if (flash_strcmp(argv[2], TO_FLASH("all")) == 0) {
probe_all();
return;
}
@ -99,7 +103,7 @@ static void read(int argc, char **argv)
num = atoi(argv[2]);
dev = saul_reg_find_nth(num);
if (dev == NULL) {
puts("error: undefined device id given");
printf("error: undefined device id given\n");
return;
}
probe(num, dev);
@ -113,13 +117,13 @@ static void write(int argc, char **argv)
if (argc < 4) {
printf("usage: %s %s <device id> <value 0> [<value 1> [<value 2]]\n",
argv[0], argv[1]);
argv[0], argv[1]);
return;
}
num = atoi(argv[2]);
dev = saul_reg_find_nth(num);
if (dev == NULL) {
puts("error: undefined device given");
printf("error: undefined device given\n");
return;
}
/* parse value(s) */
@ -151,10 +155,10 @@ static int _saul(int argc, char **argv)
list();
}
else {
if (strcmp(argv[1], "read") == 0) {
if (flash_strcmp(argv[1], TO_FLASH("read")) == 0) {
read(argc, argv);
}
else if (strcmp(argv[1], "write") == 0) {
else if (flash_strcmp(argv[1], TO_FLASH("write")) == 0) {
write(argc, argv);
}
else {

View File

@ -41,7 +41,7 @@
#include "shell_lock.h"
/* define shell command cross file array */
XFA_INIT_CONST(shell_command_t*, shell_commands_xfa);
XFA_INIT_CONST(shell_command_xfa_t*, shell_commands_xfa);
#define ETX '\x03' /** ASCII "End-of-Text", or Ctrl-C */
#define EOT '\x04' /** ASCII "End-of-Transmission", or Ctrl-D */
@ -99,8 +99,8 @@ static shell_command_handler_t search_commands_xfa(char *command)
unsigned n = XFA_LEN(shell_command_t*, shell_commands_xfa);
for (unsigned i = 0; i < n; i++) {
const volatile shell_command_t *entry = shell_commands_xfa[i];
if (strcmp(entry->name, command) == 0) {
const volatile shell_command_xfa_t *entry = shell_commands_xfa[i];
if (flash_strcmp(command, entry->name) == 0) {
return entry->handler;
}
}
@ -132,17 +132,18 @@ static void print_commands(const shell_command_t *entry)
static void print_commands_xfa(void)
{
unsigned n = XFA_LEN(shell_command_t*, shell_commands_xfa);
unsigned n = XFA_LEN(shell_command_xfa_t*, shell_commands_xfa);
for (unsigned i = 0; i < n; i++) {
const volatile shell_command_t *entry = shell_commands_xfa[i];
printf("%-20s %s\n", entry->name, entry->desc);
const volatile shell_command_xfa_t *entry = shell_commands_xfa[i];
printf("%-20" PRIsflash " %" PRIsflash "\n",
entry->name, entry->desc);
}
}
static void print_help(const shell_command_t *command_list)
{
puts("Command Description"
"\n---------------------------------------");
printf("Command Description\n"
"---------------------------------------\n");
if (command_list != NULL) {
print_commands(command_list);
}
@ -294,7 +295,7 @@ static void handle_input_line(const shell_command_t *command_list, char *line)
*writepos = '\0';
if (pstate != PARSE_BLANK && pstate != PARSE_UNQUOTED) {
puts("shell: incorrect quoting");
printf("shell: incorrect quoting\n");
return;
}
@ -503,7 +504,7 @@ void shell_run_once(const shell_command_t *shell_commands,
return;
case -ENOBUFS:
puts("shell: maximum line length exceeded");
printf("shell: maximum line length exceeded\n");
break;
default:

View File

@ -162,6 +162,14 @@ static void _fill_ethernet(usbus_cdcecm_device_t *cdcecm)
}
void _start_urb(usbus_cdcecm_device_t *cdcecm)
{
usbus_urb_init(&cdcecm->out_urb,
cdcecm->data_out,
USBUS_ETHERNET_FRAME_BUF, 0);
usbus_urb_submit(cdcecm->usbus, cdcecm->ep_out, &cdcecm->out_urb);
}
void usbus_cdcecm_init(usbus_t *usbus, usbus_cdcecm_device_t *handler)
{
assert(usbus);
@ -251,9 +259,9 @@ static int _control_handler(usbus_t *usbus, usbus_handler_t *handler,
setup->value);
cdcecm->active_iface = (uint8_t)setup->value;
if (cdcecm->active_iface == 1) {
usbdev_ep_xmit(cdcecm->ep_out->ep, cdcecm->data_out,
USBUS_CDCECM_EP_DATA_SIZE);
_notify_link_up(cdcecm);
/* Start URB */
_start_urb(cdcecm);
}
break;
@ -298,8 +306,8 @@ static void _handle_rx_flush_ev(event_t *ev)
{
usbus_cdcecm_device_t *cdcecm = container_of(ev, usbus_cdcecm_device_t,
rx_flush);
cdcecm->len = 0; /* Flush packet */
usbdev_ep_xmit(cdcecm->ep_out->ep, cdcecm->data_out, USBUS_CDCECM_EP_DATA_SIZE);
/* Start URB */
_start_urb(cdcecm);
}
static void _transfer_handler(usbus_t *usbus, usbus_handler_t *handler,
@ -310,20 +318,7 @@ static void _transfer_handler(usbus_t *usbus, usbus_handler_t *handler,
usbus_cdcecm_device_t *cdcecm = (usbus_cdcecm_device_t *)handler;
if (ep == cdcecm->ep_out->ep) {
/* Retrieve incoming data */
if (cdcecm->notif == USBUS_CDCECM_NOTIF_NONE) {
_notify_link_up(cdcecm);
}
size_t len = 0;
usbdev_ep_get(ep, USBOPT_EP_AVAILABLE, &len, sizeof(size_t));
cdcecm->len += len;
if (len == USBUS_CDCECM_EP_DATA_SIZE) {
/* ready next chunk */
usbdev_ep_xmit(ep, cdcecm->data_out + cdcecm->len,
USBUS_CDCECM_EP_DATA_SIZE);
}
else {
netdev_trigger_event_isr(&cdcecm->netdev);
}
netdev_trigger_event_isr(&cdcecm->netdev);
}
else if (ep == cdcecm->ep_in->ep) {
_handle_in_complete(usbus, handler);
@ -341,7 +336,6 @@ static void _handle_reset(usbus_t *usbus, usbus_handler_t *handler)
DEBUG("CDC ECM: Reset\n");
_handle_in_complete(usbus, handler);
cdcecm->notif = USBUS_CDCECM_NOTIF_NONE;
cdcecm->len = 0; /* Flush received data */
cdcecm->active_iface = 0;
mutex_unlock(&cdcecm->out_lock);
}

View File

@ -132,7 +132,7 @@ static int _recv(netdev_t *netdev, void *buf, size_t max_len, void *info)
(void)info;
usbus_cdcecm_device_t *cdcecm = _netdev_to_cdcecm(netdev);
size_t pktlen = cdcecm->len;
size_t pktlen = cdcecm->out_urb.transferred;
if (max_len == 0 && buf == NULL) {
return pktlen;
@ -198,7 +198,7 @@ static void _isr(netdev_t *dev)
{
usbus_cdcecm_device_t *cdcecm = _netdev_to_cdcecm(dev);
if (cdcecm->len) {
if (cdcecm->out_urb.transferred) {
cdcecm->netdev.event_callback(&cdcecm->netdev,
NETDEV_EVENT_RX_COMPLETE);
}

View File

@ -108,6 +108,12 @@ static usbus_handler_t *_ep_to_handler(usbus_t *usbus, usbdev_ep_t *ep)
return NULL;
}
static inline usbus_endpoint_t *_usbus_ep_from_usbdev(usbus_t *usbus, usbdev_ep_t* ep)
{
return ep->dir == USB_EP_DIR_IN ? &usbus->ep_in[ep->num]
: &usbus->ep_out[ep->num];
}
uint16_t usbus_add_interface(usbus_t *usbus, usbus_interface_t *iface)
{
/* While it is possible to us clist.h here, this results in less flash
@ -164,8 +170,7 @@ usbus_endpoint_t *usbus_add_endpoint(usbus_t *usbus, usbus_interface_t *iface,
usbdev_ep_t *usbdev_ep = usbdev_new_ep(usbus->dev, type, dir, len);
if (usbdev_ep) {
ep = dir == USB_EP_DIR_IN ? &usbus->ep_in[usbdev_ep->num]
: &usbus->ep_out[usbdev_ep->num];
ep = _usbus_ep_from_usbdev(usbus, usbdev_ep);
ep->maxpacketsize = len;
ep->ep = usbdev_ep;
if (iface) {
@ -217,6 +222,121 @@ static void _usbus_init_handlers(usbus_t *usbus)
}
}
#ifdef MODULE_USBUS_URB
static void _usbus_transfer_urb_submit(usbus_endpoint_t *usbus_ep,
usbus_urb_t *urb)
{
/* Maximum between the urb length and the endpoint maximum size */
size_t len = urb->len > usbus_ep->maxpacketsize ?
usbus_ep->maxpacketsize :
urb->len;
usbdev_ep_xmit(usbus_ep->ep, urb->buf, len);
urb->buf += len;
urb->len -= len;
}
void usbus_urb_submit(usbus_t *usbus, usbus_endpoint_t *endpoint, usbus_urb_t *urb)
{
(void)usbus;
assert(!(clist_find(&endpoint->urb_list, &urb->list)));
if (endpoint->ep->dir == USB_EP_DIR_IN &&
((urb->len % endpoint->maxpacketsize) == 0) &&
usbus_urb_isset_flag(urb, USBUS_URB_FLAG_AUTO_ZLP)) {
/* If it is an IN endpoint, the urb length is a whole number of
* transfers and the ZLP is requested, then set flag that it needs the
* ZLP
*/
urb->flags |= USBUS_URB_FLAG_NEEDS_ZLP;
}
clist_rpush(&endpoint->urb_list, &urb->list);
/* Initiate transfer immediately if the list is empty */
if (clist_exactly_one(&endpoint->urb_list)) {
_usbus_transfer_urb_submit(endpoint, urb);
}
}
int usbus_urb_cancel(usbus_t *usbus, usbus_endpoint_t *endpoint, usbus_urb_t *urb)
{
(void)usbus;
usbus_urb_t *active_urb = (usbus_urb_t*)clist_lpeek(&endpoint->urb_list);
if (active_urb == urb) {
usbus_urb_set_flag(active_urb, USBUS_URB_FLAG_CANCELLED);
usbus_urb_remove_flag(active_urb, USBUS_URB_FLAG_NEEDS_ZLP);
return 0;
}
if (clist_remove(&endpoint->urb_list, &urb->list)) {
return 1;
}
return -1; /* URB not found */
}
static bool _urb_transfer_complete(usbus_t *usbus, usbdev_ep_t *ep,
usbus_handler_t *handler)
{
usbus_endpoint_t *usbus_ep = _usbus_ep_from_usbdev(usbus, ep);
if (clist_is_empty(&usbus_ep->urb_list)) {
return false;
}
/* Ongoing transfer */
usbus_urb_t *active_urb = (usbus_urb_t*)clist_lpeek(&usbus_ep->urb_list);
size_t len = usbus_ep->maxpacketsize;
if (ep->dir == USB_EP_DIR_OUT) {
usbdev_ep_get(ep, USBOPT_EP_AVAILABLE, &len, sizeof(size_t));
active_urb->transferred += len;
}
if ((active_urb->len == 0) || (len < usbus_ep->maxpacketsize) ||
(usbus_urb_isset_flag(active_urb, USBUS_URB_FLAG_CANCELLED))) {
/* Only set for IN endpoints */
if (usbus_urb_isset_flag(active_urb, USBUS_URB_FLAG_NEEDS_ZLP)) {
usbus_urb_remove_flag(active_urb, USBUS_URB_FLAG_NEEDS_ZLP);
_usbus_transfer_urb_submit(usbus_ep, active_urb);
}
else {
/* transfer of URB complete */
clist_lpop(&usbus_ep->urb_list);
/* Schedule next URB first, then notify the handler */
usbus_urb_t *next_urb = (usbus_urb_t*)clist_lpeek(&usbus_ep->urb_list);
if (next_urb) {
_usbus_transfer_urb_submit(usbus_ep, next_urb);
}
DEBUG("Done with the transfer, available: %u, len: %u\n",
(unsigned)active_urb->transferred, (unsigned)active_urb->len);
handler->driver->transfer_handler(usbus, handler, ep,
USBUS_EVENT_TRANSFER_COMPLETE);
}
}
else {
_usbus_transfer_urb_submit(usbus_ep, active_urb);
}
return true;
}
#else
static bool _urb_transfer_complete(usbus_t *usbus, usbdev_ep_t *ep,
usbus_handler_t *handler)
{
(void)usbus;
(void)ep;
(void)handler;
return false;
}
#endif /* MODULE_USBUS_URB */
static void _usbus_transfer_complete(usbus_t *usbus, usbdev_ep_t *ep, usbus_handler_t *handler)
{
if (_urb_transfer_complete(usbus, ep, handler)) {
return;
}
/* Raw usbdev transfers by the handler */
handler->driver->transfer_handler(usbus, handler, ep, USBUS_EVENT_TRANSFER_COMPLETE);
}
static void *_usbus_thread(void *args)
{
usbus_t *usbus = (usbus_t *)args;
@ -361,8 +481,7 @@ static void _event_ep_cb(usbdev_ep_t *ep, usbdev_event_t event)
if (handler) {
switch (event) {
case USBDEV_EVENT_TR_COMPLETE:
handler->driver->transfer_handler(usbus, handler, ep,
USBUS_EVENT_TRANSFER_COMPLETE);
_usbus_transfer_complete(usbus, ep, handler);
break;
case USBDEV_EVENT_TR_FAIL:
if (usbus_handler_isset_flag(handler,

View File

@ -1,9 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-f031k6 \
nucleo-l011k4 \
stm32f030f4-demo \

View File

@ -1,9 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-f031k6 \
nucleo-l011k4 \
stm32f030f4-demo \

View File

@ -1,8 +1,3 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
#

View File

@ -1,8 +1,2 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
#

View File

@ -3,8 +3,8 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p-xplained-mini \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
samd10-xmini \
stm32f030f4-demo \

View File

@ -1,8 +1,3 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
#

View File

@ -1,9 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-f031k6 \
nucleo-l011k4 \
stm32f030f4-demo \

View File

@ -1,9 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-f031k6 \
nucleo-l011k4 \
stm32f030f4-demo \

View File

@ -1,10 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
bluepill-stm32f030c8 \
im880b \
nucleo-l011k4 \

View File

@ -1,10 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
bluepill-stm32f030c8 \
im880b \
nucleo-l011k4 \

View File

@ -1,6 +1,5 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \

View File

@ -1,8 +1,2 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
#

View File

@ -1,9 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
stm32f030f4-demo \
#

View File

@ -1,9 +1,9 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
#

View File

@ -1,12 +1,5 @@
BOARD_INSUFFICIENT_MEMORY := \
airfy-beacon \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
calliope-mini \
hifive1 \
hifive1b \
@ -34,7 +27,6 @@ BOARD_INSUFFICIENT_MEMORY := \
stm32f030f4-demo \
stm32l0538-disco \
telosb \
waspmote-pro \
yunjia-nrf51822 \
z1 \
#

View File

@ -1,8 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
mega-xplained \
microduino-corerf \
stm32f030f4-demo \
waspmote-pro \
zigduino \
#

View File

@ -5,7 +5,6 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
nucleo-f031k6 \
nucleo-l011k4 \
samd10-xmini \

View File

@ -1,7 +1,2 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
#

View File

@ -1,10 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
samd10-xmini \
#

View File

@ -3,8 +3,8 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p-xplained-mini \
atmega328p \
atmega328p-xplained-mini \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-l011k4 \

View File

@ -1,9 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
samd10-xmini \
stm32f030f4-demo \

View File

@ -1,6 +1,5 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \

View File

@ -1,6 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-uno \
chronos \
msb-430 \
msb-430h \

View File

@ -1,10 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
samd10-xmini \
stk3200 \

View File

@ -18,9 +18,10 @@
#include <stdio.h>
#include "xtimer.h"
#include "flash_utils.h"
#include "phydat.h"
#include "saul_reg.h"
#include "xtimer.h"
/**
* @brief Read the sensors every second
@ -44,7 +45,7 @@ int main(void)
while (dev) {
int dim = saul_reg_read(dev, &res);
printf("\nDev: %s\tType: %s\n", dev->name,
printf("\nDev: %s\tType: %" PRIsflash "\n", dev->name,
saul_class_to_str(dev->driver->type));
phydat_dump(&res, dim);
dev = dev->next;

View File

@ -1,7 +1,2 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
#

View File

@ -9,8 +9,8 @@ BOARD_INSUFFICIENT_MEMORY := \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
blackpill-stm32f103c8 \
bluepill-stm32f103c8 \
bluepill-stm32f030c8 \
bluepill-stm32f103c8 \
derfmega128 \
hifive1 \
hifive1b \

View File

@ -3,8 +3,8 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p-xplained-mini \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
samd10-xmini \
stm32f030f4-demo \

View File

@ -1,8 +1,3 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
#

View File

@ -1,6 +1,5 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \

View File

@ -1,6 +1,5 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \

View File

@ -1,6 +1,5 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \

View File

@ -1,10 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p-xplained-mini \
atmega328p \
nucleo-l011k4 \
samd10-xmini \
stm32f030f4-demo \

View File

@ -1,8 +1,2 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
#

View File

@ -1,10 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
samd10-xmini \
#

View File

@ -1,10 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p-xplained-mini \
atmega328p \
nucleo-l011k4 \
samd10-xmini \
stm32f030f4-demo \

View File

@ -4,16 +4,12 @@ BOARD_INSUFFICIENT_MEMORY := \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega128rfa1 \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
bluepill-stm32f030c8 \
derfmega128 \
i-nucleo-lrwan1 \
mega-xplained \
microduino-corerf \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-l011k4 \

View File

@ -1,8 +1,2 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
#

View File

@ -1,9 +1,3 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
atmega32u4 \
#

View File

@ -1,8 +1,2 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
#

View File

@ -1,10 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-f031k6 \
nucleo-l011k4 \
samd10-xmini \

View File

@ -1,8 +1,2 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
#

View File

@ -1,6 +1,5 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \

View File

@ -1,9 +1,3 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
atmega32u4 \
#

View File

@ -1,9 +1,4 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
samd10-xmini \
#

View File

@ -1,8 +1,2 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
#

View File

@ -6,7 +6,6 @@ BOARD_INSUFFICIENT_MEMORY := \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
stm32f030f4-demo \
samd10-xmini \
waspmote-pro \
stm32f030f4-demo \
#

View File

@ -1,8 +1,2 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
#

View File

@ -1,7 +1,6 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega328p \
@ -24,5 +23,4 @@ BOARD_INSUFFICIENT_MEMORY := \
stm32f030f4-demo \
stm32f0discovery \
stm32l0538-disco \
waspmote-pro \
#

View File

@ -1,7 +1,6 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega328p \
@ -15,5 +14,4 @@ BOARD_INSUFFICIENT_MEMORY := \
stk3200 \
stm32f030f4-demo \
stm32f0discovery \
waspmote-pro \
#

View File

@ -12,9 +12,9 @@ BOARD_INSUFFICIENT_MEMORY := \
b-l072z-lrwan1 \
blackpill-stm32f103c8 \
blackpill-stm32f103cb \
bluepill-stm32f030c8 \
bluepill-stm32f103c8 \
bluepill-stm32f103cb \
bluepill-stm32f030c8 \
calliope-mini \
cc2650-launchpad \
cc2650stk \

Some files were not shown because too many files have changed in this diff Show More