freeRTOS Camera Support

Init:

void app_camera_main () //app_camera.c

1. setup GPIO 13, 14 s pullup inut

2. setup CONFIG_LED_LEDC_PIN output, 1000Hz by calling ledc_timer_config

3. configure Camera port by calling esp_camera_init(), set xclk=20MHz, fb=2, jpeg

esp_camera_init() //components/esp32-camera/driver/camera.c 
camera_probe() //find slave address
camera_enable_out_clock(); //enable output clock 
 SCCB_Init() //I2C or TWI driver
 Set Power down line. pull 10ms high, 10ms low.
 Set Reset line, 10ms low, 10ms high
 if OV2640 software reset: SCCB_Write(0x30, FF 01, 12 80)
 SCCB_Probe() //slave_addr=00~0x7F 查slave地址, 写地址直到回复OK. 每次等1 sec!!若用twi,每次等10ms. 
 read product ID, REG_PID.REG_VER, REG16_CHIDH, REG16_CHIDL, 决定camera_model
 if (pid) call sensor's init function ovxxxx_init()
camera_model = CAMERA_OV7725 not support JPEG
             = CAMERA_OV2640 OK
             = CAMERA_OV3660 OK
             
 camera_init()
{
   s_state->width
s_state->height
fb_size = w*h*(pix_format)
s_state->sampling_mode = SM_0A00_0B00;
      s_state->dma_filter = &dma_filter_xxx_highspeed;
if JPEG, "JPEG format is only supported for ov2640 and ov3660"
use dma_filter_jpeg()
i2s_init() //i2s_isr 收I2S data 
dma_desc_init()
camera_fb_init(fb_count)
  s_state->fb -> first fb_header->buf : frame buffer; fb->next = next rame buffer.
s_state->data_ready = xQueueCreate(16)
s_state->fb_in = xQueueCreate(s_state->config.fb_count, sizeof(camera_fb_t *));
      s_state->fb_out = xQueueCreate(1, sizeof(camera_fb_t *));
xTaskCreate(&dma_filter_task, "dma_filter", 4096, NULL, 10, &s_state->dma_filter_task))
gpio_isr_handler_add(s_state->config.pin_vsync, &vsync_isr, NULL);
}

4. configure sensor , calling esp_camera_sensor_get(), set frame size 320x240

How to get camera buffer

camera_fb_t* esp_camera_fb_get()
if (fb_count == 1) use xSemaphoreTake(s_state->frame_ready, 4000ms) 等4秒或semaphor release.
if (fb_count > 1)xQueueReceive(s_state->fb_out, 4000ms) 等fb_out 送来fb

How to return camera frame/

void esp_camera_fb_return(camera_fb_t * fb)
xQueueSend(s_state->fb_in, &fb, portMAX_DELAY);
How frame is captured?
dma_filter_task() //camera.c
{
if(xQueueReceive(s_state->data_ready, &buf_idx, portMAX_DELAY) == pdTRUE) {
if (buf_idx == SIZE_MAX) {
//this is the end of the frame
dma_finish_frame();
–> camera_fb_done()
if fb_count == 1 xSemaphoreGive(s_state->frame_ready);
else {
if(xQueueIsQueueFullFromISR(s_state->fb_out) {检查fb_out queue是否没来拿
拿走清掉旧的 把新的fb 放入fb_out
} else {
已经拿走了 把新的fb 放入 fb_out
}
}
while fb_in 有fb, 把 fb_in 的fb 拿 出来
s_state->fb = next fb

        } else {
            dma_filter_buffer(buf_idx);//第一次设置fb header. copy s_state->dma_buf[buf_idx] to fb->buf
        }
}

static void IRAM_ATTR vsync_isr(void* arg)
{ //完成一个frame
signal_dma_buf_received(&need_yield) //开始或结速 准备 DMA descriptor
}
static void IRAM_ATTR i2s_isr(void* arg)
{ //完成一次DMA
signal_dma_buf_received(&need_yield);
}
signal_dma_buf_received(&need_yield) {
xQueueSendFromISR(s_state->data_ready,&dma_desc_filled) 一个DMA 完成, 把目前DMA descriptor 号传给 queue
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值