Currently the GPIO API implementation is Raspberry Pi specific, as delivering a generic GPIO API that can be used across the hardware RTEMS supports demands more community input and care. The API design is based on the cpukit/libi2c API, which is the RTEMS API for the I2C and SPI communication buses, while trying to keep multiio in mind. Right now it is just an header file that defines the data structures and function prototypes, leaving the implementation to the Raspberry Pi BSP. This header must then by included in an application, which then calls the needed directives to operate the GPIO hardware.
The first directive to call is the rtems_gpio_initialize, which receives the total amount of GPIO pins on the target hardware. This function sets a flag indicating that the API has been initialized so further calls can silently exit the function. It then proceds to allocate memory to an array of structs (rtems_gpio_pin) which will contain info for every pin, and sets each of them as not being used. The access to a pin is done through the array index. For instance, to get info on the first pin on the board (pin 1), the corresponding array index will be 0. This numbering conversion is done on the directives and not the application, so the application uses the board pin number.
At this point the application must setup the GPIO pins it wants to use. This requires a pin number to identify the pin and a pin type or function, such as:
- digital output;
- digital input;
- one of 6 alternative functions, which are hardware specific and managed by the BSP implementation of the API. The API only provides these generic types that can be used by a BSP to use some specific non-standard function to a GPIO pin, such as configuring a GPIO pin to behave as a general purpose clock, or as a receiver for an UART interface;
- not used.
To select a pin to be used two directives can be called:
rtems_gpio_select_pin -> receives a pin number (its number on the board hardware) and the pin function. The function takes this information to get the pin select memory address and proceds to select the specified function to that pin on the hardware, while updating the GPIO pin array with the information that the said pin is no longer available to selection because it is now in use.
rtems_gpio_setup_input_mode -> this function receives an array of structures (rtems_gpio_configuration) that define a number of pins and their corresponding function, and calls rtems_gpio_select_pin for each of them. This allows a BSP to define specific GPIO configurations that are useful to that target than can then be easily used by an application.
The Raspberry Pi BSP defines a structure on include/gpio.h to setup a JTAG interface using GPIO pins (https://github.com/asuol/rtems/blob/GPIO_API/c/src/lib/libbsp/arm/raspberrypi/include/gpio.h).
The API also allows a pin to be disabled, using:
rtems_gpio_disable_pin -> This directive marks a pin as not used, so it can be selected to another function.
The API only provides directives to operate digital I/O pins.
rtems_gpio_set -> Writes a logical 1 to an output pin
rtems_gpio_clear -> Writes a logical 0 to an output pin
The API further provides the following functions, which may not apply to the Raspberry Pi:
rtems_gpio_set_mb and rtems_gpio_clear_mb -> Sets and clears multiple output pins in a GPIO port. A GPIO port is a group of pins that can be operated as one entity, so this function allows to operate a GPIO port as such. While this is useful for targets that organize their GPIO pins in groups, the Raspberry Pi does not, so it was not implemented.
rtems_gpio_output_mode -> Defines the output pin operating mode. This can range from:
- push-pull – Defines that the pin can both source and sink current;
- open drain – Defines that the pin can only sink current;
- neutral – No drive mode defined.
Because the Raspberry Pi documentation  does not refer any of these modes, this function was not implemented for the Raspberry Pi, but can be useful to other targets.
rtems_gpio_get_val -> Reads an input pin logic value, or level.
rtems_gpio_input_mode -> Sets an input drive mode, which means to operate the internal pull resistor.
A pull resistor “pulls” the pin voltage either up (to 3.3v) to create a logical 1, or down (to 0v) to create a logical 0. If a pull resistor is not used the pin voltage can float, due to a number of random factors , which would cause unexpected behaviour, as logical ones and zeros could be randomly generated.
The input drive modes available on the API are:
- Pull up – Enables the internal pull up resistor;
- Pull down – Enables the internal pull down resistor;
- No pull resistor – Disables the internal pull resistors. This can be the case where an external one is used.
rtems_gpio_setup_input_mode -> This function allows to set the drive mode of a number of GPIO input pins.
The implementation of the above can be found on:
The Raspberry Pi implementation of the API -> https://github.com/asuol/rtems/blob/GPIO_API/c/src/lib/libbsp/arm/raspberrypi/gpio/libgpio.c