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
-
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?) -
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)?