Skip to content

Commit 068b769

Browse files
committed
initial commit
1 parent 1d8f7b0 commit 068b769

File tree

7 files changed

+2169
-0
lines changed

7 files changed

+2169
-0
lines changed

CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# For more information about build system see
2+
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
3+
# The following five lines of boilerplate have to be in your project's
4+
# CMakeLists in this exact order for cmake to work correctly
5+
cmake_minimum_required(VERSION 3.5)
6+
7+
set(COMPONENTS main) # "Trim" the build. Include the minimal set of components; main and anything it depends on.
8+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
9+
project(esp32-graphical-bootloader)

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# ESP32 Graphical Bootloader
2+
3+
3rd stage graphical bootloader which let's you pick an applications whic are stored in OTA partitions.
4+
5+
6+
## Build
7+
8+
Initial build and flash of the application and partition table.
9+
10+
```
11+
idf.py build flash monitor
12+
```
13+
14+
After the initial flash, it's possible to use following command, just to update the factory application:
15+
16+
```
17+
idf.py app-flash monitor
18+
```
19+
20+
## Flashing apps
21+
22+
Applications are stored in ota_0 - ota_4.
23+
24+
Build application (e.g. hello_world):
25+
```
26+
idf.py build
27+
```
28+
29+
Flash applications to ota_0:
30+
```
31+
esptool.py --chip esp32s3 --baud 921600 --before default_reset --after hard_reset write_flash 0xD20000 build/hello_world.bin
32+
```
33+
34+
Change offset for other apps:
35+
- ota_0 - 0x220000
36+
- ota_1 - 0x4E0000
37+
- ota_2 - 0x7A0000
38+
- ota_3 - 0xA60000
39+
- ota_4 - 0xD20000

main/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
idf_component_register(SRCS "graphical_bootloader_main.c" "bootloader_ui.c"
2+
INCLUDE_DIRS ".")

main/bootloader_ui.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#include <math.h>
2+
#include "lvgl.h"
3+
#include "esp_ota_ops.h"
4+
#include "esp_system.h"
5+
6+
typedef struct {
7+
lv_obj_t *scr;
8+
int count_val;
9+
} my_timer_context_t;
10+
11+
static lv_obj_t *img_text;
12+
static lv_obj_t *label_value; // Label to display the value
13+
14+
static void ota_button_event_handler(lv_event_t *e) {
15+
lv_obj_t *btn = lv_event_get_target(e);
16+
const uint32_t btn_id = lv_obj_get_child_id(btn);
17+
18+
printf("Button %ld clicked\n", btn_id + 1);
19+
20+
// Initially assume the first OTA partition, which is typically 'ota_0'
21+
const esp_partition_t *next_partition = esp_ota_get_next_update_partition(NULL);
22+
23+
// Iterate to find the correct OTA partition only if button ID is greater than 1
24+
if (btn_id > 0 && btn_id <= 5) {
25+
for (int i = 0; i < btn_id; i++) {
26+
next_partition = esp_ota_get_next_update_partition(next_partition);
27+
if (!next_partition) break; // If no next partition, break from the loop
28+
}
29+
}
30+
31+
// For button 1, next_partition will not change, thus pointing to 'ota_0'
32+
if (next_partition && esp_ota_set_boot_partition(next_partition) == ESP_OK) {
33+
printf("Setting boot partition to %s\n", next_partition->label);
34+
esp_restart(); // Restart to boot from the new partition
35+
} else {
36+
printf("Failed to set boot partition\n");
37+
}
38+
}
39+
40+
41+
static void add_number_buttons(lv_obj_t *scr, lv_obj_t *ref_obj) {
42+
int button_width = 50;
43+
int button_height = 60;
44+
45+
lv_obj_t *flex_cont = lv_obj_create(scr);
46+
lv_obj_set_size(flex_cont, 5 * button_width + 4 * 10, button_height);
47+
lv_obj_align_to(flex_cont, ref_obj, LV_ALIGN_OUT_TOP_MID, 0, -10);
48+
lv_obj_set_flex_flow(flex_cont, LV_FLEX_FLOW_ROW);
49+
lv_obj_set_flex_align(flex_cont, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
50+
lv_obj_set_scrollbar_mode(flex_cont, LV_SCROLLBAR_MODE_OFF);
51+
52+
for (int i = 0; i < 5; i++) {
53+
lv_obj_t *btn = lv_btn_create(flex_cont);
54+
lv_obj_set_size(btn, button_width, button_height);
55+
lv_obj_t *label = lv_label_create(btn);
56+
lv_label_set_text_fmt(label, "%d", i + 1);
57+
58+
lv_color_t text_color;
59+
switch (i) {
60+
case 0: text_color = lv_color_make(0, 255, 0); break;
61+
case 1: text_color = lv_color_make(255, 255, 0); break;
62+
case 2: text_color = lv_color_make(255, 165, 0); break;
63+
case 3: text_color = lv_color_make(255, 69, 0); break;
64+
case 4: text_color = lv_color_make(255, 0, 0); break;
65+
default: text_color = lv_color_make(0, 0, 0); break;
66+
}
67+
lv_obj_set_style_text_color(label, text_color, 0);
68+
69+
// Register the event handler for the button
70+
lv_obj_add_event_cb(btn, ota_button_event_handler, LV_EVENT_CLICKED, NULL);
71+
}
72+
}
73+
74+
static void add_icon_buttons(lv_obj_t *scr, lv_obj_t *ref_obj) {
75+
int button_width = 60; // Button width
76+
int button_height = 60; // Button height
77+
78+
// Create a flex container for the icon buttons
79+
lv_obj_t *icon_flex_cont = lv_obj_create(scr);
80+
lv_obj_set_size(icon_flex_cont, 4 * button_width + 3 * 10, button_height);
81+
lv_obj_align_to(icon_flex_cont, ref_obj, LV_ALIGN_OUT_TOP_MID, 0, -button_height - 20);
82+
lv_obj_set_flex_flow(icon_flex_cont, LV_FLEX_FLOW_ROW);
83+
lv_obj_set_flex_align(icon_flex_cont, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
84+
lv_obj_set_scrollbar_mode(icon_flex_cont, LV_SCROLLBAR_MODE_OFF);
85+
86+
// Array of raw images for icons
87+
const lv_img_dsc_t *icons[] = {&cloud_raw, &sun_raw, &snowflake_raw, &wind_raw};
88+
89+
// Create and position the buttons within the icon flex container
90+
for (int i = 0; i < 4; i++) {
91+
lv_obj_t *btn = lv_btn_create(icon_flex_cont);
92+
lv_obj_set_size(btn, button_width, button_height);
93+
94+
// Create an image for the button with the icon
95+
lv_obj_t *img = lv_img_create(btn);
96+
lv_img_set_src(img, icons[i]);
97+
lv_obj_center(img); // Center the image within the button
98+
}
99+
}
100+
101+
102+
void bootloader_ui(lv_obj_t *scr) {
103+
// Create new image and make it transparent
104+
img_text = lv_img_create(scr);
105+
lv_img_set_src(img_text, &esp_text);
106+
lv_obj_set_style_img_opa(img_text, 0, 0);
107+
108+
// Create a label for displaying the slider value
109+
label_value = lv_label_create(scr);
110+
lv_label_set_text(label_value, "0°C"); // Initialize with a default value
111+
112+
// Create a slider
113+
slider = lv_slider_create(scr);
114+
lv_obj_set_width(slider, 200); // Set the slider's width
115+
116+
// Position the slider at the bottom of the screen
117+
lv_obj_align(slider, LV_ALIGN_BOTTOM_MID, 0, -10); // -10 pixels from the bottom for some padding
118+
119+
// Position the label above the slider
120+
lv_obj_align_to(label_value, slider, LV_ALIGN_OUT_TOP_MID, 0, -10); // Align above slider with some padding
121+
122+
// Set the slider's range
123+
lv_slider_set_range(slider, -20, 40);
124+
125+
// Add event callback to the slider
126+
lv_obj_add_event_cb(slider, slider_event_handler, LV_EVENT_VALUE_CHANGED, NULL);
127+
128+
add_number_buttons(scr, label_value);
129+
add_icon_buttons(scr, label_value);
130+
}

main/graphical_bootloader_main.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: CC0-1.0
5+
*/
6+
7+
#include <stdio.h>
8+
#include "bsp/esp-bsp.h"
9+
#include "lvgl.h"
10+
#include "esp_log.h"
11+
12+
extern void bootloader_ui(lv_obj_t *scr);
13+
14+
void app_main(void)
15+
{
16+
ESP_LOGI("bootloader", "Starting 3rd stage bootloader...");
17+
18+
bsp_display_start();
19+
20+
bsp_display_lock(0);
21+
lv_obj_t *scr = lv_disp_get_scr_act(NULL);
22+
bootloader_ui(scr);
23+
24+
bsp_display_unlock();
25+
bsp_display_backlight_on();
26+
// Enter the main loop to process LVGL tasks
27+
while (1) {
28+
// Handle LVGL related tasks
29+
lv_task_handler();
30+
// Delay for a short period of time (e.g., 5 ms)
31+
vTaskDelay(pdMS_TO_TICKS(5));
32+
}
33+
}

main/idf_component.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
description: BSP Display example
2+
3+
dependencies:
4+
m5stack_core_s3:
5+
version: "^1.0.0"
6+
override_path: "../../../bsp/m5stack_core_s3"

0 commit comments

Comments
 (0)