API GUIDE / JPEGE / HAL
G32S10 JPEGE HAL 接口
HAL 层接口:推荐调用顺序:
1. HAL JPEGE 接口
1.1 生命周期和基础流程
void hal_jpege_struct_init(hal_jpege_param_t *param, hal_jpege_config_t *config, hal_jpege_frame_t *frame); error_code_t hal_jpege_init(const hal_jpege_config_t *config); error_code_t hal_jpege_callback_register(hal_jpege_callback_t callback); error_code_t hal_jpege_sequence_configure(const hal_jpege_param_t *param, const hal_jpege_config_t *config); error_code_t hal_jpege_start_frame(const hal_jpege_frame_t *frame); void hal_jpege_irq_handler(void); error_code_t hal_jpege_get_result(hal_jpege_frame_t *frame); error_code_t hal_jpege_deinit(void); error_code_t hal_jpege_regs_dump(void);
推荐调用顺序:
1.2 默认值
hal_jpege_struct_init() 会清零 param/config/frame,然后设置以下默认值:
| 字段 | 默认值 |
|---|---|
param.pix_format | HAL_JPEGE_PIX_FMT_NV12 |
param.bayer_format | HAL_JPEGE_BAYER_FMT_RGGB |
param.qk_table | HAL_JPEGE_QK_TABLE_HIGH_COMPRESSION |
config.codec.qt_mode | HAL_JPEGE_QT_MODE_HARD |
config.codec.qt_table | HAL_JPEGE_QT_TABLE_1 |
config.wrap | 4 |
config.ar_outstanding | 1 |
config.awlen | 0 |
config.timeout_ms | 1000 |
config.reset_cycle | 10 |
config.hw_timeout.thrd | 0xffffffff |
width、height、src_addr、dst_addr、dst_buf_size 等外部关心字段仍需由调用方填写。
1.3 初始化和复位
error_code_t hal_jpege_reset(const hal_jpege_config_t *config); error_code_t hal_jpege_init(const hal_jpege_config_t *config); error_code_t hal_jpege_deinit(void);
hal_jpege_reset 内部流程:
校验
config != NULL和reset_cycle <= 15写
SW_RESET_CYCLE使能 sequence reset 覆盖 sequence registers 和 slave registers
触发
SW_SEQ_RESET轮询
RESET_FSM_DONE,超时返回IM_ERR_TIMEOUT
hal_jpege_init 内部流程:
保存 runtime config 到 HAL 内部 context
执行
hal_jpege_reset检查 systick 是否初始化
使能 JPEGE 硬件状态中断位并清 pending
配置 frame-end hold cycles
设置内部 initialized 状态
hal_jpege_deinit 会关闭所有中断、清 pending、执行 reset,并清除 HAL 内部 configured/initialized 状态。
1.4 序列配置
error_code_t hal_jpege_sequence_configure(const hal_jpege_param_t *param, const hal_jpege_config_t *config);
该函数用于配置一组编码序列的固定参数,包括图像尺寸、像素格式、stride、MCU 数、量化模式、restart marker 和 trigger/reset 模式。
参数校验:
| 参数 | 条件 |
|---|---|
param/config | 不能为 NULL |
width | 256-1920,且必须是 4 的倍数 |
height | 256-1440,且必须是 4 的倍数 |
pix_format | 必须为 NV12/YUV420、YUYV/YUV422、单 Y 或 Bayer 之一 |
bayer_format | 必须为 RGGB/BGGR/GBRG/GRBG 之一 |
config.codec.qt_mode | 必须为 SOFT 或 HARD |
config.codec.qt_table | 必须为 table preset 1 或 2 |
ar_outstanding | 1-16 |
awlen | 0-3 |
reset_cycle | 0-15 |
qp | 硬件 QP 模式下必须 0-98 |
qk_table | 软件表模式下必须为高/中/低压缩表组之一 |
wrap | JPEG_WRAP 寄存器值;NV12/YUV420 至少 4,YUYV/YUV422 和单 Y 至少 2,最大 0xff;Bayer 不配置 |
几何参数计算:
| 输入格式 | MCU 对齐宽 | MCU 对齐高 | stride |
|---|---|---|---|
HAL_JPEGE_PIX_FMT_Y | 8 | 8 | width |
HAL_JPEGE_PIX_FMT_NV12 | 16 | 16 | width |
HAL_JPEGE_PIX_FMT_YUYV | 16 | 8 | width * 2 |
HAL_JPEGE_PIX_FMT_BAYER | 16 | 16 | width |
wrap 直接对应 SPEC 中的 JPEG_WRAP 字段,单位是 OCM 中 ISP/JPEG 可用的 8 行像素空间数量。HAL 不把它当 AXI wrap 或总线属性使用,也不再对 NV12/YUV420 做隐式单位换算;调用方应直接填最终写入寄存器的值。
Trigger 归一化:
Bayer 输入不支持自动 start,若
start_auto=true,HAL 会在内部 context 中转为手动 start 并打印 warningBayer 输入不支持 ISP linkage,若
isp_en=true,HAL 会在内部 context 中关闭 ISP 并打印 warningBayer 输入无需配置
JPEG_WRAP,HAL 不会写WRAP寄存器isp_en=false时不支持自动 start,若start_auto=true,HAL 会转为手动 start 并打印 warning上述归一化只修改 HAL 内部 context,不回写用户传入的
config
量化表配置:
| 模式 | 配置动作 |
|---|---|
HAL_JPEGE_QT_MODE_HARD | 写 qt_base1/qt_base2 到 qt_base_tab[],再写 QP |
HAL_JPEGE_QT_MODE_SOFT | 写 qt_tab1/qt_tab2 到 qt_tab[],再写 QK_TAB_SEL |
内部寄存器配置顺序:
计算 stride、MCU 数、对齐尺寸和输入平面大小
写量化相关寄存器和量化表 RAM/base table
写 trigger/reset/ISP/timeout/AW/QT 选择等控制寄存器
写帧尺寸、stride、MCU 数、输入格式、restart marker、编码像素总数和 wrap
hal_jpege_sequence_configure() 只负责写入序列级配置寄存器,不触发 SHADOW_CUR_EN。第 0 帧的 shadow 生效动作在 hal_jpege_start_frame() 中完成,以保证源/目的地址和 cache 维护已经准备好后再让当前帧配置生效。
1.5 单帧启动、IRQ 分发和取结果
error_code_t hal_jpege_start_frame(const hal_jpege_frame_t *frame); error_code_t hal_jpege_callback_register(hal_jpege_callback_t callback); void hal_jpege_irq_handler(void); error_code_t hal_jpege_get_result(hal_jpege_frame_t *frame);
hal_jpege_start_frame:
校验 HAL 已初始化、sequence config 已配置
保存 frame 到 HAL 内部 context
清除历史中断状态
校验
src_addr、dst_addr256 字节对齐写
RAWY_ADDR、BS_ADDR对源 Y/RAWY 范围执行 cache clean
对目的 buffer 执行 clean+invalidate
NV12/YUV420 格式下配置 UV 地址,若
src_uv_addr == NULL,按src_addr + stride * height推导;YUV422/Bayer 不配置该寄存器标记当前帧为 started,确保紧随其后的硬件事件可被 IRQ handler 接收
若当前 JPEG frame counter 为 0,设置
SHADOW_FLAG并触发SHADOW_CUR_EN,让 sequence 配置对第 0 帧生效;后续手动帧触发START
hal_jpege_irq_handler:
要求 HAL 已 initialized、sequence 已 configured,且当前帧处于 started;不满足时直接返回
读取
INTR_STAT & JPEGE_ALL_INTR_MASK;无命中 status 时直接返回清除本次读取到的全部 pending status
按
overflow -> frame-start abnormal -> timeout -> frame-end的优先级归一为一个hal_jpege_irq_event_t清除 started;只有 frame-end 将结果标记为 ready
在 IRQ 上下文调用已注册的 callback
HAL 不注册 IRQ_JPEG_ENC,也不执行等待。平台 IRQ entry 必须调用 hal_jpege_irq_handler()。
hal_jpege_get_result:
校验 HAL 已初始化、sequence 已配置,且 HAL 已接收到有效 frame-end
读取
GLB_STAT.BS_LEN若输出大小超过
dst_buf_size,在返回IM_ERR_NO_SPACE前执行帧级复位并清理结果状态回填
frame->output_size对输出 JPEG 范围执行 cache invalidate
若
reset_auto=false,触发SW_FRM_RESET;正常结果和IM_ERR_NO_SPACE错误路径均执行
异常 IRQ(overflow、frame-start abnormal、hardware timeout)在回调前同样执行帧级复位;reset_auto=true 时由硬件 AUTO_RESET 完成,reset_auto=false 时由 HAL 触发 SW_FRM_RESET。
hal_jpege_callback_register() 在 hal_jpege_init() 成功后、首次 hal_jpege_start_frame() 前调用。传入 NULL 恢复默认无操作 callback。JPEGE callback 运行于 IRQ 上下文,不得阻塞、做 cache 操作或启动下一帧。
1.6 Shadow 更新接口
error_code_t hal_jpege_update_qp_with_shadow(hal_jpege_shadow_timing_t shadow_timing, uint32_t qp); error_code_t hal_jpege_update_qk_table_with_shadow(hal_jpege_shadow_timing_t shadow_timing, hal_jpege_qk_table_t qk_table);
| 接口 | 适用模式 | 校验 |
|---|---|---|
hal_jpege_update_qp_with_shadow | HAL_JPEGE_QT_MODE_HARD | HAL 已 init、sequence 已 configured、qp <= 98、shadow_timing 合法、当前模式为 hard |
hal_jpege_update_qk_table_with_shadow | HAL_JPEGE_QT_MODE_SOFT | HAL 已 init、sequence 已 configured、qk_table 合法、shadow_timing 合法、当前模式为 soft |
shadow_timing 可选值:
| 值 | 说明 |
|---|---|
HAL_JPEGE_SHADOW_NEXT_START | 修改在下一帧开始生效 |
HAL_JPEGE_SHADOW_NEXT_END | 修改在下一帧结束生效 |
SHADOW_CUR_EN、SHADOW_NEXT_START_EN 和 SHADOW_NEXT_END_EN 是一次性触发位,所选 shadow 更新生效后由硬件自动清零,软件不需要额外清除这些位。
1.7 调试寄存器 dump
error_code_t hal_jpege_regs_dump(void);
hal_jpege_regs_dump() 用 INFO log 输出 JPEGE 可读寄存器,便于和 spec 或异常现场对照。该接口由两个 Kconfig 开关控制:
| 开关 | 说明 |
|---|---|
CONFIG_SDK_ENABLE_DEBUG_HELPERS | SDK 全局 debug helper 开关 |
CONFIG_JPEGE_ENABLE_DEBUG_HELPERS | JPEGE driver debug helper 开关 |
两个开关均打开时,接口返回 IM_OK 并输出寄存器;否则返回 IM_ERR_UNSUPPORTED。INTR_CLR 是 write-only 寄存器,dump 时只打印 <skip>,不会读取。qt_base_tab[32] 和 qt_tab[384] 默认也只打印 <skip>,避免普通寄存器 dump 输出过长;需要查看量化表内容时,可定义:
#define HAL_JPEGE_DUMP_READ_TABLES 1U
1.8 Cache 管理
HAL 当前在以下位置进行 cache 维护:
| 阶段 | 地址 | 操作 | 目的 |
|---|---|---|---|
start_frame | src_addr,长度 rawy_size | clean | 确保硬件读到 CPU 已写入的源 Y/RAWY 数据 |
start_frame | src_uv_addr 或推导 UV 地址,长度 rawc_size | clean | NV12/YUV420 下确保硬件读到 CPU 已写入的 UV 数据 |
start_frame | dst_addr,长度 dst_buf_size | clean+invalidate | 避免 CPU 脏 cache line 在硬件写结果后覆盖 JPEG bitstream |
get_result | dst_addr,长度 output_size | invalidate | 让 CPU 读取硬件写入后的 JPEG bitstream |
调用方在 hal_jpege_start_frame() 到 hal_jpege_get_result() 之间不应修改源/目的 buffer。
源图像与 JPEG bitstream buffer 的 cache 所有权切换见 JPEGE buffer cache 生命周期图。
1.9 线程安全与中断策略
1.9.1 IRQ 模型
JPEGE 采用与 MSCALER 一致的 interrupt-driven 分层:
JPEGE hardware -> IRQ_JPEG_ENC -> im_irq dispatch -> hal_jpege_irq_handler() -> hal_jpege_callback_t(event)
| 职责 | 归属层 | 实现 |
|---|---|---|
| 平台 IRQ 申请、使能和释放 | 应用/平台 | 由平台 IRQ 层负责 |
| 转交 SoC IRQ | 应用/平台 | 在 ISR 中调用 hal_jpege_irq_handler() |
| 读取/清除 JPEGE status,按优先级选择 event,调用 callback | HAL | hal_jpege_irq_handler() |
| buffer 分配和 256 字节对齐 | 应用层 | HAL 只校验,不分配/搬运 |
2. 典型用法
2.1 软件量化表模式
hal_jpege_struct_init(¶m, &config, &frame); param.width = 640U; param.height = 480U; param.pix_format = HAL_JPEGE_PIX_FMT_NV12; param.qk_table = HAL_JPEGE_QK_TABLE_MEDIUM_COMPRESSION; config.codec.qt_mode = HAL_JPEGE_QT_MODE_SOFT; config.codec.qt_table = HAL_JPEGE_QT_TABLE_1;
软件表模式下,param.qp 不参与 QP 配置,HAL 使用 param.qk_table 写 QK_TAB_SEL。