OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4783|回复: 14

[XILINX] linux v4l2框架下ov5640摄像头驱动报错:无法准备DMA传输

[复制链接]

8

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2022-4-29
在线时间
43 小时
发表于 2022-10-19 17:11:40 | 显示全部楼层 |阅读模式
本帖最后由 爱跑步的雯雯 于 2022-10-20 09:53 编辑

提示设备打开成功,设置像素格式也匹配,提示无法准备DMA传输,内存分配空间大小为0 ,无法采集显示图片
(图片)串口打印显示摄像头注册成功了
root@ALIENTEK-ZYNQ:~# ./cam /dev/video0
open camera successful
V4L2_PIX_FMT_RGB565
[ 7574.045542] xilinx-video amba_pl:xlnx_vipp: dma_alloc_coherent of size 0 failed
ioctl error: VIDIOC_REQBUFS: Cannot allocate memory
希望大佬帮忙分析一下原因

用的imx的linux c指南里的关于v4l2摄像头的驱动测试文件  (vivado 工程在附件里)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include <linux/fb.h>

#define FB_DEV              "/dev/fb0"      //LCD设备节点
#define FRAMEBUFFER_COUNT   3               //帧缓冲数量

/*** 摄像头像素格式及其描述信息 ***/
typedef struct camera_format {
    unsigned char description[32];  //字符串描述信息
    unsigned int pixelformat;       //像素格式
} cam_fmt;

/*** 描述一个帧缓冲的信息 ***/
typedef struct cam_buf_info {
    unsigned short *start;      //帧缓冲起始地址
    unsigned long length;       //帧缓冲长度
} cam_buf_info;

static int width;                       //LCD宽度
static int height;                      //LCD高度
static unsigned short *screen_base = NULL;//LCD显存基地址
static int fb_fd = -1;                  //LCD设备文件描述符
static int v4l2_fd = -1;                //摄像头设备文件描述符
static cam_buf_info buf_infos[FRAMEBUFFER_COUNT];
static cam_fmt cam_fmts[10];
static int frm_width, frm_height;   //视频帧宽度和高度

static int fb_dev_init(void)
{
    struct fb_var_screeninfo fb_var = {0};
    struct fb_fix_screeninfo fb_fix = {0};
    unsigned long screen_size;

    /* 打开framebuffer设备 */
    fb_fd = open(FB_DEV, O_RDWR);
    if (0 > fb_fd) {
        fprintf(stderr, "open error: %s: %s\n", FB_DEV, strerror(errno));
        return -1;
    }

    /* 获取framebuffer设备信息 */
    ioctl(fb_fd, FBIOGET_VSCREENINFO, &fb_var);
    ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_fix);

    screen_size = fb_fix.line_length * fb_var.yres;
    width = fb_var.xres;
    height = fb_var.yres;

    /* 内存映射 */
    screen_base = mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
    if (MAP_FAILED == (void *)screen_base) {
        perror("mmap error");
        close(fb_fd);
        return -1;
    }

    /* LCD背景刷白 */
    memset(screen_base, 0xFF, screen_size);
    return 0;
}

static int v4l2_dev_init(const char *device)
{
    struct v4l2_capability cap = {0};

    /* 打开摄像头 */
    v4l2_fd = open(device, O_RDWR);
    if (0 > v4l2_fd) {
        fprintf(stderr, "open error: %s: %s\n", device, strerror(errno));
        return -1;
    }else{
        printf("open camera successful\n");
        return 0;        
        }        //添加

    /* 查询设备功能 */
    ioctl(v4l2_fd, VIDIOC_QUERYCAP, &cap);

    /* 判断是否是视频采集设备 */
    if (!(V4L2_CAP_VIDEO_CAPTURE & cap.capabilities)) {
        fprintf(stderr, "Error: %s: No capture video device!\n", device);
        printf("no capture video device\n");
        close(v4l2_fd);
        return -1;
    }else{
        printf("capture video device\n");
    return 0;}
}

static void v4l2_enum_formats(void)
{
    struct v4l2_fmtdesc fmtdesc = {0};

    /* 枚举摄像头所支持的所有像素格式以及描述信息 */
    fmtdesc.index = 0;
    fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    while (0 == ioctl(v4l2_fd, VIDIOC_ENUM_FMT, &fmtdesc)) {

        // 将枚举出来的格式以及描述信息存放在数组中
        cam_fmts[fmtdesc.index].pixelformat = fmtdesc.pixelformat;
        strcpy(cam_fmts[fmtdesc.index].description, fmtdesc.description);
        fmtdesc.index++;
    }
}

static void v4l2_print_formats(void)
{
    struct v4l2_frmsizeenum frmsize = {0};
    struct v4l2_frmivalenum frmival = {0};
    int i;

    frmsize.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    frmival.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    for (i = 0; cam_fmts.pixelformat; i++) {

        printf("format<0x%x>, description<%s>\n", cam_fmts.pixelformat,
                    cam_fmts.description);

        /* 枚举出摄像头所支持的所有视频采集分辨率 */
        frmsize.index = 0;
        frmsize.pixel_format = cam_fmts.pixelformat;
        frmival.pixel_format = cam_fmts.pixelformat;
        while (0 == ioctl(v4l2_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize)) {

            printf("size<%d*%d> ",
                    frmsize.discrete.width,
                    frmsize.discrete.height);
            frmsize.index++;

            /* 获取摄像头视频采集帧率 */
            frmival.index = 0;
            frmival.width = frmsize.discrete.width;
            frmival.height = frmsize.discrete.height;
            while (0 == ioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival)) {

                printf("<%dfps>", frmival.discrete.denominator /
                        frmival.discrete.numerator);
                frmival.index++;
            }
            printf("\n");
        }
        printf("\n");
    }
}

static int v4l2_set_format(void)
{
    struct v4l2_format fmt = {0};
    struct v4l2_streamparm streamparm = {0};

    /* 设置帧格式 */
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//type类型
    fmt.fmt.pix.width = width;  //视频帧宽度
    fmt.fmt.pix.height = height;//视频帧高度
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;//V4L2_PIX_FMT_RGB565X;  //像素格式
    if (0 > ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt)) {
        fprintf(stderr, "ioctl error: VIDIOC_S_FMT: %s\n", strerror(errno));
        return -1;
    }

    /*** 判断是否已经设置为我们要求的RGB565像素格式
    如果没有设置成功表示该设备不支持RGB565像素格式 */
    if (V4L2_PIX_FMT_RGB565 != fmt.fmt.pix.pixelformat) {
        fprintf(stderr, "Error: the device does not support RGB565 format!\n");
        return -1;
    }
    else {
            printf("V4L2_PIX_FMT_RGB565\n");
        return 0;
    };

    frm_width = fmt.fmt.pix.width;  //获取实际的帧宽度
    frm_height = fmt.fmt.pix.height;//获取实际的帧高度
    printf("视频帧大小<%d * %d>\n", frm_width, frm_height);

    /* 获取streamparm */
    streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ioctl(v4l2_fd, VIDIOC_G_PARM, &streamparm);

    /** 判断是否支持帧率设置 **/
    if (V4L2_CAP_TIMEPERFRAME & streamparm.parm.capture.capability) {
        streamparm.parm.capture.timeperframe.numerator = 1;
        streamparm.parm.capture.timeperframe.denominator = 30;//30fps
        if (0 > ioctl(v4l2_fd, VIDIOC_S_PARM, &streamparm)) {
            fprintf(stderr, "ioctl error: VIDIOC_S_PARM: %s\n", strerror(errno));
            return -1;
        }
    }

    return 0;
}

static int v4l2_init_buffer(void)
{
    struct v4l2_requestbuffers reqbuf = {0};
    struct v4l2_buffer buf = {0};

    /* 申请帧缓冲 */
    reqbuf.count = FRAMEBUFFER_COUNT;       //帧缓冲的数量
    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    reqbuf.memory = V4L2_MEMORY_MMAP;
    if (0 > ioctl(v4l2_fd, VIDIOC_REQBUFS, &reqbuf)) {
        fprintf(stderr, "ioctl error: VIDIOC_REQBUFS: %s\n", strerror(errno));
        return -1;
    }

    /* 建立内存映射 */
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    for (buf.index = 0; buf.index < FRAMEBUFFER_COUNT; buf.index++) {

        ioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf);
        buf_infos[buf.index].length = buf.length;
        buf_infos[buf.index].start = mmap(NULL, buf.length,
                PROT_READ | PROT_WRITE, MAP_SHARED,
                v4l2_fd, buf.m.offset);
        if (MAP_FAILED == buf_infos[buf.index].start) {
            perror("mmap error");
            return -1;
        }
    }

    /* 入队 */
    for (buf.index = 0; buf.index < FRAMEBUFFER_COUNT; buf.index++) {

        if (0 > ioctl(v4l2_fd, VIDIOC_QBUF, &buf)) {
            fprintf(stderr, "ioctl error: VIDIOC_QBUF: %s\n", strerror(errno));
            return -1;
        }
    }

    return 0;
}

static int v4l2_stream_on(void)
{
    /* 打开摄像头、摄像头开始采集数据 */
    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    if (0 > ioctl(v4l2_fd, VIDIOC_STREAMON, &type)) {
        fprintf(stderr, "ioctl error: VIDIOC_STREAMON: %s\n", strerror(errno));
        return -1;
    }

    return 0;
}

static void v4l2_read_data(void)
{
    struct v4l2_buffer buf = {0};
    unsigned short *base;
    unsigned short *start;
    int min_w, min_h;
    int j;

    if (width > frm_width)
        min_w = frm_width;
    else
        min_w = width;
    if (height > frm_height)
        min_h = frm_height;
    else
        min_h = height;

    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    for ( ; ; ) {

        for(buf.index = 0; buf.index < FRAMEBUFFER_COUNT; buf.index++) {

            ioctl(v4l2_fd, VIDIOC_DQBUF, &buf);     //出队
            for (j = 0, base=screen_base, start=buf_infos[buf.index].start;
                        j < min_h; j++) {

                memcpy(base, start, min_w * 2); //RGB565 一个像素占2个字节
                base += width;  //LCD显示指向下一行
                start += frm_width;//指向下一行数据
            }

            // 数据处理完之后、再入队、往复
            ioctl(v4l2_fd, VIDIOC_QBUF, &buf);
        }
    }
}

int main(int argc, char *argv[])
{
    if (2 != argc) {
        fprintf(stderr, "Usage: %s <video_dev>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /* 初始化LCD */
    if (fb_dev_init())
        exit(EXIT_FAILURE);

    /* 初始化摄像头 */
    if (v4l2_dev_init(argv[1]))
        exit(EXIT_FAILURE);

    /* 枚举所有格式并打印摄像头支持的分辨率及帧率 */
    v4l2_enum_formats();
    v4l2_print_formats();

    /* 设置格式 */
    if (v4l2_set_format())
        exit(EXIT_FAILURE);

    /* 初始化帧缓冲:申请、内存映射、入队 */
    if (v4l2_init_buffer())
        exit(EXIT_FAILURE);

    /* 开启视频采集 */
    if (v4l2_stream_on())
        exit(EXIT_FAILURE);

    /* 读取数据:出队 */
    v4l2_read_data();       //在函数内循环采集数据、将其显示到LCD屏

    exit(EXIT_SUCCESS);
}



X@}UV1T7CU}`%UG2B1]~K25.png

design_1.pdf

141.89 KB, 下载次数: 7

vivado工程

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

8

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2022-4-29
在线时间
43 小时
 楼主| 发表于 2022-10-28 10:29:46 | 显示全部楼层
本帖最后由 爱跑步的雯雯 于 2022-10-28 11:07 编辑

问题已经解决了,用了楼上大佬的代码,稍作改动吧,
1。我最开始在vivdo工程里的vdma帧缓存设置的是1,(我记得我改了的,可能当时太郁闷怎么改都不对,晕了改回来了),设置为4或3,代码要和配置对应,因为原子的驱动配置是直接对寄存器配置的,也就是不用枚举啥的没得选,要和代码里直接设置的像素格式等等相对应;
2.改了原子的linux里卖弄的ov5640的一些配置,记不太清了,关键就改了PCLK和50M/60M曝光的配置,因为接受的时候有些花屏,后来改完好些了,但是还是有些横条闪烁,希望有了解的朋友可以不吝指教

3.提醒:之前师兄买了正点原子的插在摄像头上可以供摄像头移动的排线,插上后就不想是图像了或者花屏一段时间后就卡死了,觉得是线太长了,导致数据传输时跟时钟信号有延时,导致接收到错误的数据信号或者直接没有接收到数据才导致的。(个人猜测哦)

最后感谢原子,爱了爱了,代码跟驱动都简洁明了,教学做的太好了,对我帮助很大
回复 支持 反对

使用道具 举报

0

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
275
金钱
275
注册时间
2018-10-22
在线时间
35 小时
发表于 2022-10-21 13:52:05 | 显示全部楼层
  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <fcntl.h>
  4. #include <sys/ioctl.h>
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <linux/videodev2.h>
  9. #include <sys/mman.h>
  10. #include <linux/fb.h>
  11. #include <pthread.h>
  12. #include <linux/input.h>

  13. #define VIDEO_DEV                        "/dev/video0"
  14. #define FB_DEV                                "/dev/fb0"
  15. #define INPUT_DEV                        "/dev/input/event0"
  16. #define VIDEO_BUFFER_COUNT        3

  17. struct buffer_info {
  18.         void *start;
  19.         unsigned int length;
  20. };

  21. static void *thread_function(void *msg)
  22. {
  23.         int fb_fd = -1;
  24.         int video_fd = -1;
  25.         struct fb_var_screeninfo fb_var = {0};
  26.         struct fb_fix_screeninfo fb_fix = {0};
  27.         unsigned char *base;
  28.         unsigned int screensize;
  29.         struct v4l2_format fmt = {0};
  30.         struct v4l2_requestbuffers req_bufs = {0};
  31.         static struct v4l2_buffer buf;
  32.         int n_buf;
  33.         struct buffer_info bufs_info[VIDEO_BUFFER_COUNT];
  34.         enum v4l2_buf_type type;

  35.         /* 打开framebuffer设备 */
  36.         fb_fd = open(FB_DEV, O_RDWR);
  37.         if (0 > fb_fd) {
  38.                 printf("ERROR: failed to open framebuffer device %s\n", FB_DEV);
  39.                 return (void *)-1;
  40.         }

  41.         /* 获取framebuffer设备信息 */
  42.         if (0 > ioctl(fb_fd, FBIOGET_VSCREENINFO, &fb_var)) {
  43.                 printf("ERROR: failed to FBIOGET_VSCREENINFO\n");
  44.                 return (void *)-1;
  45.         }

  46.         if (0 > ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_fix)) {
  47.                 printf("ERROR: failed to FBIOGET_FSCREENINFO\n");
  48.                 return (void *)-1;
  49.         }

  50.         /* 内存映射 */
  51.         screensize = fb_var.yres * fb_fix.line_length;
  52.         base = (unsigned char *)mmap(NULL, screensize,
  53.                                 PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
  54.         if (MAP_FAILED == base) {
  55.                 printf("ERROR: failed to mmap framebuffer, size 0x%x\n", screensize);
  56.                 return (void *)-1;
  57.         }

  58.         /* 打开摄像头设备 */
  59.         video_fd = open(VIDEO_DEV, O_RDWR);
  60.         if (0 > video_fd) {
  61.                 printf("ERROR: failed to open video device %s\n", VIDEO_DEV);
  62.                 return (void *)-1;
  63.         }

  64.         /* 设置摄像头格式 */
  65.         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  66.         fmt.fmt.pix.width = fb_var.xres;
  67.         fmt.fmt.pix.height = fb_var.yres;
  68.         fmt.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
  69.         fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;

  70.         if (0 > ioctl(video_fd, VIDIOC_S_FMT, &fmt)) {
  71.                 printf("ERROR: failed to VIDIOC_S_FMT\n");
  72.                 return (void *)-1;
  73.         }

  74.         /* 请求buffer */
  75.         req_bufs.count = VIDEO_BUFFER_COUNT;
  76.         req_bufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  77.         req_bufs.memory = V4L2_MEMORY_MMAP;

  78.         if (0 > ioctl(video_fd, VIDIOC_REQBUFS, &req_bufs)) {
  79.                 printf("ERROR: failed to VIDIOC_REQBUFS\n");
  80.                 return (void *)-1;
  81.         }

  82.         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  83.         buf.memory = V4L2_MEMORY_MMAP;
  84.         for (n_buf = 0; n_buf < VIDEO_BUFFER_COUNT; n_buf++) {

  85.                 buf.index = n_buf;
  86.                 if (0 > ioctl(video_fd, VIDIOC_QUERYBUF, &buf)) {
  87.                         printf("ERROR: failed to VIDIOC_QUERYBUF\n");
  88.                         return (void *)-1;
  89.                 }

  90.                 bufs_info[n_buf].length = buf.length;
  91.                 bufs_info[n_buf].start = mmap(NULL, buf.length,
  92.                                         PROT_READ | PROT_WRITE, MAP_SHARED,
  93.                                         video_fd, buf.m.offset);
  94.                 if (MAP_FAILED == bufs_info[n_buf].start) {
  95.                         printf("ERROR: failed to mmap video buffer, size 0x%x\n", buf.length);
  96.                         return (void *)-1;
  97.                 }
  98.         }

  99.         /* buffer入队 */
  100.         for (n_buf = 0; n_buf < VIDEO_BUFFER_COUNT; n_buf++) {

  101.                 buf.index = n_buf;
  102.                 if (0 > ioctl(video_fd, VIDIOC_QBUF, &buf)) {
  103.                         printf("ERROR: failed to VIDIOC_QBUF\n");
  104.                         return (void *)-1;
  105.                 }
  106.         }

  107.         /* 开始采集 */
  108.         type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  109.         if (0 > ioctl(video_fd, VIDIOC_STREAMON, &type)) {
  110.                 printf("ERROR: failed to VIDIOC_STREAMON\n");
  111.                 return (void *)-1;
  112.         }

  113.         for ( ; ; ) {

  114.                 for(n_buf = 0; n_buf < VIDEO_BUFFER_COUNT; n_buf++) {

  115.                         buf.index = n_buf;
  116.                         if (0 > ioctl(video_fd, VIDIOC_DQBUF, &buf)) {
  117.                                 printf("ERROR: failed to VIDIOC_DQBUF\n");
  118.                                 return (void *)-1;
  119.                         }

  120.                         memcpy(base, (unsigned char *)bufs_info[n_buf].start, screensize);

  121.                         if (0 > ioctl(video_fd, VIDIOC_QBUF, &buf)) {
  122.                                 printf("ERROR: failed to VIDIOC_QBUF\n");
  123.                                 return (void *)-1;
  124.                         }
  125.                 }
  126.         }

  127.         return (void *)0;;
  128. }

  129. int main(int argc, char **argv)
  130. {
  131.         pthread_t sub_thread = {0};
  132.         int input_fd = -1;
  133.         struct input_event input_ev;

  134.         /* 创建并开启线程 */
  135.         if (0 != pthread_create(&sub_thread, NULL,
  136.                                 thread_function, "This is a thread!")) {
  137.                 printf("ERROR: failed to create thread\n");
  138.                 return -1;
  139.         }

  140.         /* 打开按键输入设备 */
  141.         if ( 0 == access("/dev/input/event2", F_OK) )
  142.                 input_fd = open("/dev/input/event2", O_RDONLY);
  143.         else
  144.                 input_fd = open("/dev/input/event1", O_RDONLY);

  145.         if (0 > input_fd) {
  146.                 printf("ERROR: failed to open input device %s", INPUT_DEV);
  147.                 return -1;
  148.         }

  149.         /* 监视按键活动 */
  150.         for ( ; ; ) {

  151.                 if (read(input_fd, &input_ev, sizeof(input_ev)) == sizeof(input_ev)) {
  152.                         if (input_ev.type == EV_KEY)                        // 判断是不是按键类型
  153.                                 if (input_ev.value == 0) {                        // 判断是否松开
  154.                                         if(input_ev.code == KEY_ENTER) {        // 判断具体按键
  155.                                                 //open(1, O_WRONLY);
  156.                                                     write(1, "show", 4);
  157.                                                     close(1);
  158.                                                 return 0;
  159.                                         }
  160.                                 }
  161.                 }
  162.         }
  163. }
复制代码
回复 支持 1 反对 0

使用道具 举报

0

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
275
金钱
275
注册时间
2018-10-22
在线时间
35 小时
发表于 2022-10-20 09:03:11 | 显示全部楼层
vivado的搭建和源码都不贴出来,你让别人怎么帮你分析
回复 支持 反对

使用道具 举报

8

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2022-4-29
在线时间
43 小时
 楼主| 发表于 2022-10-20 10:00:51 | 显示全部楼层
鑫梦 发表于 2022-10-20 09:03
vivado的搭建和源码都不贴出来,你让别人怎么帮你分析

我添加好了大佬,我今天看到一个博主的文章https://blog.csdn.net/qq_41873311/article/details/124726279 ,他也报了相同的错误,说:
大概意思就是分配内存失败了,尚不清楚这是什么信息。应该是没找到相关媒体和设备。
因为在后续的v4l2编程中也遇到过类似报错,排查错误原因就在于找不到相关设备,导致分配0内存

我不太理解是什么意思,我可以在linux路径下可以找到/dev/v4l/by_path/platform-amba_pl\:xlnx_vipp-video-index0这个设备
回复 支持 反对

使用道具 举报

0

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
275
金钱
275
注册时间
2018-10-22
在线时间
35 小时
发表于 2022-10-21 13:52:45 | 显示全部楼层
用上面的代码试试
回复 支持 反对

使用道具 举报

8

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2022-4-29
在线时间
43 小时
 楼主| 发表于 2022-10-23 21:04:07 | 显示全部楼层
鑫梦 发表于 2022-10-21 13:52
用上面的代码试试

大佬,用了上面的代码,我的触摸屏报错了,但是用别的代码触摸屏可以用,应该影响不大
关键内存分配报错
ERROR: failed to open input device /dev/input/event0
[  108.102829] cma: cma_alloc: alloc failed, req-size: 282 pages, ret: -4
[  108.113624] xilinx-video amba_pl:xlnx_vipp: dma_alloc_coherent of size 1155072 failed
回复 支持 反对

使用道具 举报

8

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2022-4-29
在线时间
43 小时
 楼主| 发表于 2022-10-24 09:46:12 | 显示全部楼层
鑫梦 发表于 2022-10-21 13:52
用上面的代码试试

大佬,用了上面的代码显示内存分配报错
[   51.138728] cma: cma_alloc: alloc failed, req-size: 282 pages, ret: -4
[   51.145597] xilinx-video amba_pl:xlnx_vipp: dma_alloc_coherent of size 1155072 failed

同时我的触摸屏也报错,ERROR: failed to open input device /dev/input/event0
后来看到串口打印的信息说没法写入
[    1.388230] cdns-i2c e0004000.i2c: 100 kHz mmio e0004000 irq 23
[    1.394927] edt_ft5426 1-0038: Alientek LCD ID: 4
[    1.496938] edt_ft5426 1-0038: edt_ft5426_ts_write: write error, addr=0x0 len=1.
[    1.504370] edt_ft5426: probe of 1-0038 failed with error -1
[    1.847791] goodix_gtxx 1-0014: ID: 1158, version: 0100
[    1.854091] goodix_gtxx 1-0014: touch number: 5
[    1.858639] goodix_gtxx 1-0014: irq trigger: 2
[    1.863078] goodix_gtxx 1-0014: abs_x: 800, abs_y: 480
[    1.868411] input: Goodix Capacitive TouchScreen as /devices/soc0/amba/e0005000.i2c/i2c-1/1-0014/input/input0
[    1.879197] cdns-i2c e0005000.i2c: 100 kHz mmio e0005000 irq 24
[    2.076807] ov5640 0-003c: Device registration is successful!
回复 支持 反对

使用道具 举报

0

主题

70

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
275
金钱
275
注册时间
2018-10-22
在线时间
35 小时
发表于 2022-10-24 11:10:07 | 显示全部楼层
爱跑步的雯雯 发表于 2022-10-23 21:04
大佬,用了上面的代码,我的触摸屏报错了,但是用别的代码触摸屏可以用,应该影响不大
关键内存分配报错 ...

没遇到过, 你再研究研究吧
回复 支持 反对

使用道具 举报

8

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2022-4-29
在线时间
43 小时
 楼主| 发表于 2022-10-24 16:56:26 | 显示全部楼层
本帖最后由 爱跑步的雯雯 于 2022-10-24 20:57 编辑
鑫梦 发表于 2022-10-24 11:10
没遇到过, 你再研究研究吧

大佬,这个代码是需要在设备树里添加event1,2这样的按键设备吧,想问代码的功能是什么啊,后面的检测案件活动是干什么的看着感觉都是if语句,监测按键的代码最后也只是打印show看看按键的工作情况,我注释掉之后代码运行又直接return 0了,想知道代码的功能是什么啊
想知道fpga还有逻辑分析仪看,在linux下调试看是哪里出了问题呀是只能一个一个printf吗。




回复 支持 反对

使用道具 举报

8

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2022-4-29
在线时间
43 小时
 楼主| 发表于 2022-10-24 21:51:57 | 显示全部楼层
鑫梦 发表于 2022-10-24 11:10
没遇到过, 你再研究研究吧

我给代码加了些打印,注释了打开按键输入设备那块

/* 开始采集 */
        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (0 > ioctl(video_fd, VIDIOC_STREAMON, &type)) {
                printf("ERROR: failed to VIDIOC_STREAMON\n");
                return (void *)-1;
        }
        printf("start capturing\n");

        for ( ; ; ) {

                for(n_buf = 0; n_buf < VIDEO_BUFFER_COUNT; n_buf++) {

                        buf.index = n_buf;
                        printf("come out %d times\n",n_buf);
                        int res = ioctl(video_fd, VIDIOC_DQBUF, &buf);
                        printf("res = %d\n" ,res);
                        if (0 > ioctl(video_fd, VIDIOC_DQBUF, &buf)) {
                                printf("ERROR: failed to VIDIOC_DQBUF\n");
                                return (void *)-1;
                        }else{
                                printf("come out success\n");
                                //return 0;       
                        }
                        memcpy(base, (unsigned char *)bufs_info[n_buf].start, screensize);
                        printf("bufs_info for lcd success\n");
                        if (0 > ioctl(video_fd, VIDIOC_QBUF, &buf)) {
                                printf("ERROR: failed to VIDIOC_QBUF\n");
                                return (void *)-1;
                        }
                        printf("come in %d times\n",n_buf);
                }
        }

最后串口打印结果:
root@ALIENTEK-ZYNQ:~# ./atk   
white biu~
open nice
set ok
buffer belong me
mmap no problem
VIDIOC_QBUF
start capturing
come out 0 times

就卡住了,发现是DQBUF这有问题,if语句正反都没打印,怀疑是摄像头没打开,没数据入列,出列一直在等待,卡死了

哦,对了,还有一件关键的,我这个工程用的摄像头没有自带晶振,我加了一个24Mhz的xclk时钟,在设备树里写了,怀疑是不是内核的ov5640.c驱动里也要加上xclk的部分啊,因为没有系统时钟所以整个摄像头就没数据,才会有一系列的结果,明天用示波器测一下看看
140 &i2c0 {
141         clock-frequency = <100000>;
142
143         ov5640@3c {
144                 compatible = "ovti,ov5640";
145                 reg = <0x3c>;
146
147                 clocks = <&clk_wiz_0 1>;
148                 clock-names = "xclk";
149
150                 pwn-gpios = <&gpio0 57 GPIO_ACTIVE_HIGH>;
151                 rst-gpios = <&gpio0 58 GPIO_ACTIVE_LOW>;
152
153                 status = "okay";
154
155                 #address-cells = <1>;
156                 #size-cells = <0>;
157
158                 port@0 {
159                         reg = <0>;
160
161                         ov5640_ep: endpoint {
162                                 remote-endpoint = <&xlnx_vcap>;
163                         };
164                 };
165         };
166 };
回复 支持 反对

使用道具 举报

8

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2022-4-29
在线时间
43 小时
 楼主| 发表于 2022-10-24 21:55:40 | 显示全部楼层
鑫梦 发表于 2022-10-24 11:10
没遇到过, 你再研究研究吧

我看xilinx的ov5640驱动里好像用了xclk,但那个是OV5640 MIPI Camera Subdev Driver,是不是不可以直接用啊
回复 支持 反对

使用道具 举报

8

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2022-4-29
在线时间
43 小时
 楼主| 发表于 2022-10-25 10:02:09 | 显示全部楼层
爱跑步的雯雯 发表于 2022-10-24 16:56
大佬,这个代码是需要在设备树里添加event1,2这样的按键设备吧,想问代码的功能是什么啊,后面的检测案 ...

怪,今天用示波器测了,pclk和xclk都正常,行信号场信号也正常,数据信号也有,屏幕刷白也正常,就是图像信息不在屏幕上显示,就在DQBUF那卡住了
回复 支持 反对

使用道具 举报

8

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2022-4-29
在线时间
43 小时
 楼主| 发表于 2022-10-26 15:57:35 | 显示全部楼层
爱跑步的雯雯 发表于 2022-10-25 10:02
怪,今天用示波器测了,pclk和xclk都正常,行信号场信号也正常,数据信号也有,屏幕刷白也正常,就是图像 ...

我在串口里使用cat /proc/interrupts查询发现:
只有一个dma控制器发送中断
48:       7570          0     GIC-0  61 Level     xilinx-dma-controller
49:          0          0     GIC-0  62 Level        xilinx-dma-controller
50:          0          0     GIC-0  63 Level        xilinx_vtc
54:          2          0  zynq-gpio  55 Edge      gt9xx
在pl.dtsi设备树里查看:只有mm2s通道可以发送中断,ss2m不能接受
lcd_vdma: dma@43000000 {
                        #dma-cells = <1>;
                        clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axis_mm2s_aclk", "m_axi_s2mm_aclk", "s_axis_s2mm_aclk";
                        clocks = <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>, <&clkc 15>;
                        compatible = "xlnx,axi-vdma-6.3", "xlnx,axi-vdma-1.00.a";
                        interrupt-names = "mm2s_introut", "s2mm_introut";
                        interrupt-parent = <&intc>;
                        interrupts = <0 29 4 0 30 4>;
                        reg = <0x43000000 0x10000>;
                        xlnx,addrwidth = <0x20>;
                        xlnx,flush-fsync = <0x1>;
                        xlnx,num-fstores = <0x4>;
                        dma-channel@43000000 {
                                compatible = "xlnx,axi-vdma-mm2s-channel";
                                interrupts = <0 29 4>;
                                xlnx,datawidth = <0x18>;
                                xlnx,device-id = <0x0>;
                                xlnx,genlock-mode ;
                                xlnx,include-dre ;
                        };
                        dma-channel@43000030 {
                                compatible = "xlnx,axi-vdma-s2mm-channel";
                                interrupts = <0 30 4>;
                                xlnx,datawidth = <0x18>;
                                xlnx,device-id = <0x0>;
                                xlnx,genlock-mode ;
                                xlnx,include-dre ;
                        };
回复 支持 反对

使用道具 举报

8

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2022-4-29
在线时间
43 小时
 楼主| 发表于 2022-10-30 16:55:07 | 显示全部楼层
爱跑步的雯雯 发表于 2022-10-28 10:29
问题已经解决了,用了楼上大佬的代码,稍作改动吧,
1。我最开始在vivdo工程里的vdma帧缓存设置的是1,( ...

对第三个提醒,我的摄像头没有自带的时钟晶振,所以用正点原子的排线的时候,可能是系统时钟和像素时钟的两根线考的太近,导致显示有问题,用正点原子的摄像头就没有问题,后来我换用杜邦线来连摄像头的时候效果就好很多了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 09:04

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表