API GUIDE / MSCALER / OVERVIEW
G32S10 MSCALER API 概述
模块概述:本文覆盖 MSCALER 的三层接口:
1. 文档范围
本文覆盖 MSCALER 的三层接口:
mscaler_regs.h:MSCALER 寄存器结构体、基地址和位域宏ll_mscaler.h:寄存器级static inline读写接口hal_mscaler.h/hal_mscaler.c:面向上层的静态配置、逐帧启动与 JPEG 联动接口
本文描述当前代码实际实现的配置、校验、cache 维护和中断完成路径。图像 buffer 的分配和生命周期由调用方负责。
2. 分层关系
callback_register / start / get_result
mscaler_regs.h定义寄存器布局、位域 mask 和寄存器访问实例。LL 仅进行寄存器读写,不保存任务状态,也不做完整参数校验。
HAL 计算 stride、缩放步进和算法参数,校验地址,维护 cache,并读取、清除和分发 frame-end 中断。
应用负责注册 SoC IRQ、提供回调和等待机制,并提供满足格式、容量和 8-byte 对齐要求的输入/输出 buffer;HAL 不分配或搬运 buffer。
3. 典型用法
以下示例均只展示 HAL 层调用。应用负责 register_scaler_irq()、wait_for_frame_done() 和帧缓冲区的获取;这些函数内部应分别连接 SoC IRQ、等待已注册 callback 发出的完成通知,以及提供满足格式、容量和 8-byte 对齐要求的 buffer。
3.1 单帧
单帧流程只处理一个源 buffer:初始化 HAL,配置静态参数,启动一次,等待 frame-end,取回结果后反初始化。
#include "hal_mscaler.h"
#define SRC_WIDTH 640U
#define SRC_HEIGHT 480U
#define DST_WIDTH 320U
#define DST_HEIGHT 240U
#define SRC_Y_SIZE (SRC_WIDTH * SRC_HEIGHT)
#define DST_Y_SIZE (DST_WIDTH * DST_HEIGHT)
error_code_t run_mscaler_nv12_frame(uint8_t *src, uint8_t *dst)
{
hal_mscaler_input_param_t param;
hal_mscaler_config_t config;
error_code_t ret;
hal_mscaler_struct_init(¶m, &config);
param.out_fmt = HAL_MSCALER_FORMAT_NV12;
param.src_width = SRC_WIDTH;
param.src_height = SRC_HEIGHT;
param.dst_width = DST_WIDTH;
param.dst_height = DST_HEIGHT;
param.src_y_addr = src;
param.src_uv_addr = &src[SRC_Y_SIZE];
param.dst_y_addr = dst;
param.dst_uv_addr = &dst[DST_Y_SIZE];
config.mstj.is_enabled = false;
ret = hal_mscaler_init();
if (ret == IM_OK) {
ret = hal_mscaler_callback_register(frame_done_callback);
}
if (ret == IM_OK) {
ret = register_scaler_irq();
}
if (ret == IM_OK) {
ret = hal_mscaler_set_configure(¶m, &config);
}
if (ret == IM_OK) {
ret = hal_mscaler_start(¶m);
}
if (ret == IM_OK) {
ret = wait_for_frame_done(config.timeout_ms);
}
if (ret == IM_OK) {
ret = hal_mscaler_get_result(¶m);
}
unregister_scaler_irq();
(void)hal_mscaler_callback_register(NULL);
hal_mscaler_deinit();
return ret;
}3.2 连续帧
连续帧流程只配置一次尺寸、格式、缩放算法和 JPEG 联动参数;每次循环更换当前帧的源/目标地址,再调用一次 hal_mscaler_start()。
#include "hal_mscaler.h"
#define SRC_WIDTH 640U
#define SRC_HEIGHT 480U
#define DST_WIDTH 320U
#define DST_HEIGHT 240U
#define SRC_Y_SIZE (SRC_WIDTH * SRC_HEIGHT)
#define DST_Y_SIZE (DST_WIDTH * DST_HEIGHT)
error_code_t run_mscaler_nv12_stream(void)
{
hal_mscaler_input_param_t param;
hal_mscaler_config_t config;
uint8_t *src;
uint8_t *dst;
uint32_t frame_index;
error_code_t ret;
hal_mscaler_struct_init(¶m, &config);
param.out_fmt = HAL_MSCALER_FORMAT_NV12;
param.src_width = SRC_WIDTH;
param.src_height = SRC_HEIGHT;
param.dst_width = DST_WIDTH;
param.dst_height = DST_HEIGHT;
config.mstj.is_enabled = false;
ret = hal_mscaler_init();
if (ret != IM_OK) {
return ret;
}
ret = hal_mscaler_callback_register(frame_done_callback);
if (ret == IM_OK) {
ret = register_scaler_irq();
}
if (ret == IM_OK) {
/* Static geometry and algorithm configuration is done once. */
ret = hal_mscaler_set_configure(¶m, &config);
}
for (frame_index = 0U; (ret == IM_OK) && (frame_index < FRAME_COUNT);
frame_index++) {
ret = get_next_frame_buffers(frame_index, &src, &dst);
if (ret != IM_OK) {
break;
}
/* Only the frame addresses change between starts. */
param.src_y_addr = src;
param.src_uv_addr = &src[SRC_Y_SIZE];
param.dst_y_addr = dst;
param.dst_uv_addr = &dst[DST_Y_SIZE];
ret = hal_mscaler_start(¶m);
if (ret == IM_OK) {
ret = wait_for_frame_done(config.timeout_ms);
}
if (ret == IM_OK) {
ret = hal_mscaler_get_result(¶m);
}
}
unregister_scaler_irq();
(void)hal_mscaler_callback_register(NULL);
hal_mscaler_deinit();
return ret;
}启用 JPEG 联动时,将 config.mstj.is_enabled 设为 true,并按图像格式和 JPEG 消费时序填写 out_buff_num 与 out_bline_num。
4. 错误码速查
| 错误码 | 常见原因 |
|---|---|
IM_OK | 初始化、启动、中断驱动的帧完成等待或结果 cache 同步成功。 |
IM_ERR_INVALID_PARAM | 尺寸不在 HAL 范围内、格式非法、缩放步进超过 0x7ffff、Y 地址或显式/推导后的 UV 地址无效或未 8-byte 对齐、帧参数与静态配置不匹配,或 out_bline_num > dst_height。 |
IM_ERR_NOT_READY | HAL 未初始化、当前任务未配置或尚未完成就取结果。 |
IM_ERR_BUSY | 配置仍被上一帧占用,或者调用方在上一帧结束前再次启动。 |
IM_ERR_TIMEOUT | 应用等待 frame-end 超过配置的超时时间。 |
5. 注意事项
hal_mscaler_init()不会配置图像参数。先调用一次hal_mscaler_set_configure()写入尺寸、格式和算法;每帧仅调用hal_mscaler_start()更新地址、stride 和启动寄存器。hal_mscaler_start()会拒绝与静态配置不一致的宽高或格式。需要改变这些参数时,先执行hal_mscaler_deinit(),再初始化和配置。HAL 不校验调用方提供的 buffer 总容量。调用方必须按 HAL 实际 stride 和图像高度计算足够空间,尤其要考虑 8-byte stride 对齐。
NV12/YUV420 的 UV 地址可以显式配置,也可以留空由 HAL 按 Y 平面大小推导;无论哪种方式,最终地址都必须有效且 8-byte 对齐。YUV422/ONLY_Y 只需要配置 Y 地址和 stride。
当前 HAL 的
out_fmt同时用于输入和输出格式,未提供颜色空间或像素格式转换。当前 HAL 对 YUYV 的源、目标 stride 都乘以
2。使用 YUYV 时应结合 packed buffer 布局和硬件要求审查该配置。INT_COMMON_0_MASK的 LL 写接口命名为 mask,但 HAL 默认不写该寄存器;HAL 在 IRQ handler 中读取并清除 frame-end 状态。