Skip to main content

TDD/TDL Driver Architecture

TuyaOpen uses a two-layer peripheral driver framework: TDL (Tuya Driver Layer) manages device lifecycle and provides the application API, while TDD (Tuya Device Driver) implements chip-specific hardware access. This separation lets you add new hardware without changing application code.

Layer Overview

LayerPrefixRoleWho writes it
TDLtdl_*Device management, registration, application APITuyaOpen SDK (you rarely modify this)
TDDtdd_*Hardware-specific driver implementing the TDL interfaceYou, when adding a new sensor/display/codec
TKLtkl_*Platform abstraction (GPIO, I2C, SPI, UART)Platform adapter (per chip)

The Registration Pattern

Every peripheral category follows the same pattern:

1. TDL defines an interface struct

typedef struct {
OPERATE_RET (*create)(TDL_OPRT_INFO *dev);
OPERATE_RET (*delete)(TDL_OPRT_INFO *dev);
OPERATE_RET (*read_value)(TDL_OPRT_INFO *dev, uint8_t *value);
} TDL_BUTTON_CTRL_INFO;

2. TDD implements the interface and registers

OPERATE_RET tdd_gpio_button_register(char *name, BUTTON_GPIO_CFG_T *cfg)
{
TDL_BUTTON_CTRL_INFO ctrl = {
.create = __tdd_create_gpio_button,
.delete = __tdd_delete_gpio_button,
.read_value = __tdd_read_gpio_value,
};
return tdl_button_register(name, &ctrl, &device_info);
}

3. Board init calls TDD registration

void board_register_hardware(void)
{
BUTTON_GPIO_CFG_T btn_cfg = {
.pin = BOARD_BUTTON_PIN,
.level = BOARD_BUTTON_ACTIVE_LV,
.mode = BUTTON_IRQ_MODE,
};
tdd_gpio_button_register("power_btn", &btn_cfg);
}

4. Application uses TDL only

board_register_hardware();

TDL_BUTTON_HANDLE handle;
TDL_BUTTON_CFG_T cfg = { .long_start_valid_time = 3000 };
tdl_button_create("power_btn", &cfg, &handle);
tdl_button_event_register(handle, TDL_BUTTON_PRESS_DOWN, my_callback);

Peripheral Categories

CategoryTDL HeaderTDD ExamplesSource Path
Buttontdl_button_driver.htdd_button_gpiosrc/peripherals/button/
LEDtdl_led_driver.htdd_led_gpiosrc/peripherals/led/
LED Pixeltdl_pixel_driver.htdd_ws2812, tdd_sm16703psrc/peripherals/leds_pixel/
Displaytdl_display_driver.htdd_disp_spi, tdd_disp_rgbsrc/peripherals/display/
Audiotdl_audio_driver.htdd_audio (T5AI), tdd_audio_alsasrc/peripherals/audio_codecs/
Cameratdl_camera_driver.htdd_camera_dvp_ov2640src/peripherals/camera/
Touchtdl_tp_driver.htdd_tp_i2c_ft6336, tdd_tp_i2c_gt911src/peripherals/tp/
IRtdl_ir_driver.htdd_ir_driversrc/peripherals/ir/
Joysticktdl_joystick_driver.htdd_joysticksrc/peripherals/joystick/
Transporttdl_transport_driver.htdd_transport_uartsrc/peripherals/transport/

Peripherals Without TDL/TDD

Some peripherals use direct TKL calls without the registration framework:

PeripheralPatternExample
IMU (BMI270)Vendor library + tkl_i2c_*examples/peripherals/imu/bmi270/
EncoderStandalone drv_encodersrc/peripherals/encoder/
SHT3x/SHT4xDirect I2C readsexamples/peripherals/i2c/sht3x_4x_sensor/
PMIC (AXP2101)Vendor driversrc/peripherals/pmic/axp2101/

For simple sensors (temperature, humidity, pressure), you typically use TKL I2C directly rather than creating a TDL/TDD layer. See Writing a New Sensor Driver.

Kconfig Integration

Each peripheral is gated by a Kconfig toggle in boards/{platform}/TKL_Kconfig:

config ENABLE_BUTTON
bool
default n

config ENABLE_LED
bool
default n

Board-specific Kconfig files select which peripherals to enable:

config BOARD_CONFIG
select ENABLE_BUTTON
select ENABLE_LED
select ENABLE_AUDIO

The build system compiles only the enabled TDD drivers.

References