All Products
Search
Document Center

IoT Platform:Porting to an Espressif ESP32 development board

Last Updated:Jun 03, 2026

This topic describes how to port C-SDK 4.0 to an ESP32 development board and use the MQTT demo to connect to Alibaba Cloud IoT Platform.

This tutorial covers the following steps:

  1. Set up the ESP-IDF development environment on macOS or Linux.

  2. Add C-SDK 4.0 as a custom ESP-IDF component.

  3. Replace the demo entry file and resolve the mbedTLS conflict.

  4. Compile, flash, and verify the MQTT connection to IoT Platform.

    Prerequisites

    Before you begin, make sure you have:

    • An ESP32 development board (this tutorial uses an ESP32 Core Board V2/ESP32 DevKitC with an onboard ESP-WROOM-32 module, a USB-to-serial module CP2102, and a power module).

    • A USB cable.

    • A computer running Linux or macOS.

    Also create an IoT Platform product and device before you start:

    1. Log in to the IoT Platform console and create a product.

    2. Create a device under the product and record the ProductKey, DeviceName, and DeviceSecret. You need these credentials when compiling the firmware.

      Note

      This tutorial uses macOS as the development environment. If you use a different operating system, see the official ESP32 getting started tutorial to set up your development environment.

    Set up the development environment

    Note

    This section is for reference only. If you run into issues, contact your development board supplier for help. To speed up the setup process, see the Espressif official getting started tutorial.

    1. Install the required packages.

    2. Clone the esp-idf repository.

      This tutorial uses the release/v4.2 branch. Other versions may cause compatibility issues.

      cd ~
      mkdir esp && cd esp
      git clone --recursive -b release/v4.2 https://github.com/espressif/esp-idf.git
    3. Install the toolchain and compilation tools.

      cd esp-idf
      ./install.sh
    4. Configure environment variables.

      • Run the export script:

        . $HOME/esp/esp-idf/export.sh
      • To avoid running this script every time, add the following function to $HOME/.bash_profile:

        set_esp32 ()
        {
            export IDF_PATH=$HOME/esp/esp-idf
            . $HOME/esp/esp-idf/export.sh
        }
    5. Copy the Wi-Fi station example to a working directory.

      cd ~/esp
      cp -r $IDF_PATH/examples/wifi/getting_started/station .
    6. Connect the development board.

    7. Configure the project.

      Run idf.py menuconfig and use the default configuration.

    8. Build, flash, and monitor.

      • In the station project directory, run idf.py build to compile.

      • After the compilation is complete, run idf.py -p PORT flash to flash the firmware. Replace PORT with your actual USB port name.

      • After the firmware is flashed, run idf.py -p PORT monitor to open the serial port monitor.

      • You can also run idf.py -p PORT flash monitor to flash and monitor in one command.

      The ESP32 development environment is now set up, and you have verified that the wifi station example compiles and runs. The following sections cover how to port C-SDK 4.0 and connect to IoT Platform.

    Port C-SDK 4.0

    Porting C-SDK 4.0 involves three tasks: adding the SDK as an idf component, replacing the port file adapted for ESP32, and resolving the mbedTLS library conflict.

    The portfiles directory in the C-SDK already contains the port file for ESP32, so porting primarily means importing the SDK source code and configuring the build system.

    Key concepts

    Read the ESP-IDF build system introduction for background. Two concepts are central to this tutorial:

    • project: The folder containing source files and configuration files for building the app.

    • components: Reusable, self-contained code units compiled into .a static libraries and linked to the app. Custom components go in the components directory of idf.

    The ESP-IDF build system uses CMake and ninja. To integrate C-SDK, move its source code into the components directory and add a CMakeLists.txt file.

    Porting methods

    • Method 1: Import the C-SDK into the project directory. Compile the SDK source code together with your other app source code.

    • Method 2: Import the C-SDK as a custom idf component into the components directory of idf.

    This tutorial uses Method 2. Using the C-SDK as an independent component helps you reuse it across multiple projects and keeps it decoupled from your application code.

    The following table shows the relevant C-SDK directories:

    Directory

    Contents

    core/

    Core SDK source files and headers

    core/sysdep/

    System dependency abstractions (includes core_adapter.c)

    core/utils/

    Utility functions

    portfiles/aiot_port/

    Platform-specific port files, including the ESP32-adapted posix_port.c

    external/

    Third-party libraries bundled with the SDK

    Porting procedure

    1. Add C-SDK as a custom component.

      Download C-SDK 4.0 and copy it to $IDF_PATH/components. In the C-SDK root directory, create a CMakeLists.txt file with the following content:

      set(include_dirs core core/sysdep core/utils)
      file(GLOB c_sdk_srcs
          "core/*.c"
          "core/utils/*.c"
          "core/sysdep/*.c"
          "portfiles/aiot_port/*.c"
          "external/*.c")
      idf_component_register(SRCS ${c_sdk_srcs}
                             INCLUDE_DIRS "${include_dirs}"
                             REQUIRES mbedtls)
      Note
      • C-SDK depends on the mbedTLS library. REQUIRES mbedtls declares this component dependency.

      • C-SDK has no Kconfig configuration items. No component Kconfig setup is needed.

      • To use advanced SDK features such as the Thing Specification Language (TSL) model or Over-the-Air (OTA) updates, add the corresponding source and header file paths to this CMakeLists.txt.

    2. Replace the port file and disable the mbedTLS conflict.

      Download posix_port.c, which has been adapted for ESP32. Replace $IDF_PATH/components/C-SDK/portfiles/aiot_port/posix_port.c with this file.

      Both LinkSDK and ESP-IDF bundle the mbedTLS library. To avoid symbol conflicts at link time, open $IDF_PATH/components/C-SDK/core/sysdep/core_adapter.c and disable the CORE_ADAPTER_MBEDTLS_ENABLED macro.

    3. Replace the demo entry file.

      Download station_example_main.c and replace station/main/station_example_main.c in your station example.

      Note
      • wifi_init_sta() retries the Wi-Fi connection until it reaches the limit defined by the EXAMPLE_ESP_MAXIMUM_RETRY macro.

      • After the Wi-Fi connection is established, the demo calls the C-SDK API to open an MQTT connection. Once connected, the device can exchange data with IoT Platform.

      • linkkit_main() contains the original C-SDK MQTT demo logic.

    4. Compile and flash.

      • In the project directory, run idf.py menuconfig and open the Example Configuration menu.

      • Set WiFi SSID, WiFi Password, and Maximum retry, then save and exit.

      • Run idf.py build to compile.

      • After the compilation is successful, run idf.py -p /dev/cu.SLAB_USBtoUART flash monitor to flash the firmware and open the serial port monitor.

      Note

      If the device uses Pre-Shared Key (PSK) key exchange, enable PSK support in mbedTLS and set the maximum PSK length to 64:

      • In idf.py menuconfig, go to Component config > mbedTLS > TLS Key Exchange Methods.

      • Enable Enable pre-shared-key ciphersuites.

      • In the CMakeLists.txt of the mbedTLS component, add set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBEDTLS_PSK_MAX_LEN=64").

    5. Verify the connection.

      A successful connection produces output similar to the following:

      ......
      I (829) phy: phy_version: 4180, cb3948e, Sep 12 2019, 16:39:13, 0, 0
      I (829) wifi: mode : sta (30:ae:a4:04:81:84)
      I (829) wifi station: wifi_init_sta finished.
      I (949) wifi: new:<11,0>, old:<1,0>, ap:<255,255>, sta:<11,0>, prof:1
      I (949) wifi: state: init -> auth (b0)
      I (969) wifi: state: auth -> assoc (0)
      I (969) wifi: state: assoc -> run (10)
      I (1129) wifi: connected with C_SDK_Test, aid = 1, channel 11, BW20, bssid = ec:26:ca:4b:68:cc
      I (1129) wifi: security type: 3, phy: bgn, rssi: -37
      I (1139) wifi: pm start, type: 1
      I (1219) wifi: AP's beacon interval = 102400 us, DTIM period = 1
      I (2129) esp_netif_handlers: sta ip: 192.168.0.100, mask: 255.255.255.0, gw: 192.168.0.1
      I (2129) wifi station: got ip:192.168.0.100
      I (2129) wifi station: connected to ap SSID:C_SDK_Test password:1234abcd
      I (2139) wifi station: Start linkkit mqtt
      [1.583][LK-0313] MQTT user calls aiot_mqtt_connect api, connect
      [1.587][LK-0317] mqtt_basic_demo&a13FNXXXXXX
      [1.590][LK-0318] 4780A5F17990D8DC4CCAD392683ED80160C4C2A1FFA649425CD0E2666A8593EB
      [1.598][LK-0319] a13FN5TplKq.mqtt_basic_demo|timestamp=2524608000000,_ss=1,_v=sdk-c-4.0.0,securemode=2,signmethod=hmacsha256,ext=1,|
      establish mbedtls connection with server(host='a13FN5TplKq.iot-as-mqtt.cn-shanghai.aliyuncs.com', port=[443])
      success to establish mbedtls connection, fd = 54(cost 29739 bytes in total, max used 44007 bytes)
      [3.493][LK-0313] MQTT connect success in 1910 ms
      AIOT_MQTTEVT_CONNECT
      [3.494][LK-0309] sub: /sys/a13FN5TplKq/mqtt_basic_demo/thing/event/+/post_reply
      [3.499][LK-0309] pub: /sys/a13FN5TplKq/mqtt_basic_demo/thing/event/property/post
      [LK-030A] > 7B 22 69 64 22 3A 22 31  22 2C 22 76 65 72 73 69 | {"id":"1","versi
      [LK-030A] > 6F 6E 22 3A 22 31 2E 30  22 2C 22 70 61 72 61 6D | on":"1.0","param
      [LK-030A] > 73 22 3A 7B 22 4C 69 67  68 74 53 77 69 74 63 68 | s":{"LightSwitch
      [LK-030A] > 22 3A 30 7D 7D                                   | ":0}}
      suback, res: -0x0000, packet id: 1, max qos: 1
      [3.573][LK-0309] pub: /sys/a13FN5TplKq/mqtt_basic_demo/thing/event/property/post_reply
      [LK-030A] < 7B 22 63 6F 64 65 22 3A  32 30 30 2C 22 64 61 74 | {"code":200,"dat
      [LK-030A] < 61 22 3A 7B 7D 2C 22 69  64 22 3A 22 31 22 2C 22 | a":{},"id":"1","
      [LK-030A] < 6D 65 73 73 61 67 65 22  3A 22 73 75 63 63 65 73 | message":"succes
      [LK-030A] < 73 22 2C 22 6D 65 74 68  6F 64 22 3A 22 74 68 69 | s","method":"thi
      [LK-030A] < 6E 67 2E 65 76 65 6E 74  2E 70 72 6F 70 65 72 74 | ng.event.propert
      [LK-030A] < 79 2E 70 6F 73 74 22 2C  22 76 65 72 73 69 6F 6E | y.post","version
      [LK-030A] < 22 3A 22 31 2E 30 22 7D                          | ":"1.0"}
      pub, qos: 0, topic: /sys/a13FNXXXXXX/mqtt_basic_demo/thing/event/property/post_reply
      pub, payload: {"code":200,"data":{},"id":"1","message":"success","method":"thing.event.property.post","version":"1.0"}
      heartbeat response
      heartbeat response
      heartbeat response
      ......

      Look for MQTT connect success and AIOT_MQTTEVT_CONNECT in the output. Recurring heartbeat response lines confirm that the MQTT connection is maintained.

      Important

      If you see the aiot_mqtt_connect failed: -0x0F0F error, this is a network connectivity issue. Check your Wi-Fi network status and make sure the board is within range of the access point. If necessary, reflash the firmware and retry.

      The error code -0x0F0F corresponds to STATE_PORT_NETWORK_CONNECT_TIMEOUT, indicating that the connection attempt timed out.

Troubleshooting

MQTT connection fails with aiot_mqtt_connect failed: -0x0F0F

The error code -0x0F0F maps to STATE_PORT_NETWORK_CONNECT_TIMEOUT, which means the board could not reach the IoT Platform server within the timeout period. Check the following:

  • Confirm the board is within Wi-Fi signal range and connected to the correct SSID.

  • Verify the WiFi SSID and WiFi Password values you entered in idf.py menuconfig.

  • If the problem persists, reflash the firmware and retry.

Build fails with duplicate mbedTLS symbols

Both LinkSDK and ESP-IDF include mbedTLS. If you see linker errors about duplicate symbols, make sure you have disabled CORE_ADAPTER_MBEDTLS_ENABLED in core_adapter.c as described in step 2 of the porting procedure.

Device resets continuously after flashing

Try erasing the flash before reflashing:

idf.py -p PORT erase_flash
idf.py -p PORT flash monitor

Serial port not recognized on macOS

Make sure the CP2102 USB driver is installed. See Establish Serial Connection with ESP32 for driver installation instructions.