API GUIDE / JPEGE / OVERVIEW

G32S10 JPEGE API 概述

模块概述:按从低到高顺序覆盖四层:

1. 文档范围

按从低到高顺序覆盖四层:

  1. jpege_regs.h:JPEGE 寄存器结构体、基地址、位域宏和硬件限制

  2. LL JPEGE:寄存器级 static inline 读写接口

  3. HAL JPEGE:序列/帧配置、cache、JPEGE status 清除和 callback 分发

2. 分层关系

APPLICATION  Application  编码业务或上层驱动
→
HAL  HAL JPEGE  init / sequence_configure / start_frame
IRQ 状态清除 / callback / get_result
→
LL  LL JPEGE  static inline 寄存器访问
→
REGISTERS  jpege_regs.h  结构体、实地址、位域与硬件范围定义
  • 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(&param, &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(&param, &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_READYHAL 未初始化、sequence 未配置、systick 未初始化,或在有效 frame-end 前调用 hal_jpege_get_result()
IM_ERR_UNSUPPORTEDshadow update 模式不匹配,或 debug helper 未打开时调用 hal_jpege_regs_dump()
IM_ERR_TIMEOUTreset FSM 超时或 JPEGE hardware timeout
IM_ERR_IOISP DDR 写数据覆盖 JPEG 读数据区域或 frame-start abnormal
IM_ERR_NO_SPACEBS_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_SEL shadow 更新,不提供整表 shadow 更新。