STM32G0 Dual Bank Flash: Read-While-Write và EEPROM Emulation không freeze
STM32G0B1 dual bank mode: DBANK option bit, read-while-write, tại sao erase Bank 2 không block code đang chạy ở Bank 1, và gotcha về prefetch khi jump giữa bank.
STM32G0B1 có 512KB Flash chia thành hai bank 256KB độc lập. Tính năng này không chỉ đơn thuần là “nhiều Flash hơn” - nó thay đổi căn bản cách firmware có thể thao tác với Flash mà không bị freeze.
Vấn đề của single-bank - nhắc lại ngắn
Trên chip single-bank, Flash controller chỉ có một bus. Khi erase/program đang chạy, bus bị chiếm - CPU không fetch được instruction → program đứng.
Erase một page 2KB mất ~20-40ms. Trong RTOS, đây đủ để bỏ lỡ nhiều SysTick, làm lỗi timeout communication, hoặc trigger watchdog.
Dual bank: hai bus độc lập
STM32G0B1 có hai Flash interface riêng biệt:
CPU
├─→ AHB Bus → Flash Interface 1 → Bank 1 (0x08000000 - 0x0803FFFF)
└─→ AHB Bus → Flash Interface 2 → Bank 2 (0x08040000 - 0x0807FFFF)
Khi Flash Interface 2 đang erase Bank 2, Flash Interface 1 vẫn phục vụ đọc Bank 1 bình thường. CPU đang chạy code từ Bank 1 không bị gián đoạn.
Timeline dual-bank erase Bank 2:
Bank 1: |--run--|--run--|--run--|--run--| ← không bị ảnh hưởng
Bank 2: |---ERASE 20-40ms---|
Interrupt, RTOS tick, UART - tất cả vẫn chạy bình thường trong khi Bank 2 đang bị erase.
Bật dual bank: DBANK option bit
Dual bank mode không tự động bật - phải set DBANK bit trong Flash Option Bytes:
/* Đọc option bytes hiện tại */
FLASH_OBProgramInitTypeDef ob_config;
HAL_FLASHEx_OBGetConfig(&ob_config);
/* Set DBANK */
ob_config.OptionType = OPTIONBYTE_USER;
ob_config.USERType = OB_USER_DBANK;
ob_config.USERConfig = OB_DBANK_128_BITS; /* Enable dual bank */
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
HAL_FLASHEx_OBProgram(&ob_config);
HAL_FLASH_OB_Launch(); /* Reset và apply option bytes */
HAL_FLASH_OB_Launch() trigger system reset - MCU sẽ khởi động lại với dual bank mode.
Lưu ý: Khi bật DBANK, mỗi double-word (64-bit) word của Flash sẽ được đọc theo 2 lần 32-bit thay vì 1 lần 64-bit. Wait state có thể cần điều chỉnh.
Single bank vs Dual bank - địa chỉ thay đổi
| Mode | Bank 1 | Bank 2 |
|---|---|---|
| Single bank | 0x08000000 - 0x0807FFFF (512K) | - |
| Dual bank | 0x08000000 - 0x0803FFFF (256K) | 0x08040000 - 0x0807FFFF (256K) |
Linker script phải reflect đúng layout khi đổi mode.
Erase/Program Bank 2 trong khi chạy từ Bank 1
Khi code đang chạy từ Bank 1, thao tác Flash trên Bank 2 không cần execute-from-RAM trick:
/* Code này đang chạy từ Bank 1 */
void SaveConfigToBank2(uint32_t page_in_bank2) {
/* page_in_bank2 = page number tính từ đầu Bank 2 */
FLASH_EraseInitTypeDef cfg = {
.TypeErase = FLASH_TYPEERASE_PAGES,
.Banks = FLASH_BANK_2, /* ← chỉ rõ Bank 2 */
.Page = page_in_bank2,
.NbPages = 1,
};
uint32_t err;
HAL_FLASH_Unlock();
HAL_FLASHEx_Erase(&cfg, &err); /* Không block Bank 1! */
/* Ghi data */
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,
0x08040000 + page_in_bank2 * 2048,
my_data);
HAL_FLASH_Lock();
}
RTOS, interrupt, UART - tiếp tục hoạt động trong khi hàm này đang erase Bank 2.
Gotcha: Prefetch phải disable khi jump giữa bank
Đây là điều ít tài liệu đề cập nhưng quan trọng trên STM32G0.
Flash prefetch buffer đọc trước instruction - nhưng nó không biết bạn sắp nhảy sang bank khác. Nếu nhảy từ Bank 1 sang Bank 2 (hoặc ngược lại) mà prefetch đang active, có thể đọc instruction sai → crash không xác định.
void JumpToBank2(uint32_t address_in_bank2) {
/* PHẢI disable prefetch trước khi jump giữa bank trên G0 */
__HAL_FLASH_PREFETCH_BUFFER_DISABLE();
typedef void (*FuncPtr)(void);
FuncPtr fn = (FuncPtr)(*(uint32_t*)(address_in_bank2 + 4));
__set_MSP(*(uint32_t*)address_in_bank2);
SCB->VTOR = address_in_bank2;
fn();
}
Lưu ý: Đây là G0-specific. Trên STM32G4, ST xác nhận không có vấn đề tương tự khi jump giữa bank.
Layout điển hình cho EEPROM emulation với dual bank
Bank 1: 0x08000000 ─────────────────── 0x0803FFFF (256K)
├─ Application code: 0x08000000 - 0x0803BFFF (240K)
└─ [có thể dùng thêm nếu cần]
Bank 2: 0x08040000 ─────────────────────────────── 0x0807FFFF (256K)
├─ EEPROM page A: 0x08040000 - 0x08040800 (2K, page 0)
└─ EEPROM page B: 0x08040800 - 0x08041000 (2K, page 1)
[phần còn lại tùy dự án]
EEPROM emulation rotate giữa page A và B trong Bank 2. Code chạy từ Bank 1 erase/ghi Bank 2 mà không bị freeze. Đây là lý do dual bank G0 rất phù hợp cho POS system hoặc thiết bị cần lưu config thường xuyên trong khi vẫn phải xử lý giao tiếp real-time.
Tóm tắt
| Mục | Giá trị | Ghi chú |
|---|---|---|
| Single bank | Erase/program freeze toàn bộ program ~20-40ms/page | Interrupt không chạy được. RTOS tick bị bỏ lỡ. Phải dùng execute-from-RAM. |
| Dual bank | Erase Bank 2 không block Bank 1 | Code từ Bank 1 chạy bình thường. Interrupt, RTOS, UART không bị ảnh hưởng. |
| DBANK bit | Option byte - phải set thủ công | Cần reset để apply. Thay đổi memory map (512K → 2×256K). |
| Prefetch gotcha | Disable trước khi jump giữa bank | G0-specific. Không disable có thể crash khi jump. |
Checklist dual bank setup
Bài liên quan
- Flash Operations STM32: Erase, Write, Polling và tại sao program đứng
- Linker Script STM32: MEMORY, sections và LMA/VMA
- STM32G0 Flash: linker script, EEPROM emulation và dual bank
Tài liệu tham khảo
- STM32G0B1 Reference Manual RM0444 - Flash chapter, dual bank configuration
- AN4894 - EEPROM Emulation on STM32
- ST Community: G0 prefetch and bank jump
Thấy nội dung này hữu ích?
Lưu lại hoặc chia sẻ cho người cũng đang học firmware, BIOS/UEFI và embedded systems.
Nội dung liên quan
Một số bài viết, ghi chú hoặc project có liên quan đến nội dung bạn vừa đọc.
Flash STM32G0: Linker Script, EEPROM Emulation và Dual Bank
Từ linker script chia vùng Flash, erase/write API, tại sao single-bank freeze, đến EEPROM emulation thực tế trên STM32G0 dual bank - không dùng thư viện ST, tự viết cho gọn.
Flash, EEPROM và RAM khác nhau như thế nào?
Giải thích nguyên lý hoạt động của Flash, EEPROM và RAM.
Flash Operations STM32: Erase, Write, Polling và tại sao program đứng
Cách thao tác Flash STM32 qua HAL: unlock, erase, write, polling vs interrupt, và nguyên nhân program freeze khi xóa Flash.
Biến note thành bài viết hoàn chỉnh
Notes là nơi ghi nhanh khái niệm.