diff --git a/.gitignore b/.gitignore index 2d1efe5ca06d..2dacfe540a5b 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,8 @@ cachegrind.out* tags # GDB initialization scripts .gdbinit +# GDB history (when using gdb-dashboard) +.gdb_history # Eclipse symbol file (output from make eclipsesym) eclipsesym.xml diff --git a/.mailmap b/.mailmap index 5d795abab2ca..aba19f1453cd 100644 --- a/.mailmap +++ b/.mailmap @@ -26,4 +26,6 @@ Peter Kietzmann René Kijewski René Kijewski Sebastian Meiling +Marian Buschsieweke Marian Buschsieweke +Marian Buschsieweke diff --git a/LOSTANDFOUND.md b/LOSTANDFOUND.md index 1132f1398fc6..b2df5cab655a 100644 --- a/LOSTANDFOUND.md +++ b/LOSTANDFOUND.md @@ -302,6 +302,18 @@ therefore, have no interest in supporting this board. As result, none of the RIOT core contributors has access to the hardware, preventing us from doing the necessary testing for maintaining this board. +### boards/nrf6310 [4953ba8e6759d2b1a1a1ea497a4ad1e71489195a] +Author(s): +- Christian Kühling +- Timo Ziegler +- Hauke Petersen + +Reason for removal: +- this was an early development board by Nordic which was discontinued + (successor: `nrf51dk`) +- also for a `BLE DEVKIT.N` board from Mommosoft, which was discontinued as well +- no hardware available anymore for testing, many exclusions from CI + [6cad5d24771ba6199228351a11b5062cd2e9b36d]: https://github.com/RIOT-OS/RIOT/commit/6cad5d24771ba6199228351a11b5062cd2e9b36d [d83d08f0995a88f399e70a7d07b44dd780082436]: https://github.com/RIOT-OS/RIOT/commit/d83d08f0995a88f399e70a7d07b44dd780082436 [cdc252ab7bd4161cc046bf93a3e55995704b24d4]: https://github.com/RIOT-OS/RIOT/commit/cdc252ab7bd4161cc046bf93a3e55995704b24d4 @@ -334,3 +346,4 @@ necessary testing for maintaining this board. [fe941ac9fe3f81c0f08ff3b8564cf439639abcda]: https://github.com/RIOT-OS/RIOT/commit/fe941ac9fe3f81c0f08ff3b8564cf439639abcda [81458c8eed8949c686d5ded652dbee10748e860b]: https://github.com/RIOT-OS/RIOT/commit/81458c8eed8949c686d5ded652dbee10748e860b [2b8a0d48940517f7df4e78c7a0b16024f46a8694]: https://github.com/RIOT-OS/RIOT/commit/2b8a0d48940517f7df4e78c7a0b16024f46a8694 +[4953ba8e6759d2b1a1a1ea497a4ad1e71489195a]: https://github.com/RIOT-OS/RIOT/commit/4953ba8e6759d2b1a1a1ea497a4ad1e71489195a diff --git a/Makefile.include b/Makefile.include index dcea932fa1a0..ab7309978a8a 100644 --- a/Makefile.include +++ b/Makefile.include @@ -934,7 +934,7 @@ include $(RIOTMAKE)/tools/targets.inc.mk include $(RIOTMAKE)/usb-codes.inc.mk # Warn if the selected board and drivers don't provide all needed features: -ifneq (, $(filter all flash, $(if $(MAKECMDGOALS), $(MAKECMDGOALS), all))) +ifeq (, $(filter help generate-Makefile.ci, $(MAKECMDGOALS))) EXPECT_ERRORS := # Test if there where dependencies against a module in DISABLE_MODULE. @@ -1012,7 +1012,8 @@ endif help: # filter all targets starting with lowercase and containing lowercase letters, hyphens, or underscores; explicitly include generate-Makefile.ci - @$(MAKE) -qp | sed -ne 's/\(^[a-z][a-z_-]*\|generate-Makefile.ci\):.*/\1/p' | sort -u + # inspired by: https://stackoverflow.com/a/26339924 + @LC_ALL=C $(MAKE) -pRrq -f $(firstword $(MAKEFILE_LIST)) : 2>/dev/null | sed -ne 's/\(^[a-z][a-z_-]*\|generate-Makefile.ci\):.*/\1/p' | sort -u ifeq (iotlab-m3,$(BOARD)) ifneq (,$(filter iotlab-%,$(MAKECMDGOALS))) diff --git a/boards/arduino-due/doc.txt b/boards/arduino-due/doc.txt index 11f1cb7ae5eb..f300b862dd3e 100644 --- a/boards/arduino-due/doc.txt +++ b/boards/arduino-due/doc.txt @@ -3,5 +3,59 @@ @ingroup boards @brief Support for the Arduino Due board -@see boards_common_arduino_due for details +\section arduino_due Arduino-Due + +## Table of Contents {#arduino_due_toc} + +1. [Overview](#arduino_due_overview) +2. [Hardware](#arduino_due_hardware) + 1. [MCU](#atmel_sam3x8e_mcu) + 2. [Board Configuration](#arduino_due_board_configuration) + 3. [Board Pinout](#arduino_due_pinout) +3. [Flashing the Device](#arduino_due_flashing) + +## Overview {#arduino_due_overview} + +The Arduino Due is a microcontroller board based on the Atmel SAM3X8E ARM Cortex-M3 CPU. +It is the first Arduino board based on a 32-bit ARM core microcontroller. + +\image html "https://store.arduino.cc/cdn/shop/files/A000062_00.front_1000x750.jpg" "Arduino Due board" width=750px + +## Hardware {#arduino_due_hardware} + +### MCU {#atmel_sam3x8e_mcu} + +The board features a SAM3X8E MCU (ARM Cortex-M3) running at up to 84MHz. +It embeds 96 KiB of SRAM and 512 KiB of flash memory. +The board reference manual is available [here](https://docs.arduino.cc/resources/datasheets/A000062-datasheet.pdf) +and the MCU datasheet is available [here](https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet.pdf). + +### Board configuration {#arduino_due_board_configuration} +The Arduino Due provides the following features: +- 54 I/Os (of which 12 PWM outputs) +- 12 analog inputs +- 4 UARTs +- 1 USB OTG +- 2 DAC outputs +- 2 TWI +- 1 power jack +- 1 SPI header +- 1 JTAG header +- 2 CAN Buses +- A reset button +- An erase button + +### Board pinout {#arduino_due_pinout} + +\image html "https://content.arduino.cc/assets/Pinout-Due_latest.png" "Arduino Due pinout" + +The board schematics are available [here](https://docs.arduino.cc/resources/schematics/A000056-schematics.pdf). + +## Flashing the device {#arduino_due_flashing} +Flashing RIOT on the Arduino Due is quite straight forward as it relies on +the preinstalled arduino bootloader. Connect your board using the programming +port to your host computer and type: + +`make BOARD=arduino-due flash` + */ diff --git a/boards/esp32-ethernet-kit-v1_0/doc.txt b/boards/esp32-ethernet-kit-v1_0/doc.txt index 9fa40cce8532..db6663a2c592 100644 --- a/boards/esp32-ethernet-kit-v1_0/doc.txt +++ b/boards/esp32-ethernet-kit-v1_0/doc.txt @@ -26,7 +26,7 @@ ## Overview {#esp32_ethernet_kit_v1_0_overview} -The Espressif [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-ethernet-kit-v1.0.html) is a development board that uses the ESP32-WROVER-B module. Most important features of the board are +The Espressif [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/esp32-ethernet-kit/user_guide.html) is a development board that uses the ESP32-WROVER-B module. Most important features of the board are - 100 Mbps Ethernet via IP101G PHY - USB bridge with JTAG interface @@ -34,7 +34,7 @@ The Espressif [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/e Furthermore, some GPIOs are broken out for extension. The USB bridge based on FDI FT2232HL provides a JTAG interface for OCD debugging through the USB interface. For flashing and debugging the board, see \ref boards_esp32_esp-ethernet-kit common board documentation. -@image html "https://docs.espressif.com/projects/esp-idf/en/latest/esp32/_images/esp32-ethernet-kit-v1.0.png" "ESP32-Ethernet-Kit V1.0" width=500 +@image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/_images/esp32-ethernet-kit-v1.0.png" "ESP32-Ethernet-Kit V1.0" width=500 [Back to table of contents](#esp32_ethernet_kit_v1_0_toc) diff --git a/boards/esp32-ethernet-kit-v1_1/doc.txt b/boards/esp32-ethernet-kit-v1_1/doc.txt index 54e3b23d50d4..e684c3876640 100644 --- a/boards/esp32-ethernet-kit-v1_1/doc.txt +++ b/boards/esp32-ethernet-kit-v1_1/doc.txt @@ -34,7 +34,7 @@ The Espressif [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/e Furthermore, some GPIOs are broken out for extension. The USB bridge based on FDI FT2232HL provides a JTAG interface for OCD debugging through the USB interface. For flashing and debugging the board, see \ref boards_esp32_esp-ethernet-kit common board documentation. -@image html "https://docs.espressif.com/projects/esp-idf/en/latest/esp32/_images/esp32-ethernet-kit-v1.1.png" "ESP32-Ethernet-Kit V1.1" width=500 +@image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/_images/esp32-ethernet-kit-v1.1.png" "ESP32-Ethernet-Kit V1.1" width=500 [Back to table of contents](#esp32_ethernet_kit_v1_1_toc) diff --git a/boards/esp32-ethernet-kit-v1_2/doc.txt b/boards/esp32-ethernet-kit-v1_2/doc.txt index 362a8894091d..64958eb87536 100644 --- a/boards/esp32-ethernet-kit-v1_2/doc.txt +++ b/boards/esp32-ethernet-kit-v1_2/doc.txt @@ -34,7 +34,7 @@ The Espressif [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/e Furthermore, some GPIOs are broken out for extension. The USB bridge based on FDI FT2232HL provides a JTAG interface for OCD debugging through the USB interface. For flashing and debugging the board, see \ref boards_esp32_esp-ethernet-kit common board documentation. -@image html "https://docs.espressif.com/projects/esp-idf/en/latest/esp32/_images/esp32-ethernet-kit-v1.2.jpg" "ESP32-Ethernet-Kit V1.2" width=500 +@image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/_images/esp32-ethernet-kit-v1.2.jpg" "ESP32-Ethernet-Kit V1.2" width=500 [Back to table of contents](#esp32_ethernet_kit_v1_2_toc) diff --git a/boards/esp32-heltec-lora32-v2/doc.txt b/boards/esp32-heltec-lora32-v2/doc.txt index b509ae9da2d2..5faa30f15bb7 100644 --- a/boards/esp32-heltec-lora32-v2/doc.txt +++ b/boards/esp32-heltec-lora32-v2/doc.txt @@ -37,7 +37,7 @@ Since the board is [open source hardware](https://github.com/Heltec-Aaron-Lee/WiFi_Kit_series), a number of clones are available. -@image html "https://heltec.org/wp-content/uploads/2020/04/SAM_0748_800X800.png" "Heltec WiFi Lora 32 V2" width=400px +@image html "https://heltec.org/wp-content/uploads/2024/07/wifi-lora-32-v2-1.png" "Heltec WiFi Lora 32 V2" width=400px [Back to table of contents](#esp32_heltec_lora32_v2_toc) diff --git a/boards/esp32c3-devkit/doc.txt b/boards/esp32c3-devkit/doc.txt index 8c9aba385426..7f468320d523 100644 --- a/boards/esp32c3-devkit/doc.txt +++ b/boards/esp32c3-devkit/doc.txt @@ -36,7 +36,7 @@ limited, the ESP32-C3-DevKit should also work for most other ESP32-C3 boards. Any modifications required for specific applications could be overridden by \ref esp32_application_specific_configurations "application-specific board configuration". -\image html "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/_images/esp32-c3-devkitm-1-v1-annotated-photo.png" "Espressif ESP32-C3-DevKitM-1" width=800px +\image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c3/_images/esp32-c3-devkitm-1-v1-annotated-photo.png" "Espressif ESP32-C3-DevKitM-1" width=800px [Back to table of contents](#esp32c3_devkit_toc) diff --git a/boards/esp32s2-devkit/doc.txt b/boards/esp32s2-devkit/doc.txt index 7d6b70187def..18cd5c1840f7 100644 --- a/boards/esp32s2-devkit/doc.txt +++ b/boards/esp32s2-devkit/doc.txt @@ -35,7 +35,7 @@ the following modules: - ESP32-S2-WROOM module (ESP32-S2-Saola-1 board) - ESP32-S2-WROVER-N4R2 module (ESP32-S2-Saola-1R board) -\image html "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/_images/esp32-s2-devkitm-1-v1-annotated-photo.png" "Espressif ESP32-S2-DevKitM-1" width=600px +\image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s2/_images/esp32-s2-devkitm-1-v1-annotated-photo.png" "Espressif ESP32-S2-DevKitM-1" width=600px
Due to the different modules used, the available versions of the @@ -174,9 +174,9 @@ boards, see section \ref esp32_peripherals "Common Peripherals". The following figures show the pinouts as configured by default board definition. -@image html https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/_images/esp32-s2-devkitm-1-v1-pin-layout.png "ESP32-S2-DevKitM-1x Pinout" width=900px -@image html https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/_images/esp32-s2-devkitc-1-v1-pinout.png "ESP32-S2-DevKitC-1x Pinout" width=900px -@image html https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/_images/esp32-s2_saola1-pinout.jpg "ESP32-S2-Saola-1x Pinout" width=900px +@image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s2/_images/esp32-s2-devkitm-1-v1-pin-layout.png" "ESP32-S2-DevKitM-1x Pinout" width=900px +@image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s2/_images/esp32-s2-devkitm-1-v1-pin-layout.png" "ESP32-S2-DevKitC-1x Pinout" width=900px +@image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s2/_images/esp32-s2_saola1-pinout.jpg" "ESP32-S2-Saola-1x Pinout" width=900px The corresponding board schematics can be found: diff --git a/boards/esp32s3-devkit/doc.txt b/boards/esp32s3-devkit/doc.txt index bbcc9db6bd4f..a5d2fe27b207 100644 --- a/boards/esp32s3-devkit/doc.txt +++ b/boards/esp32s3-devkit/doc.txt @@ -32,7 +32,7 @@ the following modules: - ESP32-S3-WROOM-1x module (ESP32-S3-DevKitC-1 board) - ESP32-S3-WROOM-2 module (ESP32-S3-DevKitC-1 board) -\image html "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/_images/ESP32-S3-DevKitC-1_v2-annotated-photo.png" "Espressif ESP32-S3-DevKitM-1" width=600px +\image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/_images/ESP32-S3-DevKitC-1_v2-annotated-photo.png" "Espressif ESP32-S3-DevKitM-1" width=600px
Due to the different modules used, the available versions of the @@ -179,8 +179,8 @@ boards, see section \ref esp32_peripherals "Common Peripherals". The following figures show the pinouts as configured by default board definition. -@image html https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/_images/ESP32-S3_DevKitC-1_pinlayout.jpg "ESP32-S3-DevKitC-1 Pinout" width=900px -@image html https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/_images/ESP32-S3_DevKitM-1_pinlayout.jpg "ESP32-S3-DevKitM-1 Pinout" width=900px +@image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/_images/ESP32-S3_DevKitC-1_pinlayout_v1.1.jpg" "ESP32-S3-DevKitC-1 Pinout" width=900px +@image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/_images/ESP32-S3_DevKitM-1_pinlayout.jpg" "ESP32-S3-DevKitM-1 Pinout" width=900px The corresponding board schematics can be found: diff --git a/boards/esp32s3-usb-otg/doc.txt b/boards/esp32s3-usb-otg/doc.txt index 25d89abda12d..5202e42275ff 100644 --- a/boards/esp32s3-usb-otg/doc.txt +++ b/boards/esp32s3-usb-otg/doc.txt @@ -32,7 +32,7 @@ it is equipped with two USB type A ports: - `USB_DEV` male port that is used to connect the board as a USB device to a host. - `USB_HOST` female port that is used to connect other USB devices to the board. -\image html "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/_images/pic_board_top_lable.png" "Espressif ESP32-S3-USB-OTG" width=600px +\image html "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/_images/pic_board_top_lable.png" "Espressif ESP32-S3-USB-OTG" width=600px @note RIOT-OS does only support the `USB_DEV` port, that is the board can only be used as USB device. diff --git a/boards/nrf6310/Kconfig b/boards/nrf6310/Kconfig deleted file mode 100644 index 53d1696153ba..000000000000 --- a/boards/nrf6310/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2020 HAW Hamburg -# -# 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. - -config BOARD - default "nrf6310" if BOARD_NRF6310 - -config BOARD_NRF6310 - bool - default y - select BOARD_COMMON_NRF51 - select CPU_MODEL_NRF51X22XXAA - -source "$(RIOTBOARD)/common/nrf51/Kconfig" diff --git a/boards/nrf6310/Makefile b/boards/nrf6310/Makefile deleted file mode 100644 index f8fcbb53a065..000000000000 --- a/boards/nrf6310/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -MODULE = board - -include $(RIOTBASE)/Makefile.base diff --git a/boards/nrf6310/Makefile.dep b/boards/nrf6310/Makefile.dep deleted file mode 100644 index babcd96228ac..000000000000 --- a/boards/nrf6310/Makefile.dep +++ /dev/null @@ -1 +0,0 @@ -include $(RIOTBOARD)/common/nrf51/Makefile.dep diff --git a/boards/nrf6310/Makefile.features b/boards/nrf6310/Makefile.features deleted file mode 100644 index 46b201fafbf4..000000000000 --- a/boards/nrf6310/Makefile.features +++ /dev/null @@ -1,8 +0,0 @@ -CPU_MODEL = nrf51x22xxaa - -# Put defined MCU peripherals here (in alphabetical order) -FEATURES_PROVIDED += periph_spi -FEATURES_PROVIDED += periph_uart - -# include common nrf51 based boards features -include $(RIOTBOARD)/common/nrf51/Makefile.features diff --git a/boards/nrf6310/Makefile.include b/boards/nrf6310/Makefile.include deleted file mode 100644 index 35c541b38c23..000000000000 --- a/boards/nrf6310/Makefile.include +++ /dev/null @@ -1,12 +0,0 @@ -# set default port depending on operating system -PORT_LINUX ?= /dev/ttyUSB0 -PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.SLAB_USBtoUART*))) - -# use jlink to program this board -PROGRAMMER ?= jlink - -# set required debug adapter for openocd if it's used -OPENOCD_DEBUG_ADAPTER = jlink - -# include nrf51 boards common configuration -include $(RIOTBOARD)/common/nrf51/Makefile.include diff --git a/boards/nrf6310/board.c b/boards/nrf6310/board.c deleted file mode 100644 index b909139fef21..000000000000 --- a/boards/nrf6310/board.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * 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 boards_nrf6310 - * @{ - * - * @file board.c - * @brief Board specific implementations for the NRF6310 board - * - * @author Christian Kühling - * @author Timo Ziegler - * @author Hauke Petersen - * - * @} - */ - -#include "board.h" -#include "cpu.h" - -void led_init(void) -{ - /* initialize and turn off on-board LEDs */ - NRF_GPIO->DIRSET = LED0_MASK | LED1_MASK | LED2_MASK; - NRF_GPIO->OUTSET = LED0_MASK | LED1_MASK | LED2_MASK; -} diff --git a/boards/nrf6310/doc.txt b/boards/nrf6310/doc.txt deleted file mode 100644 index 856a406d8256..000000000000 --- a/boards/nrf6310/doc.txt +++ /dev/null @@ -1,5 +0,0 @@ -/** -@defgroup boards_nrf6310 NRF6310 (Nordic NRF Hardware Development Kit) -@ingroup boards -@brief Support for the nRF51 boards: nrf6310 or MOMMOSOFT BLE DEVKIT.N - */ diff --git a/boards/nrf6310/include/board.h b/boards/nrf6310/include/board.h deleted file mode 100644 index c02add33edbf..000000000000 --- a/boards/nrf6310/include/board.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * 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 boards_nrf6310 - * @{ - * - * @file - * @brief Board specific definitions for the nRF51 evaluation board nrf6310 - * - * @author Christian Kühling - * @author Timo Ziegler - * @author Frank Holtz - */ - -#ifndef BOARD_H -#define BOARD_H - -#include "cpu.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @name LED pin definitions and handlers - * @{ - */ -#define LED0_PIN GPIO_PIN(0, 8) -#define LED1_PIN GPIO_PIN(0, 9) -#define LED2_PIN GPIO_PIN(0, 10) - -#define LED0_MASK (1 << 8) -#define LED1_MASK (1 << 9) -#define LED2_MASK (1 << 10) - -#define LED0_ON (NRF_GPIO->OUTCLR = LED0_MASK) -#define LED0_OFF (NRF_GPIO->OUTSET = LED0_MASK) -#define LED0_TOGGLE (NRF_GPIO->OUT ^= LED0_MASK) - -#define LED1_ON (NRF_GPIO->OUTCLR = LED1_MASK) -#define LED1_OFF (NRF_GPIO->OUTSET = LED1_MASK) -#define LED1_TOGGLE (NRF_GPIO->OUT ^= LED1_MASK) - -#define LED2_ON (NRF_GPIO->OUTCLR = LED2_MASK) -#define LED2_OFF (NRF_GPIO->OUTSET = LED2_MASK) -#define LED2_TOGGLE (NRF_GPIO->OUT ^= LED2_MASK) -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* BOARD_H */ -/** @} */ diff --git a/boards/nrf6310/include/periph_conf.h b/boards/nrf6310/include/periph_conf.h deleted file mode 100644 index bbe0d27efef4..000000000000 --- a/boards/nrf6310/include/periph_conf.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * 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 boards_nrf6310 - * @{ - * - * @file - * @brief Peripheral MCU configuration for the nRF51 board nrf6310 - * - * @author Christian Kühling - * @author Timo Ziegler - * @author Hauke Petersen - * @author Frank Holtz - */ - -#ifndef PERIPH_CONF_H -#define PERIPH_CONF_H - -#include "periph_cpu.h" -#include "cfg_clock_16_1.h" -#include "cfg_timer_012.h" -#include "cfg_rtt_default.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @name UART configuration - * @{ - */ -static const uart_conf_t uart_config[] = { - { - .dev = NRF_UART0, - .rx_pin = GPIO_PIN(0, 16), - .tx_pin = GPIO_PIN(0, 17), -#ifdef MODULE_PERIPH_UART_HW_FC - .rts_pin = GPIO_PIN(0, 19), - .cts_pin = GPIO_PIN(0, 18), -#endif - .irqn = UART0_IRQn, - }, -}; - -#define UART_NUMOF ARRAY_SIZE(uart_config) -#define UART_0_ISR isr_uart0 -/** @} */ - -/** - * @name SPI configuration - * @{ - */ -static const spi_conf_t spi_config[] = { - { - .dev = NRF_SPI0, - .sclk = 23, - .mosi = 22, - .miso = 20 - }, - { - .dev = NRF_SPI1, - .sclk = 16, - .mosi = 17, - .miso = 18 - } -}; - -#define SPI_NUMOF ARRAY_SIZE(spi_config) -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* PERIPH_CONF_H */ -/** @} */ diff --git a/boards/nucleo-g431rb/Makefile.features b/boards/nucleo-g431rb/Makefile.features index 6e9f0a052efe..9eda9d2d6e3a 100644 --- a/boards/nucleo-g431rb/Makefile.features +++ b/boards/nucleo-g431rb/Makefile.features @@ -2,6 +2,7 @@ CPU = stm32 CPU_MODEL = stm32g431rb # Put defined MCU peripherals here (in alphabetical order) +FEATURES_PROVIDED += periph_can FEATURES_PROVIDED += periph_i2c FEATURES_PROVIDED += periph_pwm FEATURES_PROVIDED += periph_rtc diff --git a/cpu/esp32/periph/can.c b/cpu/esp32/periph/can.c index cdb55201acfc..3a6e9561b9e5 100644 --- a/cpu/esp32/periph/can.c +++ b/cpu/esp32/periph/can.c @@ -240,7 +240,7 @@ static int _esp_can_send(candev_t *candev, const struct can_frame *frame) /* prepare the frame as expected by ESP32 */ twai_hal_frame_t esp_frame = { }; - esp_frame.dlc = frame->can_dlc; + esp_frame.dlc = frame->len; esp_frame.rtr = (frame->can_id & CAN_RTR_FLAG); esp_frame.frame_format = (frame->can_id & CAN_EFF_FLAG); @@ -825,7 +825,7 @@ static void IRAM_ATTR _esp_can_intr_handler(void *arg) } frame.can_id |= esp_frame.rtr ? CAN_RTR_FLAG : 0; frame.can_id |= esp_frame.frame_format ? CAN_EFF_FLAG : 0; - frame.can_dlc = esp_frame.dlc; + frame.len = esp_frame.dlc; /* apply acceptance filters only if they are set */ unsigned f_id = 0; diff --git a/cpu/esp_common/Makefile.include b/cpu/esp_common/Makefile.include index 4b4d3e3de3d4..dfac2235661a 100644 --- a/cpu/esp_common/Makefile.include +++ b/cpu/esp_common/Makefile.include @@ -157,14 +157,16 @@ $(BINDIR)/partitions.csv: $(FLASHFILE) $(Q)printf "phy_init, data, phy, 0xf000, 0x1000\n" >> $@ $(Q)printf "flashpage, data, phy, $(FLASHPAGE_ADDR_START), $(FLASHPAGE_CAP)\n" >> $@ $(Q)printf "factory, app, factory, $(FLASHFILE_POS), " >> $@ - $(Q)ls -l $< | awk '{ print $$5 }' >> $@ + # append size of $(FLASHFILE) + $(Q)wc -c < $< >> $@ else $(BINDIR)/partitions.csv: $(FLASHFILE) $(Q)printf "\n" > $(BINDIR)/partitions.csv $(Q)printf "nvs, data, nvs, 0x9000, 0x6000\n" >> $@ $(Q)printf "phy_init, data, phy, 0xf000, 0x1000\n" >> $@ $(Q)printf "factory, app, factory, $(FLASHFILE_POS), " >> $@ - $(Q)ls -l $< | awk '{ print $$5 }' >> $@ + # append size of $(FLASHFILE) + $(Q)wc -c < $< >> $@ endif $(BINDIR)/partitions.bin: $(PARTITION_TABLE_CSV) diff --git a/cpu/native/Makefile.dep b/cpu/native/Makefile.dep index 0504cdc7f475..a41f94b2d59c 100644 --- a/cpu/native/Makefile.dep +++ b/cpu/native/Makefile.dep @@ -52,3 +52,5 @@ USEMODULE += periph # UART is needed by startup.c USEMODULE += periph_uart + +USEMODULE += fdcan diff --git a/cpu/native/periph/can.c b/cpu/native/periph/can.c index 78ce8ddf9605..aa1565dc3c60 100644 --- a/cpu/native/periph/can.c +++ b/cpu/native/periph/can.c @@ -44,11 +44,11 @@ #include "debug.h" static int _init(candev_t *candev); -static int _send(candev_t *candev, const struct can_frame *frame); +static int _send(candev_t *candev, const can_frame_t *frame); static void _isr(candev_t *candev); static int _set(candev_t *candev, canopt_t opt, void *value, size_t value_len); static int _get(candev_t *candev, canopt_t opt, void *value, size_t max_len); -static int _abort(candev_t *candev, const struct can_frame *frame); +static int _abort(candev_t *candev, const can_frame_t *frame); static int _set_filter(candev_t *candev, const struct can_filter *filter); static int _remove_filter(candev_t *candev, const struct can_filter *filter); static int _power_up(candev_t *candev); @@ -67,7 +67,7 @@ static const candev_driver_t candev_linux_driver = { .remove_filter = _remove_filter, }; -static candev_event_t _can_error_to_can_evt(struct can_frame can_frame_err); +static candev_event_t _can_error_to_can_evt(can_frame_t can_frame_err); static void _callback_can_sigio(int sock, void *arg); can_conf_t candev_conf[CAN_DLL_NUMOF] = { @@ -94,7 +94,7 @@ int can_init(can_t *dev, const can_conf_t *conf) return 0; } -static candev_event_t _can_error_to_can_evt(struct can_frame can_frame_err) +static candev_event_t _can_error_to_can_evt(can_frame_t can_frame_err) { candev_event_t can_evt = CANDEV_EVENT_NOEVENT; can_err_mask_t can_err_type = can_frame_err.can_id & CAN_ERR_MASK; @@ -103,7 +103,7 @@ static candev_event_t _can_error_to_can_evt(struct can_frame can_frame_err) can_evt = CANDEV_EVENT_TX_ERROR; } else if (can_err_type & CAN_ERR_CRTL) { - switch(can_frame_err.data[1]) { + switch (can_frame_err.data[1]) { case CAN_ERR_CRTL_RX_OVERFLOW: can_evt = CANDEV_EVENT_RX_ERROR; break; @@ -168,7 +168,11 @@ static int _init(candev_t *candev) can_err_mask_t err_mask = CAN_ERR_TX_TIMEOUT | CAN_ERR_BUSOFF | CAN_ERR_CRTL; - ret = real_setsockopt(dev->sock, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, + ret = real_setsockopt(dev->sock, SOL_CAN_RAW, +#ifdef MODULE_FDCAN + CAN_RAW_FD_FRAMES | +#endif + CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask)); if (ret < 0) { @@ -210,14 +214,14 @@ static int _init(candev_t *candev) return 0; } -static int _send(candev_t *candev, const struct can_frame *frame) +static int _send(candev_t *candev, const can_frame_t *frame) { int nbytes; can_t *dev = (can_t *)candev; - nbytes = real_write(dev->sock, frame, sizeof(struct can_frame)); + nbytes = real_write(dev->sock, frame, sizeof(can_frame_t)); - if (nbytes < frame->can_dlc) { + if (nbytes < frame->len) { real_printf("CAN write op failed, nbytes=%i\n", nbytes); return -1; } @@ -232,7 +236,7 @@ static int _send(candev_t *candev, const struct can_frame *frame) static void _isr(candev_t *candev) { int nbytes; - struct can_frame rcv_frame; + can_frame_t rcv_frame; can_t *dev = (can_t *)candev; if (dev == NULL) { @@ -240,14 +244,14 @@ static void _isr(candev_t *candev) } DEBUG("candev_native _isr: CAN SIGIO interrupt received, sock = %i\n", dev->sock); - nbytes = real_read(dev->sock, &rcv_frame, sizeof(struct can_frame)); + nbytes = real_read(dev->sock, &rcv_frame, sizeof(can_frame_t)); if (nbytes < 0) { /* SIGIO signal was probably due to an error with the socket */ DEBUG("candev_native _isr: read: error during read\n"); return; } - if (nbytes < (int)sizeof(struct can_frame)) { + if (nbytes < (int)sizeof(can_frame_t)) { DEBUG("candev_native _isr: read: incomplete CAN frame\n"); return; } @@ -544,7 +548,7 @@ static int _remove_filter(candev_t *candev, const struct can_filter *filter) return 0; } -static int _abort(candev_t *candev, const struct can_frame *frame) +static int _abort(candev_t *candev, const can_frame_t *frame) { (void)frame; (void)candev; diff --git a/cpu/nrf52/radio/nrf802154/nrf802154_radio.c b/cpu/nrf52/radio/nrf802154/nrf802154_radio.c index 37fcba3fab87..404a6e676650 100644 --- a/cpu/nrf52/radio/nrf802154/nrf802154_radio.c +++ b/cpu/nrf52/radio/nrf802154/nrf802154_radio.c @@ -119,14 +119,22 @@ static void _power_off(void) static bool _l2filter(uint8_t *mhr) { uint8_t dst_addr[IEEE802154_LONG_ADDRESS_LEN]; + uint8_t src_addr[IEEE802154_LONG_ADDRESS_LEN]; le_uint16_t dst_pan; + le_uint16_t src_pan; uint8_t pan_bcast[] = IEEE802154_PANID_BCAST; - int addr_len = ieee802154_get_dst(mhr, dst_addr, &dst_pan); + int dst_addr_len = ieee802154_get_dst(mhr, dst_addr, &dst_pan); + + int src_addr_len = ieee802154_get_src(mhr, src_addr, &src_pan); if ((mhr[0] & IEEE802154_FCF_TYPE_MASK) == IEEE802154_FCF_TYPE_BEACON) { - if ((memcmp(&nrf802154_pan_id, pan_bcast, 2) == 0)) { - return true; + if (src_addr_len == IEEE802154_SHORT_ADDRESS_LEN || + src_addr_len == IEEE802154_LONG_ADDRESS_LEN){ + if ((memcmp(&nrf802154_pan_id, src_pan.u8, 2) == 0) || + (memcmp(&nrf802154_pan_id, pan_bcast, 2) == 0)) { + return true; + } } } /* filter PAN ID */ @@ -138,11 +146,11 @@ static bool _l2filter(uint8_t *mhr) } /* check destination address */ - if (((addr_len == IEEE802154_SHORT_ADDRESS_LEN) && - (memcmp(nrf802154_short_addr, dst_addr, addr_len) == 0 || - memcmp(ieee802154_addr_bcast, dst_addr, addr_len) == 0)) || - ((addr_len == IEEE802154_LONG_ADDRESS_LEN) && - (memcmp(nrf802154_long_addr, dst_addr, addr_len) == 0))) { + if (((dst_addr_len == IEEE802154_SHORT_ADDRESS_LEN) && + (memcmp(nrf802154_short_addr, dst_addr, dst_addr_len) == 0 || + memcmp(ieee802154_addr_bcast, dst_addr, dst_addr_len) == 0)) || + ((dst_addr_len == IEEE802154_LONG_ADDRESS_LEN) && + (memcmp(nrf802154_long_addr, dst_addr, dst_addr_len) == 0))) { return true; } diff --git a/cpu/sam0_common/periph/eth.c b/cpu/sam0_common/periph/eth.c index f2f54982f5cb..990538004496 100644 --- a/cpu/sam0_common/periph/eth.c +++ b/cpu/sam0_common/periph/eth.c @@ -134,7 +134,7 @@ unsigned sam0_read_phy(uint8_t phy, uint8_t addr) /* Wait for operation completion */ while (!(GMAC->NSR.reg & GMAC_NSR_IDLE)) {} /* return content of shift register */ - return (GMAC->MAN.reg & GMAC_MAN_DATA_Msk); + return GMAC->MAN.reg & GMAC_MAN_DATA_Msk; } void sam0_write_phy(uint8_t phy, uint8_t addr, uint16_t data) @@ -158,8 +158,14 @@ void sam0_eth_poweron(void) /* enable PHY */ gpio_set(sam_gmac_config[0].rst_pin); - _is_sleeping = false; + /* if the PHY is not idle, it's likely broken */ + if (!(GMAC->NSR.reg & GMAC_NSR_IDLE)) { + DEBUG_PUTS("sam0_eth: PHY not IDLE, likely broken."); + return; + } + + _is_sleeping = false; while (MII_BMCR_RESET & sam0_read_phy(0, MII_BMCR)) {} } diff --git a/cpu/sam3/periph/gpio.c b/cpu/sam3/periph/gpio.c index 6253814094b4..b55179cbca0f 100644 --- a/cpu/sam3/periph/gpio.c +++ b/cpu/sam3/periph/gpio.c @@ -22,6 +22,7 @@ * @} */ +#include "bitarithm.h" #include "cpu.h" #include "periph/gpio.h" #include "periph_conf.h" @@ -313,11 +314,11 @@ static inline void isr_handler(Pio *port, int port_num) /* take interrupt flags only from pins which interrupt is enabled */ uint32_t status = (port->PIO_ISR & port->PIO_IMR); - for (int i = 0; i < 32; i++) { - if (status & ((uint32_t)1 << i)) { - int ctx = _ctx(port_num, i); - exti_ctx[ctx].cb(exti_ctx[ctx].arg); - } + while (status) { + uint8_t pin_number; + status = bitarithm_test_and_clear(status, &pin_number); + int ctx = _ctx(port_num, pin_number); + exti_ctx[ctx].cb(exti_ctx[ctx].arg); } cortexm_isr_end(); } diff --git a/cpu/sam3/periph/hwrng.c b/cpu/sam3/periph/hwrng.c index 0f2ee7ae2b73..df65d80cef3c 100644 --- a/cpu/sam3/periph/hwrng.c +++ b/cpu/sam3/periph/hwrng.c @@ -39,9 +39,9 @@ void hwrng_read(void *buf, unsigned int num) uint8_t *b = (uint8_t *)buf; /* enable clock signal for TRNG module */ - PMC->PMC_PCER1 |= PMC_PCER1_PID41; + PMC->PMC_PCER1 = PMC_PCER1_PID41; /* enable the generation of random numbers */ - TRNG->TRNG_CR |= (KEY | TRNG_CR_ENABLE); + TRNG->TRNG_CR = (KEY | TRNG_CR_ENABLE); while (count < num) { /* wait until new value is generated -> takes up to 84 cycles */ @@ -56,7 +56,7 @@ void hwrng_read(void *buf, unsigned int num) } /* disable the generation of random numbers */ - TRNG->TRNG_CR &= ~(KEY | TRNG_CR_ENABLE); + TRNG->TRNG_CR = KEY; /* disable clock signal for TRNG module */ - PMC->PMC_PCER1 &= ~(PMC_PCER1_PID41); + PMC->PMC_PCDR1 = PMC_PCER1_PID41; } diff --git a/cpu/sam3/periph/rtt.c b/cpu/sam3/periph/rtt.c index 2da87e712c3a..7cefa4f210f3 100644 --- a/cpu/sam3/periph/rtt.c +++ b/cpu/sam3/periph/rtt.c @@ -88,12 +88,12 @@ void rtt_clear_alarm(void) void rtt_poweron(void) { - PMC->PMC_PCER0 |= (1 << ID_RTT); + PMC->PMC_PCER0 = (1 << ID_RTT); } void rtt_poweroff(void) { - PMC->PMC_PCER0 &= ~(1 << ID_RTT); + PMC->PMC_PCDR0 = (1 << ID_RTT); } void isr_rtt(void) diff --git a/cpu/sam3/periph/spi.c b/cpu/sam3/periph/spi.c index e542519dabbd..f7c56afd8003 100644 --- a/cpu/sam3/periph/spi.c +++ b/cpu/sam3/periph/spi.c @@ -71,7 +71,7 @@ void spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk) /* lock bus */ mutex_lock(&locks[bus]); /* enable SPI device clock */ - PMC->PMC_PCER0 |= (1 << spi_config[bus].id); + PMC->PMC_PCER0 = (1 << spi_config[bus].id); /* set mode and speed */ dev(bus)->SPI_CSR[0] = (SPI_CSR_SCBR(CLOCK_CORECLOCK / clk) | mode); dev(bus)->SPI_MR = (SPI_MR_MSTR | SPI_MR_MODFDIS); @@ -82,7 +82,7 @@ void spi_release(spi_t bus) { /* disable device and turn off clock signal */ dev(bus)->SPI_CR = 0; - PMC->PMC_PCER0 &= ~(1 << spi_config[bus].id); + PMC->PMC_PCDR0 = (1 << spi_config[bus].id); /* release device lock */ mutex_unlock(&locks[bus]); } diff --git a/cpu/sam3/periph/uart.c b/cpu/sam3/periph/uart.c index 206e457a429a..8cb8723ed068 100644 --- a/cpu/sam3/periph/uart.c +++ b/cpu/sam3/periph/uart.c @@ -89,12 +89,12 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len) void uart_poweron(uart_t uart) { - PMC->PMC_PCER0 |= (1 << uart_config[uart].pmc_id); + PMC->PMC_PCER0 = (1 << uart_config[uart].pmc_id); } void uart_poweroff(uart_t uart) { - PMC->PMC_PCER0 &= ~(1 << uart_config[uart].pmc_id); + PMC->PMC_PCDR0 = (1 << uart_config[uart].pmc_id); } static inline void isr_handler(int num) diff --git a/cpu/samd5x/periph/can.c b/cpu/samd5x/periph/can.c index 5d63dd6b219a..723cf452837d 100644 --- a/cpu/samd5x/periph/can.c +++ b/cpu/samd5x/periph/can.c @@ -20,9 +20,10 @@ #include #include +#include "can/device.h" #include "periph/can.h" #include "periph/gpio.h" -#include "can/device.h" +#include "pm_layered.h" #define ENABLE_DEBUG 0 #include "debug.h" @@ -107,6 +108,30 @@ static const struct can_bittiming_const bittiming_const = { static int _power_on(can_t *dev) { + /* CAN required CLK_CANx_APB and GCLK_CANx to be running and will not + * request any clock by itself. We can ensure both clocks to be running + * by preventing the MCU from entering IDLE state. + * + * The SAMD5x/SAME5x Family Data Sheet says in Section + * "39.6.9 Sleep Mode Operation" says: + * + * > The CAN can be configured to operate in any idle sleep mode. The CAN + * > cannot operate in Standby sleep mode. + * > + * > [...] + * > + * > To leave low power mode, CLK_CANx_APB and GCLK_CANx must be active + * > before writing CCCR.CSR to '0'. The CAN will acknowledge this by + * > resetting CCCR.CSA = 0. Afterwards, the application can restart CAN + * > communication by resetting bit CCCR.INIT. + * + * tl;dr: At most SAM0_PM_IDLE is allowed while not shutting down the CAN + * controller, but even that will pause communication (including RX). + */ + if (IS_USED(MODULE_PM_LAYERED)) { + pm_block(SAM0_PM_IDLE); + } + if (dev->conf->can == CAN0) { DEBUG_PUTS("CAN0 controller is used"); MCLK->AHBMASK.reg |= MCLK_AHBMASK_CAN0; @@ -125,6 +150,10 @@ static int _power_on(can_t *dev) static int _power_off(can_t *dev) { + if (IS_USED(MODULE_PM_LAYERED)) { + pm_unblock(SAM0_PM_IDLE); + } + if (dev->conf->can == CAN0) { DEBUG_PUTS("CAN0 controller is used"); MCLK->AHBMASK.reg &= ~MCLK_AHBMASK_CAN0; diff --git a/cpu/stm32/Makefile.dep b/cpu/stm32/Makefile.dep index 4d032b364568..946f666ea227 100644 --- a/cpu/stm32/Makefile.dep +++ b/cpu/stm32/Makefile.dep @@ -85,6 +85,12 @@ ifneq (,$(filter periph_adc,$(FEATURES_USED))) endif endif +ifneq (,$(filter periph_can,$(FEATURES_USED))) + ifneq (,$(filter g4,$(CPU_FAM))) + USEMODULE += fdcan + endif +endif + ifneq (,$(filter periph_vbat,$(USEMODULE))) FEATURES_REQUIRED += periph_adc endif diff --git a/cpu/stm32/include/can_params.h b/cpu/stm32/include/can_params.h index 2a693beeb0fd..bbf5ab485b55 100644 --- a/cpu/stm32/include/can_params.h +++ b/cpu/stm32/include/can_params.h @@ -30,7 +30,15 @@ extern "C" { /** Default STM32 CAN devices config */ static const can_conf_t candev_conf[] = { { -#if defined(CPU_FAM_STM32F0) +#if defined(CPU_FAM_STM32G4) + .can = FDCAN1, + .rcc_mask = RCC_APB1ENR1_FDCANEN, + .rx_pin = GPIO_PIN(PORT_A, 11), + .tx_pin = GPIO_PIN(PORT_A, 12), + .af = GPIO_AF9, + .it0_irqn = FDCAN1_IT0_IRQn, + .it1_irqn = FDCAN1_IT1_IRQn, +#elif defined(CPU_FAM_STM32F0) .can = CAN, .rcc_mask = RCC_APB1ENR_CANEN, .rx_pin = GPIO_PIN(PORT_A, 11), diff --git a/cpu/stm32/include/fdcandev_stm32.h b/cpu/stm32/include/fdcandev_stm32.h new file mode 100644 index 000000000000..6473d20418b3 --- /dev/null +++ b/cpu/stm32/include/fdcandev_stm32.h @@ -0,0 +1,427 @@ +/* + * Copyright (C) 2024 COGIP Robotics association + * + * 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_stm32 + * @ingroup drivers_can + * @defgroup fdcandev_stm32 STM32 FDCAN controller + * @brief STM32 FDCAN controller driver + * + * The STM32Gx microcontroller can have an integrated FDCAN controller + * + * This driver has been tested with a STM32G4 MCU + * but should work on others. + * + * The default bitrates are set to 1 Mbps for headers and 4 Mbps for data. + * The default sample point is set to 87.5%. + * @{ + * + * @file + * @brief FDCAN specific definitions + * + * @author Gilles DOFFE + * @} + */ + +#ifndef FDCANDEV_STM32_H +#define FDCANDEV_STM32_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "can/candev.h" + +/** Number of channels in the device (up to 3) */ +#if defined(FDCAN3) +#define FDCANDEV_STM32_CHAN_NUMOF 3 +#elif defined(FDCAN2) +#define FDCANDEV_STM32_CHAN_NUMOF 2 +#elif defined(FDCAN1) || DOXYGEN +#define FDCANDEV_STM32_CHAN_NUMOF 1 +#else +#error "FDCAN STM32: CPU not supported" +#endif + +/** + * @name ISR functions + * @{ + */ +#define ISR_FDCAN1_IT0 isr_fdcan1_it0 /**< Interrupt line 0 */ +#define ISR_FDCAN1_IT1 isr_fdcan1_it1 /**< Interrupt line 1 */ +/** @} */ + +/** + * @name Filters + * @{ + */ +#define FDCAN_STM32_NB_STD_FILTER 28U /**< Number of standard filters */ +#define FDCAN_STM32_NB_EXT_FILTER 8U /**< Number of extended filters */ +#define FDCAN_STM32_NB_FILTER \ + (FDCAN_STM32_NB_STD_FILTER + FDCAN_STM32_NB_EXT_FILTER) /**< Total number of filters */ +/** @} */ + +/** + * @name Birates + * @{ + */ +#ifndef FDCANDEV_STM32_DEFAULT_BITRATE +#define FDCANDEV_STM32_DEFAULT_BITRATE 500000U + /**< Default bitrate for headers and non-FDCAN messages */ +#endif +#ifndef FDCANDEV_STM32_DEFAULT_FD_DATA_BITRATE +#define FDCANDEV_STM32_DEFAULT_FD_DATA_BITRATE 1000000U + /**< Default FDCAN data bitrate */ +#endif +/** @} */ + +#ifndef FDCANDEV_STM32_DEFAULT_SPT +/** Default sampling-point */ +#define FDCANDEV_STM32_DEFAULT_SPT 875 +#endif + +/** bxCAN device configuration */ +typedef struct { + FDCAN_GlobalTypeDef *can; /**< CAN device */ + uint32_t rcc_mask; /**< RCC mask to enable clock */ + gpio_t rx_pin; /**< RX pin */ + gpio_t tx_pin; /**< TX pin */ + gpio_af_t af; /**< Alternate pin function to use */ + bool en_deep_sleep_wake_up; /**< Enable deep-sleep wake-up interrupt */ + uint8_t it0_irqn; /**< Interrupt line 0 IRQ channel */ + uint8_t it1_irqn; /**< Interrupt line 1 IRQ channel */ + uint8_t ttcm : 1; /**< Time triggered communication mode */ + uint8_t abom : 1; /**< Automatic bus-off management */ + uint8_t awum : 1; /**< Automatic wakeup mode */ + uint8_t nart : 1; /**< No automatic retransmission */ + uint8_t rflm : 1; /**< Receive FIFO locked mode */ + uint8_t txfp : 1; /**< Transmit FIFO priority */ + uint8_t lbkm : 1; /**< Loopback mode */ + uint8_t silm : 1; /**< Silent mode */ +} can_conf_t; +/** can_conf_t is re-defined */ +#define HAVE_CAN_CONF_T + +/** + * @name STM32 mailboxes + * @{ + */ +#define FDCAN_STM32_TX_MAILBOXES 3 + /**< Number of frame the driver can transmit simultaneously */ +#define FDCAN_STM32_RX_MAILBOXES (FDCANDEV_STM32_CHAN_NUMOF * 6) + /**< Maximum number of frame the driver can receive simultaneously. + There are 3 buffers per FIFO and 2 FIFO per channel. */ +/** @} */ + +/** FDCAN candev descriptor */ +typedef struct can can_t; +/** can_t is re-defined */ +#define HAVE_CAN_T + +#define FDCAN_SRAM_MESSAGE_RAM_SIZE 0x350 /**< FDCAN SRAM message size */ + +/** + * @name Message RAM addresses - 32 bits aligned + * @{ + */ +#define FDCAN_SRAM_FLESA 0x1CU /**< Filter List Extended Start Address */ +#define FDCAN_SRAM_F0SA 0x2CU /**< Rx FIFO0 Start Address */ +#define FDCAN_SRAM_F1SA 0x62U /**< Rx FIFO1 Start Address */ +#define FDCAN_SRAM_EFSA 0x98U /**< Event FIFO Start Address */ +#define FDCAN_SRAM_TBSA 0x9EU /**< Tx Buffer Start Address */ +/** @} */ + +/** + * @name Standard filter bit definition + * @{ + */ +#define FDCAN_SRAM_FLS_SFID1_Pos (16U) + /**< Standard filter ID 1 position */ +#define FDCAN_SRAM_FLS_SFID1_Msk (0x7FFU << FDCAN_SRAM_FLS_SFID1_Pos) + /**< Standard filter ID 1 mask */ +#define FDCAN_SRAM_FLS_SFID1 FDCAN_SRAM_FLS_SFID1_Msk + /**< Standard filter ID 1 */ +#define FDCAN_SRAM_FLS_SFID2_Msk (0x7FFU) + /**< Standard filter ID 2 mask */ +#define FDCAN_SRAM_FLS_SFID2 FDCAN_SRAM_FLS_SFID2_Msk + /**< Standard filter ID 2 */ +#define FDCAN_SRAM_FLS_SFT_Pos (30U) + /**< Standard filter type position */ +#define FDCAN_SRAM_FLS_SFT_Msk (0x3U << FDCAN_SRAM_FLS_SFT_Pos) + /**< Standard filter type mask */ +#define FDCAN_SRAM_FLS_SFT FDCAN_SRAM_FLS_SFT_Msk + /**< Standard filter type */ +#define FDCAN_SRAM_FLS_SFEC_Pos (27U) + /**< Standard filter element configuration position */ +#define FDCAN_SRAM_FLS_SFEC_Msk (0x7U << FDCAN_SRAM_FLS_SFEC_Pos) + /**< Standard filter element configuration mask */ +#define FDCAN_SRAM_FLS_SFEC FDCAN_SRAM_FLS_SFEC_Msk + /**< Standard filter element configuration */ +/** @} */ + +/** + * @name Standard filter configuration + * @{ + */ +#define FDCAN_SRAM_FLS_FILTER_SIZE 1U + /**< Standard filter size */ +#define FDCAN_SRAM_FLS_SFT_DISABLED (0x3U << FDCAN_SRAM_FLS_SFT_Pos) + /**< Filter element disabled */ +#define FDCAN_SRAM_FLS_SFT_CLASSIC (0x2U << FDCAN_SRAM_FLS_SFT_Pos) + /**< Classic filter */ +#define FDCAN_SRAM_FLS_SFEC_DISABLED (0x0U << FDCAN_SRAM_FLS_SFEC_Pos) + /**< Filter element disabled */ +#define FDCAN_SRAM_FLS_SFEC_FIFO0 (0x1U << FDCAN_SRAM_FLS_SFEC_Pos) + /**< Use FIFO0 if filter matches */ +#define FDCAN_SRAM_FLS_SFEC_FIFO1 (0x2U << FDCAN_SRAM_FLS_SFEC_Pos) + /**< Use FIFO1 if filter matches*/ +/** @} */ + +/** + * @name Extended filter bit definition + * @{ + */ +#define FDCAN_SRAM_FLE_F0_EFID1_Msk 0x1FFFFFFFU + /**< Extended filter ID 1 mask */ +#define FDCAN_SRAM_FLE_F0_EFID1 FDCAN_SRAM_FLE_F0_EFID1_Msk + /**< Extended filter ID 1 */ +#define FDCAN_SRAM_FLE_F1_EFID2_Msk 0x1FFFFFFFU + /**< Extended filter ID 2 mask */ +#define FDCAN_SRAM_FLE_F1_EFID2 FDCAN_SRAM_FLE_F1_EFID2_Msk + /**< Extended filter ID 2 */ +#define FDCAN_SRAM_FLE_F1_EFT_Pos 30U + /**< Extended filter type position */ +#define FDCAN_SRAM_FLE_F1_EFT_Msk (0x3U << FDCAN_SRAM_FLE_F1_EFT_Pos) + /**< Extended filter type mask */ +#define FDCAN_SRAM_FLE_F1_EFT FDCAN_SRAM_FLE_F1_EFT_Msk + /**< Extended filter type */ +#define FDCAN_SRAM_FLE_F0_EFEC_Pos 29U + /**< Extended filter element configuration position */ +#define FDCAN_SRAM_FLE_F0_EFEC_Msk (0x7U << FDCAN_SRAM_FLE_F0_EFEC_Pos) + /**< Extended filter element configuration mask */ +#define FDCAN_SRAM_FLE_F0_EFEC FDCAN_SRAM_FLE_F0_EFEC_Msk + /**< Extended filter element configuration */ +/** @} */ + +/** + * @name Extended filter configuration + * @{ + */ +#define FDCAN_SRAM_FLE_FILTER_SIZE 2U + /**< Extended filter size */ +#define FDCAN_SRAM_FLE_F1_EFT_CLASSIC (0x2U << FDCAN_SRAM_FLE_F1_EFT_Pos) + /**< Classic filter */ +#define FDCAN_SRAM_FLE_F0_EFEC_DISABLED (0x0U) + /**< Disabled filter */ +#define FDCAN_SRAM_FLE_F0_EFEC_FIFO0 (0x1U << FDCAN_SRAM_FLE_F0_EFEC_Pos) + /**< Use FIFO0 if filter matches */ +#define FDCAN_SRAM_FLE_F0_EFEC_FIFO1 (0x2U << FDCAN_SRAM_FLE_F0_EFEC_Pos) + /**< Use FIFI1 if filter matches */ +/** @} */ + +/** + * @name Tx Buffer bits definition + * @{ + */ +#define FDCAN_SRAM_TXBUFFER_T0_ESI_Pos 31U + /**< Error State Indicator position */ +#define FDCAN_SRAM_TXBUFFER_T0_ESI_Msk (0x1U << FDCAN_SRAM_TXBUFFER_T0_ESI_Pos) + /**< Error State Indicator mask */ +#define FDCAN_SRAM_TXBUFFER_T0_ESI FDCAN_SRAM_TXBUFFER_T0_ESI_Msk + /**< Error State Indicator */ +#define FDCAN_SRAM_TXBUFFER_T0_XTD_Pos 30U + /**< Extended Identifier position */ +#define FDCAN_SRAM_TXBUFFER_T0_XTD_Msk (0x1U << FDCAN_SRAM_TXBUFFER_T0_XTD_Pos) + /**< Extended Identifier mask */ +#define FDCAN_SRAM_TXBUFFER_T0_XTD FDCAN_SRAM_TXBUFFER_T0_XTD_Msk + /**< Extended Identifier */ +#define FDCAN_SRAM_TXBUFFER_T0_RTR_Pos 29U + /**< Remote transmission request position*/ +#define FDCAN_SRAM_TXBUFFER_T0_RTR_Msk (0x1U << FDCAN_SRAM_TXBUFFER_T0_RTR_Pos) + /**< Remote transmission request mask */ +#define FDCAN_SRAM_TXBUFFER_T0_RTR FDCAN_SRAM_TXBUFFER_T0_RTR_Msk + /**< Remote transmission request */ +#define FDCAN_SRAM_TXBUFFER_T0_ID_Pos 18U + /**< Standard Identifier position */ +#define FDCAN_SRAM_TXBUFFER_T1_EFC_Pos 23U + /**< Event FIFO Control position */ +#define FDCAN_SRAM_TXBUFFER_T1_EFC_Msk (0x1U << FDCAN_SRAM_TXBUFFER_T1_EFC_Pos) + /**< Event FIFO Control mask */ +#define FDCAN_SRAM_TXBUFFER_T1_EFC FDCAN_SRAM_TXBUFFER_T1_EFC_Msk + /**< Event FIFO Control */ +#define FDCAN_SRAM_TXBUFFER_T1_FDF_Pos 21U + /**< FD Format position */ +#define FDCAN_SRAM_TXBUFFER_T1_FDF_Msk (0x1U << FDCAN_SRAM_TXBUFFER_T1_FDF_Pos) + /**< FD Format mask */ +#define FDCAN_SRAM_TXBUFFER_T1_FDF FDCAN_SRAM_TXBUFFER_T1_FDF_Msk + /**< FD Format */ +#define FDCAN_SRAM_TXBUFFER_T1_BRS_Pos 20U + /**< Bit Rate Switching position */ +#define FDCAN_SRAM_TXBUFFER_T1_BRS_Msk (0x1U << FDCAN_SRAM_TXBUFFER_T1_BRS_Pos) + /**< Bit Rate Switching mask */ +#define FDCAN_SRAM_TXBUFFER_T1_BRS FDCAN_SRAM_TXBUFFER_T1_BRS_Msk + /**< Bit Rate Switching */ +#define FDCAN_SRAM_TXBUFFER_T1_DLC_Pos 16U + /**< Data Length Code position */ +#define FDCAN_SRAM_TXBUFFER_T1_DLC_Msk (0xFU << FDCAN_SRAM_TXBUFFER_T1_DLC_Pos) + /**< Data Length Code mask */ +#define FDCAN_SRAM_TXBUFFER_T1_DLC FDCAN_SRAM_TXBUFFER_T1_DLC_Msk + /**< Data Length Code */ +/** @} */ + +/** + * @name Tx buffers configuration + * @{ + */ +#define FDCAN_SRAM_TXBUFFER_SIZE 18U + /**< Tx buffer size */ +#define FDCAN_SRAM_TXBUFFER_T0_ESI_PASSIVE_FLAG (0x0U << FDCAN_SRAM_TXBUFFER_T0_ESI_Pos) + /**< ESI bit in CAN FD format depends only on error passive flag */ +#define FDCAN_SRAM_TXBUFFER_T0_ESI_RECESSIVE (0x1U << FDCAN_SRAM_TXBUFFER_T0_ESI_Pos) + /**< ESI bit in CAN FD format transmitted recessive */ +#define FDCAN_SRAM_TXBUFFER_T1_EFC_DISABLE (0x0U << FDCAN_SRAM_TXBUFFER_T1_EFC_Pos) + /**< Do not store Tx events */ +#define FDCAN_SRAM_TXBUFFER_T1_EFC_STORE_EVENTS (0x1U << FDCAN_SRAM_TXBUFFER_T1_EFC_Pos) + /**< Store Tx events */ +#define FDCAN_SRAM_TXBUFFER_T1_FDF_CLASSIC (0x0U << FDCAN_SRAM_TXBUFFER_T1_FDF_Pos) + /**< Classic CAN format */ +#define FDCAN_SRAM_TXBUFFER_T1_FDF_FD (0x1U << FDCAN_SRAM_TXBUFFER_T1_FDF_Pos) + /**< CAN FD format */ +#define FDCAN_SRAM_TXBUFFER_T1_BRS_OFF (0x0U << FDCAN_SRAM_TXBUFFER_T1_BRS_Pos) + /**< Disable CAN FD bit rate switching */ +#define FDCAN_SRAM_TXBUFFER_T1_BRS_ON (0x1U << FDCAN_SRAM_TXBUFFER_T1_BRS_Pos) + /**< Enable CAN FD bit rate switching */ +/** @} */ + +/** + * @name Rx Buffer bits definition + * @{ + */ +#define FDCAN_SRAM_RXFIFO_R0_ESI_Pos 31U + /**< Error State Indicator position */ +#define FDCAN_SRAM_RXFIFO_R0_ESI_Msk (0x1U << FDCAN_SRAM_RXFIFO_R0_ESI_Pos) + /**< Error State Indicator mask */ +#define FDCAN_SRAM_RXFIFO_R0_ESI FDCAN_SRAM_RXFIFO_R0_ESI_Msk + /**< Error State Indicator */ +#define FDCAN_SRAM_RXFIFO_R0_XTD_Pos 30U + /**< Extended Identifier position */ +#define FDCAN_SRAM_RXFIFO_R0_XTD_Msk (0x1U << FDCAN_SRAM_RXFIFO_R0_XTD_Pos) + /**< Extended Identifier mask */ +#define FDCAN_SRAM_RXFIFO_R0_XTD FDCAN_SRAM_RXFIFO_R0_XTD_Msk + /**< Extended Identifier */ +#define FDCAN_SRAM_RXFIFO_R0_RTR_Pos 29U + /**< Remote transmission request position*/ +#define FDCAN_SRAM_RXFIFO_R0_RTR_Msk (0x1U << FDCAN_SRAM_RXFIFO_R0_RTR_Pos) + /**< Remote transmission request mask */ +#define FDCAN_SRAM_RXFIFO_R0_RTR FDCAN_SRAM_RXFIFO_R0_RTR_Msk + /**< Remote transmission request */ +#define FDCAN_SRAM_RXFIFO_R0_ID_Pos 18U + /**< Standard Identifier position */ +#define FDCAN_SRAM_RXFIFO_R0_ID_Msk 0x1FFFFFFFU + /**< Identifier mask */ +#define FDCAN_SRAM_RXFIFO_R0_ID FDCAN_SRAM_RXFIFO_R0_ID_Msk + /**< Identifier */ +#define FDCAN_SRAM_RXFIFO_R1_EFC_Pos 23U + /**< Event FIFO Control position */ +#define FDCAN_SRAM_RXFIFO_R1_EFC_Msk (0x1U << FDCAN_SRAM_RXFIFO_R1_EFC_Pos) + /**< Event FIFO Control mask */ +#define FDCAN_SRAM_RXFIFO_R1_EFC FDCAN_SRAM_RXFIFO_R1_EFC_Msk + /**< Event FIFO Control */ +#define FDCAN_SRAM_RXFIFO_R1_FDF_Pos 21U + /**< FD Format position */ +#define FDCAN_SRAM_RXFIFO_R1_FDF_Msk (0x1U << FDCAN_SRAM_RXFIFO_R1_FDF_Pos) + /**< FD Format mask */ +#define FDCAN_SRAM_RXFIFO_R1_FDF FDCAN_SRAM_RXFIFO_R1_FDF_Msk + /**< FD Format */ +#define FDCAN_SRAM_RXFIFO_R1_BRS_Pos 20U + /**< Bit Rate Switching position */ +#define FDCAN_SRAM_RXFIFO_R1_BRS_Msk (0x1U << FDCAN_SRAM_RXFIFO_R1_BRS_Pos) + /**< Bit Rate Switching mask */ +#define FDCAN_SRAM_RXFIFO_R1_BRS FDCAN_SRAM_RXFIFO_R1_BRS_Msk + /**< Bit Rate Switching */ +#define FDCAN_SRAM_RXFIFO_R1_DLC_Pos 16U + /**< Data Length Code position */ +#define FDCAN_SRAM_RXFIFO_R1_DLC_Msk (0xFU << FDCAN_SRAM_RXFIFO_R1_DLC_Pos) + /**< Data Length Code mask */ +#define FDCAN_SRAM_RXFIFO_R1_DLC FDCAN_SRAM_RXFIFO_R1_DLC_Msk + /**< Data Length Code */ +/** @} */ + +/** + * @name Rx buffers configuration + * @{ + */ +#define FDCAN_SRAM_RXFIFO_SIZE 54U + /**< Rx FIFO size */ +#define FDCAN_SRAM_RXFIFO_ELEMENT_SIZE 18U + /**< Rx FIFO element size */ +#define FDCAN_SRAM_RXFIFO_R0_ESI_PASSIVE_FLAG (0x0U << FDCAN_SRAM_RXFIFO_R0_ESI_Pos) + /**< ESI bit in CAN FD format depends only on error passive flag */ +#define FDCAN_SRAM_RXFIFO_R0_ESI_RECESSIVE (0x1U << FDCAN_SRAM_RXFIFO_R0_ESI_Pos) + /**< ESI bit in CAN FD format transmitted recessive */ +#define FDCAN_SRAM_RXFIFO_R1_EFC_DISABLE (0x0U << FDCAN_SRAM_RXFIFO_R1_EFC_Pos) + /**< Do not store Rx events */ +#define FDCAN_SRAM_RXFIFO_R1_EFC_STORE_EVENTS (0x1U << FDCAN_SRAM_RXFIFO_R1_EFC_Pos) + /**< Store Rx events */ +#define FDCAN_SRAM_RXFIFO_R1_FDF_CLASSIC (0x0U << FDCAN_SRAM_RXFIFO_R1_FDF_Pos) + /**< Classic CAN format */ +#define FDCAN_SRAM_RXFIFO_R1_FDF_FD (0x1U << FDCAN_SRAM_RXFIFO_R1_FDF_Pos) + /**< CAN FD format */ +#define FDCAN_SRAM_RXFIFO_R1_BRS_OFF (0x0U << FDCAN_SRAM_RXFIFO_R1_BRS_Pos) + /**< CAN FD bit rate switching enabled */ +#define FDCAN_SRAM_RXFIFO_R1_BRS_ON (0x1U << FDCAN_SRAM_RXFIFO_R1_BRS_Pos) + /**< CAN FD bit rate switching disabled */ +/** @} */ + +/** This structure holds anything related to the receive part */ +typedef struct candev_stm32_rx_mailbox { + can_frame_t frame[FDCAN_STM32_RX_MAILBOXES]; + /**< Receive FIFO */ + int write_idx; + /**< Write index in the receive FIFO */ + int read_idx; + /**< Read index in the receive FIFO*/ + int is_full; + /**< Flag set when the FIFO is full */ +} candev_stm32_rx_mailbox_t; + +/** Internal interrupt flags */ +typedef struct candev_stm32_isr { + int isr_tx : 3; /**< Tx mailboxes interrupt */ + int isr_rx : 2; /**< Rx FIFO interrupt */ + int isr_wkup : 1; /**< Wake up interrupt */ +} candev_stm32_isr_t; + +/** STM32 CAN device descriptor */ +struct can { + candev_t candev; /**< Common candev struct */ + const can_conf_t *conf; /**< Configuration */ + gpio_t rx_pin; /**< RX pin */ + gpio_t tx_pin; /**< TX pin */ + gpio_af_t af; /**< Alternate pin function to use */ + const can_frame_t + *tx_mailbox[FDCAN_STM32_TX_MAILBOXES]; /**< Tx mailboxes*/ + candev_stm32_rx_mailbox_t rx_mailbox; /**< Rx mailboxes */ + candev_stm32_isr_t isr_flags; /**< ISR flags */ +}; + +/** + * @brief Set the pins of an stm32 CAN device + * + * @param[in,out] dev the device to set pins + * @param[in] tx_pin tx pin + * @param[in] rx_pin rx pin + * @param[in] af alternate function + */ +void candev_stm32_set_pins(can_t *dev, gpio_t tx_pin, gpio_t rx_pin, + gpio_af_t af); +#ifdef __cplusplus +} +#endif + +#endif /* FDCANDEV_STM32_H */ diff --git a/cpu/stm32/include/periph_cpu.h b/cpu/stm32/include/periph_cpu.h index 088a44b04671..0207019da87a 100644 --- a/cpu/stm32/include/periph_cpu.h +++ b/cpu/stm32/include/periph_cpu.h @@ -81,8 +81,12 @@ #include "periph/cpu_wdt.h" #ifdef MODULE_PERIPH_CAN +#ifdef MODULE_FDCAN +#include "fdcandev_stm32.h" +#else #include "candev_stm32.h" #endif +#endif #ifdef __cplusplus extern "C" { diff --git a/cpu/stm32/periph/Makefile b/cpu/stm32/periph/Makefile index 7c4b73deb79f..595adb4e068c 100644 --- a/cpu/stm32/periph/Makefile +++ b/cpu/stm32/periph/Makefile @@ -69,4 +69,12 @@ ifneq (,$(filter periph_wdt,$(USEMODULE))) since values can deviate up to 50% from reference) endif +ifneq (,$(filter periph_can,$(FEATURES_USED))) + ifneq (,$(filter g4,$(CPU_FAM))) + SRC += fdcan.c + else + SRC += classiccan.c + endif +endif + include $(RIOTMAKE)/periph.mk diff --git a/cpu/stm32/periph/can.c b/cpu/stm32/periph/classiccan.c similarity index 99% rename from cpu/stm32/periph/can.c rename to cpu/stm32/periph/classiccan.c index 73dbfad93ff5..ca4e2943b921 100644 --- a/cpu/stm32/periph/can.c +++ b/cpu/stm32/periph/classiccan.c @@ -412,14 +412,14 @@ static int _send(candev_t *candev, const struct can_frame *frame) else { can->sTxMailBox[mailbox].TIR = (frame->can_id & CAN_SFF_MASK) << CAN_TIxR_SFF_SHIFT; } - can->sTxMailBox[mailbox].TDTR = frame->can_dlc & CAN_TDT0R_DLC; + can->sTxMailBox[mailbox].TDTR = frame->len & CAN_TDT0R_DLC; can->sTxMailBox[mailbox].TDLR = 0; can->sTxMailBox[mailbox].TDHR = 0; - for (int j = 0; j < 4 && frame->can_dlc > j; j++) { + for (int j = 0; j < 4 && frame->len > j; j++) { can->sTxMailBox[mailbox].TDLR |= (uint32_t)(frame->data[j] << (8 * j)); } - for (int j = 4; j < 8 && frame->can_dlc > j; j++) { + for (int j = 4; j < 8 && frame->len > j; j++) { can->sTxMailBox[mailbox].TDHR |= (uint32_t)(frame->data[j] << (8 * (j - 4))); } @@ -470,7 +470,7 @@ static int read_frame(can_t *dev, struct can_frame *frame, int mailbox) } /* Get DLC */ - frame->can_dlc = can->sFIFOMailBox[mailbox].RDTR & CAN_RDT0R_DLC; + frame->len = can->sFIFOMailBox[mailbox].RDTR & CAN_RDT0R_DLC; /* Get Data */ for (int j = 0; j < 4; j++) { diff --git a/cpu/stm32/periph/fdcan.c b/cpu/stm32/periph/fdcan.c new file mode 100644 index 000000000000..bfb5a66f312c --- /dev/null +++ b/cpu/stm32/periph/fdcan.c @@ -0,0 +1,1716 @@ +/* + * Copyright (C) 2024 COGIP Robotics association + * + * 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_stm32 + * @{ + * + * @file + * @brief Implementation of the CAN FD controller driver + * + * @author Gilles DOFFE + * @} + */ + +#include +#include +#include +#include +#include + +#include "can/device.h" +#include "periph/can.h" +#include "periph/gpio.h" +#include "pm_layered.h" + +#define ENABLE_DEBUG 0 +#include "debug.h" + +#define CAN_MAX_WAIT_CHANGE (10000U) + +typedef enum { + MODE_NORMAL, + MODE_SLEEP, + MODE_INIT, +} can_mode_t; + +/* Driver functions */ +static int _init(candev_t *candev); +static void _isr(candev_t *candev); +static int _send(candev_t *candev, const can_frame_t *frame); +static int _abort(candev_t *candev, const can_frame_t *frame); +static int _set(candev_t *candev, canopt_t opt, void *value, size_t value_len); +static int _get(candev_t *candev, canopt_t opt, void *value, size_t max_len); +static int _set_filter(candev_t *candev, const struct can_filter *filter); +static int _remove_filter(candev_t *candev, const struct can_filter *filter); + +/* Interrupts handler */ +static void tx_irq_handler(can_t *dev); +static void tx_isr(can_t *dev); +static void tx_conf(can_t *dev, int mailbox); +static void rx_irq_handler(can_t *dev); +static void rx_new_message_irq_handler(can_t *dev, uint8_t message_ram_rx_fifo); +static void rx_isr(can_t *dev); + +/* Bittiming configuration */ +static inline void set_bit_timing(can_t *dev); + +static inline can_mode_t get_mode(FDCAN_GlobalTypeDef *can); +static int set_mode(FDCAN_GlobalTypeDef *can, can_mode_t mode); + +static const candev_driver_t candev_stm32_driver = { + .send = _send, + .init = _init, + .isr = _isr, + .get = _get, + .set = _set, + .abort = _abort, + .set_filter = _set_filter, + .remove_filter = _remove_filter, +}; + +/* Classic CAN bittiming */ +static const struct can_bittiming_const bittiming_const = { + .tseg1_min = 1, + .tseg1_max = 256, + .tseg2_min = 1, + .tseg2_max = 128, + .sjw_max = 1, + .brp_min = 1, + .brp_max = 1024, + .brp_inc = 1, +}; + +/* FDCAN data bittiming */ +static const struct can_bittiming_const fd_data_bittiming_const = { + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 1, + .brp_min = 1, + .brp_max = 32, + .brp_inc = 1, +}; + +enum { + STATUS_ON, + STATUS_SLEEP, +}; + +/* FDCAN channels */ +static can_t *_can[FDCANDEV_STM32_CHAN_NUMOF]; +/* FDCAN channels status */ +static uint8_t _status[FDCANDEV_STM32_CHAN_NUMOF]; + +/* Return channel for a given FDCAN device */ +static inline uint8_t get_channel(FDCAN_GlobalTypeDef *can) +{ + return (int) (((uint32_t)can - (uint32_t)FDCAN1) >> 10); +} + +/* Return FDCAN STM32 datasheet channel name */ +static inline uint8_t get_channel_id(FDCAN_GlobalTypeDef *can) +{ + return get_channel(can) + 1; +} + +/* Get current FDCAN channel mode */ +static inline can_mode_t get_mode(FDCAN_GlobalTypeDef *can) +{ + if ((can->CCCR & FDCAN_CCCR_CSR) == FDCAN_CCCR_CSR) { + DEBUG("%s: Current FDCAN%u mode: SLEEP\n", __func__, get_channel_id(can)); + return MODE_SLEEP; + } + else if ((can->CCCR & FDCAN_CCCR_INIT) == FDCAN_CCCR_INIT) { + DEBUG("%s: Current FDCAN%u mode: INIT\n", __func__, get_channel_id(can)); + return MODE_INIT; + } + else { + DEBUG("%s: Current FDCAN%u mode: NORMAL\n", __func__, get_channel_id(can)); + return MODE_NORMAL; + } +} + +/* Change FDCAN channel mode */ +static int set_mode(FDCAN_GlobalTypeDef *can, can_mode_t mode) +{ + int max_loop = CAN_MAX_WAIT_CHANGE; + int res = 0; + + switch (mode) { + case MODE_NORMAL: + DEBUG("%s: Set FDCAN%u NORMAL mode\n", __func__, get_channel_id(can)); + /* Disable sleep mode */ + can->CCCR &= ~FDCAN_CCCR_CSR; + while ((can->CCCR & FDCAN_CCCR_CSA) && max_loop != 0) { + max_loop--; + } + if (max_loop) { + max_loop = CAN_MAX_WAIT_CHANGE; + DEBUG("%s: FDCAN%u FDCAN_CCCR_CSA reset\n", __func__, get_channel_id(can)); + } + can->CCCR &= ~FDCAN_CCCR_INIT; + /* CCE (Configuration Change Enable) bit is automatically + cleared when INIT bit is cleared. So to ensure the FDCAN + channel is no more in INIT mode, wait for CCE and INIT bits + to be cleared. */ + while ((can->CCCR & FDCAN_CCCR_CCE) && max_loop != 0) { + max_loop--; + } + if (max_loop) { + max_loop = CAN_MAX_WAIT_CHANGE; + DEBUG("%s: FDCAN%u FDCAN_CCCR_CCE reset\n", __func__, get_channel_id(can)); + } + while ((can->CCCR & FDCAN_CCCR_INIT) && max_loop != 0) { + max_loop--; + } + if (max_loop) { + max_loop = CAN_MAX_WAIT_CHANGE; + DEBUG("%s: FDCAN%u_CCCR_INIT reset\n", __func__, get_channel_id(can)); + } + break; + case MODE_SLEEP: + DEBUG("%s: Set FDCAN%u SLEEP mode\n", __func__, get_channel_id(can)); + /* Enable sleep mode */ + can->CCCR |= FDCAN_CCCR_CSR; + while (!(can->CCCR & FDCAN_CCCR_CSA) && max_loop != 0) { + max_loop--; + } + break; + case MODE_INIT: + DEBUG("%s: Set FDCAN%u INIT mode\n", __func__, get_channel_id(can)); + /* Disable sleep mode */ + can->CCCR &= ~FDCAN_CCCR_CSR; + while ((can->CCCR & FDCAN_CCCR_CSA) && max_loop != 0) { + max_loop--; + } + if (max_loop) { + max_loop = CAN_MAX_WAIT_CHANGE; + } + /* Enable INIT mode */ + can->CCCR |= FDCAN_CCCR_INIT; + while (!(can->CCCR & FDCAN_CCCR_INIT) && max_loop != 0) { + max_loop--; + } + /* Enable Configuration changes */ + can->CCCR |= FDCAN_CCCR_CCE; + break; + default: + DEBUG("%s: FDCAN%u Unsupported mode\n", __func__, get_channel_id(can)); + res = -EINVAL; + break; + } + + DEBUG("%s: FDCAN%u CCCR = %lx\n", __func__, get_channel_id(can), can->CCCR); + + if (max_loop == 0) { + DEBUG("%s: FDCAN%u didn't switch mode %d\n", __func__, get_channel_id(can), mode); + res = -ETIMEDOUT; + } + + return res; +} + +void can_init(can_t *dev, const can_conf_t *conf) +{ + /* Set CAN device callbacks */ + dev->candev.driver = &candev_stm32_driver; + + /* Use the PCLK (APB1 peripheral) clock by default as this clock is always available */ + RCC->CCIPR &= ~RCC_CCIPR_FDCANSEL; + RCC->CCIPR |= RCC_CCIPR_FDCANSEL_1; + + /* Compute bittiming values for classic CAN */ + struct can_bittiming timing = { .bitrate = FDCANDEV_STM32_DEFAULT_BITRATE, + .sample_point = FDCANDEV_STM32_DEFAULT_SPT }; + can_device_calc_bittiming(CLOCK_APB1, &bittiming_const, &timing); + timing.tq = (timing.brp * NS_PER_SEC) / CLOCK_APB1; + + /* Compute bittiming values for FDCAN data stream */ + struct can_bittiming fd_data_timing = { .bitrate = FDCANDEV_STM32_DEFAULT_FD_DATA_BITRATE, + .sample_point = FDCANDEV_STM32_DEFAULT_SPT }; + can_device_calc_bittiming(CLOCK_APB1, &fd_data_bittiming_const, &fd_data_timing); + fd_data_timing.tq = (fd_data_timing.brp * NS_PER_SEC) / CLOCK_APB1; + + /* Save the calculated bittimings */ + memcpy(&dev->candev.bittiming, &timing, sizeof(timing)); + memcpy(&dev->candev.fd_data_bittiming, &fd_data_timing, sizeof(fd_data_timing)); + DEBUG("%s: &dev->rx_mailbox = %p, sizeof(dev->rx_mailbox) = %u\n", + __func__, &dev->rx_mailbox, sizeof(dev->rx_mailbox)); + + /* Save configuration */ + dev->conf = conf; + + /* Reset rx_pin/tx_pin */ + dev->rx_pin = GPIO_UNDEF; + dev->tx_pin = GPIO_UNDEF; +} + +/* Get FDCAN message RAM address */ +static uint32_t* get_message_ram(FDCAN_GlobalTypeDef *can) { + /* In case of multiple instances the RAM start address for the FDCANn is computed by end + of FDCANn-1 address + 4, and the FDCANn end address is computed by FDCANn start + address + 0x0350 - 4. */ + DEBUG("%s: FDCAN%u message RAM address is %p\n", + __func__, get_channel_id(can), + (uint32_t *)(SRAMCAN_BASE + + (((uint32_t)can - FDCAN1_BASE) >> 10) * FDCAN_SRAM_MESSAGE_RAM_SIZE) + ); + + return (uint32_t*)( + SRAMCAN_BASE + + (((uint32_t)can - FDCAN1_BASE) >> 10) * FDCAN_SRAM_MESSAGE_RAM_SIZE + ); +} + +/* Get FDCAN channel extended filters list message RAM address */ +static uint32_t* get_flesa_message_ram(FDCAN_GlobalTypeDef *can) { + DEBUG("%s: FDCAN%u FLESA message RAM address is %p\n", + __func__, get_channel_id(can), + (void*)get_message_ram(can) + FDCAN_SRAM_FLESA + ); + + return get_message_ram(can) + FDCAN_SRAM_FLESA; +} + +/* Get FDCAN channel Rx FIFO message RAM address */ +static uint32_t* get_message_ram_rx_fifo_address(FDCAN_GlobalTypeDef *can, + uint8_t message_ram_rx_fifo) { + DEBUG("%s: FDCAN%u Rx FIFO message RAM address is %p\n", + __func__, get_channel_id(can), + get_message_ram(can) + FDCAN_SRAM_F0SA + message_ram_rx_fifo * FDCAN_SRAM_RXFIFO_SIZE + ); + + return get_message_ram(can) + FDCAN_SRAM_F0SA + message_ram_rx_fifo * FDCAN_SRAM_RXFIFO_SIZE; +} + +/* Get FDCAN channel Tx buffers message RAM address */ +static uint32_t* get_message_ram_tx_buffer_address(FDCAN_GlobalTypeDef *can) { + DEBUG("%s: FDCAN%u Tx FIFO message RAM address is %p\n", + __func__, get_channel_id(can), + get_message_ram(can) + FDCAN_SRAM_TBSA + ); + + return get_message_ram(can) + FDCAN_SRAM_TBSA; +} + +/** Check if filter is set according to filter ID + * filter ID < FDCAN_STM32_NB_STD_FILTER: it is a standard filter (message ID is 11 bits long) + * filter ID >= FDCAN_STM32_NB_STD_FILTER: it is an extended filter (message ID is 29 bits long) + */ +static int filter_is_set(FDCAN_GlobalTypeDef *can, uint8_t filter_id) +{ + int ret = false; + + if (filter_id < FDCAN_STM32_NB_STD_FILTER) { + DEBUG("%s: FDCAN%u filter %u is a standard filter\n", + __func__, get_channel_id(can), filter_id); + if (filter_id < (can->RXGFC & FDCAN_RXGFC_LSS) >> FDCAN_RXGFC_LSS_Pos) { + DEBUG("%s: Filter %u is lesser than standard filter list size (%lx)\n", + __func__, + filter_id, + (can->RXGFC & FDCAN_RXGFC_LSS) >> FDCAN_RXGFC_LSS_Pos); + + /* Filter List Standard start at + RAM address + FLSSA (0x00) + standard filter offset (4 Bytes * filter_id) */ + uint32_t *fls_ram_address = get_message_ram(can) + + FDCAN_SRAM_FLS_FILTER_SIZE * filter_id; + + DEBUG("%s: FDCAN%u ftandard filter message RAM address is %p\n", + __func__, get_channel_id(can), + fls_ram_address + ); + + if (((*fls_ram_address & FDCAN_SRAM_FLS_SFT) != FDCAN_SRAM_FLS_SFT_DISABLED) + || ((*fls_ram_address & FDCAN_SRAM_FLS_SFEC) != FDCAN_SRAM_FLS_SFEC_DISABLED)) { + DEBUG("%s: FDCAN%u filter %u is enabled by SFT(%lx) and SFEC(%lx)\n", + __func__, get_channel_id(can), + filter_id, + (*fls_ram_address & FDCAN_SRAM_FLS_SFT), + (*fls_ram_address & FDCAN_SRAM_FLS_SFEC)); + + ret = true; + } + else { + DEBUG("%s: FDCAN%u filter %u is disabled by SFT(%lx) and/or SFEC(%lx)\n", + __func__, get_channel_id(can), + filter_id, + (*fls_ram_address & FDCAN_SRAM_FLS_SFT), + (*fls_ram_address & FDCAN_SRAM_FLS_SFEC)); + } + } + } + else { + DEBUG("%s: Filter %u is an extended filter\n", __func__, filter_id); + /* Real extended filter index */ + filter_id -= FDCAN_STM32_NB_STD_FILTER; + if (filter_id < (can->RXGFC & FDCAN_RXGFC_LSE) >> FDCAN_RXGFC_LSE_Pos) { + DEBUG("%s: FDCAN%u filter %u is lesser than extended filter list size (%lx)\n", + __func__, get_channel_id(can), + filter_id, + (can->RXGFC & FDCAN_RXGFC_LSE) >> FDCAN_RXGFC_LSE_Pos); + + /* Filter List Extended start at + RAM address + FLESA (0x70) + extended filter offset (8 Bytes * filter_id) */ + uint32_t *fle_ram_address_f0 = get_flesa_message_ram(can) + + FDCAN_SRAM_FLE_FILTER_SIZE * filter_id; + uint32_t *fle_ram_address_f1 = fle_ram_address_f0 + + FDCAN_SRAM_FLE_FILTER_SIZE / 2; + + DEBUG("%s: FDCAN%u extended filter message RAM F0 address is %p\n", + __func__, get_channel_id(can), + fle_ram_address_f0 + ); + DEBUG("%s: FDCAN%u extended filter message RAM F1 address is %p\n", + __func__, get_channel_id(can), + fle_ram_address_f1 + ); + + if ((*fle_ram_address_f0 & FDCAN_SRAM_FLE_F0_EFEC) != FDCAN_SRAM_FLE_F0_EFEC_DISABLED) { + + DEBUG("%s: FDCAN%u filter %u is enabled by EFEC(%lx)\n", + __func__, get_channel_id(can), + filter_id, + (*fle_ram_address_f0 & FDCAN_SRAM_FLE_F0_EFEC)); + ret = true; + } + else { + DEBUG("%s: FDCAN%u filter %u is disabled by EFEC(%lx)\n", + __func__, get_channel_id(can), + filter_id, + (*fle_ram_address_f0 & FDCAN_SRAM_FLE_F0_EFEC)); + } + } + } + + return ret; +} + +/* Set standard filter for 11 bits message ID */ +static int set_standard_filter(FDCAN_GlobalTypeDef *can, uint32_t fr1, uint32_t fr2, + uint8_t filter_id, uint8_t fifo) +{ + /* Check filter ID */ + if (filter_id >= FDCAN_STM32_NB_STD_FILTER) { + DEBUG("ERROR: invalid standard filter ID %u\n", filter_id); + return -ENXIO; + } + + /* Filter List Standard start at + RAM address + FLSSA (0x00) + standard filter offset (4 Bytes * filter_id) */ + uint32_t *fls_ram_address = get_message_ram(can) + FDCAN_SRAM_FLS_FILTER_SIZE * filter_id; + DEBUG("%s: FDCAN%u standard filter message RAM address is %p\n", + __func__, get_channel_id(can), + fls_ram_address + ); + + DEBUG("%s: FDCAN%u standard filter %u value is %lx\n", + __func__, get_channel_id(can), + filter_id, + *fls_ram_address + ); + + /* Set filter/mask */ + if ((fr1 & ~CAN_SFF_MASK) || (fr2 & ~CAN_SFF_MASK)) { + DEBUG("%s: FDCAN%u standard filter %u ID(%lx) or mask(%lx) are not valid\n", + __func__, get_channel_id(can), + filter_id, + fr1, + fr2); + + return -EINVAL; + } + + /* Set filter mask and ID */ + *fls_ram_address &= ~FDCAN_SRAM_FLS_SFID1; + *fls_ram_address |= fr1 << FDCAN_SRAM_FLS_SFID1_Pos; + + *fls_ram_address &= ~FDCAN_SRAM_FLS_SFID2; + *fls_ram_address |= fr2; + + /* Set filter type */ + *fls_ram_address &= ~FDCAN_SRAM_FLS_SFT; + *fls_ram_address |= FDCAN_SRAM_FLS_SFT_CLASSIC; + + /* Filter FIFO configuration */ + *fls_ram_address &= ~FDCAN_SRAM_FLS_SFEC; + *fls_ram_address |= (fifo ? FDCAN_SRAM_FLS_SFEC_FIFO1 : FDCAN_SRAM_FLS_SFEC_FIFO0); + + DEBUG("%s: FDCAN%u standard filter %u value is %lx\n", + __func__, get_channel_id(can), + filter_id, + *fls_ram_address + ); + + /* Set LSS (List Size of Standard filters) according to new filter ID */ + if (filter_id >= (can->RXGFC & FDCAN_RXGFC_LSS) >> FDCAN_RXGFC_LSS_Pos) { + can->RXGFC &= ~FDCAN_RXGFC_LSS; + can->RXGFC |= ((filter_id) + 1) << FDCAN_RXGFC_LSS_Pos; + + DEBUG("%s: FDCAN%u new LSS value is %u\n", + __func__, get_channel_id(can), filter_id + 1); + } + + DEBUG("%s: FDCAN%u new RXGFC value is %lx\n", + __func__, get_channel_id(can), can->RXGFC); + + return 0; +} + +/* Set extended filter for 29 bits message ID */ +static int set_extended_filter(FDCAN_GlobalTypeDef *can, uint32_t fr1, uint32_t fr2, + uint8_t filter_id, uint8_t fifo) +{ + /* Check filter ID */ + if (filter_id >= FDCAN_STM32_NB_EXT_FILTER) { + DEBUG("ERROR: invalid extended filter ID %u\n", filter_id); + return -ENXIO; + } + + /* Filter List Extended start at + RAM address + FLESA (0x70) + extended filter offset (8 Bytes * filter_id) */ + uint32_t *fle_ram_address_f0 = get_flesa_message_ram(can) + + FDCAN_SRAM_FLE_FILTER_SIZE * filter_id; + uint32_t *fle_ram_address_f1 = fle_ram_address_f0 + FDCAN_SRAM_FLE_FILTER_SIZE / 2; + + /* Reset filter */ + *fle_ram_address_f0 = 0; + *fle_ram_address_f1 = 0; + + *fle_ram_address_f0 |= (fr1 & CAN_EFF_MASK) /* Filter ID */ + | (fifo ? FDCAN_SRAM_FLE_F0_EFEC_FIFO1 + : FDCAN_SRAM_FLE_F0_EFEC_FIFO0); /* Filter FIFO configuration */ + *fle_ram_address_f1 |= (fr2 & CAN_EFF_MASK) /* Filter mask */ + | FDCAN_SRAM_FLE_F1_EFT_CLASSIC; /* Set classic filter type */ + + + DEBUG("%s: FDCAN%u extended filter %u F0 value is %lx\n", + __func__, get_channel_id(can), + filter_id, + *fle_ram_address_f0 + ); + DEBUG("%s: FDCAN%u extended filter %u F1 value is %lx\n", + __func__, get_channel_id(can), + filter_id, + *fle_ram_address_f1 + ); + + /* Set LSS (List Size of Extended filters) according to new filter ID */ + if (filter_id >= (can->RXGFC & FDCAN_RXGFC_LSE) >> FDCAN_RXGFC_LSE_Pos) { + can->RXGFC &= ~FDCAN_RXGFC_LSE; + can->RXGFC |= (filter_id + 1) << FDCAN_RXGFC_LSE_Pos; + + DEBUG("%s: FDCAN%u new LSE value is %u\n", + __func__, get_channel_id(can), filter_id + 1); + } + + DEBUG("%s: FDCAN%u new RXGFC value is %lx\n", + __func__, get_channel_id(can), can->RXGFC); + + return 0; +} + +/** Select set function for standard or extended filter. + * Extended filters can filter standard messages + */ +static int set_filter(FDCAN_GlobalTypeDef *can, uint32_t fr1, uint32_t fr2, + uint8_t filter_id, uint8_t fifo) +{ + /* Check ID and mask, to use an extended filter if needed */ + if (filter_id < FDCAN_STM32_NB_STD_FILTER) { + return set_standard_filter(can, fr1, fr2, filter_id, fifo); + } + else { + return set_extended_filter(can, fr1, fr2, filter_id - FDCAN_STM32_NB_STD_FILTER, fifo); + } +} + +static int get_can_filter(FDCAN_GlobalTypeDef *can, uint8_t filter_id, + uint32_t *filter, uint32_t *mask) +{ + if (filter_id < FDCAN_STM32_NB_STD_FILTER) { + /* Filter List Standard start at + RAM address + FLSSA (0x00) + standard filter offset (4 Bytes * filter_id) */ + uint32_t *fls_ram_address = get_message_ram(can) + FDCAN_SRAM_FLS_FILTER_SIZE * filter_id; + *filter = (*fls_ram_address & FDCAN_SRAM_FLS_SFID1) >> FDCAN_SRAM_FLS_SFID1_Pos; + *mask = (*fls_ram_address & FDCAN_SRAM_FLS_SFID2); + } + else { + filter_id -= FDCAN_STM32_NB_STD_FILTER; + /* Filter List Extended start at + RAM address + FLESA (0x70) + extended filter offset (8 Bytes * filter_id) */ + uint32_t *fle_ram_address_f0 = get_flesa_message_ram(can) + + FDCAN_SRAM_FLE_FILTER_SIZE * filter_id; + uint32_t *fle_ram_address_f1 = fle_ram_address_f0 + FDCAN_SRAM_FLE_FILTER_SIZE / 2; + *filter = (*fle_ram_address_f0 & FDCAN_SRAM_FLE_F0_EFID1); + *mask = (*fle_ram_address_f1 & FDCAN_SRAM_FLE_F1_EFID2); + } + + return 0; +} + +static void unset_standard_filter(FDCAN_GlobalTypeDef *can, uint8_t filter_id) +{ + /* Filter List Standard start at + RAM address + FLSSA (0x00) + standard filter offset (4 Bytes * filter_id) */ + uint32_t *fls_ram_address = get_message_ram(can) + FDCAN_SRAM_FLS_FILTER_SIZE * filter_id; + /* Disable filter */ + *fls_ram_address &= ~FDCAN_SRAM_FLS_SFEC; + + DEBUG("%s: FDCAN%u standard filter %u value is %lx\n", + __func__, get_channel_id(can), + filter_id, + *fls_ram_address + ); + + /* Update LSS value if necessary */ + uint8_t lss_value = (can->RXGFC & FDCAN_RXGFC_LSS) >> FDCAN_RXGFC_LSS_Pos; + can->RXGFC &= ~FDCAN_RXGFC_LSS; + can->RXGFC |= lss_value > 0 ? lss_value-- : 0; + + DEBUG("%s: FDCAN%u new LSS value is %u\n", + __func__, get_channel_id(can), filter_id); +} + +static void unset_extended_filter(FDCAN_GlobalTypeDef *can, uint8_t filter_id) +{ + /* Filter List Extended start at + RAM address + FLESA (0x70) + extended filter offset (8 Bytes * filter_id) */ + uint32_t *fle_ram_address_f0 = get_flesa_message_ram(can) + + FDCAN_SRAM_FLE_FILTER_SIZE * filter_id; + /* Disable filter */ + *fle_ram_address_f0 &= ~FDCAN_SRAM_FLE_F0_EFEC; + + DEBUG("%s: FDCAN%u extended filter %u F0 value is %lx\n", + __func__, get_channel_id(can), + filter_id, + *fle_ram_address_f0 + ); + + /* Update LSE value */ + uint8_t lse_value = (can->RXGFC & FDCAN_RXGFC_LSE) >> FDCAN_RXGFC_LSE_Pos; + can->RXGFC &= ~FDCAN_RXGFC_LSE; + can->RXGFC |= lse_value > 0 ? lse_value-- : 0; + + DEBUG("%s: FDCAN%u new LSE value is %u\n", + __func__, get_channel_id(can), filter_id); +} + +/** + * Select unset function for standard or extended filter. + * Extended filters can filter standard messages + */ +static void unset_filter(FDCAN_GlobalTypeDef *can, uint8_t filter_id) +{ + /* Check ID and mask, to use an extended filter if needed */ + if (filter_id < FDCAN_STM32_NB_STD_FILTER) { + unset_standard_filter(can, filter_id); + } + else { + unset_extended_filter(can, filter_id - FDCAN_STM32_NB_STD_FILTER); + } +} + +void candev_stm32_set_pins(can_t *dev, gpio_t tx_pin, gpio_t rx_pin, + gpio_af_t af) +{ + FDCAN_GlobalTypeDef *can = dev->conf->can; + + if (dev->tx_pin != GPIO_UNDEF) { + gpio_init(dev->tx_pin, GPIO_IN); + gpio_init_analog(dev->tx_pin); + } + if (dev->rx_pin != GPIO_UNDEF) { + gpio_init(dev->rx_pin, GPIO_IN); + gpio_init_analog(dev->rx_pin); + } + dev->tx_pin = tx_pin; + dev->rx_pin = rx_pin; + + DEBUG("%s: FDCAN%u GPIO RX = %lu\n", + __func__, get_channel_id(can), rx_pin); + DEBUG("%s: FDCAN%u GPIO TX = %lu\n", + __func__, get_channel_id(can), tx_pin); + + dev->af = af; + gpio_init_af(rx_pin, af); + gpio_init_af(tx_pin, af); +} + +static int _init(candev_t *candev) +{ + can_t *dev = container_of(candev, can_t, candev); + FDCAN_GlobalTypeDef *can = dev->conf->can; + + _can[get_channel(can)] = dev; + + /* Erase TX mailbox and RX FIFO */ + memset(dev->tx_mailbox, 0, sizeof(dev->tx_mailbox)); + memset(&dev->rx_mailbox, 0, sizeof(dev->rx_mailbox)); + + dev->isr_flags.isr_tx = 0; + dev->isr_flags.isr_rx = 0; + + /* Enable device clock */ + periph_clk_en(APB1, dev->conf->rcc_mask); + + DEBUG("%s: FDCAN%u RCC->CCIPR = %lx\n", + __func__, get_channel_id(can), RCC->CCIPR); + + _status[get_channel(can)] = STATUS_ON; + + /* configure pins */ + candev_stm32_set_pins(dev, dev->conf->tx_pin, dev->conf->rx_pin, dev->conf->af); + + set_mode(can, MODE_INIT); + + set_bit_timing(dev); + + /* Enable interrupts */ + NVIC_EnableIRQ(dev->conf->it0_irqn); + NVIC_EnableIRQ(dev->conf->it1_irqn); + + can->CCCR &= ~(FDCAN_CCCR_DAR /* Enable auto retransmission on failure */ + | FDCAN_CCCR_PXHD); /* Enable protocol exception handling */ + can->CCCR |= (FDCAN_CCCR_FDOE /* Enable FD mode */ + | FDCAN_CCCR_BRSE /* Enable bitrate switching */ + | FDCAN_CCCR_TXP); /* Enable transmit pause */ + +#ifdef STM32_PM_STOP + pm_block(STM32_PM_STOP); +#endif + + /* Clear interrupt flags */ + can->IR |= 0xFFFFFFU; + /* Enable all interrupts and both interrupt lines */ + can->IE |= 0xFFFFFFU; + + can->TXBTIE = FDCAN_TXBTIE_TIE; + + can->ILS = FDCAN_ILS_PERR | FDCAN_ILS_SMSG; + can->ILE |= FDCAN_ILE_EINT0 | FDCAN_ILE_EINT1; + + DEBUG("%s: FDCAN%u->CCCR = %lx\n", + __func__, get_channel_id(can), can->CCCR); + + int res = set_mode(can, MODE_NORMAL); + + DEBUG("%s: FDCAN%u init done, return %d\n", + __func__, get_channel_id(can), res); + + /* Reject non matching standard IDs */ + can->RXGFC |= FDCAN_RXGFC_ANFS; + /* Reject non matching extended IDs */ + can->RXGFC |= FDCAN_RXGFC_ANFE; + + return res; +} + +static inline void set_bit_timing(can_t *dev) +{ + FDCAN_GlobalTypeDef *can = dev->conf->can; + + DEBUG("%s: FDCAN%u setup bittiming\n", + __func__, get_channel_id(can)); + /* Normal CAN bittiming */ + can->NBTP = 0; + can->NBTP = (dev->candev.bittiming.sjw - 1) + << FDCAN_NBTP_NSJW_Pos /* SJW */ + | (dev->candev.bittiming.phase_seg2 - 1) + << FDCAN_NBTP_NTSEG2_Pos /* Phase Seg 2 */ + | (dev->candev.bittiming.phase_seg1 + + dev->candev.bittiming.prop_seg - 1) + << FDCAN_NBTP_NTSEG1_Pos /* Phase Seg 1 */ + | (dev->candev.bittiming.brp - 1) + << FDCAN_NBTP_NBRP_Pos; /* BRP */ + + DEBUG("%s: FDCAN%u->NBTP = %lx\n", + __func__, get_channel_id(can), can->NBTP); + + /* FD CAN bittiming */ + can->DBTP = 0; + can->DBTP = (dev->candev.fd_data_bittiming.sjw - 1) + << FDCAN_DBTP_DSJW_Pos /* SJW */ + | (dev->candev.fd_data_bittiming.phase_seg2 - 1) + << FDCAN_DBTP_DTSEG2_Pos /* Phase Seg 2 */ + | (dev->candev.fd_data_bittiming.phase_seg1 + + dev->candev.fd_data_bittiming.prop_seg - 1) + << FDCAN_DBTP_DTSEG1_Pos /* Phase Seg 1 */ + | (dev->candev.fd_data_bittiming.brp - 1) + << FDCAN_DBTP_DBRP_Pos /* BRP */ + | FDCAN_DBTP_TDC; /* Transceiver delay compensation */ + + DEBUG("%s: FDCAN%u->DBTP = %lx\n", + __func__, get_channel_id(can), can->DBTP); + + can->TDCR &= ~FDCAN_TDCR_TDCO; + can->TDCR |= (dev->candev.loop_delay / dev->candev.bittiming.tq) << FDCAN_TDCR_TDCO_Pos; + + DEBUG("%s: FDCAN%u->TDCR = %lx\n", + __func__, get_channel_id(can), can->TDCR); +} + +static uint32_t dlc_to_len(__uint32_t dlc) { + if (dlc <= 8) { + return dlc; + } + switch (dlc) + { + case 9: + return 12; + case 10: + return 16; + case 11: + return 20; + case 12: + return 24; + case 13: + return 32; + case 14: + return 48; + case 15: + return 64; + default: + DEBUG("%s: FDCAN DLC greater than 15, should never happens, consider it as 15", + __func__); + return 64; + } +} + +static uint32_t len_to_dlc(uint32_t len) { + if (len <= 8) { + return len; + } + else if (len <= 12) { + return 9; + } + else if (len <= 16) { + return 10; + } + else if (len <= 20) { + return 11; + } + else if (len <= 24) { + return 12; + } + else if (len <= 32) { + return 13; + } + else if (len <= 48) { + return 14; + } + else if (len <= 64) { + return 15; + } + else { + DEBUG("%s: FDCAN payload size greater than 64, should never happens, consider it as 64", + __func__); + return 15; + } +} + +static int _send(candev_t *candev, const can_frame_t *frame) +{ + can_t *dev = container_of(candev, can_t, candev); + FDCAN_GlobalTypeDef *can = dev->conf->can; + + DEBUG("%s: FDCAN%u candev=%p, frame=%p\n", + __func__, get_channel_id(can), + (void *) candev, (void *) frame); + + /* Check Tx FIFO is not full */ + if (can->TXFQS & FDCAN_TXFQS_TFQF) { + DEBUG("%s: FDCAN%u Tx FIFO is full\n", + __func__, get_channel_id(can)); + return -ENOMEM; + } + + /* Get free Tx buffer element */ + uint32_t put_index = (can->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos; + + dev->tx_mailbox[put_index] = frame; + + uint32_t* tx_buffer_element_t0 = get_message_ram_tx_buffer_address(can) + + (put_index * FDCAN_SRAM_TXBUFFER_SIZE); + memset(tx_buffer_element_t0, 0, FDCAN_SRAM_TXBUFFER_SIZE * 4); + uint32_t* tx_buffer_element_t1 = tx_buffer_element_t0 + 1; + uint32_t* tx_buffer_element_data = tx_buffer_element_t1 + 1; + DEBUG("%s: FDCAN%u tx_buffer_element_t0 = %p\n", + __func__, get_channel_id(can), tx_buffer_element_t0); + DEBUG("%s: FDCAN%u tx_buffer_element_t1 = %p\n", + __func__, get_channel_id(can), tx_buffer_element_t1); + DEBUG("%s: FDCAN%u tx_buffer_element_data = %p\n", + __func__, get_channel_id(can), tx_buffer_element_data); + + /* Check identifier */ + if ((frame->can_id & ~CAN_EFF_FLAG) > CAN_EFF_MASK) { + return -EINVAL; + } + + /* Determine if it a standard or extended identifier */ + uint32_t xtd_bit = ((((frame->can_id & CAN_EFF_FLAG) == CAN_EFF_FLAG) + || (frame->flags & CANFD_FDF)) ? 1 : 0) << FDCAN_SRAM_TXBUFFER_T0_XTD_Pos; + DEBUG("%s: FDCAN%u xtd_bit = %lx\n", + __func__, get_channel_id(can), xtd_bit); + + /* Shift standard ID of 18 bits */ + uint32_t id = (xtd_bit ? (frame->can_id & CAN_EFF_MASK) + : ((frame->can_id & CAN_SFF_MASK) << FDCAN_SRAM_TXBUFFER_T0_ID_Pos)); + DEBUG("%s: FDCAN%u id = %lx\n", + __func__, get_channel_id(can), id); + + uint32_t rtr_bit = ((frame->can_id & CAN_RTR_FLAG) ? 1 : 0) + << FDCAN_SRAM_TXBUFFER_T0_RTR_Pos; + DEBUG("%s: FDCAN%u rtr_bit = %lx\n", + __func__, get_channel_id(can), rtr_bit); + + *tx_buffer_element_t0 = + ((((frame->flags & CANFD_ESI) ? 1 : 0) << FDCAN_SRAM_TXBUFFER_T0_ESI_Pos) + /* The Error State Indicator (ESI) depends of error passive flag */ + | xtd_bit /* Message ID identifier type (11/29 bits) */ + | rtr_bit /* Always a data frame */ + | id); /* Message ID */ + + /* Bit rate switching is specific to FDCAN. */ + if (!(frame->flags & CANFD_FDF) && (frame->flags & CANFD_BRS)) { + DEBUG("%s: FDCAN%u frame %lu BRS is enabled on a non-fd frame\n", + __func__, get_channel_id(can), frame->can_id); + return -EINVAL; + } + + /* Check length */ + if ((frame->flags & CANFD_FDF) && (frame->len > CANFD_MAX_DLEN)) { + DEBUG("%s: FDCAN%u frame %lu len is upper than 64 bytes (%d)\n", + __func__, get_channel_id(can), frame->can_id, frame->len); + return -EINVAL; + } + if (!(frame->flags & CANFD_FDF) && (frame->len > CAN_MAX_DLEN)) { + DEBUG("%s: FDCAN%u frame %lu len is upper than 8 bytes (%d)\n", + __func__, get_channel_id(can), frame->can_id, frame->len); + return -EINVAL; + } + + *tx_buffer_element_t1 = 0; + *tx_buffer_element_t1 = FDCAN_SRAM_TXBUFFER_T1_EFC_DISABLE /* ESI bit */ + | ((frame->flags & CANFD_BRS) + ? FDCAN_SRAM_TXBUFFER_T1_BRS_ON + : FDCAN_SRAM_TXBUFFER_T1_BRS_OFF) /* Bit Rate Switching */ + | ((frame->flags & CANFD_FDF) + ? FDCAN_SRAM_TXBUFFER_T1_FDF_FD + : FDCAN_SRAM_TXBUFFER_T1_FDF_CLASSIC) /* CAN FD frame */ + | (len_to_dlc(frame->len) + << FDCAN_SRAM_TXBUFFER_T1_DLC_Pos); /* Data Length Code*/ + + DEBUG("%s: FDCAN%u *tx_buffer_element_t0 = %lx\n", + __func__, get_channel_id(can), *tx_buffer_element_t0); + DEBUG("%s: FDCAN%u *tx_buffer_element_t1 = %lx\n", + __func__, get_channel_id(can), *tx_buffer_element_t1); + + /* Set data */ + for (uint8_t byte = 0; byte < frame->len && !rtr_bit; byte++) { + *tx_buffer_element_data |= (uint32_t)frame->data[byte] << ((byte % 4) * 8); + DEBUG("%s: FDCAN%u *tx_buffer_element_data[%u] = %lx\n", + __func__, get_channel_id(can), + byte / 4, + *tx_buffer_element_data); + + if (byte % 4 == 3) { + /* Increment buffer pointer */ + ++tx_buffer_element_data; + + DEBUG("%s: FDCAN%u tx_buffer_element_data = %p\n", + __func__, get_channel_id(can), tx_buffer_element_data); + } + } + + /* Request transmission */ + can->TXBAR = 1 << put_index; + + return put_index; +} + +static int _abort(candev_t *candev, const can_frame_t *frame) +{ + can_t *dev = container_of(candev, can_t, candev); + FDCAN_GlobalTypeDef *can = dev->conf->can; + int mailbox = 0; + + for (mailbox = 0; mailbox < FDCAN_STM32_TX_MAILBOXES; mailbox++) { + if (dev->tx_mailbox[mailbox] == frame) { + break; + } + } + if (mailbox == FDCAN_STM32_TX_MAILBOXES) { + return -EOVERFLOW; + } + + can->TXBCR = 1 << (uint32_t)mailbox; + dev->tx_mailbox[mailbox] = NULL; + + return 0; +} + +static int read_frame(can_t *dev, can_frame_t *frame, int message_ram_rx_fifo) +{ + FDCAN_GlobalTypeDef *can = dev->conf->can; + + DEBUG("%s: FDCAN%u Rx FIFO%u is used\n", + __func__, get_channel_id(can), + message_ram_rx_fifo); + + uint32_t get_index = 0; + + if (message_ram_rx_fifo) { + get_index = (can->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos; + } + else { + get_index = (can->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos; + } + + uint32_t* rx_fifo_element_r0 = get_message_ram_rx_fifo_address(can, message_ram_rx_fifo) + + get_index * FDCAN_SRAM_RXFIFO_ELEMENT_SIZE; + uint32_t* rx_fifo_element_r1 = rx_fifo_element_r0 + 1; + uint8_t* rx_fifo_element_data = (uint8_t*)rx_fifo_element_r1 + 4; + + DEBUG("%s: FDCAN%u rx_fifo_element_r0 = %p\n", + __func__, get_channel_id(can), rx_fifo_element_r0); + DEBUG("%s: FDCAN%u rx_fifo_element_r1 = %p\n", + __func__, get_channel_id(can), rx_fifo_element_r1); + DEBUG("%s: FDCAN%u *rx_fifo_element_r0 = %lx\n", + __func__, get_channel_id(can), *rx_fifo_element_r0); + DEBUG("%s: FDCAN%u *rx_fifo_element_r1 = %lx\n", + __func__, get_channel_id(can), *rx_fifo_element_r1); + + /* Check identifier */ + if ((frame->can_id & ~CAN_EFF_FLAG) > CAN_EFF_MASK) { + return -EINVAL; + } + + /* Determine if it is a standard or extended identifier */ + if (*rx_fifo_element_r0 & FDCAN_SRAM_RXFIFO_R0_XTD) { + frame->can_id = *rx_fifo_element_r0 & FDCAN_SRAM_RXFIFO_R0_ID; + frame->can_id |= CAN_EFF_FLAG; + } + else { + frame->can_id = (*rx_fifo_element_r0 & FDCAN_SRAM_RXFIFO_R0_ID) + >> FDCAN_SRAM_RXFIFO_R0_ID_Pos; + } + + /* Check if it is a RTR frame */ + if (*rx_fifo_element_r0 & FDCAN_SRAM_RXFIFO_R0_RTR) { + frame->can_id |= CAN_RTR_FLAG; + } + + /* Check if it is a CAN FD frame */ + if (*rx_fifo_element_r1 & FDCAN_SRAM_RXFIFO_R1_FDF) { + frame->flags |= CANFD_FDF; + } + + /* Check if Bit Rate Switching is on */ + if (*rx_fifo_element_r1 & FDCAN_SRAM_RXFIFO_R1_BRS) { + frame->flags |= CANFD_BRS; + } + + frame->len = dlc_to_len((*rx_fifo_element_r1 & FDCAN_SRAM_RXFIFO_R1_DLC) + >> FDCAN_SRAM_RXFIFO_R1_DLC_Pos); + + /* Get Data */ + for (uint8_t byte = 0; byte < frame->len && !(frame->can_id & CAN_RTR_FLAG); byte++) { + DEBUG("%s: FDCAN%u rx_fifo_element_data = %p\n", + __func__, get_channel_id(can), rx_fifo_element_data); + DEBUG("%s: FDCAN%u *rx_fifo_element_data = %x\n", + __func__, get_channel_id(can), *rx_fifo_element_data); + frame->data[byte] = *rx_fifo_element_data; + rx_fifo_element_data++; + } + + if (message_ram_rx_fifo) { + can->RXF1A = get_index; + } + else { + can->RXF0A = get_index; + } + + return 0; +} + +static void _isr(candev_t *candev) +{ + can_t *dev = container_of(candev, can_t, candev); + + if (dev->isr_flags.isr_tx) { + tx_isr(dev); + } + + if (dev->isr_flags.isr_wkup) { + if (dev->candev.event_callback) { + dev->candev.event_callback(&dev->candev, CANDEV_EVENT_WAKE_UP, NULL); + } + } + + unsigned int irq; + + irq = irq_disable(); + if (dev->isr_flags.isr_rx & 1) { + dev->isr_flags.isr_rx &= ~1; + irq_restore(irq); + rx_isr(dev); + } + else { + irq_restore(irq); + } + + irq = irq_disable(); + if (dev->isr_flags.isr_rx & 2) { + dev->isr_flags.isr_rx &= ~2; + irq_restore(irq); + rx_isr(dev); + } + else { + irq_restore(irq); + } +} + +static void _wkup_cb(void *arg) +{ + can_t *dev = arg; + FDCAN_GlobalTypeDef *can = dev->conf->can; + + gpio_irq_disable(dev->rx_pin); + + DEBUG("%s: FDCAN%u int wkup: %p\n", __func__, get_channel_id(can), arg); + + dev->isr_flags.isr_wkup = 1; + + if (dev->candev.event_callback) { + dev->candev.event_callback(&dev->candev, CANDEV_EVENT_ISR, NULL); + } +} + +/* Disable GPIO Rx interrupt on wake up */ +static void disable_gpio_int(can_t *dev) +{ + FDCAN_GlobalTypeDef *can = dev->conf->can; + + DEBUG("%s: FDCAN%u disable Rx GPIO interrupt\n", + __func__, get_channel_id(can)); + + gpio_irq_disable(dev->rx_pin); + candev_stm32_set_pins(dev, dev->tx_pin, dev->rx_pin, dev->af); +} + +/* Enable GPIO Rx interrupt on sleep */ +static void enable_gpio_int(can_t *dev) +{ + FDCAN_GlobalTypeDef *can = dev->conf->can; + + DEBUG("%s: FDCAN%u enable Rx GPIO interrupt\n", + __func__, get_channel_id(can)); + + gpio_init_int(dev->rx_pin, GPIO_IN, GPIO_FALLING, _wkup_cb, dev); +} + +static void turn_off(can_t *dev) +{ + FDCAN_GlobalTypeDef *can = dev->conf->can; + + DEBUG("%s: FDCAN%u turn off (%p)\n", __func__, get_channel_id(can), (void *)dev); + + unsigned irq = irq_disable(); + + if (_status[get_channel(dev->conf->can)] != STATUS_SLEEP) { +#ifdef STM32_PM_STOP + pm_unblock(STM32_PM_STOP); +#endif + } + + _status[get_channel(dev->conf->can)] = STATUS_SLEEP; + + if (dev->conf->en_deep_sleep_wake_up) { + periph_clk_dis(APB1, dev->conf->rcc_mask); + enable_gpio_int(dev); + } + + irq_restore(irq); +} + +static void turn_on(can_t *dev) +{ + FDCAN_GlobalTypeDef *can = dev->conf->can; + + DEBUG("%s: FDCAN%u turn on (%p)\n", + __func__, get_channel_id(can), dev); + + unsigned irq = irq_disable(); + + if (_status[get_channel(dev->conf->can)] == STATUS_SLEEP) { +#ifdef STM32_PM_STOP + pm_block(STM32_PM_STOP); +#endif + if (dev->conf->en_deep_sleep_wake_up) { + disable_gpio_int(dev); + } + periph_clk_en(APB1, dev->conf->rcc_mask); + } + + _status[get_channel(dev->conf->can)] = STATUS_ON; + + irq_restore(irq); +} + +static int _wake_up(can_t *dev) +{ + turn_on(dev); + return set_mode(dev->conf->can, MODE_NORMAL); +} + +static int _sleep(can_t *dev) +{ + int res = set_mode(dev->conf->can, MODE_SLEEP); + turn_off(dev); + return res; +} + +static int _set(candev_t *candev, canopt_t opt, void *value, size_t value_len) +{ + can_t *dev = container_of(candev, can_t, candev); + FDCAN_GlobalTypeDef *can = dev->conf->can; + int res = 0; + can_mode_t mode; + + switch (opt) { + case CANOPT_BITTIMING: + DEBUG("%s: FDCAN%u set bittiming\n", __func__, get_channel_id(can)); + if (value_len < sizeof(dev->candev.bittiming)) { + res = -EOVERFLOW; + } + else { + memcpy(&dev->candev.bittiming, value, sizeof(dev->candev.bittiming)); + mode = get_mode(can); + if (mode == MODE_SLEEP) { + res = _wake_up(dev); + if (res != 0) { + res = -EBUSY; + break; + } + } + res = set_mode(can, MODE_INIT); + if (res == 0) { + set_bit_timing(dev); + res = sizeof(dev->candev.bittiming); + } + if (mode == MODE_SLEEP) { + if (_sleep(dev) < 0) { + res = -EBUSY; + } + } + else if (set_mode(can, mode) < 0) { + res = -EBUSY; + } + } + break; + case CANOPT_FD_BITTIMING: + DEBUG("%s: FDCAN%u set FDCAN data bittiming\n", __func__, get_channel_id(can)); + if (value_len < sizeof(dev->candev.fd_data_bittiming)) { + res = -EOVERFLOW; + } + else { + memcpy(&dev->candev.fd_data_bittiming, value, + sizeof(dev->candev.fd_data_bittiming)); + mode = get_mode(can); + if (mode == MODE_SLEEP) { + res = _wake_up(dev); + if (res != 0) { + res = -EBUSY; + break; + } + } + res = set_mode(can, MODE_INIT); + if (res == 0) { + set_bit_timing(dev); + res = sizeof(dev->candev.fd_data_bittiming); + } + if (mode == MODE_SLEEP) { + if (_sleep(dev) < 0) { + res = -EBUSY; + } + } + else if (set_mode(can, mode) < 0) { + res = -EBUSY; + } + } + break; + case CANOPT_STATE: + if (value_len < sizeof(canopt_state_t)) { + res = -EOVERFLOW; + } + else { + switch (*((canopt_state_t *)value)) { + case CANOPT_STATE_OFF: + case CANOPT_STATE_SLEEP: + DEBUG("%s: FDCAN%u power down\n", __func__, get_channel_id(can)); + res = _sleep(dev); + break; + case CANOPT_STATE_ON: + DEBUG("%s: FDCAN%u power up\n", __func__, get_channel_id(can)); + res = _wake_up(dev); + break; + case CANOPT_STATE_LISTEN_ONLY: + DEBUG("%s: FDCAN%u listen only\n", __func__, get_channel_id(can)); + mode = get_mode(can); + res = set_mode(can, MODE_INIT); + can->CCCR |= FDCAN_CCCR_MON; + res += set_mode(can, mode); + break; + case CANOPT_STATE_LOOPBACK: + DEBUG("%s: FDCAN%u loopback\n", __func__, get_channel_id(can)); + res = set_mode(can, MODE_INIT); + can->TEST |= FDCAN_TEST_LBCK; + can->CCCR |= FDCAN_CCCR_MON; + res += set_mode(can, MODE_NORMAL); + break; + } + } + break; + default: + res = -ENOTSUP; + break; + } + + return res; +} + +static int _get(candev_t *candev, canopt_t opt, void *value, size_t max_len) +{ + can_t *dev = container_of(candev, can_t, candev); + FDCAN_GlobalTypeDef *can = dev->conf->can; + int res = 0; + + switch (opt) { + case CANOPT_BITTIMING: + if (max_len < sizeof(dev->candev.bittiming)) { + res = -EOVERFLOW; + } + else { + memcpy(value, &dev->candev.bittiming, sizeof(dev->candev.bittiming)); + res = sizeof(dev->candev.bittiming); + } + break; + case CANOPT_BITTIMING_CONST: + if (max_len < sizeof(bittiming_const)) { + res = -EOVERFLOW; + } + else { + memcpy(value, &bittiming_const, sizeof(bittiming_const)); + res = sizeof(bittiming_const); + } + break; + case CANOPT_FD_BITTIMING: + if (max_len < sizeof(dev->candev.fd_data_bittiming)) { + res = -EOVERFLOW; + } + else { + memcpy(value, &dev->candev.fd_data_bittiming, + sizeof(dev->candev.fd_data_bittiming)); + res = sizeof(dev->candev.fd_data_bittiming); + } + break; + case CANOPT_FD_BITTIMING_CONST: + if (max_len < sizeof(fd_data_bittiming_const)) { + res = -EOVERFLOW; + } + else { + memcpy(value, &fd_data_bittiming_const, sizeof(fd_data_bittiming_const)); + res = sizeof(fd_data_bittiming_const); + } + break; + case CANOPT_CLOCK: + if (max_len < sizeof(uint32_t)) { + res = -EOVERFLOW; + } + else { + *((uint32_t *)value) = CLOCK_APB1; + res = sizeof(uint32_t); + } + break; + case CANOPT_RX_FILTERS: + if (max_len % sizeof(struct can_filter) != 0) { + res = -EOVERFLOW; + } + else { + uint8_t nb_enabled_filter = 0; + struct can_filter *filter_list = (struct can_filter *)value; + size_t filter_list_size = max_len / sizeof(struct can_filter); + for (unsigned i = 0; i < FDCAN_STM32_NB_FILTER; i++) { + struct can_filter *filter = filter_list + nb_enabled_filter; + if (filter_is_set(can, i)) { + nb_enabled_filter++; + get_can_filter(can, i, &filter->can_id, &filter->can_mask); + } + if (filter_list_size <= nb_enabled_filter) { + res = -EOVERFLOW; + break; + } + } + if (!res) { + res = nb_enabled_filter * sizeof(struct can_filter); + } + } + break; + case CANOPT_TEC: + if (max_len != sizeof(uint16_t)) { + res = -EOVERFLOW; + } + else { + uint16_t *tec = (uint16_t *)value; + *tec = (can->ECR & FDCAN_ECR_TEC) >> FDCAN_ECR_TEC_Pos; + res = sizeof(uint16_t); + } + break; + case CANOPT_REC: + if (max_len != sizeof(uint16_t)) { + res = -EOVERFLOW; + } + else { + uint16_t *rec = (uint16_t *)value; + *rec = (can->ECR & FDCAN_ECR_REC) >> FDCAN_ECR_REC_Pos; + res = sizeof(uint16_t); + } + break; + default: + res = -ENOTSUP; + break; + } + + return res; +} + +static int _set_filter(candev_t *candev, const struct can_filter *filter) +{ + can_t *dev = container_of(candev, can_t, candev); + FDCAN_GlobalTypeDef *can = dev->conf->can; + int res = 0; + + DEBUG("%s: FDCAN%u dev=%p, filter=0x%" PRIx32 ", mask=0x%" PRIx32 "\n", __func__, + get_channel_id(can), (void *)candev, filter->can_id, filter->can_mask); + + uint8_t i; + for (i = 0; i < FDCAN_STM32_NB_FILTER; i++) { + if (!filter_is_set(can, i) + && ((i >= FDCAN_STM32_NB_STD_FILTER) /* First free filter slot is an extended + filter */ + || (!(filter->can_id & ~CAN_SFF_MASK) + && !(filter->can_mask & ~CAN_SFF_MASK)))) { /* or the filter is standard */ + can_mode_t mode = get_mode(can); + set_mode(can, MODE_INIT); + res = set_filter(can, filter->can_id, filter->can_mask, i, i % FDCAN_STM32_RX_MAILBOXES); + set_mode(can, mode); + if (res) { + return -EINVAL; + } + + break; + } + } + + if (i == FDCAN_STM32_NB_FILTER) { + return -EOVERFLOW; + } + + return i; +} + +static int _remove_filter(candev_t *candev, const struct can_filter *filter) +{ + can_t *dev = container_of(candev, can_t, candev); + FDCAN_GlobalTypeDef *can = dev->conf->can; + + uint8_t i; + + for (i = 0; i < FDCAN_STM32_NB_FILTER; i++) { + if (filter_is_set(can, i)) { + uint32_t filt, mask; + get_can_filter(can, i, &filt, &mask); + DEBUG("%s: FDCAN%u filter=0x%" PRIx32 ",0x%" PRIx32 ", nb=%d, " + "dev_filter=0x%" PRIx32 ",0x%" PRIx32 "\n", __func__, get_channel_id(can), + filter->can_id, filter->can_mask, (int)i, filt, mask); + if ((filt == filter->can_id) /* ID match */ + /* Filter match (extended case) */ + && (((filt & CAN_EFF_FLAG) + && ((mask & CAN_EFF_MASK) == (filter->can_mask & CAN_EFF_MASK))) + /* Filter match (standard case) */ + || (!(filt & CAN_EFF_FLAG) + && ((mask & CAN_SFF_MASK) == (filter->can_mask & CAN_SFF_MASK))))) { + can_mode_t mode = get_mode(can); + set_mode(can, MODE_INIT); + unset_filter(can, i); + set_mode(can, mode); + break; + } + } + } + + return 0; +} + +static void tx_conf(can_t *dev, int mailbox) +{ + candev_t *candev = (candev_t *) dev; + FDCAN_GlobalTypeDef *can = dev->conf->can; + const can_frame_t *frame = dev->tx_mailbox[mailbox]; + + dev->tx_mailbox[mailbox] = NULL; + + DEBUG("%s: FDCAN%u, mailbox=%d\n", + __func__, get_channel_id(can), + mailbox); + + if (frame && dev->candev.event_callback) { + dev->candev.event_callback(candev, CANDEV_EVENT_TX_CONFIRMATION, + (void *) frame); + } +} + +static void tx_irq_handler(can_t *dev) +{ + FDCAN_GlobalTypeDef *can = dev->conf->can; + int flags = dev->isr_flags.isr_tx; + + //DEBUG("%s: FDCAN%u tx irq\n", __func__, get_channel_id(can)); + + if (can->IR & FDCAN_IR_TC) { + dev->isr_flags.isr_tx |= can->TXBTO; + can->IR |= FDCAN_IR_TC; + } + + if (dev->candev.event_callback && flags != dev->isr_flags.isr_tx) { + dev->candev.event_callback(&(dev->candev), CANDEV_EVENT_ISR, NULL); + } +} + +static void tx_isr(can_t *dev) +{ + unsigned int irq; + + irq = irq_disable(); + if (dev->isr_flags.isr_tx & 1) { + dev->isr_flags.isr_tx &= ~1; + irq_restore(irq); + tx_conf(dev, 0); + } + else { + irq_restore(irq); + } + + irq = irq_disable(); + if (dev->isr_flags.isr_tx & 2) { + dev->isr_flags.isr_tx &= ~2; + irq_restore(irq); + tx_conf(dev, 1); + } + else { + irq_restore(irq); + } + + irq = irq_disable(); + if (dev->isr_flags.isr_tx & 4) { + dev->isr_flags.isr_tx &= ~4; + irq_restore(irq); + tx_conf(dev, 2); + } + else { + irq_restore(irq); + } +} + +static void rx_new_message_irq_handler(can_t *dev, uint8_t message_ram_rx_fifo) +{ + candev_t *candev = (candev_t *) dev; + FDCAN_GlobalTypeDef *can = dev->conf->can; + + DEBUG("%s: FDCAN%u rx new message irq\n", __func__, get_channel_id(can)); + + if (!dev->rx_mailbox.is_full) { + int i = dev->rx_mailbox.write_idx; + read_frame(dev, &(dev->rx_mailbox.frame[i]), message_ram_rx_fifo); + + if (!dev->isr_flags.isr_rx) { + dev->isr_flags.isr_rx |= message_ram_rx_fifo + 1; + if (dev->candev.event_callback) { + dev->candev.event_callback(candev, CANDEV_EVENT_ISR, NULL); + } + } + + dev->rx_mailbox.write_idx++; + if (dev->rx_mailbox.write_idx == FDCAN_STM32_RX_MAILBOXES) { + dev->rx_mailbox.write_idx = 0; + } + if (dev->rx_mailbox.write_idx == dev->rx_mailbox.read_idx) { + dev->rx_mailbox.is_full = 1; + } + } + else { + DEBUG("%s: FDCAN%u RX fifo is full!\n", __func__, get_channel_id(can)); + if (dev->candev.event_callback) { + dev->candev.event_callback(candev, CANDEV_EVENT_RX_ERROR, NULL); + } + } +} + +static void rx_isr(can_t *dev) +{ + DEBUG("_rx_isr: device=%p\n", (void *)dev); + + while (dev->rx_mailbox.is_full || dev->rx_mailbox.read_idx != dev->rx_mailbox.write_idx) { + int i = dev->rx_mailbox.read_idx; + + if (dev->candev.event_callback) { + dev->candev.event_callback(&dev->candev, + CANDEV_EVENT_RX_INDICATION, + &dev->rx_mailbox.frame[i]); + } + + dev->rx_mailbox.read_idx++; + if (dev->rx_mailbox.read_idx == FDCAN_STM32_RX_MAILBOXES) { + dev->rx_mailbox.read_idx = 0; + } + + dev->rx_mailbox.is_full = 0; + } +} + +static void rx_irq_handler(can_t *dev) +{ + FDCAN_GlobalTypeDef *can = dev->conf->can; + candev_t *candev = (candev_t *) dev; + + DEBUG("%s: FDCAN%u rx irq\n", __func__, get_channel_id(can)); + + /* FIFO 0 */ + if ((can->IR & FDCAN_IR_RF0L) == FDCAN_IR_RF0L) { + DEBUG("%s: FDCAN%u RF0L: Rx FIFO 0 message lost\n", __func__, get_channel_id(can)); + can->IR |= FDCAN_IR_RF0L; + if (dev->candev.event_callback) { + dev->candev.event_callback(candev, CANDEV_EVENT_RX_ERROR, NULL); + } + } + if ((can->IR & FDCAN_IR_RF0F) == FDCAN_IR_RF0F) { + DEBUG("%s: FDCAN%u RF0F: Rx FIFO 0 full\n", __func__, get_channel_id(can)); + can->IR |= FDCAN_IR_RF0F; + if (dev->candev.event_callback) { + dev->candev.event_callback(candev, CANDEV_EVENT_RX_ERROR, NULL); + } + } + if ((can->IR & FDCAN_IR_RF0N) == FDCAN_IR_RF0N) { + DEBUG("%s: FDCAN%u RF0N: Rx FIFO 0 new message\n", __func__, get_channel_id(can)); + can->IR |= FDCAN_IR_RF0N; + rx_new_message_irq_handler(dev, 0); + } + + /* FIFO 1 */ + if ((can->IR & FDCAN_IR_RF1L) == FDCAN_IR_RF1L) { + DEBUG("%s: FDCAN%u RF1L: Rx FIFO 1 message lost\n", __func__, get_channel_id(can)); + can->IR |= FDCAN_IR_RF0L; + if (dev->candev.event_callback) { + dev->candev.event_callback(candev, CANDEV_EVENT_RX_ERROR, NULL); + } + } + if ((can->IR & FDCAN_IR_RF1F) == FDCAN_IR_RF1F) { + DEBUG("%s: FDCAN%u RF1F: Rx FIFO 1 full\n", __func__, get_channel_id(can)); + can->IR |= FDCAN_IR_RF1F; + if (dev->candev.event_callback) { + dev->candev.event_callback(candev, CANDEV_EVENT_RX_ERROR, NULL); + } + } + if ((can->IR & FDCAN_IR_RF1N) == FDCAN_IR_RF1N) { + DEBUG("%s: FDCAN%u RF1N: Rx FIFO 1 new message\n", __func__, get_channel_id(can)); + can->IR |= FDCAN_IR_RF1N; + rx_new_message_irq_handler(dev, 1); + } +} + +static void irq_handler(can_t *dev) +{ + FDCAN_GlobalTypeDef *can = dev->conf->can; + + DEBUG("%s: FDCAN%u Got interrupts, can->IR = %lx\n", __func__, + get_channel_id(can), dev->conf->can->IR); + + if (dev->conf->can->IR & 0x3F) { + rx_irq_handler(dev); + } + if (dev->conf->can->IR & 0xFC0) { + tx_irq_handler(dev); + } + if (can->IR & FDCAN_IR_PEA) { + DEBUG("%s: FDCAN%u PSR.LEC = %lx\n", __func__, get_channel_id(can), + dev->conf->can->PSR & FDCAN_PSR_LEC); + DEBUG("%s: FDCAN%u ECR = %lx\n", __func__, get_channel_id(can), + dev->conf->can->ECR); + can->IR |= FDCAN_IR_PEA; + } + if (can->IR & FDCAN_IR_PED) { + DEBUG("%s: FDCAN%u PSR.DLEC = %lx\n", __func__, get_channel_id(can), + dev->conf->can->PSR & FDCAN_PSR_DLEC); + DEBUG("%s: FDCAN%u ECR = %lx\n", __func__, get_channel_id(can), dev->conf->can->ECR); + can->IR |= FDCAN_IR_PED; + } + + if (dev->conf->can->IR) { + DEBUG("%s: FDCAN%u Unhandled interrupts, can->IR = %lx\n", __func__, + get_channel_id(can), dev->conf->can->IR); + can->IR |= can->IR; + } +} + +void ISR_FDCAN1_IT0(void) +{ + irq_handler(_can[0]); + + cortexm_isr_end(); +} + +void ISR_FDCAN1_IT1(void) +{ + irq_handler(_can[0]); + + cortexm_isr_end(); +} + +#if defined(FDCAN2) +void ISR_FDCAN2_IT0(void) +{ + irq_handler(_can[1]); + + cortexm_isr_end(); +} + +void ISR_FDCAN2_IT1(void) +{ + irq_handler(_can[1]); + + cortexm_isr_end(); +} +#endif /* FDCAN2 */ + +#if defined(FDCAN3) +void ISR_FDCAN3_IT0(void) +{ + irq_handler(_can[2]); + + cortexm_isr_end(); +} + +void ISR_FDCAN3_IT1(void) +{ + irq_handler(_can[2]); + + cortexm_isr_end(); +} +#endif /* FDCAN3 */ diff --git a/dist/tools/bmp/README.md b/dist/tools/bmp/README.md index 375087ee3107..640257a86999 100644 --- a/dist/tools/bmp/README.md +++ b/dist/tools/bmp/README.md @@ -51,13 +51,21 @@ The probe is auto discovered based on the USB VID (0x1D50) and PID (0x6018, `--serial` is provided. If `--port` is provided, then that port will be used as the GDB port for all -actions, except for the `term` action. +actions, except for the `term` action. `--port` also accepts values such as +network addresses. ## Supported firmwares -This tool assumes firmware version 1.10 of the Black Magic debugger. +There are minor differences in the available firmwares of the Black Magic +debugger. Compatibility has been tested with version 1.8+. -Compatibility for older versions is limited, but can be selected by providing -`--bmp-version x.y.z`. +This tool will try to determine which version of the firmware is installed, +unless the probe is accessed remotely (e.g. `--port` is a network address). If +the firmware version cannot be determined, it will assume version 1.10.2. This +can be overridden using the `--bmp-version` flag. + +As of firmware version 2.0.0 of the Black Magic debugger, support for targets +depend on the 'flavor' of firmware selected. This tool will indicate if that +is the case. ## Examples (tested with BluePill STM32F103F8C6) * test connection: diff --git a/dist/tools/bmp/bmp.py b/dist/tools/bmp/bmp.py index e43a1e24013a..1c8ec3acf900 100755 --- a/dist/tools/bmp/bmp.py +++ b/dist/tools/bmp/bmp.py @@ -25,6 +25,7 @@ from pygdbmi.gdbcontroller import GdbController TIMEOUT = 100 # seconds +DEFAULT_VERSION = Version('1.10.2') # find a suitable gdb executable, falling back to defaults if needed @@ -35,18 +36,30 @@ def find_suitable_gdb(gdb_path): for p in ['arm-none-eabi-gdb', 'gdb-multiarch']: p = shutil.which(p) if p: - print("GDB EXECUTABLE NOT FOUND! FALLING BACK TO %s" % p, file=sys.stderr) + print(f"GDB EXECUTABLE NOT FOUND! FALLING BACK TO {p}", file=sys.stderr) return p print("CANNOT LOCATE SUITABLE GDB EXECUTABLE!", file=sys.stderr) sys.exit(-1) +# detect the firmware version by parsing the product description for something like v1.10.2 +def detect_firmware_version(port): + matches = re.search(r"v[0-9]+.[0-9]+.[0-9]+", port.product) + + if not matches: + return None + + return Version(matches.group(0)[1:]) + + # find all connected BMPs and store both GDB and UART interfaces def detect_probes(): gdb_ports = [] uart_ports = [] for p in serial.tools.list_ports.comports(): if p.vid == 0x1D50 and p.pid in {0x6018, 0x6017}: + p.firmware_version = detect_firmware_version(p) + if re.fullmatch(r'COM\d\d', p.device): p.device = '//./' + p.device if 'GDB' in str(p.interface) \ @@ -62,9 +75,11 @@ def detect_probes(): def enumerate_probes(ports): print("found following Black Magic GDB servers:") for i, s in enumerate(ports): - print("\t[%s]" % s.device, end=' ') + print(f"\t[{s.device}]", end=' ') if len(s.serial_number) > 1: - print("Serial:", s.serial_number, end=' ') + print(f"Serial: {s.serial_number}", end=' ') + if s.firmware_version: + print(f"Firmware: {s.firmware_version}", end=' ') if i == 0: print("<- default", end=' ') print('') @@ -74,7 +89,14 @@ def enumerate_probes(ports): def search_serial(snr, ports): for port in ports: if snr in port.serial_number: - return port.device + return port + + +# search device with specific port number in a list of ports +def search_port(prt, ports): + for port in ports: + if prt == port.device: + return port # parse GDB output for targets @@ -83,9 +105,11 @@ def detect_targets(gdbmi, res): while True: for msg in res: if msg['type'] == 'target': - m = re.fullmatch(pattern=r"\s*(\d+)\s*(.*)\s*", string=msg['payload']) + m = re.fullmatch(pattern=r"([\s\*]*)(\d+)\s*(.*)\s*", string=msg['payload']) if m: - targets.append(m.group(2)) + supported = "***" not in m.group(1) + description = m.group(3) + targets.append((supported, description)) elif msg['type'] == 'result': assert msg['message'] == 'done', str(msg) return targets @@ -131,7 +155,7 @@ def download_to_flash(gdbmi): while True: for msg in res: if msg['type'] == 'result': - assert msg['message'] == 'done', "download failed: %s" % str(msg) + assert msg['message'] == 'done', f"download failed: {msg}" if pbar.start_time: pbar.finish() print("downloading finished") @@ -141,14 +165,12 @@ def download_to_flash(gdbmi): if section_name: if first: first = False - print("downloading... total size: %s" - % humanize.naturalsize(total_size, gnu=True)) + print(f"downloading... total size: {humanize.naturalsize(total_size, gnu=True)}") if section_name != current_sec: if pbar.start_time: pbar.finish() current_sec = section_name - print("downloading section [%s] (%s)" % ( - section_name, humanize.naturalsize(section_size, gnu=True))) + print(f"downloading section [{section_name}] ({humanize.naturalsize(section_size, gnu=True)})") pbar = ProgressBar(widgets=[Percentage(), Bar()], maxval=section_size).start() if section_sent: pbar.update(section_sent) @@ -160,29 +182,50 @@ def check_flash(gdbmi): while True: for msg in res: if msg['type'] == 'result': - assert msg['message'] == 'done', "checking failed: %s" % str(msg) + assert msg['message'] == 'done', f"checking failed: {msg}" print("checking successful") return elif msg['type'] == 'console': assert 'matched' in msg['payload'] and 'MIS-MATCHED' not in msg['payload'], \ - "checking failed: %s" % str(msg) + f"checking failed: {msg}" res = gdbmi.get_gdb_response(timeout_sec=TIMEOUT) -# choose GDB or UART port, based on available ports and application arguments -def choose_port(args, ports): - if args.port: - port = args.port +# choose GDB or UART port, based on available ports and application arguments. +def choose_probe(args, ports): + if args.serial: + descriptor = search_serial(args.serial, ports) + assert descriptor, "no BMP with this serial found" + elif args.port: + descriptor = search_port(args.port, ports) + + # bail out if no descriptor found, because port could be a network address, a pipe or + # something else. + if not descriptor: + return (args.port, None) else: - enumerate_probes(ports) - if args.serial: - port = search_serial(args.serial, ports) - assert port, "no BMP with this serial found" + assert len(ports) > 0, "no ports found" + descriptor = ports[0] + + enumerate_probes(ports) + print(f'connecting to [{descriptor.device}]...') + return (descriptor.device, descriptor) + + +# choose firmware version, based on available descriptors and application arguments. +def choose_firmware_version(args, descriptor): + if args.bmp_version == "auto": + if descriptor and descriptor.firmware_version: + version = descriptor.firmware_version + print(f"auto-detected firmware version {version}") else: - assert len(ports) > 0, "no ports found" - port = ports[0].device - print('connecting to [%s]...' % port) - return port + version = DEFAULT_VERSION + print(f"unable to detect firmware version, assuming {version} or later") + else: + version = Version(args.bmp_version) + print(f"using firmware version {version}") + + return version # terminal mode, opens TTY program @@ -193,7 +236,7 @@ def term_mode(args, uart_port): # debug mode, opens GDB shell with options def debug_mode(args, port): - gdb_args = ['-ex \'target extended-remote %s\'' % port] + gdb_args = [f'-ex \'target extended-remote {port}\''] if args.tpwr: gdb_args.append('-ex \'monitor tpwr enable\'') if args.connect_srst: @@ -208,8 +251,8 @@ def debug_mode(args, port): gdb_args.append('-ex \'monitor swd_scan\'') else: gdb_args.append('-ex \'monitor swdp_scan\'') - gdb_args.append('-ex \'attach %s\'' % args.attach) - os.system(" ".join(['\"' + args.gdb_path + '\"'] + gdb_args + [args.file])) + gdb_args.append(f'-ex \'attach {args.attach}\'') + os.system(" ".join([f'\"{args.gdb_path}\"'] + gdb_args + [args.file])) def connect_to_target(args, port): @@ -220,7 +263,7 @@ def connect_to_target(args, port): except TypeError: # and then new API gdbmi = GdbController(command=[args.gdb_path, "--nx", "--quiet", "--interpreter=mi2", args.file]) - assert gdb_write_and_wait_for_result(gdbmi, '-target-select extended-remote %s' % port, 'connecting', + assert gdb_write_and_wait_for_result(gdbmi, f'-target-select extended-remote {port}', 'connecting', expected_result='connected') # set options if args.connect_srst: @@ -243,10 +286,13 @@ def connect_to_target(args, port): targets = detect_targets(gdbmi, res) assert len(targets) > 0, "no targets found" print("found following targets:") - for t in targets: - print("\t%s" % t) + for s, t in targets: + if not s: + print(f"\t{t} (unsupported)") + else: + print(f"\t{t}") print("") - return gdbmi + return (gdbmi, targets) def parse_args(): @@ -258,9 +304,9 @@ def parse_args(): parser.add_argument('--tpwr', action='store_true', help='enable target power') parser.add_argument('--serial', help='choose specific probe by serial number') parser.add_argument('--port', help='choose specific probe by port (overrides auto selection)') - parser.add_argument('--attach', help='choose specific target by number', default='1') + parser.add_argument('--attach', help='choose specific target by number', type=int, default=1) parser.add_argument('--gdb-path', help='path to GDB', default='gdb-multiarch') - parser.add_argument('--bmp-version', help='choose specific firmware version', default='1.10.0') + parser.add_argument('--bmp-version', help='choose specific firmware version', default='auto') parser.add_argument('--term-cmd', help='serial terminal command', default='picocom --nolock --imap lfcrlf --baud 115200 %s') @@ -279,26 +325,29 @@ def main(): g, u = detect_probes() if args.action == 'term': - port = choose_port(args, u) + (port, _) = choose_probe(args, u) term_mode(args, port) else: - port = choose_port(args, g) + (port, descriptor) = choose_probe(args, g) args.file = args.file if args.file else '' - args.bmp_version = Version(args.bmp_version) + args.bmp_version = choose_firmware_version(args, descriptor) args.gdb_path = find_suitable_gdb(args.gdb_path) if args.action == 'debug': debug_mode(args, port) sys.exit(0) - gdbmi = connect_to_target(args, port) + (gdbmi, targets) = connect_to_target(args, port) if args.action == 'list': sys.exit(0) - assert gdb_write_and_wait_for_result(gdbmi, '-target-attach %s' % args.attach, 'attaching to target') + assert len(targets) >= args.attach, "attach greater than number of targets" + assert targets[args.attach - 1][0], "target unsupported by probe" + + assert gdb_write_and_wait_for_result(gdbmi, f'-target-attach {args.attach}', 'attaching to target') # reset mode: reset device using reset pin if args.action == 'reset': diff --git a/dist/tools/cosy/Makefile b/dist/tools/cosy/Makefile index 3971a9894674..ee89a3866428 100644 --- a/dist/tools/cosy/Makefile +++ b/dist/tools/cosy/Makefile @@ -1,6 +1,6 @@ PKG_NAME=cosy -PKG_URL=https://github.com/haukepetersen/cosy.git -PKG_VERSION=6131f489dda589c4c19068938f99fae679e97fb0 +PKG_URL=https://github.com/RIOT-OS/cosy/ +PKG_VERSION=087fb2d1f2e4d82c7df985e770011f703998aefa PKG_LICENSE=GPL-3 include $(RIOTBASE)/pkg/pkg.mk diff --git a/dist/tools/cosy/patches/0001-cosy-allow-to-specify-port.patch b/dist/tools/cosy/patches/0001-cosy-allow-to-specify-port.patch deleted file mode 100644 index 7f0a4caa1e95..000000000000 --- a/dist/tools/cosy/patches/0001-cosy-allow-to-specify-port.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 221c368153f2aaa73f2a474bb39f547835fdaa0d Mon Sep 17 00:00:00 2001 -From: Benjamin Valentin -Date: Sat, 11 Jun 2022 14:39:16 +0200 -Subject: [PATCH] cosy: allow to specify port - ---- - cosy.py | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/cosy.py b/cosy.py -index b36c28a..6fcb118 100755 ---- a/cosy.py -+++ b/cosy.py -@@ -28,7 +28,6 @@ import json - import frontend_server - - ROOT = path.join(Path(path.abspath(__file__)).parent, "root") --PORT = 12345 - - - def add_sym(target, sym): -@@ -352,6 +351,7 @@ if __name__ == "__main__": - p.add_argument("-c", type=argparse.FileType('w'), - help="Write module sizes to cvs file") - p.add_argument("-d", action="store_true", help="Don't run as web server") -+ p.add_argument("--port", default="12345", help="Webserver port", type=int) - args = p.parse_args() - - # extract path to elf and map file -@@ -407,4 +407,4 @@ if __name__ == "__main__": - print(subprocess.check_output((args.p + 'size', elffile)).decode("utf-8")) - - if not args.d: -- frontend_server.run(ROOT, PORT, 'index.html') -+ frontend_server.run(ROOT, args.port, 'index.html') --- -2.34.1 - diff --git a/dist/tools/cosy/patches/0002-parse_elffile-fix-riot_base.patch b/dist/tools/cosy/patches/0002-parse_elffile-fix-riot_base.patch deleted file mode 100644 index 2cef913534bb..000000000000 --- a/dist/tools/cosy/patches/0002-parse_elffile-fix-riot_base.patch +++ /dev/null @@ -1,26 +0,0 @@ -From ca34f5c4e808b9b6e61e1ceba5e7065bf71fe37a Mon Sep 17 00:00:00 2001 -From: Jana Eisoldt -Date: Mon, 21 Feb 2022 16:52:01 +0100 -Subject: [PATCH] parse_elffile: fix riot_base - ---- - cosy.py | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/cosy.py b/cosy.py -index b36c28a..2081f64 100755 ---- a/cosy.py -+++ b/cosy.py -@@ -154,9 +154,9 @@ def parse_elffile(elffile, prefix, appdir, riot_base=None): - rbase = ["riotbuild/riotproject"] - if riot_base: - rbase.append(riot_base.strip("/")) -- else: -- rbase.append("RIOT") -- rbase.append("riotbuild/riotbase") -+ -+ rbase.append("RIOT") -+ rbase.append("riotbuild/riotbase") - riot_base = "|".join([f'{p}/build|{p}' for p in rbase]) - - c = re.compile(r"(?P[0-9a-f]+) " diff --git a/dist/tools/cosy/patches/0003-take-BUILD_DIR-environment-variable-into-account.patch b/dist/tools/cosy/patches/0003-take-BUILD_DIR-environment-variable-into-account.patch deleted file mode 100644 index f1629e5d6a34..000000000000 --- a/dist/tools/cosy/patches/0003-take-BUILD_DIR-environment-variable-into-account.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 40e6dfb3ba9c50d0bac3931b981822aaa20375a6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Mikolai=20G=C3=BCtschow?= -Date: Tue, 16 Jul 2024 16:48:49 +0200 -Subject: [PATCH] take BUILD_DIR environment variable into account - ---- - cosy.py | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/cosy.py b/cosy.py -index 7a15cc5..5d66f6b 100755 ---- a/cosy.py -+++ b/cosy.py -@@ -17,7 +17,7 @@ - # along with this program. If not, see . - - import sys --from os import path -+from os import path, environ - from pathlib import Path - import argparse - import re -@@ -156,6 +156,8 @@ def parse_elffile(elffile, prefix, appdir, riot_base=None): - - rbase.append("RIOT") - rbase.append("riotbuild/riotbase") -+ if "BUILD_DIR" in environ: -+ rbase.append(environ["BUILD_DIR"]) - riot_base = "|".join([f'{p}/build|{p}' for p in rbase]) - - c = re.compile(r"(?P[0-9a-f]+) " --- -2.39.2 - diff --git a/dist/tools/tapsetup/tapsetup b/dist/tools/tapsetup/tapsetup index 0ee6b7446b68..390f0c22da74 100755 --- a/dist/tools/tapsetup/tapsetup +++ b/dist/tools/tapsetup/tapsetup @@ -63,7 +63,7 @@ unsupported_platform() { update_uplink() { if command -v dhclient > /dev/null; then - dhclient $1 + dhclient -nw $1 else echo "DHCP client \`dhclient\` not found." >&2 echo "Please reconfigure your DHCP client for interface $1" >&2 diff --git a/doc.txt b/doc.txt index 78dca2c18873..94cd317455bf 100644 --- a/doc.txt +++ b/doc.txt @@ -59,6 +59,32 @@ # define DEVELHELP #endif +/** + * @def RIOT_FILE_RELATIVE + * @brief Provides the current filename relative to the RIOT base directory (RIOTBASE) + * @warning This only works within `*.c` and `*.cpp` files. For `*.h`/`*.hpp` files the + * source compiles, however, the including `*.c`/`*.cpp` file will be + * substituted. + * @see `__FILE__` for absolute filenames that also work with *.h files + * @see @ref RIOT_FILE_NOPATH + */ +#if DOXYGEN +# define RIOT_FILE_RELATIVE +#endif + +/** + * @def RIOT_FILE_NOPATH + * @brief Provides the current filename without the parent directory path + * @warning This only works within `*.c` and `*.cpp` files. For `*.h`/`*.hpp` files the + * source compiles, however, the including `*.c`/`*.cpp` file will be + * substituted. + * @see `__FILE__` for absolute filenames that also work with *.h files + * @see @ref RIOT_FILE_RELATIVE + */ +#if DOXYGEN +# define RIOT_FILE_NOPATH +#endif + /** * @def CONFIG_THREAD_NAMES * @brief This global macro enable storage of thread names to help developers. diff --git a/doc/doxygen/riot.doxyfile b/doc/doxygen/riot.doxyfile index 5df85353f2b6..00a214d116b5 100644 --- a/doc/doxygen/riot.doxyfile +++ b/doc/doxygen/riot.doxyfile @@ -2304,8 +2304,7 @@ PREDEFINED = DOXYGEN \ MODULE_GNRC_SIXLOWPAN \ MODULE_GNRC_SIXLOWPAN_ND_ROUTER \ MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER \ - MODULE_GNRC_UDP \ - RIOT_FILE_RELATIVE + MODULE_GNRC_UDP # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The diff --git a/drivers/at/at.c b/drivers/at/at.c index e42b1f8c6cc0..d4fc81476a0a 100644 --- a/drivers/at/at.c +++ b/drivers/at/at.c @@ -513,7 +513,6 @@ static ssize_t at_readline_stop_at_str(at_dev_t *dev, char *resp_buf, size_t len } resp_pos++; - len--; if ((size_t)(resp_pos - resp_buf) >= strlen(AT_RECV_EOL)) { char *const eol_begin = resp_pos - strlen(AT_RECV_EOL); @@ -534,8 +533,10 @@ static ssize_t at_readline_stop_at_str(at_dev_t *dev, char *resp_buf, size_t len substr_p++; } } + + len--; } - if (len <= 1) { + if (len == 1) { return -ENOBUFS; } if (res < 0) { diff --git a/drivers/include/can/candev.h b/drivers/include/can/candev.h index d55b1cad5ad1..1c01ea80ed4a 100644 --- a/drivers/include/can/candev.h +++ b/drivers/include/can/candev.h @@ -80,6 +80,10 @@ struct candev { void *isr_arg; /**< argument to pass on isr event */ struct can_bittiming bittiming; /**< device bittimings */ enum can_state state; /**< device state */ +#ifdef MODULE_FDCAN + struct can_bittiming fd_data_bittiming;/**< device bittimings for FD CAN only */ + uint16_t loop_delay; /**< CAN FD transceiver loop delay */ +#endif }; /** @@ -95,7 +99,7 @@ typedef struct candev_driver { * @return < 0 on error * @return mailbox id >= 0 if OK */ - int (*send)(candev_t *dev, const struct can_frame *frame); + int (*send)(candev_t *dev, const can_frame_t *frame); /** * @brief Abort a packet sending @@ -106,7 +110,7 @@ typedef struct candev_driver { * @return < 0 on error * @return 0 on OK */ - int (*abort)(candev_t *dev, const struct can_frame *frame); + int (*abort)(candev_t *dev, const can_frame_t *frame); /** * @brief the driver's initialization function diff --git a/drivers/include/periph/i2c.h b/drivers/include/periph/i2c.h index c0b7abccbba1..1ddaa5e492cc 100644 --- a/drivers/include/periph/i2c.h +++ b/drivers/include/periph/i2c.h @@ -23,9 +23,6 @@ * this example does not check any return values...): * * @code{c} - * // initialize the bus (this is normally done during boot time) - * i2c_init(dev); - * ... * // before accessing the bus, we need to acquire it * i2c_acquire(dev); * // next we write the register address, but create no STOP condition when done @@ -40,9 +37,6 @@ * 7-bit device addressing: * * @code{c} - * // initialize the bus - * i2c_init(dev); - * ... * // first, acquire the shared bus again * i2c_acquire(dev); * // write the 16-bit register address to the device and prevent STOP condition @@ -205,6 +199,11 @@ typedef enum { * The bus MUST not be acquired before initializing it, as this is handled * internally by the i2c_init function! * + * @warning This function **MUST NOT** be called by the user unless you add + * `DISABLE_MODULE += periph_init_i2c` to your `Makefile`. If you + * do so, call this function before any call to `i2c_acquire()`, + * and call no more than **once**. + * * @param[in] dev the device to initialize */ void i2c_init(i2c_t dev); diff --git a/drivers/include/periph/spi.h b/drivers/include/periph/spi.h index 98680671eece..a7c3c3ae9636 100644 --- a/drivers/include/periph/spi.h +++ b/drivers/include/periph/spi.h @@ -34,8 +34,9 @@ * low-power mode to save energy. * * The SPI unit's initialization is split into 3 parts: - * 1. `spi_init()` should be called once for each SPI unit defined by a board - * during system initialization. + * 1. The SPI buses are automatically initialized during boot according to the + * specification in board's `periph_conf.h`. (The exact format depends on the + * MCU used.) See @ref spi_init for details. * 2. `spi_init_cs()` should be called during device driver initialization, as * each chip select pin/line is used uniquely by a specific device, i.e. chip * select lines are no shared resource. @@ -198,14 +199,17 @@ typedef enum { * MISO, MOSI, and CLK pins. After initialization, the given device should be * in power down state. * - * This function is intended to be called by the board initialization code - * during system startup to prepare the (shared) SPI device for further usage. - * It uses the board specific initialization parameters as defined in the - * board's `periph_conf.h`. + * This function is called internally during system startup to prepare the + * (shared) SPI device for further usage. It uses the board specific + * initialization parameters as defined in the board's `periph_conf.h`. * * Errors (e.g. invalid @p bus parameter) are not signaled through a return * value, but should be signaled using the assert() function internally. * + * @warning This function **MUST NOT** be called by the user unless you add + * `DISABLE_MODULE += periph_init_spi` to your `Makefile`. If you + * do so, call this function before any call to `spi_acquire()`, + * and call no more than **once**. * @note This function MUST not be called more than once per bus! * * @param[in] bus SPI device to initialize diff --git a/drivers/include/periph/uart.h b/drivers/include/periph/uart.h index 87bbc965c1d6..b57e4ea55864 100644 --- a/drivers/include/periph/uart.h +++ b/drivers/include/periph/uart.h @@ -177,7 +177,7 @@ typedef enum { #endif /** - * @brief Initialize a given UART device + * @brief Initialize and acquire a given UART device * * The UART device will be initialized with the following configuration: * - 8 data bits @@ -188,6 +188,14 @@ typedef enum { * If no callback parameter is given (rx_cb := NULL), the UART will be * initialized in TX only mode. * + * @pre The caller is not calling `uart_init()` twice without a call of + * to @ref uart_poweroff in between. + * + * @note This may block if the UART is already acquired until it is released. + * This allows sharing the underlying peripheral to provide other + * serial interfaces (e.g. if the peripheral can also provide SPI, I2C, + * etc.) + * * @param[in] uart UART device to initialize * @param[in] baud desired symbol rate in baud * @param[in] rx_cb receive callback, executed in interrupt context once @@ -401,14 +409,17 @@ int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity, void uart_write(uart_t uart, const uint8_t *data, size_t len); /** - * @brief Power on the given UART device + * @brief Power on and acquire the given UART device + * + * The UART will resume with the configuration it was most recently configured + * with. * * @param[in] uart the UART device to power on */ void uart_poweron(uart_t uart); /** - * @brief Power off the given UART device + * @brief Power off and release the given UART device * * @param[in] uart the UART device to power off */ diff --git a/drivers/mcp2515/mcp2515.c b/drivers/mcp2515/mcp2515.c index 158537fa9963..6d4f19497610 100644 --- a/drivers/mcp2515/mcp2515.c +++ b/drivers/mcp2515/mcp2515.c @@ -40,7 +40,7 @@ #define MCP2515_TX_CTRL(mailbox) ((MCP2515_TXB0CTRL) + ((mailbox) << 4)) #define MCP2515_RX_CTRL(mailbox) ((MCP2515_RXB0CTRL) + ((mailbox) << 4)) -/* length of the fixed part of a can message: 4 bytes can_id + 1 byte can_dlc */ +/* length of the fixed part of a can message: 4 bytes can_id + 1 byte len */ #define CAN_FIXED_LEN 5 /* oscillator startup time @@ -165,13 +165,13 @@ int mcp2515_send(candev_mcp2515_t *dev, const struct can_frame *frame, struct can_frame framebuf; - if (frame->can_dlc > CAN_MAX_DLEN) { + if (frame->len > CAN_MAX_DLEN) { return -1; } framebuf.can_id = frame->can_id; - framebuf.can_dlc = frame->can_dlc; - for (int i = 0; i < framebuf.can_dlc; i++) { + framebuf.len = frame->len; + for (int i = 0; i < framebuf.len; i++) { framebuf.data[i] = frame->data[i]; } @@ -192,14 +192,14 @@ int mcp2515_send(candev_mcp2515_t *dev, const struct can_frame *frame, _fill_standard_id(framebuf.can_id, outbuf); } - outbuf[4] = framebuf.can_dlc; - memcpy(&outbuf[CAN_FIXED_LEN], framebuf.data, framebuf.can_dlc); + outbuf[4] = framebuf.len; + memcpy(&outbuf[CAN_FIXED_LEN], framebuf.data, framebuf.len); /* set mailbox priority */ mcp2515_spi_write(dev, MCP2515_TX_CTRL(mailbox), &prio, 1); mcp2515_spi_write_txbuf(dev, mailbox, outbuf, - CAN_FIXED_LEN + framebuf.can_dlc); + CAN_FIXED_LEN + framebuf.len); _mcp2515_enable_irq(dev, MCP2515_CANINTE_TX0IE << mailbox); mcp2515_spi_rts(dev, mailbox); @@ -228,8 +228,8 @@ int mcp2515_receive(candev_mcp2515_t *dev, struct can_frame *frame, int mailbox) (((uint32_t)inbuf[1] & 0xE0) >> 5); } - frame->can_dlc = inbuf[4]; - memcpy(frame->data, inbuf + 5, frame->can_dlc); + frame->len = inbuf[4]; + memcpy(frame->data, inbuf + 5, frame->len); return mailbox; } diff --git a/examples/advanced_examples/psa_crypto/example_hash.c b/examples/advanced_examples/psa_crypto/example_hash.c index 0f7990a8e92c..88d06afcff1f 100644 --- a/examples/advanced_examples/psa_crypto/example_hash.c +++ b/examples/advanced_examples/psa_crypto/example_hash.c @@ -22,8 +22,10 @@ #include "psa/crypto.h" -static const uint8_t msg[] = "Hello World!"; -static const size_t msg_len = sizeof(msg)-1; // exclude NULL-byte +/* certain PSA backends require the data to be in RAM rather than ROM + * so these values cannot be `const` */ +static uint8_t msg[] = "Hello World!"; +static size_t msg_len = sizeof(msg)-1; // exclude NULL-byte static const uint8_t hash_sha224[] = { 0x45, 0x75, 0xbb, 0x4e, 0xc1, 0x29, 0xdf, 0x63, 0x80, 0xce, 0xdd, 0xe6, 0xd7, diff --git a/examples/advanced_examples/psa_crypto/example_hmac_sha256.c b/examples/advanced_examples/psa_crypto/example_hmac_sha256.c index 712cad3a17c1..a5e248d12f48 100644 --- a/examples/advanced_examples/psa_crypto/example_hmac_sha256.c +++ b/examples/advanced_examples/psa_crypto/example_hmac_sha256.c @@ -30,7 +30,9 @@ static const uint8_t HMAC_KEY[] = { }; static size_t HMAC_KEY_LEN = 32; -static const uint8_t HMAC_MSG[] = { +/* certain PSA backends require the data to be in RAM rather than ROM + * so these values cannot be `const` */ +static uint8_t HMAC_MSG[] = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, diff --git a/examples/advanced_examples/suit_update/main.c b/examples/advanced_examples/suit_update/main.c index 520a60d55577..f7b24f4a342b 100644 --- a/examples/advanced_examples/suit_update/main.c +++ b/examples/advanced_examples/suit_update/main.c @@ -88,6 +88,8 @@ static int cmd_print_riotboot_hdr(int argc, char **argv) return 0; } +SHELL_COMMAND(riotboot_hdr, "Print current slot header", cmd_print_riotboot_hdr); + static int cmd_print_current_slot(int argc, char **argv) { (void)argc; @@ -101,6 +103,9 @@ static int cmd_print_current_slot(int argc, char **argv) irq_restore(state); return 0; } + +SHELL_COMMAND(current_slot, "Print current slot number", cmd_print_current_slot); + #endif static int cmd_print_slot_content(int argc, char **argv) @@ -141,6 +146,8 @@ static int cmd_print_slot_content(int argc, char **argv) return 0; } +SHELL_COMMAND(storage_content, "Print the slot content", cmd_print_slot_content); + static int cmd_lsstorage(int argc, char **argv) { (void)argc; @@ -165,15 +172,7 @@ static int cmd_lsstorage(int argc, char **argv) return 0; } -static const shell_command_t shell_commands[] = { -#ifdef MODULE_SUIT_STORAGE_FLASHWRITE - { "current-slot", "Print current slot number", cmd_print_current_slot }, - { "riotboot-hdr", "Print current slot header", cmd_print_riotboot_hdr }, -#endif - { "storage_content", "Print the slot content", cmd_print_slot_content }, - { "lsstorage", "Print the available storage paths", cmd_lsstorage }, - { NULL, NULL, NULL } -}; +SHELL_COMMAND(lsstorage, "Print the available storage paths", cmd_lsstorage); int main(void) { @@ -197,7 +196,7 @@ int main(void) puts("Starting the shell"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/examples/advanced_examples/suit_update/tests-with-config/01-run.py b/examples/advanced_examples/suit_update/tests-with-config/01-run.py index beb92657c781..83938b196aca 100755 --- a/examples/advanced_examples/suit_update/tests-with-config/01-run.py +++ b/examples/advanced_examples/suit_update/tests-with-config/01-run.py @@ -172,7 +172,7 @@ def seq_no(child): def running_slot(child): utils.test_utils_interactive_sync_shell(child, 5, 1) - child.sendline("current-slot") + child.sendline("current_slot") child.expect(r"Running from slot (\d+)\r\n") slot = int(child.match.group(1)) return slot diff --git a/examples/advanced_examples/twr_aloha/main.c b/examples/advanced_examples/twr_aloha/main.c index cadabdc2dbcf..ed36d6152dc3 100644 --- a/examples/advanced_examples/twr_aloha/main.c +++ b/examples/advanced_examples/twr_aloha/main.c @@ -23,21 +23,12 @@ #include "control.h" -extern int _twr_handler(int argc, char **argv); -extern int _twr_ifconfig(int argc, char **argv); - -static const shell_command_t shell_commands[] = { - { "twr", "Two-way-ranging (TWR) cli", _twr_handler }, - { "ifconfig", "Network interface information", _twr_ifconfig}, - { NULL, NULL, NULL } -}; - int main(void) { /* this should start ranging... */ uwb_core_rng_init(); /* define buffer to be used by the shell */ char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 1; } diff --git a/examples/advanced_examples/twr_aloha/twr_shell.c b/examples/advanced_examples/twr_aloha/twr_shell.c index cd0f74850231..cda2bf0c4784 100644 --- a/examples/advanced_examples/twr_aloha/twr_shell.c +++ b/examples/advanced_examples/twr_aloha/twr_shell.c @@ -42,7 +42,7 @@ #define DW1000_TX_POWER_COARSE_STEP (30) /* 3dbM * 10 */ #define DW1000_TX_POWER_FINE_STEP (5) /* 0.5dbM * 10 */ -int _twr_ifconfig(int argc, char **argv) +static int _twr_ifconfig(int argc, char **argv) { (void)argc; (void)argv; @@ -78,6 +78,8 @@ int _twr_ifconfig(int argc, char **argv) return 0; } +SHELL_COMMAND(ifconfig, "Network interface information", _twr_ifconfig); + static void _print_usage(void) { puts("Usage:"); @@ -92,7 +94,7 @@ static void _print_usage(void) puts("\ttwr lst off: stop listening for ranging requests"); } -int _twr_handler(int argc, char **argv) +static int _twr_handler(int argc, char **argv) { if (argc < 2) { _print_usage(); @@ -218,3 +220,5 @@ int _twr_handler(int argc, char **argv) _print_usage(); return -1; } + +SHELL_COMMAND(twr, "Two-way-ranging (TWR) cli", _twr_handler); diff --git a/examples/essentials/default/main.c b/examples/essentials/default/main.c index b847e0e5a184..e07fa10d05e5 100644 --- a/examples/essentials/default/main.c +++ b/examples/essentials/default/main.c @@ -27,14 +27,12 @@ #include "shell.h" -#ifdef MODULE_NETIF #include "net/gnrc/pktdump.h" #include "net/gnrc.h" -#endif int main(void) { -#ifdef MODULE_NETIF +#ifdef MODULE_GNRC_PKTDUMP gnrc_netreg_entry_t dump = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, gnrc_pktdump_pid); gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump); diff --git a/examples/essentials/filesystem/main.c b/examples/essentials/filesystem/main.c index 69ec3e8262bd..5406f8bfc7e2 100644 --- a/examples/essentials/filesystem/main.c +++ b/examples/essentials/filesystem/main.c @@ -91,11 +91,8 @@ static int _tee(int argc, char **argv) return 0; } -static const shell_command_t shell_commands[] = { - { "cat", "print the content of a file", _cat }, - { "tee", "write a string in a file", _tee }, - { NULL, NULL, NULL } -}; +SHELL_COMMAND(cat, "print the content of a file", _cat); +SHELL_COMMAND(tee, "write a string in a file", _tee); /* constfs example */ #include "fs/constfs.h" @@ -142,7 +139,7 @@ int main(void) } char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/examples/essentials/leds_shell/main.c b/examples/essentials/leds_shell/main.c index c465babf4393..b0145aff1ac7 100644 --- a/examples/essentials/leds_shell/main.c +++ b/examples/essentials/leds_shell/main.c @@ -25,7 +25,7 @@ #include "led.h" #include -static int gpio_command(int argc, char **argv) +static int _gpio_cmd(int argc, char **argv) { if (argc < 4) { printf("usage: %s \n", argv[0]); @@ -64,7 +64,9 @@ static int gpio_command(int argc, char **argv) return 0; } -static int led_command(int argc, char **argv) +SHELL_COMMAND(gpio, "GPIO pin initialization and set port state HIGH/LOW", _gpio_cmd); + +static int _led_cmd(int argc, char **argv) { if (argc < 3) { printf("usage: %s \n", argv[0]); @@ -94,18 +96,14 @@ static int led_command(int argc, char **argv) return 0; } -static const shell_command_t commands[] = { - { "gpio", "GPIO pin initialization and set port state HIGH/LOW", gpio_command }, - { "led", "Switch on/off or toggle on-board LEDs", led_command}, - { NULL, NULL, NULL } -}; +SHELL_COMMAND(led, "Switch on/off or toggle on-board LEDs", _led_cmd); int main(void) { char line_buf[SHELL_DEFAULT_BUFSIZE]; printf("This board has %d LEDs\n", LED_NUMOF); - shell_run(commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/examples/language_bindings/community_supported/javascript/Makefile.ci b/examples/language_bindings/community_supported/javascript/Makefile.ci index 961056a015dc..64f84cf62210 100644 --- a/examples/language_bindings/community_supported/javascript/Makefile.ci +++ b/examples/language_bindings/community_supported/javascript/Makefile.ci @@ -23,7 +23,6 @@ BOARD_INSUFFICIENT_MEMORY := \ microbit \ nrf51dk \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/language_bindings/community_supported/lua_REPL/Makefile.ci b/examples/language_bindings/community_supported/lua_REPL/Makefile.ci index 1bccc4ef64d5..41d40d2fb8aa 100644 --- a/examples/language_bindings/community_supported/lua_REPL/Makefile.ci +++ b/examples/language_bindings/community_supported/lua_REPL/Makefile.ci @@ -40,7 +40,6 @@ BOARD_INSUFFICIENT_MEMORY := \ microbit \ nrf51dk \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/language_bindings/officially_supported/rust-gcoap/Makefile.ci b/examples/language_bindings/officially_supported/rust-gcoap/Makefile.ci index cf8d98ffa9e5..65bdec1a8cfa 100644 --- a/examples/language_bindings/officially_supported/rust-gcoap/Makefile.ci +++ b/examples/language_bindings/officially_supported/rust-gcoap/Makefile.ci @@ -24,7 +24,6 @@ BOARD_INSUFFICIENT_MEMORY := \ maple-mini \ microbit \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/networking/bluetooth_low_energy/nimble/nimble_scanner/main.c b/examples/networking/bluetooth_low_energy/nimble/nimble_scanner/main.c index 6efa2494b885..547453c6cf95 100644 --- a/examples/networking/bluetooth_low_energy/nimble/nimble_scanner/main.c +++ b/examples/networking/bluetooth_low_energy/nimble/nimble_scanner/main.c @@ -60,10 +60,7 @@ int _cmd_scan(int argc, char **argv) return 0; } -static const shell_command_t _commands[] = { - { "scan", "trigger a BLE scan", _cmd_scan }, - { NULL, NULL, NULL } -}; +SHELL_COMMAND(scan, "trigger a BLE scan", _cmd_scan); int main(void) { @@ -88,7 +85,7 @@ int main(void) /* start shell */ char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/examples/networking/coap/gcoap/client.c b/examples/networking/coap/gcoap/client.c index a2b31ff04082..5b940a60da5d 100644 --- a/examples/networking/coap/gcoap/client.c +++ b/examples/networking/coap/gcoap/client.c @@ -31,6 +31,7 @@ #include "net/sock/udp.h" #include "net/sock/util.h" #include "od.h" +#include "shell.h" #include "uri_parser.h" #include "gcoap_example.h" @@ -229,7 +230,7 @@ static int _uristr2remote(const char *uri, sock_udp_ep_t *remote, const char **p return 0; } -int gcoap_cli_cmd(int argc, char **argv) +static int _cli_cmd(int argc, char **argv) { /* Ordered like the RFC method code numbers, but off by 1. GET is code 0. */ char *method_codes[] = {"ping", "get", "post", "put"}; @@ -397,3 +398,5 @@ int gcoap_cli_cmd(int argc, char **argv) help: return _print_usage(argv); } + +SHELL_COMMAND(coap, "CoAP example", _cli_cmd); diff --git a/examples/networking/coap/gcoap/gcoap_example.h b/examples/networking/coap/gcoap/gcoap_example.h index eeb683904081..79c0c701c245 100644 --- a/examples/networking/coap/gcoap/gcoap_example.h +++ b/examples/networking/coap/gcoap/gcoap_example.h @@ -35,14 +35,6 @@ extern "C" { extern uint16_t req_count; /**< Counts requests sent by CLI. */ -/** - * @brief Shell interface exposing the client side features of gcoap - * @param argc Number of shell arguments (including shell command name) - * @param argv Shell argument values (including shell command name) - * @return Exit status of the shell command - */ -int gcoap_cli_cmd(int argc, char **argv); - /** * @brief Registers the CoAP resources exposed in the example app * diff --git a/examples/networking/coap/gcoap/main.c b/examples/networking/coap/gcoap/main.c index 612b98af5f57..61105a7f9dab 100644 --- a/examples/networking/coap/gcoap/main.c +++ b/examples/networking/coap/gcoap/main.c @@ -29,11 +29,6 @@ #define MAIN_QUEUE_SIZE (4) static msg_t _main_msg_queue[MAIN_QUEUE_SIZE]; -static const shell_command_t shell_commands[] = { - { "coap", "CoAP example", gcoap_cli_cmd }, - { NULL, NULL, NULL } -}; - int main(void) { /* for the thread running the shell */ @@ -44,7 +39,7 @@ int main(void) /* start shell */ puts("All up, running the shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); /* should never be reached */ return 0; diff --git a/examples/networking/coap/gcoap/server.c b/examples/networking/coap/gcoap/server.c index b91ff5e419f6..3d3668e90d1e 100644 --- a/examples/networking/coap/gcoap/server.c +++ b/examples/networking/coap/gcoap/server.c @@ -32,6 +32,7 @@ #include "net/utils.h" #include "od.h" #include "periph/rtc.h" +#include "shell.h" #include "time_units.h" #include "gcoap_example.h" diff --git a/examples/networking/coap/gcoap_block_server/gcoap_block.c b/examples/networking/coap/gcoap_block_server/gcoap_block.c index cee4a7bd6a95..bd4923d7a337 100644 --- a/examples/networking/coap/gcoap_block_server/gcoap_block.c +++ b/examples/networking/coap/gcoap_block_server/gcoap_block.c @@ -24,6 +24,7 @@ #include "fmt.h" #include "hashes/sha256.h" #include "net/gcoap.h" +#include "shell.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -135,7 +136,7 @@ static ssize_t _sha256_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, coap_r return pdu_len; } -int gcoap_cli_cmd(int argc, char **argv) +static int _cli_cmd(int argc, char **argv) { if (argc == 1) { /* show help for main commands */ @@ -155,6 +156,8 @@ int gcoap_cli_cmd(int argc, char **argv) return 1; } +SHELL_COMMAND(coap, "CoAP example", _cli_cmd); + void gcoap_cli_init(void) { gcoap_register_listener(&_listener); diff --git a/examples/networking/coap/gcoap_block_server/main.c b/examples/networking/coap/gcoap_block_server/main.c index 48e8be3d677b..faf7985d27ea 100644 --- a/examples/networking/coap/gcoap_block_server/main.c +++ b/examples/networking/coap/gcoap_block_server/main.c @@ -27,14 +27,8 @@ #define MAIN_QUEUE_SIZE (4) static msg_t _main_msg_queue[MAIN_QUEUE_SIZE]; -extern int gcoap_cli_cmd(int argc, char **argv); extern void gcoap_cli_init(void); -static const shell_command_t shell_commands[] = { - { "coap", "CoAP example", gcoap_cli_cmd }, - { NULL, NULL, NULL } -}; - int main(void) { /* for the thread running the shell */ @@ -45,7 +39,7 @@ int main(void) /* start shell */ puts("All up, running the shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); /* should never be reached */ return 0; diff --git a/examples/networking/coap/gcoap_dtls/Makefile.ci b/examples/networking/coap/gcoap_dtls/Makefile.ci index 2a2d882e9895..29799600d300 100644 --- a/examples/networking/coap/gcoap_dtls/Makefile.ci +++ b/examples/networking/coap/gcoap_dtls/Makefile.ci @@ -31,7 +31,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/networking/coap/nanocoap_server/Makefile b/examples/networking/coap/nanocoap_server/Makefile index 667911bc2475..d97f8e318ea3 100644 --- a/examples/networking/coap/nanocoap_server/Makefile +++ b/examples/networking/coap/nanocoap_server/Makefile @@ -20,7 +20,7 @@ USEMODULE += gnrc_icmpv6_echo USEMODULE += nanocoap_sock USEMODULE += nanocoap_resources -USEMODULE += xtimer +USEMODULE += ztimer_msec # include this for nicely formatting the returned internal value USEMODULE += fmt @@ -48,10 +48,12 @@ HIGH_MEMORY_BOARDS := native native64 same54-xpro mcb2388 ifneq (,$(filter $(BOARD),$(HIGH_MEMORY_BOARDS))) # enable separate response - USEMODULE += nanocoap_server_separate USEMODULE += event_callback + USEMODULE += event_periodic USEMODULE += event_thread USEMODULE += event_timeout_ztimer + USEMODULE += nanocoap_server_observe + USEMODULE += nanocoap_server_separate # enable fileserver USEMODULE += nanocoap_fileserver diff --git a/examples/networking/coap/nanocoap_server/coap_handler.c b/examples/networking/coap/nanocoap_server/coap_handler.c index f40a425362c2..86dd39993997 100644 --- a/examples/networking/coap/nanocoap_server/coap_handler.c +++ b/examples/networking/coap/nanocoap_server/coap_handler.c @@ -11,13 +11,13 @@ #include #include "event/callback.h" -#include "event/timeout.h" +#include "event/periodic.h" #include "event/thread.h" +#include "event/timeout.h" #include "fmt.h" #include "net/nanocoap.h" #include "net/nanocoap_sock.h" #include "hashes/sha256.h" -#include "kernel_defines.h" /* internal value that can be read/written via CoAP */ static uint8_t internal_value = 0; @@ -59,7 +59,7 @@ static ssize_t _riot_block2_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, c bufpos += coap_put_option_ct(bufpos, 0, COAP_FORMAT_TEXT); bufpos += coap_opt_put_block2(bufpos, COAP_OPT_CONTENT_FORMAT, &slicer, 1); - *bufpos++ = 0xff; + *bufpos++ = COAP_PAYLOAD_MARKER; /* Add actual content */ bufpos += coap_blockwise_put_bytes(&slicer, bufpos, block2_intro, sizeof(block2_intro)-1); @@ -196,7 +196,7 @@ static void _send_response(void *ctx) puts("_separate_handler(): send delayed response"); nanocoap_server_send_separate(ctx, COAP_CODE_CONTENT, COAP_TYPE_NON, - response, sizeof(response)); + response, sizeof(response)); } static ssize_t _separate_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, coap_request_ctx_t *context) @@ -204,7 +204,12 @@ static ssize_t _separate_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, coap static event_timeout_t event_timeout; static event_callback_t event_timed = EVENT_CALLBACK_INIT(_send_response, &_separate_ctx); - if (event_timeout_is_pending(&event_timeout) && !sock_udp_ep_equal(context->remote, &_separate_ctx.remote)) { + if (event_timeout_is_pending(&event_timeout)) { + if (nanocoap_server_is_remote_in_response_ctx(&_separate_ctx, context)) { + /* duplicate of the request a separate response is already scheduled + * for --> resending the ACK */ + return coap_build_empty_ack(pkt, (void *)buf); + } puts("_separate_handler(): response already scheduled"); return coap_build_reply(pkt, COAP_CODE_SERVICE_UNAVAILABLE, buf, len, 0); } @@ -229,6 +234,107 @@ NANOCOAP_RESOURCE(separate) { }; #endif /* MODULE_EVENT_THREAD */ +#ifdef MODULE_NANOCOAP_SERVER_OBSERVE +static ssize_t _time_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, coap_request_ctx_t *context) +{ + uint32_t obs; + bool registered = false; + if (coap_opt_get_uint(pkt, COAP_OPT_OBSERVE, &obs)) { + /* No (valid) observe option present */ + obs = UINT32_MAX; + } + + uint32_t now = ztimer_now(ZTIMER_MSEC); + + switch (obs) { + case 0: + /* register */ + if (nanocoap_register_observer(context, pkt) == 0) { + registered = true; + } + break; + case 1: + /* unregister */ + nanocoap_unregister_observer(context, pkt); + break; + default: + /* No (valid) observe option present --> ignore observe and handle + * as regular GET */ + break; + } + + const size_t estimated_data_len = + 4 /* Max Observe Option size */ + + 1 /* payload marker */ + + 10 /* strlen("4294967295"), 4294967295 == UINT32_MAX */ + + 1; /* '\n' */ + ssize_t hdr_len = coap_build_reply(pkt, COAP_CODE_CONTENT, buf, len, estimated_data_len); + + if (hdr_len < 0) { + /* we undo any potential registration if we cannot reply */ + nanocoap_unregister_observer(context, pkt); + return len; + } + + if (hdr_len == 0) { + /* no response required, probably because of no-response option matching + * the response class */ + return 0; + } + + /* coap_build_reply() is a bit goofy: It returns the size of the written + * header + `estiamted_data_len`, so we have to subtract it again to obtain + * the size of data written. */ + uint8_t *pos = buf + hdr_len - estimated_data_len; + + if (registered) { + uint16_t last_opt = 0; + pos += coap_opt_put_observe(pos, last_opt, now); + } + *pos++ = COAP_PAYLOAD_MARKER; + pos += fmt_u32_dec((void *)pos, now); + *pos++ = '\n'; + + return (uintptr_t)pos - (uintptr_t)buf; +} + +NANOCOAP_RESOURCE(time) { + .path = "/time", .methods = COAP_GET, .handler = _time_handler, +}; + +static void _notify_observer_handler(event_t *ev) +{ + (void)ev; + uint32_t now = ztimer_now(ZTIMER_MSEC); + uint8_t buf[32]; + uint8_t *pos = buf; + uint16_t last_opt = 0; + pos += coap_opt_put_observe(pos, last_opt, now); + *pos++ = COAP_PAYLOAD_MARKER; + pos += fmt_u32_dec((void *)pos, now); + *pos++ = '\n'; + iolist_t data = { + .iol_base = buf, + .iol_len = (uintptr_t)pos - (uintptr_t)buf, + }; + + /* `NANOCOAP_RESOURCE(time)` expends to XFA magic adding an entry named + * `coap_resource_time`. */ + nanocoap_notify_observers(&coap_resource_time, &data); +} + +void setup_observe_event(void) +{ + static event_t ev = { + .handler = _notify_observer_handler + }; + static event_periodic_t pev; + + event_periodic_init(&pev, ZTIMER_MSEC, EVENT_PRIO_MEDIUM, &ev); + event_periodic_start(&pev, MS_PER_SEC); +} +#endif /* MODULE_NANOCOAP_SERVER_OBSERVE */ + /* we can also include the fileserver module */ #ifdef MODULE_NANOCOAP_FILESERVER #include "net/nanocoap/fileserver.h" diff --git a/examples/networking/coap/nanocoap_server/main.c b/examples/networking/coap/nanocoap_server/main.c index 739a63e3d96f..72dba3209f49 100644 --- a/examples/networking/coap/nanocoap_server/main.c +++ b/examples/networking/coap/nanocoap_server/main.c @@ -20,13 +20,15 @@ #include #include "net/nanocoap_sock.h" -#include "xtimer.h" +#include "ztimer.h" #define COAP_INBUF_SIZE (256U) #define MAIN_QUEUE_SIZE (8) static msg_t _main_msg_queue[MAIN_QUEUE_SIZE]; +extern void setup_observe_event(void); + int main(void) { puts("RIOT nanocoap example application"); @@ -35,7 +37,11 @@ int main(void) msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE); puts("Waiting for address autoconfiguration..."); - xtimer_sleep(3); + ztimer_sleep(ZTIMER_MSEC, 3 * MS_PER_SEC); + + if (IS_USED(MODULE_NANOCOAP_SERVER_OBSERVE)) { + setup_observe_event(); + } /* print network addresses */ printf("{\"IPv6 addresses\": [\""); diff --git a/examples/networking/core_resource_directory/cord_lc/cord_lc_cli.c b/examples/networking/core_resource_directory/cord_lc/cord_lc_cli.c index 53c60cd9d4dd..174f3ae8ba81 100644 --- a/examples/networking/core_resource_directory/cord_lc/cord_lc_cli.c +++ b/examples/networking/core_resource_directory/cord_lc/cord_lc_cli.c @@ -26,6 +26,7 @@ #include "net/gnrc/netif.h" #include "net/gcoap.h" #include "net/sock/util.h" +#include "shell.h" static cord_lc_rd_t rd; static sock_udp_ep_t remote; @@ -91,7 +92,7 @@ static void _print_usage(void) { "example: cord_lc [2001:db8:3::dead:beef]:5683 endpoint"); } -int cord_lc_cli_cmd(int argc, char **argv) { +static int _cli_cmd(int argc, char **argv) { char bufpool[1024] = {0}; int raw_mode = 0; @@ -175,3 +176,5 @@ int cord_lc_cli_cmd(int argc, char **argv) { } return 0; } + +SHELL_COMMAND(cord_lc, "Cord LC example", _cli_cmd); diff --git a/examples/networking/core_resource_directory/cord_lc/main.c b/examples/networking/core_resource_directory/cord_lc/main.c index f8a8a49ec391..3ed93e33906b 100644 --- a/examples/networking/core_resource_directory/cord_lc/main.c +++ b/examples/networking/core_resource_directory/cord_lc/main.c @@ -26,13 +26,6 @@ #define MAIN_QUEUE_SIZE (8) static msg_t _main_msg_queue[MAIN_QUEUE_SIZE]; -extern int cord_lc_cli_cmd(int argc, char **argv); - -static const shell_command_t shell_commands[] = { - { "cord_lc", "Cord LC example", cord_lc_cli_cmd }, - { NULL, NULL, NULL }, -}; - int main(void) { /* we need a message queue for the thread running the shell in order to @@ -41,7 +34,7 @@ int main(void) puts("CoRE RD lookup client example!\n"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/examples/networking/dtls/dtls-echo/Makefile.ci b/examples/networking/dtls/dtls-echo/Makefile.ci index 1feb84512501..5cb8c7725a6b 100644 --- a/examples/networking/dtls/dtls-echo/Makefile.ci +++ b/examples/networking/dtls/dtls-echo/Makefile.ci @@ -27,7 +27,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/networking/dtls/dtls-echo/dtls-client.c b/examples/networking/dtls/dtls-echo/dtls-client.c index fd4e4b60ffd9..0001d792bb49 100644 --- a/examples/networking/dtls/dtls-echo/dtls-client.c +++ b/examples/networking/dtls/dtls-echo/dtls-client.c @@ -28,6 +28,7 @@ #include "timex.h" #include "net/gnrc/netif.h" #include "net/sock/udp.h" +#include "shell.h" #include "tinydtls_keys.h" /* TinyDTLS */ @@ -485,7 +486,7 @@ static void client_send(char *addr_str, char *data) return; } -int udp_client_cmd(int argc, char **argv) +static int _client_cmd(int argc, char **argv) { if (argc != 3) { printf("usage: %s \n", argv[0]); @@ -495,3 +496,5 @@ int udp_client_cmd(int argc, char **argv) return 0; } + +SHELL_COMMAND(dtlsc, "Start a DTLS client", _client_cmd); diff --git a/examples/networking/dtls/dtls-echo/dtls-server.c b/examples/networking/dtls/dtls-echo/dtls-server.c index 0c84417f3bee..4a413f7005ad 100644 --- a/examples/networking/dtls/dtls-echo/dtls-server.c +++ b/examples/networking/dtls/dtls-echo/dtls-server.c @@ -28,6 +28,7 @@ #include "net/sock/udp.h" #include "msg.h" +#include "shell.h" #include "timex.h" #include "tinydtls_keys.h" @@ -419,7 +420,7 @@ static void stop_server(void) puts("Success: DTLS server stopped"); } -int udp_server_cmd(int argc, char **argv) +static int _server_cmd(int argc, char **argv) { if (argc < 2) { printf("usage: %s start|stop\n", argv[0]); @@ -436,3 +437,5 @@ int udp_server_cmd(int argc, char **argv) } return 0; } + +SHELL_COMMAND(dtlss, "Start and stop a DTLS server", _server_cmd); diff --git a/examples/networking/dtls/dtls-echo/main.c b/examples/networking/dtls/dtls-echo/main.c index 3dc06ca90dce..71ed11c55c8a 100644 --- a/examples/networking/dtls/dtls-echo/main.c +++ b/examples/networking/dtls/dtls-echo/main.c @@ -34,15 +34,6 @@ #define MAIN_QUEUE_SIZE (8) static msg_t _main_msg_queue[MAIN_QUEUE_SIZE]; -extern int udp_client_cmd(int argc, char **argv); -extern int udp_server_cmd(int argc, char **argv); - -static const shell_command_t shell_commands[] = { - { "dtlsc", "Start a DTLS client", udp_client_cmd }, - { "dtlss", "Start and stop a DTLS server", udp_server_cmd }, - { NULL, NULL, NULL } -}; - int main(void) { /* we need a message queue for the thread running the shell in order to @@ -56,7 +47,7 @@ int main(void) /* start shell */ puts("All up, running the shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); /* should be never reached */ return 0; diff --git a/examples/networking/dtls/dtls-sock/Makefile.ci b/examples/networking/dtls/dtls-sock/Makefile.ci index 58a2c5f5cc5a..4f9d7736600b 100644 --- a/examples/networking/dtls/dtls-sock/Makefile.ci +++ b/examples/networking/dtls/dtls-sock/Makefile.ci @@ -30,7 +30,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/networking/dtls/dtls-sock/dtls-client.c b/examples/networking/dtls/dtls-sock/dtls-client.c index d50998613767..fc0b5e47d3c3 100644 --- a/examples/networking/dtls/dtls-sock/dtls-client.c +++ b/examples/networking/dtls/dtls-sock/dtls-client.c @@ -28,6 +28,7 @@ #include "net/credman.h" #include "net/sock/util.h" #include "net/utils.h" +#include "shell.h" #include "dtls_client_credentials.h" @@ -235,7 +236,7 @@ static int client_send(char *addr_str, char *data, size_t datalen) return 0; } -int dtls_client_cmd(int argc, char **argv) +static int _client_cmd(int argc, char **argv) { if (argc != 3) { printf("usage %s \n", argv[0]); @@ -252,3 +253,5 @@ int dtls_client_cmd(int argc, char **argv) return client_send(argv[1], argv[2], strlen(argv[2])); } + +SHELL_COMMAND(dtlsc, "Start a DTLS client", _client_cmd); diff --git a/examples/networking/dtls/dtls-sock/dtls-server.c b/examples/networking/dtls/dtls-sock/dtls-server.c index 4f36b9a3779f..c54f59133296 100644 --- a/examples/networking/dtls/dtls-sock/dtls-server.c +++ b/examples/networking/dtls/dtls-sock/dtls-server.c @@ -25,6 +25,7 @@ #include "net/sock/util.h" #include "net/credman.h" #include "msg.h" +#include "shell.h" #include "thread.h" #include "timex.h" @@ -283,7 +284,7 @@ void _print_usage(const char *cmd) } } -int dtls_server_cmd(int argc, char **argv) +static int _server_cmd(int argc, char **argv) { if (argc < 2) { _print_usage(argv[0]); @@ -326,3 +327,5 @@ int dtls_server_cmd(int argc, char **argv) } return 0; } + +SHELL_COMMAND(dtlss, "Start and stop a DTLS server", _server_cmd); diff --git a/examples/networking/dtls/dtls-sock/main.c b/examples/networking/dtls/dtls-sock/main.c index f80b775466df..ee9a8fb2f748 100644 --- a/examples/networking/dtls/dtls-sock/main.c +++ b/examples/networking/dtls/dtls-sock/main.c @@ -20,15 +20,6 @@ #include "shell.h" -extern int dtls_client_cmd(int argc, char **argv); -extern int dtls_server_cmd(int argc, char **argv); - -static const shell_command_t shell_commands[] = { - { "dtlsc", "Start a DTLS client", dtls_client_cmd }, - { "dtlss", "Start and stop a DTLS server", dtls_server_cmd }, - { NULL, NULL, NULL } -}; - int main(void) { puts("DTLS sock example application"); @@ -36,7 +27,7 @@ int main(void) /* start shell */ puts("All up, running the shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); /* should never be reached */ return 0; diff --git a/examples/networking/dtls/dtls-wolfssl/Makefile.ci b/examples/networking/dtls/dtls-wolfssl/Makefile.ci index 64f98b634940..a7b33c2ac94d 100644 --- a/examples/networking/dtls/dtls-wolfssl/Makefile.ci +++ b/examples/networking/dtls/dtls-wolfssl/Makefile.ci @@ -17,7 +17,6 @@ BOARD_INSUFFICIENT_MEMORY := \ maple-mini \ microbit \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/networking/dtls/dtls-wolfssl/dtls-client.c b/examples/networking/dtls/dtls-wolfssl/dtls-client.c index 655052f6d509..732ce0d71c02 100644 --- a/examples/networking/dtls/dtls-wolfssl/dtls-client.c +++ b/examples/networking/dtls/dtls-wolfssl/dtls-client.c @@ -28,6 +28,7 @@ #include "net/gnrc/netif.h" #include "log.h" +#include "shell.h" #define SERVER_PORT 11111 #define APP_DTLS_BUF_SIZE 64 @@ -83,7 +84,7 @@ static inline unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, } #endif -int dtls_client(int argc, char **argv) +static int _client_cmd(int argc, char **argv) { int ret = 0; char buf[APP_DTLS_BUF_SIZE] = "Hello from DTLS client!"; @@ -191,3 +192,5 @@ int dtls_client(int argc, char **argv) sock_dtls_close(sk); return 0; } + +SHELL_COMMAND(dtlsc, "Start a DTLS client", _client_cmd); diff --git a/examples/networking/dtls/dtls-wolfssl/dtls-server.c b/examples/networking/dtls/dtls-wolfssl/dtls-server.c index 3fb9303b3411..bb940c0c0f7b 100644 --- a/examples/networking/dtls/dtls-wolfssl/dtls-server.c +++ b/examples/networking/dtls/dtls-wolfssl/dtls-server.c @@ -29,6 +29,7 @@ #include #include "log.h" +#include "shell.h" #define SERVER_PORT 11111 #define DEBUG 1 @@ -83,7 +84,7 @@ static inline unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, #define APP_DTLS_BUF_SIZE 64 -int dtls_server(int argc, char **argv) +static int _server_cmd(int argc, char **argv) { char buf[APP_DTLS_BUF_SIZE]; int ret; @@ -160,3 +161,5 @@ int dtls_server(int argc, char **argv) } return 0; } + +SHELL_COMMAND(dtlss, "Start and stop a DTLS server", _server_cmd); diff --git a/examples/networking/dtls/dtls-wolfssl/main.c b/examples/networking/dtls/dtls-wolfssl/main.c index c6bc93342e95..d92e095d95a8 100644 --- a/examples/networking/dtls/dtls-wolfssl/main.c +++ b/examples/networking/dtls/dtls-wolfssl/main.c @@ -44,17 +44,9 @@ static int wolftest(int argc, char **argv) wolfcrypt_test(NULL); return 0; } +SHELL_COMMAND(wolftest, "Perform wolfcrypt porting test", wolftest); #endif -static const shell_command_t shell_commands[] = { - { "dtlsc", "Start a DTLS client", dtls_client }, - { "dtlss", "Start and stop a DTLS server", dtls_server }, -#ifdef MODULE_WOLFCRYPT_TEST - { "wolftest", "Perform wolfcrypt porting test", wolftest }, -#endif - { NULL, NULL, NULL } -}; - int main(void) { /* we need a message queue for the thread running the shell in order to @@ -67,7 +59,7 @@ int main(void) /* start shell */ LOG(LOG_INFO, "All up, running the shell now\n"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); /* should be never reached */ return 0; diff --git a/examples/networking/gnrc_networking/gnrc_border_router/Makefile b/examples/networking/gnrc_networking/gnrc_border_router/Makefile index 9f770f304cf4..7b6b6391d99e 100644 --- a/examples/networking/gnrc_networking/gnrc_border_router/Makefile +++ b/examples/networking/gnrc_networking/gnrc_border_router/Makefile @@ -10,6 +10,14 @@ RIOTBASE ?= $(CURDIR)/../../../.. # Default to using ethos for providing the uplink when not on native UPLINK ?= ethos +# If enabled will configure a default DNS resolver and propagate it via the +# RDNSS option to the hosts +ENABLE_DNS ?= 1 +# If the above setting is active this setting will also enable DNS caching, +# consequently dedicating some more memory space in order to reduce DNS +# requests +ENABLE_DNS_CACHING ?= 1 + # Check if the selected Uplink is valid ifeq (,$(filter ethos slip cdc-ecm wifi ethernet,$(UPLINK))) $(error Supported uplinks are `ethos`, `slip`, `cdc-ecm`, `ethernet` and `wifi`) @@ -39,8 +47,14 @@ USEMODULE += ps # Optionally include DNS support. This includes resolution of names at an # upstream DNS server and the handling of RDNSS options in Router Advertisements # to auto-configure that upstream DNS server. -#USEMODULE += sock_dns # include DNS client -#USEMODULE += gnrc_ipv6_nib_dns # include RDNSS option handling +ifneq (0,$(ENABLE_DNS)) + USEMODULE += sock_dns # include DNS client + USEMODULE += gnrc_ipv6_nib_dns # include RDNSS option handling + USEMODULE += auto_init_sock_dns # configure default DNS resolver + ifneq (0,$(ENABLE_DNS_CACHING)) + USEMODULE += dns_cache # cache DNS responses + endif +endif # When using a regular network uplink we should use DHCPv6 ifneq (,$(filter cdc-ecm wifi ethernet,$(UPLINK))$(REUSE_TAP)) @@ -57,6 +71,9 @@ endif ifeq (dhcpv6,$(PREFIX_CONF)) # include DHCPv6 client for 6LoWPAN border router USEMODULE += gnrc_dhcpv6_client_6lbr + # optionally also request an address via IA_NA in addition to the prefix. + # this is not needed when using SLAAC + USEMODULE += dhcpv6_client_ia_na else ifeq (uhcp,$(PREFIX_CONF)) # include UHCP client USEMODULE += gnrc_uhcpc diff --git a/examples/networking/gnrc_networking/gnrc_border_router/Makefile.ci b/examples/networking/gnrc_networking/gnrc_border_router/Makefile.ci index fcbe41c2a3d9..f8e68ac08ad7 100644 --- a/examples/networking/gnrc_networking/gnrc_border_router/Makefile.ci +++ b/examples/networking/gnrc_networking/gnrc_border_router/Makefile.ci @@ -34,7 +34,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430h \ nrf51dk \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/networking/gnrc_networking/gnrc_networking_mac/mac.c b/examples/networking/gnrc_networking/gnrc_networking_mac/mac.c index 2eaa251a4dcb..b498244b0f72 100644 --- a/examples/networking/gnrc_networking/gnrc_networking_mac/mac.c +++ b/examples/networking/gnrc_networking/gnrc_networking_mac/mac.c @@ -23,8 +23,9 @@ #include "net/gnrc.h" #include "net/gnrc/mac/types.h" +#include "shell.h" -int mac_cmd(int argc, char **argv) +static int _mac_cmd(int argc, char **argv) { if (argc < 2) { printf("usage: %s duty\n", argv[0]); @@ -50,3 +51,5 @@ int mac_cmd(int argc, char **argv) } return 0; } + +SHELL_COMMAND(mac, "get MAC protocol's internal information", _mac_cmd); diff --git a/examples/networking/gnrc_networking/gnrc_networking_mac/main.c b/examples/networking/gnrc_networking/gnrc_networking_mac/main.c index 05297ee34146..19def49dde10 100644 --- a/examples/networking/gnrc_networking/gnrc_networking_mac/main.c +++ b/examples/networking/gnrc_networking/gnrc_networking_mac/main.c @@ -28,15 +28,6 @@ #define MAIN_QUEUE_SIZE (8) static msg_t _main_msg_queue[MAIN_QUEUE_SIZE]; -extern int udp_cmd(int argc, char **argv); -extern int mac_cmd(int argc, char **argv); - -static const shell_command_t shell_commands[] = { - { "udp", "send data over UDP and listen on UDP ports", udp_cmd }, - { "mac", "get MAC protocol's internal information", mac_cmd }, - { NULL, NULL, NULL } -}; - int main(void) { /* we need a message queue for the thread running the shell in order to @@ -47,7 +38,7 @@ int main(void) /* start shell */ puts("All up, running the shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); /* should be never reached */ return 0; diff --git a/examples/networking/gnrc_networking/gnrc_networking_mac/udp.c b/examples/networking/gnrc_networking/gnrc_networking_mac/udp.c index afd2b6be6e34..1437848ac628 100644 --- a/examples/networking/gnrc_networking/gnrc_networking_mac/udp.c +++ b/examples/networking/gnrc_networking/gnrc_networking_mac/udp.c @@ -28,6 +28,7 @@ #include "net/gnrc/netif/hdr.h" #include "net/gnrc/udp.h" #include "net/gnrc/pktdump.h" +#include "shell.h" #include "timex.h" #include "utlist.h" #include "xtimer.h" @@ -149,7 +150,7 @@ static void stop_server(void) puts("Success: stopped UDP server"); } -int udp_cmd(int argc, char **argv) +static int _udp_cmd(int argc, char **argv) { if (argc < 2) { printf("usage: %s [send|server]\n", argv[0]); @@ -196,3 +197,5 @@ int udp_cmd(int argc, char **argv) } return 0; } + +SHELL_COMMAND(udp, "send data over UDP and listen on UDP ports", _udp_cmd); diff --git a/examples/networking/misc/lwm2m/Makefile.ci b/examples/networking/misc/lwm2m/Makefile.ci index bab3493af59e..a33f2aa1cafe 100644 --- a/examples/networking/misc/lwm2m/Makefile.ci +++ b/examples/networking/misc/lwm2m/Makefile.ci @@ -30,7 +30,6 @@ BOARD_INSUFFICIENT_MEMORY := \ maple-mini \ microbit \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/networking/misc/lwm2m/lwm2m_cli.c b/examples/networking/misc/lwm2m/lwm2m_cli.c index 9b9d63a39ecb..9b7cd1df9a76 100644 --- a/examples/networking/misc/lwm2m/lwm2m_cli.c +++ b/examples/networking/misc/lwm2m/lwm2m_cli.c @@ -22,6 +22,8 @@ #include "lwm2m_client_objects.h" #include "lwm2m_platform.h" +#include "shell.h" + #include "objects/common.h" #include "objects/device.h" #include "objects/security.h" @@ -159,7 +161,7 @@ static int _parse_lwm2m_light_cmd(int argc, char **argv) return 0; } -int lwm2m_cli_cmd(int argc, char **argv) +static int _cli_cmd(int argc, char **argv) { if (argc == 1) { goto help_error; @@ -192,3 +194,5 @@ int lwm2m_cli_cmd(int argc, char **argv) return 1; } + +SHELL_COMMAND(lwm2m, "Start LwM2M client", _cli_cmd); diff --git a/examples/networking/misc/lwm2m/main.c b/examples/networking/misc/lwm2m/main.c index f59e656c4b6b..1999dde72df1 100644 --- a/examples/networking/misc/lwm2m/main.c +++ b/examples/networking/misc/lwm2m/main.c @@ -31,11 +31,6 @@ static msg_t _shell_queue[SHELL_QUEUE_SIZE]; extern void lwm2m_cli_init(void); -extern int lwm2m_cli_cmd(int argc, char **argv); -static const shell_command_t my_commands[] = { - { "lwm2m", "Start LwM2M client", lwm2m_cli_cmd }, - { NULL, NULL, NULL } -}; int main(void) { @@ -44,7 +39,7 @@ int main(void) msg_init_queue(_shell_queue, SHELL_QUEUE_SIZE); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(my_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/examples/networking/misc/posix_sockets/Makefile.ci b/examples/networking/misc/posix_sockets/Makefile.ci index 8a8fa6637c96..7ec03bcde535 100644 --- a/examples/networking/misc/posix_sockets/Makefile.ci +++ b/examples/networking/misc/posix_sockets/Makefile.ci @@ -16,7 +16,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430h \ nrf51dk \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/networking/misc/posix_sockets/main.c b/examples/networking/misc/posix_sockets/main.c index de60a3bb139f..135833dfff53 100644 --- a/examples/networking/misc/posix_sockets/main.c +++ b/examples/networking/misc/posix_sockets/main.c @@ -26,13 +26,6 @@ #define MAIN_MSG_QUEUE_SIZE (4) static msg_t main_msg_queue[MAIN_MSG_QUEUE_SIZE]; -extern int udp_cmd(int argc, char **argv); - -static const shell_command_t shell_commands[] = { - { "udp", "send data over UDP and listen on UDP ports", udp_cmd }, - { NULL, NULL, NULL } -}; - int main(void) { /* a sendto() call performs an implicit bind(), hence, a message queue is @@ -42,7 +35,7 @@ int main(void) /* start shell */ puts("All up, running the shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); /* should be never reached */ return 0; diff --git a/examples/networking/misc/posix_sockets/udp.c b/examples/networking/misc/posix_sockets/udp.c index 4201fd822247..0731be841e83 100644 --- a/examples/networking/misc/posix_sockets/udp.c +++ b/examples/networking/misc/posix_sockets/udp.c @@ -38,6 +38,7 @@ #include "net/netif.h" /* for resolving ipv6 scope */ #endif /* SOCK_HAS_IPV6 */ +#include "shell.h" #include "thread.h" #define SERVER_MSG_QUEUE_SIZE (8) @@ -163,7 +164,7 @@ static int udp_start_server(char *port_str) return 0; } -int udp_cmd(int argc, char **argv) +static int _udp_cmd(int argc, char **argv) { if (argc < 2) { printf("usage: %s [send|server]\n", argv[0]); @@ -209,4 +210,6 @@ int udp_cmd(int argc, char **argv) } } +SHELL_COMMAND(udp, "send data over UDP and listen on UDP ports", _udp_cmd); + /** @} */ diff --git a/examples/networking/mqtt/asymcute_mqttsn/Makefile.ci b/examples/networking/mqtt/asymcute_mqttsn/Makefile.ci index 681d67cc4d13..de5192c86364 100644 --- a/examples/networking/mqtt/asymcute_mqttsn/Makefile.ci +++ b/examples/networking/mqtt/asymcute_mqttsn/Makefile.ci @@ -20,7 +20,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430h \ nrf51dk \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/networking/mqtt/asymcute_mqttsn/main.c b/examples/networking/mqtt/asymcute_mqttsn/main.c index 17c647fabe18..96f4b856c75c 100644 --- a/examples/networking/mqtt/asymcute_mqttsn/main.c +++ b/examples/networking/mqtt/asymcute_mqttsn/main.c @@ -269,6 +269,8 @@ static int _cmd_connect(int argc, char **argv) return _ok(req); } +SHELL_COMMAND(connect, "connect to MQTT-SN gateway", _cmd_connect); + static int _cmd_disconnect(int argc, char **argv) { (void)argc; @@ -288,6 +290,8 @@ static int _cmd_disconnect(int argc, char **argv) return _ok(req); } +SHELL_COMMAND(disconnect, "disconnect from MQTT-SN gateway", _cmd_disconnect); + static int _cmd_reg(int argc, char **argv) { if (argc < 2) { @@ -330,6 +334,8 @@ static int _cmd_reg(int argc, char **argv) return _ok(req); } +SHELL_COMMAND(reg, "register a given topic", _cmd_reg); + static int _cmd_unreg(int argc, char **argv) { if (argc < 2) { @@ -355,6 +361,8 @@ static int _cmd_unreg(int argc, char **argv) return 0; } +SHELL_COMMAND(unreg, "remove a topic registration [locally]", _cmd_unreg); + static int _cmd_pub(int argc, char **argv) { if (argc < 3) { @@ -399,6 +407,8 @@ static int _cmd_pub(int argc, char **argv) return _ok(req); } +SHELL_COMMAND(pub, "publish data", _cmd_pub); + static int _cmd_sub(int argc, char **argv) { if (argc < 2) { @@ -469,6 +479,8 @@ static int _cmd_sub(int argc, char **argv) return _ok(req); } +SHELL_COMMAND(sub, "subscribe to topic", _cmd_sub); + static int _cmd_unsub(int argc, char **argv) { if (argc < 2) { @@ -499,6 +511,8 @@ static int _cmd_unsub(int argc, char **argv) return _ok(req); } +SHELL_COMMAND(unsub, "unsubscribe from topic", _cmd_unsub); + static int _cmd_info(int argc, char **argv) { (void)argc; @@ -536,17 +550,7 @@ static int _cmd_info(int argc, char **argv) return 0; } -static const shell_command_t shell_commands[] = { - { "connect", "connect to MQTT-SN gateway", _cmd_connect }, - { "disconnect", "disconnect from MQTT-SN gateway", _cmd_disconnect }, - { "reg", "register a given topic", _cmd_reg }, - { "unreg", "remove a topic registration [locally]", _cmd_unreg }, - { "pub", "publish data", _cmd_pub }, - { "sub", "subscribe to topic", _cmd_sub }, - { "unsub", "unsubscribe from topic", _cmd_unsub }, - { "info", "print state information", _cmd_info }, - { NULL, NULL, NULL }, -}; +SHELL_COMMAND(info, "print state information", _cmd_info); int main(void) { @@ -559,7 +563,7 @@ int main(void) msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE); /* start shell */ char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); /* should be never reached */ return 0; diff --git a/examples/networking/mqtt/emcute_mqttsn/main.c b/examples/networking/mqtt/emcute_mqttsn/main.c index 0530b88d4ea7..e0bc2db3654f 100644 --- a/examples/networking/mqtt/emcute_mqttsn/main.c +++ b/examples/networking/mqtt/emcute_mqttsn/main.c @@ -110,6 +110,8 @@ static int cmd_con(int argc, char **argv) return 0; } +SHELL_COMMAND(con, "connect to MQTT broker", cmd_con); + static int cmd_discon(int argc, char **argv) { (void)argc; @@ -128,6 +130,8 @@ static int cmd_discon(int argc, char **argv) return 0; } +SHELL_COMMAND(discon, "disconnect from the current broker", cmd_discon); + static int cmd_pub(int argc, char **argv) { emcute_topic_t t; @@ -165,6 +169,8 @@ static int cmd_pub(int argc, char **argv) return 0; } +SHELL_COMMAND(pub, "publish something", cmd_pub); + static int cmd_sub(int argc, char **argv) { unsigned flags = EMCUTE_QOS_0; @@ -202,6 +208,8 @@ static int cmd_sub(int argc, char **argv) return 0; } +SHELL_COMMAND(sub, "subscribe topic", cmd_sub); + static int cmd_unsub(int argc, char **argv) { if (argc < 2) { @@ -228,6 +236,8 @@ static int cmd_unsub(int argc, char **argv) return 1; } +SHELL_COMMAND(unsub, "unsubscribe from topic", cmd_unsub); + static int cmd_will(int argc, char **argv) { if (argc < 3) { @@ -248,15 +258,7 @@ static int cmd_will(int argc, char **argv) return 0; } -static const shell_command_t shell_commands[] = { - { "con", "connect to MQTT broker", cmd_con }, - { "discon", "disconnect from the current broker", cmd_discon }, - { "pub", "publish something", cmd_pub }, - { "sub", "subscribe topic", cmd_sub }, - { "unsub", "unsubscribe from topic", cmd_unsub }, - { "will", "register a last will", cmd_will }, - { NULL, NULL, NULL } -}; +SHELL_COMMAND(will, "register a last will", cmd_will); int main(void) { @@ -276,7 +278,7 @@ int main(void) /* start shell */ char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); /* should be never reached */ return 0; diff --git a/examples/networking/mqtt/paho-mqtt/Makefile.ci b/examples/networking/mqtt/paho-mqtt/Makefile.ci index bf491e5b51bb..478563df14aa 100644 --- a/examples/networking/mqtt/paho-mqtt/Makefile.ci +++ b/examples/networking/mqtt/paho-mqtt/Makefile.ci @@ -26,7 +26,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/examples/networking/mqtt/paho-mqtt/main.c b/examples/networking/mqtt/paho-mqtt/main.c index 583db16f0787..46d8dc0877e2 100644 --- a/examples/networking/mqtt/paho-mqtt/main.c +++ b/examples/networking/mqtt/paho-mqtt/main.c @@ -112,6 +112,8 @@ static int _cmd_discon(int argc, char **argv) return res; } +SHELL_COMMAND(discon, "disconnect from the current broker", _cmd_discon); + static int _cmd_con(int argc, char **argv) { if (argc < 2) { @@ -189,6 +191,8 @@ static int _cmd_con(int argc, char **argv) return (ret > 0) ? 0 : 1; } +SHELL_COMMAND(con, "connect to MQTT broker", _cmd_con); + static int _cmd_pub(int argc, char **argv) { enum QoS qos = QOS0; @@ -220,6 +224,8 @@ static int _cmd_pub(int argc, char **argv) return rc; } +SHELL_COMMAND(pub, "publish something", _cmd_pub); + static int _cmd_sub(int argc, char **argv) { enum QoS qos = QOS0; @@ -261,6 +267,8 @@ static int _cmd_sub(int argc, char **argv) return ret; } +SHELL_COMMAND(sub, "subscribe topic", _cmd_sub); + static int _cmd_unsub(int argc, char **argv) { if (argc < 2) { @@ -281,15 +289,7 @@ static int _cmd_unsub(int argc, char **argv) return ret; } -static const shell_command_t shell_commands[] = -{ - { "con", "connect to MQTT broker", _cmd_con }, - { "discon", "disconnect from the current broker", _cmd_discon }, - { "pub", "publish something", _cmd_pub }, - { "sub", "subscribe topic", _cmd_sub }, - { "unsub", "unsubscribe from topic", _cmd_unsub }, - { NULL, NULL, NULL } -}; +SHELL_COMMAND(unsub, "unsubscribe from topic", _cmd_unsub); static unsigned char buf[BUF_SIZE]; static unsigned char readbuf[BUF_SIZE]; @@ -314,6 +314,6 @@ int main(void) MQTTStartTask(&client); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index d185707e1069..2cebdfe8646b 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -78,6 +78,7 @@ PSEUDOMODULES += event_timeout PSEUDOMODULES += event_timeout_ztimer PSEUDOMODULES += evtimer_mbox PSEUDOMODULES += fatfs_vfs_format +PSEUDOMODULES += fdcan PSEUDOMODULES += fmt_% PSEUDOMODULES += gcoap_forward_proxy PSEUDOMODULES += gcoap_forward_proxy_thread diff --git a/pkg/driver_cryptocell_310/doc.txt b/pkg/driver_cryptocell_310/doc.txt index 71a8804ef928..77e140d94fab 100644 --- a/pkg/driver_cryptocell_310/doc.txt +++ b/pkg/driver_cryptocell_310/doc.txt @@ -7,4 +7,12 @@ * @note The source of this package is not a git repository, but a zip file downloaded * from the Nordic Semiconductor software center. It is quite large and takes a * while to download. + * + * @warning The CryptoCell 310 peripheral on the nRF52840 MCU can only access data residing in RAM, + * not in ROM (see [nRF52840 Product Specification], Section 6.6.7). + * When using this driver as a backend for PSA Crypto API, API function will return + * `PSA_ERROR_DATA_INVALID` when provided input data resides in ROM. + * + * [nRF52840 Product Specification]: https://docs-be.nordicsemi.com/bundle/ps_nrf52840/attach/nRF52840_PS_v1.11.pdf + * */ diff --git a/pkg/driver_cryptocell_310/include/cryptocell_310_util.h b/pkg/driver_cryptocell_310/include/cryptocell_310_util.h index 540617ee08cf..c49e135f959f 100644 --- a/pkg/driver_cryptocell_310/include/cryptocell_310_util.h +++ b/pkg/driver_cryptocell_310/include/cryptocell_310_util.h @@ -23,10 +23,6 @@ extern "C" { #endif -#ifdef CPU_NRF52 -#define CHECK_POINTER_DMA_ACCESS(p) ((unsigned int)p >= 0x20000000 ? (unsigned int)p < 0x40000000 : 0) -#endif - /** * @brief Enable CryptoCell module and IRQs. * @@ -43,6 +39,17 @@ void cryptocell_310_enable(void); */ void cryptocell_310_disable(void); +/** + * @brief Check whether the given data resides in RAM + * + * Should be called on every const input that will be passed + * on to the CryptoCell peripheral. + */ +static inline bool cryptocell_310_data_within_ram(const uint8_t* data) +{ + return ((int)data >= CPU_RAM_BASE && (int)data < CPU_RAM_BASE + CPU_RAM_SIZE); +} + /** * @brief Enables CryptoCell module, IRQs and crypto libraries on nrf52840. * diff --git a/pkg/driver_cryptocell_310/psa_cryptocell_310/aes_common.c b/pkg/driver_cryptocell_310/psa_cryptocell_310/aes_common.c index c782cf09b713..df57af2023e2 100644 --- a/pkg/driver_cryptocell_310/psa_cryptocell_310/aes_common.c +++ b/pkg/driver_cryptocell_310/psa_cryptocell_310/aes_common.c @@ -40,6 +40,12 @@ psa_status_t cryptocell_310_common_aes_setup(SaSiAesUserContext_t *ctx, { SaSiAesUserKeyData_t key; + if (!cryptocell_310_data_within_ram(iv) || + !cryptocell_310_data_within_ram(key_buffer)) { + DEBUG("%s : cryptocell_310 data required to be in RAM.\n", RIOT_FILE_RELATIVE); + return PSA_ERROR_DATA_INVALID; + } + SaSiStatus ret = SaSi_AesInit(ctx, direction, mode, padding); if (ret != SASI_OK) { DEBUG("SaSi_AesInit failed with %s\n", cryptocell310_status_to_humanly_readable(ret)); @@ -77,6 +83,11 @@ psa_status_t cryptocell_310_common_aes_encrypt_decrypt(SaSiAesUserContext_t *ctx size_t length = input_length; *output_length = output_size; + if (!cryptocell_310_data_within_ram(input)) { + DEBUG("%s : cryptocell_310 data required to be in RAM.\n", RIOT_FILE_RELATIVE); + return PSA_ERROR_DATA_INVALID; + } + do { if (length > CC310_MAX_AES_INPUT_BLOCK) { size = CC310_MAX_AES_INPUT_BLOCK; diff --git a/pkg/driver_cryptocell_310/psa_cryptocell_310/cipher_chacha20.c b/pkg/driver_cryptocell_310/psa_cryptocell_310/cipher_chacha20.c index 58e35321fc36..99ee988d5872 100644 --- a/pkg/driver_cryptocell_310/psa_cryptocell_310/cipher_chacha20.c +++ b/pkg/driver_cryptocell_310/psa_cryptocell_310/cipher_chacha20.c @@ -42,9 +42,8 @@ psa_status_t psa_cipher_chacha20_encrypt(uint8_t *key_buffer, DEBUG("Peripheral ChaCha20 Cipher encryption"); psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - if (!CHECK_POINTER_DMA_ACCESS(key_buffer) || - !CHECK_POINTER_DMA_ACCESS(input) || - !CHECK_POINTER_DMA_ACCESS(output)) { + if (!cryptocell_310_data_within_ram(input)) { + DEBUG("%s : cryptocell_310 data required to be in RAM.\n", RIOT_FILE_RELATIVE); return PSA_ERROR_DATA_INVALID; } @@ -91,9 +90,8 @@ psa_status_t psa_cipher_chacha20_decrypt(uint8_t *key_buffer, DEBUG("Peripheral ChaCha20 Cipher decryption"); psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - if (!CHECK_POINTER_DMA_ACCESS(key_buffer) || - !CHECK_POINTER_DMA_ACCESS(input) || - !CHECK_POINTER_DMA_ACCESS(output)) { + if (!cryptocell_310_data_within_ram(input)) { + DEBUG("%s : cryptocell_310 data required to be in RAM.\n", RIOT_FILE_RELATIVE); return PSA_ERROR_DATA_INVALID; } diff --git a/pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_common.c b/pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_common.c index 7be3318a9121..d35fb9d1c9ed 100644 --- a/pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_common.c +++ b/pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_common.c @@ -85,6 +85,12 @@ psa_status_t cryptocell_310_common_ecc_sign(const uint8_t *priv_key, CRYS_ECPKI_UserPrivKey_t user_priv_key; CRYSError_t ret = 0; + if (!cryptocell_310_data_within_ram(priv_key) || + !cryptocell_310_data_within_ram(input)) { + DEBUG("%s : cryptocell_310 data required to be in RAM.\n", RIOT_FILE_RELATIVE); + return PSA_ERROR_DATA_INVALID; + } + rndGenerateVectFunc = CRYS_RND_GenerateVector; pDomain = (CRYS_ECPKI_Domain_t *)CRYS_ECPKI_GetEcDomain(domain); @@ -122,6 +128,13 @@ psa_status_t cryptocell_310_common_ecc_verify(const uint8_t *pub_key, CRYS_ECPKI_UserPublKey_t user_pub_key; CRYSError_t ret = 0; + if (!cryptocell_310_data_within_ram(pub_key) || + !cryptocell_310_data_within_ram(input) || + !cryptocell_310_data_within_ram(signature)) { + DEBUG("%s : cryptocell_310 data required to be in RAM.\n", RIOT_FILE_RELATIVE); + return PSA_ERROR_DATA_INVALID; + } + pDomain = (CRYS_ECPKI_Domain_t *)CRYS_ECPKI_GetEcDomain(domain); /** diff --git a/pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_ed25519.c b/pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_ed25519.c index f32d62c07e23..a5443755794c 100644 --- a/pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_ed25519.c +++ b/pkg/driver_cryptocell_310/psa_cryptocell_310/ecc_ed25519.c @@ -67,6 +67,11 @@ psa_status_t psa_derive_ecc_ed25519_public_key( const uint8_t *priv_key_buffer, CRYS_ECEDW_TempBuff_t tmp; CRYSError_t ret; + if (!cryptocell_310_data_within_ram(priv_key_buffer)) { + DEBUG("%s : cryptocell_310 data required to be in RAM.\n", RIOT_FILE_RELATIVE); + return PSA_ERROR_DATA_INVALID; + } + /* contains seed (private key), concatenated with public key */ uint8_t secret_key[CRYS_ECEDW_ORD_SIZE_IN_BYTES + CRYS_ECEDW_MOD_SIZE_IN_BYTES] = { 0x0 }; size_t secret_key_size = sizeof(secret_key); @@ -100,6 +105,13 @@ psa_status_t psa_ecc_ed25519_sign_message(const uint8_t *priv_key_buffer, CRYS_ECEDW_TempBuff_t tmp; CRYSError_t ret; + if (!cryptocell_310_data_within_ram(priv_key_buffer) || + !cryptocell_310_data_within_ram(pub_key_buffer) || + !cryptocell_310_data_within_ram(input)) { + DEBUG("%s : cryptocell_310 data required to be in RAM.\n", RIOT_FILE_RELATIVE); + return PSA_ERROR_DATA_INVALID; + } + if (input_length > (CRYS_HASH_UPDATE_DATA_MAX_SIZE_IN_BYTES - CRYS_ECEDW_SIGNATURE_BYTES)) { return PSA_ERROR_NOT_SUPPORTED; } @@ -140,6 +152,13 @@ psa_status_t psa_ecc_ed25519_verify_message(const uint8_t *key_buffer, CRYS_ECEDW_TempBuff_t tmp; CRYSError_t ret; + if (!cryptocell_310_data_within_ram(key_buffer) || + !cryptocell_310_data_within_ram(input) || + !cryptocell_310_data_within_ram(signature)) { + DEBUG("%s : cryptocell_310 data required to be in RAM.\n", RIOT_FILE_RELATIVE); + return PSA_ERROR_DATA_INVALID; + } + if (input_length > (CRYS_HASH_UPDATE_DATA_MAX_SIZE_IN_BYTES - CRYS_ECEDW_SIGNATURE_BYTES)) { return PSA_ERROR_NOT_SUPPORTED; } diff --git a/pkg/driver_cryptocell_310/psa_cryptocell_310/hashes_common.c b/pkg/driver_cryptocell_310/psa_cryptocell_310/hashes_common.c index e999ee011f20..b518dad916b3 100644 --- a/pkg/driver_cryptocell_310/psa_cryptocell_310/hashes_common.c +++ b/pkg/driver_cryptocell_310/psa_cryptocell_310/hashes_common.c @@ -48,6 +48,11 @@ psa_status_t cryptocell_310_common_hash_update(CRYS_HASHUserContext_t *ctx, size_t offset = 0; size_t size; + if (!cryptocell_310_data_within_ram(input)) { + DEBUG("%s : cryptocell_310 data required to be in RAM.\n", RIOT_FILE_RELATIVE); + return PSA_ERROR_DATA_INVALID; + } + do { if (input_length > CC310_MAX_HASH_INPUT_BLOCK) { size = CC310_MAX_HASH_INPUT_BLOCK; diff --git a/pkg/driver_cryptocell_310/psa_cryptocell_310/hmac.c b/pkg/driver_cryptocell_310/psa_cryptocell_310/hmac.c index 4bb691666f8b..0893dcec7114 100644 --- a/pkg/driver_cryptocell_310/psa_cryptocell_310/hmac.c +++ b/pkg/driver_cryptocell_310/psa_cryptocell_310/hmac.c @@ -21,6 +21,7 @@ #include "psa/crypto.h" #include "psa_error.h" +#include "cryptocell_310_util.h" #include "crys_hmac.h" #include "crys_hmac_error.h" @@ -40,6 +41,12 @@ psa_status_t psa_mac_compute_hmac_sha256(const psa_key_attributes_t *attributes, size_t required_mac_length = PSA_MAC_LENGTH(attributes->type, attributes->bits, PSA_ALG_SHA_256); + if (!cryptocell_310_data_within_ram(key_buffer) || + !cryptocell_310_data_within_ram(input)) { + DEBUG("%s : cryptocell_310 data required to be in RAM.\n", RIOT_FILE_RELATIVE); + return PSA_ERROR_DATA_INVALID; + } + if (mac_size < required_mac_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } diff --git a/pkg/lwip/Makefile b/pkg/lwip/Makefile index 19da1f5ee0f5..e4b921fd59b7 100644 --- a/pkg/lwip/Makefile +++ b/pkg/lwip/Makefile @@ -1,7 +1,7 @@ PKG_NAME=lwip PKG_URL=https://github.com/lwip-tcpip/lwip.git -# lwIP v2.2.0 -PKG_VERSION=07a0dec3d4fa08ec332e5c297c40899ae6c727c6 +# lwIP v2.2.1 +PKG_VERSION=77dcd25a72509eb83f72b033d219b1d40cd8eb95 PKG_LICENSE=BSD-3-Clause include $(RIOTBASE)/pkg/pkg.mk diff --git a/release-notes.txt b/release-notes.txt index 693ade841f4b..366a86f938eb 100644 --- a/release-notes.txt +++ b/release-notes.txt @@ -1,3 +1,517 @@ +RIOT-2025.01 - Release Notes +============================ +RIOT is a multi-threading operating system which enables soft real-time +capabilities and comes with support for a range of devices that are typically +found in the Internet of Things: 8-bit and 16-bit microcontrollers as well as +light-weight 32-bit processors. + +RIOT is based on the following design principles: energy-efficiency, soft +real-time capabilities, small memory footprint, modularity, and uniform API +access, independent of the underlying hardware (with partial POSIX compliance). + +RIOT is developed by an international open-source community which is +independent of specific vendors (e.g. similarly to the Linux community) and is +licensed with a non-viral copyleft license (LGPLv2.1), which allows indirect +business models around the free open-source software platform provided by RIOT. + + +About this release +================== + +The 2025.01 release includes: + +More work done to update the legacy `netdev` API to its new version `new_netdev_api` +(#20978, #21012, #21015, #21016, #21020, #21028, #21091, #20991). This means +that if you are still using the legacy `netdev` API, start thinking about +updating! + +We documented the community processes in a `GOVERNANCE.md` file. +This new file now clearly states all previously undocumented community procedures and +governance, and defines community roles, to further our goals of openness and transparency +within the community. + +We also added the `same51-curiosity-nano` board along with some configuration +improvements "across the board" :wink:. + +144 pull requests, composed of 280 commits, have been merged since the +last release, and 0 issues have been solved. 32 people contributed with +code in 65 days. 665 files have been touched with 75661 (+) insertions and +6329 deletions (-). + + +Notations used below +==================== + + + means new feature/item + * means modified feature/item + - means removed feature/item + + +New features and changes +======================== + +Core +---- + ++ core/cib: add const to cib_peek() (#21130) ++ core/mutex: add `mutex_init_locked()` (#20954) + +System Libraries +---------------- + ++ sys/posix/pthread: Add pthread_attr_getstack and + pthread_attr_setstack (#20934) ++ sys/stdio_nimble: add version note to README (#21085) ++ sys/stdio_uart: add stdio_clear_stdin (#19837) +* suit: move CoAP endpoints to the example (#21045) +* sys/chunked_ringbuffer: discard stale chunk when starting a new one (#21073) +* sys/psa_crypto: split algorithm definitions (#20906) +* sys/psa_crypto: Update key headers (#21046) +* sys/psa_crypto: one-shot Chacha20 support (#20720) +* sys/shell: cmds_json builtin command (#20964) +* sys/shell: reduce overhead of XFA shell commands (#20958) +* sys/stdio: stdio_available is always false with missing stdin module (#21040) +* sys/usb: Use luid_base for stable USB serials (#20944) +* sys/usb_cdc_acm_stdio: only submit and flush for non-empty buffer (#20986) +* treewide: Update Rust dependencies, adding SPI and UART support (#21133) +* usbus/cdc_ecm: port to netdev_new_api (#21028) + +Networking +---------- + ++ gnrc/ipv6_auto_subnets: add option to derive subnet prefix from EUI (#21080) ++ sys/event: add assertion that event has a handler (#20847) ++ sys/net/gnrc_pktbuf_static: add double free detection (#20974) +* gnrc_netif: netdev_new_api implies TX end irq, no need to check it (#20993) +* nanocoap/sock: re-try if wrong block was received (#20952) +* sys/net/gcoap: get rid of API abuse (#21125) +* sys/net/gcoap: reduce insanity of hack (#20945) +* sys/net/gnrc_pktbuf: detect use after free if canary is in metadata (#21000) +* sys/net/nanocoap: flush stale responses before sending request (#21122) +* sys: net: dns: use Quad9 resolver (#21120) + +Packages +-------- + ++ Feature/wakaama update on new version (#20930) +* pkg/relic: bump version to 0.7.0 (#21134) + +Boards +------ + ++ boards/same51-curiosity-nano: add support for the board (#21111) ++ cpu/saml21: add compatibility headers for vendor files migration (#20850) ++ feather-nrf52840: add config for NeoPixel LED (#21017) ++ saul: initial import of saul_bat_voltage module (#21018) +* Arduino support layer: several fixes (#21039) +* boards/adafruit-metro-m4-express: Minor improvements (#21041) +* boards/nrf52*dk: Enable Pinreset after Flashing (#20965) +* cpu/nRF52: Always recover Device before Flashing (#20970) +* makefiles/serial: better MOST_RECENT_PORT=1 for CDC ACM (#20951) + +CPU +--- + ++ dist/tools/esptools: add support for installing esp8266 toolchain (#21094) ++ sys/string_utils: add string_writer helper (#20843) +* cpu/cc2538: use RX FIFO count to determine CRC OK location (#20956) +* cpu/cortexm_common: Make cpu.h IWYU clean (#21050) +* cpu/esp32/stdio_usb_serial_jtag: Fix to ESP32 stdio usb serial + hanging if it receives data too quickly (#20972) +* cpu/sam0_common: flashpage: disable cache while writing (#21043) +* netdev_tap: port to `netdev_new_api` (#21015) + +Device Drivers +-------------- + +* drivers/atwinc15x0: port to `netdev_new_api` (#21020) +* drivers/dose: fix poweroff (#21074) +* drivers/dose: port to netdev_new_api (#20991) +* drivers/ethos: port to netdev_new_api (#21016) +* drivers/periph_init: initialize watchdog first (#21025) +* drivers/slipdev: implement NETDEV_EVENT_TX_COMPLETE event (#20975) +* drivers/slipdev: port to netdev_new_api (#20978) +* drivers/ws281x: esp32 neopixel driver to set the rmt symbol high/low + lengths at init instead of every write (#21068) + +Documentation +------------- + ++ boards/nucleo-l073rz: add MCU table to doc page (#21102) ++ boards/nucleo-l433rc: add pinout to documentation page (#20947) ++ examples: add TCP echo server & client from documentation (#16739) ++ pkg/u8g2: add to the displays doc group (#20953) ++ README.md: add references to related projects (#21052) ++ README.md: add Section Collaboration (#21078) +* doc: Improvements around Code of Conduct (#21071) +* doc: move "managing a release" from wiki (#21065) +* MAINTAINING.md/doc: move links from wiki to doc (#21066) +* sys/net/app/cord: update doc (#20921) +* GOVERNANCE.md: remove “Community Processes” in favor of “GOVERNANCE.md” + (#21067) +* CODING_CONVENTIONS.md: bump minimum Python version (#21124) +* MAINTAINING.md: point to new auto-generated maintainer list (#21069) +* README: Rephrase forum into more generic help (#20413) + +Build System / Tooling +---------------------- + ++ Examples: Add proper Table of Contents (#20957) +* Build system: support for application subfolders (#20024) +* check_in_readme.sh: tell dev _which_ README.md (#21044) +* dist/tools/bmp: improve compatibility (#21107) +* makefiles: select default prng _after_ recursive dependency + resolution (#21060) + +Testing +------- + +* sys/ztimer: mention ztimer_auto_adjust in relevant places (#21003) +* tests/build_system/xfa: improve test coverage (#20959) +* tests/core/cond_order/: calling cond signal and broadcast without + waiting threads (#21030) +* tests/core/thread_msg: lower thread priority for consistent output + order (#20989) +* tests/cpu/mpu*: exclude boards using highlevel_stdio (#20990) +* tests/net/nanocoap_cli: make use of XFA for shell commands (#20961) +* tests/periph/uart: minor improvements (#21009) +* tests/sys/events: test if event_timeout_is_pending returns false (#21032) +* tests/sys/shell: skip reboot for boards using highlevel_stdio (#20988) +* tests/sys/shell: use default terminal instead of socat (#21058) + +API Changes +----------- + ++ CODING_CONVENTIONS.md: Add IWYU policy (#20570) ++ sys/net/nanocoap: add and use coap_get_response_hdr_len() (#20950) +* drivers/netdev: revise return values of `.confirm_send()` (#20995) +* drivers/periph_gpio: let gpio_read() return bool (#20936) +* netdev_new_api: allow `.send()` to return > 0 to signal synchronos + send (#21012) +* sys/fido2: follow up continued (#18663) +* sys/luid: luid_custom() use fixed width int (#20943) + +Uncategorized +------------- +* .clang-format: Set ColumnLimit to 0 (#20963) + +And 20 minor changes. + + +Bug fixes (33) +============== + +* core/msg: re-enable IRQs before printing for highlevel_stdio (#21047) +* cpu/samd5x/periph_can: fix RX (#21184) +* cpu/sam0_common/periph_adc: add work around for errata 2.1.6 (#20994) +* boards/stm32f429i-disc1: fix touch screen axis (#21007) +* boards/wemos-zero: fix Arduio I/O Map (#21004) +* build system: error on conflicting features (#21013) +* build_system/xfa: change API to fix alignment (#20960) +* core/sched.c: fix _runqueue_pop() removing wrong thread (#20938) +* cpu/cc2538: mask length byte before checking CRC (#20998) +* cpu/sam0_common/periph_gpio_ll: fix gpio_get_port() and + gpio_ll_query_conf() (#20999) +* cpu/stm32/eth: fix and improve ETH defines (#21072) +* cpu/stm32/periph/timer: prevent spurious IRQs (#20926) +* cpu/stm32l0,l1: Fix ADC initialization order (#21011) +* dist/tools/esptool: fix the all target (#21129) +* doxygen/Makefile: fix `make latex` and `make clean` (#21090) +* drivers/at86rf215: return ENETDOWN when interface is down (#21031) +* gcoap/forward_proxy: handle timeout case (#20915) +* gnrc_netif: fix double free with netdev_new_api & gnrc_netif_pktq (#20976) +* gnrc_netif: fix packet leak with gnrc_netif_pktq & netdev_new_api (#20983) +* gnrc_netif: fix timeout in + `gnrc_netif_ipv6_wait_for_global_address()` (#21137) +* pkg/lwip: fix adaption to API change of netdev_new_api (#21091) +* pkg/wakaama/client_connection: destroy unused DTLS sessions (#21035) +* pkg/wakaama: Fix usages of `lwm2m_uri_t` and ISPO sensor (#21034) +* sys/event: fix race in event_wait_multi() (#21092) +* sys/net/gnrc/tcp: fix gnrc_tcp_open() netif handling (#20977) +* sys/net/nanocoap: fix `coap_build_reply_header()` (#20949) +* sys/net/nanocoap: fix buffer overflow in separate response handling (#21075) +* sys/net/nanocoap: fix coap_get_total_hdr_len() (#20946) +* sys/net/nanocoap: Fix sending bogus separate responses (#21076) +* sys/ztimer: implement ztimer_mbox_get_timeout() and use it to fix + race in gnrc_sock_recv() (#21113) +* tests/periph/selftest_shield: fix invalid calls to timer_init() + + GPIO IRQ tests (#21006) +* tests/periph/selftest_shield: Fix UART test (#21042) +* tests/sys/shell: improve test automation (#21114) +* tests/sys/shell: make test script more robust (#21036) +* tests/sys/ztimer_mbox_get_timeout: Fix flakiness (#21127) + + +Known issues +============ + +Network related issues (55) +--------------------------- + +* 6lo: RIOT does not receive packets from Linux when short_addr is set (#11033) +* Address registration handling inappropriate (#15867) +* app/netdev: application stops working after receiving frames with + assertion or completely without error (#8271) +* at86rf2xx: Dead lock when sending while receiving (#8242) +* cpu/esp8266: Tracking open problems of esp_wifi netdev driver (#10861) +* DHCPv6 client: Handling of NotOnLink incorrect (#20349) +* dist/tools/sliptty/start_network.sh: IPv6 connectivity is broken on + PC (#14689) +* driver/mrf24j40: blocks shell input with auto_init_gnrc_netif (#12943) +* drivers/at86rf215: Incorrect channel number set for subGHz (#15906) +* DTLS examples cannot send message to localhost (#14315) +* Emcute cannot create a double-byte name (#12642) +* ethernet: Missing multicast addr assignment (#13493) +* ethos: fails to respond to first message. (#11988) +* ethos: Unable to handle fragmented IPv6 packets from Linux kernel (#12264) +* example/gnrc_border_router cannot answer after some time (#19578) +* examples/cord_ep: Dead lock when (re-)registering in callback + function (#12884) +* examples/gnrc_border_router: esp_wifi crashes on disconnect (#14679) +* Forwarding a packet back to its link layer source should not be + allowed (#5051) +* gcoap example request on tap I/F fails with NIB issue (#8199) +* gcoap: Suspected crosstalk between requests (possible NULL call) (#14390) +* Global IPv6 addresses remain deprecated after receiving RA (#19846) +* gnrc ipv6: multicast packets are not dispatched to the upper layers (#5230) +* gnrc/ipv6: "invalid payload length" - corrupted IPv6 header when + ENABLE_DEBUG=1 in mbox.c (#20390) +* gnrc_border_router stops routing after a while (#16398) +* gnrc_border_router: Kconfig and C disagree about number of addresses + per interface (#19947) +* gnrc_icmpv6_echo: flood-pinging another node leads to leaks in own + packet buffer (#12565) +* gnrc_ipv6: Multicast is not forwarded if routing node listens to the + address (#4527) +* gnrc_netif_pktq leaks memory (#17924) +* gnrc_rpl: missing bounds checks in _parse_options (#16085) +* gnrc_rpl: nib route not updated when topology / DODAG changes (#17327) +* gnrc_rpl: old routes are not deleted (#19423) +* gnrc_rpl: takes unusually long time to start routing packets (#19147) +* gnrc_sock_udp: Possible Race condition on copy in application buffer (#10389) +* gnrc_tcp: gnrc_tcp_recv() never generates -ECONNABORTED (#17896) +* gomach: Resetting netif with cli doesn't return (#10370) +* ieee802154_submac: IPv6 fragmentation broken (#16998) +* LoRaWan node ISR stack overflowed (#14962) +* LWIP TCP Communication Error (#19676) +* lwip_sock_tcp / sock_async: received events before calling + sock_accept() are lost due to race condition. (#16303) +* Missing drop implementations in netdev_driver_t::recv (#10410) +* Neighbor Discovery not working after router reboot when using SLAAC (#11038) +* netdev_ieee802154: Mismatch between radio ll address and in memory + address (#10380) +* nrf52: Not able to add global or ULA address to interface (#13280) +* nrfmin: communication not possible after multicast ping with no + interval (#11405) +* ping6 is failing when testing with cc2538dk (#13997) +* pkg/tinydtls: auxiliary data API does not work for async sockets (#16054) +* pkg/tinydtls: DTLS handshake does not work (#19595) +* Removing a TNT global address then adding a new one does not work (#20318) +* samr30 xpro doesn't seem to use its radio ok (#12761) +* scan-build errors found during 2019.07 testing (#11852) +* stale border router does not get replaced (#12210) +* test/lwip: enabling both, IPv4 and IPv6, results in unexpected + behavior (#18097) +* tests/lwip: does not compile for IPv4 on 6LoWPAN-based boards. (#17162) +* two nodes livelock sending neighbor solicitations back and forth + between each other (#16670) +* xbee: setting PAN ID sometimes fails (#10338) + +Timer related issues (7) +------------------------ + +* misc issues with tests/trickle (#9052) +* MSP430: periph_timer clock config wrong (#8251) +* periph/timer: `timer_set()` underflow safety check (tracking issue) (#13072) +* periph_timer: systematic proportional error in timer_set (#10545) +* saml21 system time vs rtc (#10523) +* stm32_common/periph/rtc: current implementation broken/poor accuracy (#8746) +* sys/newlib: gettimeofday() returns time since boot, not current wall + time. (#9187) + +Drivers related issues (11) +--------------------------- + +* at86rf2xx: Simultaneous use of different transceiver types is not + supported (#4876) +* cpu/msp430: GPIO driver doesn't work properly (#9419) +* examples/dtls-wolfssl not working on pba-d-01-kw2x (#13527) +* fail to send data to can bus (#12371) +* mdt_erase success, but vfs_format resets board (esp32-heltec- + lora32-v2) (#14506) +* periph/spi: Switching between CPOL=0,1 problems on Kinetis with + software CS (#6567) +* periph: GPIO drivers are not thread safe (#4866) +* PWM: Single-phase initialization creates flicker (#15121) +* STM32: SPI clock not returning to idle state and generating + additional clock cycles (#11104) +* TCP client cannot send read only data (#16541) +* tests/periph_flashpage: unexpected behavior on nucleo-l4r5zi (#17599) + +Native related issues (5) +------------------------- + +* examples/micropython: floating point exception while testing on + native (#15870) +* native getchar is blocking RIOT (#16834) +* native not float safe (#495) +* native: tlsf: early malloc will lead to a crash (#5796) +* ztimer doesn't wake up on native if the pm_layered module is used (#21083) + +Other platforms related issues (13) +----------------------------------- + +* Failing tests on FE310 (Hifive1b) (#13086) +* [TRACKING] Fixes for automatic tests of ESP32 boards. (#12763) +* boards/hifive1: flashing issue (#13104) +* cpu/sam0: flashpage write / read cycle produces different results + depending on code layout in flash (#14929) +* esp32-wroom-32: tests/netstats_l2 failing sometimes (#14237) +* examples/gnrc_border_router: esp_wifi_init failed with return value + 257 on ESP32-C3 with nimble_rpble (#19319) +* gcoap/esp8266: Stack overflow with gcoap example (#13606) +* Interrupt callback function is instantly called on samd51 after + setting it from within interrupt callback function (#19861) +* MPU doesn't work on cortex-m0+ (#14822) +* newlib-nano: Printf formatting does not work properly for some + numeric types (#1891) +* periph_timer: Test coverage & broken on STM32F767ZI (#15072) +* riscv: ISR stack is too small for ENABLE_DEBUG in core files (#16395) +* stm32f7: Large performance difference between stm32f746 and stm32f767 (#14728) + +Build system related issues (6) +------------------------------- + +* `buildtest` uses wrong build directory (#9742) +* Build dependencies - processing order issues (#9913) +* dist/tools/cppcheck/cppchck.sh: errors when running with Cppcheck + 1.89 (#12771) +* EXTERNAL_MODULE_DIRS silently ignores non-existent entries (#17696) +* make: ccache leads to differing binaries (#14264) +* make: use of immediate value of variables before they have their + final value (#8913) + +Other issues (70) +----------------- + +* 2023.04 release bug tracking (#19469) +* [tracking] Bugs found by the peripheral selftest (#20071) +* [Tracking] Fix failures of test-on-iotlab (#20791) +* [TRACKING] sys/shell refactoring. (#12105) +* [tracking] unnecessary use of floating point arithmetic (#19614) +* _NVIC_SystemReset stuck in infinite loop when calling pm_reboot + through shell after flashing with J-Link (#13044) +* `make term` no longer works with JLinkExe v6.94 (#16022) +* at86rf215 stops receiving until sending a packet (#19653) +* b-l072z-lrwan1: tests/ztimer_overhead: test failure (#19224) +* backport_pr: Only works for when fork is in user (not in + organization) (#18486) +* benchmark_udp: hammering with low interval causes issues (#16808) +* boards/esp32-wroom-32: tests/mtd_raw flakey (#16130) +* build system: race condition when building and running an app for + `native` (#20948) +* Builds fail when different execstack options are around in objects (#18522) +* Can't build relic with benchmarks or tests (#12897) +* CC2538-CC2592EM has a very weak transmit power (#17543) +* CC2538DK board docs: broken links (#12889) +* cpp: Exception handling undefined (#17523) +* cpu/stm32: some tests are failing on CM33 (l5, u5) (#17439) +* doc/boards: information concerning access to RIOT shell (#17453) +* doc/LOSTANDFOUND: not rendered as expected (#17063) +* edbg: long lines flooded over serial become garbled (#14548) +* examples / tests: LoRa tests fail on platforms that don't support + LoRa (#14520) +* examples/gcoap: client broken (#19379) +* feather-m0: `make flash` reports "device unsupported" (#17722) +* flashing issue on frdm-k64f (#15903) +* frdm-k22f failing tests/periph_flashpage (#17057) +* frdm-k22f fails tests/periph_timer (#19543) +* Freeze into semtech_loramac_send call (pkg/semtech-loramac) (#18790) +* gcoap: gcoap_req_send and related should return negative for errors (#19393) +* gnrc_ipv6_nib: Neighbor Solicitation ping-pong (#18164) +* I2C not working under RIOT with U8G2 pkg (#16381) +* ieee802154_security: Nonce is reused after reboot (#16844) +* kconfiglib.py choice override of menuconfig bug (#19069) +* lwip: drivers/at86rf2xx/at86rf2xx_netdev.c invalid state during TCP + disconnect (#17209) +* lwip: invalid state transition on ieee802154_submac users (#17208) +* Making the newlib thread-safe (#4488) +* mcuboot: flashes but no output (#17524) +* MTD is confusing (#17663) +* nanocoap: incomplete response to /.well-known/core request (#10731) +* Order of auto_init functions (#13541) +* periph_rtt: rtt_set_alarm() blocks IRQ for 80 plus usec on STM32 (#19520) +* pkg/tinydtls: Multiple issues (#16108) +* Potential race condition in compile_and_test_for_board.py (#12621) +* RIOT is saw-toothing in energy consumption (even when idling) (#5009) +* riotboot: ECC faults (eg. in STM32L5 or STM32WB) not handled + gracefully (#17874) +* rust-gcoap example is incompatible with littlefs2 (#17817) +* Samr30/gpio: Erasing then write mux can generate spurious IRQ (#19993) +* samr34-xpro: some tests failing (#19223) +* sock_dtls: unable to send big messages (#17996) +* spurious IRQs in `periph_timer` (#18976) +* stdio_ethos: infinite shell loop (#17972) +* stdio_tinyusb_cdc_acm hangs with picolibc (#19277) +* STM32 Nucleo boards improperly clocked (#19778) +* STM32F4-discovery + mrf24j40 not working (#19711) +* sys/riotboot: documentation issues (#11243) +* sys/usb/usbus/cdc/ecm: interface thread blocked when connected host + interface is down (#21098) +* tests/lwip target board for python test is hardcoded to native (#6533) +* tests/periph_flashpage: failing on stm32l475ve (#17280) +* tests/pkg/relic is failing on samr21-xpro when built using llvm (#19903) +* tests/pkg_libhydrogen: test fails on master for the samr21-xpro with + LLVM (#15066) +* tests/pkg_libschc: Failing test_reassemble_success_ack_always (#19445) +* tests/test_tools: test fails while testing on samr21-xpro/iotlab-m3 (#15888) +* tests: broken with stdio_rtt if auto_init is disabled (#13120) +* tests: some tests don't work with `newlib` lock functions. (#12732) +* Types in `byteorder.h` need a cleanup (#14737) +* USB identifiers with funny characters create mojibake (#17776) +* usbus/msc: wrong error handling and behavior after usb reset (#19478) +* Use of multiple CAN bus on compatible boards (#14801) +* ztimer is incompatible with real-time requirements (#18883) + +There are 167 known issues in this release + +Fixed Issues since the last release (2024.10) +============================================= + +* cpu/nrf52: Add Make Option to Enable Pinreset (#20775) + +1 fixed issues since last release (2024.10) + + +Acknowledgements +================ +We would like to thank all companies that provided us with hardware for porting +and testing RIOT. Further thanks go to companies and institutions that +directly sponsored development time. And finally, big thanks to all of you +contributing in so many different ways to make RIOT worthwhile! + + +More information +================ +http://www.riot-os.org + + +Matrix and Forum +================ +* Join the RIOT Matrix room at: #riot-os:matrix.org +* Join the RIOT Forum at: forum.riot-os.org + + +License +======= +* The code developed by the RIOT community is licensed under the GNU Lesser + General Public License (LGPL) version 2.1 as published by the Free Software + Foundation. +* Some external sources and packages are published under a separate license. + +All code files contain licensing information. + + RIOT-2024.10 "FlexTape" - Release Notes ============================ RIOT is a multi-threading operating system which enables soft real-time diff --git a/sys/Kconfig b/sys/Kconfig index 4573def28c14..8052d8e1f037 100644 --- a/sys/Kconfig +++ b/sys/Kconfig @@ -7,6 +7,7 @@ menu "System" rsource "auto_init/Kconfig" +rsource "can/Kconfig" rsource "chunked_ringbuffer/Kconfig" rsource "congure/Kconfig" rsource "debug_irq_disable/Kconfig" diff --git a/sys/Makefile.dep b/sys/Makefile.dep index 00afb08a25ee..db8cef9c2a27 100644 --- a/sys/Makefile.dep +++ b/sys/Makefile.dep @@ -529,6 +529,10 @@ ifneq (,$(filter nanocoap_server_auto_init,$(USEMODULE))) USEMODULE += nanocoap_server endif +ifneq (,$(filter nanocoap_server_observe,$(USEMODULE))) + USEMODULE += nanocoap_server_separate +endif + ifneq (,$(filter nanocoap_server_separate,$(USEMODULE))) USEMODULE += nanocoap_server USEMODULE += sock_aux_local diff --git a/sys/auto_init/can/auto_init_periph_can.c b/sys/auto_init/can/auto_init_periph_can.c index b8314406818f..3fed0abc6e86 100644 --- a/sys/auto_init/can/auto_init_periph_can.c +++ b/sys/auto_init/can/auto_init_periph_can.c @@ -48,6 +48,9 @@ void auto_init_periph_can(void) { candev_dev[i].rx_inactivity_timeout = candev_params[i].rx_inactivity_timeout; candev_dev[i].tx_wakeup_timeout = candev_params[i].tx_wakeup_timeout; #endif +#ifdef MODULE_FDCAN + candev_dev[i].loop_delay = candev_params[i].loop_delay; +#endif can_device_init(_can_stacks[i], CANDEV_STACKSIZE, CANDEV_BASE_PRIORITY + i, candev_params[i].name, &candev_dev[i]); diff --git a/sys/can/Kconfig b/sys/can/Kconfig new file mode 100644 index 000000000000..6897449f73cc --- /dev/null +++ b/sys/can/Kconfig @@ -0,0 +1,36 @@ +menu "CAN" + depends on USEMODULE_CAN || USEMODULE_FDCAN + +menu "FD CAN" + +config FDCAN_DEVICE_SET_TRANSCEIVER_LOOP_DELAY + depends on USEMODULE_FDCAN + bool "FD CAN transceiver loop delay" + default n + help + Allow to set FD CAN Transceiver loop delay. + +config FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY + depends on FDCAN_DEVICE_SET_TRANSCEIVER_LOOP_DELAY + int "FD CAN transceiver loop delay value" + range 0 1000 + default 0 + help + This parameter defines the loop delay introduced by the CAN transceiver + during transmission. The loop delay represents the time taken for the + transmitted signal to be looped back to the CAN controller. This delay + is introduced by the physical transceiver circuitry and may vary + depending on the transceiver model and other physical factors. + + The value is typically measured in nanoseconds and should be set + according to the specifications provided by the transceiver manufacturer. + A higher loop delay can affect the timing of CAN message transmissions + and may need to be adjusted in systems with tight timing requirements. + + If unsure, leave this value as 0 or refer to the hardware documentation + for the correct delay value. + + +endmenu # FD CAN + +endmenu # CAN diff --git a/sys/can/conn/raw.c b/sys/can/conn/raw.c index d2207136e11b..f836d52c5436 100644 --- a/sys/can/conn/raw.c +++ b/sys/can/conn/raw.c @@ -122,7 +122,7 @@ static void _tx_conf_timeout(void *arg) mbox_try_put(&conn->mbox, &msg); } -int conn_can_raw_send(conn_can_raw_t *conn, const struct can_frame *frame, int flags) +int conn_can_raw_send(conn_can_raw_t *conn, const can_frame_t *frame, int flags) { assert(conn != NULL); @@ -206,7 +206,7 @@ static void _rx_timeout(void *arg) mbox_try_put(&conn->mbox, &msg); } -int conn_can_raw_recv(conn_can_raw_t *conn, struct can_frame *frame, uint32_t timeout) +int conn_can_raw_recv(conn_can_raw_t *conn, can_frame_t *frame, uint32_t timeout) { assert(conn != NULL); diff --git a/sys/can/device.c b/sys/can/device.c index eac1cccbc0c2..7a654cc4e233 100644 --- a/sys/can/device.c +++ b/sys/can/device.c @@ -35,6 +35,16 @@ #define ENABLE_DEBUG 0 #include "debug.h" +#ifdef MODULE_FDCAN +/** + * The loop delay in CAN, especially in CAN FD with bitrate switching, affects synchronization due to increased data rates. + * The unit is nanoseconds. + */ +#ifndef CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY +#error "CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY must be defined. This property can be found in the datasheet of the CAN transceiver in use. The unit is nanoseconds." +#endif /* CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY */ +#endif /* MODULE_FDCAN */ + #ifndef CAN_DEVICE_MSG_QUEUE_SIZE #define CAN_DEVICE_MSG_QUEUE_SIZE 64 #endif @@ -52,7 +62,7 @@ static int power_down(candev_dev_t *candev_dev); static void _can_event(candev_t *dev, candev_event_t event, void *arg) { msg_t msg; - struct can_frame *frame; + can_frame_t *frame; can_pkt_t *pkt; candev_dev_t *candev_dev = dev->isr_arg; @@ -78,13 +88,13 @@ static void _can_event(candev_t *dev, candev_event_t event, void *arg) case CANDEV_EVENT_TX_CONFIRMATION: DEBUG("_can_event: CANDEV_EVENT_TX_CONFIRMATION\n"); /* frame pointer in arg */ - pkt = container_of((struct can_frame *)arg, can_pkt_t, frame); + pkt = container_of((can_frame_t *)arg, can_pkt_t, frame); can_dll_dispatch_tx_conf(pkt); break; case CANDEV_EVENT_TX_ERROR: DEBUG("_can_event: CANDEV_EVENT_TX_ERROR\n"); /* frame pointer in arg */ - pkt = container_of((struct can_frame *)arg, can_pkt_t, frame); + pkt = container_of((can_frame_t *)arg, can_pkt_t, frame); can_dll_dispatch_tx_error(pkt); break; case CANDEV_EVENT_RX_INDICATION: @@ -93,7 +103,7 @@ static void _can_event(candev_t *dev, candev_event_t event, void *arg) pm_reset(candev_dev, candev_dev->rx_inactivity_timeout); #endif /* received frame in arg */ - frame = (struct can_frame *) arg; + frame = (can_frame_t *) arg; can_dll_dispatch_rx_frame(frame, candev_dev->pid); break; case CANDEV_EVENT_RX_ERROR: @@ -236,6 +246,13 @@ static void *_can_device_thread(void *args) candev_dev->ifnum = can_dll_register_candev(candev_dev); +#if defined(MODULE_FDCAN) + if (candev_dev->loop_delay == 0) { + candev_dev->loop_delay = CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY; + } + dev->loop_delay = candev_dev->loop_delay; +#endif + dev->driver->init(dev); power_up(candev_dev); diff --git a/sys/can/dll.c b/sys/can/dll.c index d1ea7737358b..8c86184c5f66 100644 --- a/sys/can/dll.c +++ b/sys/can/dll.c @@ -79,7 +79,7 @@ int _send_pkt(can_pkt_t *pkt) return handle; } -int raw_can_send(int ifnum, const struct can_frame *frame, kernel_pid_t pid) +int raw_can_send(int ifnum, const can_frame_t *frame, kernel_pid_t pid) { can_pkt_t *pkt; @@ -102,7 +102,7 @@ int raw_can_send(int ifnum, const struct can_frame *frame, kernel_pid_t pid) } #ifdef MODULE_CAN_MBOX -int raw_can_send_mbox(int ifnum, const struct can_frame *frame, mbox_t *mbox) +int raw_can_send_mbox(int ifnum, const can_frame_t *frame, mbox_t *mbox) { can_pkt_t *pkt; @@ -288,7 +288,7 @@ int raw_can_free_frame(can_rx_data_t *frame) if (!frame) { return 0; } - int ret = can_router_free_frame((struct can_frame *)frame->data.iov_base); + int ret = can_router_free_frame((can_frame_t *)frame->data.iov_base); can_pkt_free_rx_data(frame); @@ -351,7 +351,7 @@ int can_dll_register_candev(candev_dev_t *candev) return candev_nb++; } -int can_dll_dispatch_rx_frame(struct can_frame *frame, kernel_pid_t pid) +int can_dll_dispatch_rx_frame(can_frame_t *frame, kernel_pid_t pid) { can_pkt_t *pkt = can_pkt_alloc_rx(_get_ifnum(pid), frame); diff --git a/sys/can/isotp/isotp.c b/sys/can/isotp/isotp.c index 37baed206623..622064f10416 100644 --- a/sys/can/isotp/isotp.c +++ b/sys/can/isotp/isotp.c @@ -90,7 +90,7 @@ static mutex_t lock = MUTEX_INIT; static void _rx_timeout(void *arg); static int _isotp_send_fc(struct isotp *isotp, int ae, uint8_t status); -static int _isotp_tx_send(struct isotp *isotp, struct can_frame *frame); +static int _isotp_tx_send(struct isotp *isotp, can_frame_t *frame); static int _send_msg(msg_t *msg, can_reg_entry_t *entry) { @@ -189,7 +189,7 @@ static void _tx_timeout(void *arg) msg_send(&msg, isotp_pid); } -static int _isotp_rcv_fc(struct isotp *isotp, struct can_frame *frame, int ae) +static int _isotp_rcv_fc(struct isotp *isotp, can_frame_t *frame, int ae) { if (isotp->tx.state != ISOTP_WAIT_FC) { return 0; @@ -197,7 +197,7 @@ static int _isotp_rcv_fc(struct isotp *isotp, struct can_frame *frame, int ae) ztimer_remove(ZTIMER_USEC, &isotp->tx_timer); - if (frame->can_dlc < ae + FC_CONTENT_SZ) { + if (frame->len < ae + FC_CONTENT_SZ) { /* Invalid length */ isotp->tx.state = ISOTP_IDLE; return 1; @@ -254,13 +254,13 @@ static int _isotp_rcv_fc(struct isotp *isotp, struct can_frame *frame, int ae) return 0; } -static int _isotp_rcv_sf(struct isotp *isotp, struct can_frame *frame, int ae) +static int _isotp_rcv_sf(struct isotp *isotp, can_frame_t *frame, int ae) { ztimer_remove(ZTIMER_USEC, &isotp->rx_timer); isotp->rx.state = ISOTP_IDLE; int len = (frame->data[ae] & 0x0F); - if (len > frame->can_dlc - (SF_PCI_SZ + ae)) { + if (len > frame->len - (SF_PCI_SZ + ae)) { return 1; } @@ -278,7 +278,7 @@ static int _isotp_rcv_sf(struct isotp *isotp, struct can_frame *frame, int ae) return _isotp_dispatch_rx(isotp); } -static int _isotp_rcv_ff(struct isotp *isotp, struct can_frame *frame, int ae) +static int _isotp_rcv_ff(struct isotp *isotp, can_frame_t *frame, int ae) { isotp->rx.state = ISOTP_IDLE; @@ -307,7 +307,7 @@ static int _isotp_rcv_ff(struct isotp *isotp, struct can_frame *frame, int ae) isotp->rx.snip = snip; isotp->rx.idx = 0; - for (int i = ae + FF_PCI_SZ; i < frame->can_dlc; i++) { + for (int i = ae + FF_PCI_SZ; i < frame->len; i++) { ((uint8_t *)isotp->rx.snip->data)[isotp->rx.idx++] = frame->data[i]; } @@ -332,7 +332,7 @@ static int _isotp_rcv_ff(struct isotp *isotp, struct can_frame *frame, int ae) return 0; } -static int _isotp_rcv_cf(struct isotp *isotp, struct can_frame *frame, int ae) +static int _isotp_rcv_cf(struct isotp *isotp, can_frame_t *frame, int ae) { DEBUG("_isotp_rcv_cf: state=%d\n", isotp->rx.state); @@ -352,7 +352,7 @@ static int _isotp_rcv_cf(struct isotp *isotp, struct can_frame *frame, int ae) isotp->rx.sn++; isotp->rx.sn %= 16; - for (int i = ae + N_PCI_SZ; i < frame->can_dlc; i++) { + for (int i = ae + N_PCI_SZ; i < frame->len; i++) { ((uint8_t *)isotp->rx.snip->data)[isotp->rx.idx++] = frame->data[i]; if (isotp->rx.idx >= isotp->rx.snip->size) { break; @@ -386,14 +386,14 @@ static int _isotp_rcv_cf(struct isotp *isotp, struct can_frame *frame, int ae) return _isotp_send_fc(isotp, ae, ISOTP_FC_CTS); } -static int _isotp_rcv(struct isotp *isotp, struct can_frame *frame) +static int _isotp_rcv(struct isotp *isotp, can_frame_t *frame) { int ae = (isotp->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0; uint8_t n_pci_type; if (IS_ACTIVE(ENABLE_DEBUG)) { DEBUG("_isotp_rcv: id=%" PRIx32 " data=", frame->can_id); - for (int i = 0; i < frame->can_dlc; i++) { + for (int i = 0; i < frame->len; i++) { DEBUG("%02hhx", frame->data[i]); } DEBUG("\n"); @@ -425,16 +425,16 @@ static int _isotp_rcv(struct isotp *isotp, struct can_frame *frame) static int _isotp_send_fc(struct isotp *isotp, int ae, uint8_t status) { - struct can_frame fc; + can_frame_t fc; fc.can_id = isotp->opt.tx_id; if (isotp->opt.flags & CAN_ISOTP_TX_PADDING) { memset(fc.data, isotp->opt.txpad_content, CAN_MAX_DLEN); - fc.can_dlc = CAN_MAX_DLEN; + fc.len = CAN_MAX_DLEN; } else { - fc.can_dlc = ae + FC_CONTENT_SZ; + fc.len = ae + FC_CONTENT_SZ; } fc.data[ae] = N_PCI_FC | status; @@ -449,7 +449,7 @@ static int _isotp_send_fc(struct isotp *isotp, int ae, uint8_t status) if (IS_ACTIVE(ENABLE_DEBUG)) { DEBUG("_isotp_send_fc: id=%" PRIx32 " data=", fc.can_id); - for (int i = 0; i < fc.can_dlc; i++) { + for (int i = 0; i < fc.len; i++) { DEBUG("%02hhx", fc.data[i]); } DEBUG("\n"); @@ -468,11 +468,11 @@ static int _isotp_send_fc(struct isotp *isotp, int ae, uint8_t status) } } -static void _isotp_create_ff(struct isotp *isotp, struct can_frame *frame, int ae) +static void _isotp_create_ff(struct isotp *isotp, can_frame_t *frame, int ae) { frame->can_id = isotp->opt.tx_id; - frame->can_dlc = CAN_MAX_DLEN; + frame->len = CAN_MAX_DLEN; if (ae) { frame->data[0] = isotp->opt.ext_address; @@ -488,22 +488,22 @@ static void _isotp_create_ff(struct isotp *isotp, struct can_frame *frame, int a isotp->tx.sn = 1; } -static void _isotp_fill_dataframe(struct isotp *isotp, struct can_frame *frame, int ae) +static void _isotp_fill_dataframe(struct isotp *isotp, can_frame_t *frame, int ae) { size_t pci_len = N_PCI_SZ + ae; size_t space = CAN_MAX_DLEN - pci_len; size_t num_bytes = MIN(space, isotp->tx.snip->size - isotp->tx.idx); frame->can_id = isotp->opt.tx_id; - frame->can_dlc = num_bytes + pci_len; + frame->len = num_bytes + pci_len; DEBUG("_isotp_fill_dataframe: num_bytes=%" PRIuSIZE ", pci_len=%" PRIuSIZE "\n", num_bytes, pci_len); if (num_bytes < space) { if (isotp->opt.flags & CAN_ISOTP_TX_PADDING) { - frame->can_dlc = CAN_MAX_DLEN; - memset(frame->data, isotp->opt.txpad_content, frame->can_dlc); + frame->len = CAN_MAX_DLEN; + memset(frame->data, isotp->opt.txpad_content, frame->len); } } @@ -520,7 +520,7 @@ static void _isotp_fill_dataframe(struct isotp *isotp, struct can_frame *frame, static void _isotp_tx_timeout_task(struct isotp *isotp) { int ae = (isotp->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0; - struct can_frame frame; + can_frame_t frame; DEBUG("_isotp_tx_timeout_task: state=%d\n", isotp->tx.state); @@ -624,7 +624,7 @@ static void _isotp_rx_tx_conf(struct isotp *isotp) } } -static int _isotp_tx_send(struct isotp *isotp, struct can_frame *frame) +static int _isotp_tx_send(struct isotp *isotp, can_frame_t *frame) { ztimer_set(ZTIMER_USEC, &isotp->tx_timer, CAN_ISOTP_TIMEOUT_N_As); isotp->tx.tx_handle = raw_can_send(isotp->entry.ifnum, frame, isotp_pid); @@ -640,7 +640,7 @@ static int _isotp_tx_send(struct isotp *isotp, struct can_frame *frame) static int _isotp_send_sf_ff(struct isotp *isotp) { - struct can_frame frame; + can_frame_t frame; unsigned ae = (isotp->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0; if (isotp->tx.snip->size <= CAN_MAX_DLEN - SF_PCI_SZ - ae) { diff --git a/sys/can/pkt.c b/sys/can/pkt.c index b91863aa8790..bec5c5c3dc36 100644 --- a/sys/can/pkt.c +++ b/sys/can/pkt.c @@ -50,7 +50,7 @@ void can_pkt_init(void) mutex_unlock(&_mutex); } -static can_pkt_t *_pkt_alloc(int ifnum, const struct can_frame *frame) +static can_pkt_t *_pkt_alloc(int ifnum, const can_frame_t *frame) { can_pkt_t *pkt; @@ -87,7 +87,7 @@ static void _init_tx_pkt(can_pkt_t *pkt) mutex_unlock(&_mutex); } -can_pkt_t *can_pkt_alloc_tx(int ifnum, const struct can_frame *frame, kernel_pid_t tx_pid) +can_pkt_t *can_pkt_alloc_tx(int ifnum, const can_frame_t *frame, kernel_pid_t tx_pid) { can_pkt_t *pkt = _pkt_alloc(ifnum, frame); @@ -104,7 +104,7 @@ can_pkt_t *can_pkt_alloc_tx(int ifnum, const struct can_frame *frame, kernel_pid return pkt; } -can_pkt_t *can_pkt_alloc_rx(int ifnum, const struct can_frame *frame) +can_pkt_t *can_pkt_alloc_rx(int ifnum, const can_frame_t *frame) { can_pkt_t *pkt = _pkt_alloc(ifnum, frame); @@ -118,7 +118,7 @@ can_pkt_t *can_pkt_alloc_rx(int ifnum, const struct can_frame *frame) } #ifdef MODULE_CAN_MBOX -can_pkt_t *can_pkt_alloc_mbox_tx(int ifnum, const struct can_frame *frame, mbox_t *tx_mbox) +can_pkt_t *can_pkt_alloc_mbox_tx(int ifnum, const can_frame_t *frame, mbox_t *tx_mbox) { can_pkt_t *pkt = _pkt_alloc(ifnum, frame); diff --git a/sys/can/router.c b/sys/can/router.c index e7eae1b276a8..e8244d33fe76 100644 --- a/sys/can/router.c +++ b/sys/can/router.c @@ -389,7 +389,7 @@ int can_router_dispatch_tx_error(can_pkt_t *pkt) return 0; } -int can_router_free_frame(struct can_frame *frame) +int can_router_free_frame(can_frame_t *frame) { can_pkt_t *pkt = container_of(frame, can_pkt_t, frame); diff --git a/sys/chunked_ringbuffer/chunked_ringbuffer.c b/sys/chunked_ringbuffer/chunked_ringbuffer.c index a3c8e592b3f6..9eb0e35c8c0e 100644 --- a/sys/chunked_ringbuffer/chunked_ringbuffer.c +++ b/sys/chunked_ringbuffer/chunked_ringbuffer.c @@ -87,13 +87,13 @@ static unsigned _get_cur_len(chunk_ringbuf_t *rb) } } -bool crb_end_chunk(chunk_ringbuf_t *rb, bool keep) +unsigned crb_end_chunk(chunk_ringbuf_t *rb, bool keep) { int idx; /* no chunk was started */ if (rb->cur_start == NULL) { - return false; + return 0; } if (keep) { @@ -109,7 +109,7 @@ bool crb_end_chunk(chunk_ringbuf_t *rb, bool keep) } rb->cur = rb->cur_start; rb->cur_start = NULL; - return false; + return 0; } /* store complete chunk */ @@ -117,7 +117,7 @@ bool crb_end_chunk(chunk_ringbuf_t *rb, bool keep) rb->chunk_len[idx] = _get_cur_len(rb); rb->cur_start = NULL; - return true; + return rb->chunk_len[idx]; } bool crb_get_chunk_size(chunk_ringbuf_t *rb, size_t *len) diff --git a/sys/include/can/can.h b/sys/include/can/can.h index b0974aa743fb..08e0a145604a 100644 --- a/sys/include/can/can.h +++ b/sys/include/can/can.h @@ -40,9 +40,13 @@ extern "C" { #else /** - * @brief Max data length for a CAN frame + * @brief Max data length for classic and FD CAN frames (compliant with + * libsocketcan macros) + * @{ */ -#define CAN_MAX_DLEN (8) +#define CAN_MAX_DLEN (8) /**< Classic CAN maximum data length */ +#define CANFD_MAX_DLEN (64) /**< CAN FD maximum data length */ +/** @} */ /** * @name CAN_ID flags and masks @@ -59,6 +63,15 @@ extern "C" { #define CAN_ERR_MASK (0x1FFFFFFFU) /**< omit EFF, RTR, ERR flags */ /** @} */ +/** + * @name CAN FD flags extracted from libsocketcan + * @{ + */ +#define CANFD_BRS 0x01 /**< bit rate switch (second bitrate for payload data) */ +#define CANFD_ESI 0x02 /**< error state indicator of the transmitting node */ +#define CANFD_FDF 0x04 /**< mark CAN FD for dual use of struct canfd_frame */ +/** @} */ + /** * @brief CAN operational and error states */ @@ -86,14 +99,29 @@ typedef uint32_t canid_t; * @brief Controller Area Network frame */ struct can_frame { + canid_t can_id; /**< 32 bit CAN_ID + EFF/RTR/ERR flags */ + union { + uint8_t len; /**< frame payload length in byte (0 .. CAN_MAX_DLEN) */ + uint8_t can_dlc;/**< deprecated - see SocketCAN documentation */ + }; + uint8_t __pad; /**< padding */ + uint8_t __res0; /**< reserved / padding */ + uint8_t __res1; /**< reserved / padding */ + /** Frame data */ + uint8_t data[CAN_MAX_DLEN] __attribute__((aligned(8))); +}; + +#ifdef MODULE_FDCAN +struct canfd_frame { canid_t can_id; /**< 32 bit CAN_ID + EFF/RTR/ERR flags */ - uint8_t can_dlc; /**< frame payload length in byte (0 .. CAN_MAX_DLEN) */ - uint8_t __pad; /**< padding */ + uint8_t len; /**< frame payload length in byte (0 .. CAN_MAX_DLEN) */ + uint8_t flags; /**< additional flags for CAN FD */ uint8_t __res0; /**< reserved / padding */ uint8_t __res1; /**< reserved / padding */ /** Frame data */ - uint8_t data[CAN_MAX_DLEN] __attribute__((aligned(8))); + uint8_t data[CANFD_MAX_DLEN] __attribute__((aligned(8))); }; +#endif /** * @brief Controller Area Network filter @@ -142,6 +170,15 @@ struct can_bittiming_const { #endif /* defined(__linux__) */ +/** + * @brief CAN frame + */ +#ifdef MODULE_FDCAN +typedef struct canfd_frame can_frame_t; +#else +typedef struct can_frame can_frame_t; +#endif + #ifdef __cplusplus } #endif diff --git a/sys/include/can/common.h b/sys/include/can/common.h index 80babfa4e005..ba56f31b25a4 100644 --- a/sys/include/can/common.h +++ b/sys/include/can/common.h @@ -39,6 +39,15 @@ extern "C" { #include "mbox.h" #endif +/** + * @brief Default CAN maximum data length + */ +#ifdef MODULE_FDCAN +#define DEFAULT_CAN_MAX_DLEN CANFD_MAX_DLEN +#else +#define DEFAULT_CAN_MAX_DLEN CAN_MAX_DLEN +#endif + /** * @brief CAN options */ @@ -51,6 +60,10 @@ typedef enum { CANOPT_CLOCK, /**< controller main clock */ CANOPT_BITTIMING_CONST, /**< controller bittiming parameters */ CANOPT_STATE, /**< set controller state @ref canopt_state_t */ +#ifdef MODULE_FDCAN + CANOPT_FD_BITTIMING, /**< bit timing parameter for FDCAN data payload */ + CANOPT_FD_BITTIMING_CONST, /**< controller bit timing parameter for FDCAN data payload */ +#endif } canopt_t; /** diff --git a/sys/include/can/conn/raw.h b/sys/include/can/conn/raw.h index 0a6673b038af..8eed58ac14de 100644 --- a/sys/include/can/conn/raw.h +++ b/sys/include/can/conn/raw.h @@ -100,7 +100,7 @@ int conn_can_raw_close(conn_can_raw_t *conn); * @return the number of bytes received * @return any other negative number in case of an error */ -int conn_can_raw_recv(conn_can_raw_t *conn, struct can_frame *frame, uint32_t timeout); +int conn_can_raw_recv(conn_can_raw_t *conn, can_frame_t *frame, uint32_t timeout); /** * @brief Generic can send @@ -113,7 +113,7 @@ int conn_can_raw_recv(conn_can_raw_t *conn, struct can_frame *frame, uint32_t ti * @return the number of bytes sent * @return any other negative number in case of an error */ -int conn_can_raw_send(conn_can_raw_t *conn, const struct can_frame *frame, int flags); +int conn_can_raw_send(conn_can_raw_t *conn, const can_frame_t *frame, int flags); /** * @brief Set raw CAN filters diff --git a/sys/include/can/device.h b/sys/include/can/device.h index be3d858f3071..3972119d5b00 100644 --- a/sys/include/can/device.h +++ b/sys/include/can/device.h @@ -57,6 +57,9 @@ typedef struct candev_params { #if defined(MODULE_CAN_TRX) || defined(DOXYGEN) can_trx_t *trx; /**< transceiver to set */ #endif +#if defined(MODULE_FDCAN) + uint16_t loop_delay; /**< CAN FD transceiver loop delay */ +#endif #if defined(MODULE_CAN_PM) || defined(DOXYGEN) uint32_t rx_inactivity_timeout; /**< power management rx timeout value */ uint32_t tx_wakeup_timeout; /**< power management tx wake up value */ @@ -74,6 +77,9 @@ typedef struct candev_dev { #if defined(MODULE_CAN_TRX) || defined(DOXYGEN) can_trx_t *trx; /**< transceiver attached to the device */ #endif +#if defined(MODULE_FDCAN) + uint16_t loop_delay; /**< CAN FD transceiver loop delay */ +#endif #if defined(MODULE_CAN_PM) || defined(DOXYGEN) uint32_t rx_inactivity_timeout; /**< Min timeout loaded when a frame is received */ uint32_t tx_wakeup_timeout; /**< Min timeout loaded when a frame is sent */ diff --git a/sys/include/can/dll.h b/sys/include/can/dll.h index 7b00dc604166..15436cca6995 100644 --- a/sys/include/can/dll.h +++ b/sys/include/can/dll.h @@ -60,7 +60,7 @@ int can_dll_register_candev(candev_dev_t *candev); * @return 0 on success * @return -ENOMEM if the message can not be sent */ -int can_dll_dispatch_rx_frame(struct can_frame *frame, kernel_pid_t pid); +int can_dll_dispatch_rx_frame(can_frame_t *frame, kernel_pid_t pid); /** * @brief Dispatch a tx confirmation diff --git a/sys/include/can/pkt.h b/sys/include/can/pkt.h index 2538aee3d0d5..85a57282f472 100644 --- a/sys/include/can/pkt.h +++ b/sys/include/can/pkt.h @@ -42,7 +42,7 @@ typedef struct { can_reg_entry_t entry; /**< entry containing ifnum and upper layer info */ atomic_uint ref_count; /**< Reference counter (for rx frames) */ int handle; /**< handle (for tx frames */ - struct can_frame frame; /**< CAN Frame */ + can_frame_t frame; /**< CAN Frame */ } can_pkt_t; /** @@ -64,7 +64,7 @@ void can_pkt_init(void); * * @return an allocated CAN packet, NULL if an error occurred */ -can_pkt_t *can_pkt_alloc_tx(int ifnum, const struct can_frame *frame, kernel_pid_t tx_pid); +can_pkt_t *can_pkt_alloc_tx(int ifnum, const can_frame_t *frame, kernel_pid_t tx_pid); /** * @brief Allocate an incoming CAN packet @@ -74,7 +74,7 @@ can_pkt_t *can_pkt_alloc_tx(int ifnum, const struct can_frame *frame, kernel_pid * * @return an allocated CAN packet, NULL if an error occurred */ -can_pkt_t *can_pkt_alloc_rx(int ifnum, const struct can_frame *frame); +can_pkt_t *can_pkt_alloc_rx(int ifnum, const can_frame_t *frame); #if defined(MODULE_CAN_MBOX) || defined(DOXYGEN) /** @@ -89,7 +89,7 @@ can_pkt_t *can_pkt_alloc_rx(int ifnum, const struct can_frame *frame); * * @return an allocated CAN packet, NULL if an error occurred */ -can_pkt_t *can_pkt_alloc_mbox_tx(int ifnum, const struct can_frame *frame, mbox_t *mbox); +can_pkt_t *can_pkt_alloc_mbox_tx(int ifnum, const can_frame_t *frame, mbox_t *mbox); #endif /** diff --git a/sys/include/can/raw.h b/sys/include/can/raw.h index 49a704048831..6f544addb55a 100644 --- a/sys/include/can/raw.h +++ b/sys/include/can/raw.h @@ -60,7 +60,7 @@ extern "C" { * @return a positive handle identifying the sent frame on success * @return < 0 on error */ -int raw_can_send(int ifnum, const struct can_frame *frame, kernel_pid_t pid); +int raw_can_send(int ifnum, const can_frame_t *frame, kernel_pid_t pid); /** * @brief Abort a CAN frame @@ -156,7 +156,7 @@ int raw_can_set_can_opt(int ifnum, can_opt_t *opt); * @return a positive handle identifying the sent frame on success * @return < 0 on error */ -int raw_can_send_mbox(int ifnum, const struct can_frame *frame, mbox_t *mbox); +int raw_can_send_mbox(int ifnum, const can_frame_t *frame, mbox_t *mbox); /** * @brief Subscribe to a CAN filter diff --git a/sys/include/can/router.h b/sys/include/can/router.h index a842fa0338ee..8c83253da6c1 100644 --- a/sys/include/can/router.h +++ b/sys/include/can/router.h @@ -73,7 +73,7 @@ int can_router_unregister(can_reg_entry_t *entry, canid_t can_id, canid_t mask, * @return 0 on success * @return < 0 on error */ -int can_router_free_frame(struct can_frame *frame); +int can_router_free_frame(can_frame_t *frame); /** * @brief Dispatch a RX indication to subscribers threads diff --git a/sys/include/chunked_ringbuffer.h b/sys/include/chunked_ringbuffer.h index d1727ba02c95..75cf9fa4ba5d 100644 --- a/sys/include/chunked_ringbuffer.h +++ b/sys/include/chunked_ringbuffer.h @@ -82,10 +82,10 @@ void crb_init(chunk_ringbuf_t *rb, void *buffer, size_t len); * @param[in] valid True if the chunk is valid and should be stored * False if the current chunk should be discarded * - * @return true If the chunk could be stored in the valid chunk array - * @return false If there is no more space in the valid chunk array + * @return size of chunk if the chunk could be stored in the valid chunk array + * @return 0 if there is no more space in the valid chunk array */ -bool crb_end_chunk(chunk_ringbuf_t *rb, bool valid); +unsigned crb_end_chunk(chunk_ringbuf_t *rb, bool valid); /** * @brief Start a new chunk on the ringbuffer diff --git a/sys/include/net/coap.h b/sys/include/net/coap.h index 275510463d51..797d4d7f8a73 100644 --- a/sys/include/net/coap.h +++ b/sys/include/net/coap.h @@ -519,6 +519,7 @@ typedef enum { */ #define COAP_OBS_REGISTER (0) #define COAP_OBS_DEREGISTER (1) +#define COAP_OBS_MAX_VALUE_MASK (0xffffff) /**< observe value is 24 bits */ /** @} */ /** diff --git a/sys/include/net/gnrc/ipv6.h b/sys/include/net/gnrc/ipv6.h index 4c0594b38bdd..00720ae3827c 100644 --- a/sys/include/net/gnrc/ipv6.h +++ b/sys/include/net/gnrc/ipv6.h @@ -174,11 +174,15 @@ extern "C" { /** * @brief Use the same static IPv6 link local address on every network interface * + * @deprecated Will be removed after release 2025.07 - after this the static link-local + * address will always be fixed unless a use-case for the auto-increment + * can be found. + * * When CONFIG_GNRC_IPV6_STATIC_LLADDR is used, to not add the interface pid to the * set static address but use the same static link local address for all interfaces. */ #ifndef CONFIG_GNRC_IPV6_STATIC_LLADDR_IS_FIXED -#define CONFIG_GNRC_IPV6_STATIC_LLADDR_IS_FIXED 0 +#define CONFIG_GNRC_IPV6_STATIC_LLADDR_IS_FIXED 1 #endif /** diff --git a/sys/include/net/nanocoap.h b/sys/include/net/nanocoap.h index 45fc28ed2660..50d1c5107505 100644 --- a/sys/include/net/nanocoap.h +++ b/sys/include/net/nanocoap.h @@ -85,24 +85,14 @@ #include #include -#ifdef RIOT_VERSION #include "bitarithm.h" #include "bitfield.h" #include "byteorder.h" #include "iolist.h" #include "macros/utils.h" -#include "net/coap.h" #include "modules.h" -#else -#include "coap.h" -#include -#endif - -#if defined(MODULE_SOCK_UDP) || defined(DOXYGEN) +#include "net/coap.h" #include "net/sock/udp.h" -#else -typedef void sock_udp_ep_t; -#endif #if defined(MODULE_NANOCOAP_RESOURCES) #include "xfa.h" @@ -1790,6 +1780,22 @@ static inline size_t coap_opt_put_block2_control(uint8_t *buf, uint16_t lastonum (block->blknum << 4) | block->szx); } +/** + * @brief Insert an CoAP Observe Option into the buffer + * + * @param[out] buf Buffer to write to + * @param[in] lastonum last option number (must be < 6) + * @param[in] obs observe number to write + * + * @returns amount of bytes written to @p buf + */ +static inline size_t coap_opt_put_observe(uint8_t *buf, uint16_t lastonum, + uint32_t obs) +{ + obs &= COAP_OBS_MAX_VALUE_MASK; /* trim obs down to 24 bit */ + return coap_opt_put_uint(buf, lastonum, COAP_OPT_OBSERVE, obs); +} + /** * @brief Encode the given string as multi-part option into buffer * diff --git a/sys/include/net/nanocoap_sock.h b/sys/include/net/nanocoap_sock.h index 9bdf41ce2f6c..d74c629e046e 100644 --- a/sys/include/net/nanocoap_sock.h +++ b/sys/include/net/nanocoap_sock.h @@ -261,7 +261,20 @@ int nanocoap_server_prepare_separate(nanocoap_server_response_ctx_t *ctx, coap_pkt_t *pkt, const coap_request_ctx_t *req); /** - * @brief Send a separate response to a CoAP request + * @brief Check if a given separate response context was prepared for the + * remote endpoint of a given request + * + * @param[in] ctx Separate response context to check + * @param[in] req Request from the remote to check for + * + * @retval true The remote endpoint given by @p req is in @p ctx + * @retval false @p ctx was prepared for a different remote endpoint + */ +bool nanocoap_server_is_remote_in_response_ctx(const nanocoap_server_response_ctx_t *ctx, + const coap_request_ctx_t *req); + +/** + * @brief Build and send a separate response to a CoAP request * * This sends a response to a CoAP request outside the CoAP handler * @@ -279,12 +292,159 @@ int nanocoap_server_prepare_separate(nanocoap_server_response_ctx_t *ctx, * @param[in] payload Response payload * @param[in] len Payload length * - * @returns 0 on success - * negative error (see @ref sock_udp_sendv_aux) + * @retval 0 Success + * @retval -ECANCELED Request contained no-response option that did match the given @p code + * @retval <0 Negative errno code indicating the error */ int nanocoap_server_send_separate(const nanocoap_server_response_ctx_t *ctx, unsigned code, unsigned type, const void *payload, size_t len); + +/** + * @brief Build a separate response header to a CoAP request + * + * This builds the response packet header. You may add CoAP Options, a payload + * marker and a payload as needed after the header. + * + * @pre @ref nanocoap_server_prepare_separate has been called on @p ctx + * inside the CoAP handler + * @pre Synchronization between calls of this function and calls of + * @ref nanocoap_server_prepare_separate is ensured + * + * @warning This function is only available when using the module + * `nanocoap_server_separate` + * + * @param[in] ctx Context information for the CoAP response + * @param[out] buf Buffer to write the header to + * @param[in] buf_len Length of @p buf in bytes + * @param[in] code CoAP response code + * @param[in] type Response type, may be `COAP_TYPE_NON` + * @param[in] msg_id Message ID to send + * + * @return Length of the header build in bytes + * @retval -ECANCELED Request contained no-response option that did match the given @p code + * @retval <0 Negative errno code indicating the error + */ +ssize_t nanocoap_server_build_separate(const nanocoap_server_response_ctx_t *ctx, + void *buf, size_t buf_len, + unsigned code, unsigned type, + uint16_t msg_id); + +/** + * @brief Send an already build separate response + * + * @pre @ref nanocoap_server_prepare_separate has been called on @p ctx + * inside the CoAP handler + * @pre Synchronization between calls of this function and calls of + * @ref nanocoap_server_prepare_separate is ensured + * @pre @ref nanocoap_server_build_separate has been used to build the + * header in @p msg + * + * @warning This function is only available when using the module + * `nanocoap_server_separate` + * + * @param[in] ctx Context information for the CoAP response + * @param[in] reply I/O list containing the reply to send + * + * @retval 0 Success + * @retval <0 negative errno code indicating the error + */ +int nanocoap_server_sendv_separate(const nanocoap_server_response_ctx_t *ctx, + const iolist_t *reply); + +/** + * @brief Register an observer + * @param[in] req_ctx Request context belonging to @p req_pkt + * @param[in,out] req_pkt Request that contained the observe registration request + * + * @warning This depends on module `nanocoap_server_observe` + * + * @note If the same endpoint already was registered on the same resource, + * it will just update the token and keep the existing entry. This + * way duplicate detection is not needed and we eagerly can reclaim + * resources when a client lost state. + * + * @warning Preventing the same endpoint to registers more than once (using + * different tokens) to the same resource deviates from RFC 7641. + * + * The deviation here is intentional. A server can receive a second registration + * from the same endpoint for the same resource for one of the following + * reasons: + * + * 1. Reaffirming the registration by using the same token again. + * 2. Losing state on the client side. + * 3. A malicious client trying to exhaust resources. + * 4. The same resource has different representations depending on the + * request. (E.g. `/.well-known/core` can yield a wildly different response + * depending on filters provided via URI-Query Options.) + * + * For case 1 updating the registration is matching what the spec mandates. + * For two the old registration will not be of value for the client, and + * overwriting it makes more efficient use of network bandwidth and RAM. + * For 3 the deviation forces the adversary to send observe requests from + * different ports to exhaust resources, which is a very minor improvement. + * For 4 the deviation is a problem. However, the observe API does not allow to + * send out different notification messages for the same resource anyway, so + * case 4 cannot occur here. + * + * @retval 0 Success + * @retval -ENOMEM Not enough resources to register another observer + * @retval <0 Negative errno code indicating error + */ +int nanocoap_register_observer(const coap_request_ctx_t *req_ctx, coap_pkt_t *req_pkt); + +/** + * @brief Unregister an observer + * @param req_ctx Request context belonging to @p req_pkt + * @param req_pkt Received request for unregistration + * + * @warning This depends on module `nanocoap_server_observe` + * + * @note It is safe to call this multiple times, e.g. duplicate detection + * is not needed for this. + */ +void nanocoap_unregister_observer(const coap_request_ctx_t *req_ctx, + const coap_pkt_t *req_pkt); + +/** + * @brief Unregister a stale observation due to a reset message received + * @param[in] ep Endpoint to wipe from the observer list + * @param[in] msg_id Message ID of the notification send. + */ +void nanocoap_unregister_observer_due_to_reset(const sock_udp_ep_t *ep, + uint16_t msg_id); + +/** + * @brief Notify all currently registered observers of the given resource + * + * @param[in] res Resource to send updates for + * @param[in] iol I/O list containing the CoAP Options, payload marker, + * and payload of the update to send up + * + * @pre @p iol contains everything but the CoAP header needed to send out. + * This will at least be a CoAP observe option, a payload marker, + * and a payload + * + * @post For each registered observer a CoAP packet header is generated and + * the concatenation of that header and the provided list is sent + */ +void nanocoap_notify_observers(const coap_resource_t *res, const iolist_t *iol); + +/** + * @brief Build and send notification to observers registered to a specific + * resource. + * + * @note Use @ref nanocoap_notify_observers for more control (such + * as adding custom options) over the notification(s) to send. + * + * @param[in] res Resource to send updates for + * @param[in] obs 24-bit number to add as observe option + * @param[in] payload Payload to send out + * @param[in] payload_len Length of @p payload in bytes + */ +void nanocoap_notify_observers_simple(const coap_resource_t *res, uint32_t obs, + const void *payload, size_t payload_len); + /** * @brief Get next consecutive message ID for use when building a new * CoAP request. diff --git a/sys/include/suit/transport/worker.h b/sys/include/suit/transport/worker.h index f1013bbd2a9a..b19b3d35d08c 100644 --- a/sys/include/suit/transport/worker.h +++ b/sys/include/suit/transport/worker.h @@ -25,7 +25,9 @@ #ifndef SUIT_TRANSPORT_WORKER_H #define SUIT_TRANSPORT_WORKER_H -#include "net/nanocoap.h" +#if MODULE_NANOCOAP +# include "net/nanocoap.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/sys/include/ztimer.h b/sys/include/ztimer.h index 24efb37b2858..a49aa9a5193a 100644 --- a/sys/include/ztimer.h +++ b/sys/include/ztimer.h @@ -404,7 +404,7 @@ void ztimer_handler(ztimer_clock_t *clock); /** * @brief Acquire a clock * - * This will indicate the the underlying clock is required to be running. + * This will indicate the underlying clock is required to be running. * If time differences are measured using @ref ztimer_now this will make * sure ztimer won't turn of the clock source. * @@ -425,7 +425,7 @@ static inline bool ztimer_acquire(ztimer_clock_t *clock) /** * @brief Release a clock * - * This will indicate the the underlying clock isn't required to be running + * This will indicate the underlying clock isn't required to be running * anymore and may be turned off. * * @param[in] clock ztimer clock to operate on diff --git a/sys/net/application_layer/cord/doc.txt b/sys/net/application_layer/cord/doc.txt index 5703a11d906d..bbfb4261bfed 100644 --- a/sys/net/application_layer/cord/doc.txt +++ b/sys/net/application_layer/cord/doc.txt @@ -52,9 +52,9 @@ * different roles described in `RFC 9176`: * * - `cord_ep`: standard endpoint implementation following the rules as - * defined i.a. in sections 5.2, 5.3, A.1, and A.2 + * defined i.a. in sections 4.3 and 5 * - `cord_epsim`: endpoint implementation following the simple registration - * procedure as defined in section 5.3.1 + * procedure as defined in section 5.1 * - `cord_lc`: lookup client implementation for querying information from * an RD using the lookup interfaces * - `cord_config`: header file collection (default) configuration values used diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index 5f6a6e8f0d29..3a5f4f5d08a4 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -28,6 +28,7 @@ #include "bitarithm.h" #include "net/nanocoap.h" +#include "net/nanocoap_sock.h" #define ENABLE_DEBUG 0 #include "debug.h" @@ -494,16 +495,45 @@ ssize_t coap_handle_req(coap_pkt_t *pkt, uint8_t *resp_buf, unsigned resp_buf_le { assert(ctx); + if (IS_USED(MODULE_NANOCOAP_SERVER_OBSERVE) && (coap_get_type(pkt) == COAP_TYPE_RST)) { + nanocoap_unregister_observer_due_to_reset(coap_request_ctx_get_remote_udp(ctx), + coap_get_id(pkt)); + } + + switch (coap_get_type(pkt)) { + case COAP_TYPE_CON: + case COAP_TYPE_NON: + /* could be a request ==> proceed */ + break; + default: + DEBUG_PUTS("coap_handle_req(): ignoring RST/ACK"); + return -EBADMSG; + } + if (coap_get_code_class(pkt) != COAP_REQ) { - DEBUG("coap_handle_req(): not a request.\n"); + DEBUG_PUTS("coap_handle_req(): not a request --> ignore"); return -EBADMSG; } - if (pkt->hdr->code == 0) { - return coap_build_reply(pkt, COAP_CODE_EMPTY, resp_buf, resp_buf_len, 0); + if (coap_get_code_raw(pkt) == COAP_CODE_EMPTY) { + /* we are not able to process a CON/NON message with an empty code, + * so we reply with a RST, unless we got a multicast message */ + if (!sock_udp_ep_is_multicast(coap_request_ctx_get_local_udp(ctx))) { + return coap_build_reply(pkt, COAP_CODE_EMPTY, resp_buf, resp_buf_len, 0); + } } - return coap_tree_handler(pkt, resp_buf, resp_buf_len, ctx, - coap_resources, coap_resources_numof); + + ssize_t retval = coap_tree_handler(pkt, resp_buf, resp_buf_len, ctx, + coap_resources, coap_resources_numof); + if (retval < 0) { + /* handlers were not able to process this, so we reply with a RST, + * unless we got a multicast message */ + if (!sock_udp_ep_is_multicast(coap_request_ctx_get_local_udp(ctx))) { + return coap_build_reply(pkt, COAP_CODE_EMPTY, resp_buf, resp_buf_len, 0); + } + } + + return retval; } ssize_t coap_subtree_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, diff --git a/sys/net/application_layer/nanocoap/sock.c b/sys/net/application_layer/nanocoap/sock.c index 0b3db123b777..06a852a3188c 100644 --- a/sys/net/application_layer/nanocoap/sock.c +++ b/sys/net/application_layer/nanocoap/sock.c @@ -25,16 +25,14 @@ #include #include -#include "atomic_utils.h" +#include "container.h" #include "net/credman.h" #include "net/nanocoap.h" #include "net/nanocoap_sock.h" -#include "net/sock/util.h" #include "net/sock/udp.h" -#include "net/iana/portrange.h" +#include "net/sock/util.h" #include "random.h" -#include "sys/uio.h" -#include "timex.h" +#include "sys/uio.h" /* IWYU pragma: keep (exports struct iovec) */ #include "ztimer.h" #define ENABLE_DEBUG 0 @@ -48,7 +46,11 @@ * if mode or key-size change especially if certificates instead of PSK are used. */ #ifndef CONFIG_NANOCOAP_DTLS_HANDSHAKE_BUF_SIZE -#define CONFIG_NANOCOAP_DTLS_HANDSHAKE_BUF_SIZE (160) +# define CONFIG_NANOCOAP_DTLS_HANDSHAKE_BUF_SIZE (160) +#endif + +#ifndef CONFIG_NANOCOAP_MAX_OBSERVERS +# define CONFIG_NANOCOAP_MAX_OBSERVERS 4 #endif enum { @@ -67,6 +69,35 @@ typedef struct { #endif } _block_ctx_t; +/** + * @brief Structure to track the state of an observation + */ +typedef struct { + /** + * @brief Context needed to build notifications (e.g. Token, endpoint + * to send to) + * + * @details To safe ROM, we reuse the separate response code to also + * send notifications, as the functionality is almost identical. + */ + nanocoap_server_response_ctx_t response; + /** + * @brief The resource the client has subscribed to + * + * @details This is `NULL` when the slot is free + */ + const coap_resource_t *resource; + /** + * @brief Message ID used in the last notification + */ + uint16_t msg_id; +} _observer_t; + +#if MODULE_NANOCOAP_SERVER_OBSERVE +static _observer_t _observer_pool[CONFIG_NANOCOAP_MAX_OBSERVERS]; +static mutex_t _observer_pool_lock; +#endif + int nanocoap_sock_dtls_connect(nanocoap_sock_t *sock, sock_udp_ep_t *local, const sock_udp_ep_t *remote, credman_tag_t tag) { @@ -1111,13 +1142,22 @@ int nanocoap_server_prepare_separate(nanocoap_server_response_ctx_t *ctx, return 0; } -int nanocoap_server_send_separate(const nanocoap_server_response_ctx_t *ctx, - unsigned code, unsigned type, - const void *payload, size_t len) +bool nanocoap_server_is_remote_in_response_ctx(const nanocoap_server_response_ctx_t *ctx, + const coap_request_ctx_t *req) +{ + return sock_udp_ep_equal(&ctx->remote, req->remote); +} + +ssize_t nanocoap_server_build_separate(const nanocoap_server_response_ctx_t *ctx, + void *buf, size_t buf_len, + unsigned code, unsigned type, + uint16_t msg_id) { - uint8_t rbuf[sizeof(coap_hdr_t) + COAP_TOKEN_LENGTH_MAX + 1]; assert(type != COAP_TYPE_ACK); assert(type != COAP_TYPE_CON); /* TODO: add support */ + if ((sizeof(coap_hdr_t) + COAP_TOKEN_LENGTH_MAX + 1) > buf_len) { + return -EOVERFLOW; + } const uint8_t no_response_index = (code >> 5) - 1; /* If the handler code misbehaved here, we'd face UB otherwise */ @@ -1125,7 +1165,49 @@ int nanocoap_server_send_separate(const nanocoap_server_response_ctx_t *ctx, const uint8_t mask = 1 << no_response_index; if (ctx->no_response & mask) { - return 0; + return -ECANCELED; + } + + return coap_build_hdr(buf, type, ctx->token, ctx->tkl, code, msg_id); +} + +int nanocoap_server_sendv_separate(const nanocoap_server_response_ctx_t *ctx, + const iolist_t *reply) +{ + sock_udp_aux_tx_t *aux_out_ptr = NULL; + /* make sure we reply with the same address that the request was + * destined for -- except in the multicast case */ + sock_udp_aux_tx_t aux_out = { + .flags = SOCK_AUX_SET_LOCAL, + .local = ctx->local, + }; + if (!sock_udp_ep_is_multicast(&ctx->local)) { + aux_out_ptr = &aux_out; + } + ssize_t retval = sock_udp_sendv_aux(NULL, reply, &ctx->remote, aux_out_ptr); + + if (retval < 0) { + return retval; + } + + return 0; +} + +int nanocoap_server_send_separate(const nanocoap_server_response_ctx_t *ctx, + unsigned code, unsigned type, + const void *payload, size_t len) +{ + uint8_t rbuf[sizeof(coap_hdr_t) + COAP_TOKEN_LENGTH_MAX + 1]; + + ssize_t hdr_len = nanocoap_server_build_separate(ctx, rbuf, sizeof(rbuf), + code, type, random_uint32()); + if (hdr_len < 0) { + return hdr_len; + } + + /* add payload marker if needed */ + if (len) { + rbuf[hdr_len++] = 0xFF; } iolist_t data = { @@ -1136,24 +1218,126 @@ int nanocoap_server_send_separate(const nanocoap_server_response_ctx_t *ctx, iolist_t head = { .iol_next = &data, .iol_base = rbuf, + .iol_len = hdr_len, }; - head.iol_len = coap_build_hdr((coap_hdr_t *)rbuf, type, - ctx->token, ctx->tkl, - code, random_uint32()); - if (len) { - rbuf[head.iol_len++] = 0xFF; + + return nanocoap_server_sendv_separate(ctx, &head); +} +#endif + +#if MODULE_NANOCOAP_SERVER_OBSERVE +int nanocoap_register_observer(const coap_request_ctx_t *req_ctx, coap_pkt_t *req_pkt) +{ + mutex_lock(&_observer_pool_lock); + + _observer_t *free = NULL; + const coap_resource_t *resource = req_ctx->resource; + + for (size_t i = 0; i < CONFIG_NANOCOAP_MAX_OBSERVERS; i++) { + if (_observer_pool[i].resource == NULL) { + free = &_observer_pool[i]; + } + if ((_observer_pool[i].resource == resource) + && sock_udp_ep_equal(&_observer_pool[i].response.remote, + coap_request_ctx_get_remote_udp(req_ctx))) + { + /* Deviation from the standard: Subscribing twice makes no + * sense with our CoAP implementation, so either this is a + * reaffirmation of an existing subscription (same token) or the + * client lost state (different token). We just update the + * subscription in either case */ + DEBUG("nanocoap: observe slot %" PRIuSIZE " reused\n", i); + uint8_t tkl = coap_get_token_len(req_pkt); + _observer_pool[i].response.tkl = tkl; + memcpy(_observer_pool[i].response.token, coap_get_token(req_pkt), tkl); + mutex_unlock(&_observer_pool_lock); + return 0; + } } - sock_udp_aux_tx_t *aux_out_ptr = NULL; - /* make sure we reply with the same address that the request was - * destined for -- except in the multicast case */ - sock_udp_aux_tx_t aux_out = { - .flags = SOCK_AUX_SET_LOCAL, - .local = ctx->local, - }; - if (!sock_udp_ep_is_multicast(&ctx->local)) { - aux_out_ptr = &aux_out; + if (!free) { + DEBUG_PUTS("nanocoap: observe registration failed, no free slot"); + mutex_unlock(&_observer_pool_lock); + return -ENOMEM; + } + + int retval = nanocoap_server_prepare_separate(&free->response, req_pkt, req_ctx); + if (retval) { + DEBUG("nanocoap: observe registration failed: %d\n", retval); + mutex_unlock(&_observer_pool_lock); + return retval; + } + free->resource = req_ctx->resource; + free->msg_id = random_uint32(); + mutex_unlock(&_observer_pool_lock); + DEBUG("nanocoap: new observe registration at slot %" PRIuSIZE "\n", + index_of(_observer_pool, free)); + return 0; +} + +void nanocoap_unregister_observer(const coap_request_ctx_t *req_ctx, + const coap_pkt_t *req_pkt) +{ + mutex_lock(&_observer_pool_lock); + for (size_t i = 0; i < CONFIG_NANOCOAP_MAX_OBSERVERS; i++) { + if ((_observer_pool[i].resource == req_ctx->resource) + && (_observer_pool[i].response.tkl == coap_get_token_len(req_pkt)) + && !memcmp(_observer_pool[i].response.token, coap_get_token(req_pkt), + _observer_pool[i].response.tkl) + && sock_udp_ep_equal(&_observer_pool[i].response.remote, coap_request_ctx_get_remote_udp(req_ctx))) { + DEBUG("nanocoap: observer at index %" PRIuSIZE " unregistered\n", i); + _observer_pool[i].resource = NULL; + } + } + mutex_unlock(&_observer_pool_lock); +} + +void nanocoap_unregister_observer_due_to_reset(const sock_udp_ep_t *ep, + uint16_t msg_id) +{ + mutex_lock(&_observer_pool_lock); + for (size_t i = 0; i < CONFIG_NANOCOAP_MAX_OBSERVERS; i++) { + if ((_observer_pool[i].resource != NULL) + && (_observer_pool[i].msg_id == msg_id) + && sock_udp_ep_equal(&_observer_pool[i].response.remote, ep)) { + DEBUG("nanocoap: observer at index %" PRIuSIZE " unregistered due to RST\n", i); + _observer_pool[i].resource = NULL; + return; + } + } + mutex_unlock(&_observer_pool_lock); +} + +void nanocoap_notify_observers(const coap_resource_t *res, const iolist_t *iol) +{ + mutex_lock(&_observer_pool_lock); + for (size_t i = 0; i < CONFIG_NANOCOAP_MAX_OBSERVERS; i++) { + if (_observer_pool[i].resource == res) { + uint8_t rbuf[sizeof(coap_hdr_t) + COAP_TOKEN_LENGTH_MAX + 1]; + + ssize_t hdr_len = nanocoap_server_build_separate(&_observer_pool[i].response, rbuf, sizeof(rbuf), + COAP_CODE_CONTENT, COAP_TYPE_NON, + ++_observer_pool[i].msg_id); + if (hdr_len < 0) { + /* no need to keep the observer in the pool, if we cannot + * send anyway */ + _observer_pool[i].resource = NULL; + continue; + } + + const iolist_t msg = { + .iol_base = rbuf, + .iol_len = hdr_len, + .iol_next = (iolist_t *)iol + }; + + if (nanocoap_server_sendv_separate(&_observer_pool[i].response, &msg)) { + /* no need to keep the observer in the pool, if we cannot + * send anyway */ + _observer_pool[i].resource = NULL; + } + } } - return sock_udp_sendv_aux(NULL, &head, &ctx->remote, aux_out_ptr); + mutex_unlock(&_observer_pool_lock); } #endif diff --git a/sys/shell/cmds/conn_can.c b/sys/shell/cmds/conn_can.c index 031e933965ff..29806475e4bc 100644 --- a/sys/shell/cmds/conn_can.c +++ b/sys/shell/cmds/conn_can.c @@ -60,15 +60,15 @@ static int _send(int argc, char **argv) } conn_can_raw_t conn; - struct can_frame frame; + can_frame_t frame; int ifnum = atoi(argv[1]); if (ifnum >= CAN_DLL_NUMOF) { puts("Invalid ifnum"); return 1; } frame.can_id = strtoul(argv[2], NULL, 16); - frame.can_dlc = argc - 3; - for (int i = 0; i < frame.can_dlc; i++) { + frame.len = argc - 3; + for (int i = 0; i < frame.len; i++) { frame.data[i] = strtoul(argv[3 + i], NULL, 16); } conn_can_raw_create(&conn, NULL, 0, ifnum, 0); @@ -87,7 +87,7 @@ static int _dump(int argc, char **argv) int ret = -1; struct can_filter filters[SC_CAN_MAX_FILTERS]; conn_can_raw_t conn; - struct can_frame frame; + can_frame_t frame; int ifnum = atoi(argv[1]); int cnt = atoi(argv[2]); uint32_t ms = strtoul(argv[3], NULL, 0); @@ -130,11 +130,11 @@ static int _dump(int argc, char **argv) conn_can_raw_create(&conn, filters, nb_filters, ifnum, 0); while ((cnt != 1) && ((ret = conn_can_raw_recv(&conn, &frame, ms * US_PER_MS)) - == sizeof(struct can_frame))) { + == sizeof(can_frame_t))) { printf("%-8s(%d) %8" PRIX32 " [%x] ", raw_can_get_name_by_ifnum(ifnum), ifnum, - frame.can_id, frame.can_dlc); - for (int i = 0; i < frame.can_dlc; i++) { + frame.can_id, frame.len); + for (int i = 0; i < frame.len; i++) { printf(" %02X", frame.data[i]); } printf("\n"); diff --git a/sys/tiny_strerror/tiny_strerror.c b/sys/tiny_strerror/tiny_strerror.c index 77732f4d7864..386d1686d2fc 100644 --- a/sys/tiny_strerror/tiny_strerror.c +++ b/sys/tiny_strerror/tiny_strerror.c @@ -48,7 +48,9 @@ static FLASH_ATTR const char _edquot[] = "-EDQUOT"; static FLASH_ATTR const char _eexist[] = "-EEXIST"; static FLASH_ATTR const char _efault[] = "-EFAULT"; static FLASH_ATTR const char _efbig[] = "-EFBIG"; +#ifdef EHOSTDOWN /* not part of POSIX and not universally available */ static FLASH_ATTR const char _ehostdown[] = "-EHOSTDOWN"; +#endif static FLASH_ATTR const char _ehostunreach[] = "-EHOSTUNREACH"; static FLASH_ATTR const char _eidrm[] = "-EIDRM"; static FLASH_ATTR const char _eilseq[] = "-EILSEQ"; @@ -93,7 +95,9 @@ static FLASH_ATTR const char _enxio[] = "-ENXIO"; static FLASH_ATTR const char _eoverflow[] = "-EOVERFLOW"; static FLASH_ATTR const char _eownerdead[] = "-EOWNERDEAD"; static FLASH_ATTR const char _eperm[] = "-EPERM"; +#ifdef EPFNOSUPPORT /* not part of POSIX and not universally available */ static FLASH_ATTR const char _epfnosupport[] = "-EPFNOSUPPORT"; +#endif static FLASH_ATTR const char _epipe[] = "-EPIPE"; static FLASH_ATTR const char _eprotonosupport[] = "-EPROTONOSUPPORT"; static FLASH_ATTR const char _eprototype[] = "-EPROTOTYPE"; @@ -105,7 +109,9 @@ static FLASH_ATTR const char _esrch[] = "-ESRCH"; static FLASH_ATTR const char _estale[] = "-ESTALE"; static FLASH_ATTR const char _etimedout[] = "-ETIMEDOUT"; static FLASH_ATTR const char _etime[] = "-ETIME"; +#ifdef ETOOMANYREFS /* not part of POSIX and not universally available */ static FLASH_ATTR const char _etoomanyrefs[] = "-ETOOMANYREFS"; +#endif static FLASH_ATTR const char _etxtbsy[] = "-ETXTBSY"; static FLASH_ATTR const char _exdev[] = "-EXDEV"; /* EAGAIN and EWOULDBLOCK have the exact same meaning and consequently may @@ -143,7 +149,9 @@ static FLASH_ATTR const char * FLASH_ATTR const lookup[] = { [EEXIST] = _eexist, [EFAULT] = _efault, [EFBIG] = _efbig, +#ifdef EHOSTDOWN /* not part of POSIX and not universally available */ [EHOSTDOWN] = _ehostdown, +#endif [EHOSTUNREACH] = _ehostunreach, [EIDRM] = _eidrm, [EILSEQ] = _eilseq, @@ -188,7 +196,9 @@ static FLASH_ATTR const char * FLASH_ATTR const lookup[] = { [EOVERFLOW] = _eoverflow, [EOWNERDEAD ] = _eownerdead, [EPERM] = _eperm, +#ifdef EPFNOSUPPORT /* not part of POSIX and not universally available */ [EPFNOSUPPORT] = _epfnosupport, +#endif [EPIPE] = _epipe, [EPROTONOSUPPORT] = _eprotonosupport, [EPROTOTYPE] = _eprototype, @@ -200,7 +210,9 @@ static FLASH_ATTR const char * FLASH_ATTR const lookup[] = { [ESTALE] = _estale, [ETIMEDOUT] = _etimedout, [ETIME] = _etime, +#ifdef ETOOMANYREFS /* not part of POSIX and not universally available */ [ETOOMANYREFS] = _etoomanyrefs, +#endif [ETXTBSY] = _etxtbsy, [EXDEV] = _exdev, #if EAGAIN != EWOULDBLOCK diff --git a/tests/bench/xtimer/Makefile b/tests/bench/xtimer/Makefile index 0de2634d33c8..c07f5fecb664 100644 --- a/tests/bench/xtimer/Makefile +++ b/tests/bench/xtimer/Makefile @@ -42,7 +42,6 @@ LOW_MEMORY_BOARDS += \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-f030r8 \ nucleo-f042k6 \ nucleo-f070rb \ diff --git a/tests/bench/ztimer/Makefile b/tests/bench/ztimer/Makefile index 57b12aea2c88..6a77b15e3369 100644 --- a/tests/bench/ztimer/Makefile +++ b/tests/bench/ztimer/Makefile @@ -42,7 +42,6 @@ LOW_MEMORY_BOARDS += \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-f030r8 \ nucleo-f042k6 \ nucleo-f070rb \ diff --git a/tests/core/thread_float/Makefile.ci b/tests/core/thread_float/Makefile.ci index 53bfe5b5a6d7..67f931300a89 100644 --- a/tests/core/thread_float/Makefile.ci +++ b/tests/core/thread_float/Makefile.ci @@ -13,7 +13,6 @@ BOARD_INSUFFICIENT_MEMORY := \ mbed_lpc1768 \ microbit \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f031k6 \ nucleo-f042k6 \ diff --git a/tests/drivers/candev/Makefile b/tests/drivers/candev/Makefile index 18e61e9ed15b..f639279a6f15 100644 --- a/tests/drivers/candev/Makefile +++ b/tests/drivers/candev/Makefile @@ -7,3 +7,17 @@ USEMODULE += can USEMODULE += isrpipe include $(RIOTBASE)/Makefile.include + +# Loop delay +ifneq (,$(filter fdcan,$(USEMODULE))) + ifneq (1,$(RIOT_CI_BUILD)) + # Check your CAN transceiver datasheet to apply the good loop delay in nanoseconds. + # This configuration is mandatory if you are using CAN FD with bitrate switching. + # Can be configured here or through Kconfig + #CFLAGS += -DCONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY=0 + + # Allow only a default value for CI + else + CFLAGS += -DCONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY=0 + endif +endif diff --git a/tests/drivers/candev/Makefile.ci b/tests/drivers/candev/Makefile.ci index 626a7facf951..363d4f3a79ad 100644 --- a/tests/drivers/candev/Makefile.ci +++ b/tests/drivers/candev/Makefile.ci @@ -1,5 +1,4 @@ BOARD_INSUFFICIENT_MEMORY := \ atmega8 \ nucleo-l011k4 \ - stm32f030f4-demo \ # diff --git a/tests/drivers/candev/main.c b/tests/drivers/candev/main.c index 6376d0a96d0c..bb1c750befe7 100644 --- a/tests/drivers/candev/main.c +++ b/tests/drivers/candev/main.c @@ -67,9 +67,9 @@ static int _send(int argc, char **argv) { int ret = 0; - struct can_frame frame = { + can_frame_t frame = { .can_id = 1, - .can_dlc = 3, + .len = 3, .data[0] = 0xAB, .data[1] = 0xCD, .data[2] = 0xEF, @@ -83,7 +83,7 @@ static int _send(int argc, char **argv) for (int i = 1; i < argc; i++) { frame.data[i - 1] = atoi(argv[i]); } - frame.can_dlc = argc - 1; + frame.len = argc - 1; } ret = candev->driver->send(candev, &frame); @@ -110,17 +110,17 @@ static int _receive(int argc, char **argv) } for (int i = 0; i < n; i++) { - struct can_frame frame; + can_frame_t frame; puts("Reading from Rxbuf..."); isrpipe_read(&rxbuf, (uint8_t *)&(frame.can_id), sizeof(frame.can_id)); frame.can_id &= 0x1FFFFFFF; /* clear invalid bits */ - isrpipe_read(&rxbuf, (uint8_t *)&(frame.can_dlc), 1); - printf("id: %" PRIx32 " dlc: %" PRIx8, frame.can_id, frame.can_dlc); - if (frame.can_dlc > 0) { + isrpipe_read(&rxbuf, (uint8_t *)&(frame.len), 1); + printf("id: %" PRIx32 " dlc: %" PRIx8, frame.can_id, frame.len); + if (frame.len > 0) { printf(" data: "); - isrpipe_read(&rxbuf, frame.data, frame.can_dlc); /* data */ - for (int i = 0; i < frame.can_dlc; i++) { + isrpipe_read(&rxbuf, frame.data, frame.len); /* data */ + for (int i = 0; i < frame.len; i++) { printf("0x%X ", frame.data[i]); } } @@ -218,7 +218,7 @@ static const shell_command_t shell_commands[] = { static void _can_event_callback(candev_t *dev, candev_event_t event, void *arg) { (void)arg; - struct can_frame *frame; + can_frame_t *frame; switch (event) { case CANDEV_EVENT_ISR: @@ -237,19 +237,19 @@ static void _can_event_callback(candev_t *dev, candev_event_t event, void *arg) case CANDEV_EVENT_RX_INDICATION: DEBUG("_can_event: CANDEV_EVENT_RX_INDICATION\n"); - frame = (struct can_frame *)arg; + frame = (can_frame_t *)arg; DEBUG(" id: %" PRIx32 " dlc: %u data: ", frame->can_id & 0x1FFFFFFF, - frame->can_dlc); - for (uint8_t i = 0; i < frame->can_dlc; i++) { + frame->len); + for (uint8_t i = 0; i < frame->len; i++) { DEBUG("0x%X ", frame->data[i]); } DEBUG_PUTS(""); /* Store in buffer until user requests the data */ isrpipe_write(&rxbuf, (uint8_t *)&(frame->can_id), sizeof(frame->can_id)); - isrpipe_write_one(&rxbuf, frame->can_dlc); - isrpipe_write(&rxbuf, frame->data, frame->can_dlc); + isrpipe_write_one(&rxbuf, frame->len); + isrpipe_write(&rxbuf, frame->data, frame->len); break; case CANDEV_EVENT_RX_ERROR: diff --git a/tests/drivers/nrf802154/README.md b/tests/drivers/nrf802154/README.md index 6d0620ccaca2..28e0664b0f10 100644 --- a/tests/drivers/nrf802154/README.md +++ b/tests/drivers/nrf802154/README.md @@ -1,6 +1,11 @@ # About This is a manual test application for the NRF802154 radio driver. +Supported boards must have an nRF52-series chip that has an IEEE 802.15.4 radio (e.g. nrf52840dk). # Usage For testing the radio driver you can use the ifconfig and txtsnd shell commands that are included in this application. + +For testing beacon frame acceptance you can flash this test onto two nRF52 devices +and use the beaconsend command to send an IEEE 802.15.4 beacon frame. +The opponent should print the received frame details. \ No newline at end of file diff --git a/tests/drivers/nrf802154/main.c b/tests/drivers/nrf802154/main.c index 32a3f4f9c8ce..3ce0ae635863 100644 --- a/tests/drivers/nrf802154/main.c +++ b/tests/drivers/nrf802154/main.c @@ -52,6 +52,77 @@ int netdev_ieee802154_minimal_init_devs(netdev_event_cb_t cb) { return 0; } +void send_beacon_usage(char *cmd_name) +{ + printf("usage: %s [<16 bit hex source PAN ID>] (uses device PAN ID by default)\n", cmd_name); +} + +int cmd_send_beacon(int argc, char **argv) +{ + uint16_t pan_id; + /* evaluating if argument is present */ + switch (argc) { + case 1: + pan_id = nrf802154.dev.pan; + puts("using device PAN ID as source"); + break; + case 2: + if (strlen(argv[1]) != 4) { + puts("send: Error parsing PAN ID"); + send_beacon_usage(argv[0]); + return 1; + } + pan_id = strtoul(argv[1], NULL, 16); + break; + default: + send_beacon_usage(argv[0]); + return 1; + } + + printf("PAN ID: %x\n", pan_id); + + /* preparing the mac header */ + uint8_t mhr[IEEE802154_MAX_HDR_LEN]; + memset(mhr, 0, IEEE802154_MAX_HDR_LEN*sizeof(uint8_t)); + le_uint16_t src_pan = byteorder_btols(byteorder_htons(pan_id)); + le_uint16_t dst_pan = byteorder_htols(0); + size_t src_len = 2, dst_len = 0; + uint8_t *src = nrf802154.dev.short_addr, *dst = NULL; + uint8_t flags = IEEE802154_FCF_TYPE_BEACON; + + int res = ieee802154_set_frame_hdr(mhr, src, src_len, + dst, dst_len, + src_pan, dst_pan, + flags, nrf802154.dev.seq++); + if (res < 0) { + puts("send: Error preparing frame"); + send_beacon_usage(argv[0]); + return 1; + } + /* preparing packet to send */ + iolist_t iol = { + .iol_base = mhr, + .iol_len = (size_t)res, + .iol_next = NULL, + }; + + puts("Sending Beacon Frame"); + + res = netdev_ieee802154_minimal_send(&nrf802154.dev.netdev, &iol); + + if (res < 0) { + puts("send: Error on sending"); + send_beacon_usage(argv[0]); + return 1; + } + return 0; +} + +static const shell_command_t shell_commands[] = { + { "beaconsend", "Send an IEEE 802.15.4 beacon frame", cmd_send_beacon}, + {NULL, NULL, NULL} +}; + int main(void) { puts("Test application for NRF802154 IEEE 802.15.4 device driver"); @@ -66,7 +137,7 @@ int main(void) puts("Initialization successful - starting the shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/tests/net/emcute/Makefile.ci b/tests/net/emcute/Makefile.ci index e5f52901fd5c..621b90a35ae5 100644 --- a/tests/net/emcute/Makefile.ci +++ b/tests/net/emcute/Makefile.ci @@ -32,7 +32,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/net/gcoap_dns/Makefile.ci b/tests/net/gcoap_dns/Makefile.ci index 9345fcf9bd08..1b380b3cf988 100644 --- a/tests/net/gcoap_dns/Makefile.ci +++ b/tests/net/gcoap_dns/Makefile.ci @@ -27,7 +27,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/net/gcoap_forward_proxy/Makefile.ci b/tests/net/gcoap_forward_proxy/Makefile.ci index a690f42ba7f3..d3841a237454 100644 --- a/tests/net/gcoap_forward_proxy/Makefile.ci +++ b/tests/net/gcoap_forward_proxy/Makefile.ci @@ -25,7 +25,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/net/gnrc_dhcpv6_client_6lbr/Makefile.ci b/tests/net/gnrc_dhcpv6_client_6lbr/Makefile.ci index 29cc1722c05b..47da52310736 100644 --- a/tests/net/gnrc_dhcpv6_client_6lbr/Makefile.ci +++ b/tests/net/gnrc_dhcpv6_client_6lbr/Makefile.ci @@ -35,7 +35,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/net/gnrc_dhcpv6_client_stateless/Makefile.ci b/tests/net/gnrc_dhcpv6_client_stateless/Makefile.ci index f6eff6ae22dd..05d00f92c319 100644 --- a/tests/net/gnrc_dhcpv6_client_stateless/Makefile.ci +++ b/tests/net/gnrc_dhcpv6_client_stateless/Makefile.ci @@ -23,7 +23,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/net/gnrc_netif/Makefile.ci b/tests/net/gnrc_netif/Makefile.ci index a66475848ac6..00d55166d338 100644 --- a/tests/net/gnrc_netif/Makefile.ci +++ b/tests/net/gnrc_netif/Makefile.ci @@ -36,7 +36,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430h \ nrf51dk \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/net/gnrc_sixlowpan_frag_sfr_congure_impl/Makefile.ci b/tests/net/gnrc_sixlowpan_frag_sfr_congure_impl/Makefile.ci index 99e38a371fad..7980875d5d4e 100644 --- a/tests/net/gnrc_sixlowpan_frag_sfr_congure_impl/Makefile.ci +++ b/tests/net/gnrc_sixlowpan_frag_sfr_congure_impl/Makefile.ci @@ -27,7 +27,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/net/gnrc_udp/Makefile.ci b/tests/net/gnrc_udp/Makefile.ci index 0308a88f80df..51104b119ef8 100644 --- a/tests/net/gnrc_udp/Makefile.ci +++ b/tests/net/gnrc_udp/Makefile.ci @@ -23,7 +23,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/periph/uart/Makefile b/tests/periph/uart/Makefile index b60500e81f0e..c8ec516c0fd3 100644 --- a/tests/periph/uart/Makefile +++ b/tests/periph/uart/Makefile @@ -6,6 +6,7 @@ FEATURES_OPTIONAL += periph_uart_collision FEATURES_OPTIONAL += periph_uart_modecfg FEATURES_OPTIONAL += periph_uart_rxstart_irq +USEMODULE += bitfield USEMODULE += shell USEMODULE += ztimer_msec diff --git a/tests/periph/uart/main.c b/tests/periph/uart/main.c index 6c5a17a6eacb..b7b36f597650 100644 --- a/tests/periph/uart/main.c +++ b/tests/periph/uart/main.c @@ -22,11 +22,12 @@ #include #include -#include "shell.h" -#include "thread.h" +#include "bitfield.h" #include "msg.h" -#include "ringbuffer.h" #include "periph/uart.h" +#include "ringbuffer.h" +#include "shell.h" +#include "thread.h" #include "ztimer.h" #ifdef MODULE_STDIO_UART @@ -86,6 +87,8 @@ static uart_stop_bits_t stop_bits_lut[] = { UART_STOP_BITS_1, UART_STOP_BITS_2 } static int stop_bits_lut_len = ARRAY_SIZE(stop_bits_lut); #endif +static BITFIELD(uarts_initialized_mask, UART_NUMOF); + static int parse_dev(char *arg) { unsigned dev = atoi(arg); @@ -180,6 +183,9 @@ static int _self_test(uart_t dev, unsigned baud) uart_collision_detect_disable(dev); #endif + uart_poweroff(UART_DEV(dev)); + + test_mode = false; return 0; failure: @@ -248,6 +254,11 @@ static int cmd_init(int argc, char **argv) } baud = strtol(argv[2], NULL, 0); + if (bf_isset(uarts_initialized_mask, dev)) { + uart_poweroff(UART_DEV(dev)); + bf_unset(uarts_initialized_mask, dev); + } + /* initialize UART */ res = uart_init(UART_DEV(dev), baud, rx_cb, (void *)(intptr_t)dev); if (res == UART_NOBAUD) { @@ -260,6 +271,8 @@ static int cmd_init(int argc, char **argv) } printf("Success: Initialized UART_DEV(%i) at BAUD %"PRIu32"\n", dev, baud); + bf_set(uarts_initialized_mask, dev); + /* also test if poweron() and poweroff() work (or at least don't break * anything) */ sleep_test(dev, UART_DEV(dev)); @@ -396,6 +409,11 @@ static int cmd_test(int argc, char **argv) puts("[START]"); + if (bf_isset(uarts_initialized_mask, dev)) { + uart_poweroff(UART_DEV(dev)); + bf_unset(uarts_initialized_mask, dev); + } + /* run self test with different baud rates */ test_mode = true; for (unsigned i = 1; i <= 12; ++i) { diff --git a/tests/pkg/cmsis-dsp/Makefile b/tests/pkg/cmsis-dsp/Makefile index 75d308d8d603..8616b92e5318 100644 --- a/tests/pkg/cmsis-dsp/Makefile +++ b/tests/pkg/cmsis-dsp/Makefile @@ -34,7 +34,6 @@ BOARD_WHITELIST := \ stm32f4discovery \ udoo \ yunjia-nrf51822 \ - nrf6310 \ # include $(RIOTBASE)/Makefile.include diff --git a/tests/pkg/edhoc_c/Makefile.ci b/tests/pkg/edhoc_c/Makefile.ci index 89ef9b6b2a82..2906674e8204 100644 --- a/tests/pkg/edhoc_c/Makefile.ci +++ b/tests/pkg/edhoc_c/Makefile.ci @@ -19,7 +19,6 @@ BOARD_INSUFFICIENT_MEMORY := \ microbit \ nrf51dk \ nrf51dongle \ - nrf6310 \ nucleo-f030r8 \ nucleo-f031k6 \ nucleo-f042k6 \ diff --git a/tests/pkg/lwip/Makefile.ci b/tests/pkg/lwip/Makefile.ci index bca4d0c08d00..81b37f75782c 100644 --- a/tests/pkg/lwip/Makefile.ci +++ b/tests/pkg/lwip/Makefile.ci @@ -4,7 +4,6 @@ BOARD_INSUFFICIENT_MEMORY := \ bluepill-stm32f030c8 \ bluepill-stm32f103c8 \ i-nucleo-lrwan1 \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/pkg/lz4/Makefile.ci b/tests/pkg/lz4/Makefile.ci index c4b1317f3c4a..33a3a5743f8d 100644 --- a/tests/pkg/lz4/Makefile.ci +++ b/tests/pkg/lz4/Makefile.ci @@ -19,7 +19,6 @@ BOARD_INSUFFICIENT_MEMORY := \ im880b \ microbit \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/pkg/nimble_ext_adv/Makefile.ci b/tests/pkg/nimble_ext_adv/Makefile.ci index b0a9d107df38..44a3e94f66b8 100644 --- a/tests/pkg/nimble_ext_adv/Makefile.ci +++ b/tests/pkg/nimble_ext_adv/Makefile.ci @@ -3,6 +3,5 @@ BOARD_INSUFFICIENT_MEMORY := \ calliope-mini \ microbit \ nrf51dongle \ - nrf6310 \ yunjia-nrf51822 \ # diff --git a/tests/pkg/nimble_l2cap_server/nimble.inc.mk b/tests/pkg/nimble_l2cap_server/nimble.inc.mk index e00afed23b26..ec3020c81fd4 100644 --- a/tests/pkg/nimble_l2cap_server/nimble.inc.mk +++ b/tests/pkg/nimble_l2cap_server/nimble.inc.mk @@ -3,7 +3,7 @@ # Note: as the CPU variable is not set at this point, we manually 'whitelist' # all supported nrf51-boards here BOARDS_NRF51 := airfy-beacon calliope-mini microbit nrf51dk nrf51dongle \ - nrf6310 yunjia-nrf51822 + yunjia-nrf51822 ifneq (,$(filter $(BOARDS_NRF51),$(BOARD))) APP_MTU ?= 250 MSYS_CNT ?= 6 diff --git a/tests/pkg/tinydtls_sock_async/Makefile.ci b/tests/pkg/tinydtls_sock_async/Makefile.ci index 29cc1722c05b..47da52310736 100644 --- a/tests/pkg/tinydtls_sock_async/Makefile.ci +++ b/tests/pkg/tinydtls_sock_async/Makefile.ci @@ -35,7 +35,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msb-430 \ msb-430h \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/sys/conn_can/Makefile b/tests/sys/conn_can/Makefile index 4cf3e05a190f..75f82e40a27a 100644 --- a/tests/sys/conn_can/Makefile +++ b/tests/sys/conn_can/Makefile @@ -41,3 +41,23 @@ include $(RIOTBASE)/Makefile.include ifndef CONFIG_GNRC_PKTBUF_SIZE CFLAGS += -DCONFIG_GNRC_PKTBUF_SIZE=4096 endif + +ifneq (,$(filter native native64,$(BOARD))) + CFLAGS += -DTHREAD_STACKSIZE_MAIN=8192 +else + CFLAGS += -DTHREAD_STACKSIZE_MAIN=2048 +endif + +# Loop delay +ifneq (,$(filter fdcan,$(USEMODULE))) + ifneq (1,$(RIOT_CI_BUILD)) + # Check your CAN transceiver datasheet to apply the good loop delay in nanoseconds. + # This configuration is mandatory if you are using CAN FD with bitrate switching. + # Can be configured here or through Kconfig + #CFLAGS += -DCONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY=0 + + # Allow only a default value for CI + else + CFLAGS += -DCONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY=0 + endif +endif diff --git a/tests/sys/conn_can/Makefile.ci b/tests/sys/conn_can/Makefile.ci index 878ed9073928..5e9aed896eab 100644 --- a/tests/sys/conn_can/Makefile.ci +++ b/tests/sys/conn_can/Makefile.ci @@ -1,26 +1,3 @@ BOARD_INSUFFICIENT_MEMORY := \ - airfy-beacon \ - calliope-mini \ - i-nucleo-lrwan1 \ - im880b \ - microbit \ - nrf51dongle \ - nrf6310 \ - nucleo-f030r8 \ - nucleo-f031k6 \ - nucleo-f042k6 \ - nucleo-f070rb \ - nucleo-f072rb \ - nucleo-f302r8 \ - nucleo-f303k8 \ - nucleo-f303re \ - nucleo-f334r8 \ - nucleo-l031k6 \ - nucleo-l053r8 \ - saml10-xpro \ - saml11-xpro \ - stm32f030f4-demo \ - stm32f0discovery \ - stm32l0538-disco \ - yunjia-nrf51822 \ + olimexino-stm32 \ # diff --git a/tests/sys/conn_can/fdcan-ci.config b/tests/sys/conn_can/fdcan-ci.config new file mode 100644 index 000000000000..8b646dafe787 --- /dev/null +++ b/tests/sys/conn_can/fdcan-ci.config @@ -0,0 +1,2 @@ +CONFIG_FDCAN_DEVICE_SET_TRANSCEIVER_LOOP_DELAY=y +CONFIG_FDCAN_DEVICE_TRANSCEIVER_LOOP_DELAY=0 diff --git a/tests/sys/conn_can/main.c b/tests/sys/conn_can/main.c index 2a588905d656..ba833cb6d291 100644 --- a/tests/sys/conn_can/main.c +++ b/tests/sys/conn_can/main.c @@ -34,6 +34,8 @@ #include "can/can_trx.h" +#define SHELL_BUFSIZE 512 /* Needed for CAN FD frame */ + #ifdef MODULE_TJA1042 #include "tja1042.h" tja1042_trx_t tja1042 = { .trx.driver = &tja1042_driver, @@ -95,6 +97,10 @@ static void print_usage(void) puts("test_can list"); puts("test_can send ifnum can_id [B1 [B2 [B3 [B4 [B5 [B6 [B7 [B8]]]]]]]]"); puts("test_can sendrtr ifnum can_id length(0..8)"); +#ifdef MODULE_FDCAN + puts("test_can fdsend ifnum can_id [B1 [B2 [B3 [B4 [B5 [B6 [B7 ... [B64]]]]]]]]"); + puts("test_can fdsendrtr ifnum can_id length(0..64)"); +#endif printf("test_can recv ifnum user_id timeout can_id1 [can_id2..can_id%d]\n", MAX_FILTER); puts("test_can close user_id"); @@ -130,13 +136,13 @@ static int _list(int argc, char **argv) { return 0; } -static int _send(int argc, char **argv, bool rtr) +static int _send(int argc, char **argv, bool rtr, bool is_fd) { if (argc < 5) { print_usage(); return 1; } - struct can_frame frame; + can_frame_t frame; int ifnum = strtol(argv[2], NULL, 0); if (ifnum >= CAN_DLL_NUMOF) { puts("Invalid interface number"); @@ -145,22 +151,39 @@ static int _send(int argc, char **argv, bool rtr) if (rtr) { frame.can_id = CAN_RTR_FLAG | strtoul(argv[3], NULL, 16); - frame.can_dlc = strtoul(argv[4], NULL, 10); + frame.len = strtoul(argv[4], NULL, 10); } else { frame.can_id = strtoul(argv[3], NULL, 16); - frame.can_dlc = argc - 4; + frame.len = argc - 4; + } + +#ifdef MODULE_FDCAN + if (is_fd) { + frame.flags |= CANFD_FDF; + if (frame.len > DEFAULT_CAN_MAX_DLEN) { + puts("Invalid length"); + return 1; + } } - if (frame.can_dlc > 8) { + else if (frame.len > CAN_MAX_DLEN) { puts("Invalid length"); return 1; } +#else + (void) is_fd; + + if (frame.len > DEFAULT_CAN_MAX_DLEN) { + puts("Invalid length"); + return 1; + } +#endif if (rtr) { - for (int i = 0; i < frame.can_dlc; i++) { + for (int i = 0; i < frame.len; i++) { frame.data[i] = 0x0; } } else { - for (int i = 0; i < frame.can_dlc; i++) { + for (int i = 0; i < frame.len; i++) { frame.data[i] = strtol(argv[4 + i], NULL, 16); } } @@ -203,7 +226,17 @@ static int _receive(int argc, char **argv) } for (int i = 0; i < filt_num; i++) { filters[thread_nb][i].can_id = strtoul(argv[5 + i], NULL, 16); - filters[thread_nb][i].can_mask = 0xffffffff; + if (filters[thread_nb][i].can_id > CAN_SFF_MASK) { + filters[thread_nb][i].can_mask = CAN_EFF_MASK; + } + else { + filters[thread_nb][i].can_mask = CAN_SFF_MASK; + } + } + if (filt_num <= 0) { + filt_num = 1; + filters[thread_nb][0].can_id = 0; + filters[thread_nb][0].can_mask = 0; } uint32_t timeout = strtoul(argv[4], NULL, 0); msg_t msg; @@ -541,11 +574,19 @@ static int _can_handler(int argc, char **argv) return _list(argc, argv); } else if (strncmp(argv[1], "send", 5) == 0) { - return _send(argc, argv, false); + return _send(argc, argv, false, false); } else if (strncmp(argv[1], "sendrtr", 8) == 0) { - return _send(argc, argv, true); + return _send(argc, argv, true, false); + } +#ifdef MODULE_FDCAN + else if (strncmp(argv[1], "fdsend", 5) == 0) { + return _send(argc, argv, false, true); } + else if (strncmp(argv[1], "fdsendrtr", 8) == 0) { + return _send(argc, argv, true, true); + } +#endif else if (strncmp(argv[1], "recv", 5) == 0) { return _receive(argc, argv); } @@ -593,7 +634,7 @@ static int _can_handler(int argc, char **argv) static void *_receive_thread(void *args) { int thread_nb = (intptr_t)args; - struct can_frame frame; + can_frame_t frame; msg_t msg, msg_queue[RECEIVE_THREAD_MSG_QUEUE_SIZE]; /* setup the device layers message queue */ @@ -609,13 +650,13 @@ static void *_receive_thread(void *args) int ret; while ((ret = conn_can_raw_recv(&conn[thread_nb], &frame, msg.content.value)) - == sizeof(struct can_frame)) { + == sizeof(can_frame_t)) { printf("%d: %-8s %" PRIx32 " [%x] ", thread_nb, raw_can_get_name_by_ifnum(conn[thread_nb].ifnum), frame.can_id, - frame.can_dlc); - for (int i = 0; i < frame.can_dlc; i++) { + frame.len); + for (int i = 0; i < frame.len; i++) { printf(" %02X", frame.data[i]); } printf("\n"); @@ -736,8 +777,8 @@ int main(void) (void*)i, "receive_thread"); } - char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + char line_buf[SHELL_BUFSIZE]; + shell_run(_commands, line_buf, SHELL_BUFSIZE); return 0; } diff --git a/tests/sys/posix_semaphore/Makefile.ci b/tests/sys/posix_semaphore/Makefile.ci index 02ec9f8f6bbc..4c0357f2c392 100644 --- a/tests/sys/posix_semaphore/Makefile.ci +++ b/tests/sys/posix_semaphore/Makefile.ci @@ -11,7 +11,6 @@ BOARD_INSUFFICIENT_MEMORY := \ mbed_lpc1768 \ msb-430 \ msb-430h \ - nrf6310 \ nucleo-f030r8 \ nucleo-f031k6 \ nucleo-f042k6 \ diff --git a/tests/sys/psa_crypto_cipher/example_cipher_aes_128.c b/tests/sys/psa_crypto_cipher/example_cipher_aes_128.c index 41da3a8f4f68..9fe2f8b15fdd 100644 --- a/tests/sys/psa_crypto_cipher/example_cipher_aes_128.c +++ b/tests/sys/psa_crypto_cipher/example_cipher_aes_128.c @@ -32,6 +32,8 @@ static const uint8_t KEY_128[] = { 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; +/* certain PSA backends require the data to be in RAM rather than ROM + * so these values cannot be `const` */ static uint8_t PLAINTEXT[] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, diff --git a/tests/sys/psa_crypto_cipher/example_cipher_chacha20.c b/tests/sys/psa_crypto_cipher/example_cipher_chacha20.c index 8e9fcd65a1d5..341aa7436d0a 100644 --- a/tests/sys/psa_crypto_cipher/example_cipher_chacha20.c +++ b/tests/sys/psa_crypto_cipher/example_cipher_chacha20.c @@ -30,8 +30,8 @@ static const uint8_t KEY_CHACHA20[] = { 0x00, 0x08, 0x9a, 0x8b, 0x86, 0x55, 0x2e, 0x9a }; -/* This cannot be const, as the Cryptocell hardware implementation does not have - DMA access to flash storage, which contains the global const values */ +/* certain PSA backends require the data to be in RAM rather than ROM + * so these values cannot be `const` */ static uint8_t PLAINTEXT[] = { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x52, 0x49, 0x4F, 0x54, 0x21, 0x20, 0x54, 0x68, 0x65, 0x20, 0x41, 0x6E, 0x73, 0x77, 0x65, 0x72, 0x20, 0x69, diff --git a/tests/sys/psa_crypto_ecdsa/test_ecdsa_p256_vectors.c b/tests/sys/psa_crypto_ecdsa/test_ecdsa_p256_vectors.c index 254add9410b8..c3697221d322 100644 --- a/tests/sys/psa_crypto_ecdsa/test_ecdsa_p256_vectors.c +++ b/tests/sys/psa_crypto_ecdsa/test_ecdsa_p256_vectors.c @@ -40,9 +40,10 @@ static const uint8_t public_key[] = {0x04, 0x60, 0xFE, 0xD4, 0xBA, 0x25, 0x5A, 0 0x1A, 0xE9, 0xE9, 0x56, 0x28, 0xBC, 0x64, 0xF2, 0xF1, 0xB2, 0x0C, 0x2D, 0x7E, 0x9F, 0x51, 0x77, 0xA3, 0xC2, 0x94, 0xD4, 0x46, 0x22, 0x99}; -static const uint8_t message[6] = "sample"; - -static const uint8_t signature[] = {0xEF, 0xD4, 0x8B, 0x2A, 0xAC, 0xB6, 0xA8, 0xFD, 0x11, 0x40, +/* certain PSA backends require the data to be in RAM rather than ROM + * so these values cannot be `const` */ +static uint8_t message[6] = "sample"; +static uint8_t signature[] = {0xEF, 0xD4, 0x8B, 0x2A, 0xAC, 0xB6, 0xA8, 0xFD, 0x11, 0x40, 0xDD, 0x9C, 0xD4, 0x5E, 0x81, 0xD6, 0x9D, 0x2C, 0x87, 0x7B, 0x56, 0xAA, 0xF9, 0x91, 0xC3, 0x4D, 0x0E, 0xA8, 0x4E, 0xAF, 0x37, 0x16, 0xF7, 0xCB, 0x1C, 0x94, 0x2D, 0x65, 0x7C, 0x41, 0xD4, 0x36, 0xC7, 0xA1, 0xB6, 0xE2, 0x9F, 0x65, 0xF3, 0xE9, 0x00, 0xDB, 0xB9, 0xAF, 0xF4, 0x06, 0x4D, 0xC4, diff --git a/tests/sys/psa_crypto_hashes/Makefile b/tests/sys/psa_crypto_hashes/Makefile index c8c5f795ce91..be4f457d2841 100644 --- a/tests/sys/psa_crypto_hashes/Makefile +++ b/tests/sys/psa_crypto_hashes/Makefile @@ -18,3 +18,5 @@ USEMODULE += psa_hash_sha_512_224 USEMODULE += psa_hash_sha_512_256 include $(RIOTBASE)/Makefile.include + +CFLAGS += -DTHREAD_STACKSIZE_MAIN=2048 diff --git a/tests/sys/psa_crypto_hashes/Makefile.ci b/tests/sys/psa_crypto_hashes/Makefile.ci index 54417567ab01..6e784f7ec2ac 100644 --- a/tests/sys/psa_crypto_hashes/Makefile.ci +++ b/tests/sys/psa_crypto_hashes/Makefile.ci @@ -7,4 +7,5 @@ BOARD_INSUFFICIENT_MEMORY := \ atmega328p-xplained-mini \ atmega8 \ nucleo-l011k4 \ + samd10-xmini \ # diff --git a/tests/sys/psa_crypto_hashes/example_hash.c b/tests/sys/psa_crypto_hashes/example_hash.c index a2fa46959c0e..c758524c989f 100644 --- a/tests/sys/psa_crypto_hashes/example_hash.c +++ b/tests/sys/psa_crypto_hashes/example_hash.c @@ -25,8 +25,10 @@ #include "psa/crypto.h" -static const uint8_t msg[] = "Hello World!"; -static const size_t msg_len = sizeof(msg)-1; // exclude NULL-byte +/* certain PSA backends require the data to be in RAM rather than ROM + * so these values cannot be `const` */ +static uint8_t msg[] = "Hello World!"; +static size_t msg_len = sizeof(msg)-1; // exclude NULL-byte static const uint8_t hash_sha224[] = { 0x45, 0x75, 0xbb, 0x4e, 0xc1, 0x29, 0xdf, 0x63, 0x80, 0xce, 0xdd, 0xe6, 0xd7, @@ -61,6 +63,60 @@ static const uint8_t hash_sha512_256[] = { 0x72, 0x3a, 0x26, 0x71, 0x0e, 0x46, 0x76, 0x13, 0x01, 0xc8, 0xb5, 0x4c, 0x56, 0xfa, 0x72, 0x22, 0x67, 0x58, 0x1a}; +static uint8_t msg_long[] = { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa +}; + +static const uint8_t hash_long_sha224[] = { + 0x89, 0xf0, 0xbf, 0x9d, 0x18, 0xe3, 0x68, 0x66, 0xb9, 0x19, 0x8d, 0x9d, 0x1b, + 0xa9, 0x9f, 0x4c, 0xa7, 0xcb, 0x83, 0x9c, 0xf9, 0x7c, 0xd9, 0x71, 0xe3, 0xef, + 0x41, 0x6c +}; + +static const uint8_t hash_long_sha256[] = { + 0x45, 0xad, 0x4b, 0x37, 0xc6, 0xe2, 0xfc, 0x0a, 0x2c, 0xfc, 0xc1, 0xb5, 0xda, + 0x52, 0x41, 0x32, 0xec, 0x70, 0x76, 0x15, 0xc2, 0xca, 0xe1, 0xdb, 0xbc, 0x43, + 0xc9, 0x7a, 0xa5, 0x21, 0xdb, 0x81 +}; + +static const uint8_t hash_long_sha384[] = { + 0xad, 0x51, 0xdd, 0xb7, 0x80, 0x48, 0x4e, 0xc6, 0xce, 0xb4, 0x96, 0xbc, 0xc1, + 0xe2, 0x4e, 0xf8, 0x23, 0x20, 0xe2, 0xe2, 0x68, 0x7d, 0x6c, 0xba, 0xef, 0x37, + 0xcf, 0x9f, 0x47, 0xc5, 0xa6, 0xfd, 0xda, 0xe5, 0x19, 0xe9, 0x6c, 0x98, 0x6f, + 0x45, 0x97, 0x5d, 0xbc, 0x31, 0xb8, 0x09, 0x91, 0x37 +}; + +static const uint8_t hash_long_sha512[] = { + 0xe1, 0xb5, 0x2c, 0x4f, 0xf8, 0xce, 0x9c, 0x4b, 0x60, 0xbd, 0x8e, 0xc7, 0x85, + 0xab, 0x7b, 0xf3, 0xdf, 0xfc, 0x70, 0x23, 0xf7, 0xc5, 0x15, 0x88, 0xf9, 0x6b, + 0x94, 0xee, 0xba, 0x80, 0xca, 0x3b, 0x9b, 0x9e, 0xd0, 0x5a, 0xb2, 0xac, 0x87, + 0x97, 0xbb, 0x70, 0x39, 0xd6, 0x81, 0xf2, 0xe4, 0x1f, 0xcf, 0xe6, 0xdd, 0xda, + 0xb2, 0xe9, 0x51, 0x22, 0xd9, 0xc7, 0x16, 0xc2, 0xb8, 0x40, 0x6b, 0xd4 +}; + +static const uint8_t hash_long_sha512_224[] = { + 0x6f, 0xcd, 0x48, 0x1d, 0x5c, 0x9a, 0xc8, 0x8d, 0x27, 0x91, 0x91, 0xd0, 0xbf, + 0x19, 0x2d, 0x77, 0xd9, 0x7b, 0x35, 0x64, 0x82, 0x6d, 0xd3, 0xe4, 0xef, 0xb7, + 0xc1, 0xc2 +}; + +static const uint8_t hash_long_sha512_256[] = { + 0x51, 0x28, 0xb1, 0xa1, 0x72, 0x14, 0xe7, 0x4b, 0x76, 0xb5, 0x28, 0x51, 0xab, + 0xc0, 0xec, 0xc0, 0x99, 0x56, 0x32, 0x77, 0xcd, 0x20, 0x78, 0xa7, 0x56, 0x4f, + 0x63, 0x52, 0x68, 0x81, 0x4a, 0xce +}; + + /** * @brief Example function to use different hash algorithms * with the PSA Crypto API. @@ -101,5 +157,35 @@ psa_status_t example_hash(void) return status; } + status = psa_hash_compare(PSA_ALG_SHA_224, msg_long, sizeof(msg_long), hash_long_sha224, sizeof(hash_long_sha224)); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_hash_compare(PSA_ALG_SHA_256, msg_long, sizeof(msg_long), hash_long_sha256, sizeof(hash_long_sha256)); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_hash_compare(PSA_ALG_SHA_384, msg_long, sizeof(msg_long), hash_long_sha384, sizeof(hash_long_sha384)); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_hash_compare(PSA_ALG_SHA_512, msg_long, sizeof(msg_long), hash_long_sha512, sizeof(hash_long_sha512)); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_hash_compare(PSA_ALG_SHA_512_224, msg_long, sizeof(msg_long), hash_long_sha512_224, sizeof(hash_long_sha512_224)); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_hash_compare(PSA_ALG_SHA_512_256, msg_long, sizeof(msg_long), hash_long_sha512_256, sizeof(hash_long_sha512_256)); + if (status != PSA_SUCCESS) { + return status; + } + return status; } diff --git a/tests/sys/psa_crypto_hashes/example_sha3_glue.c b/tests/sys/psa_crypto_hashes/example_sha3_glue.c index 8f8a5bc9a2e5..b9100844b217 100644 --- a/tests/sys/psa_crypto_hashes/example_sha3_glue.c +++ b/tests/sys/psa_crypto_hashes/example_sha3_glue.c @@ -20,6 +20,8 @@ #include "psa/crypto.h" +/* certain PSA backends require the data to be in RAM rather than ROM + * so these values cannot be `const` */ static const uint8_t msg[] = "Hello World!"; static const size_t msg_len = sizeof(msg)-1; // exclude NULL-byte diff --git a/tests/sys/psa_crypto_mac/example_hmac_sha256.c b/tests/sys/psa_crypto_mac/example_hmac_sha256.c index 43c48c97bd2d..77c0611136d9 100644 --- a/tests/sys/psa_crypto_mac/example_hmac_sha256.c +++ b/tests/sys/psa_crypto_mac/example_hmac_sha256.c @@ -32,7 +32,9 @@ static const uint8_t HMAC_KEY[] = { }; static size_t HMAC_KEY_LEN = 32; -static const uint8_t HMAC_MSG[] = { +/* certain PSA backends require the data to be in RAM rather than ROM + * so these values cannot be `const` */ +static uint8_t HMAC_MSG[] = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, diff --git a/tests/unittests/Makefile b/tests/unittests/Makefile index cc9bdd02172f..86f91d763956 100644 --- a/tests/unittests/Makefile +++ b/tests/unittests/Makefile @@ -61,3 +61,9 @@ ifeq (, $(UNIT_TESTS)) else CFLAGS += -DTEST_SUITES='$(subst $() $(),$(comma),$(UNIT_TESTS:tests-%=%))' endif + +# Hack: If GNRC is not used, still provide access to sock_types.h to allow +# building nanocoap +ifeq (,$(filter gnrc_sock,$(USEMODULE))) + CFLAGS +=-I$(RIOTBASE)/sys/net/gnrc/sock/include +endif diff --git a/tests/unittests/Makefile.ci b/tests/unittests/Makefile.ci index cda190820678..34908417976a 100644 --- a/tests/unittests/Makefile.ci +++ b/tests/unittests/Makefile.ci @@ -44,7 +44,6 @@ BOARD_INSUFFICIENT_MEMORY := \ msba2 \ nrf51dk \ nrf51dongle \ - nrf6310 \ nucleo-c031c6 \ nucleo-f030r8 \ nucleo-f031k6 \ diff --git a/tests/unittests/tests-nanocoap/tests-nanocoap.c b/tests/unittests/tests-nanocoap/tests-nanocoap.c index b6493b7b762c..5b04de848398 100644 --- a/tests/unittests/tests-nanocoap/tests-nanocoap.c +++ b/tests/unittests/tests-nanocoap/tests-nanocoap.c @@ -1227,6 +1227,29 @@ static void test_nanocoap___rst_message(void) TEST_ASSERT_EQUAL_INT(0x55, buf[sizeof(rst_expected)]); } +/* + * Test that invalid encoding of CoAP option is caught early, so that + * later access to CoAP option does indeed not need to perform bound + * checking. + */ +static void test_nanocoap__out_of_bounds_option(void) +{ + uint8_t invalid_msg[] = { + (COAP_V1 << 6) | (COAP_TYPE_CON << 4) | 3, /* version = 1, type = CON, Token Len = 3 */ + COAP_METHOD_GET, + 0x13, 0x37, /* Message ID = 0x1337 */ + 0xca, 0xfe, 0x42, /* Token = 0xcafe42 */ + /* Option Delta: 11 (11 + 0 = 11 = URI-Path) + * Option Length: 8 */ + (COAP_OPT_URI_PATH << 4) | (8), + 0x13, 0x37, 0x42, 0x42 /* 4 bytes Option Data */ + /* End of packet - 4 bytes before the claimed end of option */ + }; + + coap_pkt_t pkt; + TEST_ASSERT_EQUAL_INT(-EBADMSG, coap_parse(&pkt, invalid_msg, sizeof(invalid_msg))); +} + Test *tests_nanocoap_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { @@ -1266,6 +1289,7 @@ Test *tests_nanocoap_tests(void) new_TestFixture(test_nanocoap__token_length_ext_16), new_TestFixture(test_nanocoap__token_length_ext_269), new_TestFixture(test_nanocoap___rst_message), + new_TestFixture(test_nanocoap__out_of_bounds_option), }; EMB_UNIT_TESTCALLER(nanocoap_tests, NULL, NULL, fixtures); diff --git a/tests/unittests/tests-rtc/tests-rtc.c b/tests/unittests/tests-rtc/tests-rtc.c index 281c868b9638..8669aa6513b7 100644 --- a/tests/unittests/tests-rtc/tests-rtc.c +++ b/tests/unittests/tests-rtc/tests-rtc.c @@ -224,6 +224,39 @@ static void test_rtc_mktime(void) TEST_ASSERT_EQUAL_INT(98197931, rtc_mktime(&t)); } +static void test_mktime(void) +{ + /* second 1 of 1970 is defined 1 second of unixtime */ + struct tm t = { + .tm_sec = 1, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 1, + .tm_mon = 0, + .tm_year = 70, + .tm_wday = 0, + .tm_yday = 1, + }; + /* This test will fail if mktime is applying timezone information + * that is not 0 seconds offset from UTC (GMT) and therefore returning unixtime. + * A usual reason for failure might be that nativ is run in a local not "UTC" timezone, + * a "Fix" for this failure is setting the environment variable TZ to "UTC" */ + TEST_ASSERT_EQUAL_INT(1, mktime(&t)); + + t = (struct tm){ + .tm_sec = 11, + .tm_min = 12, + .tm_hour = 13, + .tm_mday = 1, + .tm_mon = 0, + .tm_year = 120, + .tm_wday = 0, + .tm_yday = 1, + }; + + TEST_ASSERT_EQUAL_INT(1577884331, mktime(&t)); +} + static void test_rtc_localtime(void) { struct tm t; @@ -287,6 +320,7 @@ Test *tests_rtc_tests(void) new_TestFixture(test_rtc_year), new_TestFixture(test_rtc_compare), new_TestFixture(test_rtc_mktime), + new_TestFixture(test_mktime), new_TestFixture(test_rtc_localtime), };