Sau khi đi qua update flow, fail-safe, security và chuyện nén firmware, có một phần rất dễ bị xem nhẹ nhưng lại quyết định khá nhiều tới thiết kế bootloader: đặc tính của flash.
Với MCU, flash memory không phải kiểu vùng nhớ cứ ghi vào là xong.
Mỗi loại flash đều có ràng buộc riêng như erase trước program, page size, sector size, bank boundary, execute-while-write hay giới hạn số lần ghi xóa.
Nếu bỏ qua các điểm này, thiết kế bootloader rất dễ vướng lỗi khó debug.
Mục lục
Vì sao đặc tính của flash ảnh hưởng trực tiếp tới bootloader
Bootloader gần như luôn phải đọc flash, ghi flash memory, kiểm tra image trong flash memory và ra quyết định boot dựa trên dữ liệu đang nằm trong flash memory. Vì vậy, mọi giới hạn của flash đều tác động thẳng vào boot flow, update flow và fail-safe logic.
Bootloader không thể được thiết kế tách rời khỏi cách flash memory hoạt động trên đúng con MCU mình đang dùng.
Erase trước khi program
Đây là nguyên tắc cơ bản nhất khi làm việc với flash. Với đa số MCU, muốn ghi dữ liệu mới thì trước đó phải xóa vùng flash memory tương ứng. Không thể coi flash như RAM rồi ghi đè tự do từng byte.
Điều này kéo theo vài hệ quả quan trọng cho bootloader.
- Không thể cập nhật application image theo kiểu sửa vài byte tùy ý nếu chưa xử lý erase đúng cách.
- Muốn update an toàn thì phải tính kỹ thứ tự erase, program và verify.
- Nếu update bị gián đoạn sau khi erase nhưng trước khi ghi xong, application image có thể không còn boot được.
Page size, sector size và erase block
Flash không phải lúc nào cũng xóa và ghi theo cùng một đơn vị.
Có MCU ghi theo word hoặc phrase nhỏ, nhưng erase lại theo page hoặc sector lớn hơn nhiều.
Đây là chỗ rất dễ làm bootloader sai ngay từ lúc vẽ flash layout. Nếu metadata, application image và config nằm chung trong cùng một erase block, chỉ một lần update cũng có thể làm mất dữ liệu không định đụng tới.
Page size thường là đơn vị nhỏ hơn dùng cho một số thao tác ghi hoặc quản lý flash.
Sector size hoặc erase block là đơn vị mà flash phải xóa theo.
Thiết kế layout nên bám theo erase block trước, không nên chỉ nhìn theo kích thước file firmware.
Alignment và địa chỉ hợp lệ
Nhiều thao tác ghi flash memory yêu cầu dữ liệu phải đúng alignment, ví dụ 4 byte, 8 byte hoặc lớn hơn tùy controller. Nếu bootloader nhận dữ liệu theo block nhưng không căn chỉnh đúng, việc program flash có thể lỗi hoặc dữ liệu ghi ra không đúng như mong muốn.
Không chỉ phần ghi, cả image header, vector table, metadata và entry address của application image cũng phải nằm ở vị trí hợp lệ theo kiến trúc CPU và linker layout.
Bank boundary và chuyện boot từ nhiều vùng flash
Một số MCU chia flash thành nhiều bank. Điều này ảnh hưởng trực tiếp tới cách thiết kế A/B partition, staging area và cả chiến lược update bootloader.
Nếu application image nằm trọn trong một bank riêng, bootloader có thể dễ tổ chức hơn trong lúc bank kia vẫn đang được đọc hoặc đang giữ code chạy. Ngược lại, nếu layout cắt ngang bank boundary theo cách bất tiện thì update logic sẽ rối lên rất nhiều.
Đây cũng là lý do phải hiểu rõ việc MCU có hỗ trợ boot từ bank khác, remap bank hay swap bank hay không trước khi chọn A/B layout.
Execute while write
Một số MCU không cho vừa chạy code từ flash vừa program hoặc erase chính vùng flash đó.
Một số MCU khác cho phép ở mức nào đó nếu tách sang bank khác.
Đây là điểm rất quan trọng khi quyết định ai sẽ đứng ra làm update.
Nếu MCU không hỗ trợ execute while write trên vùng đang thao tác, bootloader hoặc flash loader có thể phải chạy từ RAM trong lúc erase/program flash. Đó là lý do nhiều thiết kế cần có flash driver chạy trong RAM.
Wear và endurance của flash
Flash có giới hạn số lần erase/program. Với application image, điều này có thể chưa quá căng nếu update không diễn ra thường xuyên. Nhưng với metadata, boot counter, state flag hoặc security counter thì mọi chuyện khác hẳn.
Nếu bootloader ghi đi ghi lại cùng một chỗ quá nhiều lần, vùng đó có thể xuống cấp sớm hơn phần còn lại. Vì vậy thiết kế metadata phải tính cả wear, chứ không chỉ tính logic state machine.
Tear khi update bị gián đoạn
Tear là tình huống dữ liệu rơi vào trạng thái nửa cũ nửa mới vì update bị gián đoạn giữa chừng.
Trên bootloader, đây là vấn đề rất thực tế vì nó có thể xảy ra đúng lúc đang ghi metadata, đang copy application image hoặc đang đổi boot state.
Giải quyết tear không chỉ là chuyện check CRC. Nó còn là chuyện sắp xếp thứ tự ghi, chọn vị trí metadata, thiết kế marker và bảo đảm khi khởi động lại thì bootloader vẫn hiểu đúng trạng thái hiện tại.
Gợi ý thực tế là luôn thiết kế theo hướng nếu bị gián đoạn giữa chừng thì bootloader vẫn đọc ra được một trạng thái rõ ràng. Thường sẽ cần ghi theo thứ tự có chủ đích, dùng marker hoặc version nhỏ để phân biệt bản ghi cũ và mới, và tránh việc chỉ dựa vào một lần ghi duy nhất cho thông tin quan trọng.
Metadata nên để ở đâu
Metadata có thể nằm ở code flash, data flash, EEPROM hoặc vùng NVM riêng, tùy kiến trúc MCU.
Nhưng chọn vị trí nào thì cũng phải xét cùng lúc ba chuyện: an toàn khi gián đoạn, số lần ghi lặp lại và nguy cơ bị xóa nhầm khi update application image.
Nếu metadata nằm chung erase block với application image hoặc config quan trọng, một thao tác erase sai có thể phá cả boot logic lẫn dữ liệu vận hành.
Flash driver chạy trong RAM
Khi flash memory không cho vừa chạy code vừa erase hoặc program trên cùng bank, bootloader hoặc flash loader có thể copy phần code thao tác với flash lên RAM rồi chạy từ đó.
Cách làm này giúp việc ghi flash memory an toàn hơn, nhưng flow update sẽ phức tạp hơn vì phải thêm bước copy code, chuẩn bị vùng RAM phù hợp và kiểm soát chặt đoạn code đang chạy trong RAM.
Những lỗi thiết kế hay gặp
Một số lỗi lặp lại rất nhiều khi thiết kế bootloader mà không nhìn kỹ đặc tính flash.
- Thiết kế flash layout không bám theo erase block thật của MCU.
- Để metadata chung erase block với application image hoặc config quan trọng.
- Không tính tới alignment khi ghi theo block.
- Chọn A/B layout nhưng MCU lại không thuận tiện để boot từ nhiều offset hoặc nhiều bank.
- Bỏ qua giới hạn execute while write.
- Ghi state quá nhiều lần vào một ô flash nhỏ mà không tính wear.
Kết luận
Đặc tính của flash không phải chi tiết phụ. Nó là một phần lõi của thiết kế bootloader trên MCU. Nếu hiểu sai cách flash hoạt động, gần như mọi thứ phía trên như update flow, fail-safe, A/B partition hay metadata đều có thể sai từ gốc.








