API GUIDE / JPEGE / OVERVIEW
G32S10 JPEGE API 概述
模块概述:按从低到高顺序覆盖四层:
1. 文档范围
按从低到高顺序覆盖四层:
jpege_regs.h:JPEGE 寄存器结构体、基地址、位域宏和硬件限制LL JPEGE:寄存器级static inline读写接口HAL JPEGE:序列/帧配置、cache、JPEGE status 清除和 callback 分发
2. 分层关系
IRQ 状态清除 / callback / get_result
jpege_regs.h:定义 JPEGE 寄存器布局、基地址、位域 mask、配置寄存器的参数范围限制LL JPEGE:只读写寄存器,不维护状态,不做参数完整性校验HAL JPEGE:封装复位、序列配置、逐帧启动、status 清除、callback、结果读取和 cache 管理;不注册 SoC IRQ,也不执行等待
3. 典型用法
3.1 基础编码流程
#include "hal_jpege.h"
#include "im_irq.h"
#include "im_time.h"
#include <stdbool.h>
#define SRC_WIDTH 640U
#define SRC_HEIGHT 480U
#define DST_SIZE (1024U * 1024U)
#define WAIT_TIMEOUT_MS 1000U
static uint8_t s_dst[DST_SIZE] __attribute__((aligned(256)));
static volatile bool s_frame_done;
static volatile error_code_t s_irq_result;
static void jpege_irq_entry(uint32_t irq_id, void *user_ctx)
{
(void)irq_id;
(void)user_ctx;
hal_jpege_irq_handler();
}
static void jpege_frame_callback(hal_jpege_irq_event_t event)
{
s_irq_result = (event == HAL_JPEGE_IRQ_EVENT_FRAME_DONE) ? IM_OK :
(event == HAL_JPEGE_IRQ_EVENT_TIMEOUT) ? IM_ERR_TIMEOUT :
IM_ERR_IO;
s_frame_done = true;
}
static error_code_t jpege_wait_frame_done(uint32_t timeout_ms)
{
uint64_t start_ms = im_time_get_ms();
while (!s_frame_done) {
if ((im_time_get_ms() - start_ms) > timeout_ms) {
return IM_ERR_TIMEOUT;
}
}
return s_irq_result;
}
error_code_t run_jpege_nv12(void *src_nv12)
{
hal_jpege_param_t param;
hal_jpege_config_t config;
hal_jpege_frame_t frame;
error_code_t ret;
bool irq_registered = false;
bool hal_initialized = false;
hal_jpege_struct_init(¶m, &config, &frame);
param.width = SRC_WIDTH;
param.height = SRC_HEIGHT;
param.pix_format = HAL_JPEGE_PIX_FMT_NV12;
param.qp = 30U;
frame.src_addr = src_nv12;
frame.dst_addr = s_dst;
frame.dst_buf_size = DST_SIZE;
ret = hal_jpege_init(&config);
if (ret == IM_OK) {
hal_initialized = true;
ret = hal_jpege_callback_register(jpege_frame_callback);
}
if (ret == IM_OK) {
ret = hal_jpege_sequence_configure(¶m, &config);
}
if (ret == IM_OK) {
ret = im_irq_request((uint32_t)IRQ_JPEG_ENC,
jpege_irq_entry, "hal_jpege", NULL);
if (ret == IM_OK) {
irq_registered = true;
ret = im_irq_enable((uint32_t)IRQ_JPEG_ENC);
}
}
if (ret == IM_OK) {
s_frame_done = false;
s_irq_result = IM_ERR_BUSY;
ret = hal_jpege_start_frame(&frame);
}
if (ret == IM_OK) {
ret = jpege_wait_frame_done(config.timeout_ms != 0U ?
config.timeout_ms : WAIT_TIMEOUT_MS);
}
if (ret == IM_OK) {
ret = hal_jpege_get_result(&frame);
}
if (ret == IM_OK) {
/* frame.output_size 是 s_dst 中 JPEG bitstream 的有效长度 */
}
if (irq_registered) {
(void)im_irq_disable((uint32_t)IRQ_JPEG_ENC);
(void)im_irq_release((uint32_t)IRQ_JPEG_ENC);
}
if (hal_initialized) {
(void)hal_jpege_deinit();
}
return ret;
}3.2 运行中更新 QP 或 QK_TAB_SEL
使用 HAL 时,硬件 QP 模式下更新 QP:
ret = hal_jpege_update_qp_with_shadow(HAL_JPEGE_SHADOW_NEXT_START, 36U);
使用 HAL 时,软件表模式下更新 QK_TAB_SEL:
ret = hal_jpege_update_qk_table_with_shadow( HAL_JPEGE_SHADOW_NEXT_END, HAL_JPEGE_QK_TABLE_LOW_COMPRESSION);
这两个 HAL 接口要求活跃 sequence 会话,应在上一帧完成、下一帧启动前调用。模式不匹配时返回 IM_ERR_UNSUPPORTED。
4. 错误码速查
| 错误码 | 常见原因 |
|---|---|
IM_OK | 成功 |
IM_ERR_INVALID_PARAM | 空指针、尺寸越界或未满足像素格式对齐、像素格式枚举非法、地址未 256 字节对齐、QP/QK/shadow/reset/AXI 参数非法、restart marker interval 非法 |
IM_ERR_NOT_READY | HAL 未初始化、sequence 未配置、systick 未初始化,或在有效 frame-end 前调用 hal_jpege_get_result() |
IM_ERR_UNSUPPORTED | shadow update 模式不匹配,或 debug helper 未打开时调用 hal_jpege_regs_dump() |
IM_ERR_TIMEOUT | reset FSM 超时或 JPEGE hardware timeout |
IM_ERR_IO | ISP DDR 写数据覆盖 JPEG 读数据区域或 frame-start abnormal |
IM_ERR_NO_SPACE | BS_LEN 超过 dst_buf_size |
5. 注意事项
HAL 不分配内存,也不做地址对齐搬运;输入和输出 buffer 的分配、生命周期、256 字节对齐由调用方保证。
NV12/YUV420 若不传
src_uv_addr,HAL 会按src_addr + stride * height推导 UV 地址;推导出的地址仍必须 256 字节对齐。Bayer 输入会被 HAL 内部强制转为手动 start 且关闭 ISP linkage,不回写用户传入的
config。每帧正常或异常结束都必须完成帧级复位;
reset_auto=false时由hal_jpege_get_result()(包括IM_ERR_NO_SPACE路径)或异常 IRQ 处理触发SW_FRM_RESET,reset_auto=true时由硬件AUTO_RESET完成。当前 HAL 使用模块级静态 context,不支持多实例并发或无锁多线程访问。
HAL 不申请 SoC IRQ,也不执行等待。应用必须注册
IRQ_JPEG_ENC,在平台 ISR 中调用hal_jpege_irq_handler(),并通过 callback 处理帧完成事件。软件表 RAM 只有一份,运行中直接重写整张软件量化表可能覆盖硬件正在使用的数据,sequence reset 时与 slave registers 一同复位。
当前 HAL 运行中只提供
QK_TAB_SELshadow 更新,不提供整表 shadow 更新。