From 3eb49b31af36b50a2742d6b519839e85996832c6 Mon Sep 17 00:00:00 2001 From: Thomas Peterson Date: Wed, 14 Jan 2026 18:49:19 +0100 Subject: [PATCH] First test --- .clangd | 2 + .devcontainer/Dockerfile | 13 ++ .devcontainer/devcontainer.json | 19 +++ .gitignore | 78 ++++++++++ .vscode/c_cpp_properties.json | 19 +++ .vscode/launch.json | 15 ++ .vscode/settings.json | 18 +++ CMakeLists.txt | 8 + README.md | 53 +++++++ dependencies.lock | 110 +++++++++++++ main/CMakeLists.txt | 4 + main/hello_world_main.c | 265 ++++++++++++++++++++++++++++++++ main/idf_component.yml | 20 +++ pytest_hello_world.py | 55 +++++++ sdkconfig.ci | 0 15 files changed, 679 insertions(+) create mode 100644 .clangd create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .gitignore create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 dependencies.lock create mode 100644 main/CMakeLists.txt create mode 100644 main/hello_world_main.c create mode 100644 main/idf_component.yml create mode 100644 pytest_hello_world.py create mode 100644 sdkconfig.ci diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..437f255 --- /dev/null +++ b/.clangd @@ -0,0 +1,2 @@ +CompileFlags: + Remove: [-f*, -m*] diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..dafb8ad --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,13 @@ +ARG DOCKER_TAG=latest +FROM espressif/idf:${DOCKER_TAG} + +ENV LC_ALL=C.UTF-8 +ENV LANG=C.UTF-8 + +RUN apt-get update -y && apt-get install udev -y + +RUN echo "source /opt/esp/idf/export.sh > /dev/null 2>&1" >> ~/.bashrc + +ENTRYPOINT [ "/opt/esp/entrypoint.sh" ] + +CMD ["/bin/bash", "-c"] \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..246b79f --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,19 @@ +{ + "name": "ESP-IDF QEMU", + "build": { + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.defaultProfile.linux": "bash", + "idf.gitPath": "/usr/bin/git" + }, + "extensions": [ + "espressif.esp-idf-extension", + "espressif.esp-idf-web" + ] + } + }, + "runArgs": ["--privileged"] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7805557 --- /dev/null +++ b/.gitignore @@ -0,0 +1,78 @@ +# macOS +.DS_Store +.AppleDouble +.LSOverride + +# Directory metadata +.directory + +# Temporary files +*~ +*.swp +*.swo +*.bak +*.tmp + +# Log files +*.log + +# Build artifacts and directories +**/build/ +build/ +*.o +*.a +*.out +*.exe # For any host-side utilities compiled on Windows + +# ESP-IDF specific build outputs +*.bin +*.elf +*.map +flasher_args.json # Generated in build directory +sdkconfig.old +sdkconfig + +# ESP-IDF dependencies +# For older versions or manual component management +/components/.idf/ +**/components/.idf/ +# For modern ESP-IDF component manager +managed_components/ +# If ESP-IDF tools are installed/referenced locally to the project +.espressif/ + +# CMake generated files +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake +install_manifest.txt +CTestTestfile.cmake + +# Python environment files +*.pyc +*.pyo +*.pyd +__pycache__/ +*.egg-info/ +dist/ + +# Virtual environment folders +venv/ +.venv/ +env/ + +# Language Servers +.clangd/ +.ccls-cache/ +compile_commands.json + +# Windows specific +Thumbs.db +ehthumbs.db +Desktop.ini + +# User-specific configuration files +*.user +*.workspace # General workspace files, can be from various tools +*.suo # Visual Studio Solution User Options +*.sln.docstates # Visual Studio diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..fa6e8ac --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,19 @@ +{ + "configurations": [ + { + "name": "ESP-IDF", + "compilerPath": "/home/thomas/.espressif/tools/riscv32-esp-elf/esp-14.2.0_20251107/riscv32-esp-elf/bin/riscv32-esp-elf-gcc", + "compileCommands": "${config:idf.buildPath}/compile_commands.json", + "includePath": [ + "${workspaceFolder}/**" + ], + "browse": { + "path": [ + "${workspaceFolder}" + ], + "limitSymbolsToIncludedHeaders": true + } + } + ], + "version": 4 +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2511a38 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "gdbtarget", + "request": "attach", + "name": "Eclipse CDT GDB Adapter" + }, + { + "type": "espidf", + "name": "Launch", + "request": "launch" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4893a04 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,18 @@ +{ + "C_Cpp.intelliSenseEngine": "default", + "idf.openOcdConfigs": [ + "interface/ftdi/esp32_devkitj_v1.cfg", + "target/esp32.cfg" + ], + "idf.port": "/dev/ttyACM0", + "idf.currentSetup": "/home/thomas/.espressif/v5.5.2/esp-idf", + "idf.customExtraVars": { + "IDF_TARGET": "esp32p4" + }, + "clangd.path": "/home/thomas/.espressif/tools/esp-clang/esp-19.1.2_20250312/esp-clang/bin/clangd", + "clangd.arguments": [ + "--background-index", + "--query-driver=/home/thomas/.espressif/tools/riscv32-esp-elf/esp-14.2.0_20251107/riscv32-esp-elf/bin/riscv32-esp-elf-gcc", + "--compile-commands-dir=/home/thomas/projekte/test1/display/build" + ] +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9cf1759 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +# idf_build_set_property(MINIMAL_BUILD ON) +project(knxdisplay) diff --git a/README.md b/README.md new file mode 100644 index 0000000..f3aa0c5 --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | Linux | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | ----- | + +# Hello World Example + +Starts a FreeRTOS task to print "Hello World". + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +## How to use example + +Follow detailed instructions provided specifically for this example. + +Select the instructions depending on Espressif chip installed on your development board: + +- [ESP32 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/index.html) +- [ESP32-S2 Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html) + + +## Example folder contents + +The project **hello_world** contains one source file in C language [hello_world_main.c](main/hello_world_main.c). The file is located in folder [main](main). + +ESP-IDF projects are built using CMake. The project build configuration is contained in `CMakeLists.txt` files that provide set of directives and instructions describing the project's source files and targets (executable, library, or both). + +Below is short explanation of remaining files in the project folder. + +``` +├── CMakeLists.txt +├── pytest_hello_world.py Python script used for automated testing +├── main +│ ├── CMakeLists.txt +│ └── hello_world_main.c +└── README.md This is the file you are currently reading +``` + +For more information on structure and contents of ESP-IDF projects, please refer to Section [Build System](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html) of the ESP-IDF Programming Guide. + +## Troubleshooting + +* Program upload failure + + * Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs. + * The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again. + +## Technical support and feedback + +Please use the following feedback channels: + +* For technical queries, go to the [esp32.com](https://esp32.com/) forum +* For a feature request or bug report, create a [GitHub issue](https://github.com/espressif/esp-idf/issues) + +We will get back to you as soon as possible. diff --git a/dependencies.lock b/dependencies.lock new file mode 100644 index 0000000..7d0bc0e --- /dev/null +++ b/dependencies.lock @@ -0,0 +1,110 @@ +dependencies: + espressif/cmake_utilities: + component_hash: + 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f + dependencies: + - name: idf + require: private + version: '>=4.1' + source: + registry_url: https://components.espressif.com + type: service + version: 0.5.3 + espressif/esp_lcd_touch: + component_hash: + 3f85a7d95af876f1a6ecca8eb90a81614890d0f03a038390804e5a77e2caf862 + dependencies: + - name: idf + require: private + version: '>=4.4.2' + source: + registry_url: https://components.espressif.com + type: service + version: 1.2.1 + espressif/esp_lcd_touch_gt911: + component_hash: + be02e243d18b9a661bc13b0d22c0a5cfa3f708cf04d6eb059772276c8c8a4d76 + dependencies: + - name: espressif/esp_lcd_touch + registry_url: https://components.espressif.com + require: public + version: ^1.2.0 + - name: idf + require: private + version: '>=4.4.2' + source: + registry_url: https://components.espressif.com/ + type: service + version: 1.2.0~1 + espressif/esp_lvgl_port: + component_hash: + f872401524cb645ee6ff1c9242d44fb4ddcfd4d37d7be8b9ed3f4e85a404efcd + dependencies: + - name: idf + require: private + version: '>=5.1' + - name: lvgl/lvgl + registry_url: https://components.espressif.com + require: public + version: '>=8,<10' + source: + registry_url: https://components.espressif.com/ + type: service + version: 2.7.0 + espressif/i2c_bus: + component_hash: + 4e990dc11734316186b489b362c61d41f23f79d58bc169795cec215e528cba14 + dependencies: + - name: espressif/cmake_utilities + registry_url: https://components.espressif.com + require: private + version: '*' + - name: idf + require: private + version: '>=4.0' + source: + registry_url: https://components.espressif.com + type: service + version: 1.5.0 + idf: + source: + type: idf + version: 5.5.2 + lvgl/lvgl: + component_hash: + 17e68bfd21f0edf4c3ee838e2273da840bf3930e5dbc3bfa6c1190c3aed41f9f + dependencies: [] + source: + registry_url: https://components.espressif.com/ + type: service + version: 9.4.0 + waveshare/esp_lcd_jd9365_10_1: + component_hash: + 6c1336b93a37df2b5be42c49c4c364d0bacdbf96f053a934f881349457fac679 + dependencies: + - name: espressif/cmake_utilities + registry_url: https://components.espressif.com + require: private + version: 0.* + - name: espressif/i2c_bus + registry_url: https://components.espressif.com + require: private + version: ^1.3.0 + - name: idf + require: private + version: '>=5.3' + source: + registry_url: https://components.espressif.com/ + type: service + targets: + - esp32p4 + version: 1.0.4 +direct_dependencies: +- espressif/esp_lcd_touch_gt911 +- espressif/esp_lvgl_port +- idf +- lvgl/lvgl +- waveshare/esp_lcd_jd9365_10_1 +manifest_hash: 1b3972520800645b8020e1ad5d7fcfe89a9006c17fff1fcaa83ae8df9e2314ff +target: esp32p4 +version: 2.0.0 diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt new file mode 100644 index 0000000..af735de --- /dev/null +++ b/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "hello_world_main.c" + PRIV_REQUIRES spi_flash esp_lcd + REQUIRES esp_timer lvgl + INCLUDE_DIRS "") diff --git a/main/hello_world_main.c b/main/hello_world_main.c new file mode 100644 index 0000000..add3dde --- /dev/null +++ b/main/hello_world_main.c @@ -0,0 +1,265 @@ +/* + * SPDX-FileCopyrightText: 2026 User + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "driver/gpio.h" +#include "driver/i2c_master.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "esp_lcd_panel_ops.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_mipi_dsi.h" +#include "esp_ldo_regulator.h" +#include "esp_lcd_touch_gt911.h" +#include "lvgl.h" +#include "esp_lcd_jd9365_10_1.h" + +#define TAG "JD9365_LVGL" + +// Display config +#define LCD_H_RES 800 +#define LCD_V_RES 1280 +#define LCD_BIT_PER_PIXEL 24 +#define LCD_RST_GPIO 27 +#define LCD_BK_GPIO 26 +#define LCD_BK_ON_LEVEL 1 + +// MIPI DSI config +#define MIPI_DSI_LANE_NUM 2 +#define MIPI_DSI_PHY_LDO_CHAN 3 +#define MIPI_DSI_PHY_LDO_VOLTAGE_MV 2500 + +// Touch config (GT911) +#define TOUCH_I2C_SDA 7 +#define TOUCH_I2C_SCL 8 +#define TOUCH_INT_GPIO 3 +#define TOUCH_RST_GPIO 2 +#define TOUCH_I2C_FREQ_HZ 400000 + +static esp_lcd_panel_handle_t panel_handle = NULL; +static esp_lcd_touch_handle_t touch_handle = NULL; +static esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; +static esp_lcd_panel_io_handle_t mipi_dbi_io = NULL; +static SemaphoreHandle_t refresh_done_sem = NULL; + +// ================= Color Transfer Done Callback =================== +static bool on_color_trans_done(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *event_data, void *user_ctx) +{ + BaseType_t high_task_awoken = pdFALSE; + if (refresh_done_sem) { + xSemaphoreGiveFromISR(refresh_done_sem, &high_task_awoken); + } + return high_task_awoken == pdTRUE; +} + + +// ================= Flush Callback =================== +static void lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *color_p) +{ + xSemaphoreTake(refresh_done_sem, portMAX_DELAY); + + esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, + area->x2 + 1, area->y2 + 1, color_p); + + lv_display_flush_ready(disp); +} + +// ================= MIPI DSI / JD9365 init =================== +static void lcd_init(void) +{ + // Backlight GPIO + gpio_config_t bk_gpio = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = 1ULL << LCD_BK_GPIO + }; + gpio_config(&bk_gpio); + gpio_set_level(LCD_BK_GPIO, LCD_BK_ON_LEVEL); + + // LDO für MIPI PHY + esp_ldo_channel_handle_t ldo_mipi = NULL; + esp_ldo_channel_config_t ldo_cfg = { + .chan_id = MIPI_DSI_PHY_LDO_CHAN, + .voltage_mv = MIPI_DSI_PHY_LDO_VOLTAGE_MV + }; + esp_ldo_acquire_channel(&ldo_cfg, &ldo_mipi); + + // MIPI DSI Bus + esp_lcd_dsi_bus_config_t bus_cfg = JD9365_PANEL_BUS_DSI_2CH_CONFIG(); + esp_lcd_new_dsi_bus(&bus_cfg, &mipi_dsi_bus); + + // Panel IO + esp_lcd_dbi_io_config_t io_cfg = JD9365_PANEL_IO_DBI_CONFIG(); + esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &io_cfg, &mipi_dbi_io); + + // Panel Driver + esp_lcd_dpi_panel_config_t dpi_cfg = JD9365_800_1280_PANEL_60HZ_DPI_CONFIG(LCD_COLOR_PIXEL_FORMAT_RGB888); + jd9365_vendor_config_t vendor_cfg = { + .flags = { .use_mipi_interface = 1 }, + .mipi_config = { .dsi_bus = mipi_dsi_bus, .dpi_config = &dpi_cfg, .lane_num = MIPI_DSI_LANE_NUM } + }; + esp_lcd_panel_dev_config_t panel_cfg = { + .reset_gpio_num = LCD_RST_GPIO, + .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, + .bits_per_pixel = LCD_BIT_PER_PIXEL, + .vendor_config = &vendor_cfg + }; + esp_lcd_new_panel_jd9365(mipi_dbi_io, &panel_cfg, &panel_handle); + + // Initialize panel first + esp_lcd_panel_reset(panel_handle); + esp_lcd_panel_init(panel_handle); + esp_lcd_panel_disp_on_off(panel_handle, true); + + // Now set up synchronization after panel is ready + refresh_done_sem = xSemaphoreCreateBinary(); + xSemaphoreGive(refresh_done_sem); // Allow first draw to proceed + + // Register color transfer done callback (signals when draw_bitmap completes) + esp_lcd_dpi_panel_event_callbacks_t cbs = { + .on_color_trans_done = on_color_trans_done, + }; + esp_lcd_dpi_panel_register_event_callbacks(panel_handle, &cbs, NULL); +} + +// ================= Touch init =================== +static void touch_init(void) +{ + // I2C Bus initialisieren + i2c_master_bus_config_t i2c_bus_cfg = { + .i2c_port = I2C_NUM_0, + .sda_io_num = TOUCH_I2C_SDA, + .scl_io_num = TOUCH_I2C_SCL, + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .flags.enable_internal_pullup = true, // Board hat externe Pullups + }; + i2c_master_bus_handle_t i2c_bus = NULL; + ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus)); + + // Touch Panel IO + esp_lcd_panel_io_handle_t touch_io = NULL; + esp_lcd_panel_io_i2c_config_t touch_io_cfg = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); + touch_io_cfg.scl_speed_hz = TOUCH_I2C_FREQ_HZ; + ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus, &touch_io_cfg, &touch_io)); + + // GT911 Touch Controller + esp_lcd_touch_config_t touch_cfg = { + .x_max = LCD_H_RES, + .y_max = LCD_V_RES, + .rst_gpio_num = TOUCH_RST_GPIO, + .int_gpio_num = TOUCH_INT_GPIO, + .levels = { + .reset = 0, + .interrupt = 0, + }, + .flags = { + .swap_xy = 0, + .mirror_x = 0, + .mirror_y = 0, + }, + }; + ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(touch_io, &touch_cfg, &touch_handle)); + ESP_LOGI(TAG, "Touch GT911 initialized"); +} + +// ================= LVGL Touch Callback =================== +static void lvgl_touch_cb(lv_indev_t *indev, lv_indev_data_t *data) +{ + uint16_t x[1]; + uint16_t y[1]; + uint8_t touch_cnt = 0; + + esp_lcd_touch_read_data(touch_handle); + bool touched = esp_lcd_touch_get_coordinates(touch_handle, x, y, NULL, &touch_cnt, 1); + + if (touched && touch_cnt > 0) { + data->point.x = x[0]; + data->point.y = y[0]; + data->state = LV_INDEV_STATE_PRESSED; + } else { + data->state = LV_INDEV_STATE_RELEASED; + } +} + +// ================= LVGL init =================== +static void lvgl_init(void) +{ + lv_init(); + + // Display erstellen + lv_display_t* display1 = lv_display_create(LCD_H_RES, LCD_V_RES); + + // Set color format to match panel (RGB888 = 24-bit) + lv_display_set_color_format(display1, LV_COLOR_FORMAT_RGB888); + + // Allocate buffers in PSRAM with proper alignment for DMA + size_t buf_size = LCD_H_RES * 100 * 3; // 100 lines at a time, RGB888 + uint8_t *buf1 = heap_caps_aligned_alloc(64, buf_size, + MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA); + uint8_t *buf2 = heap_caps_aligned_alloc(64, buf_size, + MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA); + + if (!buf1 || !buf2) { + ESP_LOGE(TAG, "Failed to allocate display buffers!"); + return; + } + + lv_display_set_buffers(display1, buf1, buf2, buf_size, LV_DISPLAY_RENDER_MODE_PARTIAL); + + // Flush-Callback setzen + lv_display_set_flush_cb(display1, lvgl_flush_cb); + + // Touch Input Device registrieren + lv_indev_t *indev = lv_indev_create(); + lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); + lv_indev_set_read_cb(indev, lvgl_touch_cb); + lv_indev_set_display(indev, display1); + + lv_display_set_default(display1); +} + +// ================= Button Callback =================== +static void btn_event_cb(lv_event_t *e) +{ + lv_event_code_t code = lv_event_get_code(e); + if (code == LV_EVENT_CLICKED) { + ESP_LOGI(TAG, "Button clicked!"); + } +} + +// ================= UI erstellen =================== +static void create_ui(void) +{ + // Button erstellen + lv_obj_t *btn = lv_button_create(lv_screen_active()); + lv_obj_set_size(btn, 200, 80); + lv_obj_center(btn); + lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); + + // Label auf dem Button + lv_obj_t *label = lv_label_create(btn); + lv_label_set_text(label, "Klick mich!"); + lv_obj_center(label); +} + +// ================= Main =================== +void app_main(void) +{ + ESP_LOGI(TAG, "Starting JD9365 + LVGL 9"); + + lcd_init(); + touch_init(); + lvgl_init(); + create_ui(); + + while (1) { + lv_tick_inc(10); + lv_task_handler(); + vTaskDelay(pdMS_TO_TICKS(10)); + } +} diff --git a/main/idf_component.yml b/main/idf_component.yml new file mode 100644 index 0000000..8b7d442 --- /dev/null +++ b/main/idf_component.yml @@ -0,0 +1,20 @@ +## IDF Component Manager Manifest File +dependencies: + ## Required IDF version + idf: + version: '>=4.1.0' + # # Put list of dependencies here + # # For components maintained by Espressif: + # component: "~1.0.0" + # # For 3rd party components: + # username/component: ">=1.0.0,<2.0.0" + # username2/component2: + # version: "~1.0.0" + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't have an effect dependencies of the `main` component. + # # All dependencies of `main` are public by default. + # public: true + waveshare/esp_lcd_jd9365_10_1: '*' + lvgl/lvgl: ^9.4.0 + espressif/esp_lvgl_port: ^2.3.0 + espressif/esp_lcd_touch_gt911: '*' diff --git a/pytest_hello_world.py b/pytest_hello_world.py new file mode 100644 index 0000000..eb02bd7 --- /dev/null +++ b/pytest_hello_world.py @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import hashlib +import logging +from typing import Callable + +import pytest +from pytest_embedded_idf.dut import IdfDut +from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_qemu.app import QemuApp +from pytest_embedded_qemu.dut import QemuDut + + +@pytest.mark.generic +@idf_parametrize('target', ['supported_targets', 'preview_targets'], indirect=['target']) +def test_hello_world(dut: IdfDut, log_minimum_free_heap_size: Callable[..., None]) -> None: + dut.expect('Hello world!') + log_minimum_free_heap_size() + + +@pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) +def test_hello_world_linux(dut: IdfDut) -> None: + dut.expect('Hello world!') + + +@pytest.mark.host_test +@pytest.mark.macos_shell +@idf_parametrize('target', ['linux'], indirect=['target']) +def test_hello_world_macos(dut: IdfDut) -> None: + dut.expect('Hello world!') + + +def verify_elf_sha256_embedding(app: QemuApp, sha256_reported: str) -> None: + sha256 = hashlib.sha256() + with open(app.elf_file, 'rb') as f: + sha256.update(f.read()) + sha256_expected = sha256.hexdigest() + + logging.info(f'ELF file SHA256: {sha256_expected}') + logging.info(f'ELF file SHA256 (reported by the app): {sha256_reported}') + + # the app reports only the first several hex characters of the SHA256, check that they match + if not sha256_expected.startswith(sha256_reported): + raise ValueError('ELF file SHA256 mismatch') + + +@pytest.mark.host_test +@pytest.mark.qemu +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) +def test_hello_world_host(app: QemuApp, dut: QemuDut) -> None: + sha256_reported = dut.expect(r'ELF file SHA256:\s+([a-f0-9]+)').group(1).decode('utf-8') + verify_elf_sha256_embedding(app, sha256_reported) + + dut.expect('Hello world!') diff --git a/sdkconfig.ci b/sdkconfig.ci new file mode 100644 index 0000000..e69de29