mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge branch 'RIOT-OS:master' into stm32_adc_cal
This commit is contained in:
commit
b09713e058
9
.github/workflows/check-commits.yml
vendored
9
.github/workflows/check-commits.yml
vendored
@ -2,6 +2,8 @@ name: check-commits
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
merge_group:
|
||||
|
||||
jobs:
|
||||
check-commits:
|
||||
runs-on: ubuntu-latest
|
||||
@ -24,3 +26,10 @@ jobs:
|
||||
- name: Run checks
|
||||
run: |
|
||||
./dist/tools/${{ matrix.check }}/check.sh "${{ github.base_ref }}"
|
||||
check-commits-success:
|
||||
needs: check-commits
|
||||
if: github.event_name != 'merge_group'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: check-commits succeeded
|
||||
run: exit 0
|
||||
|
3
.github/workflows/check-labels.yml
vendored
3
.github/workflows/check-labels.yml
vendored
@ -4,8 +4,11 @@ on:
|
||||
types: [opened, reopened, labeled, unlabeled, synchronize]
|
||||
pull_request_review:
|
||||
types: [submitted, dismissed]
|
||||
merge_group:
|
||||
|
||||
jobs:
|
||||
check-labels:
|
||||
if: github.event_name != 'merge_group'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: RIOT-OS/check-labels-action@v1.1.1
|
||||
|
2
.github/workflows/labeler.yml
vendored
2
.github/workflows/labeler.yml
vendored
@ -3,10 +3,12 @@ name: pr-labeler
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
merge_group:
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'merge_group'
|
||||
steps:
|
||||
- uses: actions/labeler@main
|
||||
with:
|
||||
|
18
.github/workflows/static-test.yml
vendored
18
.github/workflows/static-test.yml
vendored
@ -13,6 +13,7 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
merge_group:
|
||||
|
||||
jobs:
|
||||
static-tests:
|
||||
@ -21,11 +22,18 @@ jobs:
|
||||
- uses: actions/checkout@main
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: set CI_BASE_BRANCH
|
||||
run: |
|
||||
if [ -n "${{ github.base_ref }}" ]; then
|
||||
echo "CI_BASE_BRANCH=${{ github.base_ref }}" >> $GITHUB_ENV
|
||||
elif [ -n "${{ github.event.merge_group.base_ref }}" ]; then
|
||||
echo "CI_BASE_BRANCH=${{ github.event.merge_group.base_ref }}" | sed s.=refs/heads/.=. >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Setup git
|
||||
run: |
|
||||
# Note: ${{ github.base_ref }} is empty when not in a PR
|
||||
if [ -n "${{ github.base_ref }}" ]; then
|
||||
git fetch origin ${{ github.base_ref }}:${{ github.base_ref }} --no-tags
|
||||
# Note: CI_BASE_BRANCH is empty when not in a PR
|
||||
if [ -n "${CI_BASE_BRANCH}" ]; then
|
||||
git fetch origin ${CI_BASE_BRANCH}:${CI_BASE_BRANCH} --no-tags
|
||||
else
|
||||
git config diff.renameLimit 16384
|
||||
fi
|
||||
@ -34,9 +42,9 @@ jobs:
|
||||
run: docker pull riot/static-test-tools:latest
|
||||
- name: Run static-tests
|
||||
run: |
|
||||
# Note: ${{ github.base_ref }} is empty when not in a PR
|
||||
# Note: ${CI_BASE_BRANCH} is empty when not in a PR
|
||||
docker run --rm \
|
||||
-e CI_BASE_BRANCH=${{ github.base_ref }} \
|
||||
-e CI_BASE_BRANCH \
|
||||
-e GITHUB_RUN_ID=${GITHUB_RUN_ID} \
|
||||
-v $(pwd):/data/riotbuild \
|
||||
riot/static-test-tools:latest \
|
||||
|
1
.github/workflows/tools-buildtest.yml
vendored
1
.github/workflows/tools-buildtest.yml
vendored
@ -11,6 +11,7 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
merge_group:
|
||||
|
||||
jobs:
|
||||
tools-build:
|
||||
|
2
.github/workflows/tools-test.yml
vendored
2
.github/workflows/tools-test.yml
vendored
@ -9,9 +9,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
merge_group:
|
||||
|
||||
jobs:
|
||||
python-tests:
|
||||
if: github.event_name != 'merge_group'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@main
|
||||
|
36
.murdock
36
.murdock
@ -178,22 +178,18 @@ check_label() {
|
||||
return $?
|
||||
}
|
||||
|
||||
# this function returns 0 when this is build is building one of the two bors
|
||||
# branches ("staging" or "trying", 1 otherwise.
|
||||
is_bors_build() {
|
||||
test "${CI_BUILD_BRANCH}" = "staging" || test "${CI_BUILD_BRANCH}" = "trying"
|
||||
# true if "$2" starts with "$1", false otherwise
|
||||
startswith() {
|
||||
case "${2}" in
|
||||
${1}*) true ;;
|
||||
*) false ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Set CI_BASE_COMMIT in case of a bors build.
|
||||
# This assumes that bors always adds a single merge commit (possibly itself
|
||||
# including multiple merges for PRs) on the base branch.
|
||||
# That git command outputs the hash of the second merge commit (the one before
|
||||
# the topmost merge), which should be the base branch HEAD.
|
||||
# (CI_BASE_COMMIT is used by `can_fast_ci_run.py` to only build changes.)
|
||||
if test -z "${CI_BASE_COMMIT}" && is_bors_build ; then
|
||||
previous_merge="$(git log --merges --max-count 1 --skip 1 --pretty=format:%H)"
|
||||
export CI_BASE_COMMIT="${previous_merge}"
|
||||
fi
|
||||
# this function returns 0 when this build is building a merge queue branch.
|
||||
is_merge_queue_build() {
|
||||
startswith "gh-readonly-queue/" "${CI_BUILD_BRANCH}"
|
||||
}
|
||||
|
||||
# fullbuild logic
|
||||
# non-full-builds are those where can_fast_ci_run might reduce the build
|
||||
@ -216,8 +212,8 @@ fi
|
||||
# configurations.
|
||||
if [ -z "${QUICK_BUILD}" ]; then
|
||||
export QUICK_BUILD=0
|
||||
if is_bors_build ; then
|
||||
# always do full build for bors' branches
|
||||
if is_merge_queue_build; then
|
||||
# always do full build for merge queue' branches
|
||||
true
|
||||
elif [ ${FULL_BUILD} -eq 1 ]; then
|
||||
# full build if building nightly or full build requested by label
|
||||
@ -323,14 +319,6 @@ error() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# true if "$2" starts with "$1", false otherwise
|
||||
startswith() {
|
||||
case "${2}" in
|
||||
${1}*) true ;;
|
||||
*) false ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# if MURDOCK_HOOK is set, this function will execute it and pass on all it's
|
||||
# parameters. should the hook script exit with negative exit code, hook() makes
|
||||
# this script exit with error, too.
|
||||
|
@ -3,6 +3,8 @@ push:
|
||||
# these two enable potential bors support:
|
||||
- '^staging$'
|
||||
- '^trying$'
|
||||
# github merge trains:
|
||||
- '^gh-readonly-queue/'
|
||||
|
||||
pr:
|
||||
enable_comments: true
|
||||
|
@ -117,7 +117,6 @@ ifneq ($(RIOT_CI_BUILD),1)
|
||||
ifeq ($(MAKELEVEL),0)
|
||||
ifneq (,$(BOARDSDIR))
|
||||
$(warning Using BOARDSDIR is deprecated use EXTERNAL_BOARD_DIRS instead)
|
||||
$(info EXTERNAL_BOARD_DIRS can contain multiple folders separated by space)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -43,9 +43,21 @@ extern "C" {
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
#define UART_PIN_RX GPIO_PIN(0, 30)
|
||||
#define UART_PIN_TX GPIO_PIN(0, 31)
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{
|
||||
.dev = NRF_UARTE0,
|
||||
.rx_pin = GPIO_PIN(0, 30),
|
||||
.tx_pin = GPIO_PIN(0, 31),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_UNDEF,
|
||||
.cts_pin = GPIO_UNDEF,
|
||||
#endif
|
||||
.irqn = UARTE0_UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR (isr_uart0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -31,13 +31,23 @@
|
||||
|
||||
/**
|
||||
* @name UART configuration
|
||||
*
|
||||
* The CPU only supports one UART device, so we keep it simple
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
#define UART_PIN_RX 17
|
||||
#define UART_PIN_TX 18
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{ /* Mapped to USB virtual COM port */
|
||||
.dev = NRF_UART0,
|
||||
.rx_pin = GPIO_PIN(0, 17),
|
||||
.tx_pin = GPIO_PIN(0, 18),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_UNDEF,
|
||||
.cts_pin = GPIO_UNDEF,
|
||||
#endif
|
||||
.irqn = UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR isr_uart0
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -33,10 +33,21 @@ extern "C" {
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
/* UART pin configuration */
|
||||
#define UART_PIN_RX 25
|
||||
#define UART_PIN_TX 24
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{
|
||||
.dev = NRF_UART0,
|
||||
.rx_pin = GPIO_PIN(0, 25),
|
||||
.tx_pin = GPIO_PIN(0, 24),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_UNDEF,
|
||||
.cts_pin = GPIO_UNDEF,
|
||||
#endif
|
||||
.irqn = UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR isr_uart0
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -56,14 +56,6 @@ extern "C" {
|
||||
#define XTIMER_BACKOFF (19)
|
||||
/** @} */
|
||||
|
||||
/* The boards debug header only exports SWD, so JTAG-only pins PA15, PB3(*),
|
||||
* and PB4 can be remapped as regular GPIOs instead. (Note: PB3 is also used as
|
||||
* SWO. The user needs to take care to not enable SWO with the debugger while
|
||||
* at the same time PB3 is used as GPIO. But RIOT does not use SWO in any case,
|
||||
* so if a user adds this feature in her/his own code, she/he should be well
|
||||
* aware of this.)
|
||||
*/
|
||||
#define STM32F1_DISABLE_JTAG /**< Disable JTAG to allow pins being used as GPIOs */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -8,9 +8,10 @@
|
||||
|
||||
/**
|
||||
* @defgroup boards_common_esp32x ESP32x Common
|
||||
* @ingroup boards_common
|
||||
* @brief Definitions and configurations that are common for
|
||||
* all ESP32 boards.
|
||||
* all ESP32x boards.
|
||||
*
|
||||
* For detailed information about the ESP32, configuring and compiling RIOT
|
||||
* for ESP32 boards, please refer \ref esp32_riot.
|
||||
* For detailed information about ESP32x SoCs, configuring and compiling RIOT
|
||||
* for ESP32x boards, please refer \ref esp32_riot.
|
||||
*/
|
||||
|
@ -41,10 +41,13 @@ extern "C" {
|
||||
* @name Arduino's SPI buses
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief SPI_DEV(1) is connected to D11/D12/D13
|
||||
*/
|
||||
#if !defined(ARDUINO_SPI_D11D12D13) && defined(SPI_NUMOF)
|
||||
/**
|
||||
* @brief SPI_DEV(0) is connected to D11/D12/D13 for most Nucleo-64 boards
|
||||
*
|
||||
* This can be overwritten in `boards/nucleo-<foobar>/include/periph_conf.h` by
|
||||
* providing a custom `ARDUINO_SPI_D11D12D13`.
|
||||
*/
|
||||
#define ARDUINO_SPI_D11D12D13 SPI_DEV(0)
|
||||
#endif
|
||||
/** @} */
|
||||
|
@ -36,7 +36,11 @@ static const timer_conf_t timer_config[] = {
|
||||
{
|
||||
.dev = TIM2,
|
||||
.max = 0xffffffff,
|
||||
#if defined(RCC_APB1ENR_TIM2EN)
|
||||
.rcc_mask = RCC_APB1ENR_TIM2EN,
|
||||
#else
|
||||
.rcc_mask = RCC_APB1ENR1_TIM2EN,
|
||||
#endif
|
||||
.bus = APB1,
|
||||
.irqn = TIM2_IRQn
|
||||
},
|
||||
|
@ -20,10 +20,10 @@
|
||||
#ifndef PERIPH_CONF_H
|
||||
#define PERIPH_CONF_H
|
||||
|
||||
#include "periph_cpu.h"
|
||||
#include "cfg_clock_32_1.h"
|
||||
#include "cfg_rtt_default.h"
|
||||
#include "cfg_timer_default.h"
|
||||
#include "periph_cpu.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -33,9 +33,21 @@ extern "C" {
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
#define UART_PIN_RX GPIO_PIN(0, 11)
|
||||
#define UART_PIN_TX GPIO_PIN(0, 5)
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{ /* Mapped to USB virtual COM port */
|
||||
.dev = NRF_UARTE0,
|
||||
.rx_pin = GPIO_PIN(0, 11),
|
||||
.tx_pin = GPIO_PIN(0, 5),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_UNDEF,
|
||||
.cts_pin = GPIO_UNDEF,
|
||||
#endif
|
||||
.irqn = UARTE0_UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR (isr_uart0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,7 @@ config BOARD_ESP32S3_WT32_SC01_PLUS
|
||||
|
||||
select HAVE_FT5X06
|
||||
select HAVE_LCD_PARALLEL if MODULE_ST7796
|
||||
select HAVE_LCD_PARALLEL_LL_MCU if MODULE_ST7796
|
||||
select HAVE_MTD_SDCARD_DEFAULT
|
||||
select HAVE_ST7796
|
||||
|
||||
|
@ -29,6 +29,7 @@ endif
|
||||
|
||||
ifneq (,$(filter st7796,$(USEMODULE)))
|
||||
USEMODULE += lcd_parallel
|
||||
USEMODULE += lcd_parallel_ll_mcu
|
||||
endif
|
||||
|
||||
ifneq (,$(filter touch_dev,$(USEMODULE)))
|
||||
|
@ -29,13 +29,24 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name UART configuration
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
/* UART pin configuration */
|
||||
#define UART_PIN_RX 25
|
||||
#define UART_PIN_TX 24
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{ /* Mapped to USB virtual COM port */
|
||||
.dev = NRF_UART0,
|
||||
.rx_pin = GPIO_PIN(0, 25),
|
||||
.tx_pin = GPIO_PIN(0, 24),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_UNDEF,
|
||||
.cts_pin = GPIO_UNDEF,
|
||||
#endif
|
||||
.irqn = UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR isr_uart0
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -12,6 +12,13 @@ config BOARD_NRF51DK
|
||||
default y
|
||||
select BOARD_COMMON_NRF51
|
||||
select CPU_MODEL_NRF51X22XXAC
|
||||
select HAS_ARDUINO_ANALOG
|
||||
select HAS_ARDUINO_I2C
|
||||
select HAS_ARDUINO_PINS
|
||||
select HAS_ARDUINO_SHIELD_ISP
|
||||
select HAS_ARDUINO_SHIELD_UNO
|
||||
select HAS_ARDUINO_SPI
|
||||
select HAS_PERIPH_ADC
|
||||
select HAS_PERIPH_I2C
|
||||
select HAS_PERIPH_SPI
|
||||
select HAS_PERIPH_UART
|
||||
|
@ -1,11 +1,18 @@
|
||||
CPU_MODEL = nrf51x22xxac
|
||||
|
||||
# Put defined MCU peripherals here (in alphabetical order)
|
||||
FEATURES_PROVIDED += periph_adc
|
||||
FEATURES_PROVIDED += periph_i2c
|
||||
FEATURES_PROVIDED += periph_spi
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
FEATURES_PROVIDED += periph_uart_hw_fc
|
||||
FEATURES_PROVIDED += vdd_lc_filter_reg1
|
||||
FEATURES_PROVIDED += arduino_analog
|
||||
FEATURES_PROVIDED += arduino_i2c
|
||||
FEATURES_PROVIDED += arduino_pins
|
||||
FEATURES_PROVIDED += arduino_shield_isp
|
||||
FEATURES_PROVIDED += arduino_shield_uno
|
||||
FEATURES_PROVIDED += arduino_spi
|
||||
|
||||
# include common nrf51 based boards features
|
||||
include $(RIOTBOARD)/common/nrf51/Makefile.features
|
||||
|
123
boards/nrf51dk/include/arduino_iomap.h
Normal file
123
boards/nrf51dk/include/arduino_iomap.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Otto-von-Guericke-Universität Magdeburg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup boards_nrf51dk
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Mapping from MCU pins to Arduino pins
|
||||
*
|
||||
* You can use the defines in this file for simplified interaction with the
|
||||
* Arduino specific pin numbers.
|
||||
*
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
*/
|
||||
|
||||
#ifndef ARDUINO_IOMAP_H
|
||||
#define ARDUINO_IOMAP_H
|
||||
|
||||
#include "periph/gpio.h"
|
||||
#include "periph/adc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Arduino's SPI buses
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief SPI_DEV(0) is connected to D11/D12/D13
|
||||
*/
|
||||
/* D11/D12/D13 are on P0.25, P0.28, P0.29 */
|
||||
#define ARDUINO_SPI_D11D12D13 SPI_DEV(0)
|
||||
/* The ISP SPI bus is also connected to P0.25, P0.28, P0.29 */
|
||||
#define ARDUINO_SPI_ISP SPI_DEV(0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Arduino's I2C buses
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief The first I2C bus is where shields for the Arduino UNO/Mega expect
|
||||
* it
|
||||
*/
|
||||
#define ARDUINO_I2C_UNO I2C_DEV(0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Mapping of MCU pins to Arduino pins
|
||||
* @{
|
||||
*/
|
||||
/* P3 header on the nRF51DK */
|
||||
#define ARDUINO_PIN_0 GPIO_PIN(0, 12)
|
||||
#define ARDUINO_PIN_1 GPIO_PIN(0, 13)
|
||||
#define ARDUINO_PIN_2 GPIO_PIN(0, 14)
|
||||
#define ARDUINO_PIN_3 GPIO_PIN(0, 15)
|
||||
#define ARDUINO_PIN_4 GPIO_PIN(0, 16)
|
||||
#define ARDUINO_PIN_5 GPIO_PIN(0, 17)
|
||||
#define ARDUINO_PIN_6 GPIO_PIN(0, 18)
|
||||
#define ARDUINO_PIN_7 GPIO_PIN(0, 19)
|
||||
|
||||
/* P4 header on the nRF51DK */
|
||||
#define ARDUINO_PIN_8 GPIO_PIN(0, 20)
|
||||
#define ARDUINO_PIN_9 GPIO_PIN(0, 23)
|
||||
#define ARDUINO_PIN_10 GPIO_PIN(0, 24)
|
||||
#define ARDUINO_PIN_11 GPIO_PIN(0, 25)
|
||||
#define ARDUINO_PIN_12 GPIO_PIN(0, 28)
|
||||
#define ARDUINO_PIN_13 GPIO_PIN(0, 29)
|
||||
/* SCL and SDA on this header are not available as digital pins in the
|
||||
* Arduino world. It is P0.30 and P0.07 here, though. Also what would be
|
||||
* AREF in the Arduino world is P0.00 here */
|
||||
|
||||
/* P2 header on the nRF51DK */
|
||||
#define ARDUINO_PIN_14 GPIO_PIN(0, 1)
|
||||
#define ARDUINO_PIN_15 GPIO_PIN(0, 2)
|
||||
#define ARDUINO_PIN_16 GPIO_PIN(0, 3)
|
||||
#define ARDUINO_PIN_17 GPIO_PIN(0, 4)
|
||||
#define ARDUINO_PIN_18 GPIO_PIN(0, 5)
|
||||
#define ARDUINO_PIN_19 GPIO_PIN(0, 6)
|
||||
|
||||
#define ARDUINO_PIN_LAST 19
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Aliases for analog pins
|
||||
* @{
|
||||
*/
|
||||
#define ARDUINO_PIN_A0 ARDUINO_PIN_14
|
||||
#define ARDUINO_PIN_A1 ARDUINO_PIN_15
|
||||
#define ARDUINO_PIN_A2 ARDUINO_PIN_16
|
||||
#define ARDUINO_PIN_A3 ARDUINO_PIN_17
|
||||
#define ARDUINO_PIN_A4 ARDUINO_PIN_18
|
||||
#define ARDUINO_PIN_A5 ARDUINO_PIN_19
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Mapping of Arduino analog pins to RIOT ADC lines
|
||||
* @{
|
||||
*/
|
||||
#define ARDUINO_A0 ADC_LINE(0)
|
||||
#define ARDUINO_A1 ADC_LINE(1)
|
||||
#define ARDUINO_A2 ADC_LINE(2)
|
||||
#define ARDUINO_A3 ADC_LINE(3)
|
||||
#define ARDUINO_A4 ADC_LINE(4)
|
||||
#define ARDUINO_A5 ADC_LINE(5)
|
||||
|
||||
#define ARDUINO_ANALOG_PIN_LAST 5
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ARDUINO_IOMAP_H */
|
||||
/** @} */
|
@ -29,15 +29,24 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name UART configuration
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
/* UART pin configuration */
|
||||
#define UART_PIN_RX 11
|
||||
#define UART_PIN_TX 9
|
||||
#define UART_PIN_RTS 8
|
||||
#define UART_PIN_CTS 10
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{ /* Mapped to USB virtual COM port */
|
||||
.dev = NRF_UART0,
|
||||
.rx_pin = GPIO_PIN(0, 11),
|
||||
.tx_pin = GPIO_PIN(0, 9),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_PIN(0, 8),
|
||||
.cts_pin = GPIO_PIN(0, 10),
|
||||
#endif
|
||||
.irqn = UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR isr_uart0
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -73,6 +82,30 @@ static const i2c_conf_t i2c_config[] = {
|
||||
#define I2C_NUMOF ARRAY_SIZE(i2c_config)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name ADC configuration
|
||||
*
|
||||
* The ADC channels have a fixed mapping:
|
||||
*
|
||||
* | Channel | MCU Pin | Arduino pin on board |
|
||||
* |:---------- |:--------- |:------------------------------------- |
|
||||
* | AIN0 | P0.26 | -- (exposed, by no Arduino UNO pin) |
|
||||
* | AIN1 | P0.27 | -- (exposed, by no Arduino UNO pin) |
|
||||
* | AIN2 | P0.01 | A0 |
|
||||
* | AIN3 | P0.02 | A1 |
|
||||
* | AIN4 | P0.03 | A2 |
|
||||
* | AIN5 | P0.04 | A3 |
|
||||
* | AIN6 | P0.05 | A4 |
|
||||
* | AIN7 | P0.06 | A5 |
|
||||
*
|
||||
* Expose those on Arduino pins A0 to A5
|
||||
* @{
|
||||
*/
|
||||
static const adc_conf_t adc_config[] = {2, 3, 4, 5, 6, 7};
|
||||
|
||||
#define ADC_NUMOF ARRAY_SIZE(adc_config)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -29,15 +29,24 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name UART configuration
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
/* UART pin configuration */
|
||||
#define UART_PIN_RX 11
|
||||
#define UART_PIN_TX 9
|
||||
#define UART_PIN_RTS 8
|
||||
#define UART_PIN_CTS 10
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{
|
||||
.dev = NRF_UART0,
|
||||
.rx_pin = GPIO_PIN(0, 11),
|
||||
.tx_pin = GPIO_PIN(0, 9),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_PIN(0, 8),
|
||||
.cts_pin = GPIO_PIN(0, 10),
|
||||
#endif
|
||||
.irqn = UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR isr_uart0
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -35,9 +35,21 @@ extern "C" {
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
#define UART_PIN_RX GPIO_PIN(0, 19)
|
||||
#define UART_PIN_TX GPIO_PIN(0, 20)
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{
|
||||
.dev = NRF_UARTE0,
|
||||
.rx_pin = GPIO_PIN(0, 19),
|
||||
.tx_pin = GPIO_PIN(0, 20),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_UNDEF,
|
||||
.cts_pin = GPIO_UNDEF,
|
||||
#endif
|
||||
.irqn = UARTE0_UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR (isr_uart0)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -48,9 +48,21 @@ static const spi_conf_t spi_config[] = {
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
#define UART_PIN_RX GPIO_PIN(0, 8)
|
||||
#define UART_PIN_TX GPIO_PIN(0, 6)
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{ /* Mapped to USB virtual COM port */
|
||||
.dev = NRF_UARTE0,
|
||||
.rx_pin = GPIO_PIN(0, 8),
|
||||
.tx_pin = GPIO_PIN(0, 6),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_UNDEF,
|
||||
.cts_pin = GPIO_UNDEF,
|
||||
#endif
|
||||
.irqn = UARTE0_UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR (isr_uart0)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -35,14 +35,21 @@ extern "C" {
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
#define UART_IRQ_PRIO 1
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
/* UART pin configuration */
|
||||
#define UART_PIN_RX 16
|
||||
#define UART_PIN_TX 17
|
||||
#define UART_PIN_RTS 19
|
||||
#define UART_PIN_CTS 18
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR isr_uart0
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -16,8 +16,10 @@ config BOARD_NUCLEO_F030R8
|
||||
|
||||
# Put defined MCU peripherals here (in alphabetical order)
|
||||
select HAS_PERIPH_ADC
|
||||
select HAS_PERIPH_I2C
|
||||
select HAS_PERIPH_PWM
|
||||
select HAS_PERIPH_RTC
|
||||
select HAS_PERIPH_SPI
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_UART
|
||||
|
||||
|
@ -3,11 +3,13 @@ CPU_MODEL = stm32f030r8
|
||||
|
||||
# Put defined MCU peripherals here (in alphabetical order)
|
||||
FEATURES_PROVIDED += periph_adc
|
||||
FEATURES_PROVIDED += periph_i2c
|
||||
FEATURES_PROVIDED += periph_pwm
|
||||
# For RTC, Nucleos with MB1136 C-02 or MB1136 C-03 -sticker on it have the
|
||||
# required LSE oscillator provided on the X2 slot.
|
||||
# See Nucleo User Manual UM1724 section 5.6.2.
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_spi
|
||||
FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include "periph_cpu.h"
|
||||
#include "clk_conf.h"
|
||||
#include "cfg_i2c1_pb8_pb9.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -16,9 +16,11 @@ config BOARD_NUCLEO_F070RB
|
||||
|
||||
# Put defined MCU peripherals here (in alphabetical order)
|
||||
select HAS_PERIPH_ADC
|
||||
select HAS_PERIPH_DMA
|
||||
select HAS_PERIPH_I2C
|
||||
select HAS_PERIPH_PWM
|
||||
select HAS_PERIPH_RTC
|
||||
select HAS_PERIPH_SPI
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_UART
|
||||
|
||||
|
@ -3,12 +3,14 @@ CPU_MODEL = stm32f070rb
|
||||
|
||||
# Put defined MCU peripherals here (in alphabetical order)
|
||||
FEATURES_PROVIDED += periph_adc
|
||||
FEATURES_PROVIDED += periph_dma
|
||||
FEATURES_PROVIDED += periph_i2c
|
||||
FEATURES_PROVIDED += periph_pwm
|
||||
# For RTC, Nucleos with MB1136 C-02 or MB1136 C-03 -sticker on it have the
|
||||
# required LSE oscillator provided on the X2 slot.
|
||||
# See Nucleo User Manual UM1724 section 5.6.2.
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_spi
|
||||
FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
|
||||
|
@ -102,6 +102,21 @@ static const uart_conf_t uart_config[] = {
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DMA streams configuration
|
||||
* @{
|
||||
*/
|
||||
static const dma_conf_t dma_config[] = {
|
||||
{ .stream = 1 },
|
||||
{ .stream = 2 },
|
||||
};
|
||||
|
||||
#define DMA_SHARED_ISR_0 isr_dma1_ch2_3_dma2_ch1_2
|
||||
#define DMA_SHARED_ISR_0_STREAMS { 0, 1 } /* Indexes 0 and 1 of dma_config share the same isr */
|
||||
|
||||
#define DMA_NUMOF ARRAY_SIZE(dma_config)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name PWM configuration
|
||||
* @{
|
||||
@ -148,6 +163,42 @@ static const adc_conf_t adc_config[] = {
|
||||
#define ADC_NUMOF ARRAY_SIZE(adc_config)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name SPI configuration
|
||||
*
|
||||
* To find appriopate device and pins find in the MCU datasheet table
|
||||
* concerning "Alternate function AF0 to AF7" a texts similar to
|
||||
* SPI[X]_MOSI/_MISO/_SCK where SPI[X] is SPI device.
|
||||
*
|
||||
* For nucleo-f070rb this information is in the datasheet, Tables 11, 12 and 13,
|
||||
* page 30.
|
||||
* @{
|
||||
*/
|
||||
static const spi_conf_t spi_config[] = {
|
||||
{
|
||||
.dev = SPI1,
|
||||
.mosi_pin = GPIO_PIN(PORT_A, 7),
|
||||
.miso_pin = GPIO_PIN(PORT_A, 6),
|
||||
.sclk_pin = GPIO_PIN(PORT_A, 5),
|
||||
.cs_pin = GPIO_UNDEF,
|
||||
.mosi_af = GPIO_AF0,
|
||||
.miso_af = GPIO_AF0,
|
||||
.sclk_af = GPIO_AF0,
|
||||
.cs_af = GPIO_AF0,
|
||||
.rccmask = RCC_APB2ENR_SPI1EN,
|
||||
.apbbus = APB2,
|
||||
#ifdef MODULE_PERIPH_DMA
|
||||
.tx_dma = 1,
|
||||
.tx_dma_chan = 0,
|
||||
.rx_dma = 0,
|
||||
.rx_dma_chan = 0,
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#define SPI_NUMOF ARRAY_SIZE(spi_config)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,9 +1,2 @@
|
||||
# load the common Makefile.include for Nucleo boards
|
||||
include $(RIOTBOARD)/common/nucleo64/Makefile.include
|
||||
|
||||
# On-board debugger uses SWD, so JTAG-only pins PA15, PB3(*), and PB4 can be
|
||||
# remapped as regular GPIOs instead. (Note: PB3 is also used as SWO. The user
|
||||
# needs to take care to not enable SWO with the debugger while at the same time
|
||||
# PB3 is used as GPIO. But RIOT does not use SWO in any case, so if a user adds
|
||||
# this feature in her/his own code, she/he should be well aware of this.)
|
||||
CFLAGS += -DSTM32F1_DISABLE_JTAG
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "periph_cpu.h"
|
||||
#include "clk_conf.h"
|
||||
#include "cfg_timer_tim2.h"
|
||||
#include "cfg_timer_tim2_tim15_tim16.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -8,6 +8,33 @@
|
||||
The Nucleo-L433RC is a board from ST's Nucleo family supporting a ARM
|
||||
Cortex-M4 STM32L433RC microcontroller with 64KiB of RAM and 256KiB of Flash.
|
||||
|
||||
### Hardware
|
||||
|
||||
![Nucleo64 L433RC](https://www.st.com/bin/ecommerce/api/image.PF264788.en.feature-description-include-personalized-no-cpn-large.jpg)
|
||||
|
||||
### MCU
|
||||
|
||||
| MCU | STM32L476RG |
|
||||
|:---------- |:------------------- |
|
||||
| Family | ARM Cortex-M4 |
|
||||
| Vendor | ST Microelectronics |
|
||||
| RAM | 64KiB |
|
||||
| Flash | 256KiB |
|
||||
| Frequency | up to 80MHz |
|
||||
| FPU | yes |
|
||||
| Timers | 11 (2x watchdog, 1 SysTick, 7x 16-bit, 1x 32-bit) |
|
||||
| ADCs | 1x 12-bit |
|
||||
| UARTs | 5 (four USARTs and one Low-Power UART) |
|
||||
| SPIs | 3 |
|
||||
| I2Cs | 3 |
|
||||
| RTC | 1 |
|
||||
| CAN | 1 |
|
||||
| Vcc | 1.71 V - 3.6V |
|
||||
| Datasheet | [Datasheet](https://www.st.com/resource/en/datasheet/stm32l433rc.pdf) |
|
||||
| Reference Manual | [Reference Manual](https://www.st.com/resource/en/reference_manual/rm0394-stm32l41xxx42xxx43xxx44xxx45xxx46xxx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf) |
|
||||
| Programming Manual | [Programming Manual](http://www.st.com/content/ccc/resource/technical/document/programming_manual/6c/3a/cb/e7/e4/ea/44/9b/DM00046982.pdf/files/DM00046982.pdf/jcr:content/translations/en.DM00046982.pdf) |
|
||||
| Board Manual | [Board Manual](http://www.st.com/resource/en/user_manual/um2206-stm32-nucleo64p-boards-mb1319-stmicroelectronics.pdf) |
|
||||
|
||||
### Flashing the Board Using ST-LINK Removable Media
|
||||
|
||||
On-board ST-LINK programmer provides via composite USB device removable media.
|
||||
|
@ -30,6 +30,16 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Arduino's I2C buses
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief The first I2C bus is where shields for the Arduino UNO expect it
|
||||
*/
|
||||
#define ARDUINO_I2C_UNO I2C_DEV(0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Mapping of MCU pins to Arduino pins
|
||||
* @{
|
||||
|
@ -117,7 +117,12 @@ static const spi_conf_t spi_config[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
#define SPI_NUMOF ARRAY_SIZE(spi_config)
|
||||
#define SPI_NUMOF ARRAY_SIZE(spi_config)
|
||||
/**
|
||||
* @brief Provide ARDUINO_SPI_D11D12D13 explicitly, as the first SPI
|
||||
* interface is connected to the radio.
|
||||
*/
|
||||
#define ARDUINO_SPI_D11D12D13 SPI_DEV(1)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -26,8 +26,11 @@ config BOARD_P_NUCLEO_WB55
|
||||
|
||||
# Put other features for this board (in alphabetical order)
|
||||
select HAS_ARDUINO_ANALOG
|
||||
select HAS_ARDUINO_I2C
|
||||
select HAS_ARDUINO_PINS
|
||||
select HAS_ARDUINO_SHIELD_UNO
|
||||
select HAS_ARDUINO_SPI
|
||||
select HAS_ARDUINO_UART
|
||||
select HAS_RIOTBOOT
|
||||
select HAS_TINYUSB_DEVICE
|
||||
|
||||
|
@ -14,7 +14,10 @@ FEATURES_PROVIDED += periph_usbdev
|
||||
|
||||
# Put other features for this board (in alphabetical order)
|
||||
FEATURES_PROVIDED += arduino_analog
|
||||
FEATURES_PROVIDED += arduino_i2c
|
||||
FEATURES_PROVIDED += arduino_pins
|
||||
FEATURES_PROVIDED += arduino_shield_uno
|
||||
FEATURES_PROVIDED += arduino_spi
|
||||
FEATURES_PROVIDED += arduino_uart
|
||||
FEATURES_PROVIDED += riotboot
|
||||
FEATURES_PROVIDED += tinyusb_device
|
||||
|
@ -8,29 +8,37 @@ Hardware
|
||||
|
||||
![st-nucleo-wb55](https://miro.medium.com/max/700/1*9OG-4Ix4EzHX9uBpMve2IA.jpeg)
|
||||
|
||||
## Pinout
|
||||
|
||||
@image html pinouts/p-nucleo-wb55.svg "Pinout for the p-nucleo-wb55" width=50%
|
||||
|
||||
MCU
|
||||
---
|
||||
|
||||
| MCU | STM32WB55RG |
|
||||
|:---------- |:------------------------------- |
|
||||
| Family | ARM Cortex-M4 |
|
||||
| Vendor | ST Microelectronics |
|
||||
| RAM | 256KB |
|
||||
| Flash | 512KB |
|
||||
| Frequency | 64MHz |
|
||||
| FPU | yes |
|
||||
| Timers | 8 (3x 16-bit, 1x 32-bit [TIM5]) |
|
||||
| LPTimers | 2x 16-bit |
|
||||
| ADCs | 1x 19-channel 12-bit |
|
||||
| UARTs | 1 |
|
||||
| LUARTs | 1 |
|
||||
| SPIs | 1 |
|
||||
| I2Cs | 2 |
|
||||
| RTC | 1 |
|
||||
| Vcc | 1.65V - 3.6V |
|
||||
| Datasheet | [Datasheet](https://www.st.com/resource/en/datasheet/stm32wb55cc.pdf)|
|
||||
| Reference Manual | [Reference Manual](https://www.st.com/resource/en/datasheet/stm32wb55cc.pdf) |
|
||||
| User Manual | [User Manual](https://www.st.com/content/ccc/resource/technical/document/user_manual/group1/13/58/22/1a/f2/ff/43/5c/DM00517423/files/DM00517423.pdf/jcr:content/translations/en.DM00517423.pdf) |
|
||||
| MCU | STM32WB55RG |
|
||||
|:----------------- |:------------------------------------- |
|
||||
| Family | ARM Cortex-M4 |
|
||||
| Vendor | ST Microelectronics |
|
||||
| RAM | 256 KiB |
|
||||
| Flash | 512 KiB |
|
||||
| Frequency | 64 MHz |
|
||||
| FPU | yes |
|
||||
| Timers | 8 (3x 16-bit, 1x 32-bit [TIM5]) |
|
||||
| LPTimers | 2x 16-bit |
|
||||
| ADCs | 1x 19-channel 12-bit |
|
||||
| UARTs | 1 |
|
||||
| LUARTs | 1 |
|
||||
| SPIs | 1 |
|
||||
| I2Cs | 2 |
|
||||
| RTC | 1 |
|
||||
| Vcc | 1.65V - 3.6V |
|
||||
| Datasheet | [Datasheet][Datasheet] |
|
||||
| Reference Manual | [Reference Manual][Reference Manual] |
|
||||
| User Manual | [User Manual][User Manual] |
|
||||
|
||||
[Datasheet]: https://www.st.com/resource/en/datasheet/stm32wb55cc.pdf
|
||||
[Reference Manual]: https://www.st.com/resource/en/reference_manual/rm0434-multiprotocol-wireless-32bit-mcu-armbased-cortexm4-with-fpu-bluetooth-lowenergy-and-802154-radio-solution-stmicroelectronics.pdf
|
||||
[User Manual]: https://www.st.com/content/ccc/resource/technical/document/user_manual/group1/13/58/22/1a/f2/ff/43/5c/DM00517423/files/DM00517423.pdf/jcr:content/translations/en.DM00517423.pdf
|
||||
|
||||
Overview
|
||||
========
|
||||
@ -82,25 +90,25 @@ User Interface
|
||||
Implementation Status
|
||||
---------------------
|
||||
|
||||
| Device | ID | Supported | Comments |
|
||||
|:---------------- |:----------------- |:------- |:------- |
|
||||
| MCU | stm32wb | yes | |
|
||||
| | M0+ co-processor | no | |
|
||||
| | BLE | no | |
|
||||
| | 802.15.4 | no | |
|
||||
| Low-level driver | GPIO | yes | |
|
||||
| | UART | yes | UART1 |
|
||||
| | LPUART | yes | LPUART1 |
|
||||
| | I2C | yes | I2C1 |
|
||||
| | SPI | yes | |
|
||||
| | ADC | yes | |
|
||||
| | RTT | yes | |
|
||||
| | RTC | yes | |
|
||||
| | RNG | yes | |
|
||||
| | Timer | yes | TIM2 |
|
||||
| | WDT | yes | |
|
||||
| | USB | yes | |
|
||||
| | PWM | no | |
|
||||
| | AES | no | |
|
||||
| Device | ID | Supported | Comments |
|
||||
|:----------------- |:----------------- |:--------- |:--------- |
|
||||
| MCU | stm32wb | yes | |
|
||||
| | M0+ co-processor | no | |
|
||||
| | BLE | no | |
|
||||
| | 802.15.4 | no | |
|
||||
| Low-level driver | GPIO | yes | |
|
||||
| | UART | yes | UART1 |
|
||||
| | LPUART | yes | LPUART1 |
|
||||
| | I2C | yes | I2C1 |
|
||||
| | SPI | yes | |
|
||||
| | ADC | yes | |
|
||||
| | RTT | yes | |
|
||||
| | RTC | yes | |
|
||||
| | RNG | yes | |
|
||||
| | Timer | yes | TIM2 |
|
||||
| | WDT | yes | |
|
||||
| | USB | yes | |
|
||||
| | PWM | no | |
|
||||
| | AES | no | |
|
||||
|
||||
*/
|
||||
|
@ -88,6 +88,33 @@ extern "C" {
|
||||
#define ARDUINO_ANALOG_PIN_LAST 5
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Arduino's default UART device
|
||||
* @{
|
||||
*/
|
||||
#define ARDUINO_UART_D0D1 UART_DEV(1)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Arduino's I2C buses
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief The only configured I2C
|
||||
*/
|
||||
#define ARDUINO_I2C_UNO I2C_DEV(0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Arduino's SPI buses
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief SPI_DEV(0) is connected to D11/D12/D13
|
||||
*/
|
||||
#define ARDUINO_SPI_D11D12D13 SPI_DEV(0)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -50,9 +50,21 @@ static const spi_conf_t spi_config[] = {
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
#define UART_PIN_RX GPIO_PIN(0, 4)
|
||||
#define UART_PIN_TX GPIO_PIN(0, 5)
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{
|
||||
.dev = NRF_UARTE0,
|
||||
.rx_pin = GPIO_PIN(0, 4),
|
||||
.tx_pin = GPIO_PIN(0, 5),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_UNDEF,
|
||||
.cts_pin = GPIO_UNDEF,
|
||||
#endif
|
||||
.irqn = UARTE0_UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR (isr_uart0)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -18,6 +18,7 @@ config BOARD_SAME54_XPRO
|
||||
select HAS_PERIPH_RTC
|
||||
select HAS_PERIPH_RTT
|
||||
select HAS_PERIPH_PWM
|
||||
select HAS_PERIPH_FREQM
|
||||
select HAS_PERIPH_SDMMC
|
||||
select HAS_PERIPH_SPI
|
||||
select HAS_PERIPH_TIMER
|
||||
|
@ -14,6 +14,7 @@ FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
FEATURES_PROVIDED += periph_adc
|
||||
FEATURES_PROVIDED += periph_usbdev
|
||||
FEATURES_PROVIDED += periph_freqm
|
||||
|
||||
# Put other features for this board (in alphabetical order)
|
||||
FEATURES_PROVIDED += riotboot
|
||||
|
@ -3,4 +3,11 @@
|
||||
# debugger.
|
||||
TTY_BOARD_FILTER := --model 'EDBG CMSIS-DAP'
|
||||
|
||||
# Overwrite GCLK definitions, so that GCLK_IO[2..7] can be connected to GPIOs.
|
||||
# This way the frequency of signals, connected to these pins, can be measured
|
||||
# with the FREQM peripheral.
|
||||
CFLAGS += -DSAM0_GCLK_TIMER=8
|
||||
CFLAGS += -DSAM0_GCLK_PERIPH=9
|
||||
CFLAGS += -DSAM0_GCLK_100MHZ=10
|
||||
|
||||
include $(RIOTMAKE)/boards/sam0.inc.mk
|
||||
|
@ -406,6 +406,18 @@ static const sam0_common_gmac_config_t sam_gmac_config[] = {
|
||||
};
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name FREQM peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
static const freqm_config_t freqm_config[] = {
|
||||
{
|
||||
.pin = GPIO_PIN(PB, 17),
|
||||
.gclk_src = SAM0_GCLK_32KHZ
|
||||
}
|
||||
};
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -33,9 +33,21 @@ extern "C" {
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
#define UART_PIN_RX GPIO_PIN(0, 2)
|
||||
#define UART_PIN_TX GPIO_PIN(0, 3)
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{
|
||||
.dev = NRF_UARTE0,
|
||||
.rx_pin = GPIO_PIN(0, 2),
|
||||
.tx_pin = GPIO_PIN(0, 3),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_UNDEF,
|
||||
.cts_pin = GPIO_UNDEF,
|
||||
#endif
|
||||
.irqn = UARTE0_UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR (isr_uart0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -29,13 +29,24 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name UART configuration
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
#define UART_NUMOF (1U)
|
||||
/* UART pin configuration */
|
||||
#define UART_PIN_RX 1
|
||||
#define UART_PIN_TX 2
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{ /* Mapped to USB virtual COM port */
|
||||
.dev = NRF_UART0,
|
||||
.rx_pin = GPIO_PIN(0, 1),
|
||||
.tx_pin = GPIO_PIN(0, 2),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_UNDEF,
|
||||
.cts_pin = GPIO_UNDEF,
|
||||
#endif
|
||||
.irqn = UART0_IRQn,
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
#define UART_0_ISR isr_uart0
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -7,4 +7,8 @@ ifneq (,$(filter printf_float,$(USEMODULE)))
|
||||
LINKFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm
|
||||
endif
|
||||
|
||||
# Add aliases for flash_printf, flash_fprintf, flash_snprintf:
|
||||
LINKFLAGS += -Wl,--defsym=flash_printf=printf_P
|
||||
LINKFLAGS += -Wl,--defsym=flash_fprintf=fprintf_P
|
||||
LINKFLAGS += -Wl,--defsym=flash_snprintf=snprintf_P
|
||||
include $(RIOTMAKE)/arch/avr8.inc.mk
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define FLASH_UTILS_ARCH_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -35,20 +35,68 @@ extern "C" {
|
||||
#define FLASH_ATTR __flash
|
||||
#define PRIsflash "S"
|
||||
#define TO_FLASH(x) __extension__({static FLASH_ATTR const char __c[] = (x); &__c[0];})
|
||||
#define flash_strcmp strcmp_P
|
||||
#define flash_strncmp strncmp_P
|
||||
#define flash_strlen strlen_P
|
||||
#define flash_strcpy strcpy_P
|
||||
#define flash_strncpy strncpy_P
|
||||
#define flash_printf printf_P
|
||||
/* avrlibc seemingly forgot to provide vprintf_P(), but vfprintf_P() is there */
|
||||
#define flash_vprintf(fmt, arglist) vfprintf_P(stdout, fmt, arglist)
|
||||
#define flash_fprintf fprintf_P
|
||||
#define flash_vfprintf vfprintf_P
|
||||
#define flash_snprintf snprintf_P
|
||||
#define flash_vsnprintf vsnprintf_P
|
||||
#define flash_puts puts_P
|
||||
#define flash_memcpy memcpy_P
|
||||
|
||||
static inline int flash_strcmp(const char *ram, FLASH_ATTR const char *flash)
|
||||
{
|
||||
return strcmp_P(ram, (const char *)flash);
|
||||
}
|
||||
|
||||
static inline int flash_strncmp(const char *ram, FLASH_ATTR const char *flash, size_t n)
|
||||
{
|
||||
return strncmp_P(ram, (const char *)flash, n);
|
||||
}
|
||||
|
||||
static inline size_t flash_strlen(FLASH_ATTR const char *flash)
|
||||
{
|
||||
return strlen_P((const char *)flash);
|
||||
}
|
||||
|
||||
static inline char * flash_strcpy(char *ram, FLASH_ATTR const char *flash)
|
||||
{
|
||||
return strcpy_P(ram, (const char *)flash);
|
||||
}
|
||||
|
||||
static inline char * flash_strncpy(char *ram, FLASH_ATTR const char *flash, size_t n)
|
||||
{
|
||||
return strncpy_P(ram, (const char *)flash, n);
|
||||
}
|
||||
|
||||
|
||||
static inline int flash_vprintf(FLASH_ATTR const char *flash, va_list args)
|
||||
{
|
||||
/* vprintf_P() is not provided by avr-libc. But vfprintf_P() with
|
||||
* stdout as stream can be used to implement it */
|
||||
return vfprintf_P(stdout, (const char *)flash, args);
|
||||
}
|
||||
|
||||
static inline int flash_vfprintf(FILE *stream, FLASH_ATTR const char *flash,
|
||||
va_list args)
|
||||
{
|
||||
return vfprintf_P(stream, (const char *)flash, args);
|
||||
}
|
||||
|
||||
static inline int flash_vsnprintf(char *buf, size_t buf_len,
|
||||
FLASH_ATTR const char *flash, va_list args)
|
||||
{
|
||||
return vsnprintf_P(buf, buf_len, (const char *)flash, args);
|
||||
}
|
||||
|
||||
static inline void flash_puts(FLASH_ATTR const char *flash)
|
||||
{
|
||||
puts_P((const char *)flash);
|
||||
}
|
||||
|
||||
static inline void * flash_memcpy(void *dest, FLASH_ATTR const void *src,
|
||||
size_t n)
|
||||
{
|
||||
return memcpy_P(dest, (const void *)src, n);
|
||||
}
|
||||
|
||||
/* aliases need to be provided by the linker, as passing through va-args is
|
||||
* not possible */
|
||||
int flash_printf(FLASH_ATTR const char *flash, ...);
|
||||
int flash_fprintf(FILE *stream, FLASH_ATTR const char *flash, ...);
|
||||
int flash_snprintf(char *buf, size_t buf_len, FLASH_ATTR const char *flash, ...);
|
||||
|
||||
#endif /* Doxygen */
|
||||
|
||||
|
15
cpu/avr8_common/work_around_for_shitty_ubuntu_toolchain.c
Normal file
15
cpu/avr8_common/work_around_for_shitty_ubuntu_toolchain.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <avr/pgmspace.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* The outdated linker from Ubuntu's toolchain contains a bug in which it will
|
||||
* garbage collect symbols referenced only by --defsym= command line options,
|
||||
* and subsequently complain that the symbols are not defined. Adding other
|
||||
* references to those symbols from an unused function makes that buggy linker
|
||||
* happy. Since this function is never used, it will be garbage collected and
|
||||
* not impact the ROM size. */
|
||||
void work_around_for_shitty_ubuntu_toolchain_and_not_expected_to_be_called(void)
|
||||
{
|
||||
printf_P(NULL);
|
||||
fprintf_P(stdout, NULL);
|
||||
snprintf_P(NULL, 0, NULL);
|
||||
}
|
@ -35,6 +35,7 @@ rsource "bootloader/Kconfig"
|
||||
rsource "esp-ble-nimble/Kconfig"
|
||||
rsource "esp-idf/Kconfig"
|
||||
rsource "esp-idf-api/Kconfig"
|
||||
rsource "esp-lcd/Kconfig"
|
||||
rsource "periph/Kconfig"
|
||||
|
||||
endif
|
||||
|
@ -29,6 +29,10 @@ ifneq (, $(filter esp_freertos, $(USEMODULE)))
|
||||
DIRS += freertos
|
||||
endif
|
||||
|
||||
ifneq (, $(filter esp_lcd, $(USEMODULE)))
|
||||
DIRS += esp-lcd
|
||||
endif
|
||||
|
||||
ifneq (, $(filter stdio_usb_serial_jtag, $(USEMODULE)))
|
||||
DIRS += stdio_usb_serial_jtag
|
||||
endif
|
||||
|
@ -128,6 +128,12 @@ ifneq (,$(filter esp_idf_heap,$(USEMODULE)))
|
||||
USEPKG += tlsf
|
||||
endif
|
||||
|
||||
ifneq (,$(filter lcd_parallel_ll_mcu,$(USEMODULE)))
|
||||
USEMODULE += esp_lcd
|
||||
USEMODULE += esp_idf_lcd
|
||||
USEMODULE += esp_idf_heap
|
||||
endif
|
||||
|
||||
ifneq (,$(filter mtd periph_flashpage,$(USEMODULE)))
|
||||
USEMODULE += esp_idf_spi_flash
|
||||
endif
|
||||
|
@ -113,6 +113,7 @@ PSEUDOMODULES += esp_hw_counter
|
||||
PSEUDOMODULES += esp_idf_gpio_hal
|
||||
PSEUDOMODULES += esp_i2c_hw
|
||||
PSEUDOMODULES += esp_jtag
|
||||
PSEUDOMODULES += esp_lcd_gpio
|
||||
PSEUDOMODULES += esp_rtc_timer_32k
|
||||
PSEUDOMODULES += esp_spi_ram
|
||||
PSEUDOMODULES += esp_spi_oct
|
||||
@ -167,6 +168,10 @@ ifneq (,$(filter esp_spi_ram,$(USEMODULE)))
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_hw_support/include/soc/$(CPU_FAM)
|
||||
endif
|
||||
|
||||
ifneq (,$(filter esp_idf_lcd,$(USEMODULE)))
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_lcd/include
|
||||
endif
|
||||
|
||||
ifneq (,$(filter esp_idf_spi_flash,$(USEMODULE)))
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/spi_flash/include
|
||||
endif
|
||||
|
@ -26,6 +26,7 @@ rsource "eth/Kconfig"
|
||||
rsource "event/Kconfig"
|
||||
rsource "gpio/Kconfig"
|
||||
rsource "heap/Kconfig"
|
||||
rsource "lcd/Kconfig"
|
||||
rsource "nvs_flash/Kconfig"
|
||||
rsource "rmt/Kconfig"
|
||||
rsource "spi_flash/Kconfig"
|
||||
|
@ -36,6 +36,10 @@ ifneq (,$(filter esp_idf_heap,$(USEMODULE)))
|
||||
DIRS += heap
|
||||
endif
|
||||
|
||||
ifneq (,$(filter esp_idf_lcd,$(USEMODULE)))
|
||||
DIRS += lcd
|
||||
endif
|
||||
|
||||
ifneq (,$(filter esp_idf_nvs_flash,$(USEMODULE)))
|
||||
DIRS += nvs_flash
|
||||
endif
|
||||
|
@ -10,6 +10,7 @@ config MODULE_ESP_IDF_HEAP
|
||||
bool
|
||||
depends on TEST_KCONFIG
|
||||
depends on MODULE_ESP_IDF
|
||||
default y if MODULE_LCD_PARALLEL_LL_MCU
|
||||
select PACKAGE_TLSF
|
||||
help
|
||||
ESP-IDF heap library. This library is required if external SPI RAM
|
||||
|
16
cpu/esp32/esp-idf/lcd/Kconfig
Normal file
16
cpu/esp32/esp-idf/lcd/Kconfig
Normal file
@ -0,0 +1,16 @@
|
||||
# Copyright (c) 2022 Gunar Schorcht
|
||||
#
|
||||
# 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 MODULE_ESP_IDF_LCD
|
||||
bool
|
||||
depends on TEST_KCONFIG
|
||||
depends on MODULE_ESP_IDF
|
||||
|
||||
default y if MODULE_LCD_PARALLEL_LL_MCU
|
||||
|
||||
help
|
||||
ESP-IDF code for peripheral GPIO.
|
36
cpu/esp32/esp-idf/lcd/Makefile
Normal file
36
cpu/esp32/esp-idf/lcd/Makefile
Normal file
@ -0,0 +1,36 @@
|
||||
MODULE = esp_idf_lcd
|
||||
|
||||
# source files to be compiled for this module
|
||||
ESP32_SDK_SRC = \
|
||||
components/esp_lcd/src/esp_lcd_common.c \
|
||||
components/esp_lcd/src/esp_lcd_panel_io.c \
|
||||
components/esp_pm/pm_locks.c \
|
||||
components/soc/$(CPU_FAM)/lcd_periph.c \
|
||||
#
|
||||
|
||||
ifeq (esp32s3,$(CPU_FAM))
|
||||
ESP32_SDK_SRC += \
|
||||
components/driver/gdma.c \
|
||||
components/esp_lcd/src/esp_lcd_panel_io_i80.c \
|
||||
components/hal/gdma_hal.c \
|
||||
components/hal/lcd_hal.c \
|
||||
components/soc/$(CPU_FAM)/gdma_periph.c \
|
||||
#
|
||||
else ifneq (,$(filter esp32 esp32s2,$(CPU_FAM)))
|
||||
ESP32_SDK_SRC = \
|
||||
components/driver/i2s.c \
|
||||
components/esp_lcd/src/esp_lcd_panel_io_i2s.c \
|
||||
components/hal/i2s_hal.c \
|
||||
#
|
||||
endif
|
||||
|
||||
# additional include pathes required by this module
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_lcd/include
|
||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_lcd/interface
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
|
||||
ESP32_SDK_BIN = $(BINDIR)/$(MODULE)
|
||||
|
||||
include ../esp_idf.mk
|
||||
include ../esp_idf_cflags.mk
|
54
cpu/esp32/esp-lcd/Kconfig
Normal file
54
cpu/esp32/esp-lcd/Kconfig
Normal file
@ -0,0 +1,54 @@
|
||||
# Copyright (c) 2023 Gunar Schorcht
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
menuconfig MODULE_ESP_LCD
|
||||
bool "Enable LCD low-level parallel interface driver"
|
||||
depends on MODULE_LCD
|
||||
default y if HAVE_LCD_PARALLEL_LL_MCU
|
||||
help
|
||||
Enabe the MCU-driven low-level MCU 8080 8-/16-bit parallel interface
|
||||
driver.
|
||||
|
||||
if MODULE_ESP_LCD
|
||||
|
||||
config MODULE_ESP_LCD_GPIO
|
||||
bool "GPIO-driven low-level parallel interface driver"
|
||||
depends on !CPU_FAM_ESP32 && !CPU_FAM_ESP32S2 && !CPU_FAM_ESP32S3
|
||||
default y
|
||||
help
|
||||
The ESP32x SoC variant used does not have a peripheral for the parallel
|
||||
low-level interface. However, it can be emulated with special low-level
|
||||
GPIO operations. It is faster than the GPIO-driven 8-/16-bit parallel
|
||||
interface implemented in the LCD driver, but requires 4 kByte RAM for
|
||||
8-bit data bus width and 8 kByte RAM for 16-bit data bus width.
|
||||
|
||||
config LCD_WRITE_CLOCK_MHZ
|
||||
int "LCD write clock rate in MHz"
|
||||
range 1 80
|
||||
depends on CPU_FAM_ESP32 || CPU_FAM_ESP32S2 || CPU_FAM_ESP32S3
|
||||
default 10 if CPU_FAM_ESP32
|
||||
default 40 if CPU_FAM_ESP32S2
|
||||
default 20 if CPU_FAM_ESP32S3
|
||||
help
|
||||
Defines the clock rate that is used for the LCD write signal. It
|
||||
depends on used ESP32x SoC variant and used display interface.
|
||||
|
||||
config LCD_DATA_BUF_SIZE
|
||||
int "LCD data buffer size in byte"
|
||||
depends on CPU_FAM_ESP32 || CPU_FAM_ESP32S2 || CPU_FAM_ESP32S3
|
||||
default 512
|
||||
help
|
||||
Defines the size of the buffers used to write data to the LCD
|
||||
screen. Since double buffering is used, there are two buffers
|
||||
of this size. One buffer is used first by the LCD driver to
|
||||
write the data that needs to be transferred to the LCD, and
|
||||
one buffer from which the DMA then transfers the data to the
|
||||
LCD peripherals. This allows data to be written before the
|
||||
DMA transfer is complete. The larger the buffers, the better
|
||||
the performance, but the higher the memory requirements.
|
||||
|
||||
endif
|
9
cpu/esp32/esp-lcd/Makefile
Normal file
9
cpu/esp32/esp-lcd/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
MODULE = esp_lcd
|
||||
|
||||
ifneq (,$(filter esp32 esp32s2 esp32s3,$(CPU_FAM)))
|
||||
SRC = esp_lcd_mcu.c
|
||||
else
|
||||
SRC = esp_lcd_gpio.c
|
||||
endif
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
269
cpu/esp32/esp-lcd/esp_lcd_gpio.c
Normal file
269
cpu/esp32/esp-lcd/esp_lcd_gpio.c
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Gunar Schorcht
|
||||
*
|
||||
* 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_esp32
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief GPIO-driven low-Level parallel interface implementation for LCDs
|
||||
*
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "periph/gpio.h"
|
||||
#include "lcd.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
#if MODULE_ESP_LCD_GPIO
|
||||
|
||||
#include "soc/gpio_reg.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t set_mask_0; /* port 0 set mask */
|
||||
uint32_t set_mask_1; /* port 0 set mask */
|
||||
uint32_t clr_mask_0; /* port 1 clear mask */
|
||||
uint32_t clr_mask_1; /* port 1 clear mask */
|
||||
} _pin_mask_t;
|
||||
|
||||
static _pin_mask_t _low_byte_masks[256] = {};
|
||||
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
static _pin_mask_t _high_byte_masks[256] = {};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Following functions are not implemented by intention to let the
|
||||
* GPIO-driven low-level implementation handle the configuration
|
||||
* of the GPIOs. The function `_lcd_ll_mcu_set_data_dir` is used to
|
||||
* initialize the GPIO masks when the clear masks are completely 0.
|
||||
*/
|
||||
#if 0
|
||||
|
||||
static void _lcd_ll_mcu_init(lcd_t *dev)
|
||||
{
|
||||
(void)dev;
|
||||
}
|
||||
|
||||
static void _lcd_ll_mcu_cmd_start(lcd_t *dev, uint8_t cmd, bool cont)
|
||||
{
|
||||
(void)dev;
|
||||
(void)cmd;
|
||||
(void)cont;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void _lcd_ll_mcu_set_data_dir(lcd_t *dev, bool output)
|
||||
{
|
||||
DEBUG("[lcd_ll_mcu] %s %u\n", __func__, output);
|
||||
|
||||
/* sanity check to ensure that data pins can be handled as array */
|
||||
assert((&dev->params->d7_pin - &dev->params->d0_pin) == 7);
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
assert((&dev->params->d15_pin - &dev->params->d8_pin) == 7);
|
||||
#endif
|
||||
|
||||
if ((_low_byte_masks[0].clr_mask_0 == 0) &&
|
||||
(_low_byte_masks[0].clr_mask_1 == 0)) {
|
||||
/* initialize the mask array if it is not yet initialized */
|
||||
const gpio_t *pins = &dev->params->d0_pin;
|
||||
|
||||
for (unsigned data = 0; data < 256; data++) {
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
if (data & (1 << i)) {
|
||||
/* set mask */
|
||||
if (pins[i] < 32) {
|
||||
_low_byte_masks[data].set_mask_0 |= 1 << pins[i];
|
||||
}
|
||||
else {
|
||||
_low_byte_masks[data].set_mask_1 |= 1 << (pins[i] - 32);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* clear mask */
|
||||
if (pins[i] < 32) {
|
||||
_low_byte_masks[data].clr_mask_0 |= 1 << pins[i];
|
||||
}
|
||||
else {
|
||||
_low_byte_masks[data].clr_mask_1 |= 1 << (pins[i] - 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
pins = &dev->params->d8_pin;
|
||||
|
||||
for (unsigned data = 0; data < 256; data++) {
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
if (data & (1 << i)) {
|
||||
/* set mask */
|
||||
if (pins[i] < 32) {
|
||||
_high_byte_masks[data].set_mask_0 |= 1 << pins[i];
|
||||
}
|
||||
else {
|
||||
_high_byte_masks[data].set_mask_1 |= 1 << (pins[i] - 32);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* clear mask */
|
||||
if (pins[i] < 32) {
|
||||
_high_byte_masks[data].clr_mask_0 |= 1 << pins[i];
|
||||
}
|
||||
else {
|
||||
_high_byte_masks[data].clr_mask_1 |= 1 << (pins[i] - 32);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
gpio_init(dev->params->d0_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d1_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d2_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d3_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d4_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d5_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d6_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d7_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
gpio_init(dev->params->d8_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d9_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d10_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d11_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d12_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d13_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d14_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
gpio_init(dev->params->d15_pin, output ? GPIO_OUT : GPIO_IN);
|
||||
#endif /* IS_USED(MODULE_LCD_PARALLEL_16BIT) */
|
||||
}
|
||||
|
||||
static void _lcd_ll_mcu_write_data(lcd_t *dev, bool cont,
|
||||
uint16_t data, unsigned pin_num)
|
||||
{
|
||||
if (gpio_is_valid(dev->params->cs_pin)) {
|
||||
gpio_clear(dev->params->cs_pin);
|
||||
}
|
||||
|
||||
gpio_clear(dev->params->wrx_pin);
|
||||
|
||||
uint8_t _byte = data & 0xff;
|
||||
|
||||
uint32_t set_mask_0 = _low_byte_masks[_byte].set_mask_0;
|
||||
uint32_t clr_mask_0 = _low_byte_masks[_byte].clr_mask_0;
|
||||
uint32_t set_mask_1 = _low_byte_masks[_byte].set_mask_1;
|
||||
uint32_t clr_mask_1 = _low_byte_masks[_byte].clr_mask_1;
|
||||
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
_byte = data >> 8;
|
||||
|
||||
set_mask_0 |= _high_byte_masks[_byte].set_mask_0;
|
||||
clr_mask_0 |= _high_byte_masks[_byte].clr_mask_0;
|
||||
set_mask_1 |= _high_byte_masks[_byte].set_mask_1;
|
||||
clr_mask_1 |= _high_byte_masks[_byte].clr_mask_1;
|
||||
#endif
|
||||
|
||||
*((uint32_t *)GPIO_OUT_W1TS_REG) = set_mask_0;
|
||||
*((uint32_t *)GPIO_OUT_W1TC_REG) = clr_mask_0;
|
||||
*((uint32_t *)GPIO_OUT1_W1TS_REG) = set_mask_1;
|
||||
*((uint32_t *)GPIO_OUT1_W1TC_REG) = clr_mask_1;
|
||||
|
||||
gpio_set(dev->params->wrx_pin);
|
||||
|
||||
if (gpio_is_valid(dev->params->cs_pin) && !cont) {
|
||||
gpio_set(dev->params->cs_pin);
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t _lcd_ll_mcu_read_data(lcd_t *dev, bool cont, unsigned pin_num)
|
||||
{
|
||||
const gpio_t *pins = &dev->params->d0_pin;
|
||||
|
||||
if (gpio_is_valid(dev->params->cs_pin)) {
|
||||
gpio_clear(dev->params->cs_pin);
|
||||
}
|
||||
|
||||
gpio_clear(dev->params->rdx_pin);
|
||||
|
||||
uint32_t in_0 = *((uint32_t *)GPIO_IN_REG);
|
||||
uint32_t in_1 = *((uint32_t *)GPIO_IN1_REG);
|
||||
|
||||
gpio_set(dev->params->rdx_pin);
|
||||
|
||||
if (gpio_is_valid(dev->params->cs_pin) && !cont) {
|
||||
gpio_set(dev->params->cs_pin);
|
||||
};
|
||||
|
||||
uint16_t in = 0;
|
||||
|
||||
for (unsigned i = 0; i < pin_num; i++) {
|
||||
if (pins[i] < 32) {
|
||||
in |= in_0 & (1 << pins[i]) ? 1 : 0;
|
||||
}
|
||||
else {
|
||||
in |= in_1 & (1 << (pins[i] - 32)) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
static void _lcd_ll_mcu_write_byte(lcd_t *dev, bool cont, uint8_t out)
|
||||
{
|
||||
DEBUG("[lcd_ll_mcu] write byte: %02x\n", out);
|
||||
|
||||
_lcd_ll_mcu_write_data(dev, cont, out, 8);
|
||||
}
|
||||
|
||||
static uint8_t _lcd_ll_mcu_read_byte(lcd_t *dev, bool cont)
|
||||
{
|
||||
return _lcd_ll_mcu_read_data(dev, cont, 8);
|
||||
}
|
||||
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
|
||||
static void _lcd_ll_mcu_write_word(lcd_t *dev, bool cont, uint16_t out)
|
||||
{
|
||||
DEBUG("[lcd_ll_mcu] write word: %04x\n", out);
|
||||
|
||||
_lcd_ll_mcu_write_data(dev, cont, out, 16);
|
||||
}
|
||||
|
||||
static uint16_t _lcd_ll_mcu_read_word(lcd_t *dev, bool cont)
|
||||
{
|
||||
return _lcd_ll_mcu_read_data(dev, cont, 16);
|
||||
}
|
||||
|
||||
#endif /* IS_USED(MODULE_LCD_PARALLEL_16BIT) */
|
||||
|
||||
const lcd_ll_par_driver_t lcd_ll_par_driver = {
|
||||
.init = lcd_ll_par_gpio_init, /* GPIO-driven `init` is used */
|
||||
.set_data_dir = _lcd_ll_mcu_set_data_dir,
|
||||
.cmd_start = lcd_ll_par_gpio_cmd_start, /* GPIO-driven `cmd_start` is used */
|
||||
.write_byte = _lcd_ll_mcu_write_byte,
|
||||
.read_byte = _lcd_ll_mcu_read_byte,
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
.write_word = _lcd_ll_mcu_write_word,
|
||||
.read_word = _lcd_ll_mcu_read_word,
|
||||
#endif
|
||||
};
|
||||
|
||||
#else /* MODULE_ESP_LCD_GPIO */
|
||||
|
||||
/* the GPIO-driven low-level interface is not used */
|
||||
const lcd_ll_par_driver_t lcd_ll_par_driver = {
|
||||
};
|
||||
|
||||
#endif /* MODULE_ESP_LCD_GPIO */
|
260
cpu/esp32/esp-lcd/esp_lcd_mcu.c
Normal file
260
cpu/esp32/esp-lcd/esp_lcd_mcu.c
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Gunar Schorcht
|
||||
*
|
||||
* 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_esp32
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Peripheral low-Level parallel interface implementation for LCDs
|
||||
*
|
||||
* @author Gunar Schorcht <gunar@schorcht.net>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lcd.h"
|
||||
#include "lcd_internal.h"
|
||||
#include "log.h"
|
||||
#include "macros/units.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "ztimer.h"
|
||||
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "soc/gpio_reg.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#if !defined(CPU_FAM_ESP32) && !defined(CPU_FAM_ESP32S2) && !defined(CPU_FAM_ESP32S3)
|
||||
#error "ESP32x SoC family not supported"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_LCD_WRITE_CLOCK_MHZ
|
||||
#if CONFIG_LCD_I80_COLOR_IN_PSRAM
|
||||
/* PCLK has to be low enough for SPI RAM */
|
||||
#define CONFIG_LCD_WRITE_CLOCK_MHZ 2
|
||||
#else
|
||||
|
||||
#if defined(CPU_FAM_ESP32S3)
|
||||
#define CONFIG_LCD_WRITE_CLOCK_MHZ 20
|
||||
#elif defined(CPU_FAM_ESP32S2)
|
||||
#define CONFIG_LCD_WRITE_CLOCK_MHZ 40
|
||||
#else /* ESP32 */
|
||||
#define CONFIG_LCD_WRITE_CLOCK_MHZ 10
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_LCD_I80_COLOR_IN_PSRAM */
|
||||
#endif /* CONFIG_LCD_WRITE_CLOCK_MHZ */
|
||||
|
||||
static_assert(CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE >= 32,
|
||||
"CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE mus be at least 32");
|
||||
|
||||
/* ESP32x SoCs support only one LCD peripheral so we can use single instances
|
||||
* of the following variables */
|
||||
|
||||
int _cmd = -1; /* means no command needed in ESP-IDF */
|
||||
|
||||
size_t _idx_bytes = 0;
|
||||
uint8_t _data_bytes[CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE];
|
||||
uint8_t _trans_bytes[CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE];
|
||||
|
||||
esp_lcd_i80_bus_handle_t _i80_bus_handle = NULL;
|
||||
esp_lcd_panel_io_handle_t _i80_io_handle = NULL;
|
||||
|
||||
/* indicates that a transfer of the data buffer is still in progress and must
|
||||
* not be overwritten */
|
||||
static bool _dma_transfer_in_progress = false;
|
||||
|
||||
static bool _dma_transfer_done(esp_lcd_panel_io_handle_t io_handle,
|
||||
esp_lcd_panel_io_event_data_t *io_event_data,
|
||||
void *user_ctx)
|
||||
{
|
||||
(void)io_handle;
|
||||
(void)io_event_data;
|
||||
(void)user_ctx;
|
||||
|
||||
_dma_transfer_in_progress = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void _lcd_ll_mcu_init(lcd_t *dev)
|
||||
{
|
||||
esp_lcd_i80_bus_config_t i80_bus_config = {
|
||||
.dc_gpio_num = dev->params->dcx_pin,
|
||||
.wr_gpio_num = dev->params->wrx_pin,
|
||||
.clk_src = LCD_CLK_SRC_PLL160M,
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
.data_gpio_nums = {
|
||||
dev->params->d0_pin,
|
||||
dev->params->d1_pin,
|
||||
dev->params->d2_pin,
|
||||
dev->params->d3_pin,
|
||||
dev->params->d4_pin,
|
||||
dev->params->d5_pin,
|
||||
dev->params->d6_pin,
|
||||
dev->params->d7_pin,
|
||||
dev->params->d8_pin,
|
||||
dev->params->d9_pin,
|
||||
dev->params->d10_pin,
|
||||
dev->params->d11_pin,
|
||||
dev->params->d12_pin,
|
||||
dev->params->d13_pin,
|
||||
dev->params->d14_pin,
|
||||
dev->params->d15_pin,
|
||||
},
|
||||
.bus_width = 16,
|
||||
#else
|
||||
.data_gpio_nums = {
|
||||
dev->params->d0_pin,
|
||||
dev->params->d1_pin,
|
||||
dev->params->d2_pin,
|
||||
dev->params->d3_pin,
|
||||
dev->params->d4_pin,
|
||||
dev->params->d5_pin,
|
||||
dev->params->d6_pin,
|
||||
dev->params->d7_pin,
|
||||
},
|
||||
.bus_width = 8,
|
||||
#endif
|
||||
.max_transfer_bytes = dev->params->rgb_channels * 40 * sizeof(uint16_t),
|
||||
};
|
||||
|
||||
esp_lcd_panel_io_i80_config_t i80_io_config = {
|
||||
.cs_gpio_num = gpio_is_valid(dev->params->cs_pin) ? (int)dev->params->cs_pin
|
||||
: -1,
|
||||
.pclk_hz = MHZ(CONFIG_LCD_WRITE_CLOCK_MHZ),
|
||||
.trans_queue_depth = 10,
|
||||
.dc_levels = {
|
||||
.dc_idle_level = 0,
|
||||
.dc_cmd_level = 0,
|
||||
.dc_dummy_level = 1,
|
||||
.dc_data_level = 1,
|
||||
},
|
||||
.on_color_trans_done = _dma_transfer_done,
|
||||
.user_ctx = NULL,
|
||||
.lcd_cmd_bits = 8,
|
||||
.lcd_param_bits = 8,
|
||||
};
|
||||
|
||||
esp_lcd_new_i80_bus(&i80_bus_config, &_i80_bus_handle);
|
||||
esp_lcd_new_panel_io_i80(_i80_bus_handle, &i80_io_config, &_i80_io_handle);
|
||||
|
||||
if (gpio_is_valid(dev->params->rdx_pin)) {
|
||||
gpio_init(dev->params->rdx_pin, GPIO_IN_PU);
|
||||
gpio_set(dev->params->rdx_pin);
|
||||
}
|
||||
|
||||
if (gpio_is_valid(dev->params->cs_pin)) {
|
||||
gpio_init(dev->params->cs_pin, GPIO_OUT);
|
||||
gpio_clear(dev->params->cs_pin);
|
||||
}
|
||||
}
|
||||
|
||||
static void _lcd_ll_mcu_set_data_dir(lcd_t *dev, bool output)
|
||||
{
|
||||
(void)dev;
|
||||
(void)output;
|
||||
LOG_ERROR("[lcd_ll_mcu] set dir: %d is not supported\n", output);
|
||||
/* not supported yet */
|
||||
}
|
||||
|
||||
static void _lcd_ll_mcu_cmd_start(lcd_t *dev, uint8_t cmd, bool cont)
|
||||
{
|
||||
DEBUG("[lcd_ll_mcu] write cmd: %02x\n", cmd);
|
||||
|
||||
if (!cont) {
|
||||
/* cmd without parameters */
|
||||
esp_lcd_panel_io_tx_param(_i80_io_handle, cmd, NULL, 0);
|
||||
_cmd = -1;
|
||||
}
|
||||
else {
|
||||
/* cmd with parameters */
|
||||
_cmd = cmd;
|
||||
}
|
||||
}
|
||||
|
||||
static void _lcd_ll_mcu_transfer(lcd_t *dev, bool cont)
|
||||
{
|
||||
if (!cont) {
|
||||
/* if no further data follow, send the command with the data in the buffer */
|
||||
esp_lcd_panel_io_tx_param(_i80_io_handle, _cmd, _data_bytes, _idx_bytes);
|
||||
_cmd = -1;
|
||||
_idx_bytes = 0;
|
||||
}
|
||||
else if (_idx_bytes == CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE) {
|
||||
/* spin lock as long as a DMA data transfer is still in progress */
|
||||
while (_dma_transfer_in_progress) {}
|
||||
|
||||
/* copy data buffer to the DMA transfer buffer */
|
||||
memcpy(_trans_bytes, _data_bytes, _idx_bytes);
|
||||
/* start DMA data transfer */
|
||||
_dma_transfer_in_progress = true;
|
||||
esp_lcd_panel_io_tx_color(_i80_io_handle, _cmd, _data_bytes, _idx_bytes);
|
||||
|
||||
/* It should only be possible to follow more data than
|
||||
* CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE with the RAMWR command.
|
||||
* Transferring more data to continue the operation with cmd=-1 does
|
||||
* not seem to work. Therefore a RAMWRC generated in this
|
||||
* case for further data */
|
||||
_cmd = (_cmd == LCD_CMD_RAMWR) ? LCD_CMD_RAMWRC : _cmd;
|
||||
_idx_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void _lcd_ll_mcu_write_byte(lcd_t *dev, bool cont, uint8_t out)
|
||||
{
|
||||
DEBUG("[lcd_ll_mcu] write byte: %02x\n", out);
|
||||
|
||||
_data_bytes[_idx_bytes++] = out;
|
||||
/* transfer the data if necessary */
|
||||
_lcd_ll_mcu_transfer(dev, cont);
|
||||
}
|
||||
|
||||
static uint8_t _lcd_ll_mcu_read_byte(lcd_t *dev, bool cont)
|
||||
{
|
||||
LOG_ERROR("[lcd_ll_mcu] read from LCD is not supported\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
|
||||
static void _lcd_ll_mcu_write_word(lcd_t *dev, bool cont, uint16_t out)
|
||||
{
|
||||
DEBUG("[lcd_ll_mcu] write word: %04x\n", out);
|
||||
|
||||
/* out is given in BE order */
|
||||
_data_bytes[_idx_bytes++] = out >> 8;
|
||||
_data_bytes[_idx_bytes++] = out & 0xff;
|
||||
/* transfer the data if necessary */
|
||||
_lcd_ll_mcu_transfer(dev, cont);
|
||||
}
|
||||
|
||||
static uint16_t _lcd_ll_mcu_read_word(lcd_t *dev, bool cont)
|
||||
{
|
||||
LOG_ERROR("[lcd_ll_mcu] read from LCD is not supported\n");
|
||||
/* not supported yet */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* IS_USED(MODULE_LCD_PARALLEL_16BIT) */
|
||||
|
||||
const lcd_ll_par_driver_t lcd_ll_par_driver = {
|
||||
.init = _lcd_ll_mcu_init,
|
||||
.set_data_dir = _lcd_ll_mcu_set_data_dir,
|
||||
.cmd_start = _lcd_ll_mcu_cmd_start,
|
||||
.write_byte = _lcd_ll_mcu_write_byte,
|
||||
.read_byte = _lcd_ll_mcu_read_byte,
|
||||
#if IS_USED(MODULE_LCD_PARALLEL_16BIT)
|
||||
.write_word = _lcd_ll_mcu_write_word,
|
||||
.read_word = _lcd_ll_mcu_read_word,
|
||||
#endif
|
||||
};
|
@ -47,6 +47,7 @@ extern "C" {
|
||||
#define CPU_INUM_WDT 13 /**< Level interrupt with low priority 1 */
|
||||
#define CPU_INUM_SOFTWARE 17 /**< Level interrupt with low priority 1 */
|
||||
#define CPU_INUM_ETH 18 /**< Level interrupt with low priority 1 */
|
||||
#define CPU_INUM_LCD 18 /**< Level interrupt with low priority 1 */
|
||||
#define CPU_INUM_TIMER 19 /**< Level interrupt with medium priority 2 */
|
||||
#define CPU_INUM_FRC2 20 /**< Level interrupt with medium priority 2 */
|
||||
#define CPU_INUM_SYSTIMER 20 /**< Level interrupt with medium priority 2 */
|
||||
|
@ -233,6 +233,17 @@
|
||||
|
||||
#endif /* !CONFIG_ESP_FLASHPAGE_CAPACITY */
|
||||
|
||||
/**
|
||||
* LCD driver configuration
|
||||
*/
|
||||
#if MODULE_ESP_IDF_LCD
|
||||
#ifndef CONFIG_LCD_DATA_BUF_SIZE
|
||||
#define CONFIG_LCD_DATA_BUF_SIZE 512
|
||||
#endif
|
||||
|
||||
#define CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE CONFIG_LCD_DATA_BUF_SIZE
|
||||
#endif
|
||||
|
||||
#endif /* DOXYGEN */
|
||||
|
||||
/**
|
||||
|
@ -87,10 +87,19 @@ static const struct intr_handle_data_t _irq_data_table[] = {
|
||||
{ ETS_USB_SERIAL_JTAG_INTR_SOURCE, CPU_INUM_SERIAL_JTAG, 1 },
|
||||
#endif
|
||||
{ ETS_RMT_INTR_SOURCE, CPU_INUM_RMT, 1 },
|
||||
#if defined(CPU_FAM_ESP32) || defined(CPU_FAM_ESP32S2)
|
||||
{ ETS_I2S0_INTR_SOURCE, CPU_INUM_LCD, 1 },
|
||||
#elif defined(CPU_FAM_ESP32S3)
|
||||
{ ETS_LCD_CAM_INTR_SOURCE, CPU_INUM_LCD, 1 },
|
||||
#endif
|
||||
};
|
||||
|
||||
#define IRQ_DATA_TABLE_SIZE ARRAY_SIZE(_irq_data_table)
|
||||
|
||||
#if defined(CPU_FAM_ESP32) && MODULE_ESP_LCD && MODULE_ESP_ETH
|
||||
#error "esp_eth and esp_lcd can't be used at the same time because of an interrupt conflict"
|
||||
#endif
|
||||
|
||||
void esp_irq_init(void)
|
||||
{
|
||||
#ifdef SOC_CPU_HAS_FLEXIBLE_INTC
|
||||
@ -172,6 +181,17 @@ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler,
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_intr_alloc_intrstatus(int source, int flags,
|
||||
uint32_t reg, uint32_t mask,
|
||||
intr_handler_t handler,
|
||||
void *arg, intr_handle_t *ret_handle)
|
||||
{
|
||||
/* TODO status register and status mask handling for shared interrupts */
|
||||
(void)reg;
|
||||
(void)mask;
|
||||
return esp_intr_alloc(source, flags, handler, arg, ret_handle);
|
||||
}
|
||||
|
||||
esp_err_t esp_intr_free(intr_handle_t handle)
|
||||
{
|
||||
return esp_intr_disable(handle);
|
||||
|
@ -26,18 +26,19 @@
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <err.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "cpu_conf.h"
|
||||
#include "native_internal.h"
|
||||
#include "periph/timer.h"
|
||||
#include "time_units.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
@ -49,7 +50,9 @@ static unsigned long time_null;
|
||||
static timer_cb_t _callback;
|
||||
static void *_cb_arg;
|
||||
|
||||
static struct itimerval itv;
|
||||
static struct itimerspec its;
|
||||
|
||||
static timer_t itimer_monotonic;
|
||||
|
||||
/**
|
||||
* returns ticks for give timespec
|
||||
@ -89,8 +92,15 @@ int timer_init(tim_t dev, uint32_t freq, timer_cb_t cb, void *arg)
|
||||
|
||||
_callback = cb;
|
||||
_cb_arg = arg;
|
||||
|
||||
if (timer_create(CLOCK_MONOTONIC, NULL, &itimer_monotonic) != 0) {
|
||||
DEBUG_PUTS("Failed to create a monotonic itimer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (register_interrupt(SIGALRM, native_isr_timer) != 0) {
|
||||
DEBUG("darn!\n\n");
|
||||
DEBUG_PUTS("Failed to register SIGALRM handler");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -104,14 +114,14 @@ static void do_timer_set(unsigned int offset, bool periodic)
|
||||
offset = NATIVE_TIMER_MIN_RES;
|
||||
}
|
||||
|
||||
memset(&itv, 0, sizeof(itv));
|
||||
itv.it_value.tv_sec = (offset / 1000000);
|
||||
itv.it_value.tv_usec = offset % 1000000;
|
||||
memset(&its, 0, sizeof(its));
|
||||
its.it_value.tv_sec = offset / NATIVE_TIMER_SPEED;
|
||||
its.it_value.tv_nsec = (offset % NATIVE_TIMER_SPEED) * (NS_PER_SEC / NATIVE_TIMER_SPEED);
|
||||
if (periodic) {
|
||||
itv.it_interval = itv.it_value;
|
||||
its.it_interval = its.it_value;
|
||||
}
|
||||
|
||||
DEBUG("timer_set(): setting %lu.%06lu\n", itv.it_value.tv_sec, itv.it_value.tv_usec);
|
||||
DEBUG("timer_set(): setting %lu.%09lu\n", (unsigned long)its.it_value.tv_sec, its.it_value.tv_nsec);
|
||||
}
|
||||
|
||||
int timer_set(tim_t dev, int channel, unsigned int offset)
|
||||
@ -171,8 +181,8 @@ void timer_start(tim_t dev)
|
||||
DEBUG("%s\n", __func__);
|
||||
|
||||
_native_syscall_enter();
|
||||
if (real_setitimer(ITIMER_REAL, &itv, NULL) == -1) {
|
||||
err(EXIT_FAILURE, "timer_arm: setitimer");
|
||||
if (timer_settime(itimer_monotonic, 0, &its, NULL) == -1) {
|
||||
err(EXIT_FAILURE, "timer_start: timer_settime");
|
||||
}
|
||||
_native_syscall_leave();
|
||||
}
|
||||
@ -183,13 +193,13 @@ void timer_stop(tim_t dev)
|
||||
DEBUG("%s\n", __func__);
|
||||
|
||||
_native_syscall_enter();
|
||||
struct itimerval zero = {0};
|
||||
if (real_setitimer(ITIMER_REAL, &zero, &itv) == -1) {
|
||||
err(EXIT_FAILURE, "timer_arm: setitimer");
|
||||
struct itimerspec zero = {0};
|
||||
if (timer_settime(itimer_monotonic, 0, &zero, &its) == -1) {
|
||||
err(EXIT_FAILURE, "timer_stop: timer_settime");
|
||||
}
|
||||
_native_syscall_leave();
|
||||
|
||||
DEBUG("time left: %lu.%06lu\n", itv.it_value.tv_sec, itv.it_value.tv_usec);
|
||||
DEBUG("time left: %lu.%09lu\n", (unsigned long)its.it_value.tv_sec, its.it_value.tv_nsec);
|
||||
}
|
||||
|
||||
unsigned int timer_read(tim_t dev)
|
||||
|
@ -88,8 +88,6 @@ int (*real_pause)(void);
|
||||
int (*real_pipe)(int[2]);
|
||||
int (*real_select)(int nfds, ...);
|
||||
int (*real_poll)(struct pollfd *fds, ...);
|
||||
int (*real_setitimer)(int which, const struct itimerval
|
||||
*restrict value, struct itimerval *restrict ovalue);
|
||||
int (*real_setsid)(void);
|
||||
int (*real_setsockopt)(int socket, ...);
|
||||
int (*real_socket)(int domain, int type, int protocol);
|
||||
@ -535,7 +533,6 @@ void _native_init_syscalls(void)
|
||||
*(void **)(&real_dup2) = dlsym(RTLD_NEXT, "dup2");
|
||||
*(void **)(&real_select) = dlsym(RTLD_NEXT, "select");
|
||||
*(void **)(&real_poll) = dlsym(RTLD_NEXT, "poll");
|
||||
*(void **)(&real_setitimer) = dlsym(RTLD_NEXT, "setitimer");
|
||||
*(void **)(&real_setsid) = dlsym(RTLD_NEXT, "setsid");
|
||||
*(void **)(&real_setsockopt) = dlsym(RTLD_NEXT, "setsockopt");
|
||||
*(void **)(&real_socket) = dlsym(RTLD_NEXT, "socket");
|
||||
|
@ -34,7 +34,6 @@ extern "C" {
|
||||
* @brief Redefine some peripheral names to unify them between nRF51 and 52
|
||||
* @{
|
||||
*/
|
||||
#define UART_IRQN (UART0_IRQn)
|
||||
#define SPI_SCKSEL (dev(bus)->PSELSCK)
|
||||
#define SPI_MOSISEL (dev(bus)->PSELMOSI)
|
||||
#define SPI_MISOSEL (dev(bus)->PSELMISO)
|
||||
|
@ -103,7 +103,7 @@ static int write(i2c_t dev, uint16_t addr, const void *data, int len,
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2c_init(i2c_t dev)
|
||||
@ -198,7 +198,7 @@ int i2c_read_bytes(i2c_t dev, uint16_t address, void *data, size_t length,
|
||||
while (i2c(dev)->EVENTS_STOPPED == 0) {}
|
||||
NRF_PPI->CHENCLR = (1 << i2c_config[dev].ppi);
|
||||
|
||||
return length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_read_regs(i2c_t dev, uint16_t address, uint16_t reg,
|
||||
|
@ -19,19 +19,18 @@ config CPU_FAM_NRF52
|
||||
select HAS_CPU_NRF52
|
||||
select HAS_PERIPH_I2C_RECONFIGURE
|
||||
select HAS_PERIPH_SPI_GPIO_MODE
|
||||
select HAS_PERIPH_UART_NONBLOCKING
|
||||
|
||||
## CPU Models
|
||||
config CPU_MODEL_NRF52805XXAA
|
||||
bool
|
||||
select CPU_CORE_CORTEX_M4
|
||||
select CPU_FAM_NRF52
|
||||
select HAS_PERIPH_UART_NONBLOCKING
|
||||
|
||||
config CPU_MODEL_NRF52810XXAA
|
||||
bool
|
||||
select CPU_CORE_CORTEX_M4
|
||||
select CPU_FAM_NRF52
|
||||
select HAS_PERIPH_UART_NONBLOCKING
|
||||
|
||||
config CPU_MODEL_NRF52811XXAA
|
||||
bool
|
||||
@ -39,7 +38,6 @@ config CPU_MODEL_NRF52811XXAA
|
||||
select CPU_FAM_NRF52
|
||||
select HAS_BLE_PHY_CODED
|
||||
select HAS_RADIO_NRF802154
|
||||
select HAS_PERIPH_UART_NONBLOCKING
|
||||
|
||||
config CPU_MODEL_NRF52820XXAA
|
||||
bool
|
||||
@ -47,7 +45,6 @@ config CPU_MODEL_NRF52820XXAA
|
||||
select CPU_FAM_NRF52
|
||||
select HAS_BLE_PHY_CODED
|
||||
select HAS_RADIO_NRF802154
|
||||
select HAS_PERIPH_UART_NONBLOCKING
|
||||
|
||||
config CPU_MODEL_NRF52832XXAA
|
||||
bool
|
||||
@ -60,7 +57,6 @@ config CPU_MODEL_NRF52833XXAA
|
||||
select CPU_FAM_NRF52
|
||||
select HAS_BLE_PHY_CODED
|
||||
select HAS_RADIO_NRF802154
|
||||
select HAS_PERIPH_UART_NONBLOCKING
|
||||
|
||||
config CPU_MODEL_NRF52840XXAA
|
||||
bool
|
||||
@ -68,7 +64,6 @@ config CPU_MODEL_NRF52840XXAA
|
||||
select CPU_FAM_NRF52
|
||||
select HAS_BLE_PHY_CODED
|
||||
select HAS_RADIO_NRF802154
|
||||
select HAS_PERIPH_UART_NONBLOCKING
|
||||
select HAS_PERIPH_HASH_SHA_1
|
||||
select HAS_PERIPH_HASH_SHA_224
|
||||
select HAS_PERIPH_HASH_SHA_256
|
||||
|
@ -23,9 +23,9 @@ ifneq (,$(filter nrf52840xxaa,$(CPU_MODEL)))
|
||||
FEATURES_PROVIDED += periph_ecc_ed25519
|
||||
endif
|
||||
|
||||
ifeq (,$(filter nrf52832%,$(CPU_MODEL)))
|
||||
FEATURES_PROVIDED += periph_uart_nonblocking
|
||||
endif
|
||||
# All nRF52 CPUs use UARTE (UART + EasyDMA) for UART, so that can be used
|
||||
# in non-blocking mode
|
||||
FEATURES_PROVIDED += periph_uart_nonblocking
|
||||
# The ADC does not depend on any board configuration, so always available
|
||||
FEATURES_PROVIDED += periph_adc
|
||||
|
||||
|
@ -66,9 +66,9 @@ extern "C" {
|
||||
* The port definition is used (and zeroed) to suppress compiler warnings
|
||||
*/
|
||||
#if GPIO_COUNT > 1
|
||||
#define GPIO_PIN(x,y) ((x << 5) | y)
|
||||
#define GPIO_PIN(x, y) ((x << 5) | y)
|
||||
#else
|
||||
#define GPIO_PIN(x,y) ((x & 0) | y)
|
||||
#define GPIO_PIN(x, y) ((x & 0) | y)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -316,13 +316,16 @@ typedef struct {
|
||||
*/
|
||||
uint8_t gpio_int_get_exti(gpio_t pin);
|
||||
|
||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
||||
/**
|
||||
* @brief Structure for UART configuration data
|
||||
*/
|
||||
typedef struct {
|
||||
#ifdef UARTE_PRESENT
|
||||
NRF_UARTE_Type *dev; /**< UART with EasyDMA device base
|
||||
* register address */
|
||||
#else
|
||||
NRF_UART_Type *dev; /**< UART device base register address */
|
||||
#endif
|
||||
gpio_t rx_pin; /**< RX pin */
|
||||
gpio_t tx_pin; /**< TX pin */
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
@ -339,8 +342,6 @@ typedef struct {
|
||||
#define UART_TXBUF_SIZE (64)
|
||||
#endif
|
||||
|
||||
#endif /* ndef CPU_MODEL_NRF52832XXAA && ndef CPU_FAM_NRF51 */
|
||||
|
||||
/**
|
||||
* @brief USBDEV buffers must be word aligned because of DMA restrictions
|
||||
*/
|
||||
@ -407,9 +408,6 @@ typedef struct {
|
||||
#define SPI_SCKSEL (dev(bus)->PSEL.SCK) /**< Macro for SPI clk */
|
||||
#define SPI_MOSISEL (dev(bus)->PSEL.MOSI) /**< Macro for SPI mosi */
|
||||
#define SPI_MISOSEL (dev(bus)->PSEL.MISO) /**< Macro for SPI miso */
|
||||
#ifdef CPU_MODEL_NRF52832XXAA
|
||||
#define UART_IRQN (UARTE0_UART0_IRQn)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI configuration values
|
||||
|
@ -28,28 +28,32 @@
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "compiler_hints.h"
|
||||
#include "cpu.h"
|
||||
#include "periph/uart.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "periph/uart.h"
|
||||
|
||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
||||
#define UART_INVALID (uart >= UART_NUMOF)
|
||||
#define REG_BAUDRATE dev(uart)->BAUDRATE
|
||||
#define REG_CONFIG dev(uart)->CONFIG
|
||||
#define PSEL_RXD dev(uart)->PSEL.RXD
|
||||
#define PSEL_TXD dev(uart)->PSEL.TXD
|
||||
#define UART_IRQN uart_config[uart].irqn
|
||||
#define UART_PIN_RX uart_config[uart].rx_pin
|
||||
#define UART_PIN_TX uart_config[uart].tx_pin
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
#define UART_PIN_RTS uart_config[uart].rts_pin
|
||||
#define UART_PIN_CTS uart_config[uart].cts_pin
|
||||
#ifdef UARTE_PRESENT
|
||||
# define PSEL_RXD PSEL.RXD
|
||||
# define PSEL_TXD PSEL.TXD
|
||||
# define PSEL_RTS PSEL.RTS
|
||||
# define PSEL_CTS PSEL.CTS
|
||||
# define ENABLE_ON UARTE_ENABLE_ENABLE_Enabled
|
||||
# define ENABLE_OFF UARTE_ENABLE_ENABLE_Disabled
|
||||
# define UART_TYPE NRF_UARTE_Type
|
||||
#else
|
||||
# define PSEL_RXD PSELRXD
|
||||
# define PSEL_TXD PSELTXD
|
||||
# define PSEL_RTS PSELRTS
|
||||
# define PSEL_CTS PSELCTS
|
||||
# define ENABLE_ON UART_ENABLE_ENABLE_Enabled
|
||||
# define ENABLE_OFF UART_ENABLE_ENABLE_Disabled
|
||||
# define UART_TYPE NRF_UART_Type
|
||||
#endif
|
||||
#define ISR_CTX isr_ctx[uart]
|
||||
|
||||
#define RAM_MASK (0x20000000)
|
||||
|
||||
/**
|
||||
@ -63,7 +67,9 @@
|
||||
* @brief Allocate memory for the interrupt context
|
||||
*/
|
||||
static uart_isr_ctx_t isr_ctx[UART_NUMOF];
|
||||
#ifdef UARTE_PRESENT
|
||||
static uint8_t rx_buf[UART_NUMOF];
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_PERIPH_UART_NONBLOCKING
|
||||
|
||||
@ -81,149 +87,126 @@ static uint8_t uart_tx_rb_buf[UART_NUMOF][UART_TXBUF_SIZE];
|
||||
*/
|
||||
void uart_isr_handler(void *arg);
|
||||
|
||||
static inline NRF_UARTE_Type *dev(uart_t uart)
|
||||
{
|
||||
return uart_config[uart].dev;
|
||||
}
|
||||
|
||||
#else /* nrf51 and nrf52832 etc */
|
||||
|
||||
#define UART_INVALID (uart != 0)
|
||||
#define REG_BAUDRATE NRF_UART0->BAUDRATE
|
||||
#define REG_CONFIG NRF_UART0->CONFIG
|
||||
#define PSEL_RXD NRF_UART0->PSELRXD
|
||||
#define PSEL_TXD NRF_UART0->PSELTXD
|
||||
#define UART_0_ISR isr_uart0
|
||||
#define ISR_CTX isr_ctx
|
||||
|
||||
/**
|
||||
* @brief Allocate memory for the interrupt context
|
||||
*/
|
||||
static uart_isr_ctx_t isr_ctx;
|
||||
|
||||
#endif /* !CPU_MODEL_NRF52832XXAA && !CPU_FAM_NRF51 */
|
||||
/* use an enum to count the number of UART ISR macro names defined by the
|
||||
* board */
|
||||
enum {
|
||||
#ifdef UART_0_ISR
|
||||
UART_0_ISR_NUM,
|
||||
#endif
|
||||
#ifdef UART_1_ISR
|
||||
UART_1_ISR_NUM,
|
||||
#endif
|
||||
UART_ISR_NUMOF,
|
||||
};
|
||||
|
||||
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
{
|
||||
if (UART_INVALID) {
|
||||
/* ensure the ISR names have been defined as needed */
|
||||
#if !defined(CPU_NRF53) && !defined(CPU_NRF9160)
|
||||
static_assert(UART_NUMOF == UART_ISR_NUMOF, "Define(s) of UART ISR name(s) missing");
|
||||
#endif
|
||||
if ((unsigned)uart >= UART_NUMOF) {
|
||||
return UART_NODEV;
|
||||
}
|
||||
|
||||
/* remember callback addresses and argument */
|
||||
ISR_CTX.rx_cb = rx_cb;
|
||||
ISR_CTX.arg = arg;
|
||||
UART_TYPE *dev = uart_config[uart].dev;
|
||||
|
||||
#ifdef CPU_FAM_NRF51
|
||||
/* power on the UART device */
|
||||
NRF_UART0->POWER = 1;
|
||||
/* remember callback addresses and argument */
|
||||
isr_ctx[uart].rx_cb = rx_cb;
|
||||
isr_ctx[uart].arg = arg;
|
||||
|
||||
#ifndef UARTE_PRESENT
|
||||
/* only the legacy non-EasyDMA UART needs to be powered on explicitly */
|
||||
dev->POWER = 1;
|
||||
#endif
|
||||
|
||||
/* reset configuration registers */
|
||||
REG_CONFIG = 0;
|
||||
dev->CONFIG = 0;
|
||||
|
||||
/* configure RX pin */
|
||||
if (rx_cb) {
|
||||
gpio_init(UART_PIN_RX, GPIO_IN);
|
||||
PSEL_RXD = UART_PIN_RX;
|
||||
gpio_init(uart_config[uart].rx_pin, GPIO_IN);
|
||||
dev->PSEL_RXD = uart_config[uart].rx_pin;
|
||||
}
|
||||
|
||||
/* configure TX pin */
|
||||
gpio_init(UART_PIN_TX, GPIO_OUT);
|
||||
PSEL_TXD = UART_PIN_TX;
|
||||
gpio_init(uart_config[uart].tx_pin, GPIO_OUT);
|
||||
dev->PSEL_TXD = uart_config[uart].tx_pin;
|
||||
|
||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
||||
/* enable HW-flow control if defined */
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
/* set pin mode for RTS and CTS pins */
|
||||
if (UART_PIN_RTS != GPIO_UNDEF && UART_PIN_CTS != GPIO_UNDEF) {
|
||||
gpio_init(UART_PIN_RTS, GPIO_OUT);
|
||||
gpio_init(UART_PIN_CTS, GPIO_IN);
|
||||
/* configure RTS and CTS pins to use */
|
||||
dev(uart)->PSEL.RTS = UART_PIN_RTS;
|
||||
dev(uart)->PSEL.CTS = UART_PIN_CTS;
|
||||
REG_CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */
|
||||
}
|
||||
#else
|
||||
dev(uart)->PSEL.RTS = 0xffffffff; /* pin disconnected */
|
||||
dev(uart)->PSEL.CTS = 0xffffffff; /* pin disconnected */
|
||||
#endif
|
||||
#else
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
/* set pin mode for RTS and CTS pins */
|
||||
if (UART_PIN_RTS != GPIO_UNDEF && UART_PIN_CTS != GPIO_UNDEF) {
|
||||
gpio_init(UART_PIN_RTS, GPIO_OUT);
|
||||
gpio_init(UART_PIN_CTS, GPIO_IN);
|
||||
if (uart_config[uart].rts_pin != GPIO_UNDEF && uart_config[uart].cts_pin != GPIO_UNDEF) {
|
||||
gpio_init(uart_config[uart].rts_pin, GPIO_OUT);
|
||||
gpio_init(uart_config[uart].cts_pin, GPIO_IN);
|
||||
/* configure RTS and CTS pins to use */
|
||||
NRF_UART0->PSELRTS = UART_PIN_RTS;
|
||||
NRF_UART0->PSELCTS = UART_PIN_CTS;
|
||||
REG_CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */
|
||||
dev->PSEL_RTS = uart_config[uart].rts_pin;
|
||||
dev->PSEL_CTS = uart_config[uart].cts_pin;
|
||||
dev->CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */
|
||||
}
|
||||
#else
|
||||
NRF_UART0->PSELRTS = 0xffffffff; /* pin disconnected */
|
||||
NRF_UART0->PSELCTS = 0xffffffff; /* pin disconnected */
|
||||
#endif /* MODULE_PERIPH_UART_HW_FC */
|
||||
else
|
||||
#endif
|
||||
{
|
||||
dev->PSEL_RTS = 0xffffffff; /* pin disconnected */
|
||||
dev->PSEL_CTS = 0xffffffff; /* pin disconnected */
|
||||
}
|
||||
|
||||
/* select baudrate */
|
||||
switch (baudrate) {
|
||||
case 1200:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200;
|
||||
break;
|
||||
case 2400:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud2400;
|
||||
break;
|
||||
case 4800:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud4800;
|
||||
break;
|
||||
case 9600:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud9600;
|
||||
break;
|
||||
case 14400:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud14400;
|
||||
break;
|
||||
case 19200:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud19200;
|
||||
break;
|
||||
case 28800:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud28800;
|
||||
break;
|
||||
case 38400:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud38400;
|
||||
break;
|
||||
case 57600:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud57600;
|
||||
break;
|
||||
case 76800:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud76800;
|
||||
break;
|
||||
case 115200:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200;
|
||||
break;
|
||||
case 230400:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud230400;
|
||||
break;
|
||||
case 250000:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud250000;
|
||||
break;
|
||||
case 460800:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud460800;
|
||||
break;
|
||||
case 921600:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud921600;
|
||||
break;
|
||||
case 1000000:
|
||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1M;
|
||||
break;
|
||||
default:
|
||||
return UART_NOBAUD;
|
||||
case 1200:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200;
|
||||
break;
|
||||
case 2400:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud2400;
|
||||
break;
|
||||
case 4800:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud4800;
|
||||
break;
|
||||
case 9600:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud9600;
|
||||
break;
|
||||
case 14400:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud14400;
|
||||
break;
|
||||
case 19200:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud19200;
|
||||
break;
|
||||
case 28800:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud28800;
|
||||
break;
|
||||
case 38400:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud38400;
|
||||
break;
|
||||
case 57600:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud57600;
|
||||
break;
|
||||
case 76800:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud76800;
|
||||
break;
|
||||
case 115200:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200;
|
||||
break;
|
||||
case 230400:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud230400;
|
||||
break;
|
||||
case 250000:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud250000;
|
||||
break;
|
||||
case 460800:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud460800;
|
||||
break;
|
||||
case 921600:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud921600;
|
||||
break;
|
||||
case 1000000:
|
||||
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1M;
|
||||
break;
|
||||
default:
|
||||
return UART_NOBAUD;
|
||||
}
|
||||
|
||||
/* enable the UART device */
|
||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
||||
dev(uart)->ENABLE = UARTE_ENABLE_ENABLE_Enabled;
|
||||
#else
|
||||
NRF_UART0->ENABLE = UART_ENABLE_ENABLE_Enabled;
|
||||
#endif
|
||||
dev->ENABLE = ENABLE_ON;
|
||||
|
||||
#ifdef MODULE_PERIPH_UART_NONBLOCKING
|
||||
/* set up the TX buffer */
|
||||
@ -231,60 +214,60 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
#endif
|
||||
|
||||
if (rx_cb) {
|
||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
||||
dev(uart)->RXD.MAXCNT = 1;
|
||||
dev(uart)->RXD.PTR = (uint32_t)&rx_buf[uart];
|
||||
dev(uart)->INTENSET = UARTE_INTENSET_ENDRX_Msk;
|
||||
dev(uart)->SHORTS |= UARTE_SHORTS_ENDRX_STARTRX_Msk;
|
||||
dev(uart)->TASKS_STARTRX = 1;
|
||||
#ifdef UARTE_PRESENT
|
||||
dev->RXD.MAXCNT = 1;
|
||||
dev->RXD.PTR = (uint32_t)&rx_buf[uart];
|
||||
dev->INTENSET = UARTE_INTENSET_ENDRX_Msk;
|
||||
dev->SHORTS |= UARTE_SHORTS_ENDRX_STARTRX_Msk;
|
||||
dev->TASKS_STARTRX = 1;
|
||||
#else
|
||||
NRF_UART0->INTENSET = UART_INTENSET_RXDRDY_Msk;
|
||||
NRF_UART0->TASKS_STARTRX = 1;
|
||||
dev->INTENSET = UART_INTENSET_RXDRDY_Msk;
|
||||
dev->TASKS_STARTRX = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rx_cb || IS_USED(MODULE_PERIPH_UART_NONBLOCKING)) {
|
||||
#if defined(CPU_NRF53) || defined(CPU_NRF9160)
|
||||
shared_irq_register_uart(dev(uart), uart_isr_handler, (void *)(uintptr_t)uart);
|
||||
shared_irq_register_uart(dev, uart_isr_handler, (void *)(uintptr_t)uart);
|
||||
#else
|
||||
NVIC_EnableIRQ(UART_IRQN);
|
||||
NVIC_EnableIRQ(uart_config[uart].irqn);
|
||||
#endif
|
||||
}
|
||||
return UART_OK;
|
||||
}
|
||||
|
||||
/* nrf52840 || nrf52811 (using EasyDMA) */
|
||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
||||
/* UART with EasyDMA */
|
||||
#ifdef UARTE_PRESENT
|
||||
static void _write_buf(uart_t uart, const uint8_t *data, size_t len)
|
||||
{
|
||||
dev(uart)->EVENTS_ENDTX = 0;
|
||||
uart_config[uart].dev->EVENTS_ENDTX = 0;
|
||||
if (IS_USED(MODULE_PERIPH_UART_NONBLOCKING)) {
|
||||
dev(uart)->INTENSET = UARTE_INTENSET_ENDTX_Msk;
|
||||
uart_config[uart].dev->INTENSET = UARTE_INTENSET_ENDTX_Msk;
|
||||
}
|
||||
/* set data to transfer to DMA TX pointer */
|
||||
dev(uart)->TXD.PTR = (uint32_t)data;
|
||||
dev(uart)->TXD.MAXCNT = len;
|
||||
uart_config[uart].dev->TXD.PTR = (uint32_t)data;
|
||||
uart_config[uart].dev->TXD.MAXCNT = len;
|
||||
/* start transmission */
|
||||
dev(uart)->TASKS_STARTTX = 1;
|
||||
uart_config[uart].dev->TASKS_STARTTX = 1;
|
||||
/* wait for the end of transmission */
|
||||
if (!IS_USED(MODULE_PERIPH_UART_NONBLOCKING)) {
|
||||
while (dev(uart)->EVENTS_ENDTX == 0) {}
|
||||
dev(uart)->TASKS_STOPTX = 1;
|
||||
while (uart_config[uart].dev->EVENTS_ENDTX == 0) {}
|
||||
uart_config[uart].dev->TASKS_STOPTX = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
{
|
||||
assert(uart < UART_NUMOF);
|
||||
assume((unsigned)uart < UART_NUMOF);
|
||||
#ifdef MODULE_PERIPH_UART_NONBLOCKING
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
/* in IRQ or interrupts disabled */
|
||||
if (irq_is_in() || __get_PRIMASK()) {
|
||||
if (tsrb_full(&uart_tx_rb[uart])) {
|
||||
/* wait for end of ongoing transmission */
|
||||
if (dev(uart)->EVENTS_TXSTARTED) {
|
||||
while (dev(uart)->EVENTS_ENDTX == 0) {}
|
||||
dev(uart)->EVENTS_TXSTARTED = 0;
|
||||
if (uart_config[uart].dev->EVENTS_TXSTARTED) {
|
||||
while (uart_config[uart].dev->EVENTS_ENDTX == 0) {}
|
||||
uart_config[uart].dev->EVENTS_TXSTARTED = 0;
|
||||
}
|
||||
/* free one spot in buffer */
|
||||
tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]);
|
||||
@ -295,7 +278,7 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
else {
|
||||
/* if no transmission is ongoing and ring buffer is full
|
||||
free up a spot in the buffer by sending one byte */
|
||||
if (!dev(uart)->EVENTS_TXSTARTED && tsrb_full(&uart_tx_rb[uart])) {
|
||||
if (!uart_config[uart].dev->EVENTS_TXSTARTED && tsrb_full(&uart_tx_rb[uart])) {
|
||||
tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]);
|
||||
_write_buf(uart, &tx_buf[uart], 1);
|
||||
}
|
||||
@ -304,7 +287,7 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
}
|
||||
/* if no transmission is ongoing bootstrap the transmission process
|
||||
by setting a single byte to be written */
|
||||
if (!dev(uart)->EVENTS_TXSTARTED) {
|
||||
if (!uart_config[uart].dev->EVENTS_TXSTARTED) {
|
||||
if (!tsrb_empty(&uart_tx_rb[uart])) {
|
||||
tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]);
|
||||
_write_buf(uart, &tx_buf[uart], 1);
|
||||
@ -334,25 +317,33 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
|
||||
void uart_poweron(uart_t uart)
|
||||
{
|
||||
assert(uart < UART_NUMOF);
|
||||
assume((unsigned)uart < UART_NUMOF);
|
||||
|
||||
if (isr_ctx[uart].rx_cb) {
|
||||
dev(uart)->TASKS_STARTRX = 1;
|
||||
uart_config[uart].dev->TASKS_STARTRX = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_poweroff(uart_t uart)
|
||||
{
|
||||
assert(uart < UART_NUMOF);
|
||||
assume((unsigned)uart < UART_NUMOF);
|
||||
|
||||
dev(uart)->TASKS_STOPRX = 1;
|
||||
uart_config[uart].dev->TASKS_STOPRX = 1;
|
||||
}
|
||||
|
||||
int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity,
|
||||
uart_stop_bits_t stop_bits)
|
||||
{
|
||||
|
||||
if (stop_bits != UART_STOP_BITS_1 && stop_bits != UART_STOP_BITS_2) {
|
||||
assume((unsigned)uart < UART_NUMOF);
|
||||
/* Not all nRF52 MCUs support 2 stop bits, but the vendor header files
|
||||
* reflect the feature set. */
|
||||
switch (stop_bits) {
|
||||
case UART_STOP_BITS_1:
|
||||
#ifdef UARTE_CONFIG_STOP_Msk
|
||||
case UART_STOP_BITS_2:
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return UART_NOMODE;
|
||||
}
|
||||
|
||||
@ -364,43 +355,43 @@ int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity,
|
||||
return UART_NOMODE;
|
||||
}
|
||||
|
||||
/* Do not modify hardware flow control */
|
||||
uint32_t conf = uart_config[uart].dev->CONFIG & UARTE_CONFIG_HWFC_Msk;
|
||||
|
||||
#ifdef UARTE_CONFIG_STOP_Msk
|
||||
if (stop_bits == UART_STOP_BITS_2) {
|
||||
dev(uart)->CONFIG |= UARTE_CONFIG_STOP_Msk;
|
||||
}
|
||||
else {
|
||||
dev(uart)->CONFIG &= ~UARTE_CONFIG_STOP_Msk;
|
||||
conf |= UARTE_CONFIG_STOP_Msk;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (parity == UART_PARITY_EVEN) {
|
||||
dev(uart)->CONFIG |= UARTE_CONFIG_PARITY_Msk;
|
||||
}
|
||||
else {
|
||||
dev(uart)->CONFIG &= ~UARTE_CONFIG_PARITY_Msk;
|
||||
conf |= UARTE_CONFIG_PARITY_Msk;
|
||||
}
|
||||
|
||||
uart_config[uart].dev->CONFIG = conf;
|
||||
return UART_OK;
|
||||
}
|
||||
|
||||
static inline void irq_handler(uart_t uart)
|
||||
static void irq_handler(uart_t uart)
|
||||
{
|
||||
if (dev(uart)->EVENTS_ENDRX) {
|
||||
dev(uart)->EVENTS_ENDRX = 0;
|
||||
if (uart_config[uart].dev->EVENTS_ENDRX) {
|
||||
uart_config[uart].dev->EVENTS_ENDRX = 0;
|
||||
|
||||
/* make sure we actually received new data */
|
||||
if (dev(uart)->RXD.AMOUNT != 0) {
|
||||
if (uart_config[uart].dev->RXD.AMOUNT != 0) {
|
||||
/* Process received byte */
|
||||
isr_ctx[uart].rx_cb(isr_ctx[uart].arg, rx_buf[uart]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MODULE_PERIPH_UART_NONBLOCKING
|
||||
if (dev(uart)->EVENTS_ENDTX) {
|
||||
if (uart_config[uart].dev->EVENTS_ENDTX) {
|
||||
/* reset flags and idsable ISR on EVENTS_ENDTX */
|
||||
dev(uart)->EVENTS_ENDTX = 0;
|
||||
dev(uart)->EVENTS_TXSTARTED = 0;
|
||||
dev(uart)->INTENCLR = UARTE_INTENSET_ENDTX_Msk;
|
||||
uart_config[uart].dev->EVENTS_ENDTX = 0;
|
||||
uart_config[uart].dev->EVENTS_TXSTARTED = 0;
|
||||
uart_config[uart].dev->INTENCLR = UARTE_INTENSET_ENDTX_Msk;
|
||||
if (tsrb_empty(&uart_tx_rb[uart])) {
|
||||
dev(uart)->TASKS_STOPTX = 1;
|
||||
uart_config[uart].dev->TASKS_STOPTX = 1;
|
||||
} else {
|
||||
tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]);
|
||||
_write_buf(uart, &tx_buf[uart], 1);
|
||||
@ -411,13 +402,13 @@ static inline void irq_handler(uart_t uart)
|
||||
cortexm_isr_end();
|
||||
}
|
||||
|
||||
#else /* nrf51 and nrf52832 etc */
|
||||
#else /* UART without EasyDMA*/
|
||||
|
||||
void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
{
|
||||
(void)uart;
|
||||
assume((unsigned)uart < UART_NUMOF);
|
||||
|
||||
NRF_UART0->TASKS_STARTTX = 1;
|
||||
uart_config[uart].dev->TASKS_STARTTX = 1;
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
/* This section of the function is not thread safe:
|
||||
@ -430,36 +421,36 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
while loop.
|
||||
*/
|
||||
/* reset ready flag */
|
||||
NRF_UART0->EVENTS_TXDRDY = 0;
|
||||
uart_config[uart].dev->EVENTS_TXDRDY = 0;
|
||||
/* write data into transmit register */
|
||||
NRF_UART0->TXD = data[i];
|
||||
uart_config[uart].dev->TXD = data[i];
|
||||
/* wait for any transmission to be done */
|
||||
while (NRF_UART0->EVENTS_TXDRDY == 0) {}
|
||||
while (uart_config[uart].dev->EVENTS_TXDRDY == 0) {}
|
||||
}
|
||||
|
||||
NRF_UART0->TASKS_STOPTX = 1;
|
||||
uart_config[uart].dev->TASKS_STOPTX = 1;
|
||||
}
|
||||
|
||||
void uart_poweron(uart_t uart)
|
||||
{
|
||||
(void)uart;
|
||||
assume((unsigned)uart < UART_NUMOF);
|
||||
|
||||
if (isr_ctx.rx_cb) {
|
||||
NRF_UART0->TASKS_STARTRX = 1;
|
||||
if (isr_ctx[uart].rx_cb) {
|
||||
uart_config[uart].dev->TASKS_STARTRX = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_poweroff(uart_t uart)
|
||||
{
|
||||
(void)uart;
|
||||
assume((unsigned)uart < UART_NUMOF);
|
||||
|
||||
NRF_UART0->TASKS_STOPRX = 1;
|
||||
uart_config[uart].dev->TASKS_STOPRX = 1;
|
||||
}
|
||||
|
||||
int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity,
|
||||
uart_stop_bits_t stop_bits)
|
||||
{
|
||||
(void)uart;
|
||||
assume((unsigned)uart < UART_NUMOF);
|
||||
|
||||
if (stop_bits != UART_STOP_BITS_1) {
|
||||
return UART_NOMODE;
|
||||
@ -474,29 +465,27 @@ int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity,
|
||||
}
|
||||
|
||||
if (parity == UART_PARITY_EVEN) {
|
||||
NRF_UART0->CONFIG |= UART_CONFIG_PARITY_Msk;
|
||||
uart_config[uart].dev->CONFIG |= UART_CONFIG_PARITY_Msk;
|
||||
}
|
||||
else {
|
||||
NRF_UART0->CONFIG &= ~UART_CONFIG_PARITY_Msk;
|
||||
uart_config[uart].dev->CONFIG &= ~UART_CONFIG_PARITY_Msk;
|
||||
}
|
||||
|
||||
return UART_OK;
|
||||
}
|
||||
|
||||
static inline void irq_handler(uart_t uart)
|
||||
static void irq_handler(uart_t uart)
|
||||
{
|
||||
(void)uart;
|
||||
|
||||
if (NRF_UART0->EVENTS_RXDRDY == 1) {
|
||||
NRF_UART0->EVENTS_RXDRDY = 0;
|
||||
uint8_t byte = (uint8_t)(NRF_UART0->RXD & 0xff);
|
||||
isr_ctx.rx_cb(isr_ctx.arg, byte);
|
||||
if (uart_config[uart].dev->EVENTS_RXDRDY == 1) {
|
||||
uart_config[uart].dev->EVENTS_RXDRDY = 0;
|
||||
uint8_t byte = (uint8_t)(uart_config[uart].dev->RXD & 0xff);
|
||||
isr_ctx[uart].rx_cb(isr_ctx[uart].arg, byte);
|
||||
}
|
||||
|
||||
cortexm_isr_end();
|
||||
}
|
||||
|
||||
#endif /* !CPU_MODEL_NRF52832XXAA && !CPU_FAM_NRF51 */
|
||||
#endif
|
||||
|
||||
#if defined(CPU_NRF53) || defined(CPU_NRF9160)
|
||||
void uart_isr_handler(void *arg)
|
||||
@ -519,4 +508,5 @@ void UART_1_ISR(void)
|
||||
irq_handler(UART_DEV(1));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* def CPU_NRF53 || CPU_NRF9160 */
|
||||
|
@ -8,6 +8,7 @@
|
||||
config CPU_COMMON_SAM0
|
||||
bool
|
||||
select HAS_PERIPH_CPUID
|
||||
select HAS_PERIPH_ADC_CONTINUOUS
|
||||
select HAS_PERIPH_FLASHPAGE
|
||||
select HAS_PERIPH_FLASHPAGE_IN_ADDRESS_SPACE
|
||||
select HAS_PERIPH_FLASHPAGE_PAGEWISE
|
||||
|
@ -7,6 +7,7 @@ ifeq (,$(filter $(CPU_MODELS_WITHOUT_DMA),$(CPU_MODEL)))
|
||||
FEATURES_PROVIDED += periph_dma
|
||||
endif
|
||||
|
||||
FEATURES_PROVIDED += periph_adc_continuous
|
||||
FEATURES_PROVIDED += periph_flashpage
|
||||
FEATURES_PROVIDED += periph_flashpage_in_address_space
|
||||
FEATURES_PROVIDED += periph_flashpage_pagewise
|
||||
|
@ -945,6 +945,14 @@ typedef struct {
|
||||
*/
|
||||
#define WDT_HAS_INIT (1)
|
||||
|
||||
/**
|
||||
* @brief Frequency meter configuration
|
||||
*/
|
||||
typedef struct {
|
||||
gpio_t pin; /**< GPIO at which the frequency is to be measured */
|
||||
uint8_t gclk_src; /**< GCLK source select for reference */
|
||||
} freqm_config_t;
|
||||
|
||||
#if defined(REV_DMAC) || DOXYGEN
|
||||
/**
|
||||
* @name sam0 DMA peripheral
|
||||
|
@ -49,16 +49,6 @@ static int _adc_configure(Adc *dev, adc_res_t res);
|
||||
|
||||
static mutex_t _lock = MUTEX_INIT;
|
||||
|
||||
static inline void _prep(void)
|
||||
{
|
||||
mutex_lock(&_lock);
|
||||
}
|
||||
|
||||
static inline void _done(void)
|
||||
{
|
||||
mutex_unlock(&_lock);
|
||||
}
|
||||
|
||||
static inline void _wait_syncbusy(Adc *dev)
|
||||
{
|
||||
#ifdef ADC_STATUS_SYNCBUSY
|
||||
@ -263,7 +253,7 @@ int adc_init(adc_t line)
|
||||
const uint8_t adc = 0;
|
||||
#endif
|
||||
|
||||
_prep();
|
||||
mutex_lock(&_lock);
|
||||
|
||||
uint8_t muxpos = (adc_channels[line].inputctrl & ADC_INPUTCTRL_MUXPOS_Msk)
|
||||
>> ADC_INPUTCTRL_MUXPOS_Pos;
|
||||
@ -284,34 +274,44 @@ int adc_init(adc_t line)
|
||||
gpio_init_mux(sam0_adc_pins[adc][muxneg], GPIO_MUX_B);
|
||||
}
|
||||
|
||||
_done();
|
||||
mutex_unlock(&_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t adc_sample(adc_t line, adc_res_t res)
|
||||
static Adc *_dev(adc_t line)
|
||||
{
|
||||
if (line >= ADC_NUMOF) {
|
||||
DEBUG("adc: line arg not applicable\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The SAMD5x/SAME5x family has two ADCs: ADC0 and ADC1. */
|
||||
#ifdef ADC0
|
||||
Adc *dev = adc_channels[line].dev;
|
||||
return adc_channels[line].dev;
|
||||
#else
|
||||
Adc *dev = ADC;
|
||||
(void)line;
|
||||
return ADC;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool diffmode = adc_channels[line].inputctrl & ADC_INPUTCTRL_DIFFMODE;
|
||||
|
||||
_prep();
|
||||
|
||||
if (_adc_configure(dev, res) != 0) {
|
||||
_done();
|
||||
DEBUG("adc: configuration failed\n");
|
||||
return -1;
|
||||
static Adc *_adc(uint8_t dev)
|
||||
{
|
||||
/* The SAMD5x/SAME5x family has two ADCs: ADC0 and ADC1. */
|
||||
#ifdef ADC0
|
||||
switch (dev) {
|
||||
case 0:
|
||||
return ADC0;
|
||||
case 1:
|
||||
return ADC1;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
(void)dev;
|
||||
return ADC;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int32_t _sample(adc_t line)
|
||||
{
|
||||
Adc *dev = _dev(line);
|
||||
bool diffmode = adc_channels[line].inputctrl & ADC_INPUTCTRL_DIFFMODE;
|
||||
|
||||
dev->INPUTCTRL.reg = ADC_GAIN_FACTOR_DEFAULT
|
||||
| adc_channels[line].inputctrl
|
||||
@ -319,7 +319,6 @@ int32_t adc_sample(adc_t line, adc_res_t res)
|
||||
#ifdef ADC_CTRLB_DIFFMODE
|
||||
dev->CTRLB.bit.DIFFMODE = diffmode;
|
||||
#endif
|
||||
|
||||
_wait_syncbusy(dev);
|
||||
|
||||
/* Start the conversion */
|
||||
@ -331,9 +330,6 @@ int32_t adc_sample(adc_t line, adc_res_t res)
|
||||
uint16_t sample = dev->RESULT.reg;
|
||||
int result;
|
||||
|
||||
_adc_poweroff(dev);
|
||||
_done();
|
||||
|
||||
/* in differential mode we lose one bit for the sign */
|
||||
if (diffmode) {
|
||||
result = 2 * (int16_t)sample;
|
||||
@ -341,11 +337,104 @@ int32_t adc_sample(adc_t line, adc_res_t res)
|
||||
result = sample;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint8_t _shift_from_res(adc_res_t res)
|
||||
{
|
||||
/* 16 bit mode is implemented as oversampling */
|
||||
if ((res & 0x3) == 1) {
|
||||
/* ADC does automatic right shifts beyond 16 samples */
|
||||
result <<= (4 - MIN(4, res >> 2));
|
||||
return 4 - MIN(4, res >> 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _get_adcs(bool *adc0, bool *adc1)
|
||||
{
|
||||
#ifndef ADC1
|
||||
*adc0 = true;
|
||||
*adc1 = false;
|
||||
return;
|
||||
#else
|
||||
*adc0 = false;
|
||||
*adc1 = false;
|
||||
for (unsigned i = 0; i < ADC_NUMOF; ++i) {
|
||||
if (adc_channels[i].dev == ADC0) {
|
||||
*adc0 = true;
|
||||
} else if (adc_channels[i].dev == ADC1) {
|
||||
*adc1 = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8_t _shift;
|
||||
void adc_continuous_begin(adc_res_t res)
|
||||
{
|
||||
bool adc0, adc1;
|
||||
_get_adcs(&adc0, &adc1);
|
||||
|
||||
mutex_lock(&_lock);
|
||||
|
||||
if (adc0) {
|
||||
_adc_configure(_adc(0), res);
|
||||
}
|
||||
if (adc1) {
|
||||
_adc_configure(_adc(1), res);
|
||||
}
|
||||
|
||||
return result;
|
||||
_shift = _shift_from_res(res);
|
||||
}
|
||||
|
||||
int32_t adc_continuous_sample(adc_t line)
|
||||
{
|
||||
int val;
|
||||
assert(line < ADC_NUMOF);
|
||||
|
||||
mutex_lock(&_lock);
|
||||
val = _sample(line) << _shift;
|
||||
mutex_unlock(&_lock);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void adc_continuous_stop(void)
|
||||
{
|
||||
bool adc0, adc1;
|
||||
_get_adcs(&adc0, &adc1);
|
||||
|
||||
if (adc0) {
|
||||
_adc_poweroff(_adc(0));
|
||||
}
|
||||
if (adc1) {
|
||||
_adc_poweroff(_adc(1));
|
||||
}
|
||||
|
||||
mutex_unlock(&_lock);
|
||||
}
|
||||
|
||||
int32_t adc_sample(adc_t line, adc_res_t res)
|
||||
{
|
||||
if (line >= ADC_NUMOF) {
|
||||
DEBUG("adc: line arg not applicable\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mutex_lock(&_lock);
|
||||
|
||||
Adc *dev = _dev(line);
|
||||
|
||||
if (_adc_configure(dev, res) != 0) {
|
||||
DEBUG("adc: configuration failed\n");
|
||||
mutex_unlock(&_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int val = _sample(line) << _shift_from_res(res);
|
||||
|
||||
_adc_poweroff(dev);
|
||||
mutex_unlock(&_lock);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
259
cpu/sam0_common/periph/freqm.c
Normal file
259
cpu/sam0_common/periph/freqm.c
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (C) 2023 ML!PA Consulting GmbH
|
||||
*
|
||||
* 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_sam0_common
|
||||
* @ingroup drivers_periph_freqm
|
||||
* @{
|
||||
*
|
||||
* @file freqm.c
|
||||
* @brief Frequency meter driver implementation
|
||||
*
|
||||
* @author Urs Gompper <urs.gompper@ml-pa.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "periph/freqm.h"
|
||||
|
||||
/* TODO: Remove defines when Microchip vendor files (which include these
|
||||
* defines) get updated.
|
||||
*/
|
||||
/* FREQM_GCLK_ID_REF is defined in newer versions of vendor header files */
|
||||
#ifndef FREQM_GCLK_ID_REF
|
||||
#define FREQM_GCLK_ID_REF (FREQM_GCLK_ID_MSR + 1)
|
||||
#endif
|
||||
|
||||
/* Channel Enable Mask */
|
||||
#define GCLK_PCHCTRL_CHEN_Msk (_U_(0x1) << GCLK_PCHCTRL_CHEN_Pos)
|
||||
/* Enable Mask */
|
||||
#define FREQM_CTRLA_ENABLE_Msk (_U_(0x1) << FREQM_CTRLA_ENABLE_Pos)
|
||||
/* Start Measurement Mask */
|
||||
#define FREQM_CTRLB_START_Msk (_U_(0x1) << FREQM_CTRLB_START_Pos)
|
||||
/* Measurement Done Interrupt Enable Mask */
|
||||
#define FREQM_INTENSET_DONE_Msk (_U_(0x1) << FREQM_INTENSET_DONE_Pos)
|
||||
/* Measurement Done Mask */
|
||||
#define FREQM_INTFLAG_DONE_Msk (_U_(0x1) << FREQM_INTFLAG_DONE_Pos)
|
||||
/* FREQM Status Mask */
|
||||
#define FREQM_STATUS_BUSY_Msk (_U_(0x1) << FREQM_STATUS_BUSY_Pos)
|
||||
/* Sticky Count Value Overflow Mask */
|
||||
#define FREQM_STATUS_OVF_Msk (_U_(0x1) << FREQM_STATUS_OVF_Pos)
|
||||
|
||||
/* check if pin has peripheral function GCLK */
|
||||
static int _freqm_pin(gpio_t pin)
|
||||
{
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(gclk_io_pins); ++i) {
|
||||
if (gclk_io_pins[i] == pin) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _gclk_connect(uint8_t id, uint8_t src, uint32_t flags)
|
||||
{
|
||||
GCLK->GENCTRL[id].reg = GCLK_GENCTRL_SRC(src) | GCLK_GENCTRL_GENEN | flags | GCLK_GENCTRL_IDC;
|
||||
while (GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL(id)) {}
|
||||
}
|
||||
|
||||
static int _freqm_gpio_init(gpio_t msr_gpio_src, uint8_t *gclk_io_id)
|
||||
{
|
||||
/* Check if selected pin has peripheral function GCLK */
|
||||
int index = _freqm_pin(msr_gpio_src);
|
||||
|
||||
/* Fail assertion if pin has no peripheral function GCLK */
|
||||
assert(index > 0);
|
||||
|
||||
/* Lookup which GCLK_IO[x] must be used */
|
||||
*gclk_io_id = gclk_io_ids[index];
|
||||
/* GCLK_IO[0] and GCLK_IO[1] can't be used here. They are associated with
|
||||
GCLKGEN[0] and GCLKGEN[1] respectively. These in turn are used by
|
||||
SAM0_GCLK_MAIN and SAM0_GCLK_32KHZ respectively */
|
||||
assert(*gclk_io_id > 1);
|
||||
|
||||
/* Initialize GPIO as input */
|
||||
gpio_init(msr_gpio_src, GPIO_IN);
|
||||
/* Enable peripheral function GCLK/IO on GPIO */
|
||||
gpio_init_mux(msr_gpio_src, GPIO_MUX_M);
|
||||
/* Connect GCLK_IO[*gclk_io_id] with input pin */
|
||||
_gclk_connect(*gclk_io_id, GCLK_SOURCE_GCLKIN, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _freqm_clock_init(uint8_t pin, uint8_t gclk_src)
|
||||
{
|
||||
/* Selection of the Generator and write Lock for FREQM_MSR */
|
||||
GCLK->PCHCTRL[FREQM_GCLK_ID_MSR].reg = GCLK_PCHCTRL_GEN(pin) | GCLK_PCHCTRL_CHEN_Msk;
|
||||
/* Wait for synchronization */
|
||||
while ((GCLK->PCHCTRL[FREQM_GCLK_ID_MSR].reg & GCLK_PCHCTRL_CHEN_Msk) !=
|
||||
GCLK_PCHCTRL_CHEN_Msk) {}
|
||||
|
||||
/* Selection of the Generator and write Lock for FREQM_REF */
|
||||
GCLK->PCHCTRL[FREQM_GCLK_ID_REF].reg = GCLK_PCHCTRL_GEN(gclk_src) | GCLK_PCHCTRL_CHEN_Msk;
|
||||
/* Wait for synchronization */
|
||||
while ((GCLK->PCHCTRL[FREQM_GCLK_ID_REF].reg & GCLK_PCHCTRL_CHEN_Msk) !=
|
||||
GCLK_PCHCTRL_CHEN_Msk) {}
|
||||
}
|
||||
|
||||
static struct {
|
||||
freqm_cb_t callback;
|
||||
void *context;
|
||||
freqm_t idx;
|
||||
uint8_t period_cnt;
|
||||
} freqm_obj;
|
||||
|
||||
struct _sync_ctx {
|
||||
mutex_t lock; /**< Mutex for blocking till measurement is done */
|
||||
uint32_t hz; /**< Measured frequency in Hz */
|
||||
bool overflow; /**< Overflow in FREQM counter */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Mutex for locking the FREQM device
|
||||
*/
|
||||
static mutex_t msr_lock = MUTEX_INIT;
|
||||
|
||||
static void _freqm_enable(uint8_t refnum)
|
||||
{
|
||||
mutex_lock(&msr_lock);
|
||||
|
||||
/* Save refnum for frequency calculation */
|
||||
freqm_obj.period_cnt = refnum;
|
||||
|
||||
FREQM->CFGA.reg = (uint16_t)(FREQM_CFGA_REFNUM(refnum));
|
||||
|
||||
/* Enable DONE Interrupt */
|
||||
FREQM->INTENSET.reg = FREQM_INTENSET_DONE_Msk;
|
||||
|
||||
/* Enable FREQM */
|
||||
FREQM->CTRLA.reg = FREQM_CTRLA_ENABLE_Msk;
|
||||
|
||||
/* Wait for Sync */
|
||||
while ((FREQM->SYNCBUSY.reg) != 0U) {}
|
||||
}
|
||||
|
||||
static void _freqm_disable(void)
|
||||
{
|
||||
/* Disable DONE Interrupt */
|
||||
FREQM->INTENCLR.reg = FREQM_INTENCLR_MASK;
|
||||
/* Disable FREQM */
|
||||
FREQM->CTRLA.reg &= ~FREQM_CTRLA_ENABLE_Msk;
|
||||
/* Wait for Sync */
|
||||
while ((FREQM->SYNCBUSY.reg) != 0U) {}
|
||||
|
||||
mutex_unlock(&msr_lock);
|
||||
}
|
||||
|
||||
bool _freqm_get_measurement(uint32_t *result)
|
||||
{
|
||||
const freqm_config_t *config = &freqm_config[freqm_obj.idx];
|
||||
|
||||
/* Calculate measured frequency */
|
||||
uint64_t result_tmp = FREQM->VALUE.reg * (uint64_t)(sam0_gclk_freq(config->gclk_src));
|
||||
|
||||
result_tmp = result_tmp / freqm_obj.period_cnt;
|
||||
*result = (uint32_t)result_tmp;
|
||||
|
||||
/* Read overflow status */
|
||||
bool overflow_condition = ((int)FREQM->STATUS.reg & FREQM_STATUS_OVF_Msk);
|
||||
|
||||
/* Clear overflow status */
|
||||
FREQM->STATUS.reg = FREQM_STATUS_OVF_Msk;
|
||||
|
||||
return overflow_condition;
|
||||
}
|
||||
|
||||
uint32_t _us_to_ref_clock_counts(uint32_t period_us, uint8_t clock_id)
|
||||
{
|
||||
uint64_t clk_cnt = (uint64_t)period_us * sam0_gclk_freq(clock_id) / US_PER_SEC;
|
||||
|
||||
if (clk_cnt > UINT8_MAX) {
|
||||
return UINT8_MAX;
|
||||
}
|
||||
else if (clk_cnt == 0) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return clk_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
static void _sync_cb(uint32_t res, bool overflow, void *_ctx)
|
||||
{
|
||||
struct _sync_ctx *ctx = _ctx;
|
||||
|
||||
ctx->hz = res;
|
||||
ctx->overflow = overflow;
|
||||
mutex_unlock(&ctx->lock);
|
||||
}
|
||||
|
||||
int freqm_frequency_get(freqm_t idx, uint32_t *result, uint32_t period_us)
|
||||
{
|
||||
struct _sync_ctx ctx = { .lock = MUTEX_INIT_LOCKED };
|
||||
|
||||
/* Invoke non-blocking FREQM measure function */
|
||||
freqm_frequency_get_async(idx, _sync_cb, &ctx, period_us);
|
||||
|
||||
/* Block until measurement is done */
|
||||
mutex_lock(&ctx.lock);
|
||||
|
||||
*result = ctx.hz;
|
||||
return ctx.overflow ? -EOVERFLOW : 0;
|
||||
}
|
||||
|
||||
void freqm_frequency_get_async(freqm_t idx, freqm_cb_t freqm_cb, void *context, uint32_t period_us)
|
||||
{
|
||||
const freqm_config_t *config = &freqm_config[idx];
|
||||
|
||||
uint8_t refnum = _us_to_ref_clock_counts(period_us, config->gclk_src);
|
||||
|
||||
_freqm_enable(refnum);
|
||||
|
||||
/* Register callback function */
|
||||
freqm_obj.callback = freqm_cb;
|
||||
freqm_obj.context = context;
|
||||
freqm_obj.idx = idx;
|
||||
|
||||
/* Clear the Done Interrupt flag */
|
||||
FREQM->INTFLAG.reg = FREQM_INTFLAG_DONE_Msk;
|
||||
|
||||
/* Start measurement */
|
||||
FREQM->CTRLB.reg = FREQM_CTRLB_START_Msk;
|
||||
}
|
||||
|
||||
void irq_freqm(void)
|
||||
{
|
||||
/* Clear the Done Interrupt flag */
|
||||
FREQM->INTFLAG.reg = FREQM_INTFLAG_DONE_Msk;
|
||||
|
||||
uint32_t result = 0;
|
||||
|
||||
bool overflow_condition = _freqm_get_measurement(&result);
|
||||
|
||||
/* Invoke the callback function */
|
||||
freqm_obj.callback(result, overflow_condition, freqm_obj.context);
|
||||
|
||||
_freqm_disable();
|
||||
}
|
||||
|
||||
void freqm_init(freqm_t idx)
|
||||
{
|
||||
uint8_t gclk_io_id = 0;
|
||||
const freqm_config_t *config = &freqm_config[idx];
|
||||
|
||||
/* Sanity check configuration */
|
||||
assert(config->gclk_src <= GCLK_GEN_NUM_MSB);
|
||||
|
||||
_freqm_gpio_init(config->pin, &gclk_io_id);
|
||||
_freqm_clock_init(gclk_io_id, config->gclk_src);
|
||||
|
||||
/* Enable interrupt */
|
||||
NVIC_EnableIRQ(FREQM_IRQn);
|
||||
}
|
@ -325,6 +325,9 @@ void cpu_init(void)
|
||||
#ifdef MODULE_PERIPH_PM
|
||||
| MCLK_APBAMASK_PM
|
||||
#endif
|
||||
#ifdef MODULE_PERIPH_FREQM
|
||||
| MCLK_APBAMASK_FREQM
|
||||
#endif
|
||||
#ifdef MODULE_PERIPH_GPIO_IRQ
|
||||
| MCLK_APBAMASK_EIC
|
||||
#endif
|
||||
|
@ -70,13 +70,19 @@ enum {
|
||||
* @name SAMD5x GCLK definitions
|
||||
* @{
|
||||
*/
|
||||
enum {
|
||||
SAM0_GCLK_MAIN = 0, /**< 120 MHz main clock */
|
||||
SAM0_GCLK_32KHZ, /**< 32 kHz clock */
|
||||
SAM0_GCLK_TIMER, /**< 4-8 MHz clock for xTimer */
|
||||
SAM0_GCLK_PERIPH, /**< 12-48 MHz (DFLL) clock */
|
||||
SAM0_GCLK_100MHZ, /**< 100MHz FDPLL clock */
|
||||
};
|
||||
#define SAM0_GCLK_MAIN 0 /**< 120 MHz main clock */
|
||||
#ifndef SAM0_GCLK_32KHZ
|
||||
#define SAM0_GCLK_32KHZ 1 /**< 32 kHz clock */
|
||||
#endif
|
||||
#ifndef SAM0_GCLK_TIMER
|
||||
#define SAM0_GCLK_TIMER 2 /**< 4-8 MHz clock for xTimer */
|
||||
#endif
|
||||
#ifndef SAM0_GCLK_PERIPH
|
||||
#define SAM0_GCLK_PERIPH 3 /**< 12-48 MHz (DFLL) clock */
|
||||
#endif
|
||||
#ifndef SAM0_GCLK_100MHZ
|
||||
#define SAM0_GCLK_100MHZ 4 /**< 100MHz FDPLL clock */
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -198,6 +204,28 @@ static const gpio_t rtc_tamper_pins[RTC_NUM_OF_TAMPERS] = {
|
||||
GPIO_PIN(PC, 0), GPIO_PIN(PC, 1)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Pins that have peripheral function GCLK
|
||||
*/
|
||||
static const gpio_t gclk_io_pins[] = {
|
||||
GPIO_PIN(PA, 10), GPIO_PIN(PA, 11), GPIO_PIN(PA, 14),
|
||||
GPIO_PIN(PA, 15), GPIO_PIN(PA, 16), GPIO_PIN(PA, 17),
|
||||
GPIO_PIN(PA, 27), GPIO_PIN(PA, 30), GPIO_PIN(PB, 10),
|
||||
GPIO_PIN(PB, 11), GPIO_PIN(PB, 12), GPIO_PIN(PB, 13),
|
||||
GPIO_PIN(PB, 14), GPIO_PIN(PB, 15), GPIO_PIN(PB, 16),
|
||||
GPIO_PIN(PB, 17), GPIO_PIN(PB, 18), GPIO_PIN(PB, 19),
|
||||
GPIO_PIN(PB, 20), GPIO_PIN(PB, 21), GPIO_PIN(PB, 22),
|
||||
GPIO_PIN(PB, 23)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GCLK IDs of pins that have peripheral function GCLK - This maps
|
||||
* directly to gclk_io_pins.
|
||||
*/
|
||||
static const uint8_t gclk_io_ids[] = {
|
||||
4, 5, 0, 1, 2, 3, 1, 0, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief NVM User Page Mapping - Dedicated Entries
|
||||
* Config values will be applied at power-on.
|
||||
|
@ -333,6 +333,26 @@ void _wlx5xx_init_subghz_debug_pins(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void swj_init(void)
|
||||
{
|
||||
#if defined(CPU_FAM_STM32F1)
|
||||
/* Only if the selected SWJ config differs from the reset value, we
|
||||
* actually need to do something. Since both sides are compile time
|
||||
* constants, this hole code gets optimized out by default */
|
||||
if (CONFIG_AFIO_MAPR_SWJ_CFG != SWJ_CFG_FULL_SWJ) {
|
||||
/* The remapping periph clock must first be enabled */
|
||||
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
|
||||
/* Handling of the MAPR register is a bit involved due to the
|
||||
* write-only nature of the SWJ_CFG field, which returns undefined
|
||||
* garbage on read. `afio_mapr_read()` will read the current MAPR
|
||||
* value, but clear the SWF_CFG vield. `afio_mapr_wriote()` will then
|
||||
* write the value read back, but apply the `SWF_CFG` configuration
|
||||
* from `CONFIG_AFIO_MAPR_SWJ_CFG` first.*/
|
||||
afio_mapr_write(afio_mapr_read());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void cpu_init(void)
|
||||
{
|
||||
/* initialize the Cortex-M core */
|
||||
@ -362,10 +382,7 @@ void cpu_init(void)
|
||||
/* initialize stdio prior to periph_init() to allow use of DEBUG() there */
|
||||
early_init();
|
||||
|
||||
#ifdef STM32F1_DISABLE_JTAG
|
||||
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
|
||||
AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE;
|
||||
#endif
|
||||
swj_init();
|
||||
|
||||
/* trigger static peripheral initialization */
|
||||
periph_init();
|
||||
|
@ -107,6 +107,67 @@ enum {
|
||||
};
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Possible values of the `SWJ_CFG` field in the AFIO->MAPR register
|
||||
*
|
||||
* @details This wraps the vendor header file preprocessor macros into a
|
||||
* C language `enum`.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* @brief Both JTAG-DP and SW-DP enabled, reset state
|
||||
*/
|
||||
SWJ_CFG_FULL_SWJ = 0,
|
||||
/**
|
||||
* @brief Both JTAG-DP and SW-DP enabled, but NJTRST disabled and pin
|
||||
* usable as GPIO
|
||||
*/
|
||||
SWJ_CFG_NO_NJTRST = AFIO_MAPR_SWJ_CFG_NOJNTRST,
|
||||
/**
|
||||
* @brief Only SW-DP enabled, JTAG pins usable as GPIOS
|
||||
*/
|
||||
SWJ_CFG_NO_JTAG_DP = AFIO_MAPR_SWJ_CFG_JTAGDISABLE,
|
||||
/**
|
||||
* @brief Neither JTAG-DP nor SW-DP enabled, JTAG and SWD pins usable as
|
||||
* GPIOS
|
||||
*/
|
||||
SWJ_CFG_DISABLED = AFIO_MAPR_SWJ_CFG_DISABLE,
|
||||
} afio_mapr_swj_cfg_t;
|
||||
|
||||
#ifndef CONFIG_AFIO_MAPR_SWJ_CFG
|
||||
/**
|
||||
* @brief By default, disable JTAG and keep only SWD
|
||||
*
|
||||
* This frees the JTAG pins for use as regular GPIOs. We do not support flashing
|
||||
* or debugging via JTAG anyway, so there is nothing lost except for a few bytes
|
||||
* of ROM to initialize the `SWJ_CFG` register.
|
||||
*/
|
||||
#define CONFIG_AFIO_MAPR_SWJ_CFG SWJ_CFG_NO_JTAG_DP
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Read the current value of the AFIO->MAPR register reproducibly
|
||||
*
|
||||
* This will explicitly clear the write-only `SWJ_CFG` field [26:24], as the
|
||||
* values read back are undefined.
|
||||
*/
|
||||
static inline uint32_t afio_mapr_read(void)
|
||||
{
|
||||
return AFIO->MAPR & (~(AFIO_MAPR_SWJ_CFG_Msk));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write to the AFIO->MAPR register apply the SWJ configuration
|
||||
* specified via @ref CONFIG_AFIO_MAPR_SWJ_CFG
|
||||
*
|
||||
* @pre @p new_value has all bits in the range [26:24] cleared (the
|
||||
* `SWJ_CFG` field).
|
||||
*/
|
||||
static inline void afio_mapr_write(uint32_t new_value)
|
||||
{
|
||||
AFIO->MAPR = CONFIG_AFIO_MAPR_SWJ_CFG | new_value;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -170,6 +170,36 @@ typedef struct {
|
||||
#define USBDEV_NUM_ENDPOINTS 8
|
||||
#endif
|
||||
|
||||
/* unify names across STM32 families */
|
||||
#ifdef SPI_CR1_CPHA_Msk
|
||||
# define STM32_SPI_CPHA_Msk SPI_CR1_CPHA_Msk
|
||||
#endif
|
||||
#ifdef SPI_CFG2_CPHA_Msk
|
||||
# define STM32_SPI_CPHA_Msk SPI_CFG2_CPHA_Msk
|
||||
#endif
|
||||
#ifdef SPI_CR1_CPOL_Msk
|
||||
# define STM32_SPI_CPOL_Msk SPI_CR1_CPOL_Msk
|
||||
#endif
|
||||
#ifdef SPI_CFG2_CPOL_Msk
|
||||
# define STM32_SPI_CPOL_Msk SPI_CFG2_CPOL_Msk
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Override the SPI mode values
|
||||
*
|
||||
* As the mode is set in bit 3 and 2 of the configuration register, we put the
|
||||
* correct configuration there
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_SPI_MODE_T
|
||||
typedef enum {
|
||||
SPI_MODE_0 = 0, /**< CPOL=0, CPHA=0 */
|
||||
SPI_MODE_1 = STM32_SPI_CPHA_Msk, /**< CPOL=0, CPHA=1 */
|
||||
SPI_MODE_2 = STM32_SPI_CPOL_Msk, /**< CPOL=1, CPHA=0 */
|
||||
SPI_MODE_3 = STM32_SPI_CPOL_Msk | STM32_SPI_CPHA_Msk, /**< CPOL=1, CPHA=0 */
|
||||
} spi_mode_t;
|
||||
/** @} */
|
||||
|
||||
#endif /* !DOXYGEN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -120,7 +120,7 @@ static void _init_pins(i2c_t dev)
|
||||
/* The remapping periph clock must first be enabled */
|
||||
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
|
||||
/* Then the remap can occur */
|
||||
AFIO->MAPR |= AFIO_MAPR_I2C1_REMAP;
|
||||
afio_mapr_write(afio_mapr_read() | AFIO_MAPR_I2C1_REMAP);
|
||||
}
|
||||
gpio_init_af(i2c_config[dev].scl_pin, GPIO_AF_OUT_OD);
|
||||
gpio_init_af(i2c_config[dev].sda_pin, GPIO_AF_OUT_OD);
|
||||
|
@ -28,8 +28,6 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "bitarithm.h"
|
||||
#include "cpu.h"
|
||||
#include "mutex.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "periph/spi.h"
|
||||
@ -65,9 +63,9 @@ static mutex_t locks[SPI_NUMOF];
|
||||
static uint32_t clocks[SPI_NUMOF];
|
||||
|
||||
/**
|
||||
* @brief Clock divider cache
|
||||
* @brief Clock prescaler cache
|
||||
*/
|
||||
static uint8_t dividers[SPI_NUMOF];
|
||||
static uint8_t prescalers[SPI_NUMOF];
|
||||
|
||||
static inline SPI_TypeDef *dev(spi_t bus)
|
||||
{
|
||||
@ -81,33 +79,24 @@ static inline bool _use_dma(const spi_conf_t *conf)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Multiplier for clock divider calculations
|
||||
*
|
||||
* Makes the divider calculation fixed point
|
||||
*/
|
||||
#define SPI_APB_CLOCK_SHIFT (4U)
|
||||
#define SPI_APB_CLOCK_MULT (1U << SPI_APB_CLOCK_SHIFT)
|
||||
|
||||
static uint8_t _get_clkdiv(const spi_conf_t *conf, uint32_t clock)
|
||||
static uint8_t _get_prescaler(const spi_conf_t *conf, uint32_t clock)
|
||||
{
|
||||
uint32_t bus_clock = periph_apb_clk(conf->apbbus);
|
||||
/* Shift bus_clock with SPI_APB_CLOCK_SHIFT to create a fixed point int */
|
||||
uint32_t div = (bus_clock << SPI_APB_CLOCK_SHIFT) / (2 * clock);
|
||||
DEBUG("[spi] clock: divider: %"PRIu32"\n", div);
|
||||
/* Test if the divider is 2 or smaller, keeping the fixed point in mind */
|
||||
if (div <= SPI_APB_CLOCK_MULT) {
|
||||
return 0;
|
||||
|
||||
uint8_t prescaler = 0;
|
||||
uint32_t prescaled_clock = bus_clock >> 1;
|
||||
const uint8_t prescaler_max = SPI_CR1_BR_Msk >> SPI_CR1_BR_Pos;
|
||||
for (; (prescaled_clock > clock) && (prescaler < prescaler_max); prescaler++) {
|
||||
prescaled_clock >>= 1;
|
||||
}
|
||||
/* determine MSB and compensate back for the fixed point int shift */
|
||||
uint8_t rounded_div = bitarithm_msb(div) - SPI_APB_CLOCK_SHIFT;
|
||||
/* Determine if rounded_div is not a power of 2 */
|
||||
if ((div & (div - 1)) != 0) {
|
||||
/* increment by 1 to ensure that the clock speed at most the
|
||||
* requested clock speed */
|
||||
rounded_div++;
|
||||
}
|
||||
return rounded_div > BR_MAX ? BR_MAX : rounded_div;
|
||||
|
||||
/* If the callers asks for an SPI frequency of at most x, bad things will
|
||||
* happen if this cannot be met. So let's have a blown assertion
|
||||
* rather than runtime failures that require a logic analyzer to
|
||||
* debug. */
|
||||
assert(prescaled_clock <= clock);
|
||||
|
||||
return prescaler;
|
||||
}
|
||||
|
||||
void spi_init(spi_t bus)
|
||||
@ -235,30 +224,30 @@ void spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
|
||||
periph_clk_en(spi_config[bus].apbbus, spi_config[bus].rccmask);
|
||||
/* enable device */
|
||||
if (clk != clocks[bus]) {
|
||||
dividers[bus] = _get_clkdiv(&spi_config[bus], clk);
|
||||
prescalers[bus] = _get_prescaler(&spi_config[bus], clk);
|
||||
clocks[bus] = clk;
|
||||
}
|
||||
uint8_t br = dividers[bus];
|
||||
uint8_t br = prescalers[bus];
|
||||
|
||||
DEBUG("[spi] acquire: requested clock: %"PRIu32", resulting clock: %"PRIu32
|
||||
" BR divider: %u\n",
|
||||
DEBUG("[spi] acquire: requested clock: %" PRIu32
|
||||
" Hz, resulting clock: %" PRIu32 " Hz, BR prescaler: %u\n",
|
||||
clk,
|
||||
periph_apb_clk(spi_config[bus].apbbus)/(1 << (br + 1)),
|
||||
br);
|
||||
periph_apb_clk(spi_config[bus].apbbus) >> (br + 1),
|
||||
(unsigned)br);
|
||||
|
||||
uint16_t cr1_settings = ((br << BR_SHIFT) | mode | SPI_CR1_MSTR);
|
||||
uint16_t cr1 = ((br << BR_SHIFT) | mode | SPI_CR1_MSTR | SPI_CR1_SPE);
|
||||
/* Settings to add to CR2 in addition to SPI_CR2_SETTINGS */
|
||||
uint16_t cr2_extra_settings = 0;
|
||||
uint16_t cr2 = SPI_CR2_SETTINGS;
|
||||
if (cs != SPI_HWCS_MASK) {
|
||||
cr1_settings |= (SPI_CR1_SSM | SPI_CR1_SSI);
|
||||
cr1 |= (SPI_CR1_SSM | SPI_CR1_SSI);
|
||||
}
|
||||
else {
|
||||
cr2_extra_settings = (SPI_CR2_SSOE);
|
||||
cr2 = (SPI_CR2_SSOE);
|
||||
}
|
||||
|
||||
#ifdef MODULE_PERIPH_DMA
|
||||
if (_use_dma(&spi_config[bus])) {
|
||||
cr2_extra_settings |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN;
|
||||
cr2 |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN;
|
||||
|
||||
dma_acquire(spi_config[bus].tx_dma);
|
||||
dma_setup(spi_config[bus].tx_dma,
|
||||
@ -277,11 +266,8 @@ void spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
|
||||
0);
|
||||
}
|
||||
#endif
|
||||
dev(bus)->CR1 = cr1_settings;
|
||||
/* Only modify CR2 if needed */
|
||||
if (cr2_extra_settings) {
|
||||
dev(bus)->CR2 = (SPI_CR2_SETTINGS | cr2_extra_settings);
|
||||
}
|
||||
dev(bus)->CR1 = cr1;
|
||||
dev(bus)->CR2 = cr2;
|
||||
}
|
||||
|
||||
void spi_release(spi_t bus)
|
||||
@ -396,10 +382,12 @@ void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
|
||||
assert(out || in);
|
||||
|
||||
/* active the given chip select line */
|
||||
dev(bus)->CR1 |= (SPI_CR1_SPE); /* this pulls the HW CS line low */
|
||||
if ((cs != SPI_HWCS_MASK) && gpio_is_valid(cs)) {
|
||||
gpio_clear((gpio_t)cs);
|
||||
}
|
||||
else {
|
||||
dev(bus)->CR2 |= SPI_CR2_SSOE;
|
||||
}
|
||||
|
||||
#ifdef MODULE_PERIPH_DMA
|
||||
if (_use_dma(&spi_config[bus])) {
|
||||
@ -414,9 +402,11 @@ void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
|
||||
|
||||
/* release the chip select if not specified differently */
|
||||
if ((!cont) && gpio_is_valid(cs)) {
|
||||
dev(bus)->CR1 &= ~(SPI_CR1_SPE); /* pull HW CS line high */
|
||||
if (cs != SPI_HWCS_MASK) {
|
||||
gpio_set((gpio_t)cs);
|
||||
}
|
||||
else {
|
||||
dev(bus)->CR2 &= ~(SPI_CR2_SSOE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
dist/tools/doccheck/generic_exclude_patterns
vendored
1
dist/tools/doccheck/generic_exclude_patterns
vendored
@ -20,6 +20,7 @@ warning: Member EPD_BW_SPI_DISPLAY_UPDATE_OPTION_[A-Z0-9_]* \(macro definition\)
|
||||
warning: Member EPD_BW_SPI_WAIT_[A-Z0-9_]* \(macro definition\) of
|
||||
warning: Member F_CPU \(macro definition\) of
|
||||
warning: Member F_RC_OSCILLATOR \(macro definition\) of
|
||||
warning: Member freqm_config\[\] \(variable\) of
|
||||
warning: Member FXOS8700_PARAM_ADDR \(macro definition\) of
|
||||
warning: Member FXOS8700_PARAM_I2C \(macro definition\) of
|
||||
warning: Member FXOS8700_PARAM_RENEW_INTERVAL \(macro definition\) of
|
||||
|
1
dist/tools/uf2/.gitignore
vendored
1
dist/tools/uf2/.gitignore
vendored
@ -1 +1,2 @@
|
||||
uf2conv.py
|
||||
uf2families.json
|
||||
|
5
dist/tools/uf2/Makefile
vendored
5
dist/tools/uf2/Makefile
vendored
@ -5,8 +5,11 @@ PKG_LICENSE=MIT
|
||||
|
||||
include $(RIOTBASE)/pkg/pkg.mk
|
||||
|
||||
all: $(CURDIR)/uf2conv.py
|
||||
all: $(CURDIR)/uf2conv.py $(CURDIR)/uf2families.json
|
||||
|
||||
$(CURDIR)/uf2conv.py:
|
||||
cp $(PKG_SOURCE_DIR)/utils/uf2conv.py .
|
||||
chmod a+x uf2conv.py
|
||||
|
||||
$(CURDIR)/uf2families.json:
|
||||
cp $(PKG_SOURCE_DIR)/utils/uf2families.json .
|
||||
|
16306
doc/doxygen/src/pinouts/p-nucleo-wb55.svg
Normal file
16306
doc/doxygen/src/pinouts/p-nucleo-wb55.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 1.8 MiB |
159
drivers/at/at.c
159
drivers/at/at.c
@ -6,6 +6,39 @@
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/* A note on URCs (Unsolicited Result Codes), regardless of whether URC handling
|
||||
* is enabled or not.
|
||||
*
|
||||
* Some DCEs (Data Circuit-terminating Equipment, aka modem), like the LTE
|
||||
* modules from uBlox define a grace period where URCs are guaranteed NOT to be
|
||||
* sent as the time span between:
|
||||
* - the command EOL character reception AND command being internally accepted
|
||||
* - the EOL character of the last response line
|
||||
*
|
||||
* As follows, there is an indeterminate amount of time between:
|
||||
* - the command EOL character being sent
|
||||
* - the command EOL character reception AND command being internally accepted,
|
||||
* i.e. the begin of the grace period
|
||||
*
|
||||
* In other words, we can get a URC (or more?) just after issuing the command
|
||||
* and before the first line of response. The net effect is that such URCs will
|
||||
* appear to be the first line of response to the last issued command.
|
||||
*
|
||||
* The current solution is to skip characters that don't match the expected
|
||||
* response, at the expense of losing these URCs. Note, we may already lose URCs
|
||||
* when calling at_drain() just before any at_send_cmd(). Success partially
|
||||
* depends on whether command echoing is enabled or not:
|
||||
* 1. echo enabled: by observation, it seems that the grace period begins
|
||||
* BEFORE the echoed command. This has the advantage that we ALWAYS know what
|
||||
* the first line of response must look like and so if it doesn't, then it's a
|
||||
* URC. Thus, any procedure that calls at_send_cmd() will catch and discard
|
||||
* these URCs.
|
||||
* 2. echo disabled: commands that expect a response (e.g. at_send_cmd_get_resp_wait_ok())
|
||||
* will catch and discard any URC (or, if MODULE_AT_URC enabled, hand it over
|
||||
* to the URC callbacks). For the rest, it is the application's responsibility
|
||||
* to handle it.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
@ -32,6 +65,10 @@
|
||||
#define AT_EVENT_PRIO EVENT_PRIO_HIGHEST
|
||||
#endif
|
||||
|
||||
#if defined(MODULE_AT_URC)
|
||||
static int _check_urc(clist_node_t *node, void *arg);
|
||||
#endif
|
||||
|
||||
#if defined(MODULE_AT_URC_ISR)
|
||||
static void _event_process_urc(event_t *_event)
|
||||
{
|
||||
@ -62,8 +99,7 @@ int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t
|
||||
|
||||
isrpipe_init(&dev->isrpipe, (uint8_t *)buf, bufsize);
|
||||
|
||||
return uart_init(uart, baudrate, _isrpipe_write_one_wrapper,
|
||||
dev);
|
||||
return uart_init(uart, baudrate, _isrpipe_write_one_wrapper, dev);
|
||||
}
|
||||
|
||||
int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout)
|
||||
@ -99,6 +135,15 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
int at_wait_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout)
|
||||
{
|
||||
int res;
|
||||
do {
|
||||
res = at_expect_bytes(dev, bytes, timeout);
|
||||
} while (res != 0 && res != -ETIMEDOUT);
|
||||
return res;
|
||||
}
|
||||
|
||||
void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len)
|
||||
{
|
||||
uart_write(dev->uart, (const uint8_t *)bytes, len);
|
||||
@ -175,11 +220,12 @@ int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout)
|
||||
uart_write(dev->uart, (const uint8_t *)CONFIG_AT_SEND_EOL, AT_SEND_EOL_LEN);
|
||||
|
||||
if (!IS_ACTIVE(CONFIG_AT_SEND_SKIP_ECHO)) {
|
||||
if (at_expect_bytes(dev, command, timeout)) {
|
||||
if (at_wait_bytes(dev, command, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (at_expect_bytes(dev, CONFIG_AT_SEND_EOL AT_RECV_EOL_1 AT_RECV_EOL_2, timeout)) {
|
||||
if (at_expect_bytes(dev, CONFIG_AT_SEND_EOL AT_RECV_EOL_1 AT_RECV_EOL_2,
|
||||
timeout)) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
@ -218,11 +264,7 @@ ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command,
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
||||
if (res == 0) {
|
||||
/* skip possible empty line */
|
||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
||||
}
|
||||
res = at_readline_skip_empty(dev, resp_buf, len, false, timeout);
|
||||
|
||||
out:
|
||||
return res;
|
||||
@ -242,35 +284,35 @@ ssize_t at_send_cmd_get_resp_wait_ok(at_dev_t *dev, const char *command, const c
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
||||
if (res == 0) {
|
||||
/* skip possible empty line */
|
||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
||||
}
|
||||
/* URCs may occur right after the command has been sent and before the
|
||||
* expected response */
|
||||
do {
|
||||
res = at_readline_skip_empty(dev, resp_buf, len, false, timeout);
|
||||
|
||||
/* Strip the expected prefix */
|
||||
if (res > 0 && resp_prefix && *resp_prefix) {
|
||||
size_t prefix_len = strlen(resp_prefix);
|
||||
if (strncmp(resp_buf, resp_prefix, prefix_len) == 0) {
|
||||
size_t remaining_len = strlen(resp_buf) - prefix_len;
|
||||
/* The one extra byte in the copy is the terminating nul byte */
|
||||
memmove(resp_buf, resp_buf + prefix_len, remaining_len + 1);
|
||||
res -= prefix_len;
|
||||
/* Strip the expected prefix */
|
||||
if (res > 0 && resp_prefix && *resp_prefix) {
|
||||
size_t prefix_len = strlen(resp_prefix);
|
||||
if (strncmp(resp_buf, resp_prefix, prefix_len) == 0) {
|
||||
size_t remaining_len = strlen(resp_buf) - prefix_len;
|
||||
/* The one extra byte in the copy is the terminating nul byte */
|
||||
memmove(resp_buf, resp_buf + prefix_len, remaining_len + 1);
|
||||
res -= prefix_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (res >= 0);
|
||||
|
||||
/* wait for OK */
|
||||
if (res >= 0) {
|
||||
res_ok = at_readline(dev, ok_buf, sizeof(ok_buf), false, timeout);
|
||||
if (res_ok == 0) {
|
||||
/* skip possible empty line */
|
||||
res_ok = at_readline(dev, ok_buf, sizeof(ok_buf), false, timeout);
|
||||
res_ok = at_readline_skip_empty(dev, ok_buf, sizeof(ok_buf), false, timeout);
|
||||
if (res_ok < 0) {
|
||||
return -1;
|
||||
}
|
||||
ssize_t len_ok = sizeof(CONFIG_AT_RECV_OK) - 1;
|
||||
if ((len_ok != 0) && (strcmp(ok_buf, CONFIG_AT_RECV_OK) == 0)) {
|
||||
}
|
||||
else {
|
||||
/* Something else then OK */
|
||||
/* Something else than OK */
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
@ -295,8 +337,6 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* only clear the response buffer after sending the command,
|
||||
* so the same buffer can be used for command and response */
|
||||
memset(resp_buf, '\0', len);
|
||||
|
||||
while (1) {
|
||||
@ -358,19 +398,16 @@ int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout
|
||||
uart_write(dev->uart, (const uint8_t *)command, cmdlen);
|
||||
uart_write(dev->uart, (const uint8_t *)CONFIG_AT_SEND_EOL, AT_SEND_EOL_LEN);
|
||||
|
||||
if (at_expect_bytes(dev, command, timeout)) {
|
||||
return -1;
|
||||
if (!IS_ACTIVE(CONFIG_AT_SEND_SKIP_ECHO)) {
|
||||
if (at_wait_bytes(dev, command, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
if (at_expect_bytes(dev, CONFIG_AT_SEND_EOL, timeout)) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
if (at_expect_bytes(dev, CONFIG_AT_SEND_EOL AT_RECV_EOL_2, timeout)) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (at_expect_bytes(dev, ">", timeout)) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return at_wait_bytes(dev, ">", timeout);
|
||||
}
|
||||
|
||||
int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout)
|
||||
@ -378,16 +415,31 @@ int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout)
|
||||
int res;
|
||||
char resp_buf[64];
|
||||
|
||||
res = at_send_cmd_get_resp(dev, command, resp_buf, sizeof(resp_buf), timeout);
|
||||
res = at_send_cmd_get_resp(dev, command, resp_buf, sizeof(resp_buf),
|
||||
timeout);
|
||||
|
||||
if (res > 0) {
|
||||
ssize_t len_ok = sizeof(CONFIG_AT_RECV_OK) - 1;
|
||||
if ((len_ok != 0) && (strcmp(resp_buf, CONFIG_AT_RECV_OK) == 0)) {
|
||||
res = 0;
|
||||
size_t const len_ok = sizeof(CONFIG_AT_RECV_OK) - 1;
|
||||
size_t const len_err = sizeof(CONFIG_AT_RECV_ERROR) - 1;
|
||||
size_t const len_cme_cms = sizeof("+CME ERROR:") - 1;
|
||||
|
||||
while (res >= 0) {
|
||||
if (strncmp(resp_buf, CONFIG_AT_RECV_OK, len_ok) == 0) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
res = -1;
|
||||
else if (strncmp(resp_buf, CONFIG_AT_RECV_ERROR, len_err) == 0) {
|
||||
return -1;
|
||||
}
|
||||
else if (strncmp(resp_buf, "+CME ERROR:", len_cme_cms) == 0) {
|
||||
return -2;
|
||||
}
|
||||
else if (strncmp(resp_buf, "+CMS ERROR:", len_cme_cms) == 0) {
|
||||
return -2;
|
||||
}
|
||||
/* probably a sneaky URC */
|
||||
#ifdef MODULE_AT_URC
|
||||
clist_foreach(&dev->urc_list, _check_urc, resp_buf);
|
||||
#endif
|
||||
res = at_readline_skip_empty(dev, resp_buf, sizeof(resp_buf), false, timeout);
|
||||
}
|
||||
|
||||
return res;
|
||||
@ -445,6 +497,17 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
ssize_t at_readline_skip_empty(at_dev_t *dev, char *resp_buf, size_t len,
|
||||
bool keep_eol, uint32_t timeout)
|
||||
{
|
||||
ssize_t res = at_readline(dev, resp_buf, len, keep_eol, timeout);
|
||||
if (res == 0) {
|
||||
/* skip possible empty line */
|
||||
res = at_readline(dev, resp_buf, len, keep_eol, timeout);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef MODULE_AT_URC
|
||||
void at_add_urc(at_dev_t *dev, at_urc_t *urc)
|
||||
{
|
||||
|
@ -275,6 +275,52 @@ extern "C" {
|
||||
/ AT24CXXX_POLL_DELAY_US))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name AT24CS04 constants
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief 512 Byte memory
|
||||
*/
|
||||
#define AT24CS04_EEPROM_SIZE (512U)
|
||||
/**
|
||||
* @brief 32 pages of 16 bytes each
|
||||
*/
|
||||
#define AT24CS04_PAGE_SIZE (16U)
|
||||
/**
|
||||
* @brief Delay to complete write operation
|
||||
*/
|
||||
#define AT24CS04_PAGE_WRITE_DELAY_US (5000U)
|
||||
/**
|
||||
* @brief Number of poll attempts
|
||||
*/
|
||||
#define AT24CS04_MAX_POLLS (1 + (AT24CS04_PAGE_WRITE_DELAY_US \
|
||||
/ AT24CXXX_POLL_DELAY_US))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name AT24CS08 constants
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief 1 kiB memory
|
||||
*/
|
||||
#define AT24CS08_EEPROM_SIZE (1024U)
|
||||
/**
|
||||
* @brief 64 pages of 16 bytes each
|
||||
*/
|
||||
#define AT24CS08_PAGE_SIZE (16U)
|
||||
/**
|
||||
* @brief Delay to complete write operation
|
||||
*/
|
||||
#define AT24CS08_PAGE_WRITE_DELAY_US (5000U)
|
||||
/**
|
||||
* @brief Number of poll attempts
|
||||
*/
|
||||
#define AT24CS08_MAX_POLLS (1 + (AT24CS08_PAGE_WRITE_DELAY_US \
|
||||
/ AT24CXXX_POLL_DELAY_US))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name AT24C1024 constants
|
||||
* @{
|
||||
@ -369,6 +415,14 @@ extern "C" {
|
||||
#define AT24CXXX_EEPROM_SIZE (AT24C01A_EEPROM_SIZE)
|
||||
#define AT24CXXX_PAGE_SIZE (AT24C01A_PAGE_SIZE)
|
||||
#define AT24CXXX_MAX_POLLS (AT24C01A_MAX_POLLS)
|
||||
#elif IS_USED(MODULE_AT24CS04)
|
||||
#define AT24CXXX_EEPROM_SIZE (AT24CS04_EEPROM_SIZE)
|
||||
#define AT24CXXX_PAGE_SIZE (AT24CS04_PAGE_SIZE)
|
||||
#define AT24CXXX_MAX_POLLS (AT24CS04_MAX_POLLS)
|
||||
#elif IS_USED(MODULE_AT24CS08)
|
||||
#define AT24CXXX_EEPROM_SIZE (AT24CS08_EEPROM_SIZE)
|
||||
#define AT24CXXX_PAGE_SIZE (AT24CS08_PAGE_SIZE)
|
||||
#define AT24CXXX_MAX_POLLS (AT24CS08_MAX_POLLS)
|
||||
#elif IS_USED(MODULE_AT24MAC)
|
||||
#define AT24CXXX_EEPROM_SIZE (AT24MAC_EEPROM_SIZE)
|
||||
#define AT24CXXX_PAGE_SIZE (AT24MAC_PAGE_SIZE)
|
||||
|
@ -195,8 +195,8 @@ typedef struct {
|
||||
* @param[in] buf input buffer
|
||||
* @param[in] bufsize size of @p buf
|
||||
*
|
||||
* @returns success code UART_OK on success
|
||||
* @returns error code UART_NODEV or UART_NOBAUD otherwise
|
||||
* @retval success code UART_OK on success
|
||||
* @retval error code UART_NODEV or UART_NOBAUD otherwise
|
||||
*/
|
||||
int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t bufsize);
|
||||
|
||||
@ -209,8 +209,8 @@ int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t
|
||||
* @param[in] command command string to send
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns 0 when device answers "OK"
|
||||
* @returns <0 otherwise
|
||||
* @retval 0 when device answers "OK"
|
||||
* @retval <0 otherwise
|
||||
*/
|
||||
int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout);
|
||||
|
||||
@ -224,8 +224,8 @@ int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout);
|
||||
* @param[in] command command string to send
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @return 0 when prompt is received
|
||||
* @return <0 otherwise
|
||||
* @retval 0 when prompt is received
|
||||
* @retval <0 otherwise
|
||||
*/
|
||||
int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout);
|
||||
|
||||
@ -243,8 +243,8 @@ int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout
|
||||
* @param[in] len len of @p buffer
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns length of response on success
|
||||
* @returns <0 on error
|
||||
* @retval n length of response on success
|
||||
* @retval <0 on error
|
||||
*/
|
||||
ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout);
|
||||
|
||||
@ -263,8 +263,8 @@ ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command, char *resp_buf,
|
||||
* @param[in] len len of @p buffer
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns length of response on success
|
||||
* @returns <0 on error
|
||||
* @retval n length of response on success
|
||||
* @retval <0 on error
|
||||
*/
|
||||
ssize_t at_send_cmd_get_resp_wait_ok(at_dev_t *dev, const char *command, const char *resp_prefix,
|
||||
char *resp_buf, size_t len, uint32_t timeout);
|
||||
@ -286,9 +286,9 @@ ssize_t at_send_cmd_get_resp_wait_ok(at_dev_t *dev, const char *command, const c
|
||||
* @param[in] keep_eol true to keep the CR character in the response
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns length of response on success
|
||||
* @returns -1 on error
|
||||
* @returns -2 on CMS or CME error
|
||||
* @retval n length of response on success
|
||||
* @retval -1 on error
|
||||
* @retval -2 on CMS or CME error
|
||||
*/
|
||||
ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf,
|
||||
size_t len, bool keep_eol, uint32_t timeout);
|
||||
@ -300,11 +300,23 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf
|
||||
* @param[in] bytes buffer containing bytes to expect (NULL-terminated)
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns 0 on success
|
||||
* @returns <0 otherwise
|
||||
* @retval 0 on success
|
||||
* @retval <0 otherwise
|
||||
*/
|
||||
int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Repeatedly calls at_expect_bytes() until a match or timeout occurs
|
||||
*
|
||||
* @param[in] dev device to operate on
|
||||
* @param[in] bytes buffer containing bytes to expect (NULL-terminated)
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval <0 otherwise
|
||||
*/
|
||||
int at_wait_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Receives bytes into @p bytes buffer until the string pattern
|
||||
* @p string is received or the buffer is full.
|
||||
@ -317,8 +329,8 @@ int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout);
|
||||
* bytes.
|
||||
* @param[in] timeout timeout (in usec) of inactivity to finish read
|
||||
*
|
||||
* @returns 0 on success
|
||||
* @returns <0 on error
|
||||
* @retval 0 on success
|
||||
* @retval <0 on error
|
||||
*/
|
||||
int at_recv_bytes_until_string(at_dev_t *dev, const char *string,
|
||||
char *bytes, size_t *bytes_len,
|
||||
@ -341,7 +353,7 @@ void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len);
|
||||
* @param[in] len maximum number of bytes to receive
|
||||
* @param[in] timeout timeout (in usec) of inactivity to finish read
|
||||
*
|
||||
* @returns Number of bytes read, eventually zero if no bytes available
|
||||
* @retval n Number of bytes read, eventually zero if no bytes available
|
||||
*/
|
||||
ssize_t at_recv_bytes(at_dev_t *dev, char *bytes, size_t len, uint32_t timeout);
|
||||
|
||||
@ -352,8 +364,8 @@ ssize_t at_recv_bytes(at_dev_t *dev, char *bytes, size_t len, uint32_t timeout);
|
||||
* @param[in] command command to send
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns 0 on success
|
||||
* @returns <0 otherwise
|
||||
* @retval 0 on success
|
||||
* @retval <0 otherwise
|
||||
*/
|
||||
int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout);
|
||||
|
||||
@ -366,11 +378,26 @@ int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout);
|
||||
* @param[in] keep_eol true to keep the CR character in the response
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @returns line length on success
|
||||
* @returns <0 on error
|
||||
* @retval n line length on success
|
||||
* @retval <0 on error
|
||||
*/
|
||||
ssize_t at_readline(at_dev_t *dev, char *resp_buf, size_t len, bool keep_eol, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Read a line from device, skipping a possibly empty line.
|
||||
*
|
||||
* @param[in] dev device to operate on
|
||||
* @param[in] resp_buf buffer to store line
|
||||
* @param[in] len size of @p resp_buf
|
||||
* @param[in] keep_eol true to keep the CR character in the response
|
||||
* @param[in] timeout timeout (in usec)
|
||||
*
|
||||
* @retval n line length on success
|
||||
* @retval <0 on error
|
||||
*/
|
||||
ssize_t at_readline_skip_empty(at_dev_t *dev, char *resp_buf, size_t len,
|
||||
bool keep_eol, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Drain device input buffer
|
||||
*
|
||||
|
@ -73,6 +73,7 @@
|
||||
#ifndef MTD_H
|
||||
#define MTD_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "xfa.h"
|
||||
@ -517,6 +518,19 @@ int mtd_erase_sector(mtd_dev_t *mtd, uint32_t sector, uint32_t num);
|
||||
*/
|
||||
int mtd_power(mtd_dev_t *mtd, enum mtd_power_state power);
|
||||
|
||||
/**
|
||||
* @brief Get an MTD device by index
|
||||
*
|
||||
* @param[in] idx Index of the MTD device
|
||||
*
|
||||
* @return MTD_0 for @p idx 0 and so on
|
||||
* NULL if no MTD device exists for the given index
|
||||
*/
|
||||
static inline mtd_dev_t *mtd_dev_get(unsigned idx)
|
||||
{
|
||||
return ((MTD_NUMOF != 0) && (idx < MTD_NUMOF)) ? mtd_dev_xfa[idx] : NULL;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -69,6 +69,8 @@ extern mtd_emulated_t mtd_emulated_dev0;
|
||||
/**
|
||||
* @brief Get the default MTD device by index
|
||||
*
|
||||
* @deprecated Use @ref mtd_dev_get instead
|
||||
*
|
||||
* @param[in] idx Index of the MTD device
|
||||
*
|
||||
* @return MTD_0 for @p idx 0 and so on
|
||||
|
@ -245,10 +245,10 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "kernel_defines.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "periph/i2c.h"
|
||||
|
||||
@ -326,14 +326,18 @@ typedef uint8_t pcf857x_data_t; /**< type that can mask all expander pins */
|
||||
#endif /* MODULE_PCF8575 || DOXYGEN */
|
||||
/** @} */
|
||||
|
||||
/** Definition of PCF857X driver error codes */
|
||||
/**
|
||||
* @brief Definition of PCF857X driver error codes
|
||||
*
|
||||
* @deprecated These are aliases for errno error codes now, use them directly
|
||||
*/
|
||||
typedef enum {
|
||||
PCF857X_OK, /**< success */
|
||||
PCF857X_ERROR_I2C, /**< I2C communication error */
|
||||
PCF857X_ERROR_INV_EXP, /**< invalid expander variant */
|
||||
PCF857X_ERROR_INV_MODE, /**< invalid pin mode */
|
||||
PCF857X_ERROR_INV_FLANK, /**< invalid interrupt flank */
|
||||
PCF857X_ERROR_INT_PIN, /**< interrupt pin initialization failed */
|
||||
PCF857X_OK = 0, /**< success */
|
||||
PCF857X_ERROR_I2C = ENXIO, /**< I2C communication error */
|
||||
PCF857X_ERROR_INV_EXP = ENOTSUP, /**< invalid expander variant */
|
||||
PCF857X_ERROR_INV_MODE = EINVAL, /**< invalid pin mode */
|
||||
PCF857X_ERROR_INV_FLANK = EINVAL, /**< invalid interrupt flank */
|
||||
PCF857X_ERROR_INT_PIN = ENOSYS, /**< interrupt pin initialization failed */
|
||||
} pcf857x_error_codes_t;
|
||||
|
||||
/**
|
||||
@ -453,9 +457,8 @@ typedef struct {
|
||||
* has to be defined by the default configuration parameter
|
||||
* #PCF857X_PARAM_INT_PIN (pcf857x_params_t::int_pin).
|
||||
*
|
||||
* @retval PCF857X_OK on success
|
||||
* @retval PCF857X_ERROR_* a negative error code on error,
|
||||
* see #pcf857x_error_codes_t
|
||||
* @retval 0 on success
|
||||
* @retval <0 a negative errno error code on error
|
||||
*/
|
||||
int pcf857x_init(pcf857x_t *dev, const pcf857x_params_t *params);
|
||||
|
||||
@ -472,13 +475,12 @@ int pcf857x_init(pcf857x_t *dev, const pcf857x_params_t *params);
|
||||
* the driver physically supports only the modes #GPIO_IN_PU and
|
||||
* #GPIO_OD_PU. The other logically identical modes #GPIO_IN, #GPIO_OUT
|
||||
* and #GPIO_OD are emulated. For the #GPIO_IN_PU mode the function returns
|
||||
* with #PCF857X_ERROR_INV_MODE.
|
||||
* with `-EINVAL`.
|
||||
* - After initialization in #GPIO_OUT mode the pin is actively driven LOW,
|
||||
* after initialization in all other modes the pin is pulled-up to HIGH.
|
||||
*
|
||||
* @retval PCF857X_OK on success
|
||||
* @retval PCF857X_ERROR_* a negative error code on error,
|
||||
* see #pcf857x_error_codes_t
|
||||
* @retval 0 on success
|
||||
* @retval <0 a negative errno error code on error
|
||||
*/
|
||||
int pcf857x_gpio_init(pcf857x_t *dev, gpio_t pin, gpio_mode_t mode);
|
||||
|
||||
@ -504,7 +506,7 @@ int pcf857x_gpio_init(pcf857x_t *dev, gpio_t pin, gpio_mode_t mode);
|
||||
* the driver physically supports only the modes #GPIO_IN_PU and
|
||||
* #GPIO_OD_PU. The other logically identical modes #GPIO_IN, #GPIO_OUT
|
||||
* and #GPIO_OD are emulated. For the #GPIO_IN_PU mode the function returns
|
||||
* with #PCF857X_ERROR_INV_MODE.
|
||||
* with `-EINVAL`.
|
||||
* - After initialization in #GPIO_OUT mode the pin is actively driven LOW,
|
||||
* after initialization in all other modes the pin is pulled-up to HIGH.
|
||||
*
|
||||
@ -515,9 +517,8 @@ int pcf857x_gpio_init(pcf857x_t *dev, gpio_t pin, gpio_mode_t mode);
|
||||
* @param[in] isr ISR that is called back from interrupt context
|
||||
* @param[in] arg optional argument passed to the callback
|
||||
*
|
||||
* @retval PCF857X_OK on success
|
||||
* @retval PCF857X_ERROR_* a negative error code on error,
|
||||
* see #pcf857x_error_codes_t
|
||||
* @retval 0 on success
|
||||
* @retval <0 a negative errno error code on error
|
||||
*/
|
||||
int pcf857x_gpio_init_int(pcf857x_t *dev, gpio_t pin,
|
||||
gpio_mode_t mode,
|
||||
|
@ -128,6 +128,33 @@ int adc_init(adc_t line);
|
||||
*/
|
||||
int32_t adc_sample(adc_t line, adc_res_t res);
|
||||
|
||||
/**
|
||||
* @brief Configure the ADC with a given resolution for continuous sampling
|
||||
*
|
||||
* @note requires the `periph_adc_continuous` feature
|
||||
*
|
||||
* @param[in] res resolution to use for conversion
|
||||
*/
|
||||
void adc_continuous_begin(adc_res_t res);
|
||||
|
||||
/**
|
||||
* @brief Sample an ADC line without powering off the ADC afterward
|
||||
*
|
||||
* @note requires the `periph_adc_continuous` feature
|
||||
*
|
||||
* @brief Sample a value from the given ADC line
|
||||
*
|
||||
* @return the sampled value on success
|
||||
*/
|
||||
int32_t adc_continuous_sample(adc_t line);
|
||||
|
||||
/**
|
||||
* @brief Disable the ADC to save power
|
||||
*
|
||||
* @note requires the `periph_adc_continuous` feature
|
||||
*/
|
||||
void adc_continuous_stop(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user