Setting GPIO for one-wire communication (IMX6ULL)

I’m having troubles trying to set my IMX6ULL to working with one-wire protocol; using same pin to send and receive signals.
Particularly i want to control temperature sensor DS18S20, but i cant get it to do the “initialization procedure”, which consists in sending a pulse to the sensor and then receive the “acknowledge” signal from it.

I’m using colibri IMX6ULL WB 512 (core image minimal 5.7.2-devel-20230726155409+build) with a custom board, where i set pin SODIMM 137 to the sensor:

&pinctrl_gpio2 {
	fsl,pins = <
		MX6ULL_PAD_SNVS_TAMPER2__GPIO5_IO02	0x1d0b0	/* SODIMM 137 */

In initialization procedure i send the module a low signal for 480us and then i change the pin setting to “in”, and that’s where i can’t get the presence pulse from the sensor.
I sensed the pin with an oscilloscope and definetly the sensor works fine, therefore i’m able to see the low signal, but in my C program the logic level never changes.

This low signal lasts for about 50 us, but once i set the pin config to “in” im not able to detect any change.

Maybe it has something to do with the pin config itself, i’ve tried with pull-up/down config, CMOS /Schmitt Trigger in, but nothing changes (sensor datasheet says that sensor output is an opendrain with a pullup resistor). I also tried to set other pin to just “in” config and connected to the sensor to see if that was the problem but once again it didn’t work.

I would like some advices in what i should look at here, thank you!

Please check regarding SNVS pad you are using. Pinctrl groups can either contain SNVS or non-SNVS pads, but not the mix of SNVS and non-SNVS pads. SNVS pinctrl group can belong only to iomuxc_snvs, and not to iomuxc.
If using two pads connected together, then configure output one as open drain, so that you don’t need to change IO direction.

1 Like

Hi Edward thanks for answering.

I’ve tried to set the pin like you mentioned:

		fsl,pins = <
		MX6ULL_PAD_SNVS_TAMPER2__GPIO5_IO02	0xf8b0	/* SODIMM 137 */

Read pin :

&pinctrl_snvs_gpio1 {
	/delete-property/ fsl,pins;
	fsl,pins = < 
		MX6ULL_PAD_SNVS_TAMPER5__GPIO5_IO05	0x110b0 /* SODIMM 131 */

And the pin works fine it’s just i can’t get to detect that pulse. (By the way i tried all the combinations between open drain/cmos and schimitt trigger.

Used this simple script
echo 130 > /sys/class/gpio/export
echo 133 > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio130/direction
echo "in"> /sys/class/gpio/gpio133/direction
echo 1 > /sys/class/gpio/gpio130/value
sleep 0.1
echo 0 > /sys/class/gpio/gpio130/value
sleep 0.00048
echo 130 > /sys/class/gpio/unexport
sleep 0.000005
cat /sys/class/gpio/gpio133/value
sleep 0.000035
cat /sys/class/gpio/gpio133/value
sleep 0.00034

But i can’t see that change of state i’m seeing in my oscilloscope… Maybe it’s hardware related?

To capture that pulse, you need to use a GPIO interrupt. Please check the following threads:

In Linux, especially on 6ULL, everything shorter than 10ms is hard real time. Shorter than 2ms is extreme real time. Are you kidding catching 50us pulse in bash script? I didn’t time sleep 0 call, but I guess it is longer than 50us when lucky to hit I-cache.
Perhaps you could solve it with C and libgpiod, but even for C it is challenging and not guaranteed due to Linux nature. Use external MCU or perhaps upgrade to iMX7 with real time M4 code on the same chip.

Hi @germanmorgan ,

Were you able to solve this issue?

Please let me know if you have any doubts.

Best regards,
Daniel Morais

Hi Daniel, thank you all for your replies. Im trying @Edward solution right now, altough i’m seeing it’s gonna be difficult.

I didn’t have the “libgpiod” library installed on my Linux sv so i’m trying to install it, but i’m getting this error:

$ ./ --enable-tools=yes --host=arm-angstrom-linux-gnueabi --prefix=/home/yocto-project/GSM_C/libgpiod_german
autoreconf: Entering directory `.’
autoreconf: not using Gettext
autoreconf: running: aclocal --force -I m4
autoreconf: tracing
autoreconf: running: libtoolize --copy --force
libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, ‘autostuff’.
libtoolize: copying file ‘autostuff/’
libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, ‘m4’.
libtoolize: copying file ‘m4/libtool.m4’
libtoolize: copying file ‘m4/ltoptions.m4’
libtoolize: copying file ‘m4/ltsugar.m4’
libtoolize: copying file ‘m4/ltversion.m4’
libtoolize: copying file ‘m4/lt~obsolete.m4’
autoreconf: running: /usr/local/oecore-x86_64/sysroots/x86_64-angstromsdk-linux/usr/bin/autoconf --force error: Unexpanded AX_ macro found. Please install GNU autoconf-archive.
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
autoreconf: /usr/local/oecore-x86_64/sysroots/x86_64-angstromsdk-linux/usr/bin/autoconf failed with exit status: 1

Maybe if i try using"poll.h" library i will get some results? I’m kinda out of solutions, and we can’t change hardware at this stage

Hi @germanmorgan ,

Have you ever built an image using this documentation? The libgpiod is available on Yocto as a package by default on the BSP 5 layers, you can find it below:


The easiest way to install this package into your image is by adding the following line to the conf/local.conf file and building the entire image:

IMAGE_INSTALL_append += " libgpiod"

Please let me know if you have any other doubts.

Best regards,
Daniel Morais

Daniel, i managed to run libgpiod by flashing the image every time i wanted to make some change to my C program. Anyways, i wasn’t able to detect any change of edge.

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("Usage: gpio-event <CHIP-NAME> <OFFSET>\n");
        return EXIT_FAILURE;

    const char *chip_name = argv[1];
    int offset = atoi(argv[2]);

    struct gpiod_line *line = get_gpio_line(chip_name, offset);
    if (!line) {
        return EXIT_FAILURE;

    set_line_mode(line, GPIOD_LINE_ACTIVE_STATE_HIGH);

    struct timespec start_time;
    clock_gettime(CLOCK_MONOTONIC, &start_time);

    // Espera 500 ms

    gpiod_line_set_value(line, 0);

    line = get_gpio_line(chip_name, offset);
    if (!line) {
        return EXIT_FAILURE;

    if (gpiod_line_request_both_edges_events(line, "gpio-event") < 0) {
        perror("Error al configurar la línea GPIO");
        return EXIT_FAILURE;

    struct gpiod_line_event event;
    struct timespec end_time;
    while (1) {
        gpiod_line_event_wait(line, NULL);

        if (gpiod_line_event_read(line, &event) == 0) {
            clock_gettime(CLOCK_MONOTONIC, &end_time);
            long elapsed_time_ns = (end_time.tv_sec - start_time.tv_sec) * 1000000000 + (end_time.tv_nsec - start_time.tv_nsec);

            if (event.event_type == GPIOD_LINE_EVENT_RISING_EDGE) {
                printf("Flanco de subida detectado. Tiempo transcurrido: %ld ns.\n", elapsed_time_ns);
            } else if (event.event_type == GPIOD_LINE_EVENT_FALLING_EDGE) {
                printf("Flanco de bajada detectado. Tiempo transcurrido: %ld ns.\n", elapsed_time_ns);

    return EXIT_SUCCESS;

Maybe the only way to get this running would be to writing a specific C driver for the sensor?

Hi @germanmorgan ,

As mentioned by @Edward , obtaining accurate timings for these sensors can be challenging on the userspace side. With that in mind, I believe that libgpiod may not provide the necessary support to achieve your desired result.

Considering this, the most straightforward alternative would likely involve using a kernel driver. You can find the w1_therm.c driver, which appears to support the sensor you’re working with. Additionally, you can access relevant documentation here. I recommend implementing this driver and assessing whether it meets your requirements.

If you have any further questions, please don’t hesitate to reach out.

Best regards,
Daniel Morais