WT9932P4C61-TINY Development Guide
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:
- Add the BSP component from
components/wt_bspto the application project. - Select
WT9932P4C61-TINYwithidf.py set-board. - Call
wt_bsp_init()to initialize board resources. - Obtain resource handles with
wt_bsp_get_rgb(),wt_bsp_get_button(),wt_bsp_get_sdmmc(),wt_bsp_get_dsi(),wt_bsp_get_csi(), andwt_bsp_get_touch(). - 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 forESP-IDF v6.0.1and later and is compatible withv5.3and later. Usev6.0.1or a newer version for a new project.- An activated ESP-IDF environment in which
idf.py --versionruns 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
mainbranch. 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 theREADME.mdof 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.
4.2 Copy blink for a Minimal Application
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 returnNULL; 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:
- Keep
wt_bsp_init()and the main hardware initialization flow. - Build, flash, and run the unmodified factory application first.
- Remove unused UI pages or controls.
- Retain the required SD card, camera, and Wi-Fi tasks.
- Replace the UI in
lvgl_ui.c. - Modify the business state machine in
main.c. - 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:
- Disconnect
FUSB. - Connect
HUSB. - Attach the new USB device to WSL2 if applicable.
- 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:
- Run
idf.py --versionand verify the ESP-IDF version. - Run
idf.py set-boardand verifyWT9932P4C61-TINYis selected. - Run
idf.py buildand resolve build errors. - Verify the port used by
idf.py -p <PORT> flash monitor. - Check whether
wt_bsp_init()succeeds in the startup log. - Check whether a required
wt_bsp_get_*()call returnsNULL. - Verify peripheral connections, stable power, and FPC orientation.
- For C61 issues, verify the required slave or application firmware and distinguish
FUSBfromHUSB.
11. Development Guidelines
- Include
wt_bsp.hand application module headers in application code. - Do not depend on private headers under
boards/<BOARD>/. - Check all
wt_bsp_get_*()results forNULL. - 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.
12. Recommended Reading Order
- Root
README.md: confirm currently supported boards, ESP-IDF versions, and usage. examples/get-started/blink/README.mdandmain/main.c: learn board selection, BSP initialization, and RGB control.examples/get-started/button,examples/display/dsi,examples/camera/csi, andexamples/storage/sdmmc: study the required standalone peripheral examples.components/wt_bsp/include/wt_bsp.h: review the top-level BSP API.components/wt_bsp/features/*/include/: review the RGB, Button, SDMMC, DSI, CSI, and Touch APIs as needed.examples/wifi/esp-hosted/wt9932p4c61-tiny: learn how P4 uses C61 Wi-Fi.examples/get-started/c61-hello-through-p4: learn how to flash and debug C61 through the P4 bridge.examples/wt_factory/wt9932p4c61-tiny/main/main.c: study complex peripheral initialization and task organization.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.