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_Y0单 Y 平面图像
HAL_MSCALER_FORMAT_NV121Semi-planar NV12 图像
HAL_MSCALER_FORMAT_YUYV2Packed YUYV 图像

1.1.2 hal_mscaler_input_param_t

字段类型说明
out_fmthal_mscaler_format_t输入和输出图像格式;当前 HAL 不支持格式转换。
src_width / src_heightuint32_t源图宽高,范围分别为 8-1920 和 8-1440。
dst_width / dst_heightuint32_t目标图宽高,范围分别为 8-1920 和 8-1440。
src_y_addrvoid *源 Y 平面或 packed 图像起始地址,非空、8-byte 对齐。
src_uv_addrvoid *NV12/YUV420 源 UV 平面起始地址,可为 NULL;为 NULL 时 HAL 从源 Y 平面末尾推导,最终地址须 8-byte 对齐。
dst_y_addrvoid *目标 Y 平面或 packed 图像起始地址,非空、8-byte 对齐。
dst_uv_addrvoid *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_msuint32_t由应用用于 frame-end 等待的超时值;HAL 默认初始化为 800 ms。
mstjhal_mscaler_to_jpege_tHAL 实际保存的 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);

静态配置和逐帧启动的推荐调用顺序:

STEP 1  hal_mscaler_struct_init
↓
STEP 2  填写尺寸、格式与 param.mstj
↓
STEP 3  hal_mscaler_init
↓
STEP 4  hal_mscaler_callback_register + platform IRQ registration
↓
STEP 5  hal_mscaler_set_configure
↓
STEP 6  每一帧重复  填写源/目标缓冲地址
hal_mscaler_start
SoC IRQ → hal_mscaler_irq_handler
hal_mscaler_get_result
↓
STEP 7  hal_mscaler_deinit

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() 只建立模块运行状态和中断环境,并不配置某一帧的几何、算法参数或地址。其流程如下:

  1. 写 ALL_REG_RST 复位寄存器。

  2. 清除 HAL 内部 initialized/configured/started 状态并恢复默认 callback。

  3. 使能 frame-end 中断位并清除遗留的 frame-end 状态。

  4. 标记 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 源 strideALIGN_UP(src_width, 8)
Y/NV12 目标 strideALIGN_UP(dst_width, 8)
YUYV 源 strideALIGN_UP(src_width, 8) * 2
YUYV 目标 strideALIGN_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。该函数:

  1. 检查 HAL 已 initialized、已 configured,且当前帧处于 started 状态。

  2. 读取 INT_COMMON_0_INFO 的 frame-end 位;未置位时直接返回。

  3. 清除已报告的 frame-end 位。

  4. 清除 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 平面,仅 NV12clean确保 RDMA 读到 UV 数据。
hal_mscaler_start目标 Y 平面clean + invalidate避免 CPU 脏 cache line 覆盖 DMA 输出。
hal_mscaler_start目标 UV 平面,仅 NV12clean + 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。