3 个稳定版本
1.1.0 | 2023 年 8 月 26 日 |
---|---|
1.0.1 | 2023 年 8 月 22 日 |
1.0.0 | 2023 年 8 月 21 日 |
0.1.0 |
|
#345 in 嵌入式开发
每月 35 次下载
39KB
563 行
i.MX RT1060 设备配置数据 (DCD) 生成器
i.MX RT1050/1060 系列微控制器具有 ROM 启动加载程序。作为启动过程的一部分,它解释固件映像中的设备配置数据 (DCD) 部分,以执行有限的初始化和验证外设寄存器,例如设置外部存储器控制器,在执行固件映像中的任何 ARM 指令之前。
此 crate 定义
- DCD 命令的语义描述符。
- 将命令列表序列化为 DCD 二进制文件(字节数组)。
常见用例 / 工作流程
- 在固件 crate 的
build.rs
脚本中,定义 DCD 命令并将它们序列化到文件中(例如$OUT_DIR/dcd.bin
)。 - 在固件本身中,定义一个静态字节数组,用 DCD 二进制文件的内容初始化,可以将其链接到固件映像中。(无耻地宣传:static-include-bytes 有助于此步骤。)
DCD 究竟做什么?
固件映像中的 DCD 部分是一系列命令的序列化字节数组
-
写入:向地址写入值(1/2/4 字节)。
*address = value
—— 直接写入*address &= !value
—— 读取-修改-写入清除位*address |= value
—— 读取-修改-写入设置位
-
检查:从地址读取,直到值满足条件或尝试次数过多。
(*address & mask) == 0
—— 全部清除(*address & mask) == mask
—— 全部设置(*address & mask) != mask
--- 任意清除(*address & mask) != 0
--- 任意设置
-
NOP:忽略 —— 可能表现为短暂的延迟。
参考:i.MX RT1060 参考手册(版本 3),第 9.7.2 节。
以下为重要细节和注意事项,这些内容会影响对 DCD 的解释。
使用方法
use imxrt_dcd as dcd;
use imxrt_ral as ral; // feature = "imxrt1062"
// RECOMMENDED: using imxrt-ral and convenience macros
let commands_macro = vec![
dcd::write_reg!(ral::ccm_analog, CCM_ANALOG, PLL_ARM, @BYPASS, BYPASS_CLK_SRC: CLK1),
dcd::check_all_clear!(ral::ccm, CCM, CDHIPR, @PERIPH_CLK_SEL_BUSY, @PERIPH2_CLK_SEL_BUSY),
];
// equivalent direct construction
let commands_direct = vec![
dcd::Command::Write(dcd::Write {
width: dcd::Width::B4,
op: dcd::WriteOp::Write,
address: 0x400D_8000,
value: 0x0001_4000,
}),
dcd::Command::Check(dcd::Check {
width: dcd::Width::B4,
cond: dcd::CheckCond::AllClear,
address: 0x400F_C048,
mask: (1 << 3) | (1 << 5),
count: None,
}),
];
assert_eq!(commands_macro, commands_direct);
// `serialize` into an `std::io::Write`
let mut dcd_bytes = vec![];
let num_bytes_written = dcd::serialize(&mut dcd_bytes, &commands_macro).expect("IO error");
assert_eq!(num_bytes_written, 28);
assert_eq!(
&dcd_bytes,
&[
// DCD header
0xD2, 0, 28, 0x41,
// write
0xCC, 0, 12, 0x04, 0x40, 0x0D, 0x80, 0x00, 0x00, 0x01, 0x40, 0x00,
// check
0xCF, 0, 12, 0x04, 0x40, 0x0F, 0xC0, 0x48, 0x00, 0x00, 0x00, 0x28,
]
);
便捷宏
为了简化命令的构建,功能 "ral"
(默认开启)提供了便捷宏,这些宏旨在与imxrt-ral
中的寄存器定义一起使用。
这些宏具有以下共同语法:
macro!(ral::path::to::peripheral, INSTANCE, REGISTER, ...args)
其中
-
macro
可以是- 写入:
write_reg
/set_reg
/clear_reg
- 检查:
check_all_clear
/check_any_clear
/check_all_set
/check_any_set
- 写入:
-
INSTANCE
应为一个指向寄存器块的指针,例如对于ral::ccm
,这应该是CCM
。 -
每个
arg
可以是FIELD: value
=>(value << field::offset) & field::mask
- 与
ral-registers
相同的行为。 - 字段枚举/名称值可以直接在
value
表达式中使用。
- 与
@FIELD
=>FIELD::mask
- 读取为 "所有(字段的)
FIELD
" - 对于显式使用字段掩码的设置、清除和检查命令非常有用。
- 读取为 "所有(字段的)
- 任意表达式
- 可以直接引用寄存器的字段(例如
(0b110 << FIELD1::offset) | FIELD2::mask
)。
- 可以直接引用寄存器的字段(例如
然后所有参数都按位或在一起,作为命令的最终值/掩码。
此语法受到 imxrt-ral
中的 write_reg!
和其他友好的启发(重导出 ral-registers
),并针对 DCD 的限制进行了调整。
DCD 详细信息和注意事项
DCD 大小限制
DCD序列化格式与头部中的2字节长度字段4字节对齐。这允许整个DCD块(包括所有头部)的最大长度为65532字节。然而,特定芯片系列的启动ROM可能强制实施(更短)的大小限制。对于RT1060,这是1768字节。
该存储库仅强制执行64 KiB长度限制以保持二进制格式有效,但会返回序列化DCD的大小,以便用户可以添加更严格的检查。
写入命令压缩
具有相同位宽和操作(即写入/清除/设置)的多个连续写入命令可以合并(共享相同的命令头部),以节省每个额外命令4字节。
该存储库在序列化期间自动执行此压缩。这可能会帮助满足DCD大小限制。
有效的写入命令地址范围
特定芯片系列的启动ROM可能只允许写入命令到有限数量的地址范围。
例如,以下是从参考手册中为RT1060的有效地址范围(再次)
开始 | 结束(包含) | 描述 |
---|---|---|
0x400A_4000 |
0x400A_7FFF |
IOMUX控制SNVS GPR |
0x400A_8000 |
0x400A_BFFF |
IOMUX控制SNVS |
0x400A_C000 |
0x400A_FFFF |
IOMUX控制GPR |
0x401F_8000 |
0x401F_BFFF |
IOMUX控制 |
0x400D_8000 |
0x400D_BFFF |
CCM模拟 |
0x400F_C000 |
0x400F_FFFF |
CCM |
0x402F_0000 |
0x402F_3FFF |
SEMC |
将数据写入这些范围之外的任何位置将导致启动ROM立即放弃解释您剩余的DCD。
该存储库不强制执行任何地址范围限制。用户应提供针对目标芯片系列的有效写入地址。
检查命令轮询计数
检查命令可以指定以下之一
- 省略最大轮询计数:只要条件未满足,ROM将无限期地轮询。
- 最大轮询计数 == 0:根本不轮询——相当于NOP。
- 最大轮询计数 > 0:如果达到最大轮询计数,启动ROM将立即放弃解释您剩余的DCD。
请注意(通过我有限的实验),启动ROM似乎没有限制检查命令的地址范围。
技巧
命令组合
-
ral::modify_reg!(..., FIELD1: value1, FIELD2: value2)
可以使用以下DCD命令序列进行近似dcd::clear_reg!(..., @FIELD1, @FIELD2)
dcd::set_reg!(..., FIELD1:value1, FIELD2:value2)
- 注意:这可能会触发由两个读取-修改-写入周期引起的额外副作用。这是由于DCD中缺少临时变量的最小值。
-
ral::read_reg!(..., FIELD == value)
可以使用以下DCD命令序列进行近似dcd::check_all_set!(..., FIELD:value)
dcd::check_all_clear!(..., FIELD: !value)
- 注意:如果寄存器在这两次检查之间发生变化,则此方法不起作用。可以使用相同的2个命令检查同一寄存器中的多个字段。
依赖关系
~425KB