#bootloader #protocols #command #response #proto #tockloader #tock-os

tockloader-proto

A #[no_std] implementation of the protocol used by tockloader and the TockOS bootloader

3个不稳定版本

使用旧的Rust 2015

0.2.1 2017年11月16日
0.1.1 2017年11月12日
0.1.0 2017年11月11日

#1535 in 嵌入式开发

MIT/Apache

95KB
2K SLoC

Tockloader协议

Build Status

实现了Tockloader协议。

TockOS应用程序通过tockloader加载。它使用特定协议与TockOS引导加载程序通信。此crate实现了该协议,以便您可以使用Rust编写兼容未来的tockloader引导加载程序!

用法

在您的嵌入式引导加载程序中,您需要一个类似于以下内容的循环

use tockloader_proto::{ResponseEncoder, CommandDecoder};

#[no_mangle]
pub extern "C" fn main() {
    let mut uart = uart::Uart::new(uart::UartId::Uart0, 115200, uart::NewlineMode::Binary);
    let mut decoder = CommandDecoder::new();
    loop {
        if let Ok(Some(ch)) = uart.getc_try() {
            let mut need_reset = false;
            let response = match decoder.receive(ch) {
                Ok(None) => None,
                Ok(Some(tockloader_proto::Command::Ping)) => Some(tockloader_proto::Response::Pong),
                Ok(Some(tockloader_proto::Command::Reset)) => {
                    need_reset = true;
                    None
                },
                Ok(Some(_)) => Some(tockloader_proto::Response::Unknown),
                Err(_) => Some(tockloader_proto::Response::InternalError),
            };
            if need_reset {
                decoder.reset();
            }
            if let Some(response) = response {
                let mut encoder = ResponseEncoder::new(&response).unwrap();
                while let Some(byte) = encoder.next() {
                    uart.putc(byte);
                }
            }
        }
    }
}

在CLI闪存工具(如tockloader)中使用此库是一个练习留给读者(提示:您想要ResponseDecoderCommandEncoder)。

有线协议

这些都是从TockOS文档中抄来的。

所有消息都是通过UART发送的,并由客户端发起,由引导加载程序响应。

帧格式

命令

                             0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Message (arbitrary length)  | Escape Char   | Command       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • Message:由各个命令指定的命令包。通过将所有0xFC替换为两个连续的0xFC进行转义。
  • Escape Character0xFC
  • Command:命令字节。

响应

 0                   1
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Escape Char   | Response      | Message (arbitrary length)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • Escape Character0xFC
  • Response:响应字节。
  • Message:由各个命令指定的响应包。通过将所有0xFC替换为两个连续的0xFC进行转义。

命令

PING

向引导加载程序发送ping。如果一切正常,它将响应pong。

命令
  • Command0x01
  • MessageNone
响应
  • Response0x11
  • MessageNone

INFO

从引导加载程序检索信息字符串。

命令
  • Command0x03
  • MessageNone
响应
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length        | String...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     192 bytes                                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • Response0x25
  • Length:信息字符串的长度。
  • String: 信息字符串的Length字节和192长度的零。

重置

在引导加载程序中重置内部缓冲区指针。这通常在每次命令之前调用。

命令
  • 命令: 0x05
  • MessageNone
响应

无。

擦除页面

擦除内部闪存的页面。

命令
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Address                                                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • 命令: 0x06
  • 地址: 要擦除的页面的地址。小端。
响应
  • 响应: 0x15
  • MessageNone

写入页面

写入内部闪存的页面。

命令
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Address                                                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             (512 bytes)                                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • 命令: 0x07
  • 地址: 要写入的页面的地址。小端。
  • 数据: 写入页面的512个数据字节。
响应
  • 响应: 0x15
  • MessageNone

读取范围

读取内部闪存的任意范围。

命令
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Address                                                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • 命令: 0x06
  • 地址: 要擦除的页面的地址。小端。
  • 长度: 要读取的字节数。
响应
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             (arbitrary length)                                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • 响应: 0x20
  • 数据: 从闪存读取的字节。

设置属性

在内部闪存的指定索引处设置一个属性。

命令
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Index         | Key
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                | Length        | Value
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             (arbitrary length)                                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • 命令: 0x13
  • 索引: 要设置的属性索引。0-15。
  • 密钥: 八字节密钥,零填充。
  • 长度: 值的长度。1-55。
  • : 存储在属性中的Length字节值。
响应
  • 响应: 0x15
  • MessageNone

获取属性

从内部闪存获取指定索引的属性。

命令
 0
 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
| Index         |
+-+-+-+-+-+-+-+-+
  • 命令: 0x13
  • 索引: 要获取的属性索引。0-15。
响应
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Key
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                                                |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length        | Value
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             (55 bytes)                                         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • 响应: 0x22
  • 密钥: 八字节密钥,零填充。
  • 长度: 值的长度。1-55。
  • : 55字节的可能值。

内部闪存CRC

获取内部闪存范围的CRC。

命令
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Address                                                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length                                                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • 命令: 0x13
  • 地址: 开始CRC计算的地址。小端。
  • 长度: 计算CRC的范围长度。
响应
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| CRC                                                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • 响应: 0x23
  • CRC: 计算的CRC。

更改波特率

为引导加载程序设置新的波特率。

命令
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SubCmd        | Baud Rate
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                |
+-+-+-+-+-+-+-+-+
  • 命令: 0x21
  • 子命令: 子命令。使用0x01来设置新的波特率。当发送子命令0x01时,响应将以旧波特率发送,但引导加载程序将在发送响应后切换到新波特率。为了确认一切正常,引导加载程序期望再次收到CHANGE_BAUD_RATE命令,这次使用子命令0x02。不要在这两个CHANGE_BAUD_RATE命令之间发送RESET命令。确保两个消息中发送相同的波特率。
  • 波特率: 要使用的新波特率。小端。
响应
  • 响应: 0x15
  • MessageNone

依赖关系

~115KB