Bộ nhớ chương trình của một thiết bị IoT khi tích hợp tính năng cập nhật chương trình từ xa (FOTA) cần được thiết kế một các hợp lý để lưu trữ cá thành phần như Bootloader, Chương trình OTA, Chương trình ứng dụng và các biến liên kết. Bài viết này sẽ trình bày cơ bản về một số cấu trúc phân bố chương trình trong bộ nhớ, phân tích ưu nhược điểm của các cấu trúc để các bạn có thể lựa chọn phù hợp cho ứng dụng của các bạn.
Thông thường, khi không triển khai tính năng FOTA thì một chương trình ứng dụng sẽ được lưu ở ngay địa chỉ bắt đầu của khối bộ nhớ chính của bộ nhớ Flash. Khi khởi động, vi điều khiển sẽ thực thi lệnh được lưu từ vị trí này.
Hình 1. Cấu trúc chương trình trong bộ nhớ
Để có thêm thêm tính năng FOTA cho thiết bị thì khối bộ nhớ chính của vi điều khiển sẽ được chia thành nhiều vùng khác nhau để lưu trữ các chương trình như Bootloader tự phát triển; Chương trình OTA, Chương trình ứng dụng và Các biến liên kết. Trong đó:
- Bootloader tự phát triển sẽ nằm ở vị trí đầu tiên của bộ nhớ chương trình, mỗi khi vi điều khiển khởi động, bootloader sẽ được thực thi, thông qua các biến liên kết Bootloader sẽ quyết định lựa chọn thực thi Chương trình OTA hay Chương trình ứng dụng cho lần khởi động này.
- Các biến liên kết chứa thông tin chương trình cần được thực thi, để bootloader có thể biết trong lần khởi động tiếp theo, nó sẽ quyết định lựa chọn thực thi chương trình nào, các biến liên kết cũng chứa thông tin phiên bản chương trình hiện tại để trong quá trình hoạt động, chương trình ứng dụng có thể so sánh với phiên bản trên server, từ đó biết được có phiên bản mới hay không để thực hiện cập nhật.
- Chương trình OTA có nhiệm vụ chính là thực hiện tải tập tin chương trình ứng dụng từ máy chủ quản lý tập tin về và thực hiện thay thế chương trình ứng dụng. Sau đó thay đổi giá trị các biến liên kết và khởi động lại vi điều khiển.
- Chương trình ứng dụng là chương trình thực hiện các chức năng chính của thiết bị nhúng. Trong chương trình này có tích hợp thêm hàm để kiểm tra phiên bản chương trình trên máy chủ quản lý tập tin. Nếu có phiên bản mới, hàm này sẽ thực hiện thay đổi giá trị các biến liên kết và khởi động lại vi điều khiển.
[HỌC ONLINE TẠI TAPIT: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]
Tùy vào tài nguyên phần cứng và yêu cầu phát triển mà các vùng trên có thể được bố trí theo những cách khác nhau trong bộ nhớ:
Cách 1: Sơ đồ bố trí như hình 2
Mô tả quá trình hoạt động của thiết bị như sau:
- Khi chương trình ứng dụng phát hiện có phiên bản mới trên máy chủ quản lý tập tin. Nếu không có phiên bản mới, chương trình ứng dụng tiếp tục thực hiện bình thường. Nếu có phiên bản mới, chương trình ứng dụng sẽ thay đổi giá trị biến liên kết và gọi lệnh khởi động lại vi điều khiển.
- Bootloader thực thi và kiểm tra biến liên kết, sau đó nhảy tới chương trình OTA.
- Chương trình OTA để thực hiện cập nhật chương trình ứng dụng, quá trình cập nhật hoàn thành, chương trình OTA sẽ thay đổi giá trị biến liên kết và và khởi động lại vi điều khiển.
- Chương trình Bootloader thực thi, kiểm tra biến liên kết và nhảy đến chương trình ứng dụng mới.
Nhận xét: Với cách phân chia sử dụng bộ nhớ chương trình như trên, giả sử thiết bị mất kết nối Internet ngay trong lúc thực thi chương trình OTA thì thiết bị phải chờ đến khi có Internet lại để thực hiện lại quá trình OTA chứ không thể quay lại chương trình ứng dụng được, vì vùng nhớ chương trình ứng dụng đã được xóa trước khi ghi vào chương trình mới. Hoặc nếu chương trình ứng dụng mới có tồn tại lỗi ở hàm kiểm tra phiên bản chương trình trên máy chủ quản lý tập tin thì thiết bị không thể cập nhật thêm phiên bản mới nữa.
Từ cách bố trí tên, chúng ta cũng có thể tích hợp chức năng của chương trình OTA vào chương trình Bootloader, mỗi khi vi điều khiển khởi động, đều kiểm tra phiên bản mới trên server và thực hiện cập nhật nếu có trước khi nhảy qua thực thi chương trình ứng dụng.
Hình 3. Cấu trúc chương trình trong bộ nhớ khi thêm tính năng OTA – C1B
Cách 2: Sơ đồ bố trí như hình 4
Hình 4. Cấu trúc chương trình trong bộ nhớ khi thêm tính năng OTA – C2A
Với cách phân chia sử dụng bộ nhớ này thì có hai phân vùng dành cho chương trình ứng dụng, nghĩa là trong vi điều khiển tồn tại hai phiên bản chương trình ứng dụng khác nhau. Người phát triển có thể thiết kế một phân vùng (A/B) dành cho phiên bản xuất xưởng của ứng dụng và một phân vùng còn lại (B/A) để chạy chương trình chính và các bản cập nhật. Hoặc người dùng cũng có thể luân phiên cập nhật chương trình cho các vị trí A/B để thiết bị luôn duy trì hai phiên bản chương trình mới nhất. Một ưu điểm hay của cách này nữa là luôn có một chương trình ứng dụng dự phòng trong các tình huống: Mất Internet trong quá trình cập nhật chương trình hoặc bảng cập nhật mới tồn tại lỗi làm chương trình không hoạt động được. Tuy nhiên, cách phân chia này cần gấp đôi không gian bộ nhớ cho chương trình ứng dụng.
Hình 5. Quá trình hoạt động tương ứng với bố trí bộ nhớ C2A
Từ cách bố trí trên chúng ta cũng có thể tích hợp phần chức năng OTA vào Bootloader như đề cập ở cách một hoặc chúng ta cũng có thể tích hợp phần OTA vào chương trình ứng dụng như hình 6, tuy nhiên, các bố trí này làm tăng gấp đôi dung lượng cho phần chức năng OTA vì nó tồn tại trong cả hai chương trình ứng dụng:
Qua bài viết này, mình đã chia sẻ với các bạn về cấu trúc chương trình trong bộ nhớ khi triển khai thêm tính năng cập nhật chương trình từ xa. Hi vọng bài viết có thể giúp các bạn hiểu rõ hơn về tính năng nay. Từ đó, tùy vào các ứng dụng và nhu cầu khác nhau, các bạn có thể lựa chọn các cấu trúc phù hợp hoặc có thể phát triển hoàn thiện thêm.
Chúc các bạn thành công!
Thuong Nguyen