您尚未登录。

楼主 # 2025-10-20 14:31:12

xsx_kair
会员
注册时间: 2022-11-25
已发帖子: 29
积分: 19

T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

我了解的大致思路是 用ion申请硬件内存,将NV21的数据放在里面,用G2D转换,然后再拷贝的自己的内存中,
但是我ion申请内存老是失败
请大佬们指点下

头文件

//
// Created by zx on 2025/10/18.
//

#ifndef LVGLDEMO_MODULES_ION_UTILS_H
#define LVGLDEMO_MODULES_ION_UTILS_H

//#include "ion.h"
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>

#include <stdint.h>
#include <stddef.h>
//#include <linux/ion.h>

#ifdef __cplusplus
extern "C" {
#endif



// =============================
// ION HEAP MASK 定义
// =============================
// 这些定义适用于 Allwinner T113 / TinaLinux 内核
#define ION_HEAP_SYSTEM_MASK            (1 << 0)
#define ION_HEAP_SYSTEM_CONTIG_MASK     (1 << 1)
#define ION_HEAP_CARVEOUT_MASK          (1 << 2)
#define ION_HEAP_DMA_MASK               (1 << 4)
#define ION_HEAP_CMA_MASK               (1 << 8)   // 常用于G2D、视频帧缓冲等
#define ION_HEAP_RESERVE_MASK           (1 << 9)   // 部分平台有专用保留区

// 一般建议默认使用 CMA 堆
#define ION_T113_DEFAULT_HEAP_MASK      ION_HEAP_DMA_MASK|ION_HEAP_CARVEOUT_MASK

#define AW_ION_CACHED_FLAG 1		/* mappings of this buffer should be cached, ion will do cache maintenance when the buffer is mapped for dma */
#define AW_ION_CACHED_NEEDS_SYNC_FLAG 2	/* mappings of this buffer will created at mmap time, if this is set caches must be managed manually */


typedef struct {
    int buf_fd;       // dma-buf fd,用于 mmap
    size_t size;         // 申请的大小
    void *vir_addr;      // 映射的虚拟地址
    unsigned long phys_addr; // 物理地址(可选,如果支持)
} my_ion_buf_t;

// 初始化与反初始化
int my_ion_init(void);
void my_ion_deinit(void);

// 分配与释放
my_ion_buf_t * my_ion_alloc(size_t size, unsigned int heap_mask);
void my_ion_free(my_ion_buf_t *buf);

// 地址映射
int my_ion_mmap(my_ion_buf_t *buf);
void my_ion_munmap(my_ion_buf_t *buf);

void my_ion_dest(void);

#endif //LVGLDEMO_MODULES_ION_UTILS_H

源文件

/******************************************************************************************
 *文件名: ion_utils.c.c
 *创建时间:2024/12/29
 *说明:
 ******************************************************************************************/

/******************************************************************************************/
/*****************************************头文件********************************************/
/******************************************************************************************/
#include "ion_utils.h"

#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#include "zx_log.h"
/******************************************************************************************/
/*****************************************局部变量声明**************************************/
/******************************************************************************************/
static int g_ion_fd = -1;

// ========== 内核头文件定义复制 ==========
struct ion_allocation_data
{
    size_t len;
    size_t align;
    unsigned int heap_id_mask;
    unsigned int flags;
    int handle;
};

struct ion_handle_data
{
    int handle;
};

struct ion_fd_data
{
    int handle;
    int fd;
};

#define ION_IOC_MAGIC       'I'
#define ION_IOC_ALLOC       _IOWR(ION_IOC_MAGIC, 0, struct ion_allocation_data)
#define ION_IOC_FREE        _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
#define ION_IOC_MAP         _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data)
#define ION_IOC_SHARE       _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
/******************************************************************************************/
/*****************************************局部函数声明**************************************/
/******************************************************************************************/

/******************************************************************************************/
/********************************************其他******************************************/
/******************************************************************************************/

/******************************************************************************************/
/********************************************开始******************************************/
/******************************************************************************************/
int my_ion_init(void)
{
    my_ion_deinit();

    g_ion_fd = open("/dev/ion", O_RDWR);
    if (g_ion_fd < 0)
        ZX_LOG_E("open /dev/ion failed\r\n");
    return g_ion_fd;
}
void my_ion_deinit(void)
{
    if (g_ion_fd >= 0)
    {
        close(g_ion_fd);
        g_ion_fd = -1;
    }
}

my_ion_buf_t *my_ion_alloc(size_t size, unsigned int heap_mask)
{
    struct ion_allocation_data alloc_data;

    my_ion_buf_t *buf = calloc(1, sizeof(my_ion_buf_t));

    if (!buf)
    {
        ZX_LOG_E("calloc my_ion_buf_t failed\r\n");
        return NULL;
    }

    memset(&alloc_data, 0, sizeof(alloc_data));
    alloc_data.len = size;
    alloc_data.align = 4096;
    alloc_data.heap_id_mask = heap_mask;
    alloc_data.flags = AW_ION_CACHED_FLAG | AW_ION_CACHED_NEEDS_SYNC_FLAG;
    alloc_data.handle = -1;

    if (ioctl(g_ion_fd, ION_IOC_ALLOC, &alloc_data) < 0)
    {
        ZX_LOG_E("ION_IOC_ALLOC failed\r\n");
        free(buf);
        buf = NULL;
    } else
    {
        buf->buf_fd = alloc_data.handle;
        buf->size = size;
    }

    return buf;
}

int my_ion_mmap(my_ion_buf_t *buf)
{
    struct ion_fd_data fd_data;

    if (!buf)
        return -1;

    memset(&fd_data, 0, sizeof(fd_data));
    fd_data.handle = buf->buf_fd;
    if (ioctl(g_ion_fd, ION_IOC_MAP, &fd_data) < 0)
    {
        ZX_LOG_E("ION_IOC_MAP failed\r\n");
        return -1;
    }

    buf->vir_addr = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, buf->buf_fd, 0);
    if (buf->vir_addr == MAP_FAILED)
    {
        ZX_LOG_E("ion mmap failed\r\n");
        buf->vir_addr = NULL;
        return -1;
    }

    return 0;
}

void my_ion_munmap(my_ion_buf_t *buf)
{
    if (buf && buf->vir_addr)
    {
        munmap(buf->vir_addr, buf->size);
        buf->vir_addr = NULL;
    }
}

void my_ion_free(my_ion_buf_t *buf)
{
    if (!buf)
        return;

    if (buf->buf_fd >= 0)
    {
        struct ion_handle_data handle_data = {.handle = buf->buf_fd};
        ioctl(g_ion_fd, ION_IOC_FREE, &handle_data);
        close(buf->buf_fd);
        buf->buf_fd = -1;
    }

    free(buf);
}

void my_ion_dest(void)
{
    int res = -1;

    res = my_ion_init();
    if (res < 0)
        return;

    // 分配 2MB 连续内存(供 G2D、视频使用)
    my_ion_buf_t *buf = my_ion_alloc(2 * 1024 * 1024, ION_T113_DEFAULT_HEAP_MASK);
    if (!buf)
    {
        ZX_LOG_E("alloc failed\r\n");
        my_ion_deinit();
        return;
    }

    // 映射
    res = my_ion_mmap(buf);
    if (res < 0)
        ZX_LOG_E("mem map fail!\r\n");
    else
    {
        ZX_LOG_I("ION virtual addr: %p, size=%zu\n", buf->vir_addr, buf->size);
    }

    // 用完释放
    my_ion_munmap(buf);
    my_ion_free(buf);
    my_ion_deinit();
}
/****************************************end of file***************************************/

离线

#1 2025-10-20 16:34:18

晕哥
管理员
所在地: wechat: whycan_cn
注册时间: 2017-09-06
已发帖子: 9,415
积分: 9202

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

建议在能正常跑的demo基础上修改,比如 openwrt/package/allwinner/display/g2d-sample





在线

#2 2025-10-20 17:29:29

double33
会员
注册时间: 2021-11-30
已发帖子: 29
积分: 39

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

dmesg 看下报错原因,另外是不是设备树的cma预留太小

离线

#3 2025-10-20 17:55:28

double33
会员
注册时间: 2021-11-30
已发帖子: 29
积分: 39

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

你这个my_ion_dest也不能这么写,申请好重复使用就行了,不要反复申请释放,不然很容易碎片化

离线

#4 2025-10-21 10:25:52

hameyou
会员
注册时间: 2018-04-15
已发帖子: 227
积分: 8.5

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

double33 说:

你这个my_ion_dest也不能这么写,申请好重复使用就行了,不要反复申请释放,不然很容易碎片化

是的,申请一次就可以了,关闭应用之前释放就行了。

离线

楼主 #5 2025-10-21 14:28:07

xsx_kair
会员
注册时间: 2022-11-25
已发帖子: 29
积分: 19

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

double33 说:

你这个my_ion_dest也不能这么写,申请好重复使用就行了,不要反复申请释放,不然很容易碎片化

刚开始学习linux,还不太熟,想着先跑通,在优化
有没有这方面的参考资料

离线

楼主 #6 2025-10-21 15:21:31

xsx_kair
会员
注册时间: 2022-11-25
已发帖子: 29
积分: 19

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

double33 说:

你这个my_ion_dest也不能这么写,申请好重复使用就行了,不要反复申请释放,不然很容易碎片化

奇怪,用sdk里面的g2d_demo也无法从ion申请内存

离线

#7 昨天 11:00:00

double33
会员
注册时间: 2021-11-30
已发帖子: 29
积分: 39

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

可以看下ioctl 返回的报错码是什么

离线

#8 昨天 11:03:31

double33
会员
注册时间: 2021-11-30
已发帖子: 29
积分: 39

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

另外你是一次都没申请cma成功过?还是说有几率失败?

离线

楼主 #9 昨天 13:22:49

xsx_kair
会员
注册时间: 2022-11-25
已发帖子: 29
积分: 19

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

double33 说:

另外你是一次都没申请cma成功过?还是说有几率失败?

全部失败,从来没成功过,编译package里面的g2d_demo也是失败
ioctl失败的错误代码:errno=25, strerror(errno) = Not a tty

离线

#10 昨天 13:24:13

ubuntu
会员
注册时间: 2020-03-30
已发帖子: 326
积分: 304

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

xsx_kair 说:
double33 说:

另外你是一次都没申请cma成功过?还是说有几率失败?

全部失败,从来没成功过,编译package里面的g2d_demo也是失败
ioctl失败的错误代码:errno=25, strerror(errno) = Not a tty

lv_examples 加 0,1,2,3参数 可以旋转吗?

离线

#11 昨天 14:18:23

double33
会员
注册时间: 2021-11-30
已发帖子: 29
积分: 39

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

ioctl用的不对,调用方式和g2d驱动不匹配吧?照着demo写一个,或者直接找找g2d驱动代码看一下

离线

楼主 #12 昨天 15:18:15

xsx_kair
会员
注册时间: 2022-11-25
已发帖子: 29
积分: 19

Re: T113使用cpu将相机的NV21转换为RGB32格式,需要100多ms,有没有大神指点下怎么用硬件去转

@ubuntu
lv_g2d_test加参数可以旋转显示动画

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn