API GUIDE / MSCALER / HAL
G32S10 MSCALER HAL 接口
HAL 层接口:详见 code/include/drivers/g32s10/mscaler/hal_mscaler.h 和 code/drivers/g32s10/mscaler/hal_mscaler.c。
1. HAL MSCALER 接口
详见 code/include/drivers/g32s10/mscaler/hal_mscaler.h 和 code/drivers/g32s10/mscaler/hal_mscaler.c。
1.1 公开类型
1.1.1 hal_mscaler_format_t
| 值 | 寄存器值 | 说明 |
|---|---|---|
HAL_MSCALER_FORMAT_Y | 0 | 单 Y 平面图像 |
HAL_MSCALER_FORMAT_NV12 | 1 | Semi-planar NV12 图像 |
HAL_MSCALER_FORMAT_YUYV | 2 | Packed YUYV 图像 |
1.1.2 hal_mscaler_input_param_t
| 字段 | 类型 | 说明 |
|---|---|---|
out_fmt | hal_mscaler_format_t | 输入和输出图像格式;当前 HAL 不支持格式转换。 |
src_width / src_height | uint32_t | 源图宽高,范围分别为 8-1920 和 8-1440。 |
dst_width / dst_height | uint32_t | 目标图宽高,范围分别为 8-1920 和 8-1440。 |
src_y_addr | void * | 源 Y 平面或 packed 图像起始地址,非空、8-byte 对齐。 |
src_uv_addr | void * | NV12/YUV420 源 UV 平面起始地址,可为 NULL;为 NULL 时 HAL 从源 Y 平面末尾推导,最终地址须 8-byte 对齐。 |
dst_y_addr | void * | 目标 Y 平面或 packed 图像起始地址,非空、8-byte 对齐。 |
dst_uv_addr | void * | NV12/YUV420 目标 UV 平面起始地址,可为 NULL;为 NULL 时 HAL 从目标 Y 平面末尾推导,最终地址须 8-byte 对齐。 |
Y 和 YUYV 格式不使用 UV 地址。NV12/YUV420 格式可配置 Y 和 UV 地址;UV 地址为 NULL 时,HAL 使用紧随对应 Y 平面的地址。调用方必须保证源和目标 buffer 具有由尺寸、格式和 HAL 计算 stride 推导出的足够容量。
1.1.3 hal_mscaler_to_jpege_t
| 字段 | 类型 | 说明 |
|---|---|---|
out_buff_num |
uint32_t |
JPEG 联动输出缓冲行数配置;调用方通过 param.mstj 传入。 |
is_enabled |
bool |
true 为 MSCALER/JPEGE 联动;false 时 HAL 将 OUT_BUFF_NUM 设为目标图像高度。 |
1.1.4 hal_mscaler_config_t
| 字段 | 类型 | 说明 |
|---|---|---|
timeout_ms | uint32_t | 由应用用于 frame-end 等待的超时值;HAL 默认初始化为 800 ms。 |
mstj | hal_mscaler_to_jpege_t | HAL 实际保存的 JPEG 联动配置。 |
1.2 公开函数和调用顺序
void hal_mscaler_struct_init(hal_mscaler_input_param_t *param, hal_mscaler_config_t *config); void hal_mscaler_reset(void); error_code_t hal_mscaler_init(void); error_code_t hal_mscaler_callback_register(hal_mscaler_callback_t callback); void hal_mscaler_irq_handler(void); bool hal_mscaler_get_status(void); void hal_mscaler_deinit(void); error_code_t hal_mscaler_set_configure(const hal_mscaler_input_param_t *param, const hal_mscaler_config_t *config); error_code_t hal_mscaler_start(const hal_mscaler_input_param_t *param); error_code_t hal_mscaler_get_result(const hal_mscaler_input_param_t *param);
静态配置和逐帧启动的推荐调用顺序:
hal_mscaler_start
SoC IRQ → hal_mscaler_irq_handler
hal_mscaler_get_result
1.3 默认值
hal_mscaler_struct_init() 清零 param 和 frame,再设置以下默认值:
| 字段 | 默认值 |
|---|---|
param.mstj.out_buff_num |
32 |
其余字段均为零。因此 out_fmt、源/目标尺寸和 param.mstj.is_enabled 必须在
hal_mscaler_set_configure() 前由调用方填写;源/目标地址属于 frame,可在
每次 hal_mscaler_start() 前更新。
HAL 没有 frame-end 超时字段。直接使用 HAL 时,等待完成和超时策略由应用 实现;使用上层 MID 时,超时由 MID 会话管理。
1.4 初始化、复位与反初始化
hal_mscaler_init() 只建立模块运行状态和中断环境,并不配置某一帧的几何、算法参数或地址。其流程如下:
写
ALL_REG_RST复位寄存器。清除 HAL 内部 initialized/configured/started 状态并恢复默认 callback。
使能 frame-end 中断位并清除遗留的 frame-end 状态。
标记 HAL 已初始化。
hal_mscaler_reset() 依次请求 Tiziano stop 和 all-register reset。hal_mscaler_deinit() 调用该复位流程,并清除 HAL 内部状态。hal_mscaler_get_status() 仅返回模块级 initialized 标志。
1.5 静态配置和逐帧启动
error_code_t hal_mscaler_set_configure(const hal_mscaler_input_param_t *param);
error_code_t hal_mscaler_start(const hal_mscaler_frame_t *frame);
set_configure 只接受静态图像属性和 JPEG 联动配置,不使用 Y/UV buffer 地址;start 只处理当前帧的地址、stride、cache 和触发寄存器。
| 阶段 | HAL 接口 | 写入内容 | 多帧策略 |
|---|---|---|---|
| 静态配置 | hal_mscaler_set_configure() |
CH_WORK_EN、尺寸、格式、缩放步进、固定点使能、算法系数、JPEG 联动参数 |
尺寸、格式、算法和 JPEG 联动不变时只执行一次 |
| 当前帧启动 | hal_mscaler_start() |
DMAOUT/RDMA 地址和 stride、buffer cache、CTRL.SHD_CTRL、RDMA_ENABLE |
每一帧都执行一次,可更换 Y/UV buffer 地址 |
hal_mscaler_set_configure() 在调用方保证 HAL 已初始化且没有运行中的帧时使用。
它校验尺寸、格式和 out_buff_num,计算 stride、平面大小与缩放步进,写入
几何/格式/JPEG 联动寄存器,并生成 Cubic 与横纵 17-tap Lanczos 系数。
配置保存在 HAL 内部 context 中,但 RDMA 尚未启动。
hal_mscaler_start() 在调用方保证最近一次 hal_mscaler_set_configure() 已成功
时使用。它使用 context 中保存的尺寸、stride 和格式,校验当前帧 Y 地址;
NV12 时对显式 UV 地址进行校验,对 NULL UV 地址按对应 Y 平面大小推导后再
校验。随后写 RDMA/DMAOUT 地址和 stride,对输入平面 clean、对输出平面
clean+invalidate,清除历史 frame-end,提交 shadow 寄存器,最后使能 RDMA。
HAL 不检查传入 frame 与静态配置是否“匹配”,因为 frame 中只有地址。
地址校验失败时,hal_mscaler_start() 返回 IM_ERR_INVALID_PARAM 且不会启动
RDMA。静态配置成功但 hal_mscaler_start() 因当前帧地址无效而失败时,
静态配置仍保留,调用方可更换 buffer 后重试。
HAL 不等待 frame-end。应用必须在 frame-end 中断后调用
hal_mscaler_irq_handler(),在自己的等待对象上判断完成或超时,然后再调用
hal_mscaler_get_result()。发生超时后调用 hal_mscaler_deinit();只有它返回
IM_OK 后才可释放当前帧 buffer,随后重新初始化和配置。
1.6 几何、stride 和算法计算
HAL 使用以下计算规则:
| 项 | 当前实现 |
|---|---|
| 横向步进 | (16384 * src_width) / dst_width,结果必须 <= 0x7ffff |
| 纵向步进 | (16384 * src_height) / dst_height,结果必须 <= 0x7ffff |
| Y/NV12 源 stride | ALIGN_UP(src_width, 8) |
| Y/NV12 目标 stride | ALIGN_UP(dst_width, 8) |
| YUYV 源 stride | ALIGN_UP(src_width, 8) * 2 |
| YUYV 目标 stride | ALIGN_UP(dst_width, 8) * 2 |
| Y 平面大小 | stride * height |
| NV12 UV 平面大小 | stride * height / 2 |
HAL 根据 ratio_w = (16384 * dst_width) / src_width 和 ratio_h = (16384 * dst_height) / src_height 生成算法系数;两个 ratio 都会被限制到最大 27306。随后通过内部 LUT、归一化和 Cubic 参数计算得到 H-core/W-core 的 17-tap 系数与 CUB_W/CUB_WS 参数。上层不需要提供这些系数。
1.7 JPEG 联动行为
hal_mscaler_set_configure() 调用内部 JPEG 联动配置。实际写入 OUT_BUFF_NUM 和 OUT_BLINE_NUM 前有以下处理:
| 条件 | OUT_BUFF_NUM |
OUT_BLINE_NUM |
|---|---|---|
is_enabled == false |
强制设为 dst_height |
强制设为 dst_height |
is_enabled == true |
使用 param->mstj.out_buff_num |
由 HAL 按格式派生:JPEG MCU 行高(单 Y/YUYV 8、NV12 16) |
out_buff_num 按配置值原样写入、不按格式翻倍,要求不小于 16(NV12 不小于
32)且不超过 dst_height。即使 is_enabled == false,HAL 仍会校验这个
字段。out_bline_num 不对外开放配置:它必须等于该格式的 JPEG MCU 行高
(写小了 JPEGE 会 overflow,写大了 add 信号次数不够、JPEGE 帧不结束),
所以由 HAL 从 out_fmt 派生;走 im_msca_to_jpeg_* 联动链路时,JPEGE 侧的
OCM wrap 也由 MID 从 out_buff_num / 8 派生,调用方只需要填
out_buff_num。
1.8 中断分发和取结果
error_code_t hal_mscaler_callback_register(hal_mscaler_callback_t callback); void hal_mscaler_irq_handler(void); error_code_t hal_mscaler_get_result(const hal_mscaler_input_param_t *param);
hal_mscaler_callback_register() 必须在 hal_mscaler_init() 成功后、hal_mscaler_start() 前调用。传入 NULL 恢复无操作默认回调。
hal_mscaler_irq_handler() 由平台 IRQ 入口或应用 ISR 调用。HAL 不申请 SoC IRQ。该函数:
检查 HAL 已 initialized、已 configured,且当前帧处于 started 状态。
读取
INT_COMMON_0_INFO的 frame-end 位;未置位时直接返回。清除已报告的 frame-end 位。
清除 HAL 的 started 状态,随后在中断上下文调用已注册的 frame-end callback。
callback 不得阻塞或执行耗时操作。同步等待由应用自己的同步对象实现。
hal_mscaler_get_result() 不读取硬件输出长度,因为缩放后的结果大小由目标尺寸和格式预先确定。它校验 HAL 状态、静态图像参数兼容性以及 dst_y_addr 非空,然后对目标 Y 平面执行 cache invalidate;NV12 还会对显式或按 Y 平面大小推导出的 UV 平面执行 invalidate。
1.9 Cache 管理
| 阶段 | 地址 | 操作 | 目的 |
|---|---|---|---|
hal_mscaler_start | 源 Y 平面 | clean | 确保 RDMA 读到 CPU 写入的源数据。 |
hal_mscaler_start | 源 UV 平面,仅 NV12 | clean | 确保 RDMA 读到 UV 数据。 |
hal_mscaler_start | 目标 Y 平面 | clean + invalidate | 避免 CPU 脏 cache line 覆盖 DMA 输出。 |
hal_mscaler_start | 目标 UV 平面,仅 NV12 | clean + invalidate | 避免 CPU 脏 cache line 覆盖 DMA 输出。 |
hal_mscaler_get_result | 目标 Y/UV 平面 | invalidate | 让 CPU 读取 DMA 写回后的结果。 |
在 hal_mscaler_start() 返回至 hal_mscaler_get_result() 返回前,调用方不应修改源或目标 buffer。
1.10 线程安全与中断策略
MSCALER HAL 使用模块级静态状态和 context,不支持多实例并发或无锁多线程调用。多个任务共享 MSCALER 时,应在 HAL 调用外层串行化。
HAL 的中断分发路径为:
SoC IRQ entry -> hal_mscaler_irq_handler -> read INT_COMMON_0_INFO[0] -> write INT_COMMON_0_CLR[0] -> frame-end callback
HAL 不注册 CPU IRQ handler。应用负责申请 IRQ_SCALER、注册 HAL callback、调用 hal_mscaler_irq_handler(),并在任务上下文等待完成通知。
2. 典型用法
以下示例均只展示 HAL 层调用。应用负责 register_scaler_irq()、wait_for_frame_done() 和帧缓冲区的获取;这些函数内部应分别连接 SoC IRQ、等待已注册 callback 发出的完成通知,以及提供满足格式、容量和 8-byte 对齐要求的 buffer。