0

I am working on a university project to build a small IOT camera. I am using the 32F746GDISCOVERY board with the STM32F746NG MCU along with the ov2460 image sensor from WaveShare, and the B-CAMS-OMV board as an adaptor.

My code is based on an example for the STMF7508 Disco board, however, I have switched out the ov9655 BSP used in the example for the ov2460 BSP provided by STM.

Initially, I am attempting to display a continuous video feed on the LCD screen using the following data path:

Image Sensor → DCMI → DMA2 → Camera Frame buffer → DMA2 → LCD Frame buffer

I am able to communicate with the image sensor through I2C and successfully read the ID. When the image sensor is initialised, I am receiving frame event callbacks, however, no data is being written to the camera frame buffer. The DMA transfer between the camera frame buffer and the LCD frame buffer seems to be working fine.

I am pretty stumped as to why no data is being written to the camera Frame buffer and I have been working solidly on this problem over the last few weeks.

It looks like there is an issue with the DCMI DMA transfer. There could also be a problem in the configuration of the image sensor, however, this seems unlikely as I am receiving frame callbacks.

I was wondering if anyone had any experience with image sensors and STM32 MCUs and might be able to point me in the right direction.

I have attached my code below along with the CubeMX configurations I am using for DCMI and DMA2. The photo below shows a white screen on the LCD where the camera feed should be displayed as the camera frame buffer is memset to 255 upon initialisation.

camera.h

#ifndef INC_CAMERA_H_
#define INC_CAMERA_H_

#include "stm32f7xx_hal.h"
#include "stm32746g_discovery.h"
#include "stm32746g_discovery_sdram.h"
#include "stm32746g_discovery_camera.h"
#include "stdio.h"
#include "stdlib.h"
#include "LCD.h"
#include "string.h"
//#include "ov5460.h"
//#include "../../Drivers/BSP/Components/ov5640/ov5640.h"
//#include "../Drivers/BSP/Components/ov9665/ov9665.h"


#define CAMERA_FRAME_BUFFER               0xC0260000
//#define CAMERA_FRAME_BUFFER               0x60000000
#define LCD_FRAME_BUFFER                  0xC0130000

//#define CAMERA_I2C_ADDRESS (uint16_t)0x60
void I2C_CameraTest(void);
//void cameraTestLoop(void);
void statusTest(void);
void initialiseCapture(void);
//void DCMI_GetCaptureMode(void);
//void runCamera(void);
void BSP_CAMERA_LineEventCallback(void);
void LCD_LL_ConvertLineToARGB8888(void *pSrc, void *pDst);

#endif /* INC_CAMERA_H_ */

camera.c

#include "camera.h"



DMA2D_HandleTypeDef hdma2d_eval;
static TS_StateTypeDef  TS_State;

uint32_t  i, previous_mode = CONTINOUS_MODE;
uint32_t  *ptrLcd;
uint8_t status = CAMERA_OK;


uint8_t *cam_fb;
uint32_t cam_fb_size;




void LCD_init(void) {

BSP_LCD_Init();
BSP_TS_Init(BSP_LCD_GetXSize(), BSP_LCD_GetYSize());

    uint32_t  *ptrLcd;


      /* Init LCD screen buffer */
      ptrLcd = (uint32_t*)(LCD_FRAME_BUFFER);
      for (int i=0; i<(BSP_LCD_GetXSize()*BSP_LCD_GetYSize()); i++)
      {
        ptrLcd[i]=0;
      }

      BSP_LCD_LayerDefaultInit(LTDC_ACTIVE_LAYER, LCD_FRAME_BUFFER);
      //BSP_LCD_LayerRgb565Init(LTDC_ACTIVE_LAYER, LCD_FRAME_BUFFER);

      /* Set LCD Foreground Layer  */
      BSP_LCD_SelectLayer(LTDC_ACTIVE_LAYER);

      BSP_LCD_SetFont(&LCD_DEFAULT_FONT);

      /* Clear the LCD */
      BSP_LCD_Clear(LCD_COLOR_BLACK);
      BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
      BSP_LCD_FillRect(340, 80, 80, 30);
      BSP_LCD_FillRect(340, 150, 80, 30);
      BSP_LCD_DrawRect(8, 8, 322, 242);
      BSP_LCD_DrawRect(9, 9, 321, 241);
      BSP_LCD_SetFont(&Font12);
      BSP_LCD_SetTextColor(LCD_COLOR_WHITE);
      BSP_LCD_SetBackColor(LCD_COLOR_BLUE);
      BSP_LCD_DisplayStringAt(345, 90, (uint8_t *)"CONTINUOUS", LEFT_MODE);
      BSP_LCD_DisplayStringAt(345, 160, (uint8_t *)" SNAPSHOT", LEFT_MODE);
      BSP_LCD_SetFont(&LCD_DEFAULT_FONT);

      printf("done screen\n");
}

void I2C_CameraTest(void) {
    uint16_t CameraID = 0;
    printf("\nHello World\n");
    //uint16_t ov5640_ReadID(uint16_t DeviceAddr)
    //CameraID = ov5640_ReadID(CAMERA_I2C_ADDRESS);
    CameraID = ov2640_ReadID(CAMERA_I2C_ADDRESS);
    printf("\n%i\n", CameraID);


}

void cameraTestLoop(void) {
    while(1) {
        I2C_CameraTest();
        HAL_Delay(500);
    }
}


void initialiseCapture(void) {
status = BSP_CAMERA_Init(RESOLUTION_R320x240);
if(status != CAMERA_OK)
{
  BSP_LCD_SetFont(&Font16);
  BSP_LCD_SetTextColor(LCD_COLOR_WHITE);
  BSP_LCD_FillRect(10, 10, 320, 240);
  BSP_LCD_SetTextColor(LCD_COLOR_RED);
  BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
  BSP_LCD_DisplayStringAt(20, 100, (uint8_t *)"CAMERA sensor is unpluged", LEFT_MODE);
  BSP_LCD_DisplayStringAt(20, 120, (uint8_t *)"Plug the OV2640 sensor   ", LEFT_MODE);
  BSP_LCD_DisplayStringAt(20, 140, (uint8_t *)"on P1 camera connector   ", LEFT_MODE);
  BSP_LCD_DisplayStringAt(20, 160, (uint8_t *)"And restart the program  ", LEFT_MODE);
}
else
{

//  cam_fb_size = 320*240*2;            // Resolution * color depth; RGB565=16bit=2byte
//
//  cam_fb = (uint8_t *) malloc(cam_fb_size);

  memset(CAMERA_FRAME_BUFFER, 255, cam_fb_size);

  BSP_CAMERA_Init(RESOLUTION_R320x240);
  BSP_CAMERA_ContinuousStart((uint8_t *)CAMERA_FRAME_BUFFER);

}
}



void BSP_CAMERA_LineEventCallback(void)
{
  static uint32_t tmp, tmp2, counter;

  if(240 > counter)
  {
    LCD_LL_ConvertLineToARGB8888((uint32_t *)(CAMERA_FRAME_BUFFER + tmp), (uint32_t *)(LCD_FRAME_BUFFER + 0x4B28 + tmp2));
    tmp  = tmp + 320*sizeof(uint16_t);
    tmp2 = tmp2 + (480) * sizeof(uint32_t);
    counter++;
  }
  else
  {

    tmp = 0;
    tmp2 = 0;
    counter = 0;
  }
}




/**
  * @brief  Converts a line to an ARGB8888 pixel format.
  * @param  pSrc Pointer to source buffer
  * @param  pDst Output color
  * @param  xSize Buffer width
  * @param  ColorMode Input color mode
  * @retval None
  */

//void BSP_CAMERA_FrameEventCallback(void) {}

void LCD_LL_ConvertLineToARGB8888(void *pSrc, void *pDst)
{
  /* Enable DMA2D clock */
  //__HAL_RCC_DMA2D_CLK_ENABLE();

  /* Configure the DMA2D Mode, Color Mode and output offset */
  hdma2d_eval.Init.Mode         = DMA2D_M2M_PFC;
  hdma2d_eval.Init.ColorMode    = DMA2D_OUTPUT_ARGB8888;
  //hdma2d_eval.Init.ColorMode    = DMA2D_OUTPUT_RGB565;
  hdma2d_eval.Init.OutputOffset = 0;

  /* Foreground Configuration */
  hdma2d_eval.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
  hdma2d_eval.LayerCfg[1].InputAlpha = 0xFF;
  hdma2d_eval.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
  hdma2d_eval.LayerCfg[1].InputOffset = 0;

  hdma2d_eval.Instance = DMA2D;

  /* DMA2D Initialization */
  if(HAL_DMA2D_Init(&hdma2d_eval) == HAL_OK)
  {
    if(HAL_DMA2D_ConfigLayer(&hdma2d_eval, 1) == HAL_OK)
    {
      if (HAL_DMA2D_Start(&hdma2d_eval, (uint32_t)pSrc, (uint32_t)pDst, 320, 1) == HAL_OK)
      {
        /* Polling For DMA transfer */
         // printf("polling for DMA transfer!");
        HAL_DMA2D_PollForTransfer(&hdma2d_eval, 10);
      }
    }
  }
  else
  {
    /* FatFs Initialization Error */
      printf("/nFatFs Initialization Error/n");
    while(1);
  }
}

I have atempting to write to the camera frame buffer using the STM BSP Camera Driver, however I am ont recieving any data

ti7
  • 16,375
  • 6
  • 40
  • 68
Sol45
  • 1
  • 1
  • Can you write to the LCD framebuffer manually and see it displayed on the LCD? If you set the camera framebuffer to a known pattern, does it get overwritten when you DMA an image from the camera? (i.e. change the memset(...255) to some other value, and see if it changes.) – pmacfarlane Jan 15 '23 at 21:45
  • @pmacfarlane Thanks for the reply, yes I can. I have played around with setting the camera frame buffer to a couple of different values. When the camera is initialised, these values are then copied across on the frame event callbacks to the LCD frame buffer, with the correct corresponding colours showing up on the LCD screen. The problem is that the camera frame buffer is not getting populated with any new data from the camera after the initial memset. – Sol45 Jan 16 '23 at 14:53

0 Answers0