Trong quy trình phát triển hệ thống nhúng, sau khi biên dịch mã nguồn (C/Assembly), chúng ta cần một định dạng tệp trung gian để chuyển đổi mã máy vào bộ nhớ Flash của vi điều khiển. Bên cạnh Intel HEX, Motorola S-record (SREC) là một trong những định dạng phổ biến nhất. Bài viết hôm nay sẽ giúp các bạn làm chủ cấu trúc tệp SREC và cách xử lý chúng trong lập trình chuyên sâu.
🎯 Mục tiêu học tập
- Hiểu rõ lịch sử và ứng dụng của định dạng SREC.
- Phân tích chi tiết cấu trúc một bản ghi (Record) chuẩn Motorola.
- Phân biệt các loại bản ghi từ S0 đến S9.
- Nắm vững thuật toán tính Checksum để kiểm tra tính toàn vẹn dữ liệu.
- Xây dựng tư duy lập trình bộ phân giải (Parser) tệp SREC.
1. Tổng quan về định dạng Motorola S-record (SREC)
a) Lịch sử và Mục đích
Được Motorola tạo ra vào giữa những năm 1970 cho bộ xử lý 6800, S-record truyền tải thông tin nhị phân dưới dạng văn bản ASCII (Hexadecimal). Điều này giúp dữ liệu có thể dễ dàng được truyền qua các cổng nối tiếp (Serial) hoặc chỉnh sửa bằng các trình soạn thảo văn bản đơn giản mà không làm hỏng cấu trúc nhị phân.
Định dạng này còn được gọi với các tên khác như S19, S28, S37 tùy thuộc vào độ dài địa chỉ mà nó hỗ trợ.
b) So sánh với các định dạng khác
- Intel HEX: Thường dùng cho các dòng vi điều khiển của Intel hoặc 8051.
- Binary (.bin): Chứa dữ liệu thô, không có thông tin địa chỉ hoặc kiểm tra lỗi, khó đọc trực tiếp bằng mắt người.
- SREC: Linh hoạt hơn vì hỗ trợ địa chỉ lên đến 32-bit và tích hợp sẵn thông tin tiêu đề (Header) cũng như tổng kiểm tra (Checksum) cực kỳ chặt chẽ.
2. Cấu trúc chi tiết một bản ghi SREC
Một tệp SREC bao gồm nhiều dòng văn bản, mỗi dòng là một “Bản ghi” (Record). Cấu trúc của mỗi bản ghi tuân theo quy tắc nghiêm ngặt sau:
| S |
Type |
Byte Count |
Address |
Data |
Checksum |
| 1 ký tự |
1 ký tự |
2 ký tự Hex |
4/6/8 ký tự Hex |
2n ký tự Hex |
2 ký tự Hex |
- Bắt đầu (S): Luôn là chữ ‘S’ (ASCII 0x53).
- Loại (Type): Một chữ số từ ‘0’ đến ‘9’, xác định ý nghĩa của bản ghi.
- Số byte (Byte Count): Cho biết tổng số byte (cặp ký tự Hex) của các trường Address + Data + Checksum phía sau.
- Địa chỉ (Address): Vị trí trong bộ nhớ sẽ lưu trữ dữ liệu. Độ dài phụ thuộc vào Type (16, 24 hoặc 32 bit).
- Dữ liệu (Data): Các byte dữ liệu mã máy. Thông thường là 16 hoặc 32 byte mỗi dòng để dễ đọc.
- Tổng kiểm tra (Checksum): Dùng để phát hiện lỗi truyền tin.
3. Các loại bản ghi phổ biến
Dưới đây là bảng phân loại các bản ghi S-record thường gặp nhất:
| Loại |
Mục đích |
Địa chỉ |
Mô tả |
| S0 |
Tiêu đề |
16-bit (0000) |
Chứa thông tin mô tả như tên tệp, phiên bản (dạng ASCII Hex). |
| S1 / S2 / S3 |
Dữ liệu |
16 / 24 / 32-bit |
Chứa mã máy thực tế. S3 thường dùng cho các dòng ARM 32-bit. |
| S5 / S6 |
Đếm bản ghi |
16 / 24-bit |
(Tùy chọn) Chứa tổng số lượng các bản ghi S1/S2/S3 đã xuất hiện. |
| S7 / S8 / S9 |
Kết thúc |
32 / 24 / 16-bit |
Đánh dấu kết thúc tệp và chỉ định địa chỉ bắt đầu thực thi chương trình. |
💡 Lưu ý về thứ tự: Một tệp chuẩn thường có cấu trúc: S0 -> (S1/S2/S3) -> S5 -> (S7/S8/S9).
4. Thuật toán tính Checksum
Để đảm bảo dòng dữ liệu không bị sai lệch, SREC sử dụng một cơ chế Checksum đơn giản nhưng hiệu quả:
- Cộng tất cả các byte trong các trường: Byte Count, Address và Data.
- Lấy byte thấp nhất của tổng đó (LSB).
- Lấy phần bù 1 của giá trị đó (Lấy 0xFF trừ đi giá trị LSB).
Công thức trong C: checksum = 0xFF - (sum & 0xFF);
Ví dụ minh họa:
Bản ghi: S1137AF00A0A0D0000000000000000000000000061
- Sum: 13 + 7A + F0 + 0A + 0D + 00 + … + 00 =
0x019E
- LSB:
0x9E
- Checksum: 0xFF – 0x9E = 0x61 (Khớp với ký tự cuối của bản ghi).
🚀 Bài tập về nhà: Xây dựng bộ Parser SREC
Hãy viết một chương trình bằng ngôn ngữ C thực hiện các yêu cầu sau:
- Đọc tệp tin định dạng
.srec.
- Kiểm tra lỗi từng dòng (Sai định dạng S, sai loại Type, sai Checksum…).
- Nếu phát hiện lỗi: In ra màn hình số dòng và chi tiết lỗi.
- Nếu tệp hợp lệ: Xuất dữ liệu ra tệp
Output.txt với định dạng: [Address] [Data] (cách nhau bởi khoảng trắng).
📝 Tóm tắt: Tệp SREC là phương thức giao tiếp quan trọng giữa phần mềm biên dịch và phần cứng. Nắm vững cấu trúc bản ghi và cách tính Checksum sẽ giúp bạn tự tin hơn trong việc xử lý các tác vụ nạp chương trình (Bootloader) hoặc gỡ lỗi hệ thống nhúng.
Gợi ý bài tiếp theo: Tối Ưu Hóa Mã Nguồn Với Preprocessor, Macro Và Thao Tác Bit.