2022-08-08 09:55:20 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg
|
|
|
|
*
|
|
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
|
|
* directory for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ingroup boards_common_stm32
|
|
|
|
* @brief Common LED macros
|
|
|
|
* @{
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @brief Common LED macros
|
|
|
|
*
|
|
|
|
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
|
|
|
*
|
|
|
|
* This idea is that STM32 boards only define the pin and port number of LEDs
|
|
|
|
* and this header provides the rest of the defines
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef STM32_LEDS_H
|
|
|
|
#define STM32_LEDS_H
|
|
|
|
|
drivers/periph_gpio_ll: change API to access GPIO ports
The API was based on the assumption that GPIO ports are mapped in memory
sanely, so that a `GPIO_PORT(num)` macro would work allow for constant
folding when `num` is known and still be efficient when it is not.
Some MCUs, however, will need a look up tables to efficiently translate
GPIO port numbers to the port's base address. This will prevent the use
of such a `GPIO_PORT(num)` macro in constant initializers.
As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros
for each GPIO port present (regardless of MCU naming scheme), as well as
`GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port
naming scheme uses letters rather than numbers.
These can be defined as macros to the peripheral base address even when
those are randomly mapped into the address space. In addition, a C
function `gpio_port()` replaces the role of the `GPIO_PORT()` and
`gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will
still be implemented as efficient as possible and will allow constant
folding where it was formerly possible. Hence, there is no downside for
MCUs with sane peripheral memory mapping, but it is highly beneficial
for the crazy ones.
There are also two benefits for the non-crazy MCUs:
1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>`
- This directly benefits the test in `tests/periph/gpio_ll`, which
can now provide a valid GPIO port for each and every board
- Writing to invalid memory mapped I/O addresses was treated as
triggering undefined behavior by the compiler and used as a
optimization opportunity
2. We can now detect at compile time if the naming scheme of the MCU
uses letters or numbers, and produce more user friendly output.
- This is directly applied in the test app
2024-04-29 13:32:24 +02:00
|
|
|
/* Using gpio_ll_arch for the gpio_port() function. This even works when
|
|
|
|
* GPIO LL is not in used */
|
2022-08-08 09:55:20 +02:00
|
|
|
#include "gpio_ll_arch.h"
|
|
|
|
#include "kernel_defines.h"
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @name Common LED pin definitions for STM32 boards
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
#if defined(LED0_PORT_NUM) && defined (LED0_PIN_NUM)
|
drivers/periph_gpio_ll: change API to access GPIO ports
The API was based on the assumption that GPIO ports are mapped in memory
sanely, so that a `GPIO_PORT(num)` macro would work allow for constant
folding when `num` is known and still be efficient when it is not.
Some MCUs, however, will need a look up tables to efficiently translate
GPIO port numbers to the port's base address. This will prevent the use
of such a `GPIO_PORT(num)` macro in constant initializers.
As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros
for each GPIO port present (regardless of MCU naming scheme), as well as
`GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port
naming scheme uses letters rather than numbers.
These can be defined as macros to the peripheral base address even when
those are randomly mapped into the address space. In addition, a C
function `gpio_port()` replaces the role of the `GPIO_PORT()` and
`gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will
still be implemented as efficient as possible and will allow constant
folding where it was formerly possible. Hence, there is no downside for
MCUs with sane peripheral memory mapping, but it is highly beneficial
for the crazy ones.
There are also two benefits for the non-crazy MCUs:
1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>`
- This directly benefits the test in `tests/periph/gpio_ll`, which
can now provide a valid GPIO port for each and every board
- Writing to invalid memory mapped I/O addresses was treated as
triggering undefined behavior by the compiler and used as a
optimization opportunity
2. We can now detect at compile time if the naming scheme of the MCU
uses letters or numbers, and produce more user friendly output.
- This is directly applied in the test app
2024-04-29 13:32:24 +02:00
|
|
|
# define LED0_PORT ((GPIO_TypeDef *)gpio_port(LED0_PORT_NUM))
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED0_PIN GPIO_PIN(LED0_PORT_NUM, LED0_PIN_NUM)
|
|
|
|
# define LED0_MASK (1 << LED0_PIN_NUM)
|
2022-09-08 10:57:14 +02:00
|
|
|
# if IS_ACTIVE(LED0_IS_INVERTED)
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED0_ON (LED0_PORT->BSRR = (LED0_MASK << 16))
|
|
|
|
# define LED0_OFF (LED0_PORT->BSRR = LED0_MASK)
|
2022-09-08 10:57:14 +02:00
|
|
|
# else
|
|
|
|
# define LED0_ON (LED0_PORT->BSRR = LED0_MASK)
|
|
|
|
# define LED0_OFF (LED0_PORT->BSRR = (LED0_MASK << 16))
|
2022-08-08 09:55:20 +02:00
|
|
|
# endif
|
|
|
|
# define LED0_TOGGLE (LED0_PORT->ODR ^= LED0_MASK)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(LED1_PORT_NUM) && defined (LED1_PIN_NUM)
|
drivers/periph_gpio_ll: change API to access GPIO ports
The API was based on the assumption that GPIO ports are mapped in memory
sanely, so that a `GPIO_PORT(num)` macro would work allow for constant
folding when `num` is known and still be efficient when it is not.
Some MCUs, however, will need a look up tables to efficiently translate
GPIO port numbers to the port's base address. This will prevent the use
of such a `GPIO_PORT(num)` macro in constant initializers.
As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros
for each GPIO port present (regardless of MCU naming scheme), as well as
`GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port
naming scheme uses letters rather than numbers.
These can be defined as macros to the peripheral base address even when
those are randomly mapped into the address space. In addition, a C
function `gpio_port()` replaces the role of the `GPIO_PORT()` and
`gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will
still be implemented as efficient as possible and will allow constant
folding where it was formerly possible. Hence, there is no downside for
MCUs with sane peripheral memory mapping, but it is highly beneficial
for the crazy ones.
There are also two benefits for the non-crazy MCUs:
1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>`
- This directly benefits the test in `tests/periph/gpio_ll`, which
can now provide a valid GPIO port for each and every board
- Writing to invalid memory mapped I/O addresses was treated as
triggering undefined behavior by the compiler and used as a
optimization opportunity
2. We can now detect at compile time if the naming scheme of the MCU
uses letters or numbers, and produce more user friendly output.
- This is directly applied in the test app
2024-04-29 13:32:24 +02:00
|
|
|
# define LED1_PORT ((GPIO_TypeDef *)gpio_port(LED1_PORT_NUM))
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED1_PIN GPIO_PIN(LED1_PORT_NUM, LED1_PIN_NUM)
|
|
|
|
# define LED1_MASK (1 << LED1_PIN_NUM)
|
2022-09-08 10:57:14 +02:00
|
|
|
# if IS_ACTIVE(LED1_IS_INVERTED)
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED1_ON (LED1_PORT->BSRR = (LED1_MASK << 16))
|
|
|
|
# define LED1_OFF (LED1_PORT->BSRR = LED1_MASK)
|
2022-09-08 10:57:14 +02:00
|
|
|
# else
|
|
|
|
# define LED1_ON (LED1_PORT->BSRR = LED1_MASK)
|
|
|
|
# define LED1_OFF (LED1_PORT->BSRR = (LED1_MASK << 16))
|
2022-08-08 09:55:20 +02:00
|
|
|
# endif
|
|
|
|
# define LED1_TOGGLE (LED1_PORT->ODR ^= LED1_MASK)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(LED2_PORT_NUM) && defined (LED2_PIN_NUM)
|
drivers/periph_gpio_ll: change API to access GPIO ports
The API was based on the assumption that GPIO ports are mapped in memory
sanely, so that a `GPIO_PORT(num)` macro would work allow for constant
folding when `num` is known and still be efficient when it is not.
Some MCUs, however, will need a look up tables to efficiently translate
GPIO port numbers to the port's base address. This will prevent the use
of such a `GPIO_PORT(num)` macro in constant initializers.
As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros
for each GPIO port present (regardless of MCU naming scheme), as well as
`GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port
naming scheme uses letters rather than numbers.
These can be defined as macros to the peripheral base address even when
those are randomly mapped into the address space. In addition, a C
function `gpio_port()` replaces the role of the `GPIO_PORT()` and
`gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will
still be implemented as efficient as possible and will allow constant
folding where it was formerly possible. Hence, there is no downside for
MCUs with sane peripheral memory mapping, but it is highly beneficial
for the crazy ones.
There are also two benefits for the non-crazy MCUs:
1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>`
- This directly benefits the test in `tests/periph/gpio_ll`, which
can now provide a valid GPIO port for each and every board
- Writing to invalid memory mapped I/O addresses was treated as
triggering undefined behavior by the compiler and used as a
optimization opportunity
2. We can now detect at compile time if the naming scheme of the MCU
uses letters or numbers, and produce more user friendly output.
- This is directly applied in the test app
2024-04-29 13:32:24 +02:00
|
|
|
# define LED2_PORT ((GPIO_TypeDef *)gpio_port(LED2_PORT_NUM))
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED2_PIN GPIO_PIN(LED2_PORT_NUM, LED2_PIN_NUM)
|
|
|
|
# define LED2_MASK (1 << LED2_PIN_NUM)
|
2022-09-08 10:57:14 +02:00
|
|
|
# if IS_ACTIVE(LED2_IS_INVERTED)
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED2_ON (LED2_PORT->BSRR = (LED2_MASK << 16))
|
|
|
|
# define LED2_OFF (LED2_PORT->BSRR = LED2_MASK)
|
2022-09-08 10:57:14 +02:00
|
|
|
# else
|
|
|
|
# define LED2_ON (LED2_PORT->BSRR = LED2_MASK)
|
|
|
|
# define LED2_OFF (LED2_PORT->BSRR = (LED2_MASK << 16))
|
2022-08-08 09:55:20 +02:00
|
|
|
# endif
|
|
|
|
# define LED2_TOGGLE (LED2_PORT->ODR ^= LED2_MASK)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(LED3_PORT_NUM) && defined (LED3_PIN_NUM)
|
drivers/periph_gpio_ll: change API to access GPIO ports
The API was based on the assumption that GPIO ports are mapped in memory
sanely, so that a `GPIO_PORT(num)` macro would work allow for constant
folding when `num` is known and still be efficient when it is not.
Some MCUs, however, will need a look up tables to efficiently translate
GPIO port numbers to the port's base address. This will prevent the use
of such a `GPIO_PORT(num)` macro in constant initializers.
As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros
for each GPIO port present (regardless of MCU naming scheme), as well as
`GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port
naming scheme uses letters rather than numbers.
These can be defined as macros to the peripheral base address even when
those are randomly mapped into the address space. In addition, a C
function `gpio_port()` replaces the role of the `GPIO_PORT()` and
`gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will
still be implemented as efficient as possible and will allow constant
folding where it was formerly possible. Hence, there is no downside for
MCUs with sane peripheral memory mapping, but it is highly beneficial
for the crazy ones.
There are also two benefits for the non-crazy MCUs:
1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>`
- This directly benefits the test in `tests/periph/gpio_ll`, which
can now provide a valid GPIO port for each and every board
- Writing to invalid memory mapped I/O addresses was treated as
triggering undefined behavior by the compiler and used as a
optimization opportunity
2. We can now detect at compile time if the naming scheme of the MCU
uses letters or numbers, and produce more user friendly output.
- This is directly applied in the test app
2024-04-29 13:32:24 +02:00
|
|
|
# define LED3_PORT ((GPIO_TypeDef *)gpio_port(LED3_PORT_NUM))
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED3_PIN GPIO_PIN(LED3_PORT_NUM, LED3_PIN_NUM)
|
|
|
|
# define LED3_MASK (1 << LED3_PIN_NUM)
|
2022-09-08 10:57:14 +02:00
|
|
|
# if IS_ACTIVE(LED3_IS_INVERTED)
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED3_ON (LED3_PORT->BSRR = (LED3_MASK << 16))
|
|
|
|
# define LED3_OFF (LED3_PORT->BSRR = LED3_MASK)
|
2022-09-08 10:57:14 +02:00
|
|
|
# else
|
|
|
|
# define LED3_ON (LED3_PORT->BSRR = LED3_MASK)
|
|
|
|
# define LED3_OFF (LED3_PORT->BSRR = (LED3_MASK << 16))
|
2022-08-08 09:55:20 +02:00
|
|
|
# endif
|
|
|
|
# define LED3_TOGGLE (LED3_PORT->ODR ^= LED3_MASK)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(LED4_PORT_NUM) && defined (LED4_PIN_NUM)
|
drivers/periph_gpio_ll: change API to access GPIO ports
The API was based on the assumption that GPIO ports are mapped in memory
sanely, so that a `GPIO_PORT(num)` macro would work allow for constant
folding when `num` is known and still be efficient when it is not.
Some MCUs, however, will need a look up tables to efficiently translate
GPIO port numbers to the port's base address. This will prevent the use
of such a `GPIO_PORT(num)` macro in constant initializers.
As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros
for each GPIO port present (regardless of MCU naming scheme), as well as
`GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port
naming scheme uses letters rather than numbers.
These can be defined as macros to the peripheral base address even when
those are randomly mapped into the address space. In addition, a C
function `gpio_port()` replaces the role of the `GPIO_PORT()` and
`gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will
still be implemented as efficient as possible and will allow constant
folding where it was formerly possible. Hence, there is no downside for
MCUs with sane peripheral memory mapping, but it is highly beneficial
for the crazy ones.
There are also two benefits for the non-crazy MCUs:
1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>`
- This directly benefits the test in `tests/periph/gpio_ll`, which
can now provide a valid GPIO port for each and every board
- Writing to invalid memory mapped I/O addresses was treated as
triggering undefined behavior by the compiler and used as a
optimization opportunity
2. We can now detect at compile time if the naming scheme of the MCU
uses letters or numbers, and produce more user friendly output.
- This is directly applied in the test app
2024-04-29 13:32:24 +02:00
|
|
|
# define LED4_PORT ((GPIO_TypeDef *)gpio_port(LED4_PORT_NUM))
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED4_PIN GPIO_PIN(LED4_PORT_NUM, LED4_PIN_NUM)
|
|
|
|
# define LED4_MASK (1 << LED4_PIN_NUM)
|
2022-09-08 10:57:14 +02:00
|
|
|
# if IS_ACTIVE(LED4_IS_INVERTED)
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED4_ON (LED4_PORT->BSRR = (LED4_MASK << 16))
|
|
|
|
# define LED4_OFF (LED4_PORT->BSRR = LED4_MASK)
|
2022-09-08 10:57:14 +02:00
|
|
|
# else
|
|
|
|
# define LED4_ON (LED4_PORT->BSRR = LED4_MASK)
|
|
|
|
# define LED4_OFF (LED4_PORT->BSRR = (LED4_MASK << 16))
|
2022-08-08 09:55:20 +02:00
|
|
|
# endif
|
|
|
|
# define LED4_TOGGLE (LED4_PORT->ODR ^= LED4_MASK)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(LED5_PORT_NUM) && defined (LED5_PIN_NUM)
|
drivers/periph_gpio_ll: change API to access GPIO ports
The API was based on the assumption that GPIO ports are mapped in memory
sanely, so that a `GPIO_PORT(num)` macro would work allow for constant
folding when `num` is known and still be efficient when it is not.
Some MCUs, however, will need a look up tables to efficiently translate
GPIO port numbers to the port's base address. This will prevent the use
of such a `GPIO_PORT(num)` macro in constant initializers.
As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros
for each GPIO port present (regardless of MCU naming scheme), as well as
`GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port
naming scheme uses letters rather than numbers.
These can be defined as macros to the peripheral base address even when
those are randomly mapped into the address space. In addition, a C
function `gpio_port()` replaces the role of the `GPIO_PORT()` and
`gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will
still be implemented as efficient as possible and will allow constant
folding where it was formerly possible. Hence, there is no downside for
MCUs with sane peripheral memory mapping, but it is highly beneficial
for the crazy ones.
There are also two benefits for the non-crazy MCUs:
1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>`
- This directly benefits the test in `tests/periph/gpio_ll`, which
can now provide a valid GPIO port for each and every board
- Writing to invalid memory mapped I/O addresses was treated as
triggering undefined behavior by the compiler and used as a
optimization opportunity
2. We can now detect at compile time if the naming scheme of the MCU
uses letters or numbers, and produce more user friendly output.
- This is directly applied in the test app
2024-04-29 13:32:24 +02:00
|
|
|
# define LED5_PORT ((GPIO_TypeDef *)gpio_port(LED5_PORT_NUM))
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED5_PIN GPIO_PIN(LED5_PORT_NUM, LED5_PIN_NUM)
|
|
|
|
# define LED5_MASK (1 << LED5_PIN_NUM)
|
2022-09-08 10:57:14 +02:00
|
|
|
# if IS_ACTIVE(LED5_IS_INVERTED)
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED5_ON (LED5_PORT->BSRR = (LED5_MASK << 16))
|
|
|
|
# define LED5_OFF (LED5_PORT->BSRR = LED5_MASK)
|
2022-09-08 10:57:14 +02:00
|
|
|
# else
|
|
|
|
# define LED5_ON (LED5_PORT->BSRR = LED5_MASK)
|
|
|
|
# define LED5_OFF (LED5_PORT->BSRR = (LED5_MASK << 16))
|
2022-08-08 09:55:20 +02:00
|
|
|
# endif
|
|
|
|
# define LED5_TOGGLE (LED5_PORT->ODR ^= LED5_MASK)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(LED6_PORT_NUM) && defined (LED6_PIN_NUM)
|
drivers/periph_gpio_ll: change API to access GPIO ports
The API was based on the assumption that GPIO ports are mapped in memory
sanely, so that a `GPIO_PORT(num)` macro would work allow for constant
folding when `num` is known and still be efficient when it is not.
Some MCUs, however, will need a look up tables to efficiently translate
GPIO port numbers to the port's base address. This will prevent the use
of such a `GPIO_PORT(num)` macro in constant initializers.
As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros
for each GPIO port present (regardless of MCU naming scheme), as well as
`GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port
naming scheme uses letters rather than numbers.
These can be defined as macros to the peripheral base address even when
those are randomly mapped into the address space. In addition, a C
function `gpio_port()` replaces the role of the `GPIO_PORT()` and
`gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will
still be implemented as efficient as possible and will allow constant
folding where it was formerly possible. Hence, there is no downside for
MCUs with sane peripheral memory mapping, but it is highly beneficial
for the crazy ones.
There are also two benefits for the non-crazy MCUs:
1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>`
- This directly benefits the test in `tests/periph/gpio_ll`, which
can now provide a valid GPIO port for each and every board
- Writing to invalid memory mapped I/O addresses was treated as
triggering undefined behavior by the compiler and used as a
optimization opportunity
2. We can now detect at compile time if the naming scheme of the MCU
uses letters or numbers, and produce more user friendly output.
- This is directly applied in the test app
2024-04-29 13:32:24 +02:00
|
|
|
# define LED6_PORT ((GPIO_TypeDef *)gpio_port(LED6_PORT_NUM))
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED6_PIN GPIO_PIN(LED6_PORT_NUM, LED6_PIN_NUM)
|
|
|
|
# define LED6_MASK (1 << LED6_PIN_NUM)
|
2022-09-08 10:57:14 +02:00
|
|
|
# if IS_ACTIVE(LED6_IS_INVERTED)
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED6_ON (LED6_PORT->BSRR = (LED6_MASK << 16))
|
|
|
|
# define LED6_OFF (LED6_PORT->BSRR = LED6_MASK)
|
2022-09-08 10:57:14 +02:00
|
|
|
# else
|
|
|
|
# define LED6_ON (LED6_PORT->BSRR = LED6_MASK)
|
|
|
|
# define LED6_OFF (LED6_PORT->BSRR = (LED6_MASK << 16))
|
2022-08-08 09:55:20 +02:00
|
|
|
# endif
|
|
|
|
# define LED6_TOGGLE (LED6_PORT->ODR ^= LED6_MASK)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(LED7_PORT_NUM) && defined (LED7_PIN_NUM)
|
drivers/periph_gpio_ll: change API to access GPIO ports
The API was based on the assumption that GPIO ports are mapped in memory
sanely, so that a `GPIO_PORT(num)` macro would work allow for constant
folding when `num` is known and still be efficient when it is not.
Some MCUs, however, will need a look up tables to efficiently translate
GPIO port numbers to the port's base address. This will prevent the use
of such a `GPIO_PORT(num)` macro in constant initializers.
As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros
for each GPIO port present (regardless of MCU naming scheme), as well as
`GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port
naming scheme uses letters rather than numbers.
These can be defined as macros to the peripheral base address even when
those are randomly mapped into the address space. In addition, a C
function `gpio_port()` replaces the role of the `GPIO_PORT()` and
`gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will
still be implemented as efficient as possible and will allow constant
folding where it was formerly possible. Hence, there is no downside for
MCUs with sane peripheral memory mapping, but it is highly beneficial
for the crazy ones.
There are also two benefits for the non-crazy MCUs:
1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>`
- This directly benefits the test in `tests/periph/gpio_ll`, which
can now provide a valid GPIO port for each and every board
- Writing to invalid memory mapped I/O addresses was treated as
triggering undefined behavior by the compiler and used as a
optimization opportunity
2. We can now detect at compile time if the naming scheme of the MCU
uses letters or numbers, and produce more user friendly output.
- This is directly applied in the test app
2024-04-29 13:32:24 +02:00
|
|
|
# define LED7_PORT ((GPIO_TypeDef *)gpio_port(LED7_PORT_NUM))
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED7_PIN GPIO_PIN(LED7_PORT_NUM, LED7_PIN_NUM)
|
|
|
|
# define LED7_MASK (1 << LED7_PIN_NUM)
|
2022-09-08 10:57:14 +02:00
|
|
|
# if IS_ACTIVE(LED7_IS_INVERTED)
|
2022-08-08 09:55:20 +02:00
|
|
|
# define LED7_ON (LED7_PORT->BSRR = (LED7_MASK << 16))
|
|
|
|
# define LED7_OFF (LED7_PORT->BSRR = LED7_MASK)
|
2022-09-08 10:57:14 +02:00
|
|
|
# else
|
|
|
|
# define LED7_ON (LED7_PORT->BSRR = LED7_MASK)
|
|
|
|
# define LED7_OFF (LED7_PORT->BSRR = (LED7_MASK << 16))
|
2022-08-08 09:55:20 +02:00
|
|
|
# endif
|
|
|
|
# define LED7_TOGGLE (LED7_PORT->ODR ^= LED7_MASK)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/** @} */
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* STM32_LEDS_H */
|
|
|
|
/** @} */
|