FC2カウンター FPGAの部屋 ZedBoard Linux のフレームバッファにカメラ画像を表示11(SDKリモートデバック3)
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

ZedBoard Linux のフレームバッファにカメラ画像を表示11(SDKリモートデバック3)

前回は、GPIOの出力ポートを1に出来て、Camera Controller とBitmap Display Controller のリセットを解除することが出来た。そこまでは出来たのだが、カメラのレジスタ設定が出来なかった。今回はなぜ、カメラのレジスタ設定が出来ないかとその回避策を探ってみた。

SDKリモートデバックでステップ実行を行うと、カメラ設定用のI2CのステータスレジスタRead でReadしたデータが0で止まっていた。ステータスレジスタのRead はI2Cの動作がすべて完了したことを確認しているので、その代わりにusleep(1000); を入れてみたところ、カメラの設定がうまく行って、画像が表示できた。
ZedBoard_Linux_94_130216.jpg

なぜRead出来ないかは分からないが、とりあえず、画像が表示できたので、良かった。これで、カメラの画像をLinuxから読める可能性が出てきた。(今のところRead がおかしいと思っているので、控えめな表現にしましたw)
ソフトウェアのコードは、”RPi Low-level peripherals”の void setup_io(); を使わせていただいていた。前回、ZC702ボードでLinuxからaxi_gpio やMIO のGPIO をアクセスした際にも、 void setup_io(); はブログに載せていなかったが、、”RPi Low-level peripherals”の void setup_io(); のコードが変わっていたので、以前のコードを参照させていただいたことにして、全ソースコードを載せておこうと思う。free() や munmap() もしていない。(注:バグ有りコードです。Readできません)

// cam_disp3_linux.c
// 
// GPIOを1にして、カメラ表示回路を生かし、MT9D111の設定レジスタにRGB565を設定する
//
// 2013/02/11
//

#define XPAR_AXI_GPIO_0_BASEADDR        0x44000000
#define XPAR_AXI_IIC_MT9D111_BASEADDR    0x45000000

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <unistd.h>

#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)

// I/O access

volatile unsigned *setup_io(off_t addr);

volatile unsigned *cam_i2c_control_reg;
volatile unsigned *cam_i2c_status_reg;
volatile unsigned *cam_i2c_tx_fifo;
volatile unsigned *cam_i2c_rx_fifo;

void cam_i2c_init(void) {
    *cam_i2c_control_reg = 0x2// reset tx fifo
    *cam_i2c_control_reg = 0x1// enable i2c
}

void cam_i2x_write_sync(void) {
    // unsigned c;

    // c = *cam_i2c_rx_fifo;
    // while ((c & 0x84) != 0x80)
        // c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
    usleep(1000);
}

void cam_i2c_write(unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
    *cam_i2c_tx_fifo = 0x100 | (device_addr & 0xfe);    // Slave IIC Write Address
    *cam_i2c_tx_fifo = write_addr;
    *cam_i2c_tx_fifo = (write_data >> 8)|0xff;            // first data
    *cam_i2c_tx_fifo = 0x200 | (write_data & 0xff);        // second data
    cam_i2x_write_sync();
}

int main()
{
    volatile unsigned *cam_i2c, *axi_gpio;
    volatile unsigned *axi_gpio_tri;
    
    cam_i2c = setup_io((off_t)XPAR_AXI_IIC_MT9D111_BASEADDR);
    axi_gpio = setup_io((off_t)XPAR_AXI_GPIO_0_BASEADDR);
    
    cam_i2c_control_reg = cam_i2c + 0x40// 0x100番地
    cam_i2c_status_reg = cam_i2c + 0x41// 0x104番地
    cam_i2c_tx_fifo = cam_i2c + 0x42// 0x108番地
    cam_i2c_rx_fifo = cam_i2c + 0x43// 0x10C番地
    
    axi_gpio_tri = axi_gpio + 0x1// 0x4番地
    
    // GPIOに1を書いて、カメラ表示回路を動作させる
    *axi_gpio_tri = 0;    // set output
    *axi_gpio = 0x1;    // output '1'
    
    // CMOS Camera initialize, MT9D111
    cam_i2c_init();
    
    cam_i2c_write(0xba, 0xf00x1);        // IFP page 1 へレジスタ・マップを切り替える
    cam_i2c_write(0xba, 0x970x20);    // RGB Mode, RGB565
    
    return(0);
}

//
// Set up a memory regions to access GPIO
//
volatile unsigned *setup_io(off_t mapped_addr)
// void setup_io()
{
    int  mem_fd;
    char *gpio_mem, *gpio_map;

   /* open /dev/mem */
   if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
      printf("can't open /dev/mem \n");
      exit (-1);
   }

   /* mmap GPIO */

   // Allocate MAP block
   if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
      printf("allocation error \n");
      exit (-1);
   }

   // Make sure pointer is on 4K boundary
   if ((unsigned long)gpio_mem % PAGE_SIZE)
     gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE);

   // Now map it
   gpio_map = (unsigned char *)mmap(
      (caddr_t)gpio_mem,
      BLOCK_SIZE,
      PROT_READ|PROT_WRITE,
      MAP_SHARED|MAP_FIXED,
      mem_fd,
      mapped_addr
   );

   if ((long)gpio_map < 0) {
      printf("mmap error %d\n", (int)gpio_map);
      exit (-1);
   }

   // Always use volatile pointer!
   // gpio = (volatile unsigned *)gpio_map;
   return((volatile unsigned *)gpio_map);

// setup_io


東北学院大学の熊谷先生の”デバイスドライバに頼らないハードウェア操作”は、とってもためになるページなので、この辺を参照しながら、0x1A000000 からのフレームバッファをARMプロセッサから読んでみたい。

(おまけです)
2頭のペンギンが写っていたHDMI画面は、800 x 600 ピクセルのカメラ画像のフレームバッファとして使用しているので、下の写真の様な画面が表示されています。HDMIの画面は、1920 x 1080 のフルHDです。後ろから日の光が差しているので、私の姿が写っています。
ZedBoard_Linux_95_130216.jpg

(2013/02/18:追記)
Linuxが死なないで、正常動作するのはフレームバッファが0x1A000000 スタートに割り当てられる場合と考えられます。確率的にLinuxが死んだりします。詳しくは、”ZedBoard Linux のフレームバッファにカメラ画像を表示13(未完成)”を御覧ください。
  1. 2013年02月16日 05:12 |
  2. ZedBoard
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/2388-f9f82352
この記事にトラックバックする(FC2ブログユーザー)