12.2. Bốn tầng¶
Thư viện protocol được xây dựng như một ngăn xếp bốn tầng, mỗi tầng giải quyết một vấn đề duy nhất và xây dựng trên tầng bên dưới. Phần còn lại của chương đi qua ngăn xếp từ dưới lên trên.
12.2.1. Transport¶
Ở dưới cùng là ống byte giữa cam và host. Thư viện protocol không quan tâm cái nào mang byte:
USB-CDC qua cổng USB mà cam được cắm vào. Tùy chọn mặc định và có băng thông cao nhất cho mọi cam.
UART qua một cặp chân GPIO trên cam được kết nối với một bộ chuyển đổi serial trên host. Hữu ích cho các triển khai headless khi cổng USB đang bận hoặc không thể truy cập vật lý.
Nhiệm vụ duy nhất của transport là "byte vào, byte ra, theo thứ tự". Mọi thứ phía trên tầng này đều giả định rằng transport giao byte theo thứ tự chúng được ghi, nhưng cho phép các byte bị hỏng hoặc liên kết bị ngắt hoàn toàn. Các đợt mất mát (một vài byte bị thiếu) và ngắt kết nối hoàn toàn (toàn bộ liên kết biến mất trong một thời gian, sau đó quay lại) đều được xử lý ở tầng cao hơn.
12.2.2. Đóng khung¶
Tầng tiếp theo áp đặt cấu trúc lên luồng byte. Mọi thông điệp đều trở thành một gói -- một header 10 byte theo sau là payload theo sau là một trailer 4 byte. Header mang:
Một từ đồng bộ 2 byte (
0xD5AA) cho phép bộ thu tìm lại đầu của gói sau khi mất đồng bộ.Một số thứ tự 1 byte được sử dụng bởi tầng reliability.
Một ID kênh 1 byte cho biết gói thuộc về luồng logic nào.
Một trường cờ 1 byte cho các bit ACK / NAK / fragment / event.
Một opcode 1 byte phân biệt các lệnh protocol, lệnh hệ thống, và lệnh kênh.
Độ dài payload 2 byte.
CRC 2 byte trên tám byte header trước.
Payload theo sau, sau đó là CRC 4 byte trên chính payload. Hai CRC phát hiện lỗi hỏng độc lập: một bit bị đảo trong header làm vô hiệu CRC header, và bộ thu có thể loại bỏ gói mà không cần đọc payload.
12.2.3. Reliability¶
Tầng reliability chuyển đổi "các gói có thể đến" thành "các gói đã đến". Nó theo dõi các số thứ tự trong header, yêu cầu phía kia gửi xác nhận cho mọi gói cần xác nhận, và retransmit khi không nhận được xác nhận trong thời gian chờ. Theo mặc định, thời gian chờ retransmit bắt đầu ở 500 ms và nhân đôi sau mỗi lần thử lại, với ba lần thử trước khi từ bỏ.
Mỗi hành vi đó có thể cấu hình trong lệnh gọi protocol.init(): ACK có thể tắt cho các luồng một chiều, xác thực CRC có thể bỏ qua trên các transport hoàn toàn sạch, và các tham số retransmit có thể điều chỉnh cho các liên kết chậm hoặc có độ trễ cao.
12.2.4. Kênh¶
Tầng trên cùng là những gì code ứng dụng thấy. Một kênh là một luồng logic có tên được xác định bởi ID kênh từ 0 đến 31. Tối đa 32 kênh có thể cùng tồn tại trên một transport; mỗi kênh độc lập với các kênh khác, được địa chỉ hóa bởi ID của nó trong header mỗi gói. Cam khởi động với bốn kênh tích hợp -- stdin, stdout, stream, và profile -- và code ứng dụng đăng ký thêm bằng cách gọi protocol.register() với một lớp Python.
Bốn tầng không trộn lẫn mối quan tâm. Đóng khung không biết về kênh; reliability không biết về nội dung gói; tầng kênh không biết byte đến như thế nào. Sự tách biệt đó là lý do tại sao một sự hoán đổi transport (USB sang UART, chẳng hạn) không lan rộng lên code kênh, và đó là điều làm cho phần còn lại của chương có thể đi qua từng tầng một.