GPIO pull up timing

Hi,

We are testing a custom board based on the nRF5340 that drives an RGB LED strip using the TI TLC5947 LED driver.

The TLC5947 has an OE (Blank) pin that disables/enables the outputs. When the system powers up, the LEDs briefly flash before the MCU finishes initializing, which we’d like to avoid.
Our board does not include a hardware pull-up on the OE pin, so I enabled the internal pull-up in the device tree as follows:

rgb_led_strip: rgb_strip {
    compatible = "ti,tlc5947";
    clk-gpios = <&gpio1 11 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
    data-gpios = <&gpio1 10 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
    lat-gpios  = <&gpio1 12 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
    oe-gpios   = <&gpio1 13 (GPIO_PULL_UP   | GPIO_ACTIVE_HIGH)>;
    chain-length = <1>;
    color-mapping = <3 2 1>;
    status = "okay";
};

Initialization function

int tlc5947_init(const struct device *dev)
{
    const struct tlc5947_config *cfg = dev->config;
    const struct gpio_dt_spec *clk = &cfg->clk;
    const struct gpio_dt_spec *data = &cfg->data;
    const struct gpio_dt_spec *latch = &cfg->latch;
    const struct gpio_dt_spec *blank = &cfg->blank;

    int err = 0;
    if(!gpio_is_ready_dt(clk))
    {
        LOG_ERR("%s: no LEDs found (DT child nodes missing)", dev->name);
		return -ENODEV;
    }
    if(!gpio_is_ready_dt(data))
    {
        LOG_ERR("%s: no LEDs found (DT child nodes missing)", dev->name);
		return -ENODEV;
    }
    if(!gpio_is_ready_dt(latch))
    {
        LOG_ERR("%s: no LEDs found (DT child nodes missing)", dev->name);
		return -ENODEV;
    }
    if(!gpio_is_ready_dt(blank))
    {
        LOG_ERR("%s: no LEDs found (DT child nodes missing)", dev->name);
		return -ENODEV;
    }
    err = gpio_pin_configure_dt(clk, GPIO_OUTPUT_INACTIVE);
	if (err < 0) {
		LOG_ERR("%s: Unable to setup clk port", dev->name);
		return -EIO;
	}
    err = gpio_pin_configure_dt(data, GPIO_OUTPUT_INACTIVE);
	if (err < 0) {
		LOG_ERR("%s: Unable to setup data port", dev->name);
		return -EIO;
	}
    err = gpio_pin_configure_dt(latch, GPIO_OUTPUT_INACTIVE);
	if (err < 0) {
		LOG_ERR("%s: Unable to setup LAT port", dev->name);
		return -EIO;
	}
    err = gpio_pin_configure_dt(blank, GPIO_PULL_UP | GPIO_OUTPUT_ACTIVE);
	if (err < 0) {
		LOG_ERR("%s: Unable to setup OE port", dev->name);
		return -EIO;
	}
 //gpio_pin_set_dt(blank, 1);

    return 0;
}

Module definition
#define TLC5947_DATA_BUFFER_LENGTH(i) (DT_INST_PROP(i, num_channels))

#define TLC5947_DEVICE(i)                                                                         \
	static struct tlc5947_config tlc5947_config_##i = {                                            \
		.clk = GPIO_DT_SPEC_INST_GET(i, clk_gpios),                                                 \
        .data = GPIO_DT_SPEC_INST_GET(i, data_gpios),                                           \
        .latch = GPIO_DT_SPEC_INST_GET(i, lat_gpios),                                         \
        .blank = GPIO_DT_SPEC_INST_GET(i, oe_gpios),                                          \
		.channels = DT_INST_PROP(i, num_channels),                                      \
        .max_pwm = DT_INST_PROP(i, max_pwm),                                         \
	};                                                                                         \
    static uint16_t tlc5947_##i##_data_buffer[TLC5947_DATA_BUFFER_LENGTH(i)];             \
	static struct tlc5947_data tlc5947_##i##_data = {                                       \
		.data_buffer = tlc5947_##i##_data_buffer,                                       \
		.gbc_color_1 = 4096,                              \
		.gbc_color_2 = 4096,                              \
		.gbc_color_3 = 4096,                              \
	};                                                      \
                                                                                                   \
	DEVICE_DT_INST_DEFINE(i, tlc5947_init, NULL, &tlc5947_##i##_data, &tlc5947_config_##i, POST_KERNEL,   \
			        40, &tlc5947_gpio_api);
DT_INST_FOREACH_STATUS_OKAY(TLC5947_DEVICE)

Goal

Prevent any LED activity at power-up by ensuring OE = HIGH (outputs disabled) as early as possible, ideally before or during MCU startup.

Questions

  1. Is my GPIO configuration correct to guarantee OE stays HIGH before firmware initialization?
    (i.e., should I rely on the internal pull-up or configure OE earlier in system startup?)

  2. Is there a recommended way to ensure that OE remains asserted immediately after reset, before Zephyr fully configures the pins (e.g., via pinctrl or bootloader stage)?


Parents
  • Hello,

    Does the "glitch"  happen during the initialization in tlc5947_init()? Since all the pins are outputs, I don’t see any reason to enable the pull-ups or pull-downs. The active high outputs initialized with the GPIO_OUTPUT_INACTIVE flag should be configured as output low and ensure that the signal is driven low. Are the pads accessible so you can probe the signals with a scope or logic analyzer? 

    Best regards,

    Vidar

Reply
  • Hello,

    Does the "glitch"  happen during the initialization in tlc5947_init()? Since all the pins are outputs, I don’t see any reason to enable the pull-ups or pull-downs. The active high outputs initialized with the GPIO_OUTPUT_INACTIVE flag should be configured as output low and ensure that the signal is driven low. Are the pads accessible so you can probe the signals with a scope or logic analyzer? 

    Best regards,

    Vidar

Children
No Data
Related