Site icon TAPIT

Cập nhật chương trình từ xa trên vi điều khiển STM32 – Firmware Over The Air (FOTA) – P5

Trong chuỗi bài viết hướng dẫn cập nhật chương trình từ xa (FOTA) cho dòng vi điều khiển STM32F103, mình đã trình bày tổng quan về mô hình FOTA ở phần 1, cách viết chương trình Bootloader ở phần 2, và giải thích về cấu trúc của một file chương trình Intel HEX ở phần 3. Ở phần 4, mình đã hướng dẫn lập trình chương trình FOTA với file định dạng Intel HEX. Bài viết này mình sẽ tiếp tục giới thiệu cấu trúc của file firmware ở định dạng BIN và hướng dẫn lập trình chương trình FOTA với file đó. Những hướng dẫn này cũng có thể tham khảo và áp dụng cho các dòng vi điều khiển khác.

[HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]

Phần 5: Lập trình chương trình FOTA với file định dạng BIN

1. Định nghĩa

File định dạng BIN (Binary file) có đuôi .bin. Đây là một dạng tệp tin phi văn bản, được lưu trữ dưới định dạng mã nhị phân. Máy tính chúng ta hoạt động dựa theo mã nhị phân nên chúng ta thường dùng loại tệp tin này để lưu tất cả thông tin dữ liệu của bộ nhớ chương trình trên vi điều khiển.

Cấu trúc của một file định dạng BIN là:

Chúng ta khó có thể đọc hiểu được mã nhị phân nên mình dùng phần mềm SublimeText để chuyển đổi kiểu đọc từ Binary sang Hexadecimal thì sẽ thấy được nội dung của tệp tin này như hình bên dưới:

File định dạng BIN được đọc dưới dạng mã hexadecimal.

2. Cách tạo file định dạng BIN với phần mềm Keil C

Để tạo file định dạng BIN với phần mềm Keil C ta lần lượt làm các bước sau:

Giả sử tên file định dạng BIN của mình là VectorTableRelocation.bin, được lưu vào thư mục MDK-ARM/ VectorTableRelocation

Bước 1: Ấn vào Option, chọn User.

Bước 2: Kích chọn Run#1 tại mục After Build/Rebuild và Copy chuỗi sau vào trong

C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe –bin VectorTableRelocation\VectorTableRelocation.axf –output VectorTableRelocation\VectorTableRelocation.bin

Với

C:\Keil_v5\ARM\ARMCC\bin\fromelf.exe là đường dẫn file đến file fromelf.exe
VectorTableRelocation\VectorTableRelocation.axf là file .axf
VectorTableRelocation\VectorTableRelocation.bin là file .bin ta cần

Bước 3: Sau khi Build chương trình thì các bạn sẽ được như dưới

3. So sánh khi tải dữ liệu kiểu file Intel Hex và file Binary từ Server xuống vi điều khiển:

– File Intel Hex:

Dữ liệu tải xuống vi điều khiển qua giao tiếp UART được lưu dưới dạng các kí tự bảng mã ASCII.

Ví dụ mình tải một giá trị dữ liệu 32 bit là 0x200013E0. Trong Intel HEX file thì giá trị trên sẽ được chuyển sang kiểu chuỗi và tách ra thành 8 byte là ‘E’ ‘0’ ‘1’ ‘3’ ‘0’ ‘0’ ‘2’ ‘0’, khi thực hiện quá trình GET thì thông qua giao thức UART, ta sẽ nhận 8 lần kí tự như dưới.

Giá trị 0x200013E0 trong file định dạng Intel HEX khi tải xuống vi điều khiển

– File Binary:

Dữ liệu tải xuống vi điều khiển qua giao thức UART sẽ lưu 8 bit 1 lần mà không bị thay đổi thành kí tự.

Cũng giá trị 0x200013E0 như ví dụ trên thì trong file định dạng BIN thì nó sẽ được chuyển thành 4 byte 0xE0, 0x13, 0x00, 0x20. Khi thực hiện quá trình GET thì thông qua giao thức UART sẽ nhận 4 lần dữ liệu như hình dưới.

Giá trị 0x200013E0 trong Binary File khi tải xuống vi điều khiển

3. Ghi Firmware vào bộ nhớ chương trình (FLASH) và kiểm tra lỗi:

Trong bài viết này mình sẽ thực hiện quá trình lưu Firmware vào vi điều khiển trước rồi sẽ kiểm tra tính toàn ven của dữ liệu. Do vậy chương trình FOTA sẽ có một chút thay đổi như sau:

 

– Lưu Firmware vào bộ nhớ FLASH:

Để lưu Firmware vào vi điều khiển, mình sẽ thực hiện các bước như sau:

Thuật toán ghi Firmware vào bộ nhớ chương trình

Bước 1: Thực hiện GET dữ liệu về MCU, sau đó mình sẽ chia lần lượt 4 byte thành một cặp.
Ví dụ ta lấy được 0xE0, 0x13, 0x00, 0x20 là bốn byte đầu tiên như hình dưới.

Bước 2: Kết hợp phép tính OR và dịch để tạo thành một biến 32bit.

Lưu ý: Khi sử dụng phép dịch trái thì các bạn nên sử dụng ép kiểu uint32_t nhé.

Bước 3: Dùng kết quả vừa tính được ở bước 2 ghi vào địa chỉ trong bộ nhớ FLASH
Với ví dụ biến valTemp tính trên thì sẽ lưu vào địa chỉ đầu tiên trong Current Firmware Address 0x08013800 (xem lại tổ chức bộ nhớ mô hình FOTA của mình tại phần 1)

Bước 4: Tiếp tục cộng 4 cho giá trị địa chỉ (vì một lần lưu 4 byte dữ liệu) và làm lại những bước trên cho đến khi nạp hết dữ liệu trong tệp tin Binary đã tải về vào bộ nhớ FLASH.
Tiếp tục theo ví dụ trên thì giá trị 0x0800E945 sẽ lưu vào địa chỉ 0x08013804, 0801253F sẽ lưu vào 0x08013808,…

Sau khi đã lưu firmware vào bộ nhớ FLASH ta sẽ kiểm tra dữ liệu:

– Kiểm tra dữ liệu

File định dạng BIN thì chỉ chứa dữ liệu để lưu vào Firmware của MCU và không có trường kiểm tra như trường checksum trong file Intel HEX, vì vậy ta sẽ không thể kiểm tra dữ liệu đã tải về bị lỗi hay không. Ta có thể khắc phục nhược điểm đó bằng cách thêm các byte kiểm tra tính toàn vẹn của dữ liệu vào file trước khi tải lên Server.

Có nhiều phương pháp để kiểm tra lỗi trong quá trình truyền nhận như: Kiểm tra chẵn lẻ (parity check), Checksum hay CRC (Cyclic redundancy check),… Bạn có thể đọc lại thuật toán Checksum file nạp chương trình Intel HEX ở phần 3 của chuỗi bài viết này.

Còn trong phần hướng dẫn làm việc với file binary này, mình sẽ giới thiệu phương pháp CRC-32 với những lý do sau:

Lưu ý: Sau khi sử dụng tính toán CRC-32 thì các bạn sẽ có 4 byte kiểm tra và các byte này mình sẽ được gắn vào cuối Binary File. Trong quá trình lưu firmware thì ta cũng có thể lưu cả 4 byte này vào bộ nhớ Flash, điều đó không ảnh hưởng đến đến quá trình hoạt động của vi điều khiển.

Tìm hiểu thêm về CRC tại đâyCRC được STM32 hỗ trợ là CRC-32/MPEG-2

Bạn có thể sử dụng các cách sau:

Cách 1: Các bạn tự tìm hiểu và viết 1 chương trình C hoặc C# hoặc một ngôn ngữ nào khác theo các bước sau:

Bước 1: Tổng quan và phân loại về CRC32.
Bước 2: Thuật toán CRC32/MPEG-2.
Bước 3: Tính toán thủ công và kiểm tra lại bằng 1 số tool online như: https://crccalc.com/.
Bước 4: Viết chương trình đọc file bin, tính toán CRC, in giá trị lên màn hình hoặc lưu giá trị vào cuối file.

Cách 2: Sử dụng trực tiếp từ chức năng CRC của STM32.

Các bạn cần cấu hình bên STM32CubeMX như sau: chọn CRC trong Computing, sau đó bật Activated nhé.
Lưu ý: Một số dòng vi điều khiển sẽ không có phần Configuration CRC nhưng các bạn vẫn sử dụng được bình thường nhé.

Dưới đây là một chương trình ví dụ để tính giá trị CRC của một mảng: Firmware Input {0x200013E0, 0x0800E945, 0x0801253F, 0x080118D5}.

Ta sử dụng hàm HAL_CRC_Calculate trong thư viện stm32f1xx_hal_crc.c

Kết quả tính ra sẽ bằng 0xB0EDFEE4

Như vậy, để tính toán CRC-32 cho cả một file Binary làm như sau:

Bước 1: Nạp file chương trình mới vào vi điều khiển.
Bước 2: Sử dụng hàm tính CRC-32 của HAL để tính kiểm tra trực tiếp vào bộ nhớ FLASH.
Bước 3: Lấy kết quả vừa tính được thêm vào cuối file Binary.

Trong chương trình FOTA, để kiểm tra CRC-32 sau khi tải file về thì ta sẽ có một chút thay đổi ở bước 3, ở đây sẽ có 2 cách để kiểm tra:

Cách 1: So sánh kết quả tính CRC vừa tính được với 4 byte kiểm tra trong Binary File ta đã thêm trước đó. Nếu kết quả trả về bằng nhau thì chứng tỏ dữ liệu tải xuống không bị lỗi.
Cách 2: Tính CRC luôn cả 4 byte kiểm tra cuối cùng trong file .Nếu kết quả bằng 0 thì chứng tỏ dữ liệu đã được toàn vẹn trong lúc truyền tải từ Sever về đến MCU.

Ví dụ chúng ta chỉ cần truyền vào địa chỉ bắt đầu nơi muốn thực hiện CRC trong bộ nhớ FLASH và độ dài của Firmware.  

4. Kết luận

Mình đã thực hiện quá trình FOTA với 2 loại tệp tin chứa Firmware định dạng Intel HEX và định dạng BIN như ở trên đã rút ra một số kết luận như sau:

Có thể kết luận rằng thực hiện quá trình FOTA với Binary File sẽ tối ưu hơn cho nền tảng cập nhập chương trình từ xa.

 

Vậy qua bài viết này mình đã cung cấp 2 cách để cập nhật chương trình từ xa, cách bạn có thể cập nhật bằng file định dạng Intel HEX hoặc file định dạng BIN. Hi vọng sau các bài viết này, các bạn có thể hiểu thêm về Firmware Over The Air, sau đó có thể tối ưu và phát triển tiếp các mô hình khác phù hợp với các ứng dụng của các bạn.

Theo dõi thêm:
– Cơ bản về cấu trúc và tính năng Vi xử lý ARM Cortex – Mx. 
– Phân biệt các khái niệm Processor Core, Processor và Microcontroller trong Hệ thống nhúng
– Tổng hợp các bài hướng dẫn Lập trình vi điều khiển STM32F1
– Tổng hợp hướng dẫn Lập trình vi điều khiển STM32F4

 

Chúc các bạn thành công!

Nhóm TAPIT ARM R&D