New C low latency library to manage the Jetson nano GPIO

Hi Everyone

Just to announce that I am developing a C library to manage the Jetson Nano GPIO, the novelty is in that is the only one that I am aware of that does NOT use the kernel tree (/sys/), therefore it does not need previous kernel configuration or anything like that, I use DMA to write directly into the CPU registers through mapping onto /dev/mem to get low latency and higher degree of control.

Anyways, I tested most pins with an oscilloscope and it works so far, looking for beta testers, maybe this is also useful for people trying to get a deep knowledge of the machine.



JETSON NANO (TX1) family only, so far it does not support the Xaviers, etc. No hardware to test it

GPIO control of all the header pinout as input or output

PWM (hardware) control on header pins 32 & 33

Serial communications such as I2C, SPI and UART are NOT supported yet

No need of previous kernel configuration, the library will take care of that on runtime

Low latency is expected (it does not go through the kernel) direct writing to the registers (DMA)



Thanks for your sharing to the community!

I2C supported now over pins: 27 (GEN1_I2C_SDA) & 28 (GEN1_I2C_SCL) and 3 (GEN2_I2C_SDA) & 5 (GEN2_I2C_SCL) as i2c0 and i2c1. Tested with a MPU6050 gyroscope, looks ok.

It is a bit of a deviation from your topic, but I am searching how to adress the led’s 1-4 on the Jetracer Pro Expansion board. They are probably attached to the PCA9685 in the ( But they are not in the scamatic, maybe because this scematic is of the non Pro with 3 LiPo’s.

I would like the 4 leds to display the battery status of the 4 lipo’s on the (Pro) board. Dou you have a clou how to do that?

Thanks and apology for hijacking your topic.

I have never done leds with the PCA9685 but I have done servo motors, so the basics of it would be something like:
You have 4 byte registers for each led so for led0 (like in your schematics),

register 0x06 = LED0 output and brightness control byte 0 (LED0_ON_L)
register 0x07 = LED0 output and brightness control byte 1 (LED0_ON_H)
register 0x08 = LED0 output and brightness control byte 2 (LED0_OFF_L)
register 0x09 = LED0 output and brightness control byte 3 (LED0_OFF_H)

for led1 registers just continue:

register 0x0A = LED1 output and brightness control byte 0 (LED1_ON_L)
register 0x0B = LED1 output and brightness control byte 0 (LED1_ON_H)
and so on.

In code for instance using my lib I would do something like:
/* Initialize the library /
int Init = 0;
Init = gpioInitialise();
if (Init < 0)
gpio initialisation failed /
printf(“gpio initialisation failed. Finishing Program Error code: %d\n”, Init);
interrupt = 0;
pigpio initialised okay*/
printf(“gpio initialisation OK. Return code: %d\n”, Init);

int oldmode;
int newmode;
int servos;
servos = i2cOpen(1,0x40,0); /* This is for port i2c1 (jetson pins 3,5 )maybe in your case is 0 slave address is 0x40 for the PCA9685 in any case /
if (servos >= 0)
connection to I2C slave 40 OK*/
printf(“Open I2C to slave 0x40 OK. Return code: %d\n”, servos);
printf(“PCA9685 number handler: %d\n”, servos);
/* No PI connection to I2C slave 40 */
printf(“Open I2C to slave 0x40 failed. Quitting Servos thread Error code: %d\n”, servos);
interrupt = 0;

/* Now you have connection, then initialize/wake up the PCA9685 */

oldmode = i2cReadByteData(servos, 0x00); /* getting current mode /
newmode = (oldmode & 0xEF); /
wake up definition /
i2cWriteByteData(servos, 0x00, newmode); /
wake up in case /
usleep(5000); //5 milliseconds
oldmode = i2cReadByteData(servos, 0x00); /
getting current mode /
i2cWriteByteData(servos, 0x00, oldmode | 0x80); /
restart */

/* Set up the frequency */

float freq;
int oldmode;
int newmode;

/* Setting the PCA9685 frequency, this is for 50 hz */

freq = (25000000/(409650)) - 0.5; / now 25*10^6 is 25Mhz of the internal clock, 4096 is 12 bit resolution and 50hz is the wanted frequency setup) */
freq = (int) freq;

/* now there is a whole sequence to set up the frequency */

oldmode = i2cReadByteData(servos, 0x00); /* getting current mode /
newmode = (oldmode & 0x7F) | 0x10; /
sleep mode definition /
i2cWriteByteData(servos, 0x00, newmode); /
going to sleep now /
i2cWriteByteData(servos, 0xFE, freq); /
setting up the frequency now /
i2cWriteByteData(servos, 0x00, oldmode); /
coming back to the old mode /
i2cWriteByteData(servos, 0x00, oldmode | 0x80); /
final step on frequency set up */

/Send some values to led0/

float pulse_1;
int pulse;
pulse_1 = 1500; /* 1500 should be the centered position, 1000 is left and 2000 is right /
pulse_1 = (pulse_1
pulse = (int) pulse_1;
i2cWriteByteData(servo, 0x06, 0x00);
i2cWriteByteData(servo, 0x07, 0x00);
i2cWriteByteData(servo, 0x08, pulse & 0xFF);
i2cWriteByteData(servo, 0x09, pulse >> 8);
i2cWriteByteData(servo, 0xFD, 0x10); /* Shutting down all PWM channels /
i2cWriteByteData(servo, 0x00, 0x00); /
Resetting the PCA9685 last thing */

Hope is not too messy? again this is using my lib by using other methods not sure, but at least you can see the register numbers for the PCA9685.

Check my github if you want for some code for other robots with a raspberry pi and using the pigpio, again not the same but might be helpful.

Thank you very much! We’re going to try it out!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.