Tiva-C LaunchPad GPIO Pin as a Digital Input – Reading Push Button
In the previous tutorial we introduced GPIOs and demonstrated how to configure GPIO Pin as a Digital output. This tutorial is almost similar the previous tutorial except in this tutorial we will configure GPIO Pin as an input to read on-board push button. TM4C123GXL LaunchPad consists of two user push button i.e. SW1, SW2 (see Figure-1) connected to PF.4 and PF.0 respectively. For the purpose of demonstration we will use SW2 connected to GPIOF pin-0 (PF.0).
In this tutorial we will configure PF.0 as a digital Input to read on-board push button (SW2) connected to it. From TM4C123GXL reference manual, the on-board SW2 is connected to PF.0 pin as shown in Figure-2. Upon button press, the on-board Red LED is turned ON and upon release the LED is turned OFF.
This tutorial has three main parts.
This tutorial has three main parts.
- Configuring PF.1 as a Digital output for Red LED covered in previous tutorial and here as well.
- Configuring PF.0 as a Digital input for reading push button SW2. This is covered in this tutorial.
- Reading Push button and turning LED ON/OFF.
Following are the tutorial steps.
1. GPIOx Port Bus Selection:
Each GPIO Module/Port is interfaced on one/more of SoC internal buses. Buses carry data between various peripherals and Core inside SoC. In TM4C123GXL Launchpad Port A-F are interfaced on APB bus while Ports K-N and P-Q are available on the AHB bus – see Figure 1-1 in Datasheet .
APB is Advanced Peripheral Bus while AHB is Advanced High Speed Bus. AHB has high throughput and performance as compared to APB which is the legacy version of AHB bus architecture.
The first step is to select bus for the desired Port (Port-F in our case). A port bus can be selected via GPIO High-Performance Bus Control (GPIOHBCTL) Register-Figure-3.
- 0: APB bus selected
- 1: AHB bus selected
As we mentioned earlier only Ports K-N and P-Q are available on the AHB bus so we have no choice for Port-F other than APB bus. So Let’s select APB bus for Port-F.
GPIOHBCTL_REG EQU 0x400FE06C ; use APB bus for GPIOF LDR R1, =GPIOHBCTL_REG LDR R0, [R1] AND R0, R0, #0x1F ; clear bit-5 STR R0, [R1]
2. GPIOx Clock:
To reduce power consumption, by default various SoC modules (GPIO, USART, UART etc.) and associated registers are disabled. In order to use them, clock must be enabled to them. On TM4C123GH6PM clock to various GPIOs can enabled/disabled via Run Mode Clock Gating Control Register 2 (RCGC2) – Figure-4.
As can be seen from Figure-2, the clock to GPIO Port-F is enabled/disabled via bit-5 (GPIOD-EN). Let’s enable Port-F module by setting bit-5 to 1.
RCGC2GPIO_REG EQU 0x400FE108 ; enable clock to GPIO-F LDR R1, =RCGC2GPIO_REG LDR R0, [R1] ORR R0, R0, #0x20 STR R0, [R1]
3. GPIOx Pin Direction:
Any GPIO pin can be configured a Digital input or output. Before a GPIO pin is used, its direction needs to be configured appropriately. In our case as we want to read SW2 (connected to PF.0) and blink on-board Red LED (connected to PF.1), so the SW2 pin PF.0 needs to be configured as an Input while the LED pin PF.0 needs to be configured as an output. GPIO pins direction can be selected via GPIO Direction (GPIODIR) Register – Figure-5.
- 0: Corresponding pin is an input.
- 1: Corresponding pin is an output.
In our case let’s configure PF.0 as input by writing 0 to bit position 0 while PF.1 as an output by writing 1 to bit position 1.
GPIOFDIR_APB_REG EQU 0x40025400 ; set PF.0 as input, PF.1 direction as output LDR R1, =GPIOFDIR_APB_REG MOV R0, #0x02 STR R0, [R1]
4. Unlock GPIOx Pin:
There are quite large number of peripherals available on compact size TM4C123GH6PM. Almost all of there peripherals have to capability to interact with outside world using I/O. Due to the compact size, not every peripheral can be assigned a dedicated physical pin on SoC due to size constrains. To accommodate these peripherals on SoC, various peripherals are multiplexed on a single I/O pin. At a time a pin be configured to be used dedicatedly for a specific peripheral.
For example PA.0,PA.1 pins can be configured to be used as Digital I/O or UART0 Tx, Rx respectively as an alternate function. In order to Lock a pin for specific purpose/function, TM4C123GH6PM implements software based hardware lock mechanism via GPIO Lock (GPIOLOCK) Register – Figure-6.
The GPIOLOCK register enables write access to the GPIO Commit (GPIOCR) Register register (discussed later). Writing 0x4C4F434B to the GPIO Lock (GPIOLOCK) register unlocks the GPIO Commit (GPIOCR) Register register. Writing any other value to the GPIOLOCK register re-enables the locked state.
Let’s unlock GPIO Commit (GPIOCR) Register.
; gpio registers GPIOFLOCK_APB_REG EQU 0x40025520 ; register values GPIO_UNLOCK_VAL EQU 0x4C4F434B ; unlock GPIOCR Register for write access LDR R1, =GPIOFLOCK_APB_REG LDR R0, =GPIO_UNLOCK_VAL STR R0, [R1]
5. GPIOx Pin Functionality Unlock:
Once GPIO Commit (GPIOCR) Register – Figure-7, is unlocked. Its time to define:
1. Pins State (Pull-UP/Down),
2. Digital Functionalities (Digital I/O or Alternate function).
The GPIO Commit (GPIOCR) Register enables various registers (PIOAFSEL, GPIOPUR, GPIOPDR, and GPIODEN register) to configure a pin for above specifications. The GPIO Commit (GPIOCR) Register can only be written when its unlocked via GPIO Lock (GPIOLOCK) – previous step.
- 0: The corresponding GPIOAFSEL, GPIOPUR, GPIOPDR, or GPIODEN bits cannot be written for respective pin.
- 1: The corresponding GPIOAFSEL, GPIOPUR, GPIOPDR, or GPIODEN bits can be written for respective pin.
Let’s enable GPIOAFSEL, GPIOPUR, GPIOPDR, and GPIODEN for PF.0 (SW2 Pin) and PF.1 (LED Pin) – Figure-2.
; gpio registers GPIOFCR_APB_REG EQU 0x40025524 ; unlock GPIOAFSEL, GPIOPUR, GPIOPDR, and GPIODEN for PF.0-1 LDR R1, =GPIOFCR_APB_REG LDR R0, [R1] ORR R0, R0, #0x03 STR R0, [R1]
6. GPIOx Pin state:
The GPIO pin can be internally pulled-up or pulled-down thus setting the default Pin state to HIGH or LOW respectively. When pulled-high, the GPIO pin will remain in HIGH state until it is pulled down Software/External source and vise versa.
Pull-up/down states are needed in situations where a pins needs to remain in some state before a transition to be detected as an event like UART start/stop bits or Push buttons.
This is the most important step of this tutorial which differentiate this tutorial from previous Blinky LED tutorial. If we look at the TM4C123GXL board reference manual, we will come to know that when push button (SW2) is pressed, it connects PF.0 to ground – Figure-8. What this means is in order to detect button press on PF.0, PF.0 needs to be at logic-1 by default i.e the default state pin state should be high; when push button is pressed the PF.0 will get connected to ground and 0 will appear on PF.0 which we need to track.
The GPIO pin pull-up/down state can be selected via GPIO Pull-Up Select (GPIOPUR) and GPIO Pull-Down Select (GPIOPDR) respectively registers – Figure-9,10.
Note: Setting a bit in the GPIOPUR register automatically clears the corresponding bit in the GPIOPDR register.
Let’s set pull-up GPIO PF.0 pin high.
GPIOPURF_APB_REG EQU 0x40025510 ; pull up PF.0 LDR R1, =GPIOPURF_APB_REG LDR R0, [R1] ORR R0, R0, #0x01 STR R0, [R1]
7. GPIOx Pin Digital Enable:
By default digital function is disabled for GPIOx Pins. They do not drive a Digital value appear on GPIO pin. To use the pin as a digital input or output (either GPIO or alternate function), the corresponding GPIO Digital Enable (GPIODEN) – Figure-11, bit must be set appropriately.
- 0: The digital functions for the corresponding pin are disabled.
- 1: The digital functions for the corresponding pin are enabled.
Let’s enable Digital functionality for PF.0-1.
; gpio registers GPIOFDEN_APB_REG EQU 0x4002551C ; enable digital functionality for PF.0-1 LDR R1, =GPIOFDEN_APB_REG MOV R0, #0x03 STR R0, [R1]
8. Digital Read/Write:
By now we configured everything we need. The last step is to write/read 0,1 i.e (Pin Low, High) to/from desired configured GPIO pin. GPIO pins can be read/written via GPIO Data (GPIODATA) register – Figure-12. The same register is used for both read/write operations.
- 0: The digital is set Low.
- 1: The digital is set High.
NOTE: The GPIODATA has only one address but this register is virtually mapped to 256 locations in the address space i.e. GPIODATA + 0, GPIODATA+0x1, …. GPIODATA+0xFF. Each location is capable of setting Digital data to single pin depending on GPIODATA[9:2] address bits. The address bits 2-9 are associated with Digital pins 0-7 – Figure-13.
During a write, if the address bit associated with that data bit is set, the value of the GPIODATA register is altered. If the address bit is cleared, the data bit is left unchanged. For example, writing a value of 0xEB to the address GPIODATA + 0x098 has the results shown in Figure 13, where u indicates that data is unchanged by the write. This example demonstrates how GPIODATA bits 5, 2, and 1 are written.
Similarly during a read, if the address bit associated with the data bit is set, the value is read. If the address bit associated with the data bit is cleared, the data bit is read as a zero, regardless of its actual value.
For GPIOF, the GPIODATA base address (for APB bus) is: 0x40025000. As we need to read from PF.0 pin which corresponds to bit-2 in address bits; and write to PF.1 pin which from Figure-13 corresponds to bit-3. so bit-2,3 needs to be set in order for read/write operation to be effective. so the address of GPIODATA register for GPIOF Pin-0,1 will be 0x4002500C (bit-2,3 set).
; gpio registers GPIOFDATA_APB_REG EQU 0x4002500C
Finally we reached a point where actually tutorial can be implemented. As per tutorial requirements, RED LED (PF.1) needs to be turned ON on SW2 press and Turn OFF on SW2 release. The functionality is achieved via the following code snippet.
LDR R1, =GPIOFDATA_APB_REG loop ; read data register value for PF.0 LDR R0, [R1] AND R0, R0, #0x1 CMP R0, #0x1 BNE LED_ON ; if button is press, jump to LED_LED otherwise turn OFF LED ; turn OFF LED AND R0, R0, #0x01 STR R0, [R1] B loop LED_ON ; turn ON LED ORR R0, R0, #0x02 STR R0, [R1] B loop ; jump back to loop
For complete source code refer to the Github links given at the start of this tutorial.