mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 05:52:44 +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:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, reopened, synchronize]
|
types: [opened, reopened, synchronize]
|
||||||
|
merge_group:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-commits:
|
check-commits:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -24,3 +26,10 @@ jobs:
|
|||||||
- name: Run checks
|
- name: Run checks
|
||||||
run: |
|
run: |
|
||||||
./dist/tools/${{ matrix.check }}/check.sh "${{ github.base_ref }}"
|
./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]
|
types: [opened, reopened, labeled, unlabeled, synchronize]
|
||||||
pull_request_review:
|
pull_request_review:
|
||||||
types: [submitted, dismissed]
|
types: [submitted, dismissed]
|
||||||
|
merge_group:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-labels:
|
check-labels:
|
||||||
|
if: github.event_name != 'merge_group'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: RIOT-OS/check-labels-action@v1.1.1
|
- 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:
|
on:
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened]
|
||||||
|
merge_group:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
triage:
|
triage:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name != 'merge_group'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/labeler@main
|
- uses: actions/labeler@main
|
||||||
with:
|
with:
|
||||||
|
18
.github/workflows/static-test.yml
vendored
18
.github/workflows/static-test.yml
vendored
@ -13,6 +13,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- '*'
|
- '*'
|
||||||
|
merge_group:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
static-tests:
|
static-tests:
|
||||||
@ -21,11 +22,18 @@ jobs:
|
|||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
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
|
- name: Setup git
|
||||||
run: |
|
run: |
|
||||||
# Note: ${{ github.base_ref }} is empty when not in a PR
|
# Note: CI_BASE_BRANCH is empty when not in a PR
|
||||||
if [ -n "${{ github.base_ref }}" ]; then
|
if [ -n "${CI_BASE_BRANCH}" ]; then
|
||||||
git fetch origin ${{ github.base_ref }}:${{ github.base_ref }} --no-tags
|
git fetch origin ${CI_BASE_BRANCH}:${CI_BASE_BRANCH} --no-tags
|
||||||
else
|
else
|
||||||
git config diff.renameLimit 16384
|
git config diff.renameLimit 16384
|
||||||
fi
|
fi
|
||||||
@ -34,9 +42,9 @@ jobs:
|
|||||||
run: docker pull riot/static-test-tools:latest
|
run: docker pull riot/static-test-tools:latest
|
||||||
- name: Run static-tests
|
- name: Run static-tests
|
||||||
run: |
|
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 \
|
docker run --rm \
|
||||||
-e CI_BASE_BRANCH=${{ github.base_ref }} \
|
-e CI_BASE_BRANCH \
|
||||||
-e GITHUB_RUN_ID=${GITHUB_RUN_ID} \
|
-e GITHUB_RUN_ID=${GITHUB_RUN_ID} \
|
||||||
-v $(pwd):/data/riotbuild \
|
-v $(pwd):/data/riotbuild \
|
||||||
riot/static-test-tools:latest \
|
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:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- '*'
|
- '*'
|
||||||
|
merge_group:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tools-build:
|
tools-build:
|
||||||
|
2
.github/workflows/tools-test.yml
vendored
2
.github/workflows/tools-test.yml
vendored
@ -9,9 +9,11 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- '*'
|
- '*'
|
||||||
|
merge_group:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
python-tests:
|
python-tests:
|
||||||
|
if: github.event_name != 'merge_group'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
|
36
.murdock
36
.murdock
@ -178,22 +178,18 @@ check_label() {
|
|||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
# this function returns 0 when this is build is building one of the two bors
|
# true if "$2" starts with "$1", false otherwise
|
||||||
# branches ("staging" or "trying", 1 otherwise.
|
startswith() {
|
||||||
is_bors_build() {
|
case "${2}" in
|
||||||
test "${CI_BUILD_BRANCH}" = "staging" || test "${CI_BUILD_BRANCH}" = "trying"
|
${1}*) true ;;
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# Set CI_BASE_COMMIT in case of a bors build.
|
# this function returns 0 when this build is building a merge queue branch.
|
||||||
# This assumes that bors always adds a single merge commit (possibly itself
|
is_merge_queue_build() {
|
||||||
# including multiple merges for PRs) on the base branch.
|
startswith "gh-readonly-queue/" "${CI_BUILD_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
|
|
||||||
|
|
||||||
# fullbuild logic
|
# fullbuild logic
|
||||||
# non-full-builds are those where can_fast_ci_run might reduce the build
|
# non-full-builds are those where can_fast_ci_run might reduce the build
|
||||||
@ -216,8 +212,8 @@ fi
|
|||||||
# configurations.
|
# configurations.
|
||||||
if [ -z "${QUICK_BUILD}" ]; then
|
if [ -z "${QUICK_BUILD}" ]; then
|
||||||
export QUICK_BUILD=0
|
export QUICK_BUILD=0
|
||||||
if is_bors_build ; then
|
if is_merge_queue_build; then
|
||||||
# always do full build for bors' branches
|
# always do full build for merge queue' branches
|
||||||
true
|
true
|
||||||
elif [ ${FULL_BUILD} -eq 1 ]; then
|
elif [ ${FULL_BUILD} -eq 1 ]; then
|
||||||
# full build if building nightly or full build requested by label
|
# full build if building nightly or full build requested by label
|
||||||
@ -323,14 +319,6 @@ error() {
|
|||||||
exit 1
|
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
|
# 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
|
# parameters. should the hook script exit with negative exit code, hook() makes
|
||||||
# this script exit with error, too.
|
# this script exit with error, too.
|
||||||
|
@ -3,6 +3,8 @@ push:
|
|||||||
# these two enable potential bors support:
|
# these two enable potential bors support:
|
||||||
- '^staging$'
|
- '^staging$'
|
||||||
- '^trying$'
|
- '^trying$'
|
||||||
|
# github merge trains:
|
||||||
|
- '^gh-readonly-queue/'
|
||||||
|
|
||||||
pr:
|
pr:
|
||||||
enable_comments: true
|
enable_comments: true
|
||||||
|
@ -117,7 +117,6 @@ ifneq ($(RIOT_CI_BUILD),1)
|
|||||||
ifeq ($(MAKELEVEL),0)
|
ifeq ($(MAKELEVEL),0)
|
||||||
ifneq (,$(BOARDSDIR))
|
ifneq (,$(BOARDSDIR))
|
||||||
$(warning Using BOARDSDIR is deprecated use EXTERNAL_BOARD_DIRS instead)
|
$(warning Using BOARDSDIR is deprecated use EXTERNAL_BOARD_DIRS instead)
|
||||||
$(info EXTERNAL_BOARD_DIRS can contain multiple folders separated by space)
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -43,9 +43,21 @@ extern "C" {
|
|||||||
* @name UART configuration
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
#define UART_PIN_RX GPIO_PIN(0, 30)
|
{
|
||||||
#define UART_PIN_TX GPIO_PIN(0, 31)
|
.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
|
* @name UART configuration
|
||||||
*
|
|
||||||
* The CPU only supports one UART device, so we keep it simple
|
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
#define UART_PIN_RX 17
|
{ /* Mapped to USB virtual COM port */
|
||||||
#define UART_PIN_TX 18
|
.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
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
/* UART pin configuration */
|
{
|
||||||
#define UART_PIN_RX 25
|
.dev = NRF_UART0,
|
||||||
#define UART_PIN_TX 24
|
.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)
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,9 +8,10 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup boards_common_esp32x ESP32x Common
|
* @defgroup boards_common_esp32x ESP32x Common
|
||||||
|
* @ingroup boards_common
|
||||||
* @brief Definitions and configurations that are common for
|
* @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 detailed information about ESP32x SoCs, configuring and compiling RIOT
|
||||||
* for ESP32 boards, please refer \ref esp32_riot.
|
* for ESP32x boards, please refer \ref esp32_riot.
|
||||||
*/
|
*/
|
||||||
|
@ -41,10 +41,13 @@ extern "C" {
|
|||||||
* @name Arduino's SPI buses
|
* @name Arduino's SPI buses
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
/**
|
|
||||||
* @brief SPI_DEV(1) is connected to D11/D12/D13
|
|
||||||
*/
|
|
||||||
#if !defined(ARDUINO_SPI_D11D12D13) && defined(SPI_NUMOF)
|
#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)
|
#define ARDUINO_SPI_D11D12D13 SPI_DEV(0)
|
||||||
#endif
|
#endif
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@ -36,7 +36,11 @@ static const timer_conf_t timer_config[] = {
|
|||||||
{
|
{
|
||||||
.dev = TIM2,
|
.dev = TIM2,
|
||||||
.max = 0xffffffff,
|
.max = 0xffffffff,
|
||||||
|
#if defined(RCC_APB1ENR_TIM2EN)
|
||||||
|
.rcc_mask = RCC_APB1ENR_TIM2EN,
|
||||||
|
#else
|
||||||
.rcc_mask = RCC_APB1ENR1_TIM2EN,
|
.rcc_mask = RCC_APB1ENR1_TIM2EN,
|
||||||
|
#endif
|
||||||
.bus = APB1,
|
.bus = APB1,
|
||||||
.irqn = TIM2_IRQn
|
.irqn = TIM2_IRQn
|
||||||
},
|
},
|
||||||
|
@ -20,10 +20,10 @@
|
|||||||
#ifndef PERIPH_CONF_H
|
#ifndef PERIPH_CONF_H
|
||||||
#define PERIPH_CONF_H
|
#define PERIPH_CONF_H
|
||||||
|
|
||||||
#include "periph_cpu.h"
|
|
||||||
#include "cfg_clock_32_1.h"
|
#include "cfg_clock_32_1.h"
|
||||||
#include "cfg_rtt_default.h"
|
#include "cfg_rtt_default.h"
|
||||||
#include "cfg_timer_default.h"
|
#include "cfg_timer_default.h"
|
||||||
|
#include "periph_cpu.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -33,9 +33,21 @@ extern "C" {
|
|||||||
* @name UART configuration
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
#define UART_PIN_RX GPIO_PIN(0, 11)
|
{ /* Mapped to USB virtual COM port */
|
||||||
#define UART_PIN_TX GPIO_PIN(0, 5)
|
.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_FT5X06
|
||||||
select HAVE_LCD_PARALLEL if MODULE_ST7796
|
select HAVE_LCD_PARALLEL if MODULE_ST7796
|
||||||
|
select HAVE_LCD_PARALLEL_LL_MCU if MODULE_ST7796
|
||||||
select HAVE_MTD_SDCARD_DEFAULT
|
select HAVE_MTD_SDCARD_DEFAULT
|
||||||
select HAVE_ST7796
|
select HAVE_ST7796
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ endif
|
|||||||
|
|
||||||
ifneq (,$(filter st7796,$(USEMODULE)))
|
ifneq (,$(filter st7796,$(USEMODULE)))
|
||||||
USEMODULE += lcd_parallel
|
USEMODULE += lcd_parallel
|
||||||
|
USEMODULE += lcd_parallel_ll_mcu
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter touch_dev,$(USEMODULE)))
|
ifneq (,$(filter touch_dev,$(USEMODULE)))
|
||||||
|
@ -29,13 +29,24 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name UART configuration
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
/* UART pin configuration */
|
{ /* Mapped to USB virtual COM port */
|
||||||
#define UART_PIN_RX 25
|
.dev = NRF_UART0,
|
||||||
#define UART_PIN_TX 24
|
.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
|
default y
|
||||||
select BOARD_COMMON_NRF51
|
select BOARD_COMMON_NRF51
|
||||||
select CPU_MODEL_NRF51X22XXAC
|
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_I2C
|
||||||
select HAS_PERIPH_SPI
|
select HAS_PERIPH_SPI
|
||||||
select HAS_PERIPH_UART
|
select HAS_PERIPH_UART
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
CPU_MODEL = nrf51x22xxac
|
CPU_MODEL = nrf51x22xxac
|
||||||
|
|
||||||
# Put defined MCU peripherals here (in alphabetical order)
|
# Put defined MCU peripherals here (in alphabetical order)
|
||||||
|
FEATURES_PROVIDED += periph_adc
|
||||||
FEATURES_PROVIDED += periph_i2c
|
FEATURES_PROVIDED += periph_i2c
|
||||||
FEATURES_PROVIDED += periph_spi
|
FEATURES_PROVIDED += periph_spi
|
||||||
FEATURES_PROVIDED += periph_uart
|
FEATURES_PROVIDED += periph_uart
|
||||||
FEATURES_PROVIDED += periph_uart_hw_fc
|
FEATURES_PROVIDED += periph_uart_hw_fc
|
||||||
FEATURES_PROVIDED += vdd_lc_filter_reg1
|
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 common nrf51 based boards features
|
||||||
include $(RIOTBOARD)/common/nrf51/Makefile.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
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name UART configuration
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
/* UART pin configuration */
|
{ /* Mapped to USB virtual COM port */
|
||||||
#define UART_PIN_RX 11
|
.dev = NRF_UART0,
|
||||||
#define UART_PIN_TX 9
|
.rx_pin = GPIO_PIN(0, 11),
|
||||||
#define UART_PIN_RTS 8
|
.tx_pin = GPIO_PIN(0, 9),
|
||||||
#define UART_PIN_CTS 10
|
#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)
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,15 +29,24 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name UART configuration
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
/* UART pin configuration */
|
{
|
||||||
#define UART_PIN_RX 11
|
.dev = NRF_UART0,
|
||||||
#define UART_PIN_TX 9
|
.rx_pin = GPIO_PIN(0, 11),
|
||||||
#define UART_PIN_RTS 8
|
.tx_pin = GPIO_PIN(0, 9),
|
||||||
#define UART_PIN_CTS 10
|
#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
|
#ifdef __cplusplus
|
||||||
|
@ -35,9 +35,21 @@ extern "C" {
|
|||||||
* @name UART configuration
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
#define UART_PIN_RX GPIO_PIN(0, 19)
|
{
|
||||||
#define UART_PIN_TX GPIO_PIN(0, 20)
|
.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
|
#ifdef __cplusplus
|
||||||
|
@ -48,9 +48,21 @@ static const spi_conf_t spi_config[] = {
|
|||||||
* @name UART configuration
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
#define UART_PIN_RX GPIO_PIN(0, 8)
|
{ /* Mapped to USB virtual COM port */
|
||||||
#define UART_PIN_TX GPIO_PIN(0, 6)
|
.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
|
#ifdef __cplusplus
|
||||||
|
@ -35,14 +35,21 @@ extern "C" {
|
|||||||
* @name UART configuration
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
#define UART_IRQ_PRIO 1
|
{
|
||||||
|
.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_NUMOF ARRAY_SIZE(uart_config)
|
||||||
#define UART_PIN_RX 16
|
#define UART_0_ISR isr_uart0
|
||||||
#define UART_PIN_TX 17
|
|
||||||
#define UART_PIN_RTS 19
|
|
||||||
#define UART_PIN_CTS 18
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,8 +16,10 @@ config BOARD_NUCLEO_F030R8
|
|||||||
|
|
||||||
# Put defined MCU peripherals here (in alphabetical order)
|
# Put defined MCU peripherals here (in alphabetical order)
|
||||||
select HAS_PERIPH_ADC
|
select HAS_PERIPH_ADC
|
||||||
|
select HAS_PERIPH_I2C
|
||||||
select HAS_PERIPH_PWM
|
select HAS_PERIPH_PWM
|
||||||
select HAS_PERIPH_RTC
|
select HAS_PERIPH_RTC
|
||||||
|
select HAS_PERIPH_SPI
|
||||||
select HAS_PERIPH_TIMER
|
select HAS_PERIPH_TIMER
|
||||||
select HAS_PERIPH_UART
|
select HAS_PERIPH_UART
|
||||||
|
|
||||||
|
@ -3,11 +3,13 @@ CPU_MODEL = stm32f030r8
|
|||||||
|
|
||||||
# Put defined MCU peripherals here (in alphabetical order)
|
# Put defined MCU peripherals here (in alphabetical order)
|
||||||
FEATURES_PROVIDED += periph_adc
|
FEATURES_PROVIDED += periph_adc
|
||||||
|
FEATURES_PROVIDED += periph_i2c
|
||||||
FEATURES_PROVIDED += periph_pwm
|
FEATURES_PROVIDED += periph_pwm
|
||||||
# For RTC, Nucleos with MB1136 C-02 or MB1136 C-03 -sticker on it have the
|
# For RTC, Nucleos with MB1136 C-02 or MB1136 C-03 -sticker on it have the
|
||||||
# required LSE oscillator provided on the X2 slot.
|
# required LSE oscillator provided on the X2 slot.
|
||||||
# See Nucleo User Manual UM1724 section 5.6.2.
|
# See Nucleo User Manual UM1724 section 5.6.2.
|
||||||
FEATURES_PROVIDED += periph_rtc
|
FEATURES_PROVIDED += periph_rtc
|
||||||
|
FEATURES_PROVIDED += periph_spi
|
||||||
FEATURES_PROVIDED += periph_timer
|
FEATURES_PROVIDED += periph_timer
|
||||||
FEATURES_PROVIDED += periph_uart
|
FEATURES_PROVIDED += periph_uart
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include "periph_cpu.h"
|
#include "periph_cpu.h"
|
||||||
#include "clk_conf.h"
|
#include "clk_conf.h"
|
||||||
|
#include "cfg_i2c1_pb8_pb9.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -16,9 +16,11 @@ config BOARD_NUCLEO_F070RB
|
|||||||
|
|
||||||
# Put defined MCU peripherals here (in alphabetical order)
|
# Put defined MCU peripherals here (in alphabetical order)
|
||||||
select HAS_PERIPH_ADC
|
select HAS_PERIPH_ADC
|
||||||
|
select HAS_PERIPH_DMA
|
||||||
select HAS_PERIPH_I2C
|
select HAS_PERIPH_I2C
|
||||||
select HAS_PERIPH_PWM
|
select HAS_PERIPH_PWM
|
||||||
select HAS_PERIPH_RTC
|
select HAS_PERIPH_RTC
|
||||||
|
select HAS_PERIPH_SPI
|
||||||
select HAS_PERIPH_TIMER
|
select HAS_PERIPH_TIMER
|
||||||
select HAS_PERIPH_UART
|
select HAS_PERIPH_UART
|
||||||
|
|
||||||
|
@ -3,12 +3,14 @@ CPU_MODEL = stm32f070rb
|
|||||||
|
|
||||||
# Put defined MCU peripherals here (in alphabetical order)
|
# Put defined MCU peripherals here (in alphabetical order)
|
||||||
FEATURES_PROVIDED += periph_adc
|
FEATURES_PROVIDED += periph_adc
|
||||||
|
FEATURES_PROVIDED += periph_dma
|
||||||
FEATURES_PROVIDED += periph_i2c
|
FEATURES_PROVIDED += periph_i2c
|
||||||
FEATURES_PROVIDED += periph_pwm
|
FEATURES_PROVIDED += periph_pwm
|
||||||
# For RTC, Nucleos with MB1136 C-02 or MB1136 C-03 -sticker on it have the
|
# For RTC, Nucleos with MB1136 C-02 or MB1136 C-03 -sticker on it have the
|
||||||
# required LSE oscillator provided on the X2 slot.
|
# required LSE oscillator provided on the X2 slot.
|
||||||
# See Nucleo User Manual UM1724 section 5.6.2.
|
# See Nucleo User Manual UM1724 section 5.6.2.
|
||||||
FEATURES_PROVIDED += periph_rtc
|
FEATURES_PROVIDED += periph_rtc
|
||||||
|
FEATURES_PROVIDED += periph_spi
|
||||||
FEATURES_PROVIDED += periph_timer
|
FEATURES_PROVIDED += periph_timer
|
||||||
FEATURES_PROVIDED += periph_uart
|
FEATURES_PROVIDED += periph_uart
|
||||||
|
|
||||||
|
@ -102,6 +102,21 @@ static const uart_conf_t uart_config[] = {
|
|||||||
#define UART_NUMOF ARRAY_SIZE(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
|
* @name PWM configuration
|
||||||
* @{
|
* @{
|
||||||
@ -148,6 +163,42 @@ static const adc_conf_t adc_config[] = {
|
|||||||
#define ADC_NUMOF ARRAY_SIZE(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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,9 +1,2 @@
|
|||||||
# load the common Makefile.include for Nucleo boards
|
# load the common Makefile.include for Nucleo boards
|
||||||
include $(RIOTBOARD)/common/nucleo64/Makefile.include
|
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 "periph_cpu.h"
|
||||||
#include "clk_conf.h"
|
#include "clk_conf.h"
|
||||||
#include "cfg_timer_tim2.h"
|
#include "cfg_timer_tim2_tim15_tim16.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -8,6 +8,33 @@
|
|||||||
The Nucleo-L433RC is a board from ST's Nucleo family supporting a ARM
|
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.
|
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
|
### Flashing the Board Using ST-LINK Removable Media
|
||||||
|
|
||||||
On-board ST-LINK programmer provides via composite USB device removable media.
|
On-board ST-LINK programmer provides via composite USB device removable media.
|
||||||
|
@ -30,6 +30,16 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
* @brief Mapping of MCU pins to Arduino pins
|
||||||
* @{
|
* @{
|
||||||
|
@ -117,7 +117,12 @@ static const spi_conf_t spi_config[] = {
|
|||||||
#endif
|
#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)
|
# Put other features for this board (in alphabetical order)
|
||||||
select HAS_ARDUINO_ANALOG
|
select HAS_ARDUINO_ANALOG
|
||||||
|
select HAS_ARDUINO_I2C
|
||||||
select HAS_ARDUINO_PINS
|
select HAS_ARDUINO_PINS
|
||||||
select HAS_ARDUINO_SHIELD_UNO
|
select HAS_ARDUINO_SHIELD_UNO
|
||||||
|
select HAS_ARDUINO_SPI
|
||||||
|
select HAS_ARDUINO_UART
|
||||||
select HAS_RIOTBOOT
|
select HAS_RIOTBOOT
|
||||||
select HAS_TINYUSB_DEVICE
|
select HAS_TINYUSB_DEVICE
|
||||||
|
|
||||||
|
@ -14,7 +14,10 @@ FEATURES_PROVIDED += periph_usbdev
|
|||||||
|
|
||||||
# Put other features for this board (in alphabetical order)
|
# Put other features for this board (in alphabetical order)
|
||||||
FEATURES_PROVIDED += arduino_analog
|
FEATURES_PROVIDED += arduino_analog
|
||||||
|
FEATURES_PROVIDED += arduino_i2c
|
||||||
FEATURES_PROVIDED += arduino_pins
|
FEATURES_PROVIDED += arduino_pins
|
||||||
FEATURES_PROVIDED += arduino_shield_uno
|
FEATURES_PROVIDED += arduino_shield_uno
|
||||||
|
FEATURES_PROVIDED += arduino_spi
|
||||||
|
FEATURES_PROVIDED += arduino_uart
|
||||||
FEATURES_PROVIDED += riotboot
|
FEATURES_PROVIDED += riotboot
|
||||||
FEATURES_PROVIDED += tinyusb_device
|
FEATURES_PROVIDED += tinyusb_device
|
||||||
|
@ -8,29 +8,37 @@ Hardware
|
|||||||
|
|
||||||
![st-nucleo-wb55](https://miro.medium.com/max/700/1*9OG-4Ix4EzHX9uBpMve2IA.jpeg)
|
![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
|
||||||
---
|
---
|
||||||
|
|
||||||
| MCU | STM32WB55RG |
|
| MCU | STM32WB55RG |
|
||||||
|:---------- |:------------------------------- |
|
|:----------------- |:------------------------------------- |
|
||||||
| Family | ARM Cortex-M4 |
|
| Family | ARM Cortex-M4 |
|
||||||
| Vendor | ST Microelectronics |
|
| Vendor | ST Microelectronics |
|
||||||
| RAM | 256KB |
|
| RAM | 256 KiB |
|
||||||
| Flash | 512KB |
|
| Flash | 512 KiB |
|
||||||
| Frequency | 64MHz |
|
| Frequency | 64 MHz |
|
||||||
| FPU | yes |
|
| FPU | yes |
|
||||||
| Timers | 8 (3x 16-bit, 1x 32-bit [TIM5]) |
|
| Timers | 8 (3x 16-bit, 1x 32-bit [TIM5]) |
|
||||||
| LPTimers | 2x 16-bit |
|
| LPTimers | 2x 16-bit |
|
||||||
| ADCs | 1x 19-channel 12-bit |
|
| ADCs | 1x 19-channel 12-bit |
|
||||||
| UARTs | 1 |
|
| UARTs | 1 |
|
||||||
| LUARTs | 1 |
|
| LUARTs | 1 |
|
||||||
| SPIs | 1 |
|
| SPIs | 1 |
|
||||||
| I2Cs | 2 |
|
| I2Cs | 2 |
|
||||||
| RTC | 1 |
|
| RTC | 1 |
|
||||||
| Vcc | 1.65V - 3.6V |
|
| Vcc | 1.65V - 3.6V |
|
||||||
| Datasheet | [Datasheet](https://www.st.com/resource/en/datasheet/stm32wb55cc.pdf)|
|
| Datasheet | [Datasheet][Datasheet] |
|
||||||
| Reference Manual | [Reference Manual](https://www.st.com/resource/en/datasheet/stm32wb55cc.pdf) |
|
| Reference Manual | [Reference Manual][Reference Manual] |
|
||||||
| 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) |
|
| 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
|
Overview
|
||||||
========
|
========
|
||||||
@ -82,25 +90,25 @@ User Interface
|
|||||||
Implementation Status
|
Implementation Status
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
| Device | ID | Supported | Comments |
|
| Device | ID | Supported | Comments |
|
||||||
|:---------------- |:----------------- |:------- |:------- |
|
|:----------------- |:----------------- |:--------- |:--------- |
|
||||||
| MCU | stm32wb | yes | |
|
| MCU | stm32wb | yes | |
|
||||||
| | M0+ co-processor | no | |
|
| | M0+ co-processor | no | |
|
||||||
| | BLE | no | |
|
| | BLE | no | |
|
||||||
| | 802.15.4 | no | |
|
| | 802.15.4 | no | |
|
||||||
| Low-level driver | GPIO | yes | |
|
| Low-level driver | GPIO | yes | |
|
||||||
| | UART | yes | UART1 |
|
| | UART | yes | UART1 |
|
||||||
| | LPUART | yes | LPUART1 |
|
| | LPUART | yes | LPUART1 |
|
||||||
| | I2C | yes | I2C1 |
|
| | I2C | yes | I2C1 |
|
||||||
| | SPI | yes | |
|
| | SPI | yes | |
|
||||||
| | ADC | yes | |
|
| | ADC | yes | |
|
||||||
| | RTT | yes | |
|
| | RTT | yes | |
|
||||||
| | RTC | yes | |
|
| | RTC | yes | |
|
||||||
| | RNG | yes | |
|
| | RNG | yes | |
|
||||||
| | Timer | yes | TIM2 |
|
| | Timer | yes | TIM2 |
|
||||||
| | WDT | yes | |
|
| | WDT | yes | |
|
||||||
| | USB | yes | |
|
| | USB | yes | |
|
||||||
| | PWM | no | |
|
| | PWM | no | |
|
||||||
| | AES | no | |
|
| | AES | no | |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -88,6 +88,33 @@ extern "C" {
|
|||||||
#define ARDUINO_ANALOG_PIN_LAST 5
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -50,9 +50,21 @@ static const spi_conf_t spi_config[] = {
|
|||||||
* @name UART configuration
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
#define UART_PIN_RX GPIO_PIN(0, 4)
|
{
|
||||||
#define UART_PIN_TX GPIO_PIN(0, 5)
|
.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
|
#ifdef __cplusplus
|
||||||
|
@ -18,6 +18,7 @@ config BOARD_SAME54_XPRO
|
|||||||
select HAS_PERIPH_RTC
|
select HAS_PERIPH_RTC
|
||||||
select HAS_PERIPH_RTT
|
select HAS_PERIPH_RTT
|
||||||
select HAS_PERIPH_PWM
|
select HAS_PERIPH_PWM
|
||||||
|
select HAS_PERIPH_FREQM
|
||||||
select HAS_PERIPH_SDMMC
|
select HAS_PERIPH_SDMMC
|
||||||
select HAS_PERIPH_SPI
|
select HAS_PERIPH_SPI
|
||||||
select HAS_PERIPH_TIMER
|
select HAS_PERIPH_TIMER
|
||||||
|
@ -14,6 +14,7 @@ FEATURES_PROVIDED += periph_timer
|
|||||||
FEATURES_PROVIDED += periph_uart
|
FEATURES_PROVIDED += periph_uart
|
||||||
FEATURES_PROVIDED += periph_adc
|
FEATURES_PROVIDED += periph_adc
|
||||||
FEATURES_PROVIDED += periph_usbdev
|
FEATURES_PROVIDED += periph_usbdev
|
||||||
|
FEATURES_PROVIDED += periph_freqm
|
||||||
|
|
||||||
# Put other features for this board (in alphabetical order)
|
# Put other features for this board (in alphabetical order)
|
||||||
FEATURES_PROVIDED += riotboot
|
FEATURES_PROVIDED += riotboot
|
||||||
|
@ -3,4 +3,11 @@
|
|||||||
# debugger.
|
# debugger.
|
||||||
TTY_BOARD_FILTER := --model 'EDBG CMSIS-DAP'
|
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
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,9 +33,21 @@ extern "C" {
|
|||||||
* @name UART configuration
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
#define UART_PIN_RX GPIO_PIN(0, 2)
|
{
|
||||||
#define UART_PIN_TX GPIO_PIN(0, 3)
|
.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
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name UART configuration
|
* @name UART configuration
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define UART_NUMOF (1U)
|
static const uart_conf_t uart_config[] = {
|
||||||
/* UART pin configuration */
|
{ /* Mapped to USB virtual COM port */
|
||||||
#define UART_PIN_RX 1
|
.dev = NRF_UART0,
|
||||||
#define UART_PIN_TX 2
|
.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
|
LINKFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm
|
||||||
endif
|
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
|
include $(RIOTMAKE)/arch/avr8.inc.mk
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#define FLASH_UTILS_ARCH_H
|
#define FLASH_UTILS_ARCH_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <stdarg.h>
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -35,20 +35,68 @@ extern "C" {
|
|||||||
#define FLASH_ATTR __flash
|
#define FLASH_ATTR __flash
|
||||||
#define PRIsflash "S"
|
#define PRIsflash "S"
|
||||||
#define TO_FLASH(x) __extension__({static FLASH_ATTR const char __c[] = (x); &__c[0];})
|
#define TO_FLASH(x) __extension__({static FLASH_ATTR const char __c[] = (x); &__c[0];})
|
||||||
#define flash_strcmp strcmp_P
|
|
||||||
#define flash_strncmp strncmp_P
|
static inline int flash_strcmp(const char *ram, FLASH_ATTR const char *flash)
|
||||||
#define flash_strlen strlen_P
|
{
|
||||||
#define flash_strcpy strcpy_P
|
return strcmp_P(ram, (const char *)flash);
|
||||||
#define flash_strncpy strncpy_P
|
}
|
||||||
#define flash_printf printf_P
|
|
||||||
/* avrlibc seemingly forgot to provide vprintf_P(), but vfprintf_P() is there */
|
static inline int flash_strncmp(const char *ram, FLASH_ATTR const char *flash, size_t n)
|
||||||
#define flash_vprintf(fmt, arglist) vfprintf_P(stdout, fmt, arglist)
|
{
|
||||||
#define flash_fprintf fprintf_P
|
return strncmp_P(ram, (const char *)flash, n);
|
||||||
#define flash_vfprintf vfprintf_P
|
}
|
||||||
#define flash_snprintf snprintf_P
|
|
||||||
#define flash_vsnprintf vsnprintf_P
|
static inline size_t flash_strlen(FLASH_ATTR const char *flash)
|
||||||
#define flash_puts puts_P
|
{
|
||||||
#define flash_memcpy memcpy_P
|
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 */
|
#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-ble-nimble/Kconfig"
|
||||||
rsource "esp-idf/Kconfig"
|
rsource "esp-idf/Kconfig"
|
||||||
rsource "esp-idf-api/Kconfig"
|
rsource "esp-idf-api/Kconfig"
|
||||||
|
rsource "esp-lcd/Kconfig"
|
||||||
rsource "periph/Kconfig"
|
rsource "periph/Kconfig"
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
@ -29,6 +29,10 @@ ifneq (, $(filter esp_freertos, $(USEMODULE)))
|
|||||||
DIRS += freertos
|
DIRS += freertos
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (, $(filter esp_lcd, $(USEMODULE)))
|
||||||
|
DIRS += esp-lcd
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (, $(filter stdio_usb_serial_jtag, $(USEMODULE)))
|
ifneq (, $(filter stdio_usb_serial_jtag, $(USEMODULE)))
|
||||||
DIRS += stdio_usb_serial_jtag
|
DIRS += stdio_usb_serial_jtag
|
||||||
endif
|
endif
|
||||||
|
@ -128,6 +128,12 @@ ifneq (,$(filter esp_idf_heap,$(USEMODULE)))
|
|||||||
USEPKG += tlsf
|
USEPKG += tlsf
|
||||||
endif
|
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)))
|
ifneq (,$(filter mtd periph_flashpage,$(USEMODULE)))
|
||||||
USEMODULE += esp_idf_spi_flash
|
USEMODULE += esp_idf_spi_flash
|
||||||
endif
|
endif
|
||||||
|
@ -113,6 +113,7 @@ PSEUDOMODULES += esp_hw_counter
|
|||||||
PSEUDOMODULES += esp_idf_gpio_hal
|
PSEUDOMODULES += esp_idf_gpio_hal
|
||||||
PSEUDOMODULES += esp_i2c_hw
|
PSEUDOMODULES += esp_i2c_hw
|
||||||
PSEUDOMODULES += esp_jtag
|
PSEUDOMODULES += esp_jtag
|
||||||
|
PSEUDOMODULES += esp_lcd_gpio
|
||||||
PSEUDOMODULES += esp_rtc_timer_32k
|
PSEUDOMODULES += esp_rtc_timer_32k
|
||||||
PSEUDOMODULES += esp_spi_ram
|
PSEUDOMODULES += esp_spi_ram
|
||||||
PSEUDOMODULES += esp_spi_oct
|
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)
|
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_hw_support/include/soc/$(CPU_FAM)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter esp_idf_lcd,$(USEMODULE)))
|
||||||
|
INCLUDES += -I$(ESP32_SDK_DIR)/components/esp_lcd/include
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter esp_idf_spi_flash,$(USEMODULE)))
|
ifneq (,$(filter esp_idf_spi_flash,$(USEMODULE)))
|
||||||
INCLUDES += -I$(ESP32_SDK_DIR)/components/spi_flash/include
|
INCLUDES += -I$(ESP32_SDK_DIR)/components/spi_flash/include
|
||||||
endif
|
endif
|
||||||
|
@ -26,6 +26,7 @@ rsource "eth/Kconfig"
|
|||||||
rsource "event/Kconfig"
|
rsource "event/Kconfig"
|
||||||
rsource "gpio/Kconfig"
|
rsource "gpio/Kconfig"
|
||||||
rsource "heap/Kconfig"
|
rsource "heap/Kconfig"
|
||||||
|
rsource "lcd/Kconfig"
|
||||||
rsource "nvs_flash/Kconfig"
|
rsource "nvs_flash/Kconfig"
|
||||||
rsource "rmt/Kconfig"
|
rsource "rmt/Kconfig"
|
||||||
rsource "spi_flash/Kconfig"
|
rsource "spi_flash/Kconfig"
|
||||||
|
@ -36,6 +36,10 @@ ifneq (,$(filter esp_idf_heap,$(USEMODULE)))
|
|||||||
DIRS += heap
|
DIRS += heap
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter esp_idf_lcd,$(USEMODULE)))
|
||||||
|
DIRS += lcd
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter esp_idf_nvs_flash,$(USEMODULE)))
|
ifneq (,$(filter esp_idf_nvs_flash,$(USEMODULE)))
|
||||||
DIRS += nvs_flash
|
DIRS += nvs_flash
|
||||||
endif
|
endif
|
||||||
|
@ -10,6 +10,7 @@ config MODULE_ESP_IDF_HEAP
|
|||||||
bool
|
bool
|
||||||
depends on TEST_KCONFIG
|
depends on TEST_KCONFIG
|
||||||
depends on MODULE_ESP_IDF
|
depends on MODULE_ESP_IDF
|
||||||
|
default y if MODULE_LCD_PARALLEL_LL_MCU
|
||||||
select PACKAGE_TLSF
|
select PACKAGE_TLSF
|
||||||
help
|
help
|
||||||
ESP-IDF heap library. This library is required if external SPI RAM
|
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_WDT 13 /**< Level interrupt with low priority 1 */
|
||||||
#define CPU_INUM_SOFTWARE 17 /**< 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_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_TIMER 19 /**< Level interrupt with medium priority 2 */
|
||||||
#define CPU_INUM_FRC2 20 /**< 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 */
|
#define CPU_INUM_SYSTIMER 20 /**< Level interrupt with medium priority 2 */
|
||||||
|
@ -233,6 +233,17 @@
|
|||||||
|
|
||||||
#endif /* !CONFIG_ESP_FLASHPAGE_CAPACITY */
|
#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 */
|
#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 },
|
{ ETS_USB_SERIAL_JTAG_INTR_SOURCE, CPU_INUM_SERIAL_JTAG, 1 },
|
||||||
#endif
|
#endif
|
||||||
{ ETS_RMT_INTR_SOURCE, CPU_INUM_RMT, 1 },
|
{ 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)
|
#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)
|
void esp_irq_init(void)
|
||||||
{
|
{
|
||||||
#ifdef SOC_CPU_HAS_FLEXIBLE_INTC
|
#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;
|
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)
|
esp_err_t esp_intr_free(intr_handle_t handle)
|
||||||
{
|
{
|
||||||
return esp_intr_disable(handle);
|
return esp_intr_disable(handle);
|
||||||
|
@ -26,18 +26,19 @@
|
|||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <time.h>
|
#include <err.h>
|
||||||
#include <sys/time.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <err.h>
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "cpu_conf.h"
|
#include "cpu_conf.h"
|
||||||
#include "native_internal.h"
|
#include "native_internal.h"
|
||||||
#include "periph/timer.h"
|
#include "periph/timer.h"
|
||||||
|
#include "time_units.h"
|
||||||
|
|
||||||
#define ENABLE_DEBUG 0
|
#define ENABLE_DEBUG 0
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -49,7 +50,9 @@ static unsigned long time_null;
|
|||||||
static timer_cb_t _callback;
|
static timer_cb_t _callback;
|
||||||
static void *_cb_arg;
|
static void *_cb_arg;
|
||||||
|
|
||||||
static struct itimerval itv;
|
static struct itimerspec its;
|
||||||
|
|
||||||
|
static timer_t itimer_monotonic;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns ticks for give timespec
|
* 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;
|
_callback = cb;
|
||||||
_cb_arg = arg;
|
_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) {
|
if (register_interrupt(SIGALRM, native_isr_timer) != 0) {
|
||||||
DEBUG("darn!\n\n");
|
DEBUG_PUTS("Failed to register SIGALRM handler");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -104,14 +114,14 @@ static void do_timer_set(unsigned int offset, bool periodic)
|
|||||||
offset = NATIVE_TIMER_MIN_RES;
|
offset = NATIVE_TIMER_MIN_RES;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&itv, 0, sizeof(itv));
|
memset(&its, 0, sizeof(its));
|
||||||
itv.it_value.tv_sec = (offset / 1000000);
|
its.it_value.tv_sec = offset / NATIVE_TIMER_SPEED;
|
||||||
itv.it_value.tv_usec = offset % 1000000;
|
its.it_value.tv_nsec = (offset % NATIVE_TIMER_SPEED) * (NS_PER_SEC / NATIVE_TIMER_SPEED);
|
||||||
if (periodic) {
|
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)
|
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__);
|
DEBUG("%s\n", __func__);
|
||||||
|
|
||||||
_native_syscall_enter();
|
_native_syscall_enter();
|
||||||
if (real_setitimer(ITIMER_REAL, &itv, NULL) == -1) {
|
if (timer_settime(itimer_monotonic, 0, &its, NULL) == -1) {
|
||||||
err(EXIT_FAILURE, "timer_arm: setitimer");
|
err(EXIT_FAILURE, "timer_start: timer_settime");
|
||||||
}
|
}
|
||||||
_native_syscall_leave();
|
_native_syscall_leave();
|
||||||
}
|
}
|
||||||
@ -183,13 +193,13 @@ void timer_stop(tim_t dev)
|
|||||||
DEBUG("%s\n", __func__);
|
DEBUG("%s\n", __func__);
|
||||||
|
|
||||||
_native_syscall_enter();
|
_native_syscall_enter();
|
||||||
struct itimerval zero = {0};
|
struct itimerspec zero = {0};
|
||||||
if (real_setitimer(ITIMER_REAL, &zero, &itv) == -1) {
|
if (timer_settime(itimer_monotonic, 0, &zero, &its) == -1) {
|
||||||
err(EXIT_FAILURE, "timer_arm: setitimer");
|
err(EXIT_FAILURE, "timer_stop: timer_settime");
|
||||||
}
|
}
|
||||||
_native_syscall_leave();
|
_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)
|
unsigned int timer_read(tim_t dev)
|
||||||
|
@ -88,8 +88,6 @@ int (*real_pause)(void);
|
|||||||
int (*real_pipe)(int[2]);
|
int (*real_pipe)(int[2]);
|
||||||
int (*real_select)(int nfds, ...);
|
int (*real_select)(int nfds, ...);
|
||||||
int (*real_poll)(struct pollfd *fds, ...);
|
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_setsid)(void);
|
||||||
int (*real_setsockopt)(int socket, ...);
|
int (*real_setsockopt)(int socket, ...);
|
||||||
int (*real_socket)(int domain, int type, int protocol);
|
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_dup2) = dlsym(RTLD_NEXT, "dup2");
|
||||||
*(void **)(&real_select) = dlsym(RTLD_NEXT, "select");
|
*(void **)(&real_select) = dlsym(RTLD_NEXT, "select");
|
||||||
*(void **)(&real_poll) = dlsym(RTLD_NEXT, "poll");
|
*(void **)(&real_poll) = dlsym(RTLD_NEXT, "poll");
|
||||||
*(void **)(&real_setitimer) = dlsym(RTLD_NEXT, "setitimer");
|
|
||||||
*(void **)(&real_setsid) = dlsym(RTLD_NEXT, "setsid");
|
*(void **)(&real_setsid) = dlsym(RTLD_NEXT, "setsid");
|
||||||
*(void **)(&real_setsockopt) = dlsym(RTLD_NEXT, "setsockopt");
|
*(void **)(&real_setsockopt) = dlsym(RTLD_NEXT, "setsockopt");
|
||||||
*(void **)(&real_socket) = dlsym(RTLD_NEXT, "socket");
|
*(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
|
* @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_SCKSEL (dev(bus)->PSELSCK)
|
||||||
#define SPI_MOSISEL (dev(bus)->PSELMOSI)
|
#define SPI_MOSISEL (dev(bus)->PSELMOSI)
|
||||||
#define SPI_MISOSEL (dev(bus)->PSELMISO)
|
#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)
|
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) {}
|
while (i2c(dev)->EVENTS_STOPPED == 0) {}
|
||||||
NRF_PPI->CHENCLR = (1 << i2c_config[dev].ppi);
|
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,
|
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_CPU_NRF52
|
||||||
select HAS_PERIPH_I2C_RECONFIGURE
|
select HAS_PERIPH_I2C_RECONFIGURE
|
||||||
select HAS_PERIPH_SPI_GPIO_MODE
|
select HAS_PERIPH_SPI_GPIO_MODE
|
||||||
|
select HAS_PERIPH_UART_NONBLOCKING
|
||||||
|
|
||||||
## CPU Models
|
## CPU Models
|
||||||
config CPU_MODEL_NRF52805XXAA
|
config CPU_MODEL_NRF52805XXAA
|
||||||
bool
|
bool
|
||||||
select CPU_CORE_CORTEX_M4
|
select CPU_CORE_CORTEX_M4
|
||||||
select CPU_FAM_NRF52
|
select CPU_FAM_NRF52
|
||||||
select HAS_PERIPH_UART_NONBLOCKING
|
|
||||||
|
|
||||||
config CPU_MODEL_NRF52810XXAA
|
config CPU_MODEL_NRF52810XXAA
|
||||||
bool
|
bool
|
||||||
select CPU_CORE_CORTEX_M4
|
select CPU_CORE_CORTEX_M4
|
||||||
select CPU_FAM_NRF52
|
select CPU_FAM_NRF52
|
||||||
select HAS_PERIPH_UART_NONBLOCKING
|
|
||||||
|
|
||||||
config CPU_MODEL_NRF52811XXAA
|
config CPU_MODEL_NRF52811XXAA
|
||||||
bool
|
bool
|
||||||
@ -39,7 +38,6 @@ config CPU_MODEL_NRF52811XXAA
|
|||||||
select CPU_FAM_NRF52
|
select CPU_FAM_NRF52
|
||||||
select HAS_BLE_PHY_CODED
|
select HAS_BLE_PHY_CODED
|
||||||
select HAS_RADIO_NRF802154
|
select HAS_RADIO_NRF802154
|
||||||
select HAS_PERIPH_UART_NONBLOCKING
|
|
||||||
|
|
||||||
config CPU_MODEL_NRF52820XXAA
|
config CPU_MODEL_NRF52820XXAA
|
||||||
bool
|
bool
|
||||||
@ -47,7 +45,6 @@ config CPU_MODEL_NRF52820XXAA
|
|||||||
select CPU_FAM_NRF52
|
select CPU_FAM_NRF52
|
||||||
select HAS_BLE_PHY_CODED
|
select HAS_BLE_PHY_CODED
|
||||||
select HAS_RADIO_NRF802154
|
select HAS_RADIO_NRF802154
|
||||||
select HAS_PERIPH_UART_NONBLOCKING
|
|
||||||
|
|
||||||
config CPU_MODEL_NRF52832XXAA
|
config CPU_MODEL_NRF52832XXAA
|
||||||
bool
|
bool
|
||||||
@ -60,7 +57,6 @@ config CPU_MODEL_NRF52833XXAA
|
|||||||
select CPU_FAM_NRF52
|
select CPU_FAM_NRF52
|
||||||
select HAS_BLE_PHY_CODED
|
select HAS_BLE_PHY_CODED
|
||||||
select HAS_RADIO_NRF802154
|
select HAS_RADIO_NRF802154
|
||||||
select HAS_PERIPH_UART_NONBLOCKING
|
|
||||||
|
|
||||||
config CPU_MODEL_NRF52840XXAA
|
config CPU_MODEL_NRF52840XXAA
|
||||||
bool
|
bool
|
||||||
@ -68,7 +64,6 @@ config CPU_MODEL_NRF52840XXAA
|
|||||||
select CPU_FAM_NRF52
|
select CPU_FAM_NRF52
|
||||||
select HAS_BLE_PHY_CODED
|
select HAS_BLE_PHY_CODED
|
||||||
select HAS_RADIO_NRF802154
|
select HAS_RADIO_NRF802154
|
||||||
select HAS_PERIPH_UART_NONBLOCKING
|
|
||||||
select HAS_PERIPH_HASH_SHA_1
|
select HAS_PERIPH_HASH_SHA_1
|
||||||
select HAS_PERIPH_HASH_SHA_224
|
select HAS_PERIPH_HASH_SHA_224
|
||||||
select HAS_PERIPH_HASH_SHA_256
|
select HAS_PERIPH_HASH_SHA_256
|
||||||
|
@ -23,9 +23,9 @@ ifneq (,$(filter nrf52840xxaa,$(CPU_MODEL)))
|
|||||||
FEATURES_PROVIDED += periph_ecc_ed25519
|
FEATURES_PROVIDED += periph_ecc_ed25519
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (,$(filter nrf52832%,$(CPU_MODEL)))
|
# All nRF52 CPUs use UARTE (UART + EasyDMA) for UART, so that can be used
|
||||||
FEATURES_PROVIDED += periph_uart_nonblocking
|
# in non-blocking mode
|
||||||
endif
|
FEATURES_PROVIDED += periph_uart_nonblocking
|
||||||
# The ADC does not depend on any board configuration, so always available
|
# The ADC does not depend on any board configuration, so always available
|
||||||
FEATURES_PROVIDED += periph_adc
|
FEATURES_PROVIDED += periph_adc
|
||||||
|
|
||||||
|
@ -66,9 +66,9 @@ extern "C" {
|
|||||||
* The port definition is used (and zeroed) to suppress compiler warnings
|
* The port definition is used (and zeroed) to suppress compiler warnings
|
||||||
*/
|
*/
|
||||||
#if GPIO_COUNT > 1
|
#if GPIO_COUNT > 1
|
||||||
#define GPIO_PIN(x,y) ((x << 5) | y)
|
#define GPIO_PIN(x, y) ((x << 5) | y)
|
||||||
#else
|
#else
|
||||||
#define GPIO_PIN(x,y) ((x & 0) | y)
|
#define GPIO_PIN(x, y) ((x & 0) | y)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -316,13 +316,16 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
uint8_t gpio_int_get_exti(gpio_t pin);
|
uint8_t gpio_int_get_exti(gpio_t pin);
|
||||||
|
|
||||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
|
||||||
/**
|
/**
|
||||||
* @brief Structure for UART configuration data
|
* @brief Structure for UART configuration data
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
#ifdef UARTE_PRESENT
|
||||||
NRF_UARTE_Type *dev; /**< UART with EasyDMA device base
|
NRF_UARTE_Type *dev; /**< UART with EasyDMA device base
|
||||||
* register address */
|
* register address */
|
||||||
|
#else
|
||||||
|
NRF_UART_Type *dev; /**< UART device base register address */
|
||||||
|
#endif
|
||||||
gpio_t rx_pin; /**< RX pin */
|
gpio_t rx_pin; /**< RX pin */
|
||||||
gpio_t tx_pin; /**< TX pin */
|
gpio_t tx_pin; /**< TX pin */
|
||||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||||
@ -339,8 +342,6 @@ typedef struct {
|
|||||||
#define UART_TXBUF_SIZE (64)
|
#define UART_TXBUF_SIZE (64)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* ndef CPU_MODEL_NRF52832XXAA && ndef CPU_FAM_NRF51 */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief USBDEV buffers must be word aligned because of DMA restrictions
|
* @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_SCKSEL (dev(bus)->PSEL.SCK) /**< Macro for SPI clk */
|
||||||
#define SPI_MOSISEL (dev(bus)->PSEL.MOSI) /**< Macro for SPI mosi */
|
#define SPI_MOSISEL (dev(bus)->PSEL.MOSI) /**< Macro for SPI mosi */
|
||||||
#define SPI_MISOSEL (dev(bus)->PSEL.MISO) /**< Macro for SPI miso */
|
#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
|
* @brief SPI configuration values
|
||||||
|
@ -28,28 +28,32 @@
|
|||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "compiler_hints.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "periph/uart.h"
|
|
||||||
#include "periph/gpio.h"
|
#include "periph/gpio.h"
|
||||||
|
#include "periph/uart.h"
|
||||||
|
|
||||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
#ifdef UARTE_PRESENT
|
||||||
#define UART_INVALID (uart >= UART_NUMOF)
|
# define PSEL_RXD PSEL.RXD
|
||||||
#define REG_BAUDRATE dev(uart)->BAUDRATE
|
# define PSEL_TXD PSEL.TXD
|
||||||
#define REG_CONFIG dev(uart)->CONFIG
|
# define PSEL_RTS PSEL.RTS
|
||||||
#define PSEL_RXD dev(uart)->PSEL.RXD
|
# define PSEL_CTS PSEL.CTS
|
||||||
#define PSEL_TXD dev(uart)->PSEL.TXD
|
# define ENABLE_ON UARTE_ENABLE_ENABLE_Enabled
|
||||||
#define UART_IRQN uart_config[uart].irqn
|
# define ENABLE_OFF UARTE_ENABLE_ENABLE_Disabled
|
||||||
#define UART_PIN_RX uart_config[uart].rx_pin
|
# define UART_TYPE NRF_UARTE_Type
|
||||||
#define UART_PIN_TX uart_config[uart].tx_pin
|
#else
|
||||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
# define PSEL_RXD PSELRXD
|
||||||
#define UART_PIN_RTS uart_config[uart].rts_pin
|
# define PSEL_TXD PSELTXD
|
||||||
#define UART_PIN_CTS uart_config[uart].cts_pin
|
# 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
|
#endif
|
||||||
#define ISR_CTX isr_ctx[uart]
|
|
||||||
#define RAM_MASK (0x20000000)
|
#define RAM_MASK (0x20000000)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,7 +67,9 @@
|
|||||||
* @brief Allocate memory for the interrupt context
|
* @brief Allocate memory for the interrupt context
|
||||||
*/
|
*/
|
||||||
static uart_isr_ctx_t isr_ctx[UART_NUMOF];
|
static uart_isr_ctx_t isr_ctx[UART_NUMOF];
|
||||||
|
#ifdef UARTE_PRESENT
|
||||||
static uint8_t rx_buf[UART_NUMOF];
|
static uint8_t rx_buf[UART_NUMOF];
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODULE_PERIPH_UART_NONBLOCKING
|
#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);
|
void uart_isr_handler(void *arg);
|
||||||
|
|
||||||
static inline NRF_UARTE_Type *dev(uart_t uart)
|
/* use an enum to count the number of UART ISR macro names defined by the
|
||||||
{
|
* board */
|
||||||
return uart_config[uart].dev;
|
enum {
|
||||||
}
|
#ifdef UART_0_ISR
|
||||||
|
UART_0_ISR_NUM,
|
||||||
#else /* nrf51 and nrf52832 etc */
|
#endif
|
||||||
|
#ifdef UART_1_ISR
|
||||||
#define UART_INVALID (uart != 0)
|
UART_1_ISR_NUM,
|
||||||
#define REG_BAUDRATE NRF_UART0->BAUDRATE
|
#endif
|
||||||
#define REG_CONFIG NRF_UART0->CONFIG
|
UART_ISR_NUMOF,
|
||||||
#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 */
|
|
||||||
|
|
||||||
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
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;
|
return UART_NODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remember callback addresses and argument */
|
UART_TYPE *dev = uart_config[uart].dev;
|
||||||
ISR_CTX.rx_cb = rx_cb;
|
|
||||||
ISR_CTX.arg = arg;
|
|
||||||
|
|
||||||
#ifdef CPU_FAM_NRF51
|
/* remember callback addresses and argument */
|
||||||
/* power on the UART device */
|
isr_ctx[uart].rx_cb = rx_cb;
|
||||||
NRF_UART0->POWER = 1;
|
isr_ctx[uart].arg = arg;
|
||||||
|
|
||||||
|
#ifndef UARTE_PRESENT
|
||||||
|
/* only the legacy non-EasyDMA UART needs to be powered on explicitly */
|
||||||
|
dev->POWER = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* reset configuration registers */
|
/* reset configuration registers */
|
||||||
REG_CONFIG = 0;
|
dev->CONFIG = 0;
|
||||||
|
|
||||||
/* configure RX pin */
|
/* configure RX pin */
|
||||||
if (rx_cb) {
|
if (rx_cb) {
|
||||||
gpio_init(UART_PIN_RX, GPIO_IN);
|
gpio_init(uart_config[uart].rx_pin, GPIO_IN);
|
||||||
PSEL_RXD = UART_PIN_RX;
|
dev->PSEL_RXD = uart_config[uart].rx_pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* configure TX pin */
|
/* configure TX pin */
|
||||||
gpio_init(UART_PIN_TX, GPIO_OUT);
|
gpio_init(uart_config[uart].tx_pin, GPIO_OUT);
|
||||||
PSEL_TXD = UART_PIN_TX;
|
dev->PSEL_TXD = uart_config[uart].tx_pin;
|
||||||
|
|
||||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
|
||||||
/* enable HW-flow control if defined */
|
/* enable HW-flow control if defined */
|
||||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
#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 */
|
/* set pin mode for RTS and CTS pins */
|
||||||
if (UART_PIN_RTS != GPIO_UNDEF && UART_PIN_CTS != GPIO_UNDEF) {
|
if (uart_config[uart].rts_pin != GPIO_UNDEF && uart_config[uart].cts_pin != GPIO_UNDEF) {
|
||||||
gpio_init(UART_PIN_RTS, GPIO_OUT);
|
gpio_init(uart_config[uart].rts_pin, GPIO_OUT);
|
||||||
gpio_init(UART_PIN_CTS, GPIO_IN);
|
gpio_init(uart_config[uart].cts_pin, GPIO_IN);
|
||||||
/* configure RTS and CTS pins to use */
|
/* configure RTS and CTS pins to use */
|
||||||
NRF_UART0->PSELRTS = UART_PIN_RTS;
|
dev->PSEL_RTS = uart_config[uart].rts_pin;
|
||||||
NRF_UART0->PSELCTS = UART_PIN_CTS;
|
dev->PSEL_CTS = uart_config[uart].cts_pin;
|
||||||
REG_CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */
|
dev->CONFIG |= UART_CONFIG_HWFC_Msk; /* enable HW flow control */
|
||||||
}
|
}
|
||||||
#else
|
else
|
||||||
NRF_UART0->PSELRTS = 0xffffffff; /* pin disconnected */
|
|
||||||
NRF_UART0->PSELCTS = 0xffffffff; /* pin disconnected */
|
|
||||||
#endif /* MODULE_PERIPH_UART_HW_FC */
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
dev->PSEL_RTS = 0xffffffff; /* pin disconnected */
|
||||||
|
dev->PSEL_CTS = 0xffffffff; /* pin disconnected */
|
||||||
|
}
|
||||||
|
|
||||||
/* select baudrate */
|
/* select baudrate */
|
||||||
switch (baudrate) {
|
switch (baudrate) {
|
||||||
case 1200:
|
case 1200:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1200;
|
||||||
break;
|
break;
|
||||||
case 2400:
|
case 2400:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud2400;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud2400;
|
||||||
break;
|
break;
|
||||||
case 4800:
|
case 4800:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud4800;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud4800;
|
||||||
break;
|
break;
|
||||||
case 9600:
|
case 9600:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud9600;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud9600;
|
||||||
break;
|
break;
|
||||||
case 14400:
|
case 14400:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud14400;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud14400;
|
||||||
break;
|
break;
|
||||||
case 19200:
|
case 19200:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud19200;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud19200;
|
||||||
break;
|
break;
|
||||||
case 28800:
|
case 28800:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud28800;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud28800;
|
||||||
break;
|
break;
|
||||||
case 38400:
|
case 38400:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud38400;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud38400;
|
||||||
break;
|
break;
|
||||||
case 57600:
|
case 57600:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud57600;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud57600;
|
||||||
break;
|
break;
|
||||||
case 76800:
|
case 76800:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud76800;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud76800;
|
||||||
break;
|
break;
|
||||||
case 115200:
|
case 115200:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud115200;
|
||||||
break;
|
break;
|
||||||
case 230400:
|
case 230400:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud230400;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud230400;
|
||||||
break;
|
break;
|
||||||
case 250000:
|
case 250000:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud250000;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud250000;
|
||||||
break;
|
break;
|
||||||
case 460800:
|
case 460800:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud460800;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud460800;
|
||||||
break;
|
break;
|
||||||
case 921600:
|
case 921600:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud921600;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud921600;
|
||||||
break;
|
break;
|
||||||
case 1000000:
|
case 1000000:
|
||||||
REG_BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1M;
|
dev->BAUDRATE = UART_BAUDRATE_BAUDRATE_Baud1M;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return UART_NOBAUD;
|
return UART_NOBAUD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable the UART device */
|
/* enable the UART device */
|
||||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
dev->ENABLE = ENABLE_ON;
|
||||||
dev(uart)->ENABLE = UARTE_ENABLE_ENABLE_Enabled;
|
|
||||||
#else
|
|
||||||
NRF_UART0->ENABLE = UART_ENABLE_ENABLE_Enabled;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MODULE_PERIPH_UART_NONBLOCKING
|
#ifdef MODULE_PERIPH_UART_NONBLOCKING
|
||||||
/* set up the TX buffer */
|
/* 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
|
#endif
|
||||||
|
|
||||||
if (rx_cb) {
|
if (rx_cb) {
|
||||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
#ifdef UARTE_PRESENT
|
||||||
dev(uart)->RXD.MAXCNT = 1;
|
dev->RXD.MAXCNT = 1;
|
||||||
dev(uart)->RXD.PTR = (uint32_t)&rx_buf[uart];
|
dev->RXD.PTR = (uint32_t)&rx_buf[uart];
|
||||||
dev(uart)->INTENSET = UARTE_INTENSET_ENDRX_Msk;
|
dev->INTENSET = UARTE_INTENSET_ENDRX_Msk;
|
||||||
dev(uart)->SHORTS |= UARTE_SHORTS_ENDRX_STARTRX_Msk;
|
dev->SHORTS |= UARTE_SHORTS_ENDRX_STARTRX_Msk;
|
||||||
dev(uart)->TASKS_STARTRX = 1;
|
dev->TASKS_STARTRX = 1;
|
||||||
#else
|
#else
|
||||||
NRF_UART0->INTENSET = UART_INTENSET_RXDRDY_Msk;
|
dev->INTENSET = UART_INTENSET_RXDRDY_Msk;
|
||||||
NRF_UART0->TASKS_STARTRX = 1;
|
dev->TASKS_STARTRX = 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rx_cb || IS_USED(MODULE_PERIPH_UART_NONBLOCKING)) {
|
if (rx_cb || IS_USED(MODULE_PERIPH_UART_NONBLOCKING)) {
|
||||||
#if defined(CPU_NRF53) || defined(CPU_NRF9160)
|
#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
|
#else
|
||||||
NVIC_EnableIRQ(UART_IRQN);
|
NVIC_EnableIRQ(uart_config[uart].irqn);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return UART_OK;
|
return UART_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nrf52840 || nrf52811 (using EasyDMA) */
|
/* UART with EasyDMA */
|
||||||
#if !defined(CPU_MODEL_NRF52832XXAA) && !defined(CPU_FAM_NRF51)
|
#ifdef UARTE_PRESENT
|
||||||
static void _write_buf(uart_t uart, const uint8_t *data, size_t len)
|
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)) {
|
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 */
|
/* set data to transfer to DMA TX pointer */
|
||||||
dev(uart)->TXD.PTR = (uint32_t)data;
|
uart_config[uart].dev->TXD.PTR = (uint32_t)data;
|
||||||
dev(uart)->TXD.MAXCNT = len;
|
uart_config[uart].dev->TXD.MAXCNT = len;
|
||||||
/* start transmission */
|
/* start transmission */
|
||||||
dev(uart)->TASKS_STARTTX = 1;
|
uart_config[uart].dev->TASKS_STARTTX = 1;
|
||||||
/* wait for the end of transmission */
|
/* wait for the end of transmission */
|
||||||
if (!IS_USED(MODULE_PERIPH_UART_NONBLOCKING)) {
|
if (!IS_USED(MODULE_PERIPH_UART_NONBLOCKING)) {
|
||||||
while (dev(uart)->EVENTS_ENDTX == 0) {}
|
while (uart_config[uart].dev->EVENTS_ENDTX == 0) {}
|
||||||
dev(uart)->TASKS_STOPTX = 1;
|
uart_config[uart].dev->TASKS_STOPTX = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
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
|
#ifdef MODULE_PERIPH_UART_NONBLOCKING
|
||||||
for (size_t i = 0; i < len; i++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
/* in IRQ or interrupts disabled */
|
/* in IRQ or interrupts disabled */
|
||||||
if (irq_is_in() || __get_PRIMASK()) {
|
if (irq_is_in() || __get_PRIMASK()) {
|
||||||
if (tsrb_full(&uart_tx_rb[uart])) {
|
if (tsrb_full(&uart_tx_rb[uart])) {
|
||||||
/* wait for end of ongoing transmission */
|
/* wait for end of ongoing transmission */
|
||||||
if (dev(uart)->EVENTS_TXSTARTED) {
|
if (uart_config[uart].dev->EVENTS_TXSTARTED) {
|
||||||
while (dev(uart)->EVENTS_ENDTX == 0) {}
|
while (uart_config[uart].dev->EVENTS_ENDTX == 0) {}
|
||||||
dev(uart)->EVENTS_TXSTARTED = 0;
|
uart_config[uart].dev->EVENTS_TXSTARTED = 0;
|
||||||
}
|
}
|
||||||
/* free one spot in buffer */
|
/* free one spot in buffer */
|
||||||
tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]);
|
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 {
|
else {
|
||||||
/* if no transmission is ongoing and ring buffer is full
|
/* if no transmission is ongoing and ring buffer is full
|
||||||
free up a spot in the buffer by sending one byte */
|
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]);
|
tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]);
|
||||||
_write_buf(uart, &tx_buf[uart], 1);
|
_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
|
/* if no transmission is ongoing bootstrap the transmission process
|
||||||
by setting a single byte to be written */
|
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])) {
|
if (!tsrb_empty(&uart_tx_rb[uart])) {
|
||||||
tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]);
|
tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]);
|
||||||
_write_buf(uart, &tx_buf[uart], 1);
|
_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)
|
void uart_poweron(uart_t uart)
|
||||||
{
|
{
|
||||||
assert(uart < UART_NUMOF);
|
assume((unsigned)uart < UART_NUMOF);
|
||||||
|
|
||||||
if (isr_ctx[uart].rx_cb) {
|
if (isr_ctx[uart].rx_cb) {
|
||||||
dev(uart)->TASKS_STARTRX = 1;
|
uart_config[uart].dev->TASKS_STARTRX = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_poweroff(uart_t uart)
|
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,
|
int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity,
|
||||||
uart_stop_bits_t stop_bits)
|
uart_stop_bits_t stop_bits)
|
||||||
{
|
{
|
||||||
|
assume((unsigned)uart < UART_NUMOF);
|
||||||
if (stop_bits != UART_STOP_BITS_1 && stop_bits != UART_STOP_BITS_2) {
|
/* 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;
|
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;
|
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) {
|
if (stop_bits == UART_STOP_BITS_2) {
|
||||||
dev(uart)->CONFIG |= UARTE_CONFIG_STOP_Msk;
|
conf |= UARTE_CONFIG_STOP_Msk;
|
||||||
}
|
|
||||||
else {
|
|
||||||
dev(uart)->CONFIG &= ~UARTE_CONFIG_STOP_Msk;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (parity == UART_PARITY_EVEN) {
|
if (parity == UART_PARITY_EVEN) {
|
||||||
dev(uart)->CONFIG |= UARTE_CONFIG_PARITY_Msk;
|
conf |= UARTE_CONFIG_PARITY_Msk;
|
||||||
}
|
|
||||||
else {
|
|
||||||
dev(uart)->CONFIG &= ~UARTE_CONFIG_PARITY_Msk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uart_config[uart].dev->CONFIG = conf;
|
||||||
return UART_OK;
|
return UART_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void irq_handler(uart_t uart)
|
static void irq_handler(uart_t uart)
|
||||||
{
|
{
|
||||||
if (dev(uart)->EVENTS_ENDRX) {
|
if (uart_config[uart].dev->EVENTS_ENDRX) {
|
||||||
dev(uart)->EVENTS_ENDRX = 0;
|
uart_config[uart].dev->EVENTS_ENDRX = 0;
|
||||||
|
|
||||||
/* make sure we actually received new data */
|
/* make sure we actually received new data */
|
||||||
if (dev(uart)->RXD.AMOUNT != 0) {
|
if (uart_config[uart].dev->RXD.AMOUNT != 0) {
|
||||||
/* Process received byte */
|
/* Process received byte */
|
||||||
isr_ctx[uart].rx_cb(isr_ctx[uart].arg, rx_buf[uart]);
|
isr_ctx[uart].rx_cb(isr_ctx[uart].arg, rx_buf[uart]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_PERIPH_UART_NONBLOCKING
|
#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 */
|
/* reset flags and idsable ISR on EVENTS_ENDTX */
|
||||||
dev(uart)->EVENTS_ENDTX = 0;
|
uart_config[uart].dev->EVENTS_ENDTX = 0;
|
||||||
dev(uart)->EVENTS_TXSTARTED = 0;
|
uart_config[uart].dev->EVENTS_TXSTARTED = 0;
|
||||||
dev(uart)->INTENCLR = UARTE_INTENSET_ENDTX_Msk;
|
uart_config[uart].dev->INTENCLR = UARTE_INTENSET_ENDTX_Msk;
|
||||||
if (tsrb_empty(&uart_tx_rb[uart])) {
|
if (tsrb_empty(&uart_tx_rb[uart])) {
|
||||||
dev(uart)->TASKS_STOPTX = 1;
|
uart_config[uart].dev->TASKS_STOPTX = 1;
|
||||||
} else {
|
} else {
|
||||||
tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]);
|
tx_buf[uart] = tsrb_get_one(&uart_tx_rb[uart]);
|
||||||
_write_buf(uart, &tx_buf[uart], 1);
|
_write_buf(uart, &tx_buf[uart], 1);
|
||||||
@ -411,13 +402,13 @@ static inline void irq_handler(uart_t uart)
|
|||||||
cortexm_isr_end();
|
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_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++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
/* This section of the function is not thread safe:
|
/* 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.
|
while loop.
|
||||||
*/
|
*/
|
||||||
/* reset ready flag */
|
/* reset ready flag */
|
||||||
NRF_UART0->EVENTS_TXDRDY = 0;
|
uart_config[uart].dev->EVENTS_TXDRDY = 0;
|
||||||
/* write data into transmit register */
|
/* write data into transmit register */
|
||||||
NRF_UART0->TXD = data[i];
|
uart_config[uart].dev->TXD = data[i];
|
||||||
/* wait for any transmission to be done */
|
/* 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_poweron(uart_t uart)
|
||||||
{
|
{
|
||||||
(void)uart;
|
assume((unsigned)uart < UART_NUMOF);
|
||||||
|
|
||||||
if (isr_ctx.rx_cb) {
|
if (isr_ctx[uart].rx_cb) {
|
||||||
NRF_UART0->TASKS_STARTRX = 1;
|
uart_config[uart].dev->TASKS_STARTRX = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_poweroff(uart_t uart)
|
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,
|
int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity,
|
||||||
uart_stop_bits_t stop_bits)
|
uart_stop_bits_t stop_bits)
|
||||||
{
|
{
|
||||||
(void)uart;
|
assume((unsigned)uart < UART_NUMOF);
|
||||||
|
|
||||||
if (stop_bits != UART_STOP_BITS_1) {
|
if (stop_bits != UART_STOP_BITS_1) {
|
||||||
return UART_NOMODE;
|
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) {
|
if (parity == UART_PARITY_EVEN) {
|
||||||
NRF_UART0->CONFIG |= UART_CONFIG_PARITY_Msk;
|
uart_config[uart].dev->CONFIG |= UART_CONFIG_PARITY_Msk;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
NRF_UART0->CONFIG &= ~UART_CONFIG_PARITY_Msk;
|
uart_config[uart].dev->CONFIG &= ~UART_CONFIG_PARITY_Msk;
|
||||||
}
|
}
|
||||||
|
|
||||||
return UART_OK;
|
return UART_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void irq_handler(uart_t uart)
|
static void irq_handler(uart_t uart)
|
||||||
{
|
{
|
||||||
(void)uart;
|
if (uart_config[uart].dev->EVENTS_RXDRDY == 1) {
|
||||||
|
uart_config[uart].dev->EVENTS_RXDRDY = 0;
|
||||||
if (NRF_UART0->EVENTS_RXDRDY == 1) {
|
uint8_t byte = (uint8_t)(uart_config[uart].dev->RXD & 0xff);
|
||||||
NRF_UART0->EVENTS_RXDRDY = 0;
|
isr_ctx[uart].rx_cb(isr_ctx[uart].arg, byte);
|
||||||
uint8_t byte = (uint8_t)(NRF_UART0->RXD & 0xff);
|
|
||||||
isr_ctx.rx_cb(isr_ctx.arg, byte);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cortexm_isr_end();
|
cortexm_isr_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !CPU_MODEL_NRF52832XXAA && !CPU_FAM_NRF51 */
|
#endif
|
||||||
|
|
||||||
#if defined(CPU_NRF53) || defined(CPU_NRF9160)
|
#if defined(CPU_NRF53) || defined(CPU_NRF9160)
|
||||||
void uart_isr_handler(void *arg)
|
void uart_isr_handler(void *arg)
|
||||||
@ -519,4 +508,5 @@ void UART_1_ISR(void)
|
|||||||
irq_handler(UART_DEV(1));
|
irq_handler(UART_DEV(1));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* def CPU_NRF53 || CPU_NRF9160 */
|
#endif /* def CPU_NRF53 || CPU_NRF9160 */
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
config CPU_COMMON_SAM0
|
config CPU_COMMON_SAM0
|
||||||
bool
|
bool
|
||||||
select HAS_PERIPH_CPUID
|
select HAS_PERIPH_CPUID
|
||||||
|
select HAS_PERIPH_ADC_CONTINUOUS
|
||||||
select HAS_PERIPH_FLASHPAGE
|
select HAS_PERIPH_FLASHPAGE
|
||||||
select HAS_PERIPH_FLASHPAGE_IN_ADDRESS_SPACE
|
select HAS_PERIPH_FLASHPAGE_IN_ADDRESS_SPACE
|
||||||
select HAS_PERIPH_FLASHPAGE_PAGEWISE
|
select HAS_PERIPH_FLASHPAGE_PAGEWISE
|
||||||
|
@ -7,6 +7,7 @@ ifeq (,$(filter $(CPU_MODELS_WITHOUT_DMA),$(CPU_MODEL)))
|
|||||||
FEATURES_PROVIDED += periph_dma
|
FEATURES_PROVIDED += periph_dma
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
FEATURES_PROVIDED += periph_adc_continuous
|
||||||
FEATURES_PROVIDED += periph_flashpage
|
FEATURES_PROVIDED += periph_flashpage
|
||||||
FEATURES_PROVIDED += periph_flashpage_in_address_space
|
FEATURES_PROVIDED += periph_flashpage_in_address_space
|
||||||
FEATURES_PROVIDED += periph_flashpage_pagewise
|
FEATURES_PROVIDED += periph_flashpage_pagewise
|
||||||
|
@ -945,6 +945,14 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
#define WDT_HAS_INIT (1)
|
#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
|
#if defined(REV_DMAC) || DOXYGEN
|
||||||
/**
|
/**
|
||||||
* @name sam0 DMA peripheral
|
* @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 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)
|
static inline void _wait_syncbusy(Adc *dev)
|
||||||
{
|
{
|
||||||
#ifdef ADC_STATUS_SYNCBUSY
|
#ifdef ADC_STATUS_SYNCBUSY
|
||||||
@ -263,7 +253,7 @@ int adc_init(adc_t line)
|
|||||||
const uint8_t adc = 0;
|
const uint8_t adc = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_prep();
|
mutex_lock(&_lock);
|
||||||
|
|
||||||
uint8_t muxpos = (adc_channels[line].inputctrl & ADC_INPUTCTRL_MUXPOS_Msk)
|
uint8_t muxpos = (adc_channels[line].inputctrl & ADC_INPUTCTRL_MUXPOS_Msk)
|
||||||
>> ADC_INPUTCTRL_MUXPOS_Pos;
|
>> 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);
|
gpio_init_mux(sam0_adc_pins[adc][muxneg], GPIO_MUX_B);
|
||||||
}
|
}
|
||||||
|
|
||||||
_done();
|
mutex_unlock(&_lock);
|
||||||
|
|
||||||
return 0;
|
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. */
|
/* The SAMD5x/SAME5x family has two ADCs: ADC0 and ADC1. */
|
||||||
#ifdef ADC0
|
#ifdef ADC0
|
||||||
Adc *dev = adc_channels[line].dev;
|
return adc_channels[line].dev;
|
||||||
#else
|
#else
|
||||||
Adc *dev = ADC;
|
(void)line;
|
||||||
|
return ADC;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool diffmode = adc_channels[line].inputctrl & ADC_INPUTCTRL_DIFFMODE;
|
static Adc *_adc(uint8_t dev)
|
||||||
|
{
|
||||||
_prep();
|
/* The SAMD5x/SAME5x family has two ADCs: ADC0 and ADC1. */
|
||||||
|
#ifdef ADC0
|
||||||
if (_adc_configure(dev, res) != 0) {
|
switch (dev) {
|
||||||
_done();
|
case 0:
|
||||||
DEBUG("adc: configuration failed\n");
|
return ADC0;
|
||||||
return -1;
|
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
|
dev->INPUTCTRL.reg = ADC_GAIN_FACTOR_DEFAULT
|
||||||
| adc_channels[line].inputctrl
|
| adc_channels[line].inputctrl
|
||||||
@ -319,7 +319,6 @@ int32_t adc_sample(adc_t line, adc_res_t res)
|
|||||||
#ifdef ADC_CTRLB_DIFFMODE
|
#ifdef ADC_CTRLB_DIFFMODE
|
||||||
dev->CTRLB.bit.DIFFMODE = diffmode;
|
dev->CTRLB.bit.DIFFMODE = diffmode;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_wait_syncbusy(dev);
|
_wait_syncbusy(dev);
|
||||||
|
|
||||||
/* Start the conversion */
|
/* Start the conversion */
|
||||||
@ -331,9 +330,6 @@ int32_t adc_sample(adc_t line, adc_res_t res)
|
|||||||
uint16_t sample = dev->RESULT.reg;
|
uint16_t sample = dev->RESULT.reg;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
_adc_poweroff(dev);
|
|
||||||
_done();
|
|
||||||
|
|
||||||
/* in differential mode we lose one bit for the sign */
|
/* in differential mode we lose one bit for the sign */
|
||||||
if (diffmode) {
|
if (diffmode) {
|
||||||
result = 2 * (int16_t)sample;
|
result = 2 * (int16_t)sample;
|
||||||
@ -341,11 +337,104 @@ int32_t adc_sample(adc_t line, adc_res_t res)
|
|||||||
result = sample;
|
result = sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t _shift_from_res(adc_res_t res)
|
||||||
|
{
|
||||||
/* 16 bit mode is implemented as oversampling */
|
/* 16 bit mode is implemented as oversampling */
|
||||||
if ((res & 0x3) == 1) {
|
if ((res & 0x3) == 1) {
|
||||||
/* ADC does automatic right shifts beyond 16 samples */
|
/* 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
|
#ifdef MODULE_PERIPH_PM
|
||||||
| MCLK_APBAMASK_PM
|
| MCLK_APBAMASK_PM
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MODULE_PERIPH_FREQM
|
||||||
|
| MCLK_APBAMASK_FREQM
|
||||||
|
#endif
|
||||||
#ifdef MODULE_PERIPH_GPIO_IRQ
|
#ifdef MODULE_PERIPH_GPIO_IRQ
|
||||||
| MCLK_APBAMASK_EIC
|
| MCLK_APBAMASK_EIC
|
||||||
#endif
|
#endif
|
||||||
|
@ -70,13 +70,19 @@ enum {
|
|||||||
* @name SAMD5x GCLK definitions
|
* @name SAMD5x GCLK definitions
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
enum {
|
#define SAM0_GCLK_MAIN 0 /**< 120 MHz main clock */
|
||||||
SAM0_GCLK_MAIN = 0, /**< 120 MHz main clock */
|
#ifndef SAM0_GCLK_32KHZ
|
||||||
SAM0_GCLK_32KHZ, /**< 32 kHz clock */
|
#define SAM0_GCLK_32KHZ 1 /**< 32 kHz clock */
|
||||||
SAM0_GCLK_TIMER, /**< 4-8 MHz clock for xTimer */
|
#endif
|
||||||
SAM0_GCLK_PERIPH, /**< 12-48 MHz (DFLL) clock */
|
#ifndef SAM0_GCLK_TIMER
|
||||||
SAM0_GCLK_100MHZ, /**< 100MHz FDPLL clock */
|
#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)
|
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
|
* @brief NVM User Page Mapping - Dedicated Entries
|
||||||
* Config values will be applied at power-on.
|
* Config values will be applied at power-on.
|
||||||
|
@ -333,6 +333,26 @@ void _wlx5xx_init_subghz_debug_pins(void)
|
|||||||
#endif
|
#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)
|
void cpu_init(void)
|
||||||
{
|
{
|
||||||
/* initialize the Cortex-M core */
|
/* 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 */
|
/* initialize stdio prior to periph_init() to allow use of DEBUG() there */
|
||||||
early_init();
|
early_init();
|
||||||
|
|
||||||
#ifdef STM32F1_DISABLE_JTAG
|
swj_init();
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
|
|
||||||
AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* trigger static peripheral initialization */
|
/* trigger static peripheral initialization */
|
||||||
periph_init();
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -170,6 +170,36 @@ typedef struct {
|
|||||||
#define USBDEV_NUM_ENDPOINTS 8
|
#define USBDEV_NUM_ENDPOINTS 8
|
||||||
#endif
|
#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 */
|
#endif /* !DOXYGEN */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -120,7 +120,7 @@ static void _init_pins(i2c_t dev)
|
|||||||
/* The remapping periph clock must first be enabled */
|
/* The remapping periph clock must first be enabled */
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
|
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
|
||||||
/* Then the remap can occur */
|
/* 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].scl_pin, GPIO_AF_OUT_OD);
|
||||||
gpio_init_af(i2c_config[dev].sda_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 <assert.h>
|
||||||
|
|
||||||
#include "bitarithm.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
#include "periph/gpio.h"
|
#include "periph/gpio.h"
|
||||||
#include "periph/spi.h"
|
#include "periph/spi.h"
|
||||||
@ -65,9 +63,9 @@ static mutex_t locks[SPI_NUMOF];
|
|||||||
static uint32_t clocks[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)
|
static inline SPI_TypeDef *dev(spi_t bus)
|
||||||
{
|
{
|
||||||
@ -81,33 +79,24 @@ static inline bool _use_dma(const spi_conf_t *conf)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
static uint8_t _get_prescaler(const spi_conf_t *conf, uint32_t clock)
|
||||||
* @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)
|
|
||||||
{
|
{
|
||||||
uint32_t bus_clock = periph_apb_clk(conf->apbbus);
|
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);
|
uint8_t prescaler = 0;
|
||||||
DEBUG("[spi] clock: divider: %"PRIu32"\n", div);
|
uint32_t prescaled_clock = bus_clock >> 1;
|
||||||
/* Test if the divider is 2 or smaller, keeping the fixed point in mind */
|
const uint8_t prescaler_max = SPI_CR1_BR_Msk >> SPI_CR1_BR_Pos;
|
||||||
if (div <= SPI_APB_CLOCK_MULT) {
|
for (; (prescaled_clock > clock) && (prescaler < prescaler_max); prescaler++) {
|
||||||
return 0;
|
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;
|
/* If the callers asks for an SPI frequency of at most x, bad things will
|
||||||
/* Determine if rounded_div is not a power of 2 */
|
* happen if this cannot be met. So let's have a blown assertion
|
||||||
if ((div & (div - 1)) != 0) {
|
* rather than runtime failures that require a logic analyzer to
|
||||||
/* increment by 1 to ensure that the clock speed at most the
|
* debug. */
|
||||||
* requested clock speed */
|
assert(prescaled_clock <= clock);
|
||||||
rounded_div++;
|
|
||||||
}
|
return prescaler;
|
||||||
return rounded_div > BR_MAX ? BR_MAX : rounded_div;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spi_init(spi_t bus)
|
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);
|
periph_clk_en(spi_config[bus].apbbus, spi_config[bus].rccmask);
|
||||||
/* enable device */
|
/* enable device */
|
||||||
if (clk != clocks[bus]) {
|
if (clk != clocks[bus]) {
|
||||||
dividers[bus] = _get_clkdiv(&spi_config[bus], clk);
|
prescalers[bus] = _get_prescaler(&spi_config[bus], clk);
|
||||||
clocks[bus] = clk;
|
clocks[bus] = clk;
|
||||||
}
|
}
|
||||||
uint8_t br = dividers[bus];
|
uint8_t br = prescalers[bus];
|
||||||
|
|
||||||
DEBUG("[spi] acquire: requested clock: %"PRIu32", resulting clock: %"PRIu32
|
DEBUG("[spi] acquire: requested clock: %" PRIu32
|
||||||
" BR divider: %u\n",
|
" Hz, resulting clock: %" PRIu32 " Hz, BR prescaler: %u\n",
|
||||||
clk,
|
clk,
|
||||||
periph_apb_clk(spi_config[bus].apbbus)/(1 << (br + 1)),
|
periph_apb_clk(spi_config[bus].apbbus) >> (br + 1),
|
||||||
br);
|
(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 */
|
/* 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) {
|
if (cs != SPI_HWCS_MASK) {
|
||||||
cr1_settings |= (SPI_CR1_SSM | SPI_CR1_SSI);
|
cr1 |= (SPI_CR1_SSM | SPI_CR1_SSI);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cr2_extra_settings = (SPI_CR2_SSOE);
|
cr2 = (SPI_CR2_SSOE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_PERIPH_DMA
|
#ifdef MODULE_PERIPH_DMA
|
||||||
if (_use_dma(&spi_config[bus])) {
|
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_acquire(spi_config[bus].tx_dma);
|
||||||
dma_setup(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);
|
0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
dev(bus)->CR1 = cr1_settings;
|
dev(bus)->CR1 = cr1;
|
||||||
/* Only modify CR2 if needed */
|
dev(bus)->CR2 = cr2;
|
||||||
if (cr2_extra_settings) {
|
|
||||||
dev(bus)->CR2 = (SPI_CR2_SETTINGS | cr2_extra_settings);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spi_release(spi_t bus)
|
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);
|
assert(out || in);
|
||||||
|
|
||||||
/* active the given chip select line */
|
/* 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)) {
|
if ((cs != SPI_HWCS_MASK) && gpio_is_valid(cs)) {
|
||||||
gpio_clear((gpio_t)cs);
|
gpio_clear((gpio_t)cs);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
dev(bus)->CR2 |= SPI_CR2_SSOE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MODULE_PERIPH_DMA
|
#ifdef MODULE_PERIPH_DMA
|
||||||
if (_use_dma(&spi_config[bus])) {
|
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 */
|
/* release the chip select if not specified differently */
|
||||||
if ((!cont) && gpio_is_valid(cs)) {
|
if ((!cont) && gpio_is_valid(cs)) {
|
||||||
dev(bus)->CR1 &= ~(SPI_CR1_SPE); /* pull HW CS line high */
|
|
||||||
if (cs != SPI_HWCS_MASK) {
|
if (cs != SPI_HWCS_MASK) {
|
||||||
gpio_set((gpio_t)cs);
|
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 EPD_BW_SPI_WAIT_[A-Z0-9_]* \(macro definition\) of
|
||||||
warning: Member F_CPU \(macro definition\) of
|
warning: Member F_CPU \(macro definition\) of
|
||||||
warning: Member F_RC_OSCILLATOR \(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_ADDR \(macro definition\) of
|
||||||
warning: Member FXOS8700_PARAM_I2C \(macro definition\) of
|
warning: Member FXOS8700_PARAM_I2C \(macro definition\) of
|
||||||
warning: Member FXOS8700_PARAM_RENEW_INTERVAL \(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
|
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
|
include $(RIOTBASE)/pkg/pkg.mk
|
||||||
|
|
||||||
all: $(CURDIR)/uf2conv.py
|
all: $(CURDIR)/uf2conv.py $(CURDIR)/uf2families.json
|
||||||
|
|
||||||
$(CURDIR)/uf2conv.py:
|
$(CURDIR)/uf2conv.py:
|
||||||
cp $(PKG_SOURCE_DIR)/utils/uf2conv.py .
|
cp $(PKG_SOURCE_DIR)/utils/uf2conv.py .
|
||||||
chmod a+x 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.
|
* 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 <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -32,6 +65,10 @@
|
|||||||
#define AT_EVENT_PRIO EVENT_PRIO_HIGHEST
|
#define AT_EVENT_PRIO EVENT_PRIO_HIGHEST
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(MODULE_AT_URC)
|
||||||
|
static int _check_urc(clist_node_t *node, void *arg);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(MODULE_AT_URC_ISR)
|
#if defined(MODULE_AT_URC_ISR)
|
||||||
static void _event_process_urc(event_t *_event)
|
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);
|
isrpipe_init(&dev->isrpipe, (uint8_t *)buf, bufsize);
|
||||||
|
|
||||||
return uart_init(uart, baudrate, _isrpipe_write_one_wrapper,
|
return uart_init(uart, baudrate, _isrpipe_write_one_wrapper, dev);
|
||||||
dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout)
|
int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout)
|
||||||
@ -99,6 +135,15 @@ out:
|
|||||||
return res;
|
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)
|
void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len)
|
||||||
{
|
{
|
||||||
uart_write(dev->uart, (const uint8_t *)bytes, 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);
|
uart_write(dev->uart, (const uint8_t *)CONFIG_AT_SEND_EOL, AT_SEND_EOL_LEN);
|
||||||
|
|
||||||
if (!IS_ACTIVE(CONFIG_AT_SEND_SKIP_ECHO)) {
|
if (!IS_ACTIVE(CONFIG_AT_SEND_SKIP_ECHO)) {
|
||||||
if (at_expect_bytes(dev, command, timeout)) {
|
if (at_wait_bytes(dev, command, timeout)) {
|
||||||
return -1;
|
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;
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,11 +264,7 @@ ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
res = at_readline_skip_empty(dev, resp_buf, len, false, timeout);
|
||||||
if (res == 0) {
|
|
||||||
/* skip possible empty line */
|
|
||||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return res;
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
/* URCs may occur right after the command has been sent and before the
|
||||||
if (res == 0) {
|
* expected response */
|
||||||
/* skip possible empty line */
|
do {
|
||||||
res = at_readline(dev, resp_buf, len, false, timeout);
|
res = at_readline_skip_empty(dev, resp_buf, len, false, timeout);
|
||||||
}
|
|
||||||
|
|
||||||
/* Strip the expected prefix */
|
/* Strip the expected prefix */
|
||||||
if (res > 0 && resp_prefix && *resp_prefix) {
|
if (res > 0 && resp_prefix && *resp_prefix) {
|
||||||
size_t prefix_len = strlen(resp_prefix);
|
size_t prefix_len = strlen(resp_prefix);
|
||||||
if (strncmp(resp_buf, resp_prefix, prefix_len) == 0) {
|
if (strncmp(resp_buf, resp_prefix, prefix_len) == 0) {
|
||||||
size_t remaining_len = strlen(resp_buf) - prefix_len;
|
size_t remaining_len = strlen(resp_buf) - prefix_len;
|
||||||
/* The one extra byte in the copy is the terminating nul byte */
|
/* The one extra byte in the copy is the terminating nul byte */
|
||||||
memmove(resp_buf, resp_buf + prefix_len, remaining_len + 1);
|
memmove(resp_buf, resp_buf + prefix_len, remaining_len + 1);
|
||||||
res -= prefix_len;
|
res -= prefix_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} while (res >= 0);
|
||||||
|
|
||||||
/* wait for OK */
|
/* wait for OK */
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
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) {
|
if (res_ok < 0) {
|
||||||
/* skip possible empty line */
|
return -1;
|
||||||
res_ok = at_readline(dev, ok_buf, sizeof(ok_buf), false, timeout);
|
|
||||||
}
|
}
|
||||||
ssize_t len_ok = sizeof(CONFIG_AT_RECV_OK) - 1;
|
ssize_t len_ok = sizeof(CONFIG_AT_RECV_OK) - 1;
|
||||||
if ((len_ok != 0) && (strcmp(ok_buf, CONFIG_AT_RECV_OK) == 0)) {
|
if ((len_ok != 0) && (strcmp(ok_buf, CONFIG_AT_RECV_OK) == 0)) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Something else then OK */
|
/* Something else than OK */
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,8 +337,6 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command,
|
|||||||
goto out;
|
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);
|
memset(resp_buf, '\0', len);
|
||||||
|
|
||||||
while (1) {
|
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 *)command, cmdlen);
|
||||||
uart_write(dev->uart, (const uint8_t *)CONFIG_AT_SEND_EOL, AT_SEND_EOL_LEN);
|
uart_write(dev->uart, (const uint8_t *)CONFIG_AT_SEND_EOL, AT_SEND_EOL_LEN);
|
||||||
|
|
||||||
if (at_expect_bytes(dev, command, timeout)) {
|
if (!IS_ACTIVE(CONFIG_AT_SEND_SKIP_ECHO)) {
|
||||||
return -1;
|
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 at_wait_bytes(dev, ">", timeout);
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (at_expect_bytes(dev, ">", timeout)) {
|
|
||||||
return -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t 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;
|
int res;
|
||||||
char resp_buf[64];
|
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) {
|
size_t const len_ok = sizeof(CONFIG_AT_RECV_OK) - 1;
|
||||||
ssize_t len_ok = sizeof(CONFIG_AT_RECV_OK) - 1;
|
size_t const len_err = sizeof(CONFIG_AT_RECV_ERROR) - 1;
|
||||||
if ((len_ok != 0) && (strcmp(resp_buf, CONFIG_AT_RECV_OK) == 0)) {
|
size_t const len_cme_cms = sizeof("+CME ERROR:") - 1;
|
||||||
res = 0;
|
|
||||||
|
while (res >= 0) {
|
||||||
|
if (strncmp(resp_buf, CONFIG_AT_RECV_OK, len_ok) == 0) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else if (strncmp(resp_buf, CONFIG_AT_RECV_ERROR, len_err) == 0) {
|
||||||
res = -1;
|
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;
|
return res;
|
||||||
@ -445,6 +497,17 @@ out:
|
|||||||
return res;
|
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
|
#ifdef MODULE_AT_URC
|
||||||
void at_add_urc(at_dev_t *dev, at_urc_t *urc)
|
void at_add_urc(at_dev_t *dev, at_urc_t *urc)
|
||||||
{
|
{
|
||||||
|
@ -275,6 +275,52 @@ extern "C" {
|
|||||||
/ AT24CXXX_POLL_DELAY_US))
|
/ 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
|
* @name AT24C1024 constants
|
||||||
* @{
|
* @{
|
||||||
@ -369,6 +415,14 @@ extern "C" {
|
|||||||
#define AT24CXXX_EEPROM_SIZE (AT24C01A_EEPROM_SIZE)
|
#define AT24CXXX_EEPROM_SIZE (AT24C01A_EEPROM_SIZE)
|
||||||
#define AT24CXXX_PAGE_SIZE (AT24C01A_PAGE_SIZE)
|
#define AT24CXXX_PAGE_SIZE (AT24C01A_PAGE_SIZE)
|
||||||
#define AT24CXXX_MAX_POLLS (AT24C01A_MAX_POLLS)
|
#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)
|
#elif IS_USED(MODULE_AT24MAC)
|
||||||
#define AT24CXXX_EEPROM_SIZE (AT24MAC_EEPROM_SIZE)
|
#define AT24CXXX_EEPROM_SIZE (AT24MAC_EEPROM_SIZE)
|
||||||
#define AT24CXXX_PAGE_SIZE (AT24MAC_PAGE_SIZE)
|
#define AT24CXXX_PAGE_SIZE (AT24MAC_PAGE_SIZE)
|
||||||
|
@ -195,8 +195,8 @@ typedef struct {
|
|||||||
* @param[in] buf input buffer
|
* @param[in] buf input buffer
|
||||||
* @param[in] bufsize size of @p buf
|
* @param[in] bufsize size of @p buf
|
||||||
*
|
*
|
||||||
* @returns success code UART_OK on success
|
* @retval success code UART_OK on success
|
||||||
* @returns error code UART_NODEV or UART_NOBAUD otherwise
|
* @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);
|
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] command command string to send
|
||||||
* @param[in] timeout timeout (in usec)
|
* @param[in] timeout timeout (in usec)
|
||||||
*
|
*
|
||||||
* @returns 0 when device answers "OK"
|
* @retval 0 when device answers "OK"
|
||||||
* @returns <0 otherwise
|
* @retval <0 otherwise
|
||||||
*/
|
*/
|
||||||
int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout);
|
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] command command string to send
|
||||||
* @param[in] timeout timeout (in usec)
|
* @param[in] timeout timeout (in usec)
|
||||||
*
|
*
|
||||||
* @return 0 when prompt is received
|
* @retval 0 when prompt is received
|
||||||
* @return <0 otherwise
|
* @retval <0 otherwise
|
||||||
*/
|
*/
|
||||||
int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout);
|
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] len len of @p buffer
|
||||||
* @param[in] timeout timeout (in usec)
|
* @param[in] timeout timeout (in usec)
|
||||||
*
|
*
|
||||||
* @returns length of response on success
|
* @retval n length of response on success
|
||||||
* @returns <0 on error
|
* @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);
|
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] len len of @p buffer
|
||||||
* @param[in] timeout timeout (in usec)
|
* @param[in] timeout timeout (in usec)
|
||||||
*
|
*
|
||||||
* @returns length of response on success
|
* @retval n length of response on success
|
||||||
* @returns <0 on error
|
* @retval <0 on error
|
||||||
*/
|
*/
|
||||||
ssize_t at_send_cmd_get_resp_wait_ok(at_dev_t *dev, const char *command, const char *resp_prefix,
|
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);
|
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] keep_eol true to keep the CR character in the response
|
||||||
* @param[in] timeout timeout (in usec)
|
* @param[in] timeout timeout (in usec)
|
||||||
*
|
*
|
||||||
* @returns length of response on success
|
* @retval n length of response on success
|
||||||
* @returns -1 on error
|
* @retval -1 on error
|
||||||
* @returns -2 on CMS or CME 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,
|
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);
|
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] bytes buffer containing bytes to expect (NULL-terminated)
|
||||||
* @param[in] timeout timeout (in usec)
|
* @param[in] timeout timeout (in usec)
|
||||||
*
|
*
|
||||||
* @returns 0 on success
|
* @retval 0 on success
|
||||||
* @returns <0 otherwise
|
* @retval <0 otherwise
|
||||||
*/
|
*/
|
||||||
int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout);
|
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
|
* @brief Receives bytes into @p bytes buffer until the string pattern
|
||||||
* @p string is received or the buffer is full.
|
* @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.
|
* bytes.
|
||||||
* @param[in] timeout timeout (in usec) of inactivity to finish read
|
* @param[in] timeout timeout (in usec) of inactivity to finish read
|
||||||
*
|
*
|
||||||
* @returns 0 on success
|
* @retval 0 on success
|
||||||
* @returns <0 on error
|
* @retval <0 on error
|
||||||
*/
|
*/
|
||||||
int at_recv_bytes_until_string(at_dev_t *dev, const char *string,
|
int at_recv_bytes_until_string(at_dev_t *dev, const char *string,
|
||||||
char *bytes, size_t *bytes_len,
|
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] len maximum number of bytes to receive
|
||||||
* @param[in] timeout timeout (in usec) of inactivity to finish read
|
* @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);
|
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] command command to send
|
||||||
* @param[in] timeout timeout (in usec)
|
* @param[in] timeout timeout (in usec)
|
||||||
*
|
*
|
||||||
* @returns 0 on success
|
* @retval 0 on success
|
||||||
* @returns <0 otherwise
|
* @retval <0 otherwise
|
||||||
*/
|
*/
|
||||||
int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout);
|
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] keep_eol true to keep the CR character in the response
|
||||||
* @param[in] timeout timeout (in usec)
|
* @param[in] timeout timeout (in usec)
|
||||||
*
|
*
|
||||||
* @returns line length on success
|
* @retval n line length on success
|
||||||
* @returns <0 on error
|
* @retval <0 on error
|
||||||
*/
|
*/
|
||||||
ssize_t at_readline(at_dev_t *dev, char *resp_buf, size_t len, bool keep_eol, uint32_t timeout);
|
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
|
* @brief Drain device input buffer
|
||||||
*
|
*
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
#ifndef MTD_H
|
#ifndef MTD_H
|
||||||
#define MTD_H
|
#define MTD_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "xfa.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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,6 +69,8 @@ extern mtd_emulated_t mtd_emulated_dev0;
|
|||||||
/**
|
/**
|
||||||
* @brief Get the default MTD device by index
|
* @brief Get the default MTD device by index
|
||||||
*
|
*
|
||||||
|
* @deprecated Use @ref mtd_dev_get instead
|
||||||
|
*
|
||||||
* @param[in] idx Index of the MTD device
|
* @param[in] idx Index of the MTD device
|
||||||
*
|
*
|
||||||
* @return MTD_0 for @p idx 0 and so on
|
* @return MTD_0 for @p idx 0 and so on
|
||||||
|
@ -245,10 +245,10 @@ extern "C"
|
|||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "kernel_defines.h"
|
|
||||||
#include "periph/gpio.h"
|
#include "periph/gpio.h"
|
||||||
#include "periph/i2c.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 */
|
#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 {
|
typedef enum {
|
||||||
PCF857X_OK, /**< success */
|
PCF857X_OK = 0, /**< success */
|
||||||
PCF857X_ERROR_I2C, /**< I2C communication error */
|
PCF857X_ERROR_I2C = ENXIO, /**< I2C communication error */
|
||||||
PCF857X_ERROR_INV_EXP, /**< invalid expander variant */
|
PCF857X_ERROR_INV_EXP = ENOTSUP, /**< invalid expander variant */
|
||||||
PCF857X_ERROR_INV_MODE, /**< invalid pin mode */
|
PCF857X_ERROR_INV_MODE = EINVAL, /**< invalid pin mode */
|
||||||
PCF857X_ERROR_INV_FLANK, /**< invalid interrupt flank */
|
PCF857X_ERROR_INV_FLANK = EINVAL, /**< invalid interrupt flank */
|
||||||
PCF857X_ERROR_INT_PIN, /**< interrupt pin initialization failed */
|
PCF857X_ERROR_INT_PIN = ENOSYS, /**< interrupt pin initialization failed */
|
||||||
} pcf857x_error_codes_t;
|
} pcf857x_error_codes_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -453,9 +457,8 @@ typedef struct {
|
|||||||
* has to be defined by the default configuration parameter
|
* has to be defined by the default configuration parameter
|
||||||
* #PCF857X_PARAM_INT_PIN (pcf857x_params_t::int_pin).
|
* #PCF857X_PARAM_INT_PIN (pcf857x_params_t::int_pin).
|
||||||
*
|
*
|
||||||
* @retval PCF857X_OK on success
|
* @retval 0 on success
|
||||||
* @retval PCF857X_ERROR_* a negative error code on error,
|
* @retval <0 a negative errno error code on error
|
||||||
* see #pcf857x_error_codes_t
|
|
||||||
*/
|
*/
|
||||||
int pcf857x_init(pcf857x_t *dev, const pcf857x_params_t *params);
|
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
|
* the driver physically supports only the modes #GPIO_IN_PU and
|
||||||
* #GPIO_OD_PU. The other logically identical modes #GPIO_IN, #GPIO_OUT
|
* #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
|
* 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 #GPIO_OUT mode the pin is actively driven LOW,
|
||||||
* after initialization in all other modes the pin is pulled-up to HIGH.
|
* after initialization in all other modes the pin is pulled-up to HIGH.
|
||||||
*
|
*
|
||||||
* @retval PCF857X_OK on success
|
* @retval 0 on success
|
||||||
* @retval PCF857X_ERROR_* a negative error code on error,
|
* @retval <0 a negative errno error code on error
|
||||||
* see #pcf857x_error_codes_t
|
|
||||||
*/
|
*/
|
||||||
int pcf857x_gpio_init(pcf857x_t *dev, gpio_t pin, gpio_mode_t mode);
|
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
|
* the driver physically supports only the modes #GPIO_IN_PU and
|
||||||
* #GPIO_OD_PU. The other logically identical modes #GPIO_IN, #GPIO_OUT
|
* #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
|
* 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 #GPIO_OUT mode the pin is actively driven LOW,
|
||||||
* after initialization in all other modes the pin is pulled-up to HIGH.
|
* 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] isr ISR that is called back from interrupt context
|
||||||
* @param[in] arg optional argument passed to the callback
|
* @param[in] arg optional argument passed to the callback
|
||||||
*
|
*
|
||||||
* @retval PCF857X_OK on success
|
* @retval 0 on success
|
||||||
* @retval PCF857X_ERROR_* a negative error code on error,
|
* @retval <0 a negative errno error code on error
|
||||||
* see #pcf857x_error_codes_t
|
|
||||||
*/
|
*/
|
||||||
int pcf857x_gpio_init_int(pcf857x_t *dev, gpio_t pin,
|
int pcf857x_gpio_init_int(pcf857x_t *dev, gpio_t pin,
|
||||||
gpio_mode_t mode,
|
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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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