2440 摄像头驱动DMA使用问题

sj81   2009-4-27 17:35 楼主
  1. 我使用GPIO模拟IIC初始化OV9652 已经成功(我读出来和写入数值一致)
  2. 并且用应用程序打开摄像头驱动时候,摄像头驱动也已经能够不停的产生中断。
  3. 但是不知道怎么回事,但是图像死活不出现。——我用老的BSP 编译出NK 摄像头可以正常采集,排除了硬件问题。
  4. 但是我把老的BSP的代码搬到5.0 却死活不出图像了。

  5. 我推测是DMA问题,我根据内存映射表修改了一番,可是还是没有结果。

  6. 我的内存映射表

  7. g_oalAddressTable

  8.         DCD     0x80000000, 0x30000000, 64      ; 32 MB DRAM BANK 6
  9.         DCD     0x84000000, 0x10000000, 32      ; nGCS2: PCMCIA/PCCARD
  10.         DCD     0x86000000, 0x18000000, 32      ; 32 MB SROM(SRAM/ROM) BANK 3
  11.         DCD     0x88000000, 0x20000000, 32      ; 32 MB SROM(SRAM/ROM) BANK 4
  12.         DCD     0x8A000000, 0x28000000, 32      ; 32 MB SROM(SRAM/ROM) BANK 5
  13.         DCD     0x8C000000, 0x08000000, 32      ; 32 MB SROM(SRAM/ROM) BANK 1
  14.         DCD     0x90800000, 0x48000000,  1      ; Memory control register
  15.         DCD     0x90900000, 0x49000000,  1      ; USB Host register
  16.         DCD     0x90A00000, 0x4A000000,  1      ; Interrupt Control register
  17.         DCD     0x90B00000, 0x4B000000,  1      ; DMA control register
  18.         DCD     0x90C00000, 0x4C000000,  1      ; Clock & Power register
  19.         DCD     0x90D00000, 0x4D000000,  1      ; LCD control register
  20.         DCD     0x90E00000, 0x4E000000,  1      ; NAND flash control register
  21.         DCD     0x90F00000, 0x4F000000,  1      ; Camera control register
  22.         DCD     0x91000000, 0x50000000,  1      ; UART control register
  23.         DCD     0x91100000, 0x51000000,  1      ; PWM timer register
  24.         DCD     0x91200000, 0x52000000,  1      ; USB device register
  25.         DCD     0x91300000, 0x53000000,  1      ; Watchdog Timer register
  26.         DCD     0x91400000, 0x54000000,  1      ; IIC control register
  27.         DCD     0x91500000, 0x55000000,  1      ; IIS control register
  28.         DCD     0x91600000, 0x56000000,  1      ; I/O Port register
  29.         DCD     0x91700000, 0x57000000,  1      ; RTC control register
  30.         DCD     0x91800000, 0x58000000,  1      ; A/D convert register
  31.         DCD     0x91900000, 0x59000000,  1      ; SPI register
  32.         DCD     0x91A00000, 0x5A000000,  1      ; SD Interface register
  33.         DCD     0x92000000, 0x00000000, 32      ; 32 MB SROM(SRAM/ROM) BANK 0
  34.         DCD     0x94D00000, 0x34000000, 64      ; 64 MB SDRAM BANK 6——我使用的128M SDRAM 非连续方法扩展
  35.         DCD     0x00000000, 0x00000000,  0      ; end of table

  36. 我的config.bib的DMA内存设置。

  37. MEMORY
  38.     NK      80200000  01E00000  RAMIMAGE
  39.     RAM     82000000  02000000  RAM
  40.     FLASH   92000000  00100000  RESERVED

  41. ; Common RAM areas
  42.         AUD_DMA             80002000  00000800  RESERVED
  43.         SDIO_DMA            80010000  00010000  RESERVED
  44.         ARGS                80020800  00000800  RESERVED
  45.         DBGSER_DMA          80022000  00002000  RESERVED
  46.         SER_DMA             80024000  00002000  RESERVED
  47.         IR_DMA              80026000  00002000  RESERVED
  48.         SLEEP               80028000  00002000        RESERVED
  49.         EDBG                80030000  00020000  RESERVED
  50. ;        DISPLAY                    80100000  00100000  RESERVED
  51. ; camera DMA 用于摄像头DMA
  52.         CAMERA                    80050000  00110000  RESERVED
  53.         DISPLAY             84800000  00100000  RESERVED
  54.         CAMERA_CODE            84000000  00800000  RESERVED

  55. 在camera驱动中我是这么定义的
  56. //----------------------------------yl2440 4.2-->5.0 BSP 's set---------------------------
  57. // 1st Ping-pong Address
  58. #define COPIFRAMEBUFFER_A         0x30050000        // 320*240 * 2(RGB 16bit) * 4 frames = 614400 = 0x96000
  59. // 0x30030000 + 0x96000 = 0x300c6000
  60. //#define COPIFRAMEBUFFER_B         0x32000000        // Max buffer size of Port : 0x1c2000 (640*480+640*480*2/4)*4

  61. #define COPIFRAMEBUFFER_B         0x34000000        // 0x32000000-->0x34000000
  62. //要把CODE通道DMA地址放到不影响其他部分运行的RAM地址
  63. #define VIRTUAL_OFFSET                0x7C000000
  64. #define VIRTUAL_ADDR_OFFSET        VIRTUAL_OFFSET // for MPEG4

  65. 中断的线程已经不停的执行,调用了        Display_Cam_Image(0,0, 240, 240, PORT_A);这明明是用来显示的,但是怎么会不出图像呢?

  66. 请做过的前辈指导一下。

回复评论 (59)

咋没有人指点一下呢?是不是我问的问题很雷人呢?

但是我搞了两天,改来改去还是这样。
点赞  2009-4-27 20:43
在内存映射表,里面有
DCD     0x84000000, 0x10000000, 32      ; nGCS2: PCMCIA/PCCARD
这个是片选,现在我在config.bib中CAMERA_CODE        84000000  00800000  RESERVED ,这个是不妥当的吧?明天再改动一下。

欢迎大家给意见!
点赞  2009-4-27 20:56
   我这里有5.0 BSP 中的测试程序,可以保存图片成bmp。但是是公司的有偿资料,...
点赞  2009-4-27 22:12
引用: 引用 3 楼 iwillbeback008 的回复:
  我这里有5.0 BSP 中的测试程序,可以保存图片成bmp。但是是公司的有偿资料,...


你的 5.0 的我估计也有,我买立宇泰的有,但是那个使用的是IIC接口,现在我先在原来的接口上搞好先
点赞  2009-4-27 22:30
引用: 引用 2 楼 gooogleman 的回复:
在内存映射表,里面有
DCD    0x84000000, 0x10000000, 32      ; nGCS2: PCMCIA/PCCARD
这个是片选,现在我在config.bib中CAMERA_CODE        84000000  00800000  RESERVED ,这个是不妥当的吧?明天再改动一下。

欢迎大家给意见!

自己再顶。

我再修改一下先。慢慢尝试,做过、配置过DMA的告诉小弟一声。
点赞  2009-4-28 08:49
dma 的配置、启用、停止很简单,使用物理地址,网卡、硬盘等经常使用...
你贴的东西没用...
点赞  2009-4-28 08:53
调用了    Display_Cam_Image(0,0, 240, 240, PORT_A);
这个函数里面怎么执行的?
我们刚开始做,碰到异常,就直接将buffer数据用串口打印出来。用纯色图片,比如红色的,这样看数据就比较方便。
点赞  2009-4-28 08:58
BTW:OV的芯片有一个内部测试模式,输出固定的颜色条图像信息,不需要外部有实际拍摄的东西。
点赞  2009-4-28 08:59
这篇不MARK了直接加精了。
点赞  2009-4-28 09:00
引用: 引用 7 楼 shuiyan 的回复:
调用了    Display_Cam_Image(0,0, 240, 240, PORT_A);
这个函数里面怎么执行的?
我们刚开始做,碰到异常,就直接将buffer数据用串口打印出来。用纯色图片,比如红色的,这样看数据就比较方便。


shuiyan 牛人这方法不错。首先证明能够采集到数据。我试试。

线程是这样的


  1. //=============================================================================
  2. //                数据处理线程IST
  3. //
  4. //=============================================================================
  5. DWORD CameraCaptureThread(void)
  6. {
  7.         unsigned char tmp=0;
  8.         static unsigned int time,old_time;
  9.         static unsigned int cam_intr;

  10.        
  11.         RETAILMSG(1, (TEXT("CameraCaptureThread funtion run test!!!\r\n")));
  12.         while(1)
  13.         {
  14.                
  15.         RETAILMSG(1, (TEXT(" Camera interrupt.....before WaitForSingleObject\r\n")));
  16.                 WaitForSingleObject(CameraEvent, DisplayTime);
  17.                
  18.         RETAILMSG(1, (TEXT(" Camera interrupt.....after WaitForSingleObject\r\n")));
  19.                                
  20.                 //if( DisplayEnable )
  21.                 {

  22.                         frame_count++;

  23.                         if (s2440INT->rINTSUBMSK & BIT_SUB_CAM_C)
  24.                         {
  25.                                 cam_intr = BIT_SUB_CAM_C;
  26.                                 //RETAILMSG(1,(_T("CAM_C, ts %d\r\n"), GetTickCount()));
  27.                         }
  28.                         else if (s2440INT->rINTSUBMSK & BIT_SUB_CAM_P)
  29.                         {
  30.                                 cam_intr = BIT_SUB_CAM_P;
  31.                                 //RETAILMSG(1,(_T("CAM_P, ts %d\r\n"), GetTickCount()));
  32.                         }
  33.                        

  34.                         //{
  35.                                 //RETAILMSG(1,(TEXT("-------------------\r\n")));
  36.                                 //Display_Cam_Image(64, 64, QCIF_XSIZE, QCIF_YSIZE, PORT_A);
  37.                                 Display_Cam_Image(0,0, 240, 240, PORT_A);——显示图像
  38.                         //}

  39.                         if (cam_intr == BIT_SUB_CAM_C)
  40.                         {
  41.                                 RETAILMSG(1, (TEXT(" Camera interrupt.....BIT_SUB_CAM_C@@@@")));
  42.                                 Buffer_codec_info_update();
  43.                         }

  44.                         if (cam_intr == BIT_SUB_CAM_P)
  45.                         {
  46.                                 RETAILMSG(1, (TEXT(" Camera interrupt.....BIT_SUB_CAM_P@@@@")));
  47.                                 Buffer_preview_info_update();
  48.                         }

  49.                         // add by wogo at 2009.04.25
  50.                         s2440INT->rSUBSRCPND = INTSUB_CAM_P;
  51.                         s2440INT->rSUBSRCPND = INTSUB_CAM_C;
  52.                         s2440INT->rSRCPND = BIT_CAM;

  53.                         if (s2440INT->rINTPND & BIT_CAM)
  54.                         {
  55.                                 s2440INT->rINTPND = BIT_CAM;
  56.                         }
  57.                         s2440INT->rINTSUBMSK &= ~(INTSUB_CAM_P | INTSUB_CAM_C);
  58.                         s2440INT->rINTMSK &= ~BIT_CAM;
  59.                         RETAILMSG(1,(TEXT("::: SYSINTR_CAM    OEMInterruptDone\r\n")));
  60.                                
  61.                        
  62.                 }
  63.         }
  64. }
点赞  2009-4-28 09:13

  1. ///////////////////////////////////////////////////////
  2. //直接显示图像
  3. ///////////////////////////////////////////////////////

  4. void Display_Cam_Image(U32 pos_x, U32 pos_y, U32 size_x, U32 size_y, U8 port)
  5. {
  6.         U8 *buffer_rgb;
  7.         U32 y;
  8.         int temp;
  9.        
  10.         //unsigned short *ptr = (unsigned short *)(FRAMEBUF_BASE+0x5dc0);
  11.        
  12.         static unsigned short transfer_data[QCIF_XSIZE*QCIF_YSIZE];
  13.         static unsigned int time,old_time;
  14.        
  15.         RETAILMSG(1,(_T("Display_Cam_Image()\r\n")));
  16.        
  17.         //if (port)
  18.         {
  19.                 temp = (s2440CAM->rCIPRSTATUS>>26)&3;
  20.                 temp = (temp + 2) % 4;
  21.                
  22.                 switch (temp)
  23.                 {
  24.                 case 0:
  25.                         buffer_rgb = (U8 *)s2440CAM->rCIPRCLRSA1;
  26.                         break;
  27.                 case 1:
  28.                         buffer_rgb = (U8 *)s2440CAM->rCIPRCLRSA2;
  29.                         break;
  30.                 case 2:
  31.                         buffer_rgb = (U8 *)s2440CAM->rCIPRCLRSA3;
  32.                         break;
  33.                 case 3:
  34.                         buffer_rgb = (U8 *)s2440CAM->rCIPRCLRSA4;
  35.                         break;
  36.                 default :
  37.                         buffer_rgb = (U8 *)s2440CAM->rCIPRCLRSA1;
  38.                         break;
  39.                 }
  40.         }
  41.         RETAILMSG(1,(_T("preview buf index = %d\r\n"), temp));

  42. #if (DOTNET_DRIVER)
  43.         SetKMode(TRUE);
  44. #endif
  45.        
  46.         buffer_rgb += VIRTUAL_OFFSET;

  47. //        time = GetTickCount();
  48. //        RETAILMSG(1,(TEXT("+:%d\r\n"),(time - old_time)));


  49. #if 1
  50.         for (y=0;y<(size_y-2);y++) //rgb format
  51.         {
  52.                 //memcpy((void *)(FRAMEBUF_BASE+0x5e00+y*240*2),(void *)buffer_rgb,(QCIF_XSIZE)*2);
  53.                 //memcpy((void *)(FRAMEBUF_BASE+ (240*pos_y + pos_x) + y*240*2),(void *)buffer_rgb,(QCIF_XSIZE)*2);

  54.                 //our LCD vbuff is xsize = 480 ysize = 320 QCIF_XSIZE = 240
  55.                 //copy one line
  56.                 memcpy((void *)(FRAMEBUF_BASE+ (240*2*pos_y + pos_x*2) + y*240*2),
  57.                            (void *)buffer_rgb,
  58.                            (size_x*2));

  59.                 //跳到图像的下一行开始指针
  60.                 buffer_rgb += (QCIF_XSIZE*2);
  61.         }
  62. #endif

  63. #if (DOTNET_DRIVER)
  64.         SetKMode(FALSE);
  65. #endif

  66. //        old_time = GetTickCount();
  67. //        RETAILMSG(1,(TEXT("-:%d\r\n"),(old_time - time)));

  68. }
点赞  2009-4-28 09:15
引用: 引用 6 楼 morris88 的回复:
dma 的配置、启用、停止很简单,使用物理地址,网卡、硬盘等经常使用...
你贴的东西没用...


我觉得就是DMA使用的问题。

我在config.bib这样使用

CAMERA                80050000  00110000  RESERVED ——这个没有问题
——下面两个84000000 以上了就是超过34000000 /64M的 范围,导致DMA不能落在SDRAM映射范围以内了!
    DISPLAY             84800000  00100000  RESERVED——
    CAMERA_CODE        84000000  00800000  RESERVED

虽然我的内存是128M的,但是使用了不连续的映射方法,所以不出问题才怪!

点赞  2009-4-28 09:59
DMA 寄存器里面的源地址和目的地址是物理地址,你不要写成虚拟地址了。
#define COPIFRAMEBUFFER_B     0x34000000 你的内存总共就64M 0x34000000 就是你内存结束的地方了 所以0x34000000后面没有可用的内存了。
还有就是 DMA 所用的内存必须是连续的,所以你DMA的缓冲区最好用RESERVED的内存地址
或者用DMA专用的内存分配函数分配DMA Buffer
点赞  2009-4-28 10:06
现在还没开始搞,51过后写驱动,先关注你的帖子。
点赞  2009-4-28 10:07
uping
点赞  2009-4-28 10:11
引用: 引用 13 楼 xajhuang 的回复:
DMA 寄存器里面的源地址和目的地址是物理地址,你不要写成虚拟地址了。
#define COPIFRAMEBUFFER_B    0x34000000 你的内存总共就64M 0x34000000 就是你内存结束的地方了 所以0x34000000后面没有可用的内存了。
还有就是 DMA 所用的内存必须是连续的,所以你DMA的缓冲区最好用RESERVED的内存地址
或者用DMA专用的内存分配函数分配DMA Buffer


那我在config.bib使用 后面那块内存应该可以吧?

就是这里:DCD     0x94D00000, 0x34000000, 64      ; 64 MB SDRAM BANK 6——我使用的128M SDRAM 非连续方法扩展
点赞  2009-4-28 10:17
NK      80200000  01E00000  RAMIMAGE
    RAM     82000000  02000000  RAM
    FLASH   92000000  00100000  RESERVED
这里只映射了 32M 内存, 你扩展的64M没有映射到RAM中去。
点赞  2009-4-28 10:22
uping
点赞  2009-4-28 10:24
引用: 引用 17 楼 xajhuang 的回复:
NK      80200000  01E00000  RAMIMAGE
    RAM    82000000  02000000  RAM
    FLASH  92000000  00100000  RESERVED
这里只映射了 32M 内存, 你扩展的64M没有映射到RAM中去。


这些也没有映射到RAM啊,照样也可以用呢。
; Common RAM areas
    AUD_DMA             80002000  00000800  RESERVED
    SDIO_DMA            80010000  00010000  RESERVED
    ARGS                80020800  00000800  RESERVED
    DBGSER_DMA          80022000  00002000  RESERVED
    SER_DMA             80024000  00002000  RESERVED
    IR_DMA              80026000  00002000  RESERVED
    SLEEP               80028000  00002000    RESERVED
    EDBG                80030000  00020000  RESERVED
点赞  2009-4-28 10:29
123下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复