GPIO ports are a collection of GPIO pins. 8051 uP port size is 8 pins. NXP LPC port size is 32 pins. For STM ARM port size is 16. We can say, GPIO port is 16-bit wide and each bit corresponds to the pin.
What is the internal circuitry for GPIO?
The enable line decides (which is configured using registers) whether the pin will be used as Output or input. If selected output, the circuitry for th output buffer and input buffer :
When we write 0, the pmos gets activated and the pin goes to Vcc while it goes to GND when written1. Mirror image is the input buffer.
By default, all the pins are in HIGH-Z (High Impedance) stage and thus can be read 0 or 1 leadin to leakage current. On enabling any of the pull up or down, the pin doesn't remain in the High-Z stage and thus no leakage current. We can enable these registers by configuring some registers.
Under open-drain (nmos activated) output mode configuration. It is useless until we activate an internal/external pull-up register.
Add pull-up. This configuration can be used to drive LEDs or I2C bus.
By default, the configuration is Push-Pull (Both pmos and nmos present) for output mode (by default they are input). Let's optimize power consumption for GPIO :-
Because, the input voltage is in Indeterminate stage, both the transistors are ON giving a path between Vcc and Gnd and thus a leakage current. This is combat in modern MCU using Schmitt Trigger.
Each GPIO port has a certain set of registers. Minimally, they will have a direction register that decides how the GPIO is used as an input/output/else. Output data reg is to write to the GPIO port. There are many configuration registers available for GPIO ports.
These ports are drivrn by AHB1 bus which has a max clock speed of 168 MHz. Each port has its own set of configuration registers, thus the MCU supports in total 144 i/o pins. Dicovery board gives access to 5 ports that is 80 GPIO pins. STM32F4029-Discovery board gives access
For each GPIO Port, there is a MODER Register. Its offset from base address is 0x00 and for GPIO Port A and B, the reset values aren't 0. The register is 32-bit long. A set of two bits is used to configure a pin of the GPIO. For ex, the register bit 0 and 1 are of GPIO pin-0 and so on upto 15. The pair combination decide the purpose of the pin by default input.
A GPIO pin should have all the functionalitites including input (also as interrupt), output, alternate func (like SPI, I2C) and analog. Only then, can a pin called GPIO (unlike power pins, etc). The internal structure of a GPIO pin in STM32 uC.
INPUT : When the pin is configured as input, only the upper part is on and therefore, the input data register is updated every AHB1 clock cycle because GPIO is connected to AHB1. In Floating Input mode, the pull registers are turned off which is therefore useless. In the data sheet we can find the value of these resistor values. External pull-ups are used when product development circuitry team recommends a resistor value to ensure good efficiency and working.
OUTPUT: Push-pull is the default config and when we write 1. PMOS is ON and the current-sourcing (Outward flow of current from the MCU) occurs while writing 0 means NMOS is ON and the LED diode is in reverse bias, thus no current flows.
Open drain: In this configuration, it is required that we provide a external pull-up because while writing 0. NMOS would be on and thus the output pin is 0. But when 1 is written, the output is open drain. Here if we turn the internal pull-up resistor ON, then the LED won't glow as its resistance is HIGH! (40Kohms). Thus, in open-drain configuration, LED can be switched ON by using external pull-up.
NOTE: In the output mode configuration, the input circuitry is also ON, thus we can read the output pin also.
ALTERNATE Func : In this configuration, the Output control is in the hands of other peripherals. Other peripherals use this pin for there purposes for ex I2C_SDA, USART_CLK. Also, in the read circuitry, the input is read by Alternate Input Function (such as USART_RX), etc.
GPIO Output Type Register : This register decides what is the type of the pin in the OUTPUT mode, be it push-pull or open-drain. Therefore, this register is having 16 bits in reserved and the other 16 bits are used to decide from the two for individual pin of the register.
GPIO Output Speed Register: This register decides the slew rate of the pin that is how fast the transisiton from Low to High or High to Low is happening.
The use of this register is usually ignored but for the advance cases for instance when your MCU doesn't support I2C, then you want to implement I2C using bit-banging and there the I2C demands certain Tfall and Trise time and there you can use it.
GPIO_PUP Data-Register is used to turn on and off the pull-up/pull-down register.
GPIO_IDR: Input data register is used to read from the input pin and thus, only read permission are given for this.
This register is updated in every AHB1 clock cycle.
GPIO_ODR: Output data register where you write the value, either 0 or 1. This pin can also be read.
Summarizing, for a GPIO pin, the available modes are :-
1, Input floating
2. Input pull-up
3. Input pull-down
4. Analog
5. Output-open-drain with pull-up or pull-down.
6. Output-push-pull with pull-up or pull-down.
7. Alternate function with push-pull and pull-up or pull-down.
8. Alternate function with open-drain and pull-up or pull-down.
There are 16 possible combinations available for this configuration. For individual pins, the different functionality modes are available for different purposes :-
Thus if AF0 is selected, this pin will be used MCO1 (Micro-controller Clock 1) and likewise.
To configure a pin to different AF, the alternate function low and alternate function high register available. Low is used to configure the pins from 0 to 7. Each pin is given four slots to decide from the 16 possible combination.
For example to set PA0 to USART4_TX, then and to configure PA0 to AF8, we need to make the GPIOAF low-register for A Port and 0th pin as 1000 (8dec) .
To enable clock for GPIO, we know we have to consult the RCC AHB1ENR register in which we can enable clock for different peripherals.
Device layer exposes various API's to the application layer so that the user is able to control the peripherals to write applications. API (Application program interface) are a set of functions and procedures allowing the creation of applications that access the features or data of an operating system, application, or other service.
Let's begin with writing gpio driver and then test it on some applications. To begin with, let's write device specific header file. In the device specific header file, we have :-
1. Base Addresses of various peripherals (like Flash, SRAM1, SRAM2, ROM,etc)
2. Base addresses of various bus domains like AHB1, APB2,etc
3. Bus addresses of various peripherals hanging on to the various bus domains.
4. Clock enable and disable macros in order to deal with clock management of various peripherals.
5. IRQ definitions : https://sites.google.com/lnmiit.ac.in/manvendrasingh98/projects/embedded-systems/mcu-vector-table
4. Peripheral register structure : A C structure for every peripheral containing its register-data-set.
5. Peripheral register bit position : To define the addresses of individual bits.
6. Other useful micro-controller configuration macros.
By doing #include<stm32F429xx.h>, both the applications and the driver files can access the device specific header file.
inc and src contains project related header files and project related source file respectively. Likewise, all the drivers header files in inc folder and all the drivers source files in src. Let's first create device specific header file.