FC2カウンター FPGAの部屋 2012年11月02日
FC2ブログ

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

FPGAの部屋

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

FusionPCBから基板が届きました

今日、FusionPCBから基板が届きました。10月15日に注文したので、18日くらいで届きました。3回頼んだ中で一番早かったです。
基板は板厚1mm、50mm x 100mm、レジスト色は赤です。やはり基板は結構薄いです。明日から基板に部品を載せて、早く光らせてみたいです。楽しみです。
acrylic_signs_14_121102.jpg

  1. 2012年11月02日 21:34 |
  2. Make出展
  3. | トラックバック:0
  4. | コメント:0

ZedBoardにビットマップ・ディスプレイ・コントローラを追加する17(ARMのソフトからキャラクタを書けた2)

ZedBoardにビットマップ・ディスプレイ・コントローラを追加する16(ARMのソフトからキャラクタを書けた)”の続き。

前回、ZynqのARMプロセッサのソフトウェアからビットマップ・ディスプレイ・コントローラに文字を書くことが出来た。その際使用した関数はXil_DCacheFlush(); だった。これはソースを読んでみるとL1, L2キャッシュをすべてフラッシュするようだ。これでは、画像フレームバッファをキャッシュするキャッシュラインだけでなく他のキャッシュラインもフラッシュされてしまう。これでは無駄が大きい。その内に、Xil_DCacheFlushLine((unsigned int)addr); という関数をツイッターで教えて頂いた。これだったら、当該キャッシュラインだけをフラッシュすることができるはずだ。
なお、Xil_DCacheFlushLine() のソースコードは、ISE14.2を使用している場合は、Xilinx\14.2\ISE_DS\EDK\sw\lib\bsp\standalone_v3_07_a\src\cortexa9\xil_cache.c にある。ツイッターで教えて頂いた。ありがとうございました。

ARMのキャッシュラインの幅は32バイトの様なので、文字をラスタ毎に書き込んでいる時のアドレスの下5ビットが0x1Cになったら、Xil_DCacheFlushLine() を行うこととする。この変更を加えて、drawn_disp.elf をSDKから実行したところ問題なく文字が表示された。やはり文字を表示するのが速い。
ZedBoad_BitMap_DispCnt_100_121101.jpg

下に、drawn_disp.c を示す。

/* * drawn_disp.c * *  Created on: 2012/09/25 *      Author: Masaaki */

#include "xparameters.h"
#include "xgpio.h"

#define VIDEO_BUFFER_START_ADDRESS    0x10000000

void Xil_DCacheFlush(void);
void Xil_DCacheFlushLine(unsigned int adr);

// char_draw: アドレスとキャラクタコードを受け取ってそのキャラクタを描画する
// addr : 描画するキャラクタのスタートアドレス
// char_code : 描画するキャラクタのコード
// char_color : 描画するキャラクタのカラー、32ビットで表される、0RGBと8ビットずつで表す
// 戻り値:次のキャラクタの描画先頭アドレスを示す。
unsigned int *char_draw(unsigned int *addr, unsigned char char_code, unsigned int char_color){
    int i,j;
    unsigned int char_pattern;
    unsigned int char_code_int;
    unsigned int *cal_char_addr;
    unsigned int *return_addr;

    char_code_int = (unsigned int)(char_code);
    return_addr = addr + 8;
    cal_char_addr = (unsigned int *)(XPAR_CHAR_ROM_AXI_LITE_0_S_AXI_RNG00_BASEADDR+((char_code_int<<3)<<2)); // キャラジェネROMのデータは32ビット幅で下の8ビットだけ有効
    for(i=0; i<8; i++){
        char_pattern = *(volatile unsigned int *)(cal_char_addr); // キャラクタのパターンを読み出し
        for(j=0; j<8; j++){
            if(char_pattern & 0x1// 7ビット目が1の時はドットを描画
                *(volatile unsigned int *)((unsigned int)addr ^ 4) = char_color;
            else
                *(volatile unsigned int *)((unsigned int)addr ^ 4) = 0// 黒を描画
            // Xil_DCacheFlush();    // 1番目の時間計測
            if (((unsigned int)addr & 0x1f) == 0x1c) // キャッシュラインの終わりで当該キャッシュラインをフラッシュ
                        Xil_DCacheFlushLine((unsigned int)addr);
            addr++;
            char_pattern >>= 1// キャラクタのパターンを1ビット右シフト
        }
        addr -= 8// 行の最初のアドレスに戻す
        addr += 640// アドレスを1行下にする
        cal_char_addr++;
    }
    // Xil_DCacheFlush();    // 2番目の時間計測

    return return_addr;
}

int main()
{
    static XGpio GPIOInstance_Ptr;
    int xStatus;
    unsigned char char_code;
    unsigned int * ddr2_addr;
    unsigned int coler_code;
    unsigned int char_cnt;
    int i, j;

    // AXI GPIO Initialization
    xStatus = XGpio_Initialize(&GPIOInstance_Ptr,XPAR_AXI_GPIO_0_DEVICE_ID);
    if(XST_SUCCESS != xStatus)
        print("GPIO INIT FAILED\n\r");
    // AXI GPIO Set the Direction(Output setting)
    XGpio_SetDataDirection(&GPIOInstance_Ptr, 10);
    // init_doneに1を出力
    XGpio_DiscreteWrite(&GPIOInstance_Ptr, 11);

    for (ddr2_addr=(unsigned int *)VIDEO_BUFFER_START_ADDRESS; ddr2_addr<(unsigned int *)((unsigned int)VIDEO_BUFFER_START_ADDRESS + (unsigned int)0x12C000); ddr2_addr++){
        *(volatile unsigned int *)((unsigned int)ddr2_addr ^ 4) = 0;
        if (((unsigned int)ddr2_addr & 0x1f) == 0x1c) // キャッシュラインの終わりで当該キャッシュラインをフラッシュ
            Xil_DCacheFlushLine((unsigned int)ddr2_addr);
    }
    // Xil_DCacheFlush();

    ddr2_addr = (unsigned int *)VIDEO_BUFFER_START_ADDRESS;
    char_cnt = 0;
    for(j=0; j<8; j++){
        for(i=1; i<8; i++){
            switch(i){
                case 1 :
                    coler_code = 0xff;
                    break;
                case 2 :
                    coler_code = 0xff00;
                    break;
                case 3 :
                    coler_code = 0xffff;
                    break;
                case 4 :
                    coler_code = 0xff0000;
                    break;
                case 5 :
                    coler_code = 0xff00ff;
                    break;
                case 6 :
                    coler_code = 0xffff00;
                    break;
                case 7 :
                    coler_code = 0xffffff;
            }

            for(char_code=0x21; char_code<0x80; char_code++){
                if(char_code >= 0x80// キャラクタコードが上限に達したら、一番下に戻す
                    char_code = 0x21;
                if (char_cnt!=0 && char_cnt%80==0)
                    ddr2_addr = (unsigned int *)((unsigned int)ddr2_addr + 640*4*7); // 1行書き終わったので、下の行に、アドレスは640ドットx1ピクセル4バイトx7行
                ddr2_addr = char_draw(ddr2_addr, char_code, coler_code); // キャラクタを描画
                char_cnt++;
            }
        }
    }

    //Xil_DCacheFlush();    // 3番めの時間計測
    return 0;
}


これで、Zynq-7000シリーズのARMプロセッサを使用して、ビットマップ・ディスプレイ・コントローラに文字を描画するソフトウェアは完成だ。
  1. 2012年11月02日 05:02 |
  2. ZedBoard
  3. | トラックバック:0
  4. | コメント:0