API GUIDE / HASH / Middleware
G32S10 HASH Middleware 接口
Middleware 层接口:应用包含:
1. 构建配置与文件组织
1.1 文件职责
| 文件 | 说明 |
|---|---|
include/im_hash.h | 公开宏、类型、对象的可见定义和 7 个 API |
src/im_hash.c | 流式处理、padding、DMA 分段、IRQ、waiter 和恢复 |
Kconfig | HASH MID 编译选项 |
CMakeLists.txt | 在 CONFIG_MIDDLEWARE_HASH=y 时编译 MID |
example/main/main.c | SHA-256 one-shot 和 streaming known-answer 示例 |
应用包含:
#include "im_hash.h"
2. 资源模型与公开宏
2.1 公开宏
| 宏 | 当前值 | 说明 |
|---|---|---|
IM_HASH_DMA_BUFFER_ALIGN_BYTES | 4 | DMA staging buffer 起始地址对齐 |
IM_HASH_MAX_BLOCK_BYTES | 128 | 最大算法 block,对应 SHA-384/SHA-512 |
2.2 DMA staging buffer
im_hash_config_t.dma_buffer 由调用方持有,MID 不分配、不释放该缓冲区。
要求:
CPU 可访问、HASH DMA 可见。
起始地址按
IM_HASH_DMA_BUFFER_ALIGN_BYTES对齐。大小至少为一个算法 block。
大小为所选算法 block 的整数倍。
从成功的
im_hash_init()保持有效到im_hash_deinit()返回。
示例:
static uint8_t s_hash_dma_buffer[256U] __attribute__((aligned(IM_HASH_DMA_BUFFER_ALIGN_BYTES)));
2.3 中断所有权
im_hash_config_t.irq_id 必须等于 IRQ_HASH。MID 拥有该 IRQ,应用不得同时注册
自己的 HASH IRQ handler。
3. 公开类型
3.1 im_hash_t
typedef struct im_hash im_hash_t;
调用方持有的 HASH 设备对象。第一次 im_hash_init() 前必须零初始化,初始化后地址
保持不变。对象字段由 MID 管理,应用不得直接修改。
3.2 im_hash_state_t
typedef enum {
IM_HASH_STATE_RESET = 0,
IM_HASH_STATE_READY,
IM_HASH_STATE_ACTIVE,
IM_HASH_STATE_WAITING,
IM_HASH_STATE_TIMEOUT,
IM_HASH_STATE_ERROR,
} im_hash_state_t;| 状态 | 说明 |
|---|---|
RESET | 未初始化或已 deinit。 |
READY | 可以开始一条新 HASH 消息。 |
ACTIVE | 流式消息已开始,可以继续 update。 |
WAITING | 当前 block/segment 的 HASH DMA 正在等待 MRD 中断。 |
TIMEOUT | 正在执行超时恢复。 |
ERROR | 恢复失败,只允许 im_hash_deinit()。 |
类型公开仅因为 im_hash_t 使用调用方静态存储;MID 不提供状态查询 API。
4. HASH MID 设备生命周期
RESET → READY · config_struct_init → init 成功
READY → ACTIVE · im_hash_begin()
ACTIVE → WAITING · update() / final()
WAITING → ACTIVE · 硬件完成
ACTIVE / ERROR → READY · 完成 / abort 成功
READY → RESET · im_hash_deinit()
im_hash_digest() 等价于 begin + update + final;abort 失败进入 ERROR。
正常完成后回到 READY,可继续处理下一条消息。超时后 abort 成功也回到 READY; abort 失败进入 ERROR。
5. 接口规范
5.1 im_hash_config_struct_init()
void im_hash_config_struct_init(im_hash_config_t *config);
填充第 5.3 节所列默认值。传 NULL 无效果。
调用方在 init 前仍需设置:
config.dma_buffer = s_hash_dma_buffer; config.dma_buffer_size = sizeof(s_hash_dma_buffer);
5.2 im_hash_init()
error_code_t im_hash_init(im_hash_t *dev, const im_hash_config_t *config);
执行:
校验设备对象处于 RESET 且未占用。
校验 DMA mode、algorithm、staging buffer、大小、对齐和
IRQ_HASH。将 staging buffer 转为物理地址并保存配置快照。
初始化 HAL、内部 waiter 和 DMA 完成 callback。
注册并使能
IRQ_HASH。进入 READY。
关键返回码:
| 返回值 | 条件 |
|---|---|
IM_OK | 初始化成功。 |
IM_ERR_INVALID_PARAM | mode、DMA buffer、对齐、大小、算法或 IRQ 非法。 |
IM_ERR_BUSY | 设备对象已初始化或当前不可复用。 |
| 其它 | HAL/IRQ 初始化错误。 |
5.3 im_hash_begin()
error_code_t im_hash_begin(im_hash_t *dev);
开始一条流式 HASH 消息,清除原消息长度和 tail。此调用不传输数据,不生成 digest。
成功状态为 ACTIVE。若设备未初始化或不在 READY,返回 BUSY。
5.4 im_hash_update()
error_code_t im_hash_update(im_hash_t *dev, const uint8_t *data, size_t length);
追加原始消息字节。
| 参数 | 约束 |
|---|---|
data | length != 0 时必须非 NULL |
length | 可以是任意字节数,不要求 block 对齐 |
不满足一个算法 block 的数据保存在内部 tail。完整 block 会复制到 DMA staging buffer、执行 cache clean 并启动 HASH DMA。函数等待 MRD 完成后才返回。
每次 DMA segment 使用 MID 默认超时 1000 ms。流式 API 当前没有单独的超时参数。
成功返回时状态为 ACTIVE,可以继续 update。
5.5 im_hash_final()
error_code_t im_hash_final(im_hash_t *dev, uint8_t *digest, size_t digest_size);
结束当前消息并输出 digest。
digest_size 必须精确等于算法 digest 大小,不接受“至少”大小。
final 会:
追加
0x80和零 padding。写入原始消息 bit 长度。
提交一个或两个最终 block。
等待 MRD 完成。
从 HAL 读取 digest。
把 digest word 转换为标准字节序。
回到 READY。
5.6 im_hash_digest()
error_code_t im_hash_digest(im_hash_t *dev, const uint8_t *data, size_t length, uint8_t *digest, size_t digest_size, uint32_t timeout_ms);
同步封装 begin + update + final,适合一段连续内存。
timeout_ms 是每个内部 DMA segment 的等待上限;0 使用默认 1000 ms。它不是整条
消息的总超时。
5.7 im_hash_deinit()
error_code_t im_hash_deinit(im_hash_t *dev);
中止活动消息,关闭并释放 IRQ_HASH,清理 HAL callback/user data,反初始化 HAL。
全部清理成功时回到 RESET;任一清理步骤失败时状态进入 ERROR,函数返回该错误,
调用方不得继续开始新的 HASH 消息。调用方的 DMA staging buffer 不会被释放。
6. 错误处理与并发约束
6.1 常见错误码
| 错误码 | 典型原因 |
|---|---|
IM_ERR_INVALID_PARAM | 空指针、DMA 对齐/大小非法、CPU mode、错误 digest 大小 |
IM_ERR_NOT_READY | update/final 没有活动消息,或活动状态不允许继续 |
IM_ERR_BUSY | 已有操作进行中,或 begin 时设备未初始化、已占用或不在 READY |
IM_ERR_TIMEOUT | HASH DMA/MRD 等待超时 |
IM_ERR_HARDWARE | HAL 报告 HASH 硬件错误 |
6.2 上下文和并发
所有 API 必须在任务上下文调用。
不可从 IRQ 调用。
同一
im_hash_t同时只能执行一条 HASH 消息。init/deinit 不得与 update/final/digest 并发。
一个
IRQ_HASH只能由一个 MID 对象拥有。
7. 典型用法
7.1 流式更新
ret = im_hash_begin(&s_hash);
if (ret == IM_OK) {
ret = im_hash_update(&s_hash, part1, part1_size);
}
if (ret == IM_OK) {
ret = im_hash_update(&s_hash, part2, part2_size);
}
if (ret == IM_OK) {
ret = im_hash_final(&s_hash, digest, digest_size);
}各次 update 长度不需要按 block 对齐。