当前位置: 首页 > news >正文

TQ2440开发板移植UBOOT-2010.06总结(3)

    接下来是为UBOOT增加驱动。

    1) NOR FALSH:

        TQ2440的NOR FLASH和UBOOT源文件中用到的AM29LV800相似,只需在/include/configs/TQ2440.h里作一些改动即可。具体参考网上教程。

    2) 网卡:

         网卡DM9000的驱动在UBOOT中已自带,首先在/include/configs/TQ2440.h中注释掉原网卡CS8900的宏。

         添加DM9000的宏,添加CONFIG_CMD_PING以支持PING命令。

         添加CONFIG_ETHADDR、CONFIG_NETMASK、CONFIG_IPADDR、CONFIG_SERVERIP等宏来设置网络参数(在UBOOT命令行中用setenv和setenv也可以设置)。

         然后修改board/samsung/TQ2440/TQ2440.c的网卡初始化部分为:

1 int board_eth_init(bd_t *bis)
2 { 
3     return dm9000_initialize(bis);
4 }

          最后因为存在一点小BUG,还要在drivers/net/dm9000x.c里注释掉dm9000_init函数中的以下部分

 1 #if 0
 2 i = 0; 
 3 while (!(phy_read(1) & 0x20))
 4 { /* autonegation complete bit */ 
 5     udelay(1000); i++;
 6     if (i == 10000) { 
 7           printf("could not establish link "); 
 8           return 0; 
 9     } 
10 } #endif

         以及注释掉dm9000_halt函数中的以下部分:

 1 static void dm9000_halt(struct eth_device *netdev) 
 2 {
 3 #if 0 
 4     DM9000_DBG("%sn", __func__); 
 5     /* RESET devie */ 
 6     phy_write(0, 0x8000);
 7      /* PHY RESET */ 
 8     DM9000_iow(DM9000_GPR, 0x01);
 9      /* Power‐Down PHY */ 
10     DM9000_iow(DM9000_IMR, 0x80); 
11     /* Disable all interrupt */ 
12     DM9000_iow(DM9000_RCR, 0x00); 
13     /* Disable RX */ 
14 #endif 
15 }

       3) NAND FLASH

             UBOOT的NAND驱动在目录drivers/mtd/nand下。

             在目录下可以找到2410的NAND驱动s3c2410_nand.c,文件里面主要是s3c2410_dev_ready()、s3c2410_hwcontrol()、board_nand_init()三个函数。

             所以只需要实现2440的这三个函数即可。创建一个s3c2440_nand.c文件,并在MAKEFILE里加上s3c2440_nand.o的目标。文件内容如下(代码是从别处复制的):

 1 #include <common.h>
 2 #if 0
 3 #define DEBUGN
 4 printf
 5 #else
 6 #define DEBUGN(x, args ...) {}
 7 #endif
 8 #include <nand.h>
 9 #include <asm/arch/s3c24x0_cpu.h>
10 #include <asm/arch/s3c2410.h>
11 #include <asm/io.h>
12 #define __REGb(x) (*(volatile unsigned char *)(x))
13 #define __REGi(x) (*(volatile unsigned int *)(x))
14 
15 #define NF_BASE 0x4e000000 
16 #define NFCONF __REGi(NF_BASE + 0x0)
17 #define NFCONT __REGi(NF_BASE + 0x4) 
18 #define NFCMD __REGb(NF_BASE + 0x8) 
19 #define NFADDR __REGb(NF_BASE + 0xc) 
20 #define NFDATA __REGb(NF_BASE + 0x10)
21 #define NFMECCD0 __REGi(NF_BASE + 0x14) 
22 #define NFMECCD1 __REGi(NF_BASE + 0x18) 
23 #define NFSECCD __REGi(NF_BASE + 0x1C) 
24 #define NFSTAT __REGb(NF_BASE + 0x20) 
25 #define NFSTAT0 __REGi(NF_BASE + 0x24) 
26 #define NFSTAT1 __REGi(NF_BASE + 0x28) 
27 #define NFMECC0 __REGi(NF_BASE + 0x2C)
28 #define NFMECC1 __REGi(NF_BASE + 0x30)
29 #define NFSECC __REGi(NF_BASE + 0x34) 
30 #define NFSBLK __REGi(NF_BASE + 0x38) 
31 #define NFEBLK __REGi(NF_BASE + 0x3c)
32 #define S3C2440_NFCONT_nCE (1<<1)
33 #define S3C2440_ADDR_NCLE 0x0c
34 #define S3C2440_ADDR_NALE 0x08
35 
36 
37 
38 ulong IO_ADDR_W = NF_BASE;
39 static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
40 {
41     struct nand_chip *chip = mtd->priv;
42     if (ctrl & NAND_CTRL_CHANGE) {
43         IO_ADDR_W = NF_BASE;
44         if (!(ctrl & NAND_CLE))
45             IO_ADDR_W |= S3C2440_ADDR_NCLE;
46         if (!(ctrl & NAND_ALE))
47             IO_ADDR_W |= S3C2440_ADDR_NALE;
48         if (ctrl & NAND_NCE)
49             NFCONT &= ~S3C2440_NFCONT_nCE;
50         else
51             NFCONT |= S3C2440_NFCONT_nCE;
52     }
53     if (cmd != NAND_CMD_NONE)
54         writeb(cmd,(void *)IO_ADDR_W);
55 }
56 static int s3c2440_dev_ready(struct mtd_info *mtd)
57 {
58     return (NFSTAT & 0x01);
59 }
60 int board_nand_init(struct nand_chip *nand)
61 {
62     u_int32_t cfg;
63     u_int8_t tacls, twrph0, twrph1;
64     struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
65     writel(readl(&clk_power->CLKCON) | (1 << 4), &clk_power->CLKCON);
66     /* initialize hardware */
67     twrph0 = 4;
68     twrph1 = 2;
69     tacls = 0;
70     cfg = ((tacls<<12)|(twrph0<<8)|(twrph1<<4));
71     NFCONF=cfg;
72     cfg = ((1<<6)|(1<<4)|(0<<1)|(1<<0));
73     NFCONT=cfg;
74     /* initialize nand_chip data structure */
75     nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;
76     /* read_buf and write_buf are default */
77     /* read_byte and write_byte are default */
78     /* hwcontrol always must be implemented */
79     nand->cmd_ctrl = s3c2440_hwcontrol;
80     nand->dev_ready = s3c2440_dev_ready;
81     nand->ecc.mode = NAND_ECC_SOFT;
82     return 0;
83 }
View Code

             然后在TQ2440.h里添加

 1 #define CONFIG_CMD_NAND
 2 #define CONFIG_CMDLINE_EDITING
 3 #ifdef CONFIG_CMDLINE_EDITING
 4 #undef CONFIG_AUTO_COMPLETE
 5 #else
 6 #define CONFIG_AUTO_COMPLETE
 7 #endif
 8 
 9 #if defined(CONFIG_CMD_NAND)
10 #define CONFIG_SYS_NAND_BASE 0x4E000000 
11 #define CONFIG_SYS_MAX_NAND_DEVICE 1
12 #define CONFIG_MTD_NAND_VERIFY_WRITE 1
13 #define NAND_SAMSUNG_LP_OPTIONS 1  
14 #endif

            注意,我的TQ2440开发板上用的NAND型号是K9F2G08U0A,是Large Page,因此需要开启NAND_SAMSUNG_LP_OPTIONS选项,不是LP的话需要注释掉。

       4) LCD

            显示部分的驱动在drivers/video目录下。需要实现三个函数:lcd_enable()、video_hw_init()、video_set_lut()函数。

            其中video_hw_init()最重要,负责初始化LCD的硬件,然后填充GraphicDevice结构体,向上层传递显示缓存的地址、大小,显示设备分辨率等参数。

            在此目录下新建一个s3c2440_fb.c文件,拷贝以下代码:

  1 #include <common.h>
  2 #if defined(CONFIG_VIDEO_S3C2440)
  3 #include <video_fb.h>
  4 #include "videomodes.h"
  5 #include <asm/arch/s3c24x0_cpu.h>
  6 #include <asm/io.h>
  7 /*
  8 * Export Graphic Device
  9 */
 10 GraphicDevice smi;
 11 
 12 #define LCD_X_SIZE 240
 13 #define LCD_Y_SIZE 320
 14 #define VIDEO_MEM_SIZE (LCD_Y_SIZE*LCD_X_SIZE)//0x200000
 15 #define MVAL (13)
 16 #define MVAL_USED (0) //0=each frame 1=rate by MVAL
 17 #define INVVDEN (1) //0=normal 1=inverted
 18 #define BSWP (0) //Byte swap control
 19 #define HWSWP (1) //Half word swap control
 20 #define VBPD (12) 
 21 #define VFPD (4) 
 22 #define VSPW (5) 
 23 #define HBPD (22) 
 24 #define HFPD (33) 
 25 #define HSPW (44)
 26 #define CLKVAL_TFT (6)
 27 
 28 volatile unsigned short LCD_BUFFER[LCD_Y_SIZE][LCD_X_SIZE];
 29 
 30 void lcd_enable(void)
 31 {
 32     struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
 33     struct s3c24x0_lcd * const lcd = s3c24x0_get_base_lcd();
 34     gpio->GPGUP = gpio->GPGUP & ((~(1 << 4)) | (1 << 4));
 35     gpio->GPGCON = gpio->GPGCON & ((~( 3 << 8)) | ( 3 << 8));
 36     gpio->GPGDAT = gpio->GPGDAT | (1 << 4 );
 37     lcd->LCDCON5 = lcd->LCDCON5 & ((~( 1 << 3)) | (1 << 3)); // PWREN
 38     lcd->LCDCON5 = lcd->LCDCON5 & ((~( 1 << 5)) | (0 << 5)); // INVPWREN
 39     lcd->LCDCON1 |= 1;
 40     gpio->GPBUP = gpio->GPBUP & ((~(1 << 1)) | (1 << 1));
 41     gpio->GPBCON = gpio->GPBCON & ((~( 3 << 2)) | ( 3 << 2));
 42     gpio->GPBDAT = gpio->GPBDAT | (1 << 1 );
 43 }
 44 
 45 void *video_hw_init (void)
 46 {
 47     struct s3c24x0_lcd * const lcd = s3c24x0_get_base_lcd();
 48     GraphicDevice *pGD = (GraphicDevice *)&smi;
 49     int videomode;
 50     int bppmode;
 51     unsigned long t1, hsynch, vsynch;
 52     char *penv;
 53     int tmp, i, bits_per_pixel;
 54     struct ctfb_res_modes *res_mode;
 55     struct ctfb_res_modes var_mode;
 56     tmp = 0;
 57     videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
 58 
 59     /* get video mode via environment */
 60     if ((penv = getenv ("videomode")) != NULL) {
 61     /* deceide if it is a string */
 62         if (penv[0] <= '9') {
 63             videomode = (int) simple_strtoul (penv, NULL, 16);
 64             tmp = 1;
 65         }
 66     } else {
 67         tmp = 1;
 68     }
 69     if (tmp) {
 70     /* parameter are vesa modes */
 71     /* search params */
 72         for (i = 0; i < VESA_MODES_COUNT; i++) {
 73             if (vesa_modes[i].vesanr == videomode)
 74         break;
 75         }
 76         if (i == VESA_MODES_COUNT) {
 77             printf ("no VESA Mode found, switching to mode 0x%x ",
 78             CONFIG_SYS_DEFAULT_VIDEO_MODE);
 79             i = 0;
 80         }
 81         res_mode = (struct ctfb_res_modes *)&res_mode_init[vesa_modes[i].resindex];
 82         bits_per_pixel = vesa_modes[i].bits_per_pixel;
 83     } else {
 84         res_mode = (struct ctfb_res_modes *) &var_mode;
 85         bits_per_pixel = video_get_params (res_mode, penv);
 86     }
 87 
 88     /* calculate hsynch and vsynch freq (info only) */
 89     t1 = (res_mode->left_margin + res_mode->xres + res_mode->right_margin +
 90     res_mode->hsync_len) / 8;
 91     t1 *= 8;
 92     t1 *= res_mode->pixclock;
 93     t1 /= 1000;
 94     hsynch = 1000000000L / t1;
 95     t1 *= (res_mode->upper_margin + res_mode->yres + res_mode->lower_margin +
 96     res_mode->vsync_len);
 97     t1 /= 1000;
 98     vsynch = 1000000000L / t1;
 99     /* fill in Graphic device struct */
100     sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
101         res_mode->yres, bits_per_pixel, (hsynch / 1000), (vsynch / 1000));
102     pGD->winSizeX = res_mode->xres;
103     pGD->winSizeY = res_mode->yres;
104     pGD->plnSizeX = res_mode->xres;
105     pGD->plnSizeY = res_mode->yres;
106 
107     switch (bits_per_pixel)
108     {
109         case 8:
110             pGD->gdfBytesPP = 1;
111             pGD->gdfIndex = GDF__8BIT_INDEX;
112             bppmode = 11;
113         break;
114         case 16:
115             pGD->gdfBytesPP = 2;
116             pGD->gdfIndex = GDF_16BIT_565RGB;
117             bppmode = 12;
118         break;
119         case 24:
120             pGD->gdfBytesPP = 3;
121             pGD->gdfIndex = GDF_24BIT_888RGB;
122             bppmode = 13;
123         break;
124     }
125 
126     pGD->frameAdrs = &LCD_BUFFER[0][0];//LCD_VIDEO_ADDR;
127     pGD->memSize = VIDEO_MEM_SIZE;
128     lcd->LCDCON1 = (CLKVAL_TFT << 8) | (MVAL_USED << 7) | (3 << 5) | (bppmode << 1) | 0;
129     lcd->LCDCON2 = (VBPD << 24) | (pGD->winSizeY-1 << 14) | (VFPD << 6) | (VSPW);
130     lcd->LCDCON3 = (HBPD << 19) | (pGD->winSizeX-1 << 8) | (HFPD);
131     lcd->LCDCON4 = (MVAL << 8) | (HSPW);
132     lcd->LCDCON5 = (1 << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 7) | (0 << 6) | (1 << 3) | (BSWP << 1) | (HWSWP);
133     lcd->LCDINTMSK |= (3);
134     lcd->LPCSEL &= (~7);
135     lcd->TPAL = 0x0;
136     writel((pGD->frameAdrs >> 1), &lcd->LCDSADDR1);
137     /* This marks the end of the frame buffer. */
138     writel((((readl(&lcd->LCDSADDR1))&0x1fffff)+(pGD->winSizeX+0)*pGD->winSizeY), &lcd->LCDSADDR2);
139     writel((pGD->winSizeX & 0x7ff), &lcd->LCDSADDR3);
140 
141     /* Clear video memory */
142     memset((void *)pGD->frameAdrs, 0, pGD->memSize);
143 
144     lcd_enable();
145     return ((void*)&smi);
146 }
147 void video_set_lut (unsigned int index,
148     /* color number */
149     unsigned char r, /* red */
150     unsigned char g, /* green */
151     unsigned char b /* blue */
152 )
153 {
154 }
155 #endif /* CONFIG_VIDEO_S3C2440 */
View Code

           往目录下的MAKEFILE文件里添加: COBJS-$(CONFIG_VIDEO_S3C2440) += s3c2440_fb.o videomodes.o

           video目录下的videomodes.c文件的数组 ctfb_vesa_modes vesa_modes 和 ctfb_res_modes res_mode_init 列出了屏幕参数,然后video_hw_init函数根据环境变量指定的屏幕去寻找对应的配置参数(如果没有此变量就用默认设定,在TQ2440.h中),并用于初始化。

           添加新参数后的videomodes.c部分代码如下(新增参数在最后):

 1 const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = {
 2     {0x301, RES_MODE_640x480, 8},
 3     {0x310, RES_MODE_640x480, 15},
 4     {0x311, RES_MODE_640x480, 16},
 5     {0x312, RES_MODE_640x480, 24},
 6     {0x303, RES_MODE_800x600, 8},
 7     {0x313, RES_MODE_800x600, 15},
 8     {0x314, RES_MODE_800x600, 16},
 9     {0x315, RES_MODE_800x600, 24},
10     {0x305, RES_MODE_1024x768, 8},
11     {0x316, RES_MODE_1024x768, 15},
12     {0x317, RES_MODE_1024x768, 16},
13     {0x318, RES_MODE_1024x768, 24},
14     {0x161, RES_MODE_1152x864, 8},
15     {0x162, RES_MODE_1152x864, 15},
16     {0x163, RES_MODE_1152x864, 16},
17     {0x307, RES_MODE_1280x1024, 8},
18     {0x319, RES_MODE_1280x1024, 15},
19     {0x31A, RES_MODE_1280x1024, 16},
20     {0x31B, RES_MODE_1280x1024, 24},
21         {0x213, RES_MODE_320x240,  16}, 
22 };
23 const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
24     /* x     y pixclk   le    ri  up    lo   hs vs  s  vmode */
25     {640, 480, 39721, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED},
26     {800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED},
27     {1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0, FB_VMODE_NONINTERLACED},
28     {960, 720, 13100, 160, 40, 32, 8, 80, 4, 0, FB_VMODE_NONINTERLACED},
29     {1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0, FB_VMODE_NONINTERLACED},
30     {1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0, FB_VMODE_NONINTERLACED},
31         {320, 240, 10000, 33, 22, 4, 12, 44, 5, 0, FB_VMODE_NONINTERLACED},  
32 };
View Code

          然后修改videomodes.h:

...
#ifndef CONFIG_SYS_DEFAULT_VIDEO_MODE
#define CONFIG_SYS_DEFAULT_VIDEO_MODE 0x213 #endif
...
....
#define RES_MODE_320x240        6
#define RES_MODES_COUNT       7 (原值加1)

#define VESA_MODES_COUNT 20  (原值加1)
.... 

         最后修改TQ2440.h,增加:

/* LCD settings */
#define CONFIG_VIDEO
#define CONFIG_VIDEO_S3C2440
#define CONFIG_VIDEO_LOGO
#define VIDEO_FB_16BPP_WORD_SWAP
#define CONFIG_SYS_VIDEO_LOGO_MAX_SIZE (320*240+1024+100)
#define CONFIG_CMD_BMP
#define CONFIG_CFB_CONSOLE

#define VIDEO_KBD_INIT_FCT 0
#define VIDEO_TSTC_FCT serial_tstc
#define VIDEO_GETC_FCT serial_getc

         增加了VIDEO部分后,UBOOT的控制台(console)输出转到了LCD上,而输入还是串口。如果希望串口和LCD同时输出控制台信息怎么办呢。

         打开common/console.c文件,修改putc()和puts()函数:

 1 void putc(const char c)
 2 {
 3 #ifdef CONFIG_SILENT_CONSOLE
 4     if (gd->flags & GD_FLG_SILENT)
 5         return;
 6 #endif
 7 
 8 #ifdef CONFIG_DISABLE_CONSOLE
 9     if (gd->flags & GD_FLG_DISABLE_CONSOLE)
10         return;
11 #endif
12 
13     if (gd->flags & GD_FLG_DEVINIT) {
14         /* Send to the standard output */
15         fputc(stdout, c);
16                 serial_putc(c);         //新增添代码
17     } else {
18         /* Send directly to the handler */
19         serial_putc(c);
20     }
21 }
22 
23 void puts(const char *s)
24 {
25 #ifdef CONFIG_SILENT_CONSOLE
26     if (gd->flags & GD_FLG_SILENT)
27         return;
28 #endif
29 
30 #ifdef CONFIG_DISABLE_CONSOLE
31     if (gd->flags & GD_FLG_DISABLE_CONSOLE)
32         return;
33 #endif
34 
35     if (gd->flags & GD_FLG_DEVINIT) {
36         /* Send to the standard output */
37         fputs(stdout, s);
38                 serial_puts(s);        //新增添代码
39     } else {
40         /* Send directly to the handler */
41         serial_puts(s);
42     }
43 }
View Code

       5) 总结

               最后稍稍总结一下,移植过程中需要修改/增添某个驱动,首先在drivers目录下找到该驱动的类型对应的文件夹

               打开MAKEFILE文件,找到按"CONFIG_XXXX"条件编译的目标

               例如: "COBJS-$(CONFIG_DRIVER_S3C4510_ETH) += s3c4510b_eth.o ", 打开s3c4510b_eth.c文件,从中找到哪些是主要的函数。

               根据自己开发板的情况,新建XXXX.c文件,往里面实现这几个主要的函数。

               最后在主头文件里(如TQ2440.h)添加相应的宏,以开启此项功能。

       


 

转载于:https://www.cnblogs.com/Ilmen/p/3578255.html

相关文章:

  • ext button 属性
  • IE,URL中文读取
  • python进阶一_简介,安装与环境部署
  • 判断投递失败原因方法
  • css入门
  • ToString()格式化输出
  • WPF中的属性触发器Trigger Property
  • PL/SQL中文乱码解决方法
  • wince 显示图片
  • unix
  • 发布一个半成品的操作系统,还没有写完,希望大家多交流
  • 基于ScheduledExecutorService的并发定时任务处理能力测试
  • 利用API 建立Dependent Value Set
  • 键盘布局
  • USB--u盘被禁止
  • ----------
  • 08.Android之View事件问题
  • Android Studio:GIT提交项目到远程仓库
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • Codepen 每日精选(2018-3-25)
  • laravel with 查询列表限制条数
  • Python3爬取英雄联盟英雄皮肤大图
  • 和 || 运算
  • 回顾 Swift 多平台移植进度 #2
  • 机器学习学习笔记一
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 力扣(LeetCode)22
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 设计模式 开闭原则
  • 收藏好这篇,别再只说“数据劫持”了
  • 一文看透浏览器架构
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • (02)Hive SQL编译成MapReduce任务的过程
  • (第61天)多租户架构(CDB/PDB)
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (转)视频码率,帧率和分辨率的联系与区别
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .net2005怎么读string形的xml,不是xml文件。
  • .net打印*三角形
  • .pings勒索病毒的威胁:如何应对.pings勒索病毒的突袭?
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • @ComponentScan比较
  • @Import注解详解
  • @JsonFormat与@DateTimeFormat注解的使用
  • [ 手记 ] 关于tomcat开机启动设置问题
  • [120_移动开发Android]008_android开发之Pull操作xml文件
  • [Android Pro] Notification的使用
  • [ANT] 项目中应用ANT
  • [Arduino学习] ESP8266读取DHT11数字温湿度传感器数据
  • [BZOJ] 1001: [BeiJing2006]狼抓兔子
  • [CISCN2019 华北赛区 Day1 Web2]ikun
  • [Contest20180313]灵大会议
  • [EFI]MSI GF63 Thin 9SCXR电脑 Hackintosh 黑苹果efi引导文件