FPGA / ARM / DSP Wishbone SoC
<
WB+LINUX+USB+TCPIP+WEBServer >
Lab2 :
Linux VGA Display Frame Buffer
WB+LINUX+USB+TCPIP+WEBServer 整合實驗2
▋Introduction
Lab.2本實驗同樣在ARM9 Linux Kernel上, 進行VGA圖片顯示實驗, 程式會透過ARM9 Linux 之File System, 讀取在NFS(連接到PC Ubuntu) 或 USB Flash Drive(隨身碟) 上的圖片檔案, 圖片檔為轉換過的Binary Image Raw檔。
後面章節將會讀取其他標準圖形檔。
▋Design Codes
fbtst.h
//a framebuffer device structure;
typedef struct fbdev{
int fb;
unsigned long fb_mem_offset;
unsigned long fb_mem;
struct fb_fix_screeninfo fb_fix;
struct fb_var_screeninfo fb_var;
char dev[20];
} FBDEV, *PFBDEV;
//open & init a frame buffer
//to use this function,
//you must set FBDEV.dev=\"/dev/fb0\"
//or \"/dev/fbX\"
//it\'s your frame buffer.
int fb_open(PFBDEV pFbdev);
//close a frame buffer
int fb_close(PFBDEV pFbdev);
//get display depth
int get_display_depth(PFBDEV pFbdev);
//full screen clear
void fb_memset(void *addr, int c, size_t len);
fbtst.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <asm/page.h>
#include <linux/fb.h>
#include "fbtst.h"
#define TRUE 1
#define FALSE 0
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))
//open & init a frame buffer
int fb_open(PFBDEV pFbdev)
{
printf("fb_open\n");
pFbdev->fb = open(pFbdev->dev, O_RDWR);
if(pFbdev->fb < 0)
{
printf("Error opening %s: %m. Check kernel config/n", pFbdev->dev);
return FALSE;
}
if (-1 == ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))
{
printf("ioctl FBIOGET_VSCREENINFO/n");
return FALSE;
}
if (-1 == ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))
{
printf("ioctl FBIOGET_FSCREENINFO/n");
return FALSE;
}
//map physics address to virtual address
pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);
pFbdev->fb_mem = (unsigned long int)mmap(
(void *)pFbdev->fb_fix.smem_start,
pFbdev->fb_fix.smem_len + pFbdev->fb_mem_offset,
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
pFbdev->fb,
0);
if (-1L == (long) pFbdev->fb_mem)
{
printf("mmap error! mem:%d offset:%d/n", pFbdev->fb_mem,
pFbdev->fb_mem_offset);
return FALSE;
}
return TRUE;
}
//close frame buffer
int fb_close(PFBDEV pFbdev)
{
close(pFbdev->fb);
pFbdev->fb=-1;
}
//get display depth
int get_display_depth(PFBDEV pFbdev)
{
if(pFbdev->fb<=0)
{
printf("fb device not open, open it first/n");
return FALSE;
}
return pFbdev->fb_var.bits_per_pixel;
}
//full screen clear
void fb_memset (void *addr, int c, size_t len)
{
memset(addr, c, len);
}
void fb_fill (void *addr, size_t line)
{
int i,j,aa;
unsigned char *fbm;
fbm=(unsigned char *) addr;
aa=0;
for(i=0;i<0x10;i++)
for(j=0;j<line;j++) fbm[aa++]=(i*0x10)+j;
}
void fb_dump (void *addr, size_t line)
{
int i,j,aa;
unsigned char *fbm;
fbm=(unsigned char *) addr;
aa=0;
for(i=0;i<0x10;i++)
for(j=0;j<line;j++) printf("*%x",fbm[aa++]);
}
void delayA(int ndly)
{
int i,j,k;
for(i=0;i<ndly;i++)
for(j=0;j<0x100;j++)
for(k=0;k<0x100;k++)
{ asm("nop"); };
}
main(int argc, char *argv[])
{
char ch;
int ii,nrd;
FBDEV fbdev;
int fid;
if(argc>=1)
if((fid=open(argv[1],O_RDONLY))==-1) { printf("open error !!"); }
memset(&fbdev, 0, sizeof(FBDEV));
strcpy(fbdev.dev, "/dev/fb0");
if(fb_open(&fbdev)==FALSE)
{
printf("open frame buffer error/n");
return;
}
printf("id %s\n",fbdev.fb_fix.id);
printf("fb_mem %x\n",fbdev.fb_mem);
printf("fb_mem_offset %x\n",fbdev.fb_mem_offset);
printf("fb_fix.smem_start %x\n",fbdev.fb_fix.smem_start);
printf("fb_fix.smem_len %x\n",fbdev.fb_fix.smem_len);
nrd=read(fid,(unsigned char *)(fbdev.fb_mem + fbdev.fb_mem_offset),480*272*2);
printf("Size %x\n",nrd);
fb_close(&fbdev);
close(fid);
}
Makefile
CROSS=/usr/local/arm/3.4.1/bin/arm-linux-
all: fbtst
fbtst:
$(CROSS)gcc -o fbtst fbtst.c
clean:
rm -rf fbtst *.o
