Lesson 09: GPIO Ports and Configurations
The microprocessors access their I/O (Input/Output) devices either by special I/O instructions that read and write to peripherals located in a separate I/O address space, called "Port Mapped I/O, PMIO", or by using the instructions that are provided to access memory, called "Memory-mapped I/O, MMIO". ARM-based processors use memory-mapped I/O. The I/O ports share the same address space with memory. That means the software can access an I/O port simply by reading from or writing to the appropriate address, and these addresses are usually called "Registers". Most I/O ports can be configured into different I/O functions through the registers, and you can find detailed information about I/O Registers from the microprocessor's datasheet.
Even the accessing I/O register "look" like reads and writes to memory variables, but there are still some differences between the memory and I/O Registers. For example, some bits in the Register are read-only, and some are write-only; some bits can only be cleared or set; some bits cannot be modified, and some are reserved for future use.
General-Purpose Input/Output (GPIO)
GPIO is a generic pin on a microcontroller and is controllable by the program at run time. GPIO pins have no predefined purpose and can be operated as parallel interfaces. It allows the microcontroller to exchange digital information with external devices. For example, GPIO can be used for reading from a temperature sensor and for writing output to an LCD module or LEDs for status.
GPIO pins have the following capabilities:
- GPIO pins can be configured to be input or output
- GPIO pins can be enabled or disabled
- Input values are readable( typically logic high or low)
- Output values are writable and can be read-back
- Input pin can be used to trigger the interrupt function
Instead of directly configuring and controlling each individual GPIO pin, we set up a group of GPIO pins (typically 8 GPIO pins) into a PORT. Through the PORT registers, we can control and access multiple GPIO pins at a time.
Texas Instruments Tiva TM4C I/O Ports
The GPIO on the Tiva TM4C family is extremely flexible. Any GPIO can be configured to different functions: it can be an interrupt, edge-triggered on rising, falling, or both, or it can be level-sensitive to high or low values.
Tiva C microcontroller is a low-power ARM Cortex-M4 microprocessor and runs typically at 3.3V, so the logic levels of I/O pins are 3.3V. The drive strength of the outputs of the GPIO is programmable to be 2, 4, or 8 milliamps. All GPIO pins have programmable weak pull-up, pull-down, and open-drain modes.
- Never exceed the input logic high voltage of any pin beyond the VDD limit unless you are sure that the source will not exceed the limit voltage.
- Don't use negative input voltages with any pin. Be sure of polarity.
- Don't stress any GPIO pin beyond 10 ~ 15mA, although the max limit is 25mA. Use external switching devices like FETs, BJTs, and photo-isolators to drive high power loads.
GPIO DATA Register
The data register is eight bits wide and is used to:
- Read the value input on those GPIO pins that are configured as inputs.
- Program the value on those GPIO pins that are configured as outputs.
When the port pin is configured as GPIO pins, the GPIOn->DATA register is used to read and write data on the registers. If the pin is configured as a digital output pin, the data written to the GPIOn->DATA register reflects on the corresponding output pin. A read from GPIOn->DATA register returns the last bit value written if the respective pins are configured as output, or it returns the value on the corresponding input pins when these are configured as inputs.
GPIO Addressing Masking (Hardware masking address)
GPIO Address masking is a somewhat unusual technique for programming the GPIO port pins. Each GPIO port has a DATA register address. If you write an 8-bit value directly to the DATA register and all eight pins will be modified. If you just want to modify specific bits of this port, you would have to read the value on the port pins, change the specific bits, and then write the value back out to the port. This is called a read-modify-write operation, and it's fraught with issues. For instance, if an interrupt changed at pin state in the middle of this process, your code would write the wrong value to the pin.
For example, set PA1 to logic 1:
GPIOA->DATA = GPIOA->DATA | _BIT1;
On the Tiva TM4C parts, you can use a bit-mask to indicate which bits are to be modified. This is done in hardware by mapping each GPIO port to 256 addresses, which can cover every possible combination of the port pins. Bits [9:2] of the address are used as the bit-mask.
For example, if we want to modify the value on GPIO Port D pins 1, 2, and 5 only, the bit-mask value, in this case, is (0010 0110)2 in a binary number (bit 1, 2, and 5 are set to "1", other bits are set to "0"). Then convert the vale to a bit-mask address by shifting the bit-mask value to the left by 2-bits. It will be (00 1001 1000)2 in binary. You can use a bit-mask to indicate which bits are to be modified and if you look at the diagram:
GPIO addressing mask can be used on input and output pins.
In C code, pointers can be used to point to hardware mask addresses.
volatile uint32_t *PD125 = (uint32_t *)GPIOD + (_PIN1 | _PIN2 | _PIN5); // PD1, PD2 and PD5 are output pins
*PD125 = 0xEB; // Only change pins 1, 2 and 5 on port D
*PD125 = 0; // Clear pins 1, 2 and 5 to zero on port D
*PD125 = 0xFF; // Set pins 1, 2, and 5 to one on port D
TM4C GPIOn->DIR Direction Control Register
The GPIOn->DIR register is the data direction register. Bits set to HIGH in the GPIOn->DIR configure the corresponding pin to be output. Clearing a bit configures the pin to be input.
All bits are cleared by a reset. Therefore, GPIO pins are input by default. In the 6th GPIO configuration step, only output pins need to be configured, the input pins do not.