Device Initialization

Last Updated on : 2023-11-29 09:04:39download

This topic describes how initialization works on Bluetooth devices.



Device initialization is the first stage that a program performs to prepare itself for operation. After the device is powered, it calls a range of functions to initialize the hardware environment, TuyaOS software, Bluetooth stack, and applications.

Tuya-enabled Bluetooth devices follow the typical initialization process of embedded systems. And a set of generic APIs makes it easy to port across platforms.


API calls during global initialization:

Device Initialization

The TuyaOS Bluetooth LE SDK provides multiple initialization APIs, which are called by the SDK at different times. The APIs for device initialization are exposed to developers.

OPERATE_RET tuya_init_first(VOID_T)
OPERATE_RET tuya_init_second(VOID_T)
OPERATE_RET tuya_init_third(VOID_T)
OPERATE_RET tuya_init_last(VOID_T)
OPERATE_RET tuya_main_loop(VOID_T)

The table below lists the differences between initialization APIs.

API Timing Use cases
tuya_init_first Invoked after the MCU is initialized. Initialize the basic peripherals and resources. The device is required to respond immediately after startup.
tuya_init_second Invoked before or when the Bluetooth stack is initialized. Initialize the Bluetooth stack and logging.
tuya_init_third Invoked after the Bluetooth stack is initialized. Features that can only be initialized after obtaining the status of the Bluetooth stack.
Initialize the advanced peripherals, digital interfaces, and main business services.
tuya_init_last The final stage for SDK initialization. Initialize the remaining business services and features.
tuya_main_loop Main loop The loop function, also known as the task loop API, is where multiple functions are implemented, for example, the processing of queues or events and the software timer handler.

The above APIs are invoked in two layers and involve the following APIs.

OPERATE_RET tal_init_first(VOID_T);
OPERATE_RET tal_init_second(VOID_T);
OPERATE_RET tal_init_third(VOID_T);
OPERATE_RET tal_init_last(VOID_T);
OPERATE_RET tal_main_loop(VOID_T);

OPERATE_RET tkl_init_first(VOID_T);
OPERATE_RET tkl_init_second(VOID_T);
OPERATE_RET tkl_init_third(VOID_T);
OPERATE_RET tkl_init_last(VOID_T);
OPERATE_RET tkl_main_loop(VOID_T);

In the end, the tkl_…… APIs are directly invoked by the chip platform’s main or main-like function.

In the TuyaOS Bluetooth LE APIs, this is the only set of APIs that use reverse invoke. It serves as an entry point for the entire SDK, avoiding further reverse invoke. This design isolates Tuya’s SDK from the chip vendor’s SDK and enables cross-platform development.

Data structure


typedef struct {
    UINT8_T  *p_firmware_name;
    UINT8_T  *p_firmware_version;
    UINT32_T firmware_version;
    UINT8_T  *p_hardware_version;
    UINT32_T hardware_version;

    UINT8_T  *p_sdk_version;
    UINT8_T  *p_kernel_version;
} tal_common_info_t;
  • p_firmware_name: The pointer to the firmware name, in string format.
  • p_firmware_version: The pointer to the firmware version, in string format.
  • firmware_version: The firmware version, in numeric value format.
  • p_hardware_version: The pointer to the hardware version, in string format.
  • hardware_version: The hardware version, in numeric value format.
  • p_sdk_version: The pointer to the SDK version, in string format.
  • p_kernel_version: The pointer to the kernel version, in string format.

API description

This section describes the important APIs in the device initialization process.

Turn logging on/off

Device Initialization

For more information about vendor logging, see Development Platform.

Log output


Initialize logging settings

OPERATE_RET tal_log_create_manage_and_init(CONST TAL_LOG_LEVEL_E level, CONST INT_T buf_len, CONST TAL_LOG_OUTPUT_CB output);

Print standard TuyaOS logs with time and location, supporting logging level, string, and data stream.

  • level is used to define the logging level, defaulting to TAL_LOG_LEVEL_DEBUG.

  • buf_len specifies the maximum length of the log buffer.

  • output is the exit function for log output, which is specified in the application layer. It defaults to tuya_log_output_cb.

Turn testing on/off

To turn the testing code on, set TUYA_SDK_TEST to 1.

To turn the testing code off, set TUYA_SDK_TEST to 0.

You can test pairing, communication, and peripherals using the testing code and host. Be sure to turn the testing feature off for the production firmware.

Turn debug mode on/off


If your project is not currently intended for production, you can perform temporary authorization in the debug mode. This is only for debugging purposes. Before production, change the code back.

Initialize dynamic memory

The size of the dynamic memory: BOARD_HEAP_SIZE

#define BOARD_HEAP_SIZE 5120

VOID_T tuya_memory_init(VOID_T)
    tuya_mem_heap_create(heap_pool, BOARD_HEAP_SIZE, &heap_handle);

Initialize device information

OPERATE_RET app_config_info_set(VOID_T)
    tal_common_info_t tal_common_info   = {0};
    tal_common_info.p_firmware_name     = (UINT8_T*)FIRMWARE_NAME;
    tal_common_info.p_firmware_version  = (UINT8_T*)FIRMWARE_VERSION;
    tal_common_info.firmware_version    = FIRMWARE_VERSION_HEX;
    tal_common_info.p_hardware_version  = (UINT8_T*)HARDWARE_VERSION;
    tal_common_info.hardware_version    = HARDWARE_VERSION_HEX;
    tal_common_info.p_sdk_version       = (UINT8_T*)"0.2.0";
    tal_common_info.p_kernel_version    = (UINT8_T*)"0.0.1";
    return tal_common_info_init(&tal_common_info);

Test power-up time

OPERATE_RET tuya_init_first(VOID_T)
#if defined(TUYA_SDK_TEST) && (TUYA_SDK_TEST == 1)
    TUYA_GPIO_BASE_CFG_T gpio_cfg = {
        .mode = TUYA_GPIO_PUSH_PULL,
        .direct = TUYA_GPIO_OUTPUT,
        .level = TUYA_GPIO_LEVEL_LOW,
    tal_gpio_init(BOARD_POWER_ON_PIN, &gpio_cfg);


    return OPRT_OK;

To determine the power-up time of a chip platform, utilize a logic analyzer to test the time difference between the VCC and BOARD_POWER_ON_PIN pins being pulled high.

For more information about the test result, see Development Platform.

Initialize Bluetooth stack

OPERATE_RET tal_ble_bt_init(TAL_BLE_ROLE_E role, CONST TAL_BLE_EVT_FUNC_CB ble_event);

Set the initial value of parameters including radio frequency (RF), Generic Access Profile (GAP), and Generic Attribute Profile (GATT), specify the services and characteristic values, and initialize the connection status, advertising, and scanning (if applicable).

  • The valid values of role are central, peripheral, and beacon. The default value is peripheral.

  • ble_event is the Bluetooth event callback. Its value is tuya_ble_evt_callback in the application layer, handling Bluetooth events such as connection, disconnection, discovering, and connection parameters update.

Initialize Bluetooth pairing

VOID_T tuya_ble_protocol_init(VOID_T)
    tuya_ble_protocol_param.firmware_version = tal_common_info.firmware_version,
    tuya_ble_protocol_param.hardware_version = tal_common_info.hardware_version,
    memcpy(tuya_ble_protocol_param.device_id,       device_id_test, DEVICE_ID_LEN);
    memcpy(tuya_ble_protocol_param.auth_key,        auth_key_test, AUTH_KEY_LEN);
    memcpy(tuya_ble_protocol_param.mac_addr_string, TY_DEVICE_MAC, MAC_STRING_LEN);
    memcpy(tuya_ble_protocol_param.product_id,      TY_DEVICE_PID, tuya_ble_protocol_param.product_id_len);
    memcpy(tuya_ble_protocol_param.adv_local_name, TY_DEVICE_NAME, tuya_ble_protocol_param.adv_local_name_len);


  • tuya_ble_sdk_init() is used to initialize the parameters including firmware version, MAC address, device ID, authkey, PID, and advertising name.

  • tuya_ble_callback_queue_register() is used to register callbacks to process pairing logic including pairing state, timestamp, DP data, and unbinding.

This API is used to process pairing parameters and events in the communication between the Tuya-enabled Bluetooth device and the Smart Life app.

Initialize serial port

The serial port is used for production authorization testing and functional testing, with a default baud rate of 9600 bps.

Note: If you use Tuya’s flashing tool, the baud rate must be 9600.

TAL_UART_CFG_T tal_uart_cfg = {
    .rx_buffer_size = 256,
    .open_mode = O_BLOCK,
        .baudrate = 9600,
        .parity = TUYA_UART_PARITY_TYPE_NONE,
        .databits = TUYA_UART_DATA_LEN_8BIT,
        .stopbits = TUYA_UART_STOP_LEN_1BIT,
        .flowctrl = TUYA_UART_FLOWCTRL_NONE,

STATIC VOID_T tuya_uart_irq_rx_cb(TUYA_UART_NUM_E port_id, VOID_T *buff, UINT16_T len)
    if (port_id == TUYA_UART_NUM_0) {
        tuya_ble_common_uart_receive_data(buff, len);
    } else {
#if defined(TUYA_SDK_TEST) && (TUYA_SDK_TEST == 1)
        test_cmd_send(TEST_ID_GET(TEST_GID_UART, TEST_CID_RX_UART_PORT), (VOID_T*)&port_id, SIZEOF(UINT32_T));
        test_cmd_send(TEST_ID_GET(TEST_GID_UART, TEST_CID_RX_UART_DATA), buff, len);

OPERATE_RET tuya_init_last(VOID_T)
    tal_uart_init(TUYA_UART_NUM_0, &tal_uart_cfg);
    tal_uart_rx_reg_irq_cb(TUYA_UART_NUM_0, tuya_uart_irq_rx_cb);


    return OPRT_OK;

About the driver API

TuyaOS Kernel Layer (TKL) provides a set of standard driver APIs required to run a minimum viable TuyaOS product. Note that not all drivers have the TKL API.

If the driver you need in the TKL is not implemented or not available, you can use the API provided by the chip vendor directly.

Support and help

If you have any problems with TuyaOS development, you can post your questions in the Tuya Developer Forum.