GPIO Support on STM32F processors — Details


#include <cyg/hal/hal_io.h>

cyg_uint32 pin = CYGHWR_HAL_STM32_PIN_OUT( port , bit , ppod , pupd , speed );

cyg_uint32 pin = CYGHWR_HAL_STM32_PIN_ALTFN_OUT( port , bit , af , ppod , pupd , speed );

cyg_uint32 pin = CYGHWR_HAL_STM32_PIN_IN( port , bit , pupd );

cyg_uint32 pin = CYGHWR_HAL_STM32_PIN_ALTFN_IN( port , bit , af , ppod , pupd );

cyg_uint32 pin = CYGHWR_HAL_STM32_PIN_ANALOG( port , bit );


CYGHWR_HAL_STM32_GPIO_OUT ( pin , val );

CYGHWR_HAL_STM32_GPIO_IN ( pin , val );


The STM32 HAL provides a number of macros to support the encoding of GPIO pin identity and configuration into a single 32 bit descriptor. This is useful to drivers and other packages that need to configure and use different lines for different devices.

A descriptor is created with one of the 5 variants depending on how the pin is to be used: CYGHWR_HAL_STM32_PIN_IN defines the pin as an input whose value can be accessed by the user using the macro CYGHWR_HAL_STM32_GPIO_IN (see later) CYGHWR_HAL_STM32_PIN_OUT defines the pin as an output where the user can set the pin output value with the macro CYGHWR_HAL_STM32_GPIO_OUT (see later); CYGHWR_HAL_STM32_PIN_ALTFN_OUT and CYGHWR_HAL_STM32_PIN_ALTFN_IN are used to define a pin that will be controlled by an on-chip peripheral; or CYGHWR_HAL_STM32_PIN_ANALOG which means it can be used as an input to the ADC peripheral or an output from the DAC peripheral.

The distinction between the CYGHWR_HAL_STM32_PIN_ALTFN_OUT and CYGHWR_HAL_STM32_PIN_ALTFN_IN is purely whether a speed parameter is required, since both macros define a pin that will be controlled by an on-chip peripheral. This distinction is required to provide simpler F1 family support for its different alternative I/O mapping implementation.

The 5 variants take a subset of arguments from the following list:

This identifies the GPIO port to which the pin is attached. Ports are identified by letters from A to I.
This gives the bit or pin number within the port. These are numbered from 0 to 15.

For the ALTFN macros this parameter indicates which on-chip peripheral is used to control the pin. Consult ST's documentation for the specific processor model to determine which peripheral number is used to select the peripheral for the required pin mapping.

This field is not-relevant to, and hence ignored by, the F1 family of devices where the alternative AFIO configuration mechanism is used.

If this is an output pin (either GPIO output or driven by a peripheral), this setting indicates whether it should be driven in push-pull mode (PUSHPULL) or open-drain mode (OPENDRAIN). If the pin is not an output pin, this value is unused, but for clarity can be given the setting NA.
If this is an input pin, or an output pin configured in open-drain mode (whether controlled by GPIO or a peripheral), this setting can be used to indicate whether a weak pull-up resistor (PULLUP) is used, or a weak pull-down resistor (PULLDOWN) is used. If neither are to be used, then a value of NONE can be given. For F1 family devices the value FLOATING can be used to identify a floating input, which is synonomous with NONE for F2/F4 family devices.

This setting indicates the output speed for GPIO outputs. At time of writing, the speeds for F1 parts can be 2MHz, 10MHz or 50MHz and for F2/F4 parts can be 2MHz, 25MHz, 50Mhz, 100MHz with 30pF capacitance or 80MHz with 15pF capacitance. It is possible to indicate the desired speed by passing in the generic values LOW, MED, FAST, or HIGH.

For F1 family devices these are synonymous with using values of 2MHZ, 25MHZ, 50MHz or 50MHz respectively (FAST and HIGH being synonyms due to the 50MHz limit on F1 family devices).

For F2/F4 family devices these are synonymous with using values of 2MHZ, 25MHZ, or 50MHz respectively, with no corresponding value for HIGH due to its variable nature.

In order to make these definitions more future-proof and abstract, it is therefore strongly recommended to use this form of setting instead: AT_LEAST(mhz) to indicate the next speed rating above the supplied speed (in MHz); and analogously, AT_MOST(mhz) to indicate that the supplied speed in MHz must not be exceeded.

For non-GPIO output pins, a value of NA can be given.

The following examples show how these macros may be used:

// Define port A pin 10 as being controlled by a peripheral which, for
// this pin on F2/F4 devices, is alternate function 7 (and for this
// pin that means USART1), without any pull-ups/pull-downs.
#define CYGHWR_HAL_STM32_UART1_RX               CYGHWR_HAL_STM32_ALTFN_IN( A, 10, 7, NA, NONE )

// Define port B pin 10 as a push-pull output under the control of the
// peripheral which, for this pin on F2/F4 devices, is alternate
// function 7 (and for this pin that means USART3), with an output
// speed of 50MHz or greater.
#define CYGHWR_HAL_STM32_UART3_TX               CYGHWR_HAL_STM32_ALTFN_OUT( B, 10, 7, PUSHPULL, NONE, AT_LEAST(50) )

// Define port A pin 12 as a push-pull output under GPIO control, with no
// pull-ups/pull-downs, with an output speed of 50MHz or greater.

Additionally, the macro CYGHWR_HAL_STM32_GPIO_NONE may be used in place of a pin descriptor and has a value that no valid descriptor can take. It may therefore be used as a placeholder where no GPIO pin is present or to be used. This can be useful when defining pin configurations for a series of instances of a peripheral (e.g. UART ports), but where not all instances support all the same pins (e.g. hardware flow control lines).

The remaining macros all take a suitably constructed GPIO pin descriptor as an argument. CYGHWR_HAL_STM32_GPIO_SET configures the pin according to the descriptor and must be called before any other macros. CYGHWR_HAL_STM32_GPIO_OUT sets the output to the value of the least significant bit of the val argument. The val argument of CYGHWR_HAL_STM32_GPIO_IN should be a pointer to an int, which will be set to 0 if the pin input is zero, and 1 otherwise.

Further helper macros are available, and it is recommended to consult the header file <cyg/hal/var_io_pins.h> (also present in the include subdirectory of the STM32 variant HAL package within the eCos source repository), for the complete list if needed. Ensure you only inspect the relevant sections of this low-level header file when investigating specific F1 and F2/F4 processor family variants.

EXTI wrapper

If a platform implements CYGINT_HAL_STM32_GPIO_EXTI_VECTOR then support for a simple EXTI interrupt handler wrapper is provided. This is used to “hide” the eCos interrupt implementation when supporting callback handlers for interrupt enabled GPIO pins. For almost all STM32 platforms and eCos applications this wrapper functionality is NOT required, and the CYGIMP_HAL_STM32_GPIO_EXTI_VECTOR option should not be enabled.

The interface is exported via manifests that are only defined when the relevant functionality is available. The pin argument is a standard eCos GPIO pin descriptor as described above.

The CYGHWR_HAL_VAR_GPIO_IRQ_INIT() referenced code should be called at a suitable initialisation point either by the platform or the eCos application, prior to enabling a specific source.

When enabling a callback for a GPIO EXTI source the trigger parameter encodes whether the handler is called for rising (CYGHWR_HAL_VAR_IRQ_EDGE_RISE), falling (CYGHWR_HAL_VAR_IRQ_EDGE_FALL), or either (CYGHWR_HAL_VAR_IRQ_EDGE_BOTH), edge events. When the configured event occurs the referenced handler function is called with the supplied arg parameter.

An example use of this functionality is when building eCos WICED applications against an unmodified WICED-SDK source-tree,

The HAL_VAR_EXTI_EVENT_CONFIGURE() code allows for control of EXTI events. The vector is the corresponding EXTI interrupt identifier. The up parameter encodes whether the event is triggered from a rising signal (1) or falling signal (0). The enable parameter defines whether the event is being enabled (1) or disabled (0).

EXTI wrapper API

#include <cyg/hal/hal_io.h>


cyg_bool enabled = CYGHWR_HAL_VAR_GPIO_IRQ_ENABLE(cyg_uint32 pin, cyg_uint8 trigger, cyg_hal_var_gpio_callback_t handler, void *arg);

void CYGHWR_HAL_VAR_GPIO_IRQ_DISABLE(cyg_uint32 pin);

void HAL_VAR_EXTI_EVENT_CONFIGURE(cyg_uint32 vector, cyg_uint32 up, cyg_uint32 enable);