我了解的大致思路是 用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***************************************/
离线
dmesg 看下报错原因,另外是不是设备树的cma预留太小
离线
你这个my_ion_dest也不能这么写,申请好重复使用就行了,不要反复申请释放,不然很容易碎片化
离线
你这个my_ion_dest也不能这么写,申请好重复使用就行了,不要反复申请释放,不然很容易碎片化
是的,申请一次就可以了,关闭应用之前释放就行了。
离线
你这个my_ion_dest也不能这么写,申请好重复使用就行了,不要反复申请释放,不然很容易碎片化
刚开始学习linux,还不太熟,想着先跑通,在优化
有没有这方面的参考资料
离线
你这个my_ion_dest也不能这么写,申请好重复使用就行了,不要反复申请释放,不然很容易碎片化
奇怪,用sdk里面的g2d_demo也无法从ion申请内存
离线
可以看下ioctl 返回的报错码是什么
离线
另外你是一次都没申请cma成功过?还是说有几率失败?
离线
另外你是一次都没申请cma成功过?还是说有几率失败?
全部失败,从来没成功过,编译package里面的g2d_demo也是失败
ioctl失败的错误代码:errno=25, strerror(errno) = Not a tty
离线
double33 说:另外你是一次都没申请cma成功过?还是说有几率失败?
全部失败,从来没成功过,编译package里面的g2d_demo也是失败
ioctl失败的错误代码:errno=25, strerror(errno) = Not a tty
lv_examples 加 0,1,2,3参数 可以旋转吗?
离线
ioctl用的不对,调用方式和g2d驱动不匹配吧?照着demo写一个,或者直接找找g2d驱动代码看一下
离线
@ubuntu
lv_g2d_test加参数可以旋转显示动画
离线