kendryte / kendryte-standalone-sdk

Standalone SDK for kendryte K210
https://kendryte.com
Apache License 2.0
440 stars 161 forks source link

dvp_get_interrupt(uint32_t interrupt) takes lot of time to return #102

Closed krishnak closed 4 years ago

krishnak commented 4 years ago

I am using a OV7740 camera module, it can deliver 60FPS at VGA and 120FPS at QVGA. I have set the camera module at QVGA@ 60FPS. I am using the following interrupt routine (see below) to capture the image frame. It is an example from your github for standalone-sdk demo dvp_ov.

I am using a counter fpscount to calculate how many times this interrupt fired in a second, I use a timer interrupt every 5 seconds to read this fpscount and then reset fpscount=0.

I get 58FPS - it is very close to 60FPS the camera frame rate - Good.

I move the fpscount++ inside the if block as below

if (dvp_get_interrupt(DVP_STS_FRAME_FINISH))
    {
         fpscount++;
        dvp_clear_interrupt(DVP_STS_FRAME_FINISH);
        g_dvp_finish_flag = 1;
    }

Now the only instruction that is executed extra is dvp_get_interrupt(DVP_STS_FRAME_FINISH)

Now the fps drops to 28.

Please note: No other processing is done on the image frame, it is not even displayed on LCD. When I display it on a LCD the FPS drops to 22.

As you can see the FPS is dropping from 58 to 28, to half the frame rate by one single call to if (dvp_get_interrupt(DVP_STS_FRAME_FINISH)) This can't be right, can you please let me know whether it is a bug or is it something to do with my settings.

I am using the development release of standalone SDK, I am using toolchain 8.2.0 downloaded from github.

Test code

static int sensor_irq(void *ctx)
{
                            fpscount++;
    if (dvp_get_interrupt(DVP_STS_FRAME_FINISH))
    {
        dvp_clear_interrupt(DVP_STS_FRAME_FINISH);
        g_dvp_finish_flag = 1;
    }
    else
    {
        if (g_dvp_finish_flag == 0)
            dvp_start_convert();
        dvp_clear_interrupt(DVP_STS_FRAME_START);
    }

    return 0;
}

int timer_callback(void *ctx) {
    fpsdisplay = *(int *)ctx;
    fpscount = 0;
    fpsdisplay/=5;
    snprintf(debug,15,"FPS=%d",fpsdisplay);
    lcd_draw_string(240,210,debug,WHITE);
    return 0;
}
minux commented 4 years ago

what if sensor_irq triggers twice per frame (one for start and another for finish)?

If you really want to measure the overhead of a call, use the mcycle CSR.

krishnak commented 4 years ago

That is a valid point, to test that I did the following

  1. With 60 FPS setting in the camera register the FPS counter in IRQ was doing 58FPS before the the call to dvp_get_interrupt. 28FPS after the dvp_get_interrupt(DVP_STS_FRAME_FINISH)
  2. With 30FPS setting in the camera register the FPS counter in IRQ was doing 29FPS before the the call to dvp_get_interrupt. 14FPS after the dvp_get_interrupt(DVP_STS_FRAME_FINISH)

If the sensor_irq is getting triggered twice per frame then the else block will produce an equivalent count as that of IF block, yes it does!!. your theory is correct.

But that means the camera module is delivering only half the frames for the setting.

Do you have any register settings for OV7740 that has been tested on OV7740 for greater than 30FPS?

krishnak commented 4 years ago

Just an update, 60FPS QVGA OV7740 - settings needs to be as follows, for any one who wants it. Reference {0x11, 0x00}
{0x55, 0x40}

Clock has to be 24MHz <-- this is the main criteria