A collection of macros and functions that simplifies defining and using General Purpose I/O pins.
File(s):
Use a minimum compiler optimization level of 1, otherwise code bloat will occur. Even an innocuous C statement such as "PORTB |= (1 << 2);" will result in several redundant assembly instructions at -O0.
A GPIO pin is defined using the PX_GPIO utility macro, e.g.
#define PX_GPIO_LED PX_GPIO(B, 2, PX_GPIO_DIR_OUT, PX_GPIO_INIT_LO)
Now wherever PX_GPIO_LED is found, the C preprocessor will substitute it with the following sequence:
@ PX_GPIO_INIT_LO
Initialize output pin low (0)
@ PX_GPIO_DIR_OUT
Set pin direction to output.
There are 3 ways to use this GPIO driver:
The first way is to use macros that utilize the C preprocessor to resolve to optimal C code before it is fed to the compiler. The disadvantage of this approach is the lack of syntax checking and the obtuse error message that the compiler may generate. The recursive macro magic is demonstrated with an example:
The following code:
#define PX_GPIO_OUT_SET_HI(gpio)
Set GPIO pin output high.
Expands to:
Which reduces to:
#define PX_BIT_SET_HI(var, bit)
Set a bit (1)
Which reduces even further to:
do {PORTB |= (1 << 2);} while(0);
Which the optimizing compiler replaces with a single assembly statement:
Which enables the LED :)
Example:
#include "px_gpio.h"
#define PX_GPIO_LED PX_GPIO(B, 0, PX_GPIO_DIR_OUT, PX_GPIO_INIT_LO)
#define PX_GPIO_PB PX_GPIO(D, 7, PX_GPIO_DIR_IN, PX_GPIO_INIT_PULL_UP)
int main(void)
{
while(true)
{
{
}
else
{
}
}
}
#define PX_GPIO_INIT(gpio)
Initialise a GPIO pin.
#define PX_GPIO_IN_IS_LO(gpio)
Test if GPIO pin input is low.
#define PX_GPIO_OUT_SET_LO(gpio)
Set GPIO pin output low.
Even though it appears that functions calls are used, the lines reduce to single assembly statements for maximum efficiency and minimum code size:
7a: 28 98 cbi 0x05, 0 ; 5
7c: 20 9a sbi 0x04, 0 ; 4
7e: 5f 9a sbi 0x0b, 7 ; 11
80: 57 98 cbi 0x0a, 7 ; 10
while(true)
{
82: 4f 99 sbic 0x09, 7 ; 9
84: 02 c0 rjmp .+4 ; 0x8a <main+0x10>
{
86: 28 9a sbi 0x05, 0 ; 5
88: fc cf rjmp .-8 ; 0x82 <main+0x8>
}
else
{
8a: 28 98 cbi 0x05, 0 ; 5
8c: fa cf rjmp .-12 ; 0x82 <main+0x8>
The second method is to declare the GPIO pin info as a 'static const' structure in an H file and use inline C functions. If the compiler optimisation is enabled then the code will also resolve to (mostly) single assembly statements during compile time.
Don't forget to prefix 'static const'! The compiler must know that the GPIO pin data will never change so that it can make the best optimization decisions.
Example (in an H file):
#define PX_GPIO_LED PX_GPIO(B, 2, PX_GPIO_DIR_OUT, PX_GPIO_INIT_LO)
static const px_gpio_t px_gpio_led = {PX_GPIO_LED};
static inline void led_enable(void)
{
}
void px_gpio_out_set_hi(const px_gpio_handle_t *gpio)
Set GPIO pin output high.
Example:
#include "px_gpio.h"
#define PX_GPIO_LED PX_GPIO(B, 0, PX_GPIO_DIR_OUT, PX_GPIO_INIT_LO)
#define PX_GPIO_PB PX_GPIO(D, 6, PX_GPIO_DIR_IN, PX_GPIO_INIT_PULL_UP)
int main(void)
{
while(true)
{
{
}
else
{
}
}
}
void px_gpio_out_set_lo(const px_gpio_handle_t *gpio)
Set GPIO pin output low.
bool px_gpio_in_is_lo(const px_gpio_handle_t *gpio)
Test if GPIO pin input is low.
void px_gpio_init(const px_gpio_handle_t *gpio)
Initialise a GPIO pin using supplied handle.
GPIO pin handle definition.
The third method is to declare a GPIO pin as a dynamic structure that can change by the code while it is executing. This is useful where GPIO pin mapping must be changed on the fly.
Example (in a C file):
#define PX_GPIO_LED PX_GPIO(B, 2, PX_GPIO_DIR_OUT, PX_GPIO_INIT_LO)
px_gpio_t px_gpio_led;
void led_init(bool led_on)
{
if(led_on)
{
}
}
void px_gpio_open(px_gpio_handle_t *gpio, px_gpio_reg_t port, px_gpio_reg_t ddr, px_gpio_reg_t pin, uint8_t bit, uint8_t dir, uint8_t init)
Initialise a GPIO structure.
◆ px_gpio_handle_t
GPIO pin handle definition.
Definition at line 113 of file px_gpio.h.
| Data Fields |
|
GPIO_TypeDef * |
gpio_base_reg |
GPIO peripheral base register address. |
|
uint8_t |
pin |
Pin: 0, 1, 2, ..., or 15. |
|
px_gpio_mode_t |
mode |
Mode: Input, Output, Alternative Function or Analog. |
|
px_gpio_otype_t |
otype |
Output type: push-pull or open-drain. |
|
px_gpio_ospeed_t |
ospeed |
Output speed: low, medium, high or very high. |
|
px_gpio_pull_t |
pull |
None, pull-up or pull-down. |
|
px_gpio_out_init_t |
out_init |
Initial output value: Low (0) or high (1) |
|
px_gpio_af_t |
af |
Alternative function: AF0, AF1, ... or AF7. |
|
px_gpio_reg_t |
port |
PORTx register address. |
|
px_gpio_reg_t |
ddr |
DDRx register address. |
|
px_gpio_reg_t |
pin |
PINx register address. |
|
uint8_t |
bit |
Bit: 0, 1, 2, 3, 4, 5, 6 or 7. |
|
uint8_t |
dir |
Direction: PX_GPIO_DIR_OUT or PX_GPIO_DIR_IN. |
|
uint8_t |
init |
Initial value: PX_GPIO_INIT_HI, PX_GPIO_INIT_LO, PX_GPIO_INIT_HIZ or PX_GPIO_INIT_PULL_UP. |
◆ PX_GPIO
| #define PX_GPIO |
( |
|
port, |
|
|
|
bit, |
|
|
|
dir, |
|
|
|
init |
|
) |
| &PORT ## port, &DDR ## port, &PIN ## port, bit, dir, init |
Helper macro to define a GPIO pin.
Usage example:
#define PX_GPIO_LED GPIO(D, 7, PX_GPIO_DIR_OUT, PX_GPIO_INIT_LO)
- Parameters
-
| port | A, B, C, ... |
| bit | 0, 1, 2, 3, 4, 5, 6 or 7 |
| dir | PX_GPIO_DIR_OUT or PX_GPIO_DIR_IN |
| init | PX_GPIO_INIT_HI, PX_GPIO_INIT_LO, PX_GPIO_INIT_HIZ or PX_GPIO_INIT_PULL_UP |
Definition at line 250 of file px_gpio.h.
◆ PX_GPIO_INIT
| #define PX_GPIO_INIT |
( |
|
gpio | ) |
_GPIO_INIT(gpio) |
Initialise a GPIO pin.
Definition at line 254 of file px_gpio.h.
◆ PX_GPIO_OUT_SET_HI
| #define PX_GPIO_OUT_SET_HI |
( |
|
gpio | ) |
_GPIO_OUT_SET_HI(gpio) |
Set GPIO pin output high.
Definition at line 278 of file px_gpio.h.
◆ PX_GPIO_OUT_SET_LO
| #define PX_GPIO_OUT_SET_LO |
( |
|
gpio | ) |
_GPIO_PIN_OUT_SET_LO(gpio) |
Set GPIO pin output low.
Definition at line 282 of file px_gpio.h.
◆ PX_GPIO_OUT_TOGGLE
| #define PX_GPIO_OUT_TOGGLE |
( |
|
gpio | ) |
_GPIO_OUT_TOGGLE(gpio) |
Toggle GPIO pin output.
Definition at line 286 of file px_gpio.h.
◆ PX_GPIO_OUT_IS_HI
| #define PX_GPIO_OUT_IS_HI |
( |
|
gpio | ) |
_GPIO_OUT_IS_HI(gpio) |
Test if GPIO pin output is set high.
Definition at line 290 of file px_gpio.h.
◆ PX_GPIO_OUT_IS_LO
| #define PX_GPIO_OUT_IS_LO |
( |
|
gpio | ) |
_GPIO_OUT_IS_LO(gpio) |
Test if GPIO pin output is set low.
Definition at line 294 of file px_gpio.h.
◆ PX_GPIO_IN_IS_HI
| #define PX_GPIO_IN_IS_HI |
( |
|
gpio | ) |
_GPIO_IN_IS_HI(gpio) |
Test if GPIO pin input is high.
Definition at line 298 of file px_gpio.h.
◆ PX_GPIO_IN_IS_LO
| #define PX_GPIO_IN_IS_LO |
( |
|
gpio | ) |
_GPIO_IN_IS_LO(gpio) |
Test if GPIO pin input is low.
Definition at line 302 of file px_gpio.h.
◆ PX_GPIO_DIR_SET_OUT
| #define PX_GPIO_DIR_SET_OUT |
( |
|
gpio | ) |
_GPIO_DIR_SET_OUT(gpio) |
Set GPIO pin direction to output.
Definition at line 306 of file px_gpio.h.
◆ PX_GPIO_DIR_SET_IN
| #define PX_GPIO_DIR_SET_IN |
( |
|
gpio | ) |
_GPIO_DIR_SET_IN(gpio) |
Set GPIO pin direction to input.
Definition at line 310 of file px_gpio.h.
◆ PX_GPIO_DIR_IS_OUT
| #define PX_GPIO_DIR_IS_OUT |
( |
|
gpio | ) |
_GPIO_DIR_IS_OUT(gpio) |
Test if GPIO pin is configured to be an output.
Definition at line 314 of file px_gpio.h.
◆ PX_GPIO_DIR_IS_IN
| #define PX_GPIO_DIR_IS_IN |
( |
|
gpio | ) |
_GPIO_DIR_IS_IN(gpio) |
Test if GPIO pin is configured to be an input.
Definition at line 318 of file px_gpio.h.
◆ PX_GPIO_PULL_UP_ENABLE
| #define PX_GPIO_PULL_UP_ENABLE |
( |
|
gpio | ) |
_GPIO_PULL_UP_ENABLE(gpio) |
Enable pull-up on GPIO pin.
Definition at line 322 of file px_gpio.h.
◆ PX_GPIO_PULL_DISABLE
| #define PX_GPIO_PULL_DISABLE |
( |
|
gpio | ) |
_GPIO_PULL_DISABLE(gpio) |
Disable pull-up on GPIO pin.
Definition at line 326 of file px_gpio.h.
◆ PX_GPIO_INIT_DDR
| #define PX_GPIO_INIT_DDR |
( |
|
gpio | ) |
_GPIO_INIT_DDR(gpio) |
Macro to calculate bit mask used to initialise DDR register.
Definition at line 330 of file px_gpio.h.
◆ PX_GPIO_INIT_PORT
| #define PX_GPIO_INIT_PORT |
( |
|
gpio | ) |
_GPIO_INIT_PORT(gpio) |
Macro to calculate bit mask used to initialise PORT register.
Definition at line 334 of file px_gpio.h.
◆ px_gpio_reg_t
GPIO peripheral register address definition.
Definition at line 215 of file px_gpio.h.
◆ px_gpio_dir_t
GPIO dir selection.
| Enumerator |
|---|
| PX_GPIO_DIR_IN | Set pin direction to input.
|
| PX_GPIO_DIR_OUT | Set pin direction to output.
|
Definition at line 199 of file px_gpio.h.
◆ px_gpio_init_t
GPIO init selection.
| Enumerator |
|---|
| PX_GPIO_INIT_LO | Initialize output pin low (0)
|
| PX_GPIO_INIT_HI | Initialize output pin high (1)
|
| PX_GPIO_INIT_HIZ | Initialize input pin as high impedance (no pull-up)
|
| PX_GPIO_INIT_PULL_UP | Initialize input pin with pull-up enabled.
|
Definition at line 206 of file px_gpio.h.
◆ px_gpio_open()
Initialise a GPIO structure.
- Parameters
-
| [out] | gpio | px_gpio_t structure |
| [in] | port | PORTx register address, e.g. &PORTB |
| [in] | ddr | DDRx register address, e.g. &DDRB |
| [in] | pin | PINx register address, e.g. &PINB |
| [in] | bit | Bit: 0, 1, 2, 3, 4, 5, 6 or 7 |
| [in] | dir | Direction: PX_GPIO_DIR_OUT or PX_GPIO_DIR_IN |
| [in] | init | Initial value: PX_GPIO_INIT_HI, PX_GPIO_INIT_LO, PX_GPIO_INIT_HIZ or PX_GPIO_INIT_PULL_UP |
Example:
Definition at line 358 of file px_gpio.h.
◆ px_gpio_init()
Initialise a GPIO pin.
Initialise a GPIO pin using supplied handle.
Definition at line 375 of file px_gpio.h.
◆ px_gpio_init_ddr()
Calculate bit mask used to initialise DDR register.
Definition at line 396 of file px_gpio.h.
◆ px_gpio_init_port()
Calculate bit mask used to initialise PORT register.
Definition at line 402 of file px_gpio.h.
◆ px_gpio_out_set_hi()
Set GPIO pin output high.
Definition at line 408 of file px_gpio.h.
◆ px_gpio_out_set_lo()
Set GPIO pin output low.
Definition at line 414 of file px_gpio.h.
◆ px_gpio_out_toggle()
Toggle GPIO pin output.
Definition at line 420 of file px_gpio.h.
◆ px_gpio_out_is_hi()
Test if GPIO pin output is set high.
Definition at line 426 of file px_gpio.h.
◆ px_gpio_out_is_lo()
Test if GPIO pin output is set low.
Definition at line 432 of file px_gpio.h.
◆ px_gpio_in_is_hi()
Test if GPIO pin input is high.
Definition at line 438 of file px_gpio.h.
◆ px_gpio_in_is_lo()
Test if GPIO pin input is low.
Definition at line 444 of file px_gpio.h.
◆ px_gpio_dir_set_out()
Set GPIO pin direction to output.
Definition at line 450 of file px_gpio.h.
◆ px_gpio_dir_set_in()
Set GPIO pin direction to input.
Definition at line 456 of file px_gpio.h.
◆ px_gpio_dir_is_out()
Test if GPIO pin is configured to be an output.
Definition at line 462 of file px_gpio.h.
◆ px_gpio_dir_is_in()
Test if GPIO pin is configured to be an input.
Definition at line 468 of file px_gpio.h.
◆ px_gpio_pull_up_enable()
Enable pull-up on GPIO pin.
Definition at line 474 of file px_gpio.h.
◆ px_gpio_pull_up_disable()
Disable pull-up on GPIO pin.
Definition at line 480 of file px_gpio.h.