Base mới
ak-mcu-base v1.3.0, bootloader 1.2.0
Base cũ
legacy/sources/ của ak-base-kit-pio v1.3.0, bootloader 0.0.3
Board
AK Base Kit, STM32L151CBT6 (128K flash, 32K RAM)
Ngày lập
06/10/2026
Khuyến nghị. Dự án mới dùng ak-mcu-base. Base cũ dành cho dự án đang chạy trên nó, hoặc khi cần ngay driver mà base mới chưa có.

1. Bản đồ flash, vẽ đúng tỉ lệ

Cả hai bên đều dành 12K đầu flash cho phần khởi động và để lại 116K cho app. Khác nhau ở cách dùng 12K đó.

Base cũboot dùng 6.820 B
8K
4K
APP 116K tại 0x08003000
ak-mcu-baseboot dùng 8.056 B
12K
APP 116K tại 0x08003000, 256 B đầu là header ảnh
0x080000000x08020000
BootloaderBSF: trạng thái boot ↔ appApplication

Bootloader mới lớn hơn 1.236 B vì thêm CRC32, kiểm header, hai bản ghi trạng thái và chế độ cứu ảnh. Trạng thái boot chuyển sang EEPROM nên vùng BSF 4K nhường lại cho bootloader; app không mất byte nào.

2. Những điểm hơn

2.1 Bootloader và cập nhật firmware

Hạng mụcBase cũak-mcu-baseĐã kiểm bằng
Toàn vẹn ảnhTổng 16 bit của các word, chỉ tính sau khi chépCRC32 toàn ảnh, tính mỗi lần boot và trước khi càiUnit test, trên board
Nạp nhầm ảnhChỉ có magic number trong headerHeader mang tên board và địa chỉ nạp; ảnh của board khác bị từ chối ngay khi nhận xongUnit test
Cài hỏng lặp lạiChecksum sai thì reset và thử lại mãiTối đa 3 lần, sau đó về chế độ loader chờ nạpUnit test
Mất điện lúc càiXoá hết APP rồi chép; lần boot sau dựa vào lệnh còn trong BSFTrang header của APP xoá đầu tiên, chép cuối cùng: ảnh chép dở luôn "không hợp lệ"3.252 điểm cắt điện trên giả lập, cho cả hai kiểu staging
Trạng thái boot ↔ appBSF 4K trong flash, xoá rồi mới ghi2 × 32 B trong EEPROM, hai bản ghi luân phiên có số thứ tựCắt ở từng byte của lần ghi (65 điểm); trên board: OTA liên tiếp
Giao thức nạpBoot có giao thức UART riêng, app đi đường khácMột giao thức fw_proto cho cả boot lẫn app, dùng chung UART với shellTrên board

Bản mới còn có: tự cài lại từ staging khi APP hỏng, và chế độ AK_STAGING=internal (APP 58K + staging 58K trong flash trong) cho board không gắn flash SPI. Cả hai mới qua unit test.

2.2 Kernel AK

API giữ nguyên (task_post_*, timer_set, fsm/tsm, bảng task). Mọi thay đổi đều có unit test.

Hạng mụcBase cũak-mcu-base
Timer chu kỳ khi một handler chạy lâuNạp lại counter = period, bỏ phần trễ nên trôi dầnMốc hết hạn tuyệt đối, giữ đúng pha
timer_set() gọi sau handler chạy N msBị trừ luôn N ms đã dồn nên nổ sớmTính từ thời điểm gọi
Tải của ngắt tick 1 msMỗi ms cấp một message và duyệt cả danh sách timerChỉ post khi timer gần nhất đến hạn
src_task_id của message từ polling taskMang id của task chạy gần nhấtAK_TASK_IDLE_ID
Vòng lặp chính lúc rảnhQuay liên tụcWFI; kiểm hàng đợi và ngủ trong cùng một critical section
Bảng task khai báo saipri = 0 ghi ra ngoài mảngFATAL ngay lúc khởi động

2.3 Build, kiểm thử và chuyển chip

Hạng mụcBase cũak-mcu-base
Tối ưu lúc link (LTO)KhôngBật mặc định; boot và app nhỏ hơn khoảng 14%
Cảnh báo biên dịchKhông ép-Wall -Wextra -Werror cho mã của base
Kiểm thử trên máy tínhChỉ lớp ModbusKernel 16 ca, bootloader và OTA 165 kiểm tra, OTA đầu-cuối trên giả lập ak_sim
Phụ thuộc chipKernel, boot, app gọi thẳng SPL và lớp ArduinoMã phía trên HAL không include header của chip; thêm chip là viết port/<chip>/

2.4 Số đo trên board

Phép đoKết quảGhi chú
OTA ảnh 10,5K qua UART 115200 bằng ak_fw.py1,6 sGồm cả verify trên board. Trước khi sửa tool là 5,4 s
Từ reset tới lúc app chạy, ảnh 11K31 msĐã gồm CRC toàn ảnh
Mức dùng pool message pure cao nhất2Sau nhiều phút chạy; khớp với việc tick không còn post mỗi ms

Không so trực tiếp được với OTA qua RS485 9600 của base cũ (khoảng 78 s mỗi lượt) vì khác đường truyền và khác cỡ ảnh.

Thêm ở v1.2.0 và v1.3.0 Nhật ký sự cố trong EEPROM (HardFault, FATAL, watchdog, task bị bỏ đói), giám sát từng task, đo mức dùng stack, script xuất dự án mới, build PlatformIO và CI. Modbus RTU trên RS485 (slave, master, OTA: ảnh 20K mất 26 s ở 9600 baud, đo trên kit) và bộ demo trên kit (đồng hồ số, Snake, Flappy). Chi tiết: tien-ich.md.

3. Ngang nhau

Bốn thứ dưới đây dễ bị tưởng là điểm mới, nhưng base cũ đã có.

  • Console TX không chặn (ring + ngắt TXE): base cũ có sẵn, bản mới thêm ở v1.1.0.
  • Ghi flash trong theo half-page từ RAM.
  • Watchdog trong bootloader: cũ 32 s, mới 10 s.
  • Chỗ cho app: 116K tại 0x08003000, staging trên flash SPI tại 0x80000.

4. Còn thiếu so với base cũ

ThiếuGhi chú
Driver: nút, còi, OLED, nRF24, EEPROM ngoài, lớp ArduinoCố ý không mang sang; viết lại theo nhu cầu từng sản phẩm
Rollback về ảnh trướcChỉ có cài lại từ staging
Ký số ảnhChỉ có CRC: chống hỏng dữ liệu, không chống giả mạo
Dự án conChưa dự án nào chuyển sang; các dự án hiện có vẫn theo base cũ
App và bootloader phải cùng đời Bootloader 1.0.0 chỉ đọc bản ghi trạng thái thứ nhất nên bỏ sót lệnh cài của app từ 1.1.0. Nạp bootloader trước qua SWD, rồi mới nạp hoặc OTA app.

5. Đã kiểm gì trên board

  • Boot sang app, shell (help, ver, info, verify, stat), OTA nhiều lượt qua bootloader 1.1.0.
  • Chế độ loader 16 s không reset. Dừng lõi 13 s bằng debugger thì watchdog của bootloader reset và quay lại đúng chế độ loader.
  • Dồn 40 dòng lệnh khi một lệnh chậm đang chạy: không FATAL, dòng thừa bị bỏ kèm thông báo.
Chưa kiểm trên board Rút điện giữa lúc bootloader đang cài, OTA ảnh gần 116K, timeout của flash SPI, độ chính xác timer bằng máy hiện sóng.