SDK สำหรับ TESAIoT Dev Kit
คู่มืออ้างอิง API และ Tutorial (ModusToolbox)
Loading...
Searching...
No Matches

Functions

void lfs_wifi_creds_init (void)
 บน variant นี้เป็น no-op — bento_storage_init() เป็นเจ้าของการเริ่มต้นใช้งาน
void lfs_wifi_creds_deinit (void)
 บน variant นี้เป็น no-op; ลำดับการ teardown ของ mtb-mpy ไม่นำมาใช้ที่นี่
bool lfs_wifi_creds_ready (void)
 ส่งต่อไปยัง bento_storage_ready(); ตรวจก่อนการอ่านและการเขียนทุกครั้ง
int lfs_wifi_creds_read (qspi_wifi_entry_t *entries, int max_entries)
 เติมอาร์เรย์ของผู้เรียก; คืนค่าจำนวนรายการ และคืน 0 เมื่อการตรวจความถูกต้องล้มเหลวไม่ว่ากรณีใด
bool lfs_wifi_creds_write (const qspi_wifi_entry_t *entries, int count)
 เขียนทับ /.wifi_creds ด้วย CRC32; ทำ snapshot ภายใต้ lock แล้วเขียนนอก lock
bool lfs_wifi_creds_needs_resave (void)
 บน variant นี้เป็น false เสมอ — ที่เก็บฝั่ง C เขียนเฉพาะรูปแบบปัจจุบันเท่านั้น

Detailed Description

ฟังก์ชัน 6 ตัวบนไฟล์เดียว คือ /.wifi_creds บนพาร์ทิชัน LittleFS: มีรายการ qspi_wifi_entry_t ได้มากที่สุดตาม QSPI_WIFI_CREDS_MAX (6) รายการ (100 ไบต์ แบบ packed ประกอบด้วย SSID, password, security, flags; ประกาศไว้ใน wifi_creds_types.h ส่วน prototype อยู่ใน lfs_wifi_creds.h) บน variant mtb-only ทั้ง 6 ตัวมาจากซอร์สที่ส่งมอบจริง — template/bento_libs/claw/common/storage_c/lfs_wifi_creds_c.c — ซึ่ง proj_cm33_ns/wifi_init.c และ WiFi worker ใน sensor_auto_task.c ลิงก์เข้ากับไฟล์นั้น ตัวอย่างประกอบทุกตัวในตระกูลนี้ยกมาจากไฟล์ 2 ไฟล์นั้น ซึ่งทั้งคู่อยู่ใน zip ของ mtb-only

variant ที่ใช้ได้
mtb-mpy และ mtb-only

Function Documentation

◆ lfs_wifi_creds_init()

void lfs_wifi_creds_init ( void )

บน variant นี้เป็น no-op — bento_storage_init() เป็นเจ้าของการเริ่มต้นใช้งาน

Initialize LFS credential store. MUST be called from MicroPython task AFTER VFS mount succeeds.

ข้อกำหนดการเรียกใช้
บน variant นี้เป็น no-op: bento_storage_init() เป็นเจ้าของการเริ่มต้นใช้งาน และที่เก็บใช้งานได้ทันทีที่ lfs_wifi_creds_ready() รายงานว่าโวลุมเมานต์แล้ว ให้คงการเรียกนี้ไว้ที่ตำแหน่งที่โค้ดบูตส่วนกลางวางไว้ เพื่อให้ซอร์สเดียวกันคอมไพล์ได้บน mtb-mpy ซึ่งที่นั่นเป็นการเริ่มต้นใช้งานจริงที่ต้องรันจาก MicroPython task หลังเมานต์ VFS โดยมี gc_collect() อยู่ก่อนหน้าทันที การเริ่มต้นที่เก็บต้องมาก่อน ready / read / write ทุกครั้ง ไม่คืนค่า
variant ที่ใช้ได้
mtb-mpy และ mtb-only
ตัวอย่าง
นิยามที่ส่งมอบจริง (บรรทัดแรกของที่เก็บ)
void lfs_wifi_creds_init(void) { /* bento_storage_init() owns bring-up */ }
void lfs_wifi_creds_deinit(void) { }
bool lfs_wifi_creds_ready(void) { return bento_storage_ready(); }
/* The mtb-mpy store can inherit a pre-LFS sector image that wants rewriting;
* this store writes only the current format, so never. */
bool lfs_wifi_creds_needs_resave(void) { return false; }
int lfs_wifi_creds_read(qspi_wifi_entry_t *entries, int max_entries) {
if (entries == NULL || max_entries <= 0) return 0;
if (!bento_storage_ready()) return 0;
int n = bento_storage_read_file(CREDS_FILE, s_buf, sizeof(s_buf));
if (n < CREDS_TOTAL_SIZE) return 0;
uint32_t magic; memcpy(&magic, &s_buf[0], 4);
uint16_t version; memcpy(&version, &s_buf[4], 2);
uint16_t count; memcpy(&count, &s_buf[6], 2);
if (magic != QSPI_WIFI_CREDS_MAGIC) return 0;
if (version != QSPI_WIFI_CREDS_VERSION) return 0;
if (count > QSPI_WIFI_CREDS_MAX) return 0;
uint32_t stored; memcpy(&stored, &s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], 4);
if (stored != calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) {
/* Legacy XOR-32 fallback, exactly as the mtb-mpy reader does. */
if (stored != calc_xor32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) return 0;
}
int out = (count < (uint16_t)max_entries) ? count : max_entries;
memcpy(entries, &s_buf[CREDS_HEADER_SIZE], (size_t)out * sizeof(qspi_wifi_entry_t));
/* Defensive termination, same as the mtb-mpy reader. */
for (int i = 0; i < out; i++) {
entries[i].ssid[32] = '\0';
entries[i].password[64] = '\0';
}
return out;
}
bool lfs_wifi_creds_write(const qspi_wifi_entry_t *entries, int count) {
if (count < 0 || count > QSPI_WIFI_CREDS_MAX) return false;
if (count > 0 && entries == NULL) return false;
if (!bento_storage_ready()) return false;
memset(s_buf, 0, sizeof(s_buf));
uint32_t magic = QSPI_WIFI_CREDS_MAGIC;
uint16_t version = QSPI_WIFI_CREDS_VERSION;
uint16_t cnt = (uint16_t)count;
memcpy(&s_buf[0], &magic, 4);
memcpy(&s_buf[4], &version, 2);
memcpy(&s_buf[6], &cnt, 2);
if (count > 0) {
memcpy(&s_buf[CREDS_HEADER_SIZE], entries,
(size_t)count * sizeof(qspi_wifi_entry_t));
}
uint32_t crc = calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE);
memcpy(&s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], &crc, 4);
return bento_storage_write_file(CREDS_FILE, s_buf, sizeof(s_buf));
}

◆ lfs_wifi_creds_deinit()

void lfs_wifi_creds_deinit ( void )

บน variant นี้เป็น no-op; ลำดับการ teardown ของ mtb-mpy ไม่นำมาใช้ที่นี่

Invalidate LFS handle before MicroPython soft reset. Called from mpy_main.c before mp_deinit().

ข้อกำหนดการเรียกใช้
บน variant นี้เป็น no-op บน mtb-mpy ฟังก์ชันนี้ทำให้ handle ของ Python ที่ที่เก็บถืออยู่ใช้ไม่ได้ และลำดับของมันกำหนดไว้ตายตัว — หลัง wifi_creds_flush_if_dirty() ครั้งสุดท้าย และก่อนที่ gc_sweep_all() จะทำลายอ็อบเจ็กต์ VFS; ที่เก็บฝั่ง C ไม่มี teardown ที่เทียบเท่า เพราะ bento_storage ยังเมานต์อยู่ตลอดอายุการทำงานของเฟิร์มแวร์ ไม่คืนค่า
variant ที่ใช้ได้
mtb-mpy และ mtb-only
ตัวอย่าง
นิยามที่ส่งมอบจริง
void lfs_wifi_creds_init(void) { /* bento_storage_init() owns bring-up */ }
void lfs_wifi_creds_deinit(void) { }
bool lfs_wifi_creds_ready(void) { return bento_storage_ready(); }
/* The mtb-mpy store can inherit a pre-LFS sector image that wants rewriting;
* this store writes only the current format, so never. */
bool lfs_wifi_creds_needs_resave(void) { return false; }
int lfs_wifi_creds_read(qspi_wifi_entry_t *entries, int max_entries) {
if (entries == NULL || max_entries <= 0) return 0;
if (!bento_storage_ready()) return 0;
int n = bento_storage_read_file(CREDS_FILE, s_buf, sizeof(s_buf));
if (n < CREDS_TOTAL_SIZE) return 0;
uint32_t magic; memcpy(&magic, &s_buf[0], 4);
uint16_t version; memcpy(&version, &s_buf[4], 2);
uint16_t count; memcpy(&count, &s_buf[6], 2);
if (magic != QSPI_WIFI_CREDS_MAGIC) return 0;
if (version != QSPI_WIFI_CREDS_VERSION) return 0;
if (count > QSPI_WIFI_CREDS_MAX) return 0;
uint32_t stored; memcpy(&stored, &s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], 4);
if (stored != calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) {
/* Legacy XOR-32 fallback, exactly as the mtb-mpy reader does. */
if (stored != calc_xor32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) return 0;
}
int out = (count < (uint16_t)max_entries) ? count : max_entries;
memcpy(entries, &s_buf[CREDS_HEADER_SIZE], (size_t)out * sizeof(qspi_wifi_entry_t));
/* Defensive termination, same as the mtb-mpy reader. */
for (int i = 0; i < out; i++) {
entries[i].ssid[32] = '\0';
entries[i].password[64] = '\0';
}
return out;
}
bool lfs_wifi_creds_write(const qspi_wifi_entry_t *entries, int count) {
if (count < 0 || count > QSPI_WIFI_CREDS_MAX) return false;
if (count > 0 && entries == NULL) return false;
if (!bento_storage_ready()) return false;
memset(s_buf, 0, sizeof(s_buf));
uint32_t magic = QSPI_WIFI_CREDS_MAGIC;
uint16_t version = QSPI_WIFI_CREDS_VERSION;
uint16_t cnt = (uint16_t)count;
memcpy(&s_buf[0], &magic, 4);
memcpy(&s_buf[4], &version, 2);
memcpy(&s_buf[6], &cnt, 2);
if (count > 0) {
memcpy(&s_buf[CREDS_HEADER_SIZE], entries,
(size_t)count * sizeof(qspi_wifi_entry_t));
}
uint32_t crc = calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE);
memcpy(&s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], &crc, 4);
return bento_storage_write_file(CREDS_FILE, s_buf, sizeof(s_buf));
}

◆ lfs_wifi_creds_ready()

bool lfs_wifi_creds_ready ( void )

ส่งต่อไปยัง bento_storage_ready(); ตรวจก่อนการอ่านและการเขียนทุกครั้ง

Check if LFS credential store is ready for use.

ข้อกำหนดการเรียกใช้
ส่งต่อไปยัง bento_storage_ready() ตรวจก่อนการอ่านทุกครั้งและการเขียนทุกครั้ง ที่จุดเรียกทุกจุดในของที่ส่งมอบจริง โดยไม่มีข้อยกเว้น — เมื่อยังไม่พร้อม การอ่านคืนค่า 0 และการเขียนคืนค่า false แต่ตัวกัน (guard) นี้ทำให้ "ที่เก็บยังไม่พร้อม" ยังแยกออกจาก "ไม่มีข้อมูล" ได้ การเริ่มต้นที่เก็บต้องมาก่อนการเรียกนี้ ต้นทุนต่ำ; ไม่มีการล็อก
variant ที่ใช้ได้
mtb-mpy และ mtb-only
ตัวอย่าง
นิยามที่ส่งมอบจริง และการใช้งานภายในการอ่านและการเขียน
void lfs_wifi_creds_init(void) { /* bento_storage_init() owns bring-up */ }
void lfs_wifi_creds_deinit(void) { }
bool lfs_wifi_creds_ready(void) { return bento_storage_ready(); }
/* The mtb-mpy store can inherit a pre-LFS sector image that wants rewriting;
* this store writes only the current format, so never. */
bool lfs_wifi_creds_needs_resave(void) { return false; }
int lfs_wifi_creds_read(qspi_wifi_entry_t *entries, int max_entries) {
if (entries == NULL || max_entries <= 0) return 0;
if (!bento_storage_ready()) return 0;
int n = bento_storage_read_file(CREDS_FILE, s_buf, sizeof(s_buf));
if (n < CREDS_TOTAL_SIZE) return 0;
uint32_t magic; memcpy(&magic, &s_buf[0], 4);
uint16_t version; memcpy(&version, &s_buf[4], 2);
uint16_t count; memcpy(&count, &s_buf[6], 2);
if (magic != QSPI_WIFI_CREDS_MAGIC) return 0;
if (version != QSPI_WIFI_CREDS_VERSION) return 0;
if (count > QSPI_WIFI_CREDS_MAX) return 0;
uint32_t stored; memcpy(&stored, &s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], 4);
if (stored != calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) {
/* Legacy XOR-32 fallback, exactly as the mtb-mpy reader does. */
if (stored != calc_xor32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) return 0;
}
int out = (count < (uint16_t)max_entries) ? count : max_entries;
memcpy(entries, &s_buf[CREDS_HEADER_SIZE], (size_t)out * sizeof(qspi_wifi_entry_t));
/* Defensive termination, same as the mtb-mpy reader. */
for (int i = 0; i < out; i++) {
entries[i].ssid[32] = '\0';
entries[i].password[64] = '\0';
}
return out;
}
bool lfs_wifi_creds_write(const qspi_wifi_entry_t *entries, int count) {
if (count < 0 || count > QSPI_WIFI_CREDS_MAX) return false;
if (count > 0 && entries == NULL) return false;
if (!bento_storage_ready()) return false;
memset(s_buf, 0, sizeof(s_buf));
uint32_t magic = QSPI_WIFI_CREDS_MAGIC;
uint16_t version = QSPI_WIFI_CREDS_VERSION;
uint16_t cnt = (uint16_t)count;
memcpy(&s_buf[0], &magic, 4);
memcpy(&s_buf[4], &version, 2);
memcpy(&s_buf[6], &cnt, 2);
if (count > 0) {
memcpy(&s_buf[CREDS_HEADER_SIZE], entries,
(size_t)count * sizeof(qspi_wifi_entry_t));
}
uint32_t crc = calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE);
memcpy(&s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], &crc, 4);
return bento_storage_write_file(CREDS_FILE, s_buf, sizeof(s_buf));
}

◆ lfs_wifi_creds_read()

int lfs_wifi_creds_read ( qspi_wifi_entry_t * entries,
int max_entries )

เติมอาร์เรย์ของผู้เรียก; คืนค่าจำนวนรายการ และคืน 0 เมื่อการตรวจความถูกต้องล้มเหลวไม่ว่ากรณีใด

Read all saved WiFi credentials from LittleFS.

Waits up to 10 seconds for LFS init (VFS mount). Validates magic, version, checksum before returning data.

Parameters
entriesOutput array (must hold QSPI_WIFI_CREDS_MAX elements)
max_entriesMax entries to read
Returns
Number of valid entries read (0 if LFS not ready or no data)
ข้อกำหนดการเรียกใช้
เติมอาร์เรย์ของผู้เรียก (ขนาดตาม QSPI_WIFI_CREDS_MAX) แล้วคืนค่าจำนวนรายการ; คืน 0 เมื่อ magic, version หรือ checksum ล้มเหลวไม่ว่ากรณีใด — ไม่มีรหัสข้อผิดพลาดแยกต่างหาก และ 0 ยังหมายถึงไฟล์ว่างด้วย ตรวจ magic, version และ count ก่อน จากนั้นตรวจ CRC32 โดยมี XOR-32 แบบเดิมเป็นทางถอย แล้วปิดท้าย SSID และ password ทุกตัวด้วย NUL ไว้ก่อนเพื่อความปลอดภัย ตรงกับที่ตัวอ่านของ mtb-mpy ทำทุกประการ เมื่อปลายทางคืออาร์เรย์ g_boot_wifi_creds ที่ใช้ร่วมกัน การเรียกนั้นอยู่ ภายใต้ wifi_creds_lock() / wifi_creds_unlock(); การอ่านตอนบูตมีผู้อ้างสิทธิ์รายเดียวแต่ก็ยังจับ lock ไว้เพื่อความสม่ำเสมอ (wifi_creds_lock เป็น no-op ก่อนที่ scheduler จะเริ่มทำงาน) อ่านผ่าน bento_storage_read_file(); เรียกจาก task ใดก็ได้
variant ที่ใช้ได้
mtb-mpy และ mtb-only
ตัวอย่าง
ตัวอ่านที่ส่งมอบจริง
void lfs_wifi_creds_init(void) { /* bento_storage_init() owns bring-up */ }
void lfs_wifi_creds_deinit(void) { }
bool lfs_wifi_creds_ready(void) { return bento_storage_ready(); }
/* The mtb-mpy store can inherit a pre-LFS sector image that wants rewriting;
* this store writes only the current format, so never. */
bool lfs_wifi_creds_needs_resave(void) { return false; }
int lfs_wifi_creds_read(qspi_wifi_entry_t *entries, int max_entries) {
if (entries == NULL || max_entries <= 0) return 0;
if (!bento_storage_ready()) return 0;
int n = bento_storage_read_file(CREDS_FILE, s_buf, sizeof(s_buf));
if (n < CREDS_TOTAL_SIZE) return 0;
uint32_t magic; memcpy(&magic, &s_buf[0], 4);
uint16_t version; memcpy(&version, &s_buf[4], 2);
uint16_t count; memcpy(&count, &s_buf[6], 2);
if (magic != QSPI_WIFI_CREDS_MAGIC) return 0;
if (version != QSPI_WIFI_CREDS_VERSION) return 0;
if (count > QSPI_WIFI_CREDS_MAX) return 0;
uint32_t stored; memcpy(&stored, &s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], 4);
if (stored != calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) {
/* Legacy XOR-32 fallback, exactly as the mtb-mpy reader does. */
if (stored != calc_xor32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) return 0;
}
int out = (count < (uint16_t)max_entries) ? count : max_entries;
memcpy(entries, &s_buf[CREDS_HEADER_SIZE], (size_t)out * sizeof(qspi_wifi_entry_t));
/* Defensive termination, same as the mtb-mpy reader. */
for (int i = 0; i < out; i++) {
entries[i].ssid[32] = '\0';
entries[i].password[64] = '\0';
}
return out;
}
bool lfs_wifi_creds_write(const qspi_wifi_entry_t *entries, int count) {
if (count < 0 || count > QSPI_WIFI_CREDS_MAX) return false;
if (count > 0 && entries == NULL) return false;
if (!bento_storage_ready()) return false;
memset(s_buf, 0, sizeof(s_buf));
uint32_t magic = QSPI_WIFI_CREDS_MAGIC;
uint16_t version = QSPI_WIFI_CREDS_VERSION;
uint16_t cnt = (uint16_t)count;
memcpy(&s_buf[0], &magic, 4);
memcpy(&s_buf[4], &version, 2);
memcpy(&s_buf[6], &cnt, 2);
if (count > 0) {
memcpy(&s_buf[CREDS_HEADER_SIZE], entries,
(size_t)count * sizeof(qspi_wifi_entry_t));
}
uint32_t crc = calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE);
memcpy(&s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], &crc, 4);
return bento_storage_write_file(CREDS_FILE, s_buf, sizeof(s_buf));
}

◆ lfs_wifi_creds_write()

bool lfs_wifi_creds_write ( const qspi_wifi_entry_t * entries,
int count )

เขียนทับ /.wifi_creds ด้วย CRC32; ทำ snapshot ภายใต้ lock แล้วเขียนนอก lock

Write WiFi credentials to LittleFS.

Creates/overwrites /.wifi_creds with magic + version + entries + checksum.

Parameters
entriesArray of entries to write
countNumber of entries (1..QSPI_WIFI_CREDS_MAX)
Returns
true on success
ข้อกำหนดการเรียกใช้
เขียนทับ /.wifi_creds ด้วย magic, version, รายการจำนวน count และ CRC32 — เป็น CRC32 เสมอ ไม่ใช่ checksum แบบเดิมโดยเด็ดขาด คืนค่าเป็น bool; เมื่อล้มเหลว แฟล็ก dirty จะยังคงตั้งอยู่โดยเจตนา เพื่อให้รอบถัดไปลองใหม่ — ห้ามล้าง g_boot_wifi_creds_dirty รอบการเขียนที่ล้มเหลว เส้นทางข้าม task บน variant นี้เป็น ตรงข้ามกับของ mtb-mpy: ทำ snapshot ของตัวแปร global ภายใต้ lock แล้วจึงเขียน นอก lock เพราะการเขียนแฟลชกินเวลาระดับมิลลิวินาที และ BLE worker ใช้ตัวแปร global เหล่านั้นร่วมกัน ฟังก์ชันนี้ทำงานทันทีใน WiFi worker task (คอมไพล์เฉพาะเมื่อ BENTO_HAS_MPY เป็น 0) — เมื่อไม่มี VM ก็ไม่มี mpy_main.c จึงไม่มีตัว flush ที่เลื่อนไปทำตอน REPL ว่าง; ถ้อยคำ "requires MicroPython task context" ใน lfs_wifi_creds.h พูดถึงที่เก็บแบบ Python-VFS ไม่ใช่ตัวนี้ เขียนผ่าน bento_storage_write_file()
variant ที่ใช้ได้
mtb-mpy และ mtb-only
ตัวอย่าง
การบันทึกทันทีใน WiFi worker (sensor_auto_task.c): ทำ snapshot ภายใต้ lock เขียนนอก lock และล้างแฟล็ก dirty เฉพาะเมื่อสำเร็จเท่านั้น
/* ...context: inside the IPC_CMD_WIFI_CONNECT success path ... */
#if !BENTO_HAS_MPY
/* No VM means no mpy_main.c and therefore no deferred flusher — the
* "requires MicroPython task context" above is about the Python-VFS
* store, not this one. This runs in the WiFi worker task, and the C
* store is plain lfs2 over serial memory, so write it out now.
* Snapshot under the lock, write outside it: the flash write takes
* milliseconds and the BLE worker shares these globals. */
{
qspi_wifi_entry_t snap[QSPI_WIFI_CREDS_MAX];
int n;
wifi_creds_lock();
n = (int)g_boot_wifi_creds_count;
if (n > QSPI_WIFI_CREDS_MAX) n = QSPI_WIFI_CREDS_MAX;
memcpy(snap, g_boot_wifi_creds, (size_t)n * sizeof(qspi_wifi_entry_t));
wifi_creds_unlock();
extern bool lfs_wifi_creds_write(const qspi_wifi_entry_t *entries, int count);
if (lfs_wifi_creds_write(snap, n)) {
wifi_creds_lock();
g_boot_wifi_creds_dirty = false;
wifi_creds_unlock();
printf("[WiFiIPC] Credentials persisted (%d entries)\r\n", n);
} else {
printf("[WiFiIPC] ERROR: credential save failed — kept dirty\r\n");
}
}
#endif

ตัวเขียนที่ส่งมอบจริงเอง:

void lfs_wifi_creds_init(void) { /* bento_storage_init() owns bring-up */ }
void lfs_wifi_creds_deinit(void) { }
bool lfs_wifi_creds_ready(void) { return bento_storage_ready(); }
/* The mtb-mpy store can inherit a pre-LFS sector image that wants rewriting;
* this store writes only the current format, so never. */
bool lfs_wifi_creds_needs_resave(void) { return false; }
int lfs_wifi_creds_read(qspi_wifi_entry_t *entries, int max_entries) {
if (entries == NULL || max_entries <= 0) return 0;
if (!bento_storage_ready()) return 0;
int n = bento_storage_read_file(CREDS_FILE, s_buf, sizeof(s_buf));
if (n < CREDS_TOTAL_SIZE) return 0;
uint32_t magic; memcpy(&magic, &s_buf[0], 4);
uint16_t version; memcpy(&version, &s_buf[4], 2);
uint16_t count; memcpy(&count, &s_buf[6], 2);
if (magic != QSPI_WIFI_CREDS_MAGIC) return 0;
if (version != QSPI_WIFI_CREDS_VERSION) return 0;
if (count > QSPI_WIFI_CREDS_MAX) return 0;
uint32_t stored; memcpy(&stored, &s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], 4);
if (stored != calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) {
/* Legacy XOR-32 fallback, exactly as the mtb-mpy reader does. */
if (stored != calc_xor32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) return 0;
}
int out = (count < (uint16_t)max_entries) ? count : max_entries;
memcpy(entries, &s_buf[CREDS_HEADER_SIZE], (size_t)out * sizeof(qspi_wifi_entry_t));
/* Defensive termination, same as the mtb-mpy reader. */
for (int i = 0; i < out; i++) {
entries[i].ssid[32] = '\0';
entries[i].password[64] = '\0';
}
return out;
}
bool lfs_wifi_creds_write(const qspi_wifi_entry_t *entries, int count) {
if (count < 0 || count > QSPI_WIFI_CREDS_MAX) return false;
if (count > 0 && entries == NULL) return false;
if (!bento_storage_ready()) return false;
memset(s_buf, 0, sizeof(s_buf));
uint32_t magic = QSPI_WIFI_CREDS_MAGIC;
uint16_t version = QSPI_WIFI_CREDS_VERSION;
uint16_t cnt = (uint16_t)count;
memcpy(&s_buf[0], &magic, 4);
memcpy(&s_buf[4], &version, 2);
memcpy(&s_buf[6], &cnt, 2);
if (count > 0) {
memcpy(&s_buf[CREDS_HEADER_SIZE], entries,
(size_t)count * sizeof(qspi_wifi_entry_t));
}
uint32_t crc = calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE);
memcpy(&s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], &crc, 4);
return bento_storage_write_file(CREDS_FILE, s_buf, sizeof(s_buf));
}

◆ lfs_wifi_creds_needs_resave()

bool lfs_wifi_creds_needs_resave ( void )

บน variant นี้เป็น false เสมอ — ที่เก็บฝั่ง C เขียนเฉพาะรูปแบบปัจจุบันเท่านั้น

Check if credentials need re-saving (XOR-32 → CRC32 migration). Call after boot WiFi auto-connect; if true, re-read and re-write.

ข้อกำหนดการเรียกใช้
บน variant นี้เป็น false เสมอ: ที่เก็บฝั่ง C เขียนเฉพาะรูปแบบ CRC32 ปัจจุบันเท่านั้น สิ่งที่มันเขียนไว้จึงไม่มีอะไรที่ต้องย้ายรูปแบบ โค้ดบูตส่วนกลางยังเรียกฟังก์ชันนี้หลังการอ่าน และเขียนใหม่เมื่อได้ค่า true พร้อม count มากกว่า 0 — ทางแยกนั้นทำงานจริงบน mtb-mpy ซึ่งไฟล์รูปแบบเดิมที่ใช้ XOR-32 จะได้รับการบันทึกใหม่เป็น CRC32 และที่นี่ไม่มีการเข้าทางแยกนั้นเลย ไฟล์รูปแบบเดิมที่อ่านบน variant นี้ยังได้รับการยอมรับอยู่ (ทางถอย XOR-32) และจะกลายเป็น CRC32 ในการเขียนครั้งถัดไป
variant ที่ใช้ได้
mtb-mpy และ mtb-only
ตัวอย่าง
นิยามที่ส่งมอบจริง
void lfs_wifi_creds_init(void) { /* bento_storage_init() owns bring-up */ }
void lfs_wifi_creds_deinit(void) { }
bool lfs_wifi_creds_ready(void) { return bento_storage_ready(); }
/* The mtb-mpy store can inherit a pre-LFS sector image that wants rewriting;
* this store writes only the current format, so never. */
bool lfs_wifi_creds_needs_resave(void) { return false; }
int lfs_wifi_creds_read(qspi_wifi_entry_t *entries, int max_entries) {
if (entries == NULL || max_entries <= 0) return 0;
if (!bento_storage_ready()) return 0;
int n = bento_storage_read_file(CREDS_FILE, s_buf, sizeof(s_buf));
if (n < CREDS_TOTAL_SIZE) return 0;
uint32_t magic; memcpy(&magic, &s_buf[0], 4);
uint16_t version; memcpy(&version, &s_buf[4], 2);
uint16_t count; memcpy(&count, &s_buf[6], 2);
if (magic != QSPI_WIFI_CREDS_MAGIC) return 0;
if (version != QSPI_WIFI_CREDS_VERSION) return 0;
if (count > QSPI_WIFI_CREDS_MAX) return 0;
uint32_t stored; memcpy(&stored, &s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], 4);
if (stored != calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) {
/* Legacy XOR-32 fallback, exactly as the mtb-mpy reader does. */
if (stored != calc_xor32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE)) return 0;
}
int out = (count < (uint16_t)max_entries) ? count : max_entries;
memcpy(entries, &s_buf[CREDS_HEADER_SIZE], (size_t)out * sizeof(qspi_wifi_entry_t));
/* Defensive termination, same as the mtb-mpy reader. */
for (int i = 0; i < out; i++) {
entries[i].ssid[32] = '\0';
entries[i].password[64] = '\0';
}
return out;
}
bool lfs_wifi_creds_write(const qspi_wifi_entry_t *entries, int count) {
if (count < 0 || count > QSPI_WIFI_CREDS_MAX) return false;
if (count > 0 && entries == NULL) return false;
if (!bento_storage_ready()) return false;
memset(s_buf, 0, sizeof(s_buf));
uint32_t magic = QSPI_WIFI_CREDS_MAGIC;
uint16_t version = QSPI_WIFI_CREDS_VERSION;
uint16_t cnt = (uint16_t)count;
memcpy(&s_buf[0], &magic, 4);
memcpy(&s_buf[4], &version, 2);
memcpy(&s_buf[6], &cnt, 2);
if (count > 0) {
memcpy(&s_buf[CREDS_HEADER_SIZE], entries,
(size_t)count * sizeof(qspi_wifi_entry_t));
}
uint32_t crc = calc_crc32(s_buf, CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE);
memcpy(&s_buf[CREDS_HEADER_SIZE + CREDS_ENTRIES_SIZE], &crc, 4);
return bento_storage_write_file(CREDS_FILE, s_buf, sizeof(s_buf));
}