diff options
Diffstat (limited to 'recipes-demo/de10-nano-gpio-apps')
22 files changed, 1889 insertions, 0 deletions
| diff --git a/recipes-demo/de10-nano-gpio-apps/de10-nano-gpio-apps.bb b/recipes-demo/de10-nano-gpio-apps/de10-nano-gpio-apps.bb new file mode 100644 index 0000000..aee2942 --- /dev/null +++ b/recipes-demo/de10-nano-gpio-apps/de10-nano-gpio-apps.bb @@ -0,0 +1,84 @@ +SUMMARY = "Example applications for DE-Nano FPGA GPIO manipulation" +SECTION = "DE10-Nano" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://LICENSE;md5=d252b8b27e3e6ea89c9c6912b3c4373d" + +PACKAGE_ARCH = "${MACHINE_ARCH}" + +PR = "r0" +PV = "1.0" +PV_append = "+${PR}" + +SRC_URI = "\ +	file://build_poll_KEY0_pb_state.sh \ +	file://build_show_KEY0_pb_state.sh \ +	file://build_toggle_fpga_leds.sh \ +	file://build_watch_switch_events_ioctl.sh \ +	file://build_watch_switch_events.sh \ +	file://LICENSE \ +	file://poll_KEY0_pb_state.c \ +	file://README_first.txt \ +	file://README_gpio-keys.txt \ +	file://README_gpio-leds.txt \ +	file://README_gpio.txt \ +	file://show_KEY0_pb_state.c \ +	file://show_KEY0_pb_state.sh \ +	file://toggle_fpga_leds.c \ +	file://toggle_fpga_leds.sh \ +	file://watch_switch_events.c \ +	file://watch_switch_events_ioctl.c \ +	file://watch_switch_events.sh \ +	file://find_gpio_controllers_dt.src \ +	file://find_gpio_leds_dt.src \ +	file://find_gpio_keys_dt.src \ +" +TOP_FILES  = "LICENSE" +TOP_FILES += "README_first.txt" + +RAW_GPIO_FILES  = "build_poll_KEY0_pb_state.sh" +RAW_GPIO_FILES += "build_show_KEY0_pb_state.sh" +RAW_GPIO_FILES += "poll_KEY0_pb_state.c" +RAW_GPIO_FILES += "README_gpio.txt" +RAW_GPIO_FILES += "show_KEY0_pb_state.c" +RAW_GPIO_FILES += "show_KEY0_pb_state.sh" +RAW_GPIO_FILES += "find_gpio_controllers_dt.src" + +GPIO_LEDS_FILES  = "build_toggle_fpga_leds.sh" +GPIO_LEDS_FILES += "README_gpio-leds.txt" +GPIO_LEDS_FILES += "toggle_fpga_leds.c" +GPIO_LEDS_FILES += "toggle_fpga_leds.sh" +GPIO_LEDS_FILES += "find_gpio_leds_dt.src" + +GPIO_KEYS_FILES  = "build_watch_switch_events_ioctl.sh" +GPIO_KEYS_FILES += "build_watch_switch_events.sh" +GPIO_KEYS_FILES += "README_gpio-keys.txt" +GPIO_KEYS_FILES += "watch_switch_events.c" +GPIO_KEYS_FILES += "watch_switch_events_ioctl.c" +GPIO_KEYS_FILES += "watch_switch_events.sh" +GPIO_KEYS_FILES += "find_gpio_keys_dt.src" + +S = "${WORKDIR}" + +do_install () { +	 +	cd ${S} + +	install -d ${D}/examples/gpio/sandbox +	cp -a ${TOP_FILES} ${D}/examples/gpio/sandbox + +	install -d ${D}/examples/gpio/sandbox/raw-gpio +	cp -a ${RAW_GPIO_FILES} ${D}/examples/gpio/sandbox/raw-gpio + +	install -d ${D}/examples/gpio/sandbox/gpio-leds +	cp -a ${GPIO_LEDS_FILES} ${D}/examples/gpio/sandbox/gpio-leds + +	install -d ${D}/examples/gpio/sandbox/gpio-keys +	cp -a ${GPIO_KEYS_FILES} ${D}/examples/gpio/sandbox/gpio-keys + +	rm -f gpio_sandbox.tgz +	tar czf gpio_sandbox.tgz -C ${D}/examples/gpio sandbox +	cp -a gpio_sandbox.tgz ${D}/examples/gpio +} + +FILES_${PN} += "examples/gpio/" + diff --git a/recipes-demo/de10-nano-gpio-apps/files/LICENSE b/recipes-demo/de10-nano-gpio-apps/files/LICENSE new file mode 100644 index 0000000..ab84792 --- /dev/null +++ b/recipes-demo/de10-nano-gpio-apps/files/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) +Copyright (c) 2016 Intel Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +  +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. +  +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + diff --git a/recipes-demo/de10-nano-gpio-apps/files/README_first.txt b/recipes-demo/de10-nano-gpio-apps/files/README_first.txt new file mode 100644 index 0000000..fd26d84 --- /dev/null +++ b/recipes-demo/de10-nano-gpio-apps/files/README_first.txt @@ -0,0 +1,31 @@ +This directory contains three different example directories that contain +documentation and examples for interacting with the GPIO resources on the Altas +board. + +raw-gpio - contains a README file that describes how to discover and interact +           with the gpio framework provided by the linux environment on the +           DE10-Nano target.  There is a script and two C programs that +           demonstrate how to programmatically detect the state of the KEY0 push +           button on the DE10-Nano board.  The script and one C program simply +           read the state, output it and exit, the second C program enables the +           interrupt functionality for the GPIO and waits for the push button +           press to generate the interrupt that it waits for. + +gpio-keys - contains a README file that describes how to discover and interact +            with the gpio-keys framework provided by the linux environment on +            the DE10-Nano target.  There is a script and two C programs that +            demonstrate how to programmatically detect the input events +            generated by the SW0, SW1, SW2 and SW3 switches on the DE10-Nano +            board.  The script and one C program simply report the input events +            as they are detected, the second C program adds a call to the +            ioctl() function to read the current state of all four switches as +            each input event is processed. + +gpio-leds - contains a README file that describes how to discover and interact +            with the gpio-leds framework provided by the linux environment on +            the DE10-Nano target.  There is a script and a C program that +            demonstrate how to programmatically control the LEDS on the +            DE10-Nano board. + +Please see the README files in each sub directory for more information. + diff --git a/recipes-demo/de10-nano-gpio-apps/files/README_gpio-keys.txt b/recipes-demo/de10-nano-gpio-apps/files/README_gpio-keys.txt new file mode 100644 index 0000000..d5b0ac2 --- /dev/null +++ b/recipes-demo/de10-nano-gpio-apps/files/README_gpio-keys.txt @@ -0,0 +1,232 @@ +This readme describes the linux kernel gpio-keys framework as it deploys on the +DE10-Nano target environment.  You may find the following references useful for +more information on this topic as well. + +<linux-source-tree>/Documentation/gpio/gpio.txt +<linux-source-tree>/Documentation/gpio/sysfs.txt +<linux-source-tree>/Documentation/input/input.txt +<linux-source-tree>/Documentation/input/event-codes.txt +<linux-source-tree>/Documentation/input/input-programming.txt +<linux-source-tree>/Documentation/devicetree/bindings/gpio/gpio.txt +<linux-source-tree>/Documentation/devicetree/bindings/input/gpio-keys.txt +<linux-source-tree>/Documentation/devicetree/bindings/input/gpio-keys-polled.txt + +If you cut and paste the following function into a console running on the +DE10-Nano target you can extract the useful information contained in the run +time devicetree maintained by the kernel in the procfs. + +################################################################################ +# find gpio-keys in device tree +################################################################################ +function find_gpio_keys_dt () +{ +    for NEXT in $(find -L /proc/device-tree -name "compatible" | sort); +    do +        cat ${NEXT} | grep -xz "gpio-keys" > /dev/null && { +            KEYS_DIRNAME="$(dirname ${NEXT})"; +            KEYS_COMPATIBLE="$(cat ${KEYS_DIRNAME}/compatible)"; +            echo "${KEYS_DIRNAME}"; +            echo -e "\tcompatible = '${KEYS_COMPATIBLE}'"; +            for NEXT_KEY in $(find -L "${KEYS_DIRNAME}" -name "gpios" | sort); +            do +                NEXT_KEY_DIR="$(dirname ${NEXT_KEY})"; +                echo "${NEXT_KEY_DIR}"; +                KEYS_GPIOS="$(hexdump -v -e '"0x" 4/1 "%02x" " "' "${NEXT_KEY}")"; +                CONTROLLER_PHANDLE_HEX=$(echo ${KEYS_GPIOS} | cut -d ' ' -f 1); +                GPIO_BIT_HEX=$(echo ${KEYS_GPIOS} | cut -d ' ' -f 2); +                INVERTED_FLAG_HEX=$(echo ${KEYS_GPIOS} | cut -d ' ' -f 3); +                printf "             gpios = ('%d', '%d', '%d') : ('%s', '%s', '%s')\n" "${CONTROLLER_PHANDLE_HEX}" "${GPIO_BIT_HEX}" "${INVERTED_FLAG_HEX}" "controller" "bit" "flag"; +                KEYS_CODE="$(hexdump -v -e '"0x" 4/1 "%02x"' "${NEXT_KEY_DIR}/linux,code")"; +                printf "              code = '%d'\n" "${KEYS_CODE}"; +                GPIO_CONTROLLER="unknown"; +                CONTROLLER_PHANDLE_DEC="$(printf "%d" "${CONTROLLER_PHANDLE_HEX}")"; +                for NEXT in $(find -L /proc/device-tree -name "phandle" | sort); +                do +                    PHANDLE_HEX="$(hexdump -v -e '"0x" 4/1 "%02x"' "${NEXT}")"; +                    PHANDLE_DEC="$(printf "%d" "${PHANDLE_HEX}")"; +                    [ "${PHANDLE_DEC}" -eq "${CONTROLLER_PHANDLE_DEC}" ] && { +                        GPIO_CONTROLLER="$(dirname ${NEXT})" +                    }; +                done; +                printf "        controller = '%s'\n" "${GPIO_CONTROLLER}"; +            done +        }; +    done +} +################################################################################ + +The function above is provided in the file 'find_gpio_keys_dt.src', which you +can source into your environment by running 'source find_gpio_keys_dt.src'. + +When we run the function above on the DE10-Nano target it searches for nodes +containing the 'compatible' string 'gpio-keys', there should be only one node +located.  The function then prints the path to the node that it found and  +extracts the 'gpios' binding and the 'linux,code' binding for each key node and +prints these statistics. + +root@DE10-Nano:~# find_gpio_keys_dt +/proc/device-tree/soc/keys +        compatible = 'gpio-keys' +/proc/device-tree/soc/keys/sw0 +             gpios = ('50', '0', '1') : ('controller', 'bit', 'flag') +              code = '64' +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100004000' +/proc/device-tree/soc/keys/sw1 +             gpios = ('50', '1', '1') : ('controller', 'bit', 'flag') +              code = '65' +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100004000' +/proc/device-tree/soc/keys/sw2 +             gpios = ('50', '2', '1') : ('controller', 'bit', 'flag') +              code = '66' +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100004000' +/proc/device-tree/soc/keys/sw3 +             gpios = ('50', '3', '1') : ('controller', 'bit', 'flag') +              code = '67' +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100004000' +root@DE10-Nano:~# + +For more information on the gpio controllers framework, please read the +README_gpio.txt document.  The 'gpio@0x100004000' controller identified above +maps to the 'dipsw_pio' controller that provides a 4-bit input, fpga based gpio, +registered as 'gpio-keys' in the device tree to be used in the gpio-keys +framework to receive input events from switches SW0-SW3 on the DE10-Nano board. + +The gpio-keys framework will register an input event device that will post input +events when the gpios above change their state.  The 'code' associated with each +gpio above will be encoded in the input event message along with the state of +the switch.  We can see the input device in the devfs like this: + +root@DE10-Nano:~# ls -lR /dev/input +/dev/input: +total 0 +drwxr-xr-x    2 root     root            80 Jul  9 16:25 by-path +crw-rw----    1 root     input      13,  64 Jan  1  1970 event0 +crw-rw----    1 root     input      13,  65 Jul  9 16:25 event1 +crw-rw----    1 root     input      13,  63 Jan  1  1970 mice +crw-rw----    1 root     input      13,  32 Jan  1  1970 mouse0 + +/dev/input/by-path: +total 0 +lrwxrwxrwx    1 root     root             9 Jan  1  1970 platform-ffc04000.i2c-event -> ../event0 +lrwxrwxrwx    1 root     root             9 Jul  9 16:25 platform-soc:base-fpga-region:keys-event -> ../event1 + +In this case the event1 device is the device for our gpio-keys input, we can +tell this from the '/dev/input/by-path' links that have more descriptive names. + +The sysfs also describes the input device environment for us in a useful way. + +root@DE10-Nano:~# ls -l /sys/class/input/ +total 0 +lrwxrwxrwx    1 root     root             0 Jan  1  1970 event0 -> ../../devices/platform/soc/ffc04000.i2c/i2c-0/0-0053/input/input0/event0 +lrwxrwxrwx    1 root     root             0 Jul 14 19:17 event1 -> ../../devices/platform/soc/soc:keys/input/input1/event1 +lrwxrwxrwx    1 root     root             0 Jan  1  1970 input0 -> ../../devices/platform/soc/ffc04000.i2c/i2c-0/0-0053/input/input0 +lrwxrwxrwx    1 root     root             0 Jul 14 19:17 input1 -> ../../devices/platform/soc/soc:keys/input/input1 +lrwxrwxrwx    1 root     root             0 Jan  1  1970 mice -> ../../devices/virtual/input/mice +lrwxrwxrwx    1 root     root             0 Jan  1  1970 mouse0 -> ../../devices/platform/soc/ffc04000.i2c/i2c-0/0-0053/input/input0/mouse0 + +And from the above we can see that the 'soc:keys' device exists in the sysfs. + +root@DE10-Nano:~# ls /sys/devices/platform/soc/soc:keys +disabled_keys      driver_override    modalias           switches +disabled_switches  input              power              uevent +driver             keys               subsystem +root@DE10-Nano:~# ls /sys/devices/platform/soc/soc:keys/input +input1 +root@DE10-Nano:~# ls /sys/devices/platform/soc/soc:keys/input/input1 +capabilities  event1        modalias      phys          properties    uevent +device        id            name          power         subsystem     uniq +root@DE10-Nano:~# ls /sys/devices/platform/soc/soc:keys/input/input1/event1 +dev        device     power      subsystem  uevent +root@DE10-Nano:~# cat /sys/devices/platform/soc/soc:keys/input/input1/name +soc:keys +root@DE10-Nano:~# cat /sys/devices/platform/soc/soc:keys/input/input1/event1/dev +13:65 +root@DE10-Nano:~# ls -l /dev/input/event1 +crw-rw----    1 root     input      13,  65 Jul  9 16:25 /dev/input/event1 + +So now that we know what our input event device is, we can simply read from it +to capture the input events as they arrive.  The device will block until the +next event message is received.  We can do this like so: + +root@DE10-Nano:~# hexdump -C /dev/input/event1 +00000000  ca 61 a5 55 a4 44 08 00  01 00 40 00 00 00 00 00  |.a.U.D....@.....| +00000010  ca 61 a5 55 a4 44 08 00  00 00 00 00 00 00 00 00  |.a.U.D..........| +00000020  cc 61 a5 55 24 2a 02 00  01 00 40 00 01 00 00 00  |.a.U$*....@.....| +00000030  cc 61 a5 55 24 2a 02 00  00 00 00 00 00 00 00 00  |.a.U$*..........| +00000040  cd 61 a5 55 04 a0 0b 00  01 00 41 00 00 00 00 00  |.a.U......A.....| +00000050  cd 61 a5 55 04 a0 0b 00  00 00 00 00 00 00 00 00  |.a.U............| +00000060  cf 61 a5 55 bf 21 06 00  01 00 41 00 01 00 00 00  |.a.U.!....A.....| +00000070  cf 61 a5 55 bf 21 06 00  00 00 00 00 00 00 00 00  |.a.U.!..........| +00000080  d1 61 a5 55 7c 14 03 00  01 00 42 00 00 00 00 00  |.a.U|.....B.....| +00000090  d1 61 a5 55 7c 14 03 00  00 00 00 00 00 00 00 00  |.a.U|...........| +000000a0  d2 61 a5 55 22 2a 02 00  01 00 42 00 01 00 00 00  |.a.U"*....B.....| +000000b0  d2 61 a5 55 22 2a 02 00  00 00 00 00 00 00 00 00  |.a.U"*..........| +000000c0  d4 61 a5 55 8d ac 05 00  01 00 43 00 00 00 00 00  |.a.U......C.....| +000000d0  d4 61 a5 55 8d ac 05 00  00 00 00 00 00 00 00 00  |.a.U............| +000000e0  d7 61 a5 55 8c ac 05 00  01 00 43 00 01 00 00 00  |.a.U......C.....| +000000f0  d7 61 a5 55 8c ac 05 00  00 00 00 00 00 00 00 00  |.a.U............| +^C + +The output above results after we start hexdump reading from the input event1 +device, and then we toggle SW0 on and off, then we toggle SW1 on and off, then +we toggle SW2 on and off, and then we toggle SW3 on and off.  In 16 byte event +messages that appear above, we can see the first 4 bytes that represent the +second of the event, followed by the next 4 bytes that represent the millisecond +of the event, followed by the next 2 bytes that represent the event type, +followed by the next 2 bytes that represent the event code, followed by the +last 4 bytes that represent the event value.  So we can see the first line 0x00 +is an EV_KEY event for SW0 with code 0x40 and value 0.  Then line 0x10 is an +EV_SYN event, followed by line 0x20 which is the next EV_KEY event for SW0 with +code 0x40 and value 1.  Then line 0x30 is another EV_SYN event.  This pattern +repeats itself for the SW1 events with code 0x41, then the SW2 events with code +0x42 and finally the SW3 events with code 0xx43. + +-------------------------------------------------------------------------------- +Example programs and scripts +-------------------------------------------------------------------------------- +This directory contains a few examples to demonstrate how to interact with the +switches on the DE10-Nano board that have been registered in the gpio-keys +framework.  There is a shell script called 'watch_switch_events.sh' and a C +program called 'watch_switch_events.c'.  Each of these examples monitor the FPGA +gpio-keys input event in exactly the same way.  Then there is a C program called +'watch_switch_events_ioctl.c' which simply adds an ioctl() call to the +'watch_switch_events.c' program so that it can detect the current state of all +the switches, which can only be accomplished with the ioctl() call. + +To build the 'watch_switch_events.c' application simply run the +'build_watch_switch_events.sh' shell script.  That will compile the +'watch_switch_events.c' source file and produce the executable +'watch_switch_events' application.  Refer to the 'build_watch_switch_events.sh' +script to see how the application is actually compiled and refer to the C +program source file for more details on how it actually works. + +To build the 'watch_switch_events_ioctl.c' application simply run the +'build_watch_switch_events_ioctl.sh' shell script.  That will compile the +'watch_switch_events_ioctl.c' source file and produce the executable +'watch_switch_events_ioctl' application.  Refer to the +'build_watch_switch_events_ioctl.sh' script to see how the application is +actually compiled and refer to the C program source file for more details on how +it actually works. + +Refer to the 'watch_switch_events.sh' source file for more details on how it +actually works. + +Once you've built the applications, you can run both the script and the +applications like this: + +./watch_switch_events.sh	<<< to run the script +./watch_switch_events		<<< to run the program +./watch_switch_events_ioctl	<<< to run the program with ioctl() + +The programs and script will monitor the input events for the gpio-keys device +registered in the system.  To generate an input event slide the switches SW0, +SW1, SW2 and SW3 on the DE10-Nano board.  As you slide the switches you will see +the programs and script print out the input events that they receive from the +system.  The ioctl version of the program will additionally print out the +current state of all the switches at each input event as well.  To terminate the +script or programs just type CTRL-C on the console that you launched them from. + +Both the programs and the script monitor the switches by interacting with the +input event device node provided by the gpio-keys framework which leverages the +linux gpio controller framework. + diff --git a/recipes-demo/de10-nano-gpio-apps/files/README_gpio-leds.txt b/recipes-demo/de10-nano-gpio-apps/files/README_gpio-leds.txt new file mode 100644 index 0000000..21cc5dc --- /dev/null +++ b/recipes-demo/de10-nano-gpio-apps/files/README_gpio-leds.txt @@ -0,0 +1,182 @@ +This readme describes the linux kernel gpio-leds framework as it deploys on the +DE10-Nano target environment.  You may find the following references useful for +more information on this topic as well. + +<linux-source-tree>/Documentation/leds/leds-class.txt +<linux-source-tree>/Documentation/devicetree/bindings/leds/common.txt +<linux-source-tree>/Documentation/devicetree/bindings/leds/leds-gpio.txt + +If you cut and paste the following function into a console running on the +DE10-Nano target you can extract the useful information contained in the run +time devicetree maintained by the kernel in the procfs. + +################################################################################ +# find gpio-leds in device tree +################################################################################ +function find_gpio_leds_dt () +{ +    for NEXT in $(find -L /proc/device-tree -name "compatible" | sort); +    do +        cat ${NEXT} | grep -xz "gpio-leds" > /dev/null && { +            LEDS_DIRNAME="$(dirname ${NEXT})"; +            LEDS_COMPATIBLE="$(cat ${LEDS_DIRNAME}/compatible)"; +            echo "${LEDS_DIRNAME}"; +            echo -e "\tcompatible = '${LEDS_COMPATIBLE}'"; +            for NEXT_LED in $(find -L "${LEDS_DIRNAME}" -name "gpios" | sort); +            do +                NEXT_LED_DIR="$(dirname ${NEXT_LED})"; +                echo "${NEXT_LED_DIR}"; +                LEDS_GPIOS="$(hexdump -v -e '"0x" 4/1 "%02x" " "' "${NEXT_LED}")"; +                CONTROLLER_PHANDLE_HEX=$(echo ${LEDS_GPIOS} | cut -d ' ' -f 1); +                GPIO_BIT_HEX=$(echo ${LEDS_GPIOS} | cut -d ' ' -f 2); +                INVERTED_FLAG_HEX=$(echo ${LEDS_GPIOS} | cut -d ' ' -f 3); +                printf "             gpios = ('%d', '%d', '%d') : ('%s', '%s', '%s')\n" "${CONTROLLER_PHANDLE_HEX}" "${GPIO_BIT_HEX}" "${INVERTED_FLAG_HEX}" "controller" "bit" "flag"; +                GPIO_CONTROLLER="unknown"; +                CONTROLLER_PHANDLE_DEC="$(printf "%d" "${CONTROLLER_PHANDLE_HEX}")"; +                for NEXT in $(find -L /proc/device-tree -name "phandle" | sort); +                do +                    PHANDLE_HEX="$(hexdump -v -e '"0x" 4/1 "%02x"' "${NEXT}")"; +                    PHANDLE_DEC="$(printf "%d" "${PHANDLE_HEX}")"; +                    [ "${PHANDLE_DEC}" -eq "${CONTROLLER_PHANDLE_DEC}" ] && { +                        GPIO_CONTROLLER="$(dirname ${NEXT})" +                    }; +                done; +                printf "        controller = '%s'\n" "${GPIO_CONTROLLER}"; +            done +        }; +    done +} +################################################################################ + +The function above is provided in the file 'find_gpio_leds_dt.src', which you +can source into your environment by running 'source find_gpio_leds_dt.src'. + +When we run the function above on the DE10-Nano target it searches for nodes +containing the 'compatible' string 'gpio-leds', there should be only one node +located.  The function then prints the path to the node that it found and  +extracts the 'gpios' binding for each led node and prints these statistics. + +root@DE10-Nano:~# find_gpio_leds_dt +/proc/device-tree/leds +        compatible = 'gpio-leds' +/proc/device-tree/leds/hps0 +             gpios = ('51', '24', '0') : ('controller', 'bit', 'flag') +        controller = '/proc/device-tree/soc/gpio@ff709000/gpio-controller@0' +/proc/device-tree/soc/leds +        compatible = 'gpio-leds' +/proc/device-tree/soc/leds/fpga0 +             gpios = ('49', '0', '0') : ('controller', 'bit', 'flag') +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100003000' +/proc/device-tree/soc/leds/fpga1 +             gpios = ('49', '1', '0') : ('controller', 'bit', 'flag') +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100003000' +/proc/device-tree/soc/leds/fpga2 +             gpios = ('49', '2', '0') : ('controller', 'bit', 'flag') +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100003000' +/proc/device-tree/soc/leds/fpga3 +             gpios = ('49', '3', '0') : ('controller', 'bit', 'flag') +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100003000' +/proc/device-tree/soc/leds/fpga4 +             gpios = ('49', '4', '0') : ('controller', 'bit', 'flag') +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100003000' +/proc/device-tree/soc/leds/fpga5 +             gpios = ('49', '5', '0') : ('controller', 'bit', 'flag') +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100003000' +/proc/device-tree/soc/leds/fpga6 +             gpios = ('49', '6', '0') : ('controller', 'bit', 'flag') +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100003000' +/proc/device-tree/soc/leds/fpga7 +             gpios = ('49', '7', '0') : ('controller', 'bit', 'flag') +        controller = '/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100003000' + +For more information on the gpio controllers framework, please read the +README_gpio.txt document.  The 'gpio@0x100003000' controller identified above +maps to the 'led_pio' controller that provides an 8-bit output, fpga based gpio, +registered as 'gpio-leds' in the device tree to be used in the gpio-leds +framework to drive LED0-LED7 on the DE10-Nano board.  The 'gpio@ff709000' +controller identified above maps to the 'gpio1' controller that provides a  +29-bit, hps based gpio controller, the HPS GPIO53 port served by this controller +is registered as 'gpio-leds' in the device tree to be used in the gpio-leds +framework to drive the USERLED on the Altas board. + +The gpio-led framework will register sysfs entries for each led port, and +provide files that we can use to control and query the state of the leds.  If we +look at the sysfs led class directory like this: + +root@DE10-Nano:~# ls /sys/class/leds/ +fpga_led0  fpga_led2  fpga_led4  fpga_led6  hps_led0 +fpga_led1  fpga_led3  fpga_led5  fpga_led7 + +We see all the led entries that the gpio-leds framework has registered for us. +Each of these directories contain the following format: + +root@DE10-Nano:~# ls /sys/class/leds/fpga_led0 +brightness      max_brightness  subsystem       uevent +device          power           trigger +root@DE10-Nano:~# ls /sys/class/leds/hps_led0 +brightness      max_brightness  subsystem       uevent +device          power           trigger + +There are two files in these entries that are particularly useful to us, the +'trigger' file and the 'brightness' file.  The 'trigger' file identifies what +automatic triggers get applied to the led port, by default the 'hps_led0' port +is assigned to be triggered as 'heartbeat' and if we examine the 'trigger' file +we should see that: + +root@DE10-Nano:~# cat /sys/class/leds/hps_led0/trigger +none nand-disk mmc0 timer oneshot [heartbeat] backlight gpio cpu0 cpu1 default-on + +If we look at any of the 'fpga_led*' entiries we should see no trigger applied +to them; + +root@DE10-Nano:~# cat /sys/class/leds/fpga_led0/trigger +[none] nand-disk mmc0 timer oneshot heartbeat backlight gpio cpu0 cpu1 default-on + +The 'brightness' file allows us to turn the led on or off and query the state of +the led.  Like this + +root@DE10-Nano:~# cat /sys/class/leds/fpga_led0/brightness +0 + +The 'fpga_led0' port is currently off, so if we set this port to anything but +zero, we will turn that led on, like this: + +root@DE10-Nano:~# echo 1 > /sys/class/leds/fpga_led0/brightness +root@DE10-Nano:~# cat /sys/class/leds/fpga_led0/brightness +1 + +Now the 'fpga_led0' port is on, if we sest this port back to zero the we will +turn that led off, like this: + +root@DE10-Nano:~# echo 0 > /sys/class/leds/fpga_led0/brightness +root@DE10-Nano:~# cat /sys/class/leds/fpga_led0/brightness +0 + +-------------------------------------------------------------------------------- +Example programs and scripts +-------------------------------------------------------------------------------- +This directory contains a few examples to demonstrate how to control the LEDs on +the DE10-Nano board.  There is a shell script called 'toggle_fpga_leds.sh' and a C +program called 'toggle_fpga_leds.c'.  Each of these examples toggle the FPGA +LEDs in exactly the same way. + +To build the 'toggle_fpga_leds' application simply run the +'build_toggle_fpga_leds.sh' shell script.  That will compile the +'toggle_fpga_leds.c' source file and produce the executable 'toggle_fpga_leds' +application.  Refer to the 'build_toggle_fpga_leds.sh' script to see how the +application is actually compiled and refer to the C program source file and the +shell script source file for more details on how they actually work. + +Once you've built the application, you can run both the script and the +application like this: + +./toggle_fpga_leds.sh	<<< to run the script +./toggle_fpga_leds	<<< to run the program + +The program and script will exit automatically after they sequentially turn each +led on and then off. + +Both the program and the script manipulate the LEDs by interacting with the +sysfs file entries provided by the linux gpio-led framework which leverages the +linux gpio controller framework. + diff --git a/recipes-demo/de10-nano-gpio-apps/files/README_gpio.txt b/recipes-demo/de10-nano-gpio-apps/files/README_gpio.txt new file mode 100644 index 0000000..ba0b0f4 --- /dev/null +++ b/recipes-demo/de10-nano-gpio-apps/files/README_gpio.txt @@ -0,0 +1,358 @@ +This readme describes the linux kernel gpio framework as it deploys on the +DE10-Nano target environment.  You may find the following references useful for +more information on this topic as well. + +<linux-source-tree>/Documentation/gpio/gpio.txt +<linux-source-tree>/Documentation/gpio/sysfs.txt +<linux-source-tree>/Documentation/devicetree/bindings/gpio/gpio.txt +<linux-source-tree>/Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt +<linux-source-tree>/Documentation/devicetree/bindings/gpio/gpio-altera.txt + +If you cut and paste the following function into a console running on the +DE10-Nano target you can extract the useful information contained in the run +time devicetree maintained by the kernel in the procfs. + +################################################################################ +# find gpio controllers in device tree +################################################################################ +function find_gpio_controllers_dt () +{ +    for NEXT in $(find -L /proc/device-tree -name "compatible" | sort); +    do +        cat ${NEXT} | grep -xz "snps,dw-apb-gpio" > /dev/null && { +            GPIO_DIRNAME="$(dirname ${NEXT})"; +            echo ${GPIO_DIRNAME}; +            GPIO_COMPATIBLE="$(cat ${GPIO_DIRNAME}/compatible)"; +            echo -e "\tcompatible = '${GPIO_COMPATIBLE}'"; +            WF="${GPIO_DIRNAME}/gpio-controller@0/snps,nr-gpios"; +            GPIO_HEX_WIDTH="$(hexdump -v -e '"0x"' -e '4/1 "%02x"' "${WF}")"; +            GPIO_WIDTH=$(printf "%d" ${GPIO_HEX_WIDTH}); +            echo -e "\t     width = '${GPIO_WIDTH}'" +        }; +        cat ${NEXT} | grep -e "altr,pio" > /dev/null && { +            GPIO_DIRNAME="$(dirname ${NEXT})"; +            echo ${GPIO_DIRNAME}; +            GPIO_COMPATIBLE="$(cat ${GPIO_DIRNAME}/compatible)"; +            echo -e "\tcompatible = '${GPIO_COMPATIBLE}'"; +            WF="${GPIO_DIRNAME}/altr,gpio-bank-width"; +            GPIO_HEX_WIDTH="$(hexdump -v -e '"0x"' -e '4/1 "%02x"' "${WF}")"; +            GPIO_WIDTH=$(printf "%d" ${GPIO_HEX_WIDTH}); +            echo -e "\t     width = '${GPIO_WIDTH}'" +        }; +    done +} +################################################################################ + +The function above is provided in the file 'find_gpio_controllers_dt.src', which +you can source into your environment by running +'source find_gpio_controllers_dt.src'. + +When we run the function above on the DE10-Nano target it searches for nodes +containing the 'compatible' string fragments of 'snps,dw-apb-gpio' or 'altr,pio' +which are the identifiers for the hard GPIO controllers and the soft GPIO +controllers, respectively, in our system.  The function then prints the path to +the node that it found and extracts the compatible string and width of the gpio +controller and prints those statistics out as well.  It does this for all gpio +controller nodes that it locates in the device tree. + +root@DE10-Nano:~# find_gpio_controllers_dt +/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100003000 +        compatible = 'altr,pio-15.0altr,pio-1.0' +             width = '8' +/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100004000 +        compatible = 'altr,pio-15.0altr,pio-1.0' +             width = '4' +/proc/device-tree/soc/bridge@0xc0000000/gpio@0x100005000 +        compatible = 'altr,pio-15.0altr,pio-1.0' +             width = '2' +/proc/device-tree/soc/gpio@ff708000 +        compatible = 'snps,dw-apb-gpio' +             width = '29' +/proc/device-tree/soc/gpio@ff709000 +        compatible = 'snps,dw-apb-gpio' +             width = '29' +/proc/device-tree/soc/gpio@ff70a000 +        compatible = 'snps,dw-apb-gpio' +             width = '27' + +Now the run time binary device tree blob does not contain some of the useful +labels that were used in the original DTS source files that can help us +understand what gpio controllers belong to what functions on the board.  These +fragments out of the original DTS source file contain the labels which show +the functions of the various gpio controllers a little better: + +led_pio: gpio@0x100003000 { +}; +dipsw_pio: gpio@0x100004000 { +};  +button_pio: gpio@0x100005000 { +}; +gpio@ff708000 { +	gpio0: gpio-controller@0 { +	}; +}; +gp | 
