Skip to contentSkip to conversation

soc-camera: current stack

DISCUSSION Agustin 3 participants 5 messages Dec 19, 2008 – Dec 22, 2008 1 message not in the archive Media (V4L/DVB)

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Agustin

author
#1 lore raw

Hi Guennadi,

Quoted 4 lines · Guennadi Liakhovetski

... My current stack is at

http://gross-embedded.homelinux.org/~lyakh/v4l-20081217/
...

I was about to try this stack on my Phytec i.MX31 system when I found there is no mx3_camera driver in it. Too bad!

I still haven't been able to retrieve a VGA sized dummy image from my FPGA on a Phytec dev-kit, stuck at "select timeout". I was hoping that this new stack could have some important stuff that your previous (from November) didn't.

I can't tell if I am having a hardware issue... Do you have any modification or fix in your Phytec i.MX31 dev-kit?

Thanks & regards,
--Agustín.

--
Agustin Ferrin Pozuelo
Embedded Systems Consultant
http://embedded.ferrin.org/

--
video4linux-list mailing list
Unsubscribe mailto:[email protected]?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list

#2 lore raw
Quoted 10 lines · Agustin

Hi Guennadi,

Quoted 4 lines · Guennadi Liakhovetski

... My current stack is at

http://gross-embedded.homelinux.org/~lyakh/v4l-20081217/
...

I was about to try this stack on my Phytec i.MX31 system when I found there is no mx3_camera driver in it. Too bad!

Well, sorry, no, i.MX31 is not in that patchset. It depends on other drivers, that are still in review, and this patchset represents what I'm pushing upstream _now_.

Quoted 7 lines

I still haven't been able to retrieve a VGA sized dummy image from my FPGA on a Phytec dev-kit, stuck at "select timeout". I was hoping that this new stack could have some important stuff that your previous (from November) didn't.

I can't tell if I am having a hardware issue... Do you have any modification or fix in your Phytec i.MX31 dev-kit?

Nothing ground-breaking. The snapshot I uploaded for you in November worked for me and it should work for you too. By "select timeout" I suspect you're not getting any interrupts at all, right? That's your first task - to get your setup generate at least one interrupt, then it'll be easier:-) You say "haven't been able to retrieve a VGA sized dummy image"
- does it mean you can retrieve other (smaller) sizes? If not, I would check signalling. Check the master clock, whether the pixel clock is generated. You're using master mode, right? If both clocks are ok, check syncs. You said before your logic analyser showed a plausible picture... Are you doing 8 or 16 bits? Check output of /proc/interrupts _while_ a task is waiting in select, you should be getting irq #167 - one per frame.

Good luck
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer

--
video4linux-list mailing list
Unsubscribe mailto:[email protected]?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list

author
#3 lore raw

Success with mx3_camera, panic at mx3_cam_dma_done

Hi again,

Quoted 9 lines · Guennadi Liakhovetski
Quoted 3 lines · Agustin

I can't tell if I am having a hardware issue...
Do you have any modification or fix in your
Phytec i.MX31 dev-kit?

Nothing ground-breaking. The snapshot I uploaded for you in November worked for me and it should work for you too. By "select timeout" I suspect you're not getting any interrupts at all, right?

Indeed.

Quoted 5 lines

That's your first task - to get your setup generate at least one interrupt, then it'll be easier:-) You say "haven't been able to retrieve a VGA sized dummy image" - does it mean you can retrieve other (smaller) sizes?

Nope!

Quoted 5 lines

If not, I would check signalling. Check the master clock, whether the pixel clock is generated. You're using master mode, right? If both clocks are ok, check syncs. You said before your logic analyser showed a plausible picture...

Indeed I could see those signals quite fine, all the way to devkit connector. Later on it is a pain to attach probes...

I tried swapping the devkit for an older one, and voila! I got my dearest first image right away.

It might be that the connector was not pushed to the end, or it might be some issue with the new devkit Phytec sent me last month, it is quite different, has some manual rework, and it is missing the white ink layer so I can't tell jumpers apart.

Quoted 3 lines

Are you doing 8 or 16 bits? Check output of /proc/interrupts _while_ a task is waiting in select, you should be getting irq #167 - one per frame.

Yeah but fortunately I didn't have to go that far debugging.

However, I still managed to make mx3_camera driver crash. It is probably a race condition around end-of-capture event, because I can retrieve an arbitrary number of frames without issues, then when application exits the dma gets triggered again and mx3_cam_dma_done() fails, probably trying to access an already freed buffer. If I only use one buffer, there are no issues either, I think it is because mx3_cam_dma_done() anticipates the lack of buffers each time. However, I might be loosing frames in this case.

I attach a log of the crash, along with the still capture test application I am using (a simplification of the 'official' V4L2 example). 'Sixcam' is the name of my project, BTW.

I will try to provide a fix as soon as I get off this Christmas work crunch I am having... But now that I got the data through to userspace (and the prototype boards apparently working) my next weeks of work promise some happy results.

Thanks & regards,
--Agustín.

--
Agustin Ferrin Pozuelo
Embedded Systems Consultant
http://embedded.ferrin.org/
Tel. +34 610502587

sixcam_module_init():406
sixcam: TRIGGER High.
camera 0-0: MX3 Camera driver attached to camera 0 sixcam_video_probe():284
camera 0-0: MX3 Camera driver detached from camera 0 camera 0-0: MX3 Camera driver attached to camera 0 sixcam_set_fmt():244
rect->width=640 rect->height=480.
sixcam: camera #0 reg 5h was 0, set to 25.
sixcam: camera #0 reg 6h was 0, set to 9.
sixcam: camera #0 reg 2h was 0, set to 0.
sixcam: camera #0 reg 1h was 0, set to 0.
sixcam: camera #0 reg 4h was 0, set to 639.
sixcam: camera #0 reg 3h was 0, set to 479.
sixcam: camera #0 reg 9h was 0, set to 489. sixcam_query_bus_param():229 sixcam_try_fmt():266
icd->width=640 icd->height=480. fmt.pix.width=640 fmt.pix.height=480. sixcam_set_fmt():244
rect->width=640 rect->height=480.
sixcam: camera #0 reg 5h was 25, set to 25.
sixcam: camera #0 reg 6h was 9, set to 9.
sixcam: camera #0 reg 2h was 0, set to 0.
sixcam: camera #0 reg 1h was 0, set to 0.
sixcam: camera #0 reg 4h was 639, set to 639.
sixcam: camera #0 reg 3h was 479, set to 479.
sixcam: camera #0 reg 9h was 489, set to 489. sixcam_query_bus_param():229 sixcam_set_bus_param():218
sixcam: sixcam_bus_params <= 0x2215. sixcam_start_capture():196
sixcam: TRIGGER High.
sixcam: TRIGGER Low. sixcam_stop_capture():208

Unable to handle kernel NULL pointer dereference at virtual address 0000002c
pgd = c0004000
[0000002c] *pgd=00000000
Internal error: Oops: 17 [#1] PREEMPT
Modules linked in: sixcam mx3_camera soc_camera videobuf_dma_contig videobuf_core
CPU: 0    Not tainted  (2.6.28-rc3-next-20081105gato-03042-g25a4055-dirty #40)
PC is at mx3_cam_dma_done+0x28/0x108 [mx3_camera]
LR is at idmac_interrupt+0x174/0x350
pc : [<bf0134e8>]    lr : [<c0192630>]    psr: a0000113

sp : c0329e48 ip : 0000002c fp : c0329e64
r10: 00000007 r9 : c0363860 r8 : c88b43c0
r7 : c0328000 r6 : c88a6000 r5 : c88a6030 r4 : 00000000 r3 : 00200200 r2 : 00000004 r1 : 00000080 r0 : c88b43c0
Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: 00c5387f Table: 861b4000 DAC: 00000017 Process swapper (pid: 0, stack limit = 0xc0328260)

Stack: (0xc0329e48 to 0xc032a000)

9e40: c0329e64 c0363700 00000001 c61d696c c0329eac c0329e68
9e60: c0192630 bf0134cc 14dcb184 00000000 00000003 c0354900 c0329e94 c0363870 9e80: c00903b8 c6243de0 00000000 00000000 000000a7 c0342780 c0328000 8001e0b8 9ea0: c0329ecc c0329eb0 c0060a60 c01924c8 c0328000 c033275c c6243de0 000000a7 9ec0: c0329eec c0329ed0 c0062bb0 c0060a30 00000000 c0342744 c0330034 c0362b90 9ee0: c0329f14 c0329ef0 c019075c c0062b14 c0329f14 0000002a c035f750 00000000 9f00: 00000002 00000001 c0329f34 c0329f18 c0022060 c01906cc c0329f44 0000001f 9f20: fc400000 002a0000 c0329f8c c0329f38 c0022a6c c002200c c034d418 00000000 9f40: 00000000 c0328000 c0023e7c c0328000 c034cc68 c032bcd4 8001e0ec 4107b364 9f60: 8001e0b8 c0329f8c c0329f90 c0329f80 c0023eb8 c0023ebc 60000013 ffffffff 9f80: c0329fac c0329f90 c0023da4 c0023e88 c032bcd4 c0328000 c034c7f4 c034c7e4 9fa0: c0329fc4 c0329fb0 c0287a20 c0023d7c c034c7f4 c0354c48 c0329ff4 c0329fc8 9fc0: c0008a08 c02879b8 c00083ac 00000000 00000000 c001fd58 00000000 00c5387d 9fe0: c034ccd4 c002015c 00000000 c0329ff8 80008034 c0008820 00000000 00000000

Backtrace: 
[<bf0134c0>] (mx3_cam_dma_done+0x0/0x108 [mx3_camera]) from [<c0192630>] (idmac_interrupt+0x174/0x350)
 r6:c61d696c r5:00000001 r4:c0363700
[<c01924bc>] (idmac_interrupt+0x0/0x350) from [<c0060a60>] (handle_IRQ_event+0x3c/0x74)
[<c0060a24>] (handle_IRQ_event+0x0/0x74) from [<c0062bb0>] (handle_level_irq+0xa8/0x150)
 r7:000000a7 r6:c6243de0 r5:c033275c r4:c0328000
[<c0062b08>] (handle_level_irq+0x0/0x150) from [<c019075c>] (ipu_irq_fn+0x9c/0xd0)
 r7:c0362b90 r6:c0330034 r5:c0342744 r4:00000000
[<c01906c0>] (ipu_irq_fn+0x0/0xd0) from [<c0022060>] (asm_do_IRQ+0x60/0x8c)
 r8:00000001 r7:00000002 r6:00000000 r5:c035f750 r4:0000002a
[<c0022000>] (asm_do_IRQ+0x0/0x8c) from [<c0022a6c>] (__irq_svc+0x4c/0x98)
Exception stack(0xc0329f38 to 0xc0329f80)

9f20: c034d418 00000000
9f40: 00000000 c0328000 c0023e7c c0328000 c034cc68 c032bcd4 8001e0ec 4107b364 9f60: 8001e0b8 c0329f8c c0329f90 c0329f80 c0023eb8 c0023ebc 60000013 ffffffff
r6:002a0000 r5:fc400000 r4:0000001f
[<c0023e7c>] (default_idle+0x0/0x48) from [<c0023da4>] (cpu_idle+0x34/0x68) [<c0023d70>] (cpu_idle+0x0/0x68) from [<c0287a20>] (rest_init+0x74/0x88)
r6:c034c7e4 r5:c034c7f4 r4:c0328000
[<c02879ac>] (rest_init+0x0/0x88) from [<c0008a08>] (start_kernel+0x1f4/0x270)
r4:c0354c48
[<c0008814>] (start_kernel+0x0/0x270) from [<80008034>] (0x80008034)
r6:c002015c r5:c034ccd4 r4:00c5387d

Code: e59f30e0 e2456030 e596402c e284c02c (e594102c) 
Kernel panic - not syncing: Fatal exception in interrupt

/*
* Based on V4L2 video capture example
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#include <asm/types.h> /* for videodev2.h */
#include <linux/videodev2.h>

#include "sixcam.h"

#define zerofill(x) memset(&(x),0,sizeof(x))

struct buffer {
    void * start;
    size_t length;
};

static char * dev_name = "/dev/v4l/video0";
static int fd = -1;
struct buffer * buffers = NULL;
static unsigned int n_buffers = 0;

static void errno_exit(const char * s)

{
    fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
    exit(EXIT_FAILURE);
}

static int xioctl(int fd, int request, void *arg)

{
    int r;

    do r = ioctl(fd, request, arg);
    while(-1 == r && EINTR == errno);

    return r;
}

static void process_image(const void *p)

{
    printf("Got one image.\n");
}

static int read_frame(void)

{
    struct v4l2_buffer buf;

    zerofill(buf);
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;

    if( -1 == xioctl(fd, VIDIOC_DQBUF, &buf))
    {
        switch( errno) {
        case EAGAIN:
            fprintf(stderr, "VIDIOC_DQBUF -EAGAIN.\n");
            return 0;

        case EIO:
            /* Could ignore EIO, see spec. */

            /* fall through */

        default:
            errno_exit("VIDIOC_DQBUF");
        }
    }

    assert(buf.index < n_buffers);

    process_image(buffers[buf.index].start);

    if(-1 == xioctl(fd, VIDIOC_QBUF, &buf))
        errno_exit("VIDIOC_QBUF");

    return 1;
}

static void open_device(void)

{
    struct stat st; 

    if(-1 == stat(dev_name, &st)) {
        fprintf(stderr, "Cannot identify '%s': %d, %s\n",
             dev_name, errno, strerror(errno));
        exit(EXIT_FAILURE);
    }

    if(!S_ISCHR(st.st_mode)) {
        fprintf(stderr, "%s is no device\n", dev_name);
        exit(EXIT_FAILURE);
    }

    fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);

    if(-1 == fd) {
        fprintf(stderr, "Cannot open '%s': %d, %s\n",
             dev_name, errno, strerror(errno));
        exit(EXIT_FAILURE);
    }
}

static void init_mmap(void)

{
    struct v4l2_requestbuffers req;
    int i;

    zerofill(req);

    req.count               = 2;
    req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory              = V4L2_MEMORY_MMAP;

    if(-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
        if(EINVAL == errno) {
            fprintf(stderr, "%s does not support "
                 "memory mapping\n", dev_name);
            exit(EXIT_FAILURE);
        } else {
            errno_exit("VIDIOC_REQBUFS");
        }
    }

    printf("Got %i buffers\n", req.count);
    if(req.count < 1) {
        fprintf(stderr, "Insufficient buffer memory on %s\n", dev_name);
        exit(EXIT_FAILURE);
    }

    buffers = calloc(req.count, sizeof(*buffers));

    if(!buffers) {
        fprintf(stderr, "Out of memory\n");
        exit(EXIT_FAILURE);
    }

    for(i = 0; i < req.count; ++i) {
        struct v4l2_buffer buf;

        zerofill(buf);

        buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory      = V4L2_MEMORY_MMAP;
        buf.index       = i;

        if(-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
            errno_exit("VIDIOC_QUERYBUF");

        printf("m-mapping buffer #%i at %p, size 0x%X...\n", i, buf.m.offset
                , buf.length);
        buffers[i].length = buf.length;
        buffers[i].start =
            mmap(NULL /* start anywhere */,
                  buf.length,
                  PROT_READ | PROT_WRITE        /* recommended */,
                  MAP_SHARED                    /* recommended */,
                  fd, buf.m.offset);

        if(MAP_FAILED == buffers[i].start)
            errno_exit("mmap");
    }
    n_buffers = i;
}

static void init_device(void)

{
    struct v4l2_capability cap;
    struct v4l2_cropcap cropcap;
    struct v4l2_crop crop;
    struct v4l2_format fmt;
    unsigned int min;

    if(-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
        if(EINVAL == errno) {
            fprintf(stderr, "%s is no V4L2 device\n",
                 dev_name);
            exit(EXIT_FAILURE);
        } else {
            errno_exit("VIDIOC_QUERYCAP");
        }
    }

    if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
        fprintf(stderr, "%s is no video capture device\n",
             dev_name);
        exit(EXIT_FAILURE);
    }

    if(!(cap.capabilities & V4L2_CAP_STREAMING)) {
        fprintf(stderr, "%s does not support streaming i/o\n",
             dev_name);
        exit(EXIT_FAILURE);
    }

    /* Select video input, video standard and tune here. */

    zerofill(cropcap);

    cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    if(0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap)) {
        crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        crop.c = cropcap.defrect; /* reset to default */

        if(-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) {
            switch(errno) {
            case EINVAL:
                /* Cropping not supported. */
                break;
            default:
                /* Errors ignored. */
                break;
            }
        }
    } else {        
        /* Errors ignored. */
    }


    zerofill(fmt);

    fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width       = 640; 
    fmt.fmt.pix.height      = 480;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
    fmt.fmt.pix.field       = V4L2_FIELD_ANY;

    if(-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
        errno_exit("VIDIOC_S_FMT");

    /* Note VIDIOC_S_FMT may change width and height. */
    printf("VIDIOC_S_FMT returned width %i and height %i.\n"
        , fmt.fmt.pix.width, fmt.fmt.pix.height);

    init_mmap();
}

static void start_capturing(void)

{
    unsigned int i;
    enum v4l2_buf_type type;

    for(i = 0; i < n_buffers; i++)
    {
        struct v4l2_buffer buf;

        zerofill(buf);

        buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory      = V4L2_MEMORY_MMAP;
        buf.index       = i;

        /* Enqueue buffer */
        if(-1 == xioctl(fd, VIDIOC_QBUF, &buf))
            errno_exit("VIDIOC_QBUF");
    }
    
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    if(-1 == xioctl(fd, VIDIOC_STREAMON, &type))
        errno_exit("VIDIOC_STREAMON");
}

static void mainloop(void)

{
    unsigned int count;

    count = 7;

    while(count-- > 0) {
        for(;;) {
            fd_set fds;
            struct timeval tv;
            int r;

            FD_ZERO(&fds);
            FD_SET(fd, &fds);

            /* Timeout. */
            tv.tv_sec = 10;
            tv.tv_usec = 0;

            r = select(fd + 1, &fds, NULL, NULL, &tv);

            if(-1 == r) {
                if(EINTR == errno)
                    continue;

                errno_exit("select");
            }

            if(0 == r) {
                fprintf(stderr, "Select timeout.\n");
                exit(EXIT_FAILURE);
            }

            if(read_frame())
                break;
    
            /* EAGAIN - continue select loop. */
        }
    }
}

static void stop_capturing(void)

{
    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    if(-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))
        errno_exit("VIDIOC_STREAMOFF");
}

static void uninit_device(void)

{
    unsigned int i;

    for(i = 0; i < n_buffers; ++i)
        if(-1 == munmap(buffers[i].start, buffers[i].length))
            errno_exit("munmap");

    free(buffers);
}

static void close_device(void)

{
    if(-1 == close(fd))
        errno_exit("close");

    fd = -1;
}

int main(int argc, char ** argv)

{
    if( argc > 1 ) dev_name = argv[1];
    open_device();
    init_device();
    start_capturing();
    mainloop();
    stop_capturing();
    uninit_device();
    close_device();

    return 0;
}

--
video4linux-list mailing list
Unsubscribe mailto:[email protected]?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list

#4 lore raw
In reply to Agustin

Hi Agustin,

Quoted 2 lines · Agustin

I was about to try this stack on my Phytec i.MX31 system when I found there is no mx3_camera driver in it. Too bad!

We are working hard on a mainline quality patch series for the phyCORE-i.MX31 and a bunch of these patches already went into the maintainer trees for the 2.6.29 merge window.

One of the next central components is the pmic driver, which hasn't reached mainline quality yet. If that's finished, camera drivers will surely be in a better situation wrt. mainline.

rsc

Signature · 9 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

--
video4linux-list mailing list
Unsubscribe mailto:[email protected]?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
#5 lore raw
Quoted 6 lines · Robert Schwebel

Hi Agustin,

Quoted 2 lines · Agustin

I was about to try this stack on my Phytec i.MX31 system when I found there is no mx3_camera driver in it. Too bad!

Quoted 7 lines

We are working hard on a mainline quality patch series for the phyCORE-i.MX31 and a bunch of these patches already went into the maintainer trees for the 2.6.29 merge window.

One of the next central components is the pmic driver, which hasn't reached mainline quality yet. If that's finished, camera drivers will surely be in a better situation wrt. mainline.

pmic is good, although, I don't remember it affecting the camera driver _directly_, so, I think, it is perfectly possible to have a good camera driver with no PMIC support. As you know, PMIC is a separate IC, and shall be handled by a separate (regulator?) driver. As you write - your PMIC driver will be relevant for the phyCORE board, and not necessarily so for other designs. So, I don't think this affects the chances of the imx31 camera driver to be included in the mainline.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer

--
video4linux-list mailing list
Unsubscribe mailto:[email protected]?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list