In this activity we will use the ADB command line and shell running on the development system, to directly manipulate the Dragonboard 410c GPIO pins. A version of "Blinky" will be implemented that periodically flashes a LED of the target. A second version will turn the LED on/off under control of a press button. The "app" will run as batch file of ADB commands on the dev machine remotely controlling Dragonboard. A Linux shell script running on the target will also be used that encapsulates the batched ADB commands..

 

Previous blogs in this series have covered the Dragonboard features, setting up the Android development system and developing an Android UI app to access hardware (the sensors class). In the later activity, ADB was (under the hood) used to deploy the app from the dev machine to the target. You can also run an ADB command line to directly use ADB commands and even run a shell in which you can make Linux command line calls on the target.


Target System: Dragonboard 410c in factory state (runs Android).
Development System: Windows 10 desktop Version 1511
Development Environment: Android Studio

For this activity you need ADB to be in the command prompt path, which was covered in the a previous blog.

 

Android Architecture

image

Android Architecture: More detail here 

 

Android is a mobile operating system championed by Google. Its source code is released by Google under Open Source licensing although commercially shipped Android devices (eg Phones) tend to have proprietary software components. It is essentially a graphical user interface operating system, with a toiuch focus. Apps are written using the Android SDK and are generally written in Java. For development purposes, emulators are available.The OS for an Android system is essentially in two parts. One is the Android UI, the other is the Linux Kernel. The kernel implements to low level aspects of the OS including hardware interfacing. The Android Debug Bridge (ADB) enables us to drill into the hardware from a remote terminal.

 

Android Debug Bridge

The Android Debug Bridge (ADB) provides connectivity to the target Android device. Connectivity normally is via USB but can be over a local (eg WiFi) network. Android Studio uses ADB to deploy, run and debug apps. You can also use it via a command line as a remote terminal into the target from your development system. You can copy files to and from the target, access its its file system, manually deploy apps, run a Linux shell remotely and directly manipulate hardware such as GPIO.

To access ADB, connect up your target device to the development system using a USB cable (USB-OTG (micro USB) on target to USB Host on dev system).
Run a command prompt  (admin might be useful) Alternatively you can use the Android Monitor Window in Android Studio.
Enter  (In what follows > is the prompt so don't enter that as well)

>adb version  
>adb devices  ... you should see your device listed

Comment: You can have more than one device connected to your dev machine; in which case you need to specify which target you want to apply a command on. For simplicity, it is assumed that you are only using one device. See the Android Debug Bridge document on how to specify a target.
Note: To enable ADB debugging on a device, it  must be enabled. See the second previous blog.

PS: adb –d  <command> will direct attention to the one and only USB device (assumes only one).

>adb shell
You should now have a Linux command prompt on the device.
Try ls to get a listing
Enter exit or cntrl-c to exit the shell.
adb <adb command>
This runs the shell command and immediately exits the shell when done. Try:
>adb shell ls

 

ADB commands can be run individually using >ad shell <command>  which then returns to the PCs command prompt. If though a series of commands are required, you would enter the shell as follows:

>adb devices
>adb root
>adb remount
>adb shell
You can then issue commands as if you were logged onto a Linux system (the target).

Unless otherwise stated, in what follows, it is assumed you are in a shell as above when ADB commands are used.

 

The Low Speed Connector

image

The 40 pin Low Speed connector provides a physical interface to the target system's GPI pins. There are potentially 12 such pins available on pins 23 to 34. They are called

  • GPIO_A
  • GPIO_L.

Potentially" because they may be configured for other use. For example, GPIO_F is not available for GPIO unles the kernel is reconfigured. Our focus here on the pins that can be set or cleared as output or can be read as input (hi or lo).
The connector also provides connectivity to

  • 2 x UARTs (UART0 and UART1),
  • 2  x I2C ports (IC0 and IC1),
  • The SPI port (SPI0)
  • M2S.

image


Android runs as user interface on top of a Linux kernel. Services, such as Sensors can sit on between Android and the kernel and are loaded under Linux. With ADB we are communicating with the kernel via a service (ADB), no Android UI interactions.  The various hardware devices are configured and interacted with via Linux drivers that are loaded when the system starts.  The Android UI then interacts with the drivers through a Hardware Abstraction Layer (HAL). For example , the Sensors class used in the previous blog has a HAL manifestation.

Within the adb kernel command shell, hardware is interacted with as part of the file system.  You navigate down to a hardware's folder where elements in that folder are properties that hardware that can be set by echoing to them or cat-ed to read from them. Try:

>ls /sys/class/gpio
This gives a list of the "active" GPIO port:.
>root@msm8916_64:/ # ls /sys/class/gpio 
export gpiochip576 gpiochip608 .... .... gpiochip900 gpiochip902 unexport

We have to activate them using .. before they show.  We can send ports’ APQ number to export (activated/enabled) or to unexport (deactivated/disabled)

 

The GPIO ports have to be “activated” before you can use them. For each GPIO port A to L in the schematic above, note its APQ_GPIO number. For example, GPIO_A is APQ_GPIO_36.  The “magic number you need for this port then is 938, which is determined by adding 902 the the APQ number. The GPIO_A is then enabled by the following command:

>echo 938 > /sys/class/gpio/export
Note: Its safest with these commands to make sure there is a space between is entity within the  command; eg space either side of  >

>ls /adb/class/gpio will now list gpio36 which is GPIO_A.

>root@msm8916_64:/ # ls /sys/class/gpio
export
gpio938
gpiochip576
gpiochip608
....
....
gpiochip900
gpiochip902
unexport

To disable that port:

>echo 938 > /sys/class/gpio/unexport

 

If we now issue the command:

>ls /sys/class/gpio/gpio938

we get a list of things we can do with GPIO_A (gpio38)…

Correction: I find that you have to cd into the gpio938 folder before you can examine what’s in there although you can manipulate its connects from afar.
126|root@msm8916_64:/data # cd /sys/class/gpio/gpio938
root@msm8916_64:/sys/class/gpio/gpio938 # ls
active_low
device
direction
edge
power
subsystem
uevent
value
root@msm8916_64:/sys/class/gpio/gpio938 # cd $home

Note the highlighted attributes direction and value for the GPIO port. Examine the following:

root@msm8916_64:/data # echo "out" > /sys/class/gpio/gpio938/direction
root@msm8916_64:/data # cat /sys/class/gpio/gpio938/direction
out
root@msm8916_64:/data # echo "1" > /sys/class/gpio/gpio938/value
root@msm8916_64:/data # cat  /sys/class/gpio/gpio938/value
1
root@msm8916_64:/data # echo "0" > /sys/class/gpio/gpio938/value
root@msm8916_64:/data # cat  /sys/class/gpio/gpio938/value
0
root@msm8916_64:/data # echo "in" > /sys/class/gpio/gpio938/direction
root@msm8916_64:/data # cat /sys/class/gpio/gpio938/direction
in
root@msm8916_64:/data # cat  /sys/class/gpio/gpio938/value
0

If pin #23 was then connected to ground or Vcc we would examine its input state using the last command.
Ps (a big) Nb: The pin voltages are 1.8v on the Dragonboard. Do not exceed that

 

96Boards Signal Pin MCU Pin Offset gpio Out works In Works Comment
GPIO_A 23 APQ_GPIO_36 938 gpio938      
GPIO_B 24 APQ_GPIO_12 914 gpio914      
GPIO_C 25 APQ_GPIO_13 915 gpio915      
GPIO_D 26 APQ_GPIO_69 971 gpio971      
GPIO_E 27 APQ_GPIO_135 1017 gpio1017      
GPIO_F 28 PM_MPP_4         Not available as GPIO
GPIO_G 29 APQ_GPIO_24 926 gpio926      
GPIO_H 30 APQ_GPIO_25 927 gpio927      
GPIO_I 31 APQ_GPIO_35 937 gpio937      
GPIO_J 32 APQ_GPIO_34 936 gpio936      
GPIO_K 33 APQ_GPIO_28 930 gpio930      
GPIO_L 34 APQ_GPIO_33 935 gpio935      

In the ADB GPIO commands, refer to a GPIO port via its gpio column value

Blinky

You can connect a LED directly across pins 1 and 23.

You can then toggle the LED with the following commands:

>echo "out" > /sys/class/gpio/gpio938/direction


>echo "1" > /sys/class/gpio/gpio938/value >echo "0" > /sys/class/gpio/gpio938/value
etc.

Now wouldn’t it be nice if we could run this as an app with a period between blinks.  Lets do it as a batch file:

One way I have found works is to script adb shell commands into a text file, type the file using the DOS type command and pipe the output into adb shell. eg:

>type commands.txt | adb shell

commands.txt needs two lines after the commands:

adb-command1
adb-command2
exit
<- Blank line here

The blank line makes sure that when the adb commands are run in the shell, the process exits adb shell back to the Windows command prompt..

The following script, setup.txt, would setup GPIO_A:

echo 938 > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio938/direction
exit
|

The following script on.txt would set GPIO_A:

echo "1" > /sys/class/gpio/gpio938/value
exit
|

The following script off.txt would clear GPIO_A:

echo "1" > /sys/class/gpio/gpio938/value
exit
|
The following script setdown,txt then releases GPIO_A
echo 938 > /sys/class/gpio/unexport
exit
|

In these scripts, the | in the last line is only meant to indicate a blank line, not a literal |.

 

A set of the scripts can be encapsulated by being called in sequence from a batch file. The following is Blinky as a batch file:

@echo off
adb devices
adb root
rem adb remount

type setup.txt | adb shell
@echo .
@echo Ready to blink on and off for 20 seconds
pause

for /l %%i in (1,1,10) do call :blink %%i
goto end

:blink
@echo .
@echo %1 ON
type on.txt | adb shell
timeout  1 > nul
@echo %1 OFF
type off.txt | adb shell
timeout  1 > nul
exit /b

:end
@echo .
type setdown.txt | adb shell
@echo Done
pause

 

Blinky as a Linux Shell Script

We should though be able to script all of the above as a Linux shell script. The version of Linux running on the Dragon board uses sh as its shell. So we would script Blinky as blinky.sh:

#!/system/bin/sh

#Setup.txt
echo 938 > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio938/direction

a=0
while [ $a -lt 4 ]
do
    #Loop counter
    a=$(( a+1))
    echo $a ON
    
    #on.txt
    echo "1" > /sys/class/gpio/gpio938/value
    sleep 1
    echo $a OFF

    #off.txt
    echo "0" > /sys/class/gpio/gpio938/value
    sleep 1
done

#Setdown.txt
echo 938 > /sys/class/gpio/unexport

exit

It can be run by piping it to adb shell as previous:

>type blinky.sh | adb shell

Part 2  : Running it as a complete shell script.