WT9932P4C61-TINY Development Guide

  • WT9932P4C61-TINY
  • ESP32-P4
  • ESP32-C61
  • WT_BSP
  • BSP
  • ESP-IDF
  • Git
Update history
Date Version Author Update content
2026-07-15 1.1.0 Yobie Zhou Added WT_BSP download and update instructions and synchronized the latest examples and development workflow
2026-07-09 1.0.0 Yobie Zhou Added application development workflow based on WT_BSP

1. Development Model

WT_BSP is the board support package maintained by Wireless-Tag for ESP32 development boards. When developing for the WT9932P4C61-TINY, build application logic on top of WT_BSP instead of hard-coding GPIO numbers, display initialization parameters, camera pins, or SD card pins in application code.

The recommended workflow is:

  1. Add the BSP component from components/wt_bsp to the application project.
  2. Select WT9932P4C61-TINY with idf.py set-board.
  3. Call wt_bsp_init() to initialize board resources.
  4. Obtain resource handles with wt_bsp_get_rgb(), wt_bsp_get_button(), wt_bsp_get_sdmmc(), wt_bsp_get_dsi(), wt_bsp_get_csi(), and wt_bsp_get_touch().
  5. Check each returned handle before using the corresponding feature.

This approach provides the following benefits:

  • Application code is not tied to specific hardware pins.
  • The same example can be adapted to multiple Wireless-Tag boards with fewer changes.
  • Unused peripheral features can be disabled through menuconfig.
  • Board-specific differences are maintained in components/wt_bsp/boards/WT9932P4C61-TINY.

2. Get and Update WT_BSP

The official WT_BSP repository is available at:

The repository is actively maintained. Clone the official repository for a new installation. If it is already present locally, synchronize its main branch before starting a project or troubleshooting an issue so that you use the latest board adaptations, examples, and tools.

2.1 Requirements

Prepare the following software:

  • Git.
  • ESP-IDF. WT_BSP is optimized for ESP-IDF v6.0.1 and later and is compatible with v5.3 and later. Use v6.0.1 or a newer version for a new project.
  • An activated ESP-IDF environment in which idf.py --version runs successfully.

2.2 Clone the Repository

Choose a directory for development projects and clone the official repository:

mkdir -p ~/work
cd ~/work
git clone https://github.com/Wireless-TAG-Maker/WT_BSP.git
cd WT_BSP

The current repository does not require --recursive; a regular git clone is sufficient. After cloning, check the current branch and latest commit:

git status --short --branch
git log -1 --oneline

The repository should normally be on the main branch. The following sections assume this location:

~/work/WT_BSP

You may use another location. Replace the paths in the commands with the actual local path when necessary.

2.3 Update an Existing Repository

If WT_BSP already exists locally, enter the repository and check for uncommitted changes first:

cd ~/work/WT_BSP
git status --short --branch

If the working tree is clean, switch to main and synchronize official changes with a fast-forward-only pull:

git switch main
git pull --ff-only origin main

Check the synchronized revision:

git log -1 --oneline

If git status reports local changes, commit them on a development branch or temporarily save them with git stash before updating main. Do not discard local work merely to update the repository.

Recommendation: Keep custom applications outside the WT_BSP repository or on a dedicated Git branch. This reduces conflicts when synchronizing the official main branch. Teams should also record the tested WT_BSP commit so that other developers can reproduce the same build environment.

2.4 Verify the Latest Repository

After an update, build the minimal blink example to verify ESP-IDF, WT_BSP, and the board selection tool:

cd ~/work/WT_BSP/examples/get-started/blink
idf.py set-board
idf.py build

Select WT9932P4C61-TINY from the interactive list. For non-interactive selection, run:

WT_BSP_BOARD=WT9932P4C61-TINY idf.py set-board
idf.py build

set-board generates the board defaults used by the project. When switching to a board with a different target chip, the tool automatically runs fullclean.

3. WT_BSP Structure

Assuming the repository is located at:

~/work/WT_BSP

The main directories are:

Path Description
components/wt_bsp Core BSP component
components/wt_bsp/include Top-level public headers such as wt_bsp.h
components/wt_bsp/src Common BSP implementation
components/wt_bsp/features Reusable features such as RGB, button, SDMMC, DSI, CSI, and touch
components/wt_bsp/boards Board-specific adaptations
components/wt_bsp/boards/WT9932P4C61-TINY Board configuration and resource initialization for this board
components/wt_bsp/tools set-board, p4_flash, and CMake helper scripts
examples/get-started/blink Minimal RGB LED example for environment and BSP verification
examples/get-started/button Onboard button event example
examples/get-started/c61-hello-through-p4 C61 Hello example flashed through the P4 bridge
examples/display/dsi MIPI DSI display and LVGL example
examples/camera/csi MIPI CSI camera, PPA, and DSI live-view example
examples/storage/sdmmc MicroSD mounting and file I/O example
examples/wifi/esp-hosted/wt9932p4c61-tiny P4 Wi-Fi through the onboard C61 with ESP-Hosted
examples/wt_factory/wt9932p4c61-tiny Integrated display, camera, touch, SD card, and Wi-Fi factory example

Application developers normally need to focus on:

  • examples/: read the README.md of the example closest to the required feature, then copy or reference its code.
  • components/wt_bsp/include/wt_bsp.h: the top-level BSP API.
  • components/wt_bsp/features/*/include/: APIs for individual peripheral features.

Application code should not directly include private board files such as:

#include "boards/WT9932P4C61-TINY/board.h"
#include "board_config.h"

Use the unified interfaces exposed by wt_bsp.h instead.

4. Create an Application Project

4.1 Choose the Closest Example

The latest WT_BSP provides separate examples for the main features. Choose a starting point based on the application requirements:

Requirement Recommended Starting Point
Verify the environment or control the RGB LED examples/get-started/blink
Handle the onboard button examples/get-started/button
Drive a MIPI DSI display with LVGL examples/display/dsi
Capture and display MIPI CSI camera frames examples/camera/csi
Use a MicroSD card examples/storage/sdmmc
Use C61 Wi-Fi from the P4 examples/wifi/esp-hosted/wt9932p4c61-tiny
Develop or evaluate the C61 separately examples/get-started/c61-hello-through-p4
Combine display, camera, touch, SD card, and Wi-Fi examples/wt_factory/wt9932p4c61-tiny

Read the selected example's README.md to confirm its hardware connections and build steps before using it as the development baseline.

For a first custom application, copy blink because it has a small structure and clear dependencies:

get_idf
cd ~/work/WT_BSP/examples
mkdir -p my_apps
cp -r get-started/blink my_apps/my_p4c61_app
cd my_apps/my_p4c61_app

Remove old build output from the copied project:

rm -rf build managed_components sdkconfig sdkconfig.old

Keep and modify these files as needed:

File Action Description
CMakeLists.txt Keep Already integrates the WT_BSP CMake helper
main/CMakeLists.txt Keep Registers application sources
main/main.c Modify Replace with application logic
sdkconfig.defaults Keep or modify Project default configuration
sdkconfig.wt9932p4c61_tiny Keep Board defaults read by set-board
README.md / README_CN.md Modify Replace with application documentation

Select the board and build:

WT_BSP_BOARD=WT9932P4C61-TINY idf.py set-board
idf.py build

4.3 Required CMake Configuration

The top-level CMakeLists.txt must add the WT_BSP components directory and apply its board defaults.

For a project under WT_BSP/examples/..., use the pattern from the official examples:

cmake_minimum_required(VERSION 3.16)

set(EXTRA_COMPONENT_DIRS "../../../components")

include("../../../components/wt_bsp/tools/wt_bsp_project.cmake")
wt_bsp_apply_sdkconfig_defaults()

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(my_p4c61_app)

For an external project at ~/work/my_p4c61_app with WT_BSP at ~/work/WT_BSP, use an absolute BSP path:

cmake_minimum_required(VERSION 3.16)

set(WT_BSP_PATH "$ENV{HOME}/work/WT_BSP")
set(EXTRA_COMPONENT_DIRS "${WT_BSP_PATH}/components")

include("${WT_BSP_PATH}/components/wt_bsp/tools/wt_bsp_project.cmake")
wt_bsp_apply_sdkconfig_defaults()

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(my_p4c61_app)

Replace WT_BSP_PATH when the repository is stored elsewhere. A basic main/CMakeLists.txt is:

idf_component_register(SRC_DIRS "."
                    INCLUDE_DIRS ".")

4.4 Add Board Defaults

idf.py set-board looks for a board defaults file in the project. For WT9932P4C61-TINY, its name is:

sdkconfig.wt9932p4c61_tiny

The minimal selection entry is:

CONFIG_WT_BSP_BOARD_WT9932P4C61_TINY=y

Real applications may also require defaults for the partition table, PSRAM, LVGL, display, or camera. Copy the file from the closest official example and adjust it for the application.

Running idf.py set-board generates:

sdkconfig.board
sdkconfig.board.Kconfig

These files are generated by the tool and should not be edited manually.

5. Minimal Application Template

The following application initializes the BSP, turns on the RGB LED, and checks the board handle:

#include "esp_err.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "wt_bsp.h"

static const char *TAG = "my_app";

void app_main(void)
{
    esp_err_t ret = wt_bsp_init();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "BSP init failed: %s", esp_err_to_name(ret));
        return;
    }

    wt_bsp_board_t board = wt_bsp_get_board();
    if (board) {
        ESP_LOGI(TAG, "WT_BSP board initialized");
    }

    wt_bsp_rgb_t rgb = wt_bsp_get_rgb();
    if (rgb) {
        wt_bsp_rgb_set_pixel(rgb, 0, (wt_bsp_rgb_color_t){.r = 0, .g = 64, .b = 255});
        wt_bsp_rgb_refresh(rgb);
    }

    while (1) {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

Important points:

  • Call wt_bsp_init() before obtaining resources.
  • A wt_bsp_get_*() function can return NULL; always check its result.
  • Do not assume every board provides a display, camera, touch controller, or SD card.
  • Do not use private board pin macros in application code.

6. Select, Build, and Flash

6.1 Select the Board

Interactive selection:

idf.py set-board

Non-interactive selection:

WT_BSP_BOARD=WT9932P4C61-TINY idf.py set-board

Select directly while building:

WT_BSP_BOARD=WT9932P4C61-TINY idf.py build

When a project has multiple board configuration files, set-board lists the supported boards. Selecting WT9932P4C61-TINY sets the target to esp32p4.

6.2 Build

idf.py build

After changing the board, target chip, or low-level configuration, clean the project before retrying unexpected build failures:

idf.py fullclean
idf.py build

6.3 Flash an ESP32-P4 Application

Flash P4 applications through FUSB:

idf.py -p /dev/ttyACM0 flash monitor

Replace /dev/ttyACM0 with the actual port. Exit the monitor with:

Ctrl + ]

6.4 Configure Features with menuconfig

Open the configuration interface:

idf.py menuconfig

Disable unused peripheral features to reduce initialization overhead and dependencies, then rebuild:

idf.py build

Continue checking every wt_bsp_get_*() result because a resource may be unsupported, disabled in configuration, or unavailable after an initialization failure.

7. Common BSP Features

7.1 RGB LED

The board has an onboard WS2812 RGB LED:

wt_bsp_rgb_t rgb = wt_bsp_get_rgb();
if (rgb) {
    wt_bsp_rgb_set_pixel(rgb, 0, (wt_bsp_rgb_color_t){.r = 255, .g = 0, .b = 0});
    wt_bsp_rgb_refresh(rgb);
}

It can indicate startup, errors, network state, or user interaction.

7.2 Button

Obtain the default button handle and register a callback. Keep callbacks short; set a flag or send a queue message instead of running blocking operations:

static void button_cb(wt_bsp_button_t button,
                      wt_bsp_button_event_t event,
                      void *user_data)
{
    if (event == WT_BSP_BUTTON_EVENT_KEEPALIVE) {
        /* Set a flag or notify a task. */
    } else if (event == WT_BSP_BUTTON_EVENT_RELEASE) {
        /* Clear the long-press state or handle release. */
    }
}

wt_bsp_button_t button = wt_bsp_get_button();
if (button) {
    wt_bsp_button_register_event_cb(button, button_cb, NULL);
}

Refer to components/wt_bsp/features/button/include/wt_bsp_button.h for the current event definitions and APIs.

7.3 MicroSD

Obtain and mount the SD card resource before file operations:

wt_bsp_sdmmc_t sdmmc = wt_bsp_get_sdmmc();
if (sdmmc) {
    esp_err_t ret = wt_bsp_sdmmc_mount(sdmmc);
    if (ret == ESP_OK) {
        sdmmc_card_t *card = wt_bsp_sdmmc_get_card(sdmmc);
        (void)card;
    }
}

Insert the card before mounting, verify that mounting succeeded before file I/O, and close or synchronize important files promptly. The BSP handles SDMMC pins and power; application code should not initialize the bus again.

7.4 MIPI DSI Display and LVGL

Use these examples as references:

examples/display/dsi
examples/wt_factory/wt9932p4c61-tiny/main/main.c
examples/wt_factory/wt9932p4c61-tiny/main/lvgl_ui.c

Initialize the BSP, obtain the DSI resource, start LVGL using the BSP APIs, and protect all LVGL operations with the BSP LVGL lock helpers. LVGL is not thread-safe. The display FPC orientation and pinout must match the board.

7.5 MIPI CSI Camera

Start with examples/camera/csi. A typical flow initializes the BSP, obtains the CSI resource, registers a frame callback, starts capture, processes frames with PPA when appropriate, and sends the output to the display or application algorithm.

ESP32-P4 is well suited to display, camera, and image-transfer workloads. Hardware-accelerated PPA processing reduces CPU load for format conversion, scaling, and rotation.

7.6 Touch

Touch is normally used with the DSI display and LVGL. Obtain the touch resource from the BSP rather than initializing the controller again. The board adaptation maintains the supported panel, touch controller, and I2C configuration.

7.7 Wi-Fi and ESP32-C61

ESP32-P4 does not provide Wi-Fi by itself. The onboard ESP32-C61 supplies wireless connectivity:

Scenario Recommended Method
A P4 application needs Wi-Fi Use examples/wifi/esp-hosted/wt9932p4c61-tiny or the factory example; P4 accesses C61 Wi-Fi through ESP-Hosted / Wi-Fi Remote
Develop C61 firmware separately Run idf.py p4_flash through FUSB, then flash and debug C61 through HUSB

C61 firmware is not required for P4-only features such as RGB, display, camera, or SD card.

8. Develop from the Factory Example

For an application that combines display, camera, touch, SD card, and Wi-Fi, start from the factory example instead of adding every complex dependency to blink:

cd ~/work/WT_BSP/examples
mkdir -p my_apps
cp -r wt_factory/wt9932p4c61-tiny my_apps/my_factory_app
cd my_apps/my_factory_app
rm -rf build managed_components sdkconfig sdkconfig.old

Modify it in this order:

  1. Keep wt_bsp_init() and the main hardware initialization flow.
  2. Build, flash, and run the unmodified factory application first.
  3. Remove unused UI pages or controls.
  4. Retain the required SD card, camera, and Wi-Fi tasks.
  5. Replace the UI in lvgl_ui.c.
  6. Modify the business state machine in main.c.
  7. Adjust the partition table, NVS, log levels, and performance settings last.

Maintain a working baseline and replace one subsystem at a time so that failures are easier to locate.

9. Develop ESP32-C61 Firmware Separately

The onboard ESP32-C61 is flashed through a temporary P4 USB-UART bridge.

9.1 Use the Official C61 Example

The latest WT_BSP provides:

examples/get-started/c61-hello-through-p4

Run this example completely before using its C61 project as a custom development starting point.

9.2 Flash the P4 Bridge

Connect FUSB, enter the example, and run:

cd ~/work/WT_BSP/examples/get-started/c61-hello-through-p4
idf.py set-target esp32c61
idf.py p4_flash

Select the P4 serial port and enter Y when prompted to overwrite the current P4 firmware.

9.3 Switch to HUSB

After p4_flash succeeds:

  1. Disconnect FUSB.
  2. Connect HUSB.
  3. Attach the new USB device to WSL2 if applicable.
  4. Locate the new TinyUSB CDC port, for example with ls /dev/ttyACM*.

9.4 Flash the C61 Application

From the same example directory, flash through the HUSB TinyUSB CDC port:

idf.py -p <HUSB_CDC_PORT> flash monitor

Replace <HUSB_CDC_PORT> with the actual HUSB port. The example continuously prints messages containing Hello Wireless-tag after a successful flash.

Once the official example works, copy it and modify the C61 application. P4 is used only to install the bridge; subsequent C61 build, flash, and debugging operations use HUSB.

To restore a P4 application, reconnect FUSB and flash the P4 project again.

10. Debugging

10.1 Logs

Give each module its own log tag:

static const char *TAG = "my_module";
ESP_LOGI(TAG, "module started");

Increase the log level in menuconfig during development and reduce unnecessary output before release.

10.2 Build Directories

Use separate projects or build directories for P4 and C61 to prevent their target configurations from overwriting each other:

idf.py -B build_p4 build
idf.py -B build_c61 set-target esp32c61 build

10.3 Dependency Updates

ESP-IDF managed components create:

managed_components/
dependencies.lock

managed_components/ contains downloaded dependencies. dependencies.lock records resolved versions and should normally be retained for reproducible team builds.

10.4 Troubleshooting Order

Check problems in this order:

  1. Run idf.py --version and verify the ESP-IDF version.
  2. Run idf.py set-board and verify WT9932P4C61-TINY is selected.
  3. Run idf.py build and resolve build errors.
  4. Verify the port used by idf.py -p <PORT> flash monitor.
  5. Check whether wt_bsp_init() succeeds in the startup log.
  6. Check whether a required wt_bsp_get_*() call returns NULL.
  7. Verify peripheral connections, stable power, and FPC orientation.
  8. For C61 issues, verify the required slave or application firmware and distinguish FUSB from HUSB.

11. Development Guidelines

  • Include wt_bsp.h and application module headers in application code.
  • Do not depend on private headers under boards/<BOARD>/.
  • Check all wt_bsp_get_*() results for NULL.
  • Handle errors returned by BSP and ESP-IDF APIs.
  • Run long operations in FreeRTOS tasks rather than button callbacks or LVGL critical sections.
  • Update LVGL only while holding the appropriate lock or from the UI task.
  • Manage PSRAM, cache alignment, and frame-buffer lifetimes carefully for camera processing.
  • Protect SD card data against unexpected power loss.
  • Treat P4 and C61 as separate targets: P4 runs the main application and high-performance peripherals, while C61 provides wireless connectivity or independent low-power processing.
  1. Root README.md: confirm currently supported boards, ESP-IDF versions, and usage.
  2. examples/get-started/blink/README.md and main/main.c: learn board selection, BSP initialization, and RGB control.
  3. examples/get-started/button, examples/display/dsi, examples/camera/csi, and examples/storage/sdmmc: study the required standalone peripheral examples.
  4. components/wt_bsp/include/wt_bsp.h: review the top-level BSP API.
  5. components/wt_bsp/features/*/include/: review the RGB, Button, SDMMC, DSI, CSI, and Touch APIs as needed.
  6. examples/wifi/esp-hosted/wt9932p4c61-tiny: learn how P4 uses C61 Wi-Fi.
  7. examples/get-started/c61-hello-through-p4: learn how to flash and debug C61 through the P4 bridge.
  8. examples/wt_factory/wt9932p4c61-tiny/main/main.c: study complex peripheral initialization and task organization.
  9. examples/wt_factory/wt9932p4c61-tiny/main/lvgl_ui.c: study how the UI reflects hardware state.

After completing these sections, you can build a custom WT9932P4C61-TINY application on top of WT_BSP.