Lesson 10: 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 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, 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 have some difference 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 used.
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 Addressing Masking
GPIO Address masking is a somewhat unusual technique for programming the GPIO port pins. Each GPIO port has a base address, if you write an 8-bit value directly to this base address 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.
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 pin 1, 2, and 5 only, the bit-mask, 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 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 in the diagram: