AUTOSAR OS: Bảng Lập Lịch – Hạt Nhân Của Lập Lịch Kích Hoạt Theo Thời Gian

AUTOSAR OS: Bảng Lập Lịch – Hạt Nhân Của Lập Lịch Kích Hoạt Theo Thời Gian

Trong các hệ thống điều khiển điện tử ô tô, tính thời gian thực và độ xác định là tối quan trọng để đảm bảo an toàn chức năng. Bảng Lập Lịch (Schedule Table) đóng vai trò là cơ chế cốt lõi trong AUTOSAR OS, cho phép lập lịch kích hoạt theo thời gian. Cơ chế này kiểm soát chính xác việc kích hoạt tác vụ và thiết lập sự kiện thông qua một chuỗi thời gian được định nghĩa tĩnh, đặc biệt phù hợp với các ứng dụng yêu cầu đồng bộ hóa thời gian nghiêm ngặt như hệ thống điều khiển động cơ hoặc khung gầm. Bài viết này sẽ phân tích chi tiết cấu trúc, quản lý vòng đời, cơ chế đồng bộ hóa, và các điểm cần lưu ý khi triển khai Bảng Lập Lịch, giúp các nhà phát triển xây dựng hệ thống thời gian thực với tính xác định cao.

I. Cấu Trúc Bảng Lập Lịch: Định Nghĩa Tĩnh Chuỗi Thời Gian

1.1. Các Thành Phần Chính

Một Bảng Lập Lịch bao gồm một tập hợp có thứ tự các **Điểm Kích Hoạt (Expiry Points)**. Mỗi điểm kích hoạt định nghĩa một độ lệch thời gian so với thời điểm bắt đầu của bảng và các hành động cần được kích hoạt. Các thành phần chính bao gồm:

Thành phần Mô tả Tham số cấu hình
Bộ đếm điều khiển (Driving Counter) Đối tượng Counter cung cấp cơ sở thời gian Độ phân giải (ví dụ: 1ms), giá trị đếm tối đa
Thời lượng (Duration) Độ dài chu kỳ của bảng lập lịch (đơn vị Tick) OsScheduleTableDuration
Điểm kích hoạt (Expiry Point) Điểm kích hoạt theo thời gian, bao gồm độ lệch và hành động Offset (số Tick so với điểm bắt đầu), ActionList
Hành động (Action) Thao tác được kích hoạt tại điểm kích hoạt Kích hoạt tác vụ / Thiết lập sự kiện / Tăng bộ đếm

Ví dụ cấu hình (ARXML):

<OsScheduleTable>
  <ShortName>ST_HE_THONG_DIEU_KHIEN</ShortName>
  <OsScheduleTableCounter>BoDem_1ms</OsScheduleTableCounter>
  <OsScheduleTableDuration>100</OsScheduleTableDuration> <!-- Chu kỳ 100ms -->
  <OsScheduleTableExpiryPoints>
    <OsExpiryPoint>
      <OsExpiryPointOffset>0</OsExpiryPointOffset> <!-- Điểm bắt đầu -->
      <OsExpiryPointActions>
        <OsActivateTask>TacVu_KiemSoatDongCo</OsActivateTask>
      </OsExpiryPointActions>
    </OsExpiryPoint>
    <OsExpiryPoint>
      <OsExpiryPointOffset>50</OsExpiryPointOffset> <!-- Độ lệch 50ms -->
      <OsExpiryPointActions>
        <OsSetEvent>
          <OsSetEventTask>TacVu_XuLyCamBien</OsSetEventTask>
          <OsSetEventMask>SuKien_ThuThapDuLieu</OsSetEventMask>
        </OsSetEvent>
      </OsExpiryPointActions>
    </OsExpiryPoint>
  </OsScheduleTableExpiryPoints>
</OsScheduleTable>

1.2. Mối Quan Hệ Thời Gian Giữa Các Điểm Kích Hoạt

Các điểm kích hoạt trong bảng lập lịch phải tuân thủ các ràng buộc thời gian nghiêm ngặt:

  • Độ lệch ban đầu (Initial Offset): Khoảng thời gian giữa điểm kích hoạt đầu tiên và điểm bắt đầu của bảng, nằm trong khoảng [0, OsCounterMaxAllowedValue] hoặc [OsCounterMinCycle, OsCounterMaxAllowedValue].
  • Độ trễ (Delay): Khoảng thời gian giữa hai điểm kích hoạt liền kề, được tính bằng Y.Offset - X.Offset, phải lớn hơn hoặc bằng OsCounterMinCycle.
  • Độ trễ cuối cùng (Final Delay): Khoảng thời gian từ điểm kích hoạt cuối cùng đến khi bảng lập lịch kết thúc chu kỳ, được tính bằng Duration - FinalExpiryPoint.Offset.

Minh họa quan hệ thời gian:

Duration = 100ms
ExpiryPoint1: Offset = 10ms → Delay = 10ms (so với điểm khởi đầu)
ExpiryPoint2: Offset = 30ms → Delay = 20ms (so với ExpiryPoint1)
ExpiryPoint3: Offset = 70ms → Delay = 40ms (so với ExpiryPoint2)
FinalDelay = 100 - 70 = 30ms

1.3. Các Ràng Buộc Đối Với Điểm Kích Hoạt

Theo đặc tả AUTOSAR SWS OS, cấu hình điểm kích hoạt phải đáp ứng:

  1. Mỗi điểm kích hoạt phải chứa ít nhất một hành động (kích hoạt tác vụ hoặc thiết lập sự kiện) [SWS_OS_00201].
  2. Tất cả các giá trị Offset của điểm kích hoạt phải là duy nhất và được sắp xếp theo thứ tự tăng dần.
  3. Hiệu số Offset của bất kỳ hai điểm kích hoạt nào phải lớn hơn hoặc bằng OsCounterMinCycle [SWS_OS_00206].
  4. Offset tối đa phải nhỏ hơn Duration của bảng lập lịch [SWS_OS_00227].

II. Quản Lý Vòng Đời Bảng Lập Lịch: Khởi Động/Dừng/Đồng Bộ

2.1. Mô Hình Chuyển Đổi Trạng Thái

Bảng lập lịch có một máy trạng thái rõ ràng, chuyển đổi trạng thái thông qua các lời gọi API:

Trạng thái Mô tả Điều kiện kích hoạt
STOPPED Trạng thái ban đầu, không thực hiện điểm kích hoạt nào Hệ thống khởi động hoặc gọi DungBangLapLich()
RUNNING Hoạt động bình thường, kích hoạt điểm kích hoạt theo giá trị Counter Gọi KhoiDongBangLapLichTuyetDoi/TuongDoi()
SYNCHRONIZING Đang trong quá trình đồng bộ, điều chỉnh bộ đếm nội bộ Gọi DongBoBangLapLich()
PAUSED Tạm dừng thực hiện, giữ lại tiến trình hiện tại Gọi TamDungBangLapLich() (hỗ trợ tùy chọn)
WAITING Chờ tín hiệu đồng bộ Sau khi gọi KhoiDongBangLapLichDongBo() nhưng chưa đồng bộ

API chuyển đổi trạng thái:

// Khởi động tuyệt đối: Bảng được kích hoạt khi Counter đạt giá trị Start
StatusType KhoiDongBangLapLichTuyetDoi(LoaiBangLapLich idBangLapLich, LoaiTick giaTriBatDau);

// Khởi động tương đối: Bảng được kích hoạt sau Offset tính từ giá trị Counter hiện tại
StatusType KhoiDongBangLapLichTuongDoi(LoaiBangLapLich idBangLapLich, LoaiTick doLech);

// Dừng bảng lập lịch
StatusType DungBangLapLich(LoaiBangLapLich idBangLapLich);

// Tạm dừng bảng lập lịch
StatusType TamDungBangLapLich(LoaiBangLapLich idBangLapLich);

// Tiếp tục bảng lập lịch
StatusType TiepTucBangLapLich(LoaiBangLapLich idBangLapLich);

// Đồng bộ bảng lập lịch với một cơ sở thời gian bên ngoài
StatusType DongBoBangLapLich(LoaiBangLapLich idBangLapLich, LoaiTick giaTriDongBo);

2.2. So Sánh Các Chế Độ Khởi Động

Bảng lập lịch hỗ trợ hai phương thức khởi động, phù hợp với các kịch bản khác nhau:

Chế độ khởi động Đặc điểm Kịch bản ứng dụng
Khởi động tuyệt đối Tất cả các bảng lập lịch khởi động đồng thời khi Counter đạt giá trị Start đã định Đồng bộ nhiều ECU trong hệ thống phân tán
Khởi động tương đối Khởi động dựa trên độ lệch so với giá trị Counter hiện tại, tránh kích hoạt đồng thời Cân bằng tải hệ thống, phân tán các đỉnh CPU

Ví dụ về rủi ro khi khởi động tuyệt đối:
Ba bảng lập lịch đều sử dụng chế độ khởi động tuyệt đối (Start=0), dẫn đến tất cả các điểm kích hoạt được thực hiện đồng thời khi hệ thống khởi động, khiến tải CPU tăng vọt lên 90%. Giải pháp là sử dụng khởi động tương đối, thiết lập Offset = 10ms, 20ms, 30ms để phân tán thời điểm kích hoạt.

2.3. Cơ Chế Đồng Bộ

Để giải quyết sự sai lệch thời gian trong các hệ thống phân tán, bảng lập lịch cung cấp hai chiến lược đồng bộ:

2.3.1. Đồng Bộ Ngầm Định

  • Bộ đếm điều khiển cũng là bộ đếm đồng bộ, yêu cầu Duration = modun của bộ đếm điều khiển (OsCounterMaxAllowedValue + 1).
  • Chỉ hỗ trợ khởi động tuyệt đối, thường khởi động khi Counter=0: KhoiDongBangLapLichTuyetDoi(ST_ID, 0).
  • Thích hợp cho việc đồng bộ nhiều bảng lập lịch trong một ECU duy nhất.

2.3.2. Đồng Bộ Tường Minh

  • Sử dụng một nguồn đồng bộ bên ngoài độc lập với bộ đếm điều khiển, cần cấu hình:
    • OsScheduleTableSyncStrategy = EXPLICIT
    • OsScheduleTablePrecision: Dung sai đồng bộ (ví dụ: 2ms)
    • OsScheduleTableMaxShorten/Lengthen: Phạm vi điều chỉnh
  • Quy trình đồng bộ:
    // Bắt đầu chờ đồng bộ
    KhoiDongBangLapLichDongBo(idBangLapLich);
    // Cung cấp giá trị cơ sở đồng bộ
    DongBoBangLapLich(idBangLapLich, ThoiGianToanCau);
    
  • Thích hợp cho các kịch bản hợp tác nhiều ECU hoặc đồng bộ thời gian toàn cầu.

III. Kích Hoạt Sự Kiện Từ Bảng Lập Lịch: Hành Động và Cơ Chế Thực Hiện

3.1. Các Loại Hành Động Tại Điểm Kích Hoạt

Điểm kích hoạt của bảng lập lịch hỗ trợ nhiều loại hành động, có thể được cấu hình kết hợp:

3.1.1. Kích Hoạt Tác Vụ (ActivateTask)

Khởi động một tác vụ cụ thể, hỗ trợ kích hoạt nhiều tác vụ:

<OsExpiryPointActions>
  <OsActivateTask>TacVu_Mot</OsActivateTask>
  <OsActivateTask>TacVu_Hai</OsActivateTask>
</OsExpiryPointActions>

3.1.2. Thiết Lập Sự Kiện (SetEvent)

Gửi một mặt nạ sự kiện đến một tác vụ cụ thể:

<OsSetEvent>
  <OsSetEventTask>TacVu_XuLyCamBien</OsSetEventTask>
  <OsSetEventMask>0x03</OsSetEventMask> <!-- Thiết lập đồng thời hai sự kiện -->
</OsSetEvent>

3.2. Thứ Tự Thực Hiện và Ưu Tiên

  • Thứ tự thực hiện hành động: Trong cùng một điểm kích hoạt, tất cả các tác vụ được kích hoạt trước, sau đó mới xử lý các thiết lập sự kiện.
  • Quy tắc giành quyền của tác vụ: Tác vụ có độ ưu tiên cao hơn sẽ ngay lập tức giành quyền thực thi khi được kích hoạt, tạm dừng tác vụ có độ ưu tiên thấp hơn đang chạy.
  • Hợp nhất sự kiện: Khi nhiều sự kiện cho cùng một tác vụ được thiết lập tại cùng một điểm kích hoạt, chúng sẽ được hợp nhất bằng phép toán OR bitwise (|).

3.3. Chế Độ Chu Kỳ và Chế Độ Một Lần

Bảng lập lịch hỗ trợ hai chế độ hoạt động:

Chế độ Đặc điểm Tham số cấu hình
Chế độ một lần (Single-shot) Thực hiện một lần rồi tự động dừng OsScheduleTableCycle = SINGLE_SHOT
Chế độ chu kỳ (Repeating) Thực hiện lặp lại liên tục OsScheduleTableCycle = REPEATING

Lưu ý khi sử dụng chế độ chu kỳ:

  • FinalDelay phải lớn hơn hoặc bằng OsCounterMinCycle.
  • Mỗi chu kỳ sẽ tự động quay lại điểm bắt đầu sau khi kết thúc Duration.
  • Có thể chuyển đổi chế độ thông qua TiepTheoBangLapLich().

IV. Thực Hành Kỹ Thuật và Các Vấn Đề Thường Gặp

4.1. Danh Mục Kiểm Tra Cấu Hình

  1. Xác minh tham số thời gian:
    • Tất cả các Offset của điểm kích hoạt phải là duy nhất và theo thứ tự tăng dần.
    • Độ trễ (Delay) giữa các điểm kích hoạt phải lớn hơn hoặc bằng OsCounterMinCycle (ví dụ: 1ms).
    • Duration phải là bội số của Offset tối đa.
  2. Thiết kế cân bằng tải:
    • Tránh cấu hình nhiều tác vụ tiêu tốn nhiều CPU tại cùng một Offset.
    • Các tác vụ quan trọng nên được đặt tại các Offset có tải thấp hơn (ví dụ: 30ms, 70ms).
    • Sử dụng khởi động tương đối với Offset để phân tán thời điểm kích hoạt của nhiều bảng lập lịch.
  3. Lựa chọn chiến lược đồng bộ:
    • Các tác vụ hợp tác giữa nhiều ECU: Sử dụng khởi động tuyệt đối + đồng bộ cứng.
    • Nhiều bảng lập lịch trong một ECU: Sử dụng khởi động tương đối + đồng bộ mềm.

4.2. Vấn Đề Điển Hình và Giải Pháp

4.2.1. Điểm Kích Hoạt Không Được Thực Thi

  • Nguyên nhân: Độ phân giải của Counter không khớp với bảng lập lịch.
  • Giải pháp: Đảm bảo Counter của bảng lập lịch và đơn vị Offset của điểm kích hoạt nhất quán (ví dụ: đều là 1ms).

4.2.2. Đồng Bộ Thất Bại Gây Rung Động

  • Hiện tượng: Khoảng thời gian thực thi tác vụ sai lệch > 10ms.
  • Giải pháp: Tăng SyncTolerance hoặc áp dụng đồng bộ mềm.

4.2.3. Đỉnh Tải CPU

  • Hiện tượng: Tỷ lệ sử dụng CPU tăng đột ngột khi bảng lập lịch khởi động.
  • Giải pháp: Sử dụng khởi động tương đối với Offset để phân tán thời điểm kích hoạt của nhiều bảng lập lịch.

Ví dụ sai:

// SAI: Nhiều bảng lập lịch khởi động tuyệt đối đồng thời
KhoiDongBangLapLichTuyetDoi(bangLapLichA, 0);
KhoiDongBangLapLichTuyetDoi(bangLapLichB, 0); // Khởi động đồng thời với bangLapLichA, gây đỉnh CPU

Ví dụ đúng:

// ĐÚNG: Khởi động tương đối để phân tán thời gian
KhoiDongBangLapLichTuongDoi(bangLapLichA, 0);
KhoiDongBangLapLichTuongDoi(bangLapLichB, 20); // Khởi động trễ 20ms

4.3. Trường Hợp Hợp Tác Nhiều Bảng Lập Lịch

Một hệ thống ADAS cần xử lý đồng bộ dữ liệu từ nhiều cảm biến: camera (30Hz), radar (20Hz), và lidar (10Hz). Giải pháp:

// Cấu hình 3 bảng lập lịch, sử dụng khởi động tuyệt đối để đảm bảo pha thẳng hàng
// Chu kỳ bảng lập lịch: 1000ms (bội số chung nhỏ nhất)
KhoiDongBangLapLichTuyetDoi(BangLapLich_CamBienAnh, 0);      // Chu kỳ 33.33ms
KhoiDongBangLapLichTuyetDoi(BangLapLich_Radar, 0);       // Chu kỳ 50ms
KhoiDongBangLapLichTuyetDoi(BangLapLich_Lidar, 0);       // Chu kỳ 100ms

// Ví dụ cấu hình điểm kích hoạt (bảng lập lịch camera)
// Offset: 0, 33, 66, 100, 133, 166... (mỗi 33ms một điểm kích hoạt)

Các điểm quan trọng:

  • Sử dụng cùng một bộ đếm điều khiển.
  • Duration = 1000ms (bội số chung nhỏ nhất).
  • Đảm bảo căn chỉnh tại điểm 0 thông qua khởi động tuyệt đối.
  • Mỗi Offset của điểm kích hoạt phải là bội số của chu kỳ cảm biến tương ứng.

V. Bảng Lập Lịch và Alarm: So Sánh Ứng Dụng

Tiêu chí Bảng Lập Lịch (Schedule Table) Alarm
Độ phức tạp Hỗ trợ phối hợp nhiều tác vụ, nhiều điểm kích hoạt Điểm kích hoạt đơn lẻ
Độ chính xác thời gian Cao (hỗ trợ đồng bộ thời gian toàn cầu) Trung bình (dựa trên Counter)
Tính linh hoạt cấu hình Cấu hình tĩnh, không thể thay đổi động trong thời gian chạy Hỗ trợ cấu hình lại trong thời gian chạy
Kịch bản ứng dụng Phối hợp tác vụ định kỳ, đồng bộ phân tán Tác vụ hẹn giờ đơn giản, kích hoạt một lần
Chi phí hệ thống Cao hơn (cần duy trì trạng thái nhiều điểm kích hoạt) Thấp hơn (điểm kích hoạt đơn lẻ)
Khả năng đồng bộ Hỗ trợ đồng bộ cứng và đồng bộ mềm Không hỗ trợ

Gợi ý thiết kế:

  • Các tác vụ có liên kết chặt chẽ như điều khiển động cơ, ABS → Sử dụng Bảng Lập Lịch.
  • Các tác vụ độc lập như timeout nhận truyền thông, reset watchdog → Sử dụng Alarm.
  • Kịch bản phối hợp nhiều ECU → Ưu tiên Bảng Lập Lịch (hỗ trợ đồng bộ thời gian toàn cầu).

VI. Kinh Nghiệm Thực Tế và Các Sai Lầm Thường Gặp

6.1. Pha Khởi Động Tuyệt Đối Lệch Gây Ra Dữ Liệu Không Đồng Bộ Giữa Các ECU

Hiện tượng lỗi

Trong một hệ thống điều khiển dẫn động bốn bánh, ECU_Truoc và ECU_Sau cần trao đổi dữ liệu yêu cầu mô-men xoắn với chu kỳ 20ms. Trong thử nghiệm thực tế, việc trao đổi dữ liệu cho thấy độ trễ ngẫu nhiên từ 5 đến 15ms, dẫn đến dao động trong phân bổ mô-men xoắn.

Phân tích nguyên nhân

  1. Cả hai ECU đều sử dụng chế độ khởi động tuyệt đối cho bảng lập lịch:
    // ECU_Truoc
    KhoiDongBangLapLichTuyetDoi(BangLapLich_DanDongBonBanh, 0);
    
    // ECU_Sau
    KhoiDongBangLapLichTuyetDoi(BangLapLich_DanDongBonBanh, 0);
    
  2. Vấn đề là Bộ đếm 1ms của hai ECU không khởi động đồng thời:
    • OsOSStartHook() của ECU_Truoc bắt đầu thực thi sau 2.3ms kể từ khi hệ thống khởi động.
    • OsOSStartHook() của ECU_Sau bắt đầu thực thi sau 8.7ms kể từ khi hệ thống khởi động.
    • Có một độ lệch ban đầu 6.4ms giữa hai Bộ đếm.
  3. Do sử dụng khởi động tuyệt đối (Start=0), hai bảng lập lịch được kích hoạt khi Bộ đếm của riêng chúng về 0, dẫn đến pha không cố định.

Giải pháp

// Giải pháp 1: Sử dụng khởi động tương đối, căn chỉnh pha thủ công
// ECU_Truoc (nút chính)
KhoiDongBangLapLichTuyetDoi(BangLapLich_DanDongBonBanh, 0);

// ECU_Sau (nút phụ)
LoaiTick giaTriBoDemHienTai = LayGiaTriBoDem(BoDem_1ms);
LoaiTick doLechDenChuKyTiepTheo = (20 - giaTriBoDemHienTai % 20) % 20;
KhoiDongBangLapLichTuongDoi(BangLapLich_DanDongBonBanh, doLechDenChuKyTiepTheo);

// Giải pháp 2: Sử dụng đồng bộ tường minh (khuyên dùng cho kịch bản độ chính xác cao)
// Cấu hình chiến lược đồng bộ
OsScheduleTableSyncStrategy = EXPLICIT;
OsScheduleTablePrecision = 2; // Dung sai ±2ms

// Truyền thời gian toàn cầu qua FlexRay hoặc Ethernet
DongBoBangLapLich(BangLapLich_DanDongBonBanh, thoiGianToanCau);

Tóm tắt kinh nghiệm

  • Sai lầm của khởi động tuyệt đối: Nhiều ECU sử dụng cùng giá trị khởi động tuyệt đối không đảm bảo căn chỉnh pha.
  • Cửa sổ thời gian khởi động: Thời gian thực thi của OsOSStartHook() bị ảnh hưởng bởi quá trình khởi tạo phần cứng, tồn tại sự không chắc chắn.
  • Cơ sở thời gian bên ngoài: Hệ thống phân tán phải sử dụng đồng bộ tường minh hoặc cơ sở thời gian bên ngoài (ví dụ: thời gian toàn cầu FlexRay).

6.2. FinalDelay Không Đủ Dẫn Đến Lập Lịch Bất Thường

Hiện tượng lỗi

Trong một hệ thống điều khiển hộp số, tác vụ chuyển số (TacVu_ChuyenSo) được cấu hình với chu kỳ 100ms, nhưng đôi khi xảy ra lỗi trễ phản hồi chuyển số vượt quá 200ms.

Phân tích nguyên nhân

  1. Cấu hình bảng lập lịch:
    <OsScheduleTableDuration>100</OsScheduleTableDuration>
    <OsExpiryPoint>
      <OsExpiryPointOffset>99</OsExpiryPointOffset>
      <OsExpiryPointActions>
        <OsActivateTask>TacVu_ChuyenSo</OsActivateTask>
      </OsExpiryPointActions>
    </OsExpiryPoint>
    
  2. Vấn đề là OsCounterMinCycle = 2 (chu kỳ tối thiểu của Bộ đếm là 2 Tick).
  3. FinalDelay = Duration - MaxOffset = 100 - 99 = 1ms.
  4. Do FinalDelay < OsCounterMinCycle, vi phạm quy định AUTOSAR [SWS_OS_00227].
  5. Một số triển khai OS sẽ tự động bỏ qua điểm kích hoạt cuối cùng, dẫn đến TacVu_ChuyenSo đôi khi không được kích hoạt.

Giải pháp

<!-- Giải pháp 1: Điều chỉnh Offset -->
<OsExpiryPointOffset>98</OsExpiryPointOffset>
<!-- FinalDelay = 100 - 98 = 2ms ≥ OsCounterMinCycle ✓ -->

<!-- Giải pháp 2: Tăng Duration -->
<OsScheduleTableDuration>101</OsScheduleTableDuration>
<!-- FinalDelay = 101 - 99 = 2ms ≥ OsCounterMinCycle ✓ -->

<!-- Giải pháp 3: Sử dụng Offset=0 -->
<OsExpiryPointOffset>0</OsExpiryPointOffset>
<!-- FinalDelay = 100 - 0 = 100ms ≥ OsCounterMinCycle ✓ -->

Tóm tắt kinh nghiệm

  • Ràng buộc quy định: FinalDelay ≥ OsCounterMinCycle là một yêu cầu bắt buộc, vi phạm sẽ dẫn đến hành vi không xác định.
  • Kiểm tra công cụ: Công cụ cấu hình nên tự động kiểm tra ràng buộc này, nhưng không nên phụ thuộc hoàn toàn vào công cụ.
  • Giá trị biên: Các Offset gần giới hạn Duration nên được sử dụng cẩn thận, khuyến nghị Offset ≤ Duration * 0.8.

6.3. Sự Cố Hợp Nhất Mặt Nạ Sự Kiện Dẫn Đến Chức Năng Bất Thường

Hiện tượng lỗi

Trong một hệ thống ESP, TacVu_Phanh được kích hoạt thông qua bảng lập lịch, thiết lập hai sự kiện SuKien_TinhApLuc và SuKien_NhaVan. Trong thử nghiệm, khi hai sự kiện đáng lẽ phải được thiết lập đồng thời, đôi khi chỉ một trong số chúng có hiệu lực.

Phân tích nguyên nhân

  1. Mã cấu hình:
    <OsExpiryPoint>
      <OsExpiryPointOffset>10</OsExpiryPointOffset>
      <OsExpiryPointActions>
        <OsSetEvent>
          <OsSetEventTask>TacVu_Phanh</OsSetEventTask>
          <OsSetEventMask>SuKien_TinhApLuc</OsSetEventMask>
        </OsSetEvent>
        <OsSetEvent>
          <OsSetEventTask>TacVu_Phanh</OsSetEventTask>
          <OsSetEventMask>SuKien_NhaVan</OsSetEventMask>
        </OsSetEvent>
      </OsExpiryPointActions>
    </OsExpiryPoint>
    
  2. Một số triển khai OS có thể tồn tại điều kiện tranh chấp khi xử lý nhiều hành động SetEvent tại cùng một điểm kích hoạt.
  3. Vấn đề nghiêm trọng hơn là tác vụ sau khi xử lý sự kiện đầu tiên, có thể bị tác vụ ưu tiên cao hơn giành quyền, dẫn đến việc thiết lập sự kiện thứ hai bị vô hiệu.

Giải pháp

<!-- Giải pháp 1: Hợp nhất thành một SetEvent duy nhất (khuyên dùng) -->
<OsExpiryPointActions>
  <OsSetEvent>
    <OsSetEventTask>TacVu_Phanh</OsSetEventTask>
    <OsSetEventMask>0x03</OsSetEventMask> <!-- OR bitwise của hai sự kiện -->
  </OsSetEvent>
</OsExpiryPointActions>

<!-- Giải pháp 2: Sử dụng ActivateTask thay vì SetEvent -->
<OsExpiryPointActions>
  <OsActivateTask>TacVu_Phanh</OsActivateTask>
</OsExpiryPointActions>

Tóm tắt kinh nghiệm

  • Hợp nhất sự kiện: Nhiều sự kiện của cùng một tác vụ nên được hợp nhất trong một hành động SetEvent duy nhất, tránh gọi nhiều lần.
  • Tính nguyên tố (Atomicity): Sử dụng phép toán OR bitwise để hợp nhất mặt nạ sự kiện, đảm bảo tính nguyên tố.
  • Đơn giản hóa hành động: Nếu tác vụ chỉ phụ thuộc vào sự kiện để kích hoạt, có thể xem xét trực tiếp sử dụng ActivateTask.

6.4. Bảng Lập Lịch Khởi Động Lại Gây Ra Biến Động Thời Gian

Hiện tượng lỗi

Trong một hệ thống điều khiển động cơ, tác vụ điều khiển động cơ (TacVu_DieuKhienDongCo) với chu kỳ 10ms, sau khoảng 1 giờ hoạt động, đột nhiên xuất hiện biến động thời gian 5ms, dẫn đến dao động tốc độ động cơ.

Phân tích nguyên nhân

  1. Hệ thống cấu hình một cơ chế chẩn đoán, khi phát hiện lỗi nhỏ sẽ khởi động lại bảng lập lịch liên quan:
    if (kiemTraLoiHeThong()) {
      DungBangLapLich(BangLapLich_DongCo);
      // Thực hiện các thao tác khôi phục...
      KhoiDongBangLapLichTuongDoi(BangLapLich_DongCo, 0);
    }
    
  2. Vấn đề là có khoảng 5ms độ trễ giữa DungBangLapLich() và KhoiDongBangLapLichTuongDoi().
  3. Khi khởi động lại, bảng lập lịch bắt đầu tính thời gian từ giá trị Bộ đếm hiện tại, dẫn đến thời gian bị lệch 5ms.
  4. Do bảng lập lịch sử dụng khởi động tương đối, chuỗi điểm kích hoạt mới không còn thẳng hàng với chuỗi cũ.

Giải pháp

// Giải pháp 1: Ghi lại thời điểm khởi động, căn chỉnh pha (khuyên dùng)
static LoaiTick doLechDaLuu = 0;

void KhoiPhucBangLapLich() {
  LoaiTick giaTriBoDemHienTai = LayGiaTriBoDem(BoDem_1ms);
  DungBangLapLich(BangLapLich_DongCo);

  // Thực hiện các thao tác khôi phục...

  // Sử dụng Offset đã lưu, đảm bảo pha liên tục
  KhoiDongBangLapLichTuongDoi(BangLapLich_DongCo, doLechDaLuu);
}

// Lưu Offset khi khởi tạo
void KhoiTaoBangLapLich() {
  LoaiTick giaTriBoDemHienTai = LayGiaTriBoDem(BoDem_1ms);
  doLechDaLuu = (10 - giaTriBoDemHienTai % 10) % 10;
  KhoiDongBangLapLichTuongDoi(BangLapLich_DongCo, doLechDaLuu);
}

// Giải pháp 2: Sử dụng Pause/Resume thay vì Stop/Start
void KhoiPhucBangLapLich() {
  TamDungBangLapLich(BangLapLich_DongCo);
  // Thực hiện các thao tác khôi phục...
  TiepTucBangLapLich(BangLapLich_DongCo);
}

Tóm tắt kinh nghiệm

  • Tính liên tục thời gian: Khi khởi động lại bảng lập lịch phải xem xét vấn đề căn chỉnh pha.
  • Pause so với Stop: Nếu chỉ tạm dừng thực thi, sử dụng TamDungBangLapLich() thay vì DungBangLapLich().
  • Lưu trạng thái: Trạng thái của các bảng lập lịch quan trọng (Offset khởi động, điểm kích hoạt hiện tại, v.v.) nên được lưu trữ trong bộ nhớ không bay hơi.

Thẻ: AUTOSAR AUTOSAR OS Schedule Table Time-Triggered Real-time Operating System

Đăng vào ngày 13 tháng 11 lúc 16:01