GPIO usage

Hi,

I am trying to use gpio_set_value() in c++ as advised in some other post, but it seems /usr/include/linux/gpio.h on AGX Xavier provides a limited interface (a bunch of macros and structs) and it certainly doesn’t offer this function. Do I need to install something to get this work or is it depreciated?

error: ‘gpio_set_value’ was not declared in this scope
gpio_set_value(ledId, 1);

Alternatively, I can use a file descriptor, but I am trying to get the best speed possible. Did anyone do any performance testing between the two solutions?

hello nouuata,

you’re getting kernel compile errors? it should be a generic kernel api to set value,
did you included correct header file, note, Jetson AGX Xavier is using different GPIO header files, it’s t194 for Xavier series,
for example,
$L4T_Sources/r32.5.1/Linux_for_Tegra/source/public/kernel/nvidia/include/dt-bindings/gpio/tegra194-gpio.h

Well, it is a bit weird. /usr/include/linux/gpio.h seems to have a limited interface for some reason. I found the proper header files in /usr/src/linux-headers-4.9.140-tegra-linux_x86_64/kernel-4.9/include/ and /lib/modules/4.9.140-tegra/build/include/ like you mentioned. Now the problem is none of them would compile. If I include -I/lib/modules/4.9.140-tegra/build/include/which should be the correct way to do it, I get

In file included from /usr/include/aarch64-linux-gnu/bits/fcntl-linux.h:346:0,
from /usr/include/aarch64-linux-gnu/bits/fcntl.h:61,
from /usr/include/fcntl.h:35,
from /home/nouuata/workspace/cart/test2.cpp:6:
/lib/modules/4.9.140-tegra/build/include/linux/falloc.h:12:2: error: ‘__s16’ does not name a type; did you mean ‘__y1l’?
__s16 l_type;
^~~~~
__y1l
/lib/modules/4.9.140-tegra/build/include/linux/falloc.h:13:2: error: ‘__s16’ does not name a type; did you mean ‘__y1l’?
__s16 l_whence;
^~~~~
__y1l
/lib/modules/4.9.140-tegra/build/include/linux/falloc.h:14:2: error: ‘__s64’ does not name a type; did you mean ‘__f64’?
__s64 l_start;
^~~~~
__f64
/lib/modules/4.9.140-tegra/build/include/linux/falloc.h:15:2: error: ‘__s64’ does not name a type; did you mean ‘__f64’?
__s64 l_len; /* len == 0 means until end of file */
^~~~~
__f64
/lib/modules/4.9.140-tegra/build/include/linux/falloc.h:16:2: error: ‘__s32’ does not name a type; did you mean ‘__f32’?
__s32 l_sysid;
^~~~~
__f32
/lib/modules/4.9.140-tegra/build/include/linux/falloc.h:17:2: error: ‘__u32’ does not name a type; did you mean ‘__f32’?
__u32 l_pid;
^~~~~
__f32
/lib/modules/4.9.140-tegra/build/include/linux/falloc.h:18:2: error: ‘__s32’ does not name a type; did you mean ‘__f32’?
__s32 l_pad[4]; /* reserved area */
^~~~~
__f32
CMakeFiles/test2.dir/build.make:62: recipe for target ‘CMakeFiles/test2.dir/test2.cpp.o’ failed
make[2]: *** [CMakeFiles/test2.dir/test2.cpp.o] Error 1
CMakeFiles/Makefile2:67: recipe for target ‘CMakeFiles/test2.dir/all’ failed
make[1]: *** [CMakeFiles/test2.dir/all] Error 2
Makefile:83: recipe for target ‘all’ failed
make: *** [all] Error 2

If I include -I/lib/modules/4.9.140-tegra/build/ then the compiler resolves the above issues, but the include headers get messed up:

/lib/modules/4.9.140-tegra/build/include/linux/gpio.h:93:10: fatal error: linux/bug.h: No such file or directory
#include <linux/bug.h>
^~~~~~~~~~~~~
compilation terminated.
CMakeFiles/boot.dir/build.make:566: recipe for target ‘CMakeFiles/boot.dir/modules/Module_TetraLight.cpp.o’ failed
make[2]: *** [CMakeFiles/boot.dir/modules/Module_TetraLight.cpp.o] Error 1
CMakeFiles/Makefile2:104: recipe for target ‘CMakeFiles/boot.dir/all’ failed
make[1]: *** [CMakeFiles/boot.dir/all] Error 2
Makefile:83: recipe for target ‘all’ failed
make: *** [all] Error 2

hello nouuata,

are you download L4T Driver Package (BSP) Sources via L4T | NVIDIA Developer page?
please refer to developer guide, Building the NVIDIA Kernel.

may I know the default kernel compile works or not?
could you please share the details steps to reproduce your issue,
thanks

Yes, everything was downloaded from NVIDIA official page, I am using jetpack 4.4.1. I wrote a script to compile the kernel, but it is pretty similar to the content on the link you provided:

#!/bin/sh
export JETPACK_ROOT=/path/to/jetpack/base/folder
export CROSS_COMPILE=/opt/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
export TEGRA_KERNEL_OUT=$JETPACK_ROOT/kernel_out
export ARCH=arm64
export LOCALVERSION=-tegra
export TEGRA_X2_ROOTFS=$JETPACK_ROOT/jetpack_4.4.1/Linux_for_Tegra/rootfs/

cd $JETPACK_ROOT/public_sources_4.4.1/Linux_for_Tegra/source/public/kernel_src/kernel/kernel-4.9

make O=$TEGRA_KERNEL_OUT tegra_defconfig
make O=$TEGRA_KERNEL_OUT zImage
make O=$TEGRA_KERNEL_OUT dtbs

cp $TEGRA_KERNEL_OUT/arch/arm64/boot/dts/tegra194-p2888-0001-p2822-0000.dtb $JETPACK_ROOT/jetpack_4.4.1/Linux_for_Tegra/kernel/dtb

cd $JETPACK_ROOT/public_sources_4.4.1

Then I copy the compiled kernel to the device

scp $TEGRA_KERNEL_OUT/arch/arm64/boot/Image nvidia_agx_xavier/boot

and flash

cd $JETPACK_ROOT/jetpack_4.4.1/Linux_for_Tegra/
sudo ./flash.sh -k kernel-dtb jetson-xavier mmcblk0p1

If the gpio is already included in this build, it should work, but I encountered the issues detailed in my previous post.

I noticed one extra command in the link you provided, building extra kernel modules (and assuming gpio is required to be build as a module):

sudo make O=$TEGRA_KERNEL_OUT modules_install INSTALL_MOD_PATH=$TEGRA_X2_ROOTFS

and I ran it, while taking the default input values, but I get other issues:

...   
# configuration written to .config
#
warning: (SPI_TEGRA186_AON && NV_TEGRA_BPMP) selects TEGRA_HSP which has unmet direct dependencies (ARCH_TEGRA)
warning: (SPI_TEGRA186_AON && NV_TEGRA_BPMP) selects NV_TEGRA_IVC which has unmet direct dependencies (ARCH_TEGRA || ARCH_TEGRA)
cp: cannot stat './modules.order': No such file or directory
make[1]: *** [.../public_sources_4.4.1/Linux_for_Tegra/source/public/kernel_src/kernel/kernel-4.9/Makefile:1360: _modinst_] Error 1
make[1]: Leaving directory '.../kernel_out'
make: *** [Makefile:171: sub-make] Error 2

hello nouuata,

just for confirmation, don’t the previous post shows the build failures.
you’re actually able to build device tree blob successfully with the default sources package?
may I know what’s the kernel modification you’d done?
thanks

The kernel compiles successfully including the dtb flash. I added IMX334 driver and the corresponding device tree to that kernel - quite similar to the available drivers in the NVIDIA kernel source, but that’s not related to the gpio issues. No modifications related to the gpio were made. The AGX Xavier works smoothly with this kernel.

The following commands produce expected result:

$ cd /sys/class/gpio
$ echo 393 > export
$ cd gpio393
$ echo 1 > value

On top of this, I have a c++ cmake project and I can control the gpio successfully by manipulating the /sys/class/gpio/gpio393/value when adding the following function in my code (credits to RidgeRun):

int gpio_set_value(unsigned int gpio, unsigned int value)
{
	int fd, len;
	char buf[MAX_BUF];

	len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

	fd = open(buf, O_WRONLY);
	if (fd < 0) {
		perror("gpio/set-value");
		return fd;
	}

	if (value)
		ssize_t er = write(fd, "1", 2);
	else
		ssize_t er = write(fd, "0", 2);

	close(fd);
	return 0;
}

However, if I use the kernel gpio.h via
#include <linux/gpio.h>
then that header file has a limited interface ( /usr/include/linux/gpio.h) .
Similarly, adding an include path-I/lib/modules/4.9.140-tegra/build/include/to the CmakeLists includes the proper gpio.h header, but fails to link it properly. It seems like I need to build and install the gpio as a separate kernel module, but that fails either.

cp: cannot stat './modules.order': No such file or directory

hello nouuata,

could you please have a try to include the header file as following,
i.e. #include <dt-bindings/gpio/gpio.h>

Hi JerryChang,

Negative. Same issue.

Let’s close this topic. I am happy with the solution I have currently. If I have performance issues in the future, I will come back to this topic again.

Thanks for your help!