読者です 読者をやめる 読者になる 読者になる

日曜技術者のメモ

趣味でやった事のメモ書きです。

Simple framebufferを有効にする

Linux QEMU

Linux上からディスプレイに出力する方法を調べているとSimple framebufferという物がある様なのでqemu上で試したメモ。

qemuは前回のqemu2svの環境を流用。

qemu側の変更点

  • hw_if.cからソケット通信を削除して単体で動作する様に修正
  • ベースアドレスの変更
    qemu-2.1.2/hw/arm/xilinx_zynq.c
sysbus_create_simple("hw_if", 0xE1000000, NULL);

kernel側の変更点

  • make menuconfigを実行
    Simple framebuffer supportを有効にする。
    Device Drivers→Graphics support→Support for frame buffer deviceと選択する。
    f:id:ginnyu-tei:20141118225529j:plain

  • device treeに以下を追加

ps7_fb: framebuffer@E1000000 {                                                                
    compatible = "simple-framebuffer";                                                        
    reg = <0xE1000000 (800 * 600 * 2)>;                                                       
    width = <800>;                                                                            
    height = <600>;                                                                           
    stride = <(800 * 2)>;                                                                     
    format = "r5g6b5";                                                                        
};

ひな形は↓にあった。
Documentation/devicetree/bindings/video/simple-framebuffer.txt

qemu起動

起動後にdmesgを実行するとログ内でsimple framebufferが認識しているのがわかる。

simple-framebuffer e1000000.framebuffer: framebuffer at 0xe1000000, 0xea600 bytes, mapped to 0xf010000
0                                                                                                     
simple-framebuffer e1000000.framebuffer: format=r5g6b5, mode=800x600x16, linelength=1600

また、/dev/fb0が追加されている。

もうちょっと確認する

hw_if.cを修正する。
hw/char/hw_if.c

static void hw_if_write(void *opaque, hwaddr offset,uint64_t value, unsigned size){
    if (value != 0) {  
        printf("write::%lx %lx %x\n",offset >> 2,value,size);                                           
    }
}

value != 0がないと黒のドットがすべてprintされるので0以外を出力している。
この状態でecho -ne "a" > /dev/fb0とやってみた。

zynq> echo -ne "a" > /dev/fb0
write::0 61 1

0x61はASCIIコードで"a"なのでライトできてる様です。

実機に実装する際はデュアルポートメモリを置いて片方は0xE1000000にバスからライトして片方はVGAなりHDMIなりに同期信号付けて渡せば動作しそう。
リフレッシュレートの設定が見つからないけどLinuxは同期をどうしてるんだろう?書けるだけ書いているのかな?