#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "driver/gpio.h"
#include "esp_heap_caps.h"
#define GPIO_SIGNAL_PIN 23
#define GPIO_SIGNAL_INTR ESP_INTR_FLAG_LEVEL1
#define GPIO_SIGNAL_BIT (1 << 0)
#define DEBOUNCE_TIME_MS 500 // Tempo de debounce de 500 ms
// Estados da máquina de estados
typedef enum {
WAITING_SIGNAL,
FLASHING_FIRMWARE,
FINISHED_FLASHING
} state_t;
// Variáveis globais
static state_t current_state = WAITING_SIGNAL;
static EventGroupHandle_t gpio_evt_group;
// Callback para interrupção
static void IRAM_ATTR gpio_isr_handler(void* arg) {
// Define o bit de evento do ISR
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xEventGroupSetBitsFromISR(gpio_evt_group, GPIO_SIGNAL_BIT, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
// Função da tarefa de Espera de Sinal
void wait_signal_task(void *pvParameters) {
while (1) {
if (current_state == WAITING_SIGNAL) {
// Aguarda o sinal
printf("Aguardando sinal...\n");
xEventGroupWaitBits(
gpio_evt_group,
GPIO_SIGNAL_BIT,
pdTRUE,
pdTRUE,
portMAX_DELAY
);
printf("Sinal detectado! Iniciando gravação...\n");
current_state = FLASHING_FIRMWARE;
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
// Função da tarefa de Gravação de Firmware
void flash_firmware_task(void *pvParameters) {
const int progress_max = 37; // Comprimento da barra de progresso
int progress;
while (1) {
if (current_state == FLASHING_FIRMWARE) {
printf("Gravando firmware...\n");
for (progress = 0; progress <= progress_max; progress++) {
// Imprime o indicador de progresso
printf("\r["); // Retorna ao início da linha
for (int i = 0; i < progress_max; i++) {
if (i < progress) {
printf("#"); // Caractere de progresso
} else {
printf(" "); // Espaço representa a parte não completada
}
}
printf("] %d%%", (progress * 100) / progress_max);
fflush(stdout); // Força a atualização da saída do console
vTaskDelay(100 / portTICK_PERIOD_MS); // Atraso entre atualizações
}
printf("\nFirmware gravado com sucesso!\n");
// Exibir informações de memória
printf("Memória total livre: %lu bytes\n", esp_get_free_heap_size());
printf("Menor tamanho de memória livre: %d bytes\n",
heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT));
current_state = FINISHED_FLASHING;
} else if (current_state == FINISHED_FLASHING) {
printf("Gravação concluída. Voltando para a espera de sinal.\n");
xEventGroupClearBits(gpio_evt_group, GPIO_SIGNAL_BIT);
current_state = WAITING_SIGNAL; // Volta para aguardar o sinal
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
// Função para inicializar a GPIO para detecção de sinal
void init_gpio() {
gpio_config_t io_conf;
// Configura para interrupção na borda de subida
io_conf.intr_type = GPIO_INTR_POSEDGE;
io_conf.pin_bit_mask = (1ULL << GPIO_SIGNAL_PIN);
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config(&io_conf);
// Instala o serviço de interrupção GPIO e configura a callback para o pino
gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1);
gpio_isr_handler_add(GPIO_SIGNAL_PIN, gpio_isr_handler, NULL);
}
void app_main() {
// Inicializa a GPIO
init_gpio();
// Inicializa o grupo de eventos
gpio_evt_group = xEventGroupCreate();
// Cria a tarefa de Espera de Sinal
xTaskCreate(wait_signal_task, "wait_signal_task", 2048, NULL, 10, NULL);
// Cria a tarefa de Gravação de Firmware
xTaskCreate(flash_firmware_task, "flash_firmware_task", 2048, NULL, 5, NULL);
}