mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
cpu/stm32/periph_gpio_ll: Fix and clean up
The separate Schmitt trigger bit in the configuration is dropped, as the Schmitt trigger is only every disabled when in `GPIO_DISCONNECT` mode. So no need to encode the same information twice. The `gpio_state_t` is improved to be a bitmask that holds the MODER register value and a flag indicating whether open-drain mode should be enabled. Finally, `GPIO_DISCONNECT` is implemented. This is done by placing the GPIO in analog mode, which by disabling the Schmitt trigger reduces power consumption.
This commit is contained in:
parent
447493e719
commit
6028097132
@ -102,14 +102,33 @@ typedef enum {
|
||||
GPIO_TRIGGER_LEVEL_LOW = GPIO_TRIGGER_LEVEL | GPIO_TRIGGER_EDGE_FALLING,
|
||||
} gpio_irq_trig_t;
|
||||
|
||||
/**
|
||||
* @brief Possible modes to write to the STM32 GPIOx MODER register
|
||||
*/
|
||||
typedef enum {
|
||||
GPIOX_MODER_INPUT = 0x0, /**< Pin is used as input (reset value) */
|
||||
GPIOX_MODER_OUTPUT = 0x1, /**< Pin is used as output */
|
||||
GPIOX_MODER_AF = 0x2, /**< Pin is routed to peripheral (alternate function) */
|
||||
GPIOX_MODER_ANALOG = 0x3, /**< Pin is in analog mode (least current leakage) */
|
||||
} gpiox_moder_t;
|
||||
|
||||
/**
|
||||
* @brief Check if gpio_state_t requires open drain mode
|
||||
*/
|
||||
#define GPIO_STATE_T_OPEN_DRAIN_FLAG 0x4
|
||||
/**
|
||||
* @brief Bitmask to extract moder config
|
||||
*/
|
||||
#define GPIO_STATE_T_MODER_Msk 0x3
|
||||
|
||||
#define HAVE_GPIO_STATE_T
|
||||
typedef enum {
|
||||
GPIO_OUTPUT_PUSH_PULL,
|
||||
GPIO_OUTPUT_OPEN_DRAIN,
|
||||
GPIO_OUTPUT_OPEN_SOURCE,
|
||||
GPIO_INPUT,
|
||||
GPIO_USED_BY_PERIPHERAL,
|
||||
GPIO_DISCONNECT,
|
||||
GPIO_INPUT = GPIOX_MODER_INPUT,
|
||||
GPIO_OUTPUT_PUSH_PULL = GPIOX_MODER_OUTPUT,
|
||||
GPIO_OUTPUT_OPEN_DRAIN = GPIOX_MODER_OUTPUT | GPIO_STATE_T_OPEN_DRAIN_FLAG,
|
||||
GPIO_USED_BY_PERIPHERAL = GPIOX_MODER_AF,
|
||||
GPIO_DISCONNECT = GPIOX_MODER_ANALOG,
|
||||
GPIO_OUTPUT_OPEN_SOURCE = 0x7, /**< not supported */
|
||||
} gpio_state_t;
|
||||
|
||||
#define HAVE_GPIO_PULL_T
|
||||
@ -130,7 +149,7 @@ typedef union gpio_conf_stm32 gpio_conf_t;
|
||||
* @ingroup drivers_periph_gpio_ll
|
||||
*/
|
||||
union gpio_conf_stm32 {
|
||||
uint16_t bits; /**< the raw bits */
|
||||
uint8_t bits; /**< the raw bits */
|
||||
struct {
|
||||
/**
|
||||
* @brief State of the pin
|
||||
@ -150,18 +169,6 @@ union gpio_conf_stm32 {
|
||||
* configured to @ref GPIO_OUTPUT_PUSH_PULL or @ref GPIO_OUTPUT_OPEN_DRAIN.
|
||||
*/
|
||||
gpio_slew_t slew_rate : 2;
|
||||
/**
|
||||
* @brief Whether to disable the input Schmitt trigger
|
||||
*
|
||||
* @details This could be called `schmitt_trigger` with inverse
|
||||
* meaning, but the API contract says that additional
|
||||
* members in the structure should have a sane
|
||||
* default when zero.
|
||||
*
|
||||
* This value is ignored *unless* @ref gpio_conf_stm32::state is
|
||||
* configured to @ref GPIO_INPUT.
|
||||
*/
|
||||
bool schmitt_trigger_disabled : 1;
|
||||
/**
|
||||
* @brief Initial value of the output
|
||||
*
|
||||
@ -176,7 +183,6 @@ union gpio_conf_stm32 {
|
||||
* consulted.
|
||||
*/
|
||||
bool initial_value : 1;
|
||||
uint8_t : 7; /*< padding */
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -77,6 +77,22 @@ static inline void print_str(const char *str)
|
||||
# define GPIOAEN RCC_APB2ENR_IOPAEN
|
||||
#endif
|
||||
|
||||
/* Bitmask to extract a mode field of the mode register "MODER".
|
||||
* Note: Some families provide both, hence #elif */
|
||||
#ifdef GPIO_MODER_MODER0_Msk
|
||||
# define MODE_Msk GPIO_MODER_MODER0_Msk
|
||||
#elif GPIO_MODER_MODE0_Msk
|
||||
# define MODE_Msk GPIO_MODER_MODE0_Msk
|
||||
#endif
|
||||
|
||||
/* Number of bits a mode field in the mode register "MODER" is wide.
|
||||
* Note: Some families provide both, hence #elif */
|
||||
#ifdef GPIO_MODER_MODER1_Pos
|
||||
# define MODE_BITS GPIO_MODER_MODER1_Pos
|
||||
#elif GPIO_MODER_MODE1_Pos
|
||||
# define MODE_BITS GPIO_MODER_MODE1_Pos
|
||||
#endif
|
||||
|
||||
static void _init_clock(gpio_port_t port)
|
||||
{
|
||||
periph_clk_en(GPIO_BUS, (GPIOAEN << GPIO_PORT_NUM(port)));
|
||||
@ -90,14 +106,12 @@ static void _init_clock(gpio_port_t port)
|
||||
}
|
||||
|
||||
#if defined(GPIO_MODER_MODER0) || defined(GPIO_MODER_MODE0)
|
||||
static void _set_dir(gpio_port_t port, uint8_t pin, bool output)
|
||||
static void _set_mode(gpio_port_t port, uint8_t pin, gpiox_moder_t mode)
|
||||
{
|
||||
GPIO_TypeDef *p = (void *)port;
|
||||
uint32_t tmp = p->MODER;
|
||||
tmp &= ~(0x3 << (2 * pin));
|
||||
if (output) {
|
||||
tmp |= 1UL << (2 * pin);
|
||||
}
|
||||
tmp &= ~(MODE_Msk << (MODE_BITS * pin));
|
||||
tmp |= (unsigned)mode << (MODE_BITS * pin);
|
||||
p->MODER = tmp;
|
||||
}
|
||||
#endif
|
||||
@ -107,15 +121,19 @@ static void _set_dir(gpio_port_t port, uint8_t pin, bool output)
|
||||
static gpio_state_t _get_state(gpio_port_t port, uint8_t pin)
|
||||
{
|
||||
GPIO_TypeDef *p = (void *)port;
|
||||
uint32_t moder = (p->MODER >> (2 * pin)) & 0x3UL;
|
||||
gpiox_moder_t moder = (p->MODER >> (MODE_BITS * pin)) & MODE_Msk;
|
||||
switch (moder) {
|
||||
case 0:
|
||||
case GPIOX_MODER_INPUT:
|
||||
return GPIO_INPUT;
|
||||
case 1:
|
||||
case GPIOX_MODER_OUTPUT:
|
||||
return ((p->OTYPER >> pin) & 0x1UL) ? GPIO_OUTPUT_OPEN_DRAIN
|
||||
: GPIO_OUTPUT_PUSH_PULL;
|
||||
case GPIOX_MODER_ANALOG:
|
||||
return GPIO_DISCONNECT;
|
||||
default:
|
||||
case GPIOX_MODER_AF:
|
||||
return GPIO_USED_BY_PERIPHERAL;
|
||||
}
|
||||
return GPIO_USED_BY_PERIPHERAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -333,10 +351,10 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf)
|
||||
_set_legacy_f1_config(port, pin, conf);
|
||||
#else
|
||||
/* modern STM32 style GPIO configuration register layout */
|
||||
_set_output_type(port, pin, conf.state == GPIO_OUTPUT_OPEN_DRAIN);
|
||||
_set_output_type(port, pin, conf.state & GPIO_STATE_T_OPEN_DRAIN_FLAG);
|
||||
_set_pull_config(port, pin, conf.pull);
|
||||
_set_slew_rate(port, pin, conf.slew_rate);
|
||||
_set_dir(port, pin, conf.state < GPIO_INPUT);
|
||||
_set_mode(port, pin, conf.state & GPIO_STATE_T_MODER_Msk);
|
||||
#endif
|
||||
irq_restore(state);
|
||||
|
||||
@ -386,8 +404,4 @@ void gpio_ll_print_conf(gpio_conf_t conf)
|
||||
gpio_ll_print_conf_common(conf);
|
||||
print_str(", slew: ");
|
||||
print_str(slew_strs[conf.slew_rate]);
|
||||
|
||||
if (conf.schmitt_trigger_disabled) {
|
||||
print_str(", Schmitt trigger disabled");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user