1. 增加Nandflash读取代码
因为要显示图片,而图片明显是放在Nandflash中比较合适,因此需要有能够操作Nandflash的函数。在U-boot中已经有能操作Nandflash的函数了,但是我找了半天也不知道该怎么调用,因此还是上自己的代码吧。
1 #define NFCONF *(volatile unsigned int *)0x70200000 2 #define NFCONT *(volatile unsigned int *)0x70200004 3 #define NFCMMD *(volatile unsigned char *)0x70200008 4 #define NFADDR *(volatile unsigned int *)0x7020000c 5 #define NFDATA *(volatile unsigned char *)0x70200010 6 #define NFSTAT *(volatile unsigned int *)0x70200028 7 #define NAND_SECTOR_SIZE 2048 8 #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1) 9 10 #define TACLS 7 11 #define TWRPH0 7 12 #define TWRPH1 7 13 14 /** 15 * \brief Nandflash初始化 16 */ 17 static void __nand_init(void) 18 { 19 NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4); 20 NFCONT = (1<<4) | (1<<1) | (1); 21 } 22 23 static void __nand_select(void) 24 { 25 NFCONT &= ~(1<<1); 26 } 27 28 static void __nand_deselect(void) 29 { 30 NFCONT |= (1<<1); 31 } 32 33 static void __nand_cmd(unsigned char cmd) 34 { 35 NFCMMD = cmd; 36 } 37 38 static void __nand_addr (unsigned int addr) 39 { 40 unsigned int col = addr&NAND_BLOCK_MASK; 41 unsigned int page = addr/NAND_SECTOR_SIZE; 42 43 NFADDR = col & 0xff; 44 NFADDR = (col>>8) & 0xff; 45 NFADDR = page & 0xff; 46 NFADDR = (page >> 8) & 0xff; 47 NFADDR = (page >> 16) & 0x3; 48 } 49 50 static void __nand_wait_teady(void) 51 { 52 int i; 53 while (!(NFSTAT & 1)) 54 for (i = 0; i < 10; i++); 55 } 56 57 static unsigned char __nand_data(void) 58 { 59 unsigned char p; 60 p = NFDATA; 61 return p; 62 } 63 64 /** 65 * \brief 从Nandflash中读取数据至内存中 66 */ 67 static void __nand_read (unsigned int addr, unsigned char *buf, unsigned int len) 68 { 69 int col = addr % 2048; 70 int i = 0; 71 __nand_select(); 72 while (i < len) { 73 __nand_cmd(0); 74 __nand_addr(addr); 75 __nand_cmd(0x30); 76 __nand_wait_teady(); 77 78 for (; col < 2048&&(i < len); col++) { 79 buf[i] = __nand_data(); 80 i++; 81 addr++; 82 } 83 col = 0; 84 } 85 __nand_deselect(); 86 } 87 88 static void __nand_reset(void) 89 { 90 __nand_select(); 91 __nand_cmd(0xff); 92 __nand_wait_teady(); 93 __nand_deselect(); 94 } 95 96 /** 97 * \brief 将Nandflash中的内容读取至内存 98 */ 99 void nand_copy2ram(unsigned int addr, unsigned char *buff, unsigned int len) 100 { 101 //__nand_init(); 102 __nand_reset(); 103 __nand_read(addr, buff, len); 104 }
注意第101行我把__nand_init注释掉了,因为U-boot起来之后肯定已经对Nandflash初始化过了。
2. 修改LCD代码
lcd.c
1 #include "lcd.h" 2 3 static int PEN_COLOR = LCD_RED; /* 定义画笔(前景)颜色 */ 4 static int BK_COLOR = LCD_BLACK; /* 定义背景颜色 */ 5 6 /** 7 * \brief LCD初始化 8 */ 9 void lcd_init (void) 10 { 11 GPICON = 0; 12 GPICON |= 0xaaaaaaaa; 13 GPJCON = 0; 14 GPJCON |= 0xaaaaaa; 15 16 MIFPCON &= ~(0x1<<3); 17 SPCON &= ~0x3; 18 SPCON |= 0x1; 19 20 VIDCON0 = (14<<6) | (0x1<<4) | (0x3); 21 VIDCON1 = (0x1<6) | (0x1<<5); 22 23 VIDTCON0 = (1<<16) | (1<<8) | (9); 24 VIDTCON1 = (1<<16) | (1<<8) | (40); 25 26 VIDTCON2 = ((LCD_HEIGHT - 1) << 11) | (LCD_WIDTH - 1); 27 WINCON0 = (0xb<<2) | (0x1); 28 29 VIDOSD0A = 0; 30 VIDOSD0B = ((LCD_WIDTH - 1) << 11) | ((LCD_HEIGHT - 1)); 31 32 VIDOSD0C = LCD_WIDTH * LCD_HEIGHT; 33 34 VIDW00ADD0B0 = SHOW_BUF; 35 } 36 37 /** 38 * \brief 设置画笔颜色 39 */ 40 void lcd_set_pen_color (int color) 41 { 42 PEN_COLOR = color; 43 } 44 45 /** 46 * \brief 设置背景颜色 47 */ 48 void lcd_set_bk_color (int color) 49 { 50 BK_COLOR = color; 51 } 52 53 /** 54 * \brief 绘制一个点 55 */ 56 void lcd_draw_point (int x, int y) 57 { 58 *((int *)SHOW_BUF + x + y * LCD_WIDTH) = PEN_COLOR; 59 } 60 61 void lcd_draw_bk (int x, int y) 62 { 63 *((int *)SHOW_BUF + x + y * LCD_WIDTH) = BK_COLOR; 64 } 65 66 /** 67 * \brief 清屏(填充背景色) 68 */ 69 void lcd_clean (void) 70 { 71 int i, j; 72 for(i=0; i) { 73 for(j=0; j ) { 74 lcd_draw_bk(j, i); 75 } 76 } 77 } 78 79 /** 80 * \brief 显示一张BMP图片 81 */ 82 void lcd_show_bmp (int x , int y , unsigned char *pic) 83 { 84 col_t c; 85 BITMAPFILEHEADER filehead; 86 BITMAPINFOHEADER infohead; 87 int i, j; 88 unsigned char *p = 0; 89 int width_error = 0; 90 int old_pen_color; 91 92 memcpy(&filehead , pic, sizeof(filehead)); 93 memcpy(&infohead , pic + sizeof(filehead), sizeof(infohead)); 94 95 width_error = (4 - infohead.biWidth * 3 % 4) % 4; 96 97 p = pic + sizeof(filehead) + sizeof(infohead); 98 99 old_pen_color = PEN_COLOR; 100 101 c.c.non = 0; 102 for (j = infohead.biHeight-1; j>=0; j--) { 103 for (i = 0; i < infohead.biWidth; i++) { 104 c.c.b = *p++; 105 c.c.g = *p++; 106 c.c.r = *p++; 107 108 PEN_COLOR = c.l; 109 lcd_draw_point(x + i, y + j); 110 } 111 p += width_error; 112 } 113 PEN_COLOR = old_pen_color; 114 }
lcd.h
1 #ifndef __LCD_H 2 #define __LCD_H 3 4 /* 定义寄存器地址 */ 5 #define GPICON (*(unsigned int *)0x7F008100) 6 #define SPCON (*(unsigned int *)0x7F0081A0) 7 #define MIFPCON (*(unsigned int *)0x7410800c) 8 #define GPJCON (*(unsigned int *)0x7F008120) 9 10 #define VIDCON0 (*(unsigned int *)0x77100000) 11 #define VIDCON1 (*(unsigned int *)0x77100004) 12 #define VIDCON2 (*(unsigned int *)0x77100008) 13 #define VIDTCON0 (*(unsigned int *)0x77100010) 14 #define VIDTCON1 (*(unsigned int *)0x77100014) 15 #define VIDTCON2 (*(unsigned int *)0x77100018) 16 #define WINCON0 (*(unsigned int *)0x77100020) 17 #define WINCON1 (*(unsigned int *)0x77100024) 18 #define WINCON2 (*(unsigned int *)0x77100028) 19 #define WINCON3 (*(unsigned int *)0x7710002C) 20 #define WINCON4 (*(unsigned int *)0x77100030) 21 #define VIDOSD0A (*(unsigned int *)0x77100040) 22 #define VIDOSD0B (*(unsigned int *)0x77100044) 23 #define VIDOSD0C (*(unsigned int *)0x77100048) 24 #define VIDOSD1A (*(unsigned int *)0x77100050) 25 #define VIDOSD1B (*(unsigned int *)0x77100054) 26 #define VIDOSD1C (*(unsigned int *)0x77100058) 27 #define VIDW00ADD0B0 (*(unsigned int *)0x771000A0) 28 #define GPECON (*(unsigned int *)0x7f008080) 29 #define GPEDAT (*(unsigned int *)0x7f008084) 30 31 #define LCD_WIDTH 480 /* 定义LCD宽度 */ 32 #define LCD_HEIGHT 272 /* 定义LCD高度 */ 33 34 /* 定义显存地址 */ 35 #define SHOW_BUF 0x54000000 36 37 /* 定义常用颜色 */ 38 #define COL(R,G,B) ((R<<16) | (G<<8) | (B)) 39 #define LCD_RED COL(0xFF, 0, 0) 40 #define LCD_GREEN COL(0, 0xFF, 0) 41 #define LCD_BLUE COL(0, 0, 0xFF) 42 #define LCD_WHITE COL(0xFF, 0xFF, 0xFF) 43 #define LCD_BLACK COL(0, 0, 0) 44 45 typedef unsigned short WORD; 46 typedef unsigned char BYTE; 47 typedef unsigned int DWORD; 48 typedef int LONG; 49 50 #pragma pack(2) 51 typedef struct tagBITMAPFILEHEADER 52 { 53 WORD bfType; // 位图文件的类型,必须为BM 54 DWORD bfSize; // 位图文件的大小,以字节为单位 55 WORD bfReserved1; // 位图文件保留字,必须为0 56 WORD bfReserved2; // 位图文件保留字,必须为0 57 DWORD bfOffBits; // 位图数据的起始位置,以相对于位图 58 // 文件头的偏移量表示,以字节为单位 59 } BITMAPFILEHEADER; 60 61 typedef struct tagBITMAPINFOHEADER 62 { 63 DWORD biSize; // 本结构所占用字节数 64 LONG biWidth; // 位图的宽度,以像素为单位 65 LONG biHeight; // 位图的高度,以像素为单位 66 WORD biPlanes; // 目标设备的级别,必须为1 67 WORD biBitCount; // 每个像素所需的位数,必须是1(双色), 68 // 4(16色),8(256色)或24(真彩色)之一 69 DWORD biCompression; // 位图压缩类型,必须是 0(不压缩), 70 // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 71 DWORD biSizeImage; // 位图的大小,以字节为单位 72 LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数 73 LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数 74 DWORD biClrUsed; // 位图实际使用的颜色表中的颜色数 75 DWORD biClrImportant; // 位图显示过程中重要的颜色数 76 } BITMAPINFOHEADER; 77 #pragma pack(4) 78 79 struct _rgb_ 80 { 81 unsigned char b; 82 unsigned char g; 83 unsigned char r; 84 unsigned char non; 85 }; 86 87 typedef union _color_ 88 { 89 struct _rgb_ c; 90 unsigned int l; 91 } col_t; 92 93 /******************************* 函数声明 **************************/ 94 /** 95 * \brief LCD初始化 96 */ 97 extern void lcd_init (void); 98 99 /** 100 * \brief 设置画笔颜色 101 */ 102 extern void lcd_set_pen_color (int color); 103 104 /** 105 * \brief 设置背景颜色 106 */ 107 extern void lcd_set_bk_color (int color); 108 109 /** 110 * \brief 绘制一个点 111 */ 112 extern void lcd_draw_point (int x, int y); 113 114 /** 115 * \brief 清屏(填充背景色) 116 */ 117 extern void lcd_clean (void); 118 119 /** 120 * \brief 显示一张BMP图片 121 */ 122 extern void lcd_show_bmp (int x , int y , unsigned char *pic); 123 124 #endif
3. 修改board.c和Makefile
nand_copy2ram第一个参数为Nandflash中要读取的地址,在这里我写的是0x100000,因此运行程序前需要保证该地址有我想要的图片;第二个参数为内存地址,需要与保证其他程序不会使用该地址,且与lcd_show_bmp传入的地址相同;第三个参数为拷贝数据大小,一张480*272的24位图大小不会超过400K,这里传入0x80000足够了。
此外还要修改lib_arm下的Makefile,在COBJS后面加上nand.o后编译。
4. 下载程序
编译成功后在U-boot中将新编译出的U-boot下载进Nandflash的0地址,将BMP图片下载到0x100000地址。重启开发板,能看到LCD上显示出图片。