fix wifi & flash + eink screen on core 1, by using queue
This commit is contained in:
@@ -62,7 +62,7 @@ if (TARGET tinyusb_host)
|
||||
)
|
||||
|
||||
# pull in common dependencies
|
||||
target_link_libraries(hello_usb pico_stdlib pico_ssd1306 hardware_i2c Config ePaper GUI Fonts hardware_spi pico_multicore tinyusb_host tinyusb_board pico_cyw43_arch_lwip_threadsafe_background)
|
||||
target_link_libraries(hello_usb pico_stdlib pico_ssd1306 hardware_i2c Config ePaper GUI Fonts hardware_spi pico_multicore pico_flash tinyusb_host tinyusb_board pico_cyw43_arch_lwip_threadsafe_background)
|
||||
|
||||
# enable usb output, disable uart output
|
||||
pico_enable_stdio_usb(hello_usb 0)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include "wifi_manager.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "pico/flash.h"
|
||||
#include "pico/util/queue.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -31,6 +33,10 @@ static bool g_force_full_refresh = false; // Flag to force full refresh when li
|
||||
// Synchronization flag for multicore initialization
|
||||
static volatile bool g_display_ready = false;
|
||||
|
||||
// Queue for display messages (replacing raw FIFO to avoid conflict with flash_safe_execute)
|
||||
static queue_t g_display_queue;
|
||||
#define QUEUE_LENGTH 8
|
||||
|
||||
// Display update message structure for inter-core communication
|
||||
typedef struct {
|
||||
EntryList entries;
|
||||
@@ -84,9 +90,18 @@ static void init_epaper_display() {
|
||||
EPD_7IN5B_V2_Display_Partial(g_epd_image, 0, 0, EPD_7IN5B_V2_WIDTH, EPD_7IN5B_V2_HEIGHT);
|
||||
EPD_7IN5B_V2_Display_Partial(g_epd_image, 0, 0, EPD_7IN5B_V2_WIDTH, EPD_7IN5B_V2_HEIGHT);
|
||||
|
||||
printf("Trying to connect to wifi\r\n");
|
||||
bool connected = wifi_try_auto_connect();
|
||||
|
||||
|
||||
Paint_SelectImage(g_epd_red);
|
||||
printf("Drawing header\r\n");
|
||||
if (connected) {
|
||||
Paint_DrawString_EN(10, 10, "What's new today: ...", &Font24, WHITE, RED);
|
||||
} else {
|
||||
Paint_DrawString_EN(10, 10, "What's new today:", &Font24, WHITE, RED);
|
||||
}
|
||||
|
||||
|
||||
// Display the image with both black and red buffers
|
||||
EPD_7IN5B_V2_Display_Partial(g_epd_red, 0, 0, EPD_7IN5B_V2_WIDTH, EPD_7IN5B_V2_HEIGHT);
|
||||
@@ -98,6 +113,9 @@ static void init_epaper_display() {
|
||||
* Core 1 function: Runs display initialization and update handling
|
||||
*/
|
||||
static void core1_display_init() {
|
||||
// Initialize flash safe execute support for this core
|
||||
flash_safe_execute_core_init();
|
||||
|
||||
// Initialize WiFi on Core 1 so IRQs are handled here
|
||||
wifi_init();
|
||||
|
||||
@@ -109,20 +127,18 @@ static void core1_display_init() {
|
||||
// Initialize for partial refresh on second call
|
||||
EPD_7IN5B_V2_Init_Part();
|
||||
|
||||
// Core 1 main loop: handle display updates via FIFO
|
||||
// Core 1 main loop: handle display updates via Queue
|
||||
while (true) {
|
||||
// Check if there's a message from core 0
|
||||
if (multicore_fifo_rvalid()) {
|
||||
// Read the message pointer
|
||||
uint32_t msg_addr = multicore_fifo_pop_blocking();
|
||||
DisplayMessage *msg = (DisplayMessage *)msg_addr;
|
||||
DisplayMessage *msg;
|
||||
// Check if there's a message in the queue
|
||||
if (queue_try_remove(&g_display_queue, &msg)) {
|
||||
|
||||
// Drain FIFO to get the latest message
|
||||
while (multicore_fifo_rvalid()) {
|
||||
// Drain Queue to get the latest message
|
||||
DisplayMessage *next_msg;
|
||||
while (queue_try_remove(&g_display_queue, &next_msg)) {
|
||||
printf("[Core 1] Skipping intermediate update\n");
|
||||
free(msg); // Free the stale message
|
||||
msg_addr = multicore_fifo_pop_blocking();
|
||||
msg = (DisplayMessage *)msg_addr;
|
||||
msg = next_msg;
|
||||
}
|
||||
|
||||
printf("[Core 1] Updating display with %d entries\n", msg->entries.count);
|
||||
@@ -173,12 +189,16 @@ static void core1_display_init() {
|
||||
}
|
||||
|
||||
void epaper_start_background_thread() {
|
||||
// Initialize the queue before starting the thread
|
||||
queue_init(&g_display_queue, sizeof(DisplayMessage*), QUEUE_LENGTH);
|
||||
|
||||
printf("Launching e-Paper display init on core 1...\n");
|
||||
multicore_launch_core1(core1_display_init);
|
||||
}
|
||||
|
||||
void epaper_send_update(const char *entry, bool finish_line) {
|
||||
if (!g_display_ready) return; // Don't send if display isn't ready
|
||||
// printf("[Core 0] Preparing display update: '%s' (finish_line=%d)\n", entry, finish_line);
|
||||
|
||||
// Check if list is at capacity
|
||||
if (g_entry_list.count >= MAX_ENTRIES) {
|
||||
@@ -224,11 +244,11 @@ void epaper_send_update(const char *entry, bool finish_line) {
|
||||
msg->yend = msg->ystart + 25;
|
||||
}
|
||||
|
||||
// Send message pointer to core 1 if FIFO has space
|
||||
if (multicore_fifo_wready()) {
|
||||
multicore_fifo_push_blocking((uint32_t)msg);
|
||||
// Send message pointer to core 1 via Queue
|
||||
if (queue_try_add(&g_display_queue, &msg)) {
|
||||
// printf("[Core 0] Display update sent to core 1\n");
|
||||
} else {
|
||||
printf("[Core 0] FIFO full, skipping display update\n");
|
||||
printf("[Core 0] Queue full, skipping display update\n");
|
||||
free(msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ static bool execute_command(CommandAction action, const char* input) {
|
||||
if (parsed < 2) {
|
||||
printf("Usage: /connect <ssid> <password>\n");
|
||||
if (g_display_manager) g_display_manager->refresh("Usage: /connect <ssid> <pass>", nullptr);
|
||||
// epaper_send_update("Usage: /connect <ssid> <pass>", true);
|
||||
epaper_send_update("Usage: /connect <ssid> <pass>", true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -67,11 +67,18 @@ static bool execute_command(CommandAction action, const char* input) {
|
||||
|
||||
if (wifi_connect(ssid, password)) {
|
||||
if (g_display_manager) g_display_manager->refresh("Connected!", ssid);
|
||||
// epaper_send_update("Connected!", true);
|
||||
// wifi_save_credentials(ssid, password);
|
||||
int rc = wifi_save_credentials(ssid, password);
|
||||
if (rc != 0) {
|
||||
char err_msg[32];
|
||||
snprintf(err_msg, sizeof(err_msg), "Flash Error: %d", rc);
|
||||
if (g_display_manager) g_display_manager->refresh(err_msg, nullptr);
|
||||
epaper_send_update(err_msg, true);
|
||||
} else {
|
||||
epaper_send_update("Connected!", true);
|
||||
}
|
||||
} else {
|
||||
if (g_display_manager) g_display_manager->refresh("Connection Failed", nullptr);
|
||||
// epaper_send_update("Connection Failed", true);
|
||||
epaper_send_update("Connection Failed", true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -219,20 +226,13 @@ int main() {
|
||||
sleep_ms(3000); // Give time for power to settle and serial to connect
|
||||
printf("System Booting...\n");
|
||||
|
||||
// Launch display initialization on core 1
|
||||
// Launch display initialization on core 1, WIFI and Flash safe execute
|
||||
epaper_start_background_thread();
|
||||
|
||||
DisplayManager display;
|
||||
display.init();
|
||||
g_display_manager = &display;
|
||||
|
||||
if (wifi_try_auto_connect()) {
|
||||
display.refresh("WiFi Auto-Connected", nullptr);
|
||||
epaper_send_update("WiFi Auto-Connected", true);
|
||||
} else {
|
||||
display.refresh("Waiting for Keyboard", nullptr);
|
||||
}
|
||||
|
||||
printf("Initializing TinyUSB Host...\n");
|
||||
tuh_init(BOARD_TUH_RHPORT);
|
||||
printf("TinyUSB Host Initialized.\n");
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "wifi_manager.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "pico/flash.h"
|
||||
#include "hardware/flash.h"
|
||||
#include "hardware/sync.h"
|
||||
#include <stdio.h>
|
||||
@@ -60,7 +62,20 @@ void wifi_scan() {
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_save_credentials(const char* ssid, const char* password) {
|
||||
// Helper struct for flash operations
|
||||
struct FlashWriteParams {
|
||||
const uint8_t* data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
// Actual flash operation to be executed safely
|
||||
static void do_flash_write(void *param) {
|
||||
FlashWriteParams *p = (FlashWriteParams*)param;
|
||||
flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE);
|
||||
flash_range_program(FLASH_TARGET_OFFSET, p->data, p->size);
|
||||
}
|
||||
|
||||
int wifi_save_credentials(const char* ssid, const char* password) {
|
||||
WifiCreds creds;
|
||||
creds.magic = WIFI_CREDS_MAGIC;
|
||||
strncpy(creds.ssid, ssid, sizeof(creds.ssid) - 1);
|
||||
@@ -68,17 +83,25 @@ void wifi_save_credentials(const char* ssid, const char* password) {
|
||||
strncpy(creds.password, password, sizeof(creds.password) - 1);
|
||||
creds.password[sizeof(creds.password) - 1] = '\0';
|
||||
|
||||
uint32_t ints = save_and_disable_interrupts();
|
||||
flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE);
|
||||
flash_range_program(FLASH_TARGET_OFFSET, (const uint8_t*)&creds, sizeof(creds));
|
||||
restore_interrupts(ints);
|
||||
FlashWriteParams params = { (const uint8_t*)&creds, sizeof(creds) };
|
||||
int rc = flash_safe_execute(do_flash_write, ¶ms, 1000);
|
||||
|
||||
if (rc == PICO_OK) {
|
||||
printf("WiFi credentials saved to flash.\n");
|
||||
} else {
|
||||
printf("Failed to save WiFi credentials: %d\n", rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool wifi_try_auto_connect() {
|
||||
// On RP2040/RP2350, flash is memory-mapped at XIP_BASE (0x10000000).
|
||||
// We can read from it directly like a normal pointer without special API calls.
|
||||
// The hardware XIP controller handles fetching data from the flash chip.
|
||||
const WifiCreds* creds = (const WifiCreds*)(XIP_BASE + FLASH_TARGET_OFFSET);
|
||||
|
||||
// Check for the magic number to verify valid data exists.
|
||||
// Erased flash reads as 0xFFFFFFFF, so this check fails if no data was saved.
|
||||
if (creds->magic != WIFI_CREDS_MAGIC) {
|
||||
printf("No saved WiFi credentials found.\n");
|
||||
return false;
|
||||
|
||||
@@ -22,8 +22,9 @@ bool wifi_connect(const char* ssid, const char* password);
|
||||
|
||||
/**
|
||||
* Saves the WiFi credentials to flash memory for auto-connect.
|
||||
* Returns 0 (PICO_OK) on success, or an error code on failure.
|
||||
*/
|
||||
void wifi_save_credentials(const char* ssid, const char* password);
|
||||
int wifi_save_credentials(const char* ssid, const char* password);
|
||||
|
||||
/**
|
||||
* Attempts to connect using saved credentials.
|
||||
|
||||
Reference in New Issue
Block a user