移植linux-2.6.32.2到感知SensorRF2开发平台(基于mini2440)(实录)—— 杨学鹏

移植linux-2.6.32.2到感知SensorRF2开发平台(实录)—— 杨学鹏

根据《Mini2440_Linux一直开发实战指南.pdf》的移植步骤,亲自对购买的开发平台进行了系统移植,下面是移植的全过程记录:

目录:

1,下载linux-2.6.32.2源码并解压 2

2,指定交叉编译链 2

3,检验编译是否通过 2

4,修改机器码和时钟频率 2

5,修改init/main.c文件(这一步为什么做,有待探究。不做串口无显示。) 3

6,编译测试 4

7,移植NAND驱动并更改分区信息 4

8,使内核支持yaffs2文件系统 8

9,移植DM9000网卡驱动 10

10,激活TRC驱动 14

11,添加背光驱动 16

12,移植LCD显示驱动 21

13,修改Linux Logo 28

14,添加ADC驱动 32

15,添加触摸屏驱动 42

16,配置USB外设 51

17,移植SD卡驱动 58

18,移植UDA1341音频驱动 60

19,休整串口驱动 62

20,移植I2C-EEPROM驱动 64

21,移植看门狗驱动 65

1,下载linux-2.6.32.2源码并解压

怎么下,怎么解压不用我说了吧。很简单,linux本身的命令;

http://www.kernel.org/pub/linux/kernel/v2.6/ 

# tar zxvf linux-2.6.32.2.tar.gz

2,指定交叉编译链

# vi Makefile

ARCH ?= $(SUBARCH)

CROSS_COMPILE ?= 

改为

ARCH ?= arm

CROSS_COMPILE ?= arm-linux-

如下图:

3,检验编译是否通过

执行编译命令,看能否编译通过,不必烧写到开发平台。

# make s3c2410_defconfig

# make

make时间比较长,请耐心等待。

4,修改机器码和时钟频率

删除arch/arm/mach-s3c2440/mach-mini2440.c

# rm arch/arm/mach-s3c2440/mach-mini2440.c -f

拷贝arch/arm/mach-s3c2440/mach-smdk2440.cmach-mini2440.c

# cp arch/arm/mach-s3c2440/mach-smdk2440.c  arch/arm/mach-s3c2440/mach-mini2440.c

# vi arch/arm/mach-s3c2440/mach-mini2440.c

①将

MACHINE_START(S3C2440, "SMDK2440")

修改为

MACHINE_START(MINI2440, "FriendlyARM Mini2440 development board")

如下图:

②将static void __init smdk2440_map_io(void)函数中的

s3c24xx_init_clocks(16934400);

改为

s3c24xx_init_clocks(12000000);

如下图:

③在mach-mini2440.c文件的冒号模式下执行如下命令:

%s/smdk2440/mini2440/g

目的是将文中的smdk2440改成mini2440.

④屏蔽掉mini2440_machine_init(void)函数中的

smdk_machine_init();

因为我们自己要写。

5,修改init/main.c文件(这一步为什么做,有待探究。不做串口无显示。)

①第117行左右,增加如下代码:

char __initdata boot_command_line1[100] = "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC1,115200";

如下图:

②第521行左右,增加变量i

如下图:

③第554行左右,增加如下代码:

printk(KERN_NOTICE "Kernel command line:222s\n");

printk(KERN_NOTICE "%s", command_line);

for (i=0; i<66; i++)

{

command_line[i] = boot_command_line1[i];

}

如下图:

④第571行左右,增加如下代码:

for (i=0; i<66; i++)

{

boot_command_line[i] = boot_command_line1[i];

}

如下图:

6,编译测试

# make mini2440_defconfig

# make zImage

可在arch/arm/boot下生成zImage文件,将它烧写到开发平台,运行,串口可输出如下信息:(见temp/串口输出信息1.txt

7,移植NAND驱动并更改分区信息

# vi arch/arm/mach-s3c2440/mach-mini2440.c

①添加头文件。

// add by xuepeng

#include <linux/mtd/partitions.h>

#include <plat/nand.h>

如下图:

②添加static struct mtd_partition mini2440_default_nand_part[]

// add by xuepeng

static struct mtd_partition mini2440_default_nand_part[] = {

[0] = {

.name = "supervivi",

.size = 0x00040000,

.offset = 0,

},

[1] = {

.name = "param",

.offset = 0x00040000,

.size = 0x00020000,

},

[2] = {

.name = "Kernel",

.offset = 0x00060000,

.size = 0x00500000,

},

[3] = {

.name = "root",

.offset = 0x00560000,

.size = 1024 * 1024 * 1024, //

},

[4] = {

.name = "nand",

.offset = 0x00000000,

.size = 1024 * 1024 * 1024, //

}

};

如下图:

③添加static struct s3c2410_nand_set mini2440_nand_sets[] 

// add by xuepeng

static struct s3c2410_nand_set mini2440_nand_sets[] = {

[0] = {

.name = "NAND",

.nr_chips = 1,

.nr_partitions = ARRAY_SIZE(mini2440_default_nand_part),

.partitions = mini2440_default_nand_part,

},

};

如下图:

④添加static struct s3c2410_platform_nand mini2440_nand_info 

// add by xuepeng

static struct s3c2410_platform_nand mini2440_nand_info = {

.tacls = 20,

.twrph0 = 60,

.twrph1 = 20,

.nr_sets = ARRAY_SIZE(mini2440_nand_sets),

.sets = mini2440_nand_sets,

.ignore_unset_ecc = 1,

};

如下图:

⑤mini2440_devices[]中添加平台设备。

static struct platform_device *mini2440_devices[] __initdata = {

&s3c_device_usb,

&s3c_device_lcd,

&s3c_device_wdt,

&s3c_device_i2c0,

&s3c_device_iis,

&s3c_device_nand, // add by xuepeng

};

如下图:

⑥mini2440_machine_init(void)函数中,platform_add_devices函数前,添加:

// add by xuepeng

s3c_device_nand.dev.platform_data = &mini2440_nand_info;

如下图:

⑦编译测试。

可以看到串口输出信息。(见temp/串口输出信息2.txt

(跟linux-2.6.35.4的移植不太一样啊!!!!!)

8,使内核支持yaffs2文件系统

yaffs2源码。

②为内核打补丁。

# cd yaffs2

# ./patch-ker.sh c ../linux-2.6.32.2

如下图:

可以看到linux-2.6.32.2/fs目录下,多了yaffs2目录。

③配置内核。

# make menuconfig

File systems --->

[*] Miscellaneous filesystems --->

选上

<*> YAFFS2 file system support

如下图:

保存并退出。

④编译测试内核。

# make zImage

烧写到开发平台,此时如果开发平台之前烧有yaffs2文件系统,则串口输出信息如下:

(见temp/串口输出信息3.txt

9,移植DM9000网卡驱动

》》》》》》》》》mach-mini2440.c文件中:

①添加头文件。

// add by xuepeng

#include <linux/dm9000.h>

如下图:

②添加MACH_MINI2440_DM9K_BASE宏定义。

// add by xuepeng

/* DM9000AEP 10/100 ethernet controller */

#define MACH_MINI2440_DM9K_BASE (S3C2410_CS4 + 0x300)

③添加static struct resource mini2440_dm9k_resource[]

// add by xuepeng

static struct resource mini2440_dm9k_resource[] = {

        [0] = {

                .start = MACH_MINI2440_DM9K_BASE,

                .end   = MACH_MINI2440_DM9K_BASE + 3,

                .flags = IORESOURCE_MEM

        },

        [1] = {

                .start = MACH_MINI2440_DM9K_BASE + 4,

                .end   = MACH_MINI2440_DM9K_BASE + 7,

                .flags = IORESOURCE_MEM

        },

        [2] = {

                .start = IRQ_EINT7,

                .end   = IRQ_EINT7,

                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,

        }

};

④添加static struct dm9000_plat_data mini2440_dm9k_pdata

// add by xuepeng

/*

 *  * The DM9000 has no eeprom, and it's MAC address is set by

 *   * the bootloader before starting the kernel.

 *    */

static struct dm9000_plat_data mini2440_dm9k_pdata = {

        .flags  =  (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),

};

⑤添加static struct platform_device mini2440_device_eth

// add by xuepeng

static struct platform_device mini2440_device_eth = {

         .name           = "dm9000",

         .id             = -1,

         .num_resources  = ARRAY_SIZE(mini2440_dm9k_resource),

         .resource       = mini2440_dm9k_resource,

         .dev            = {

                 .platform_data  = &mini2440_dm9k_pdata,

         },

};

如下图:

⑥mini2440_devices[]中添加平台设备。

&mini2440_device_eth, // add by xuepeng

如下图:

》》》》》》》》》drivers/net/dm9000.c文件中:

⑦添加头文件。

// add by xuepeng

#if defined(CONFIG_ARCH_S3C2410)

#include <mach/regs-mem.h>

#endif

如下图:

⑧修改dm9000_init函数。

函数开始处添加:

// add by xuepeng

#if defined(CONFIG_ARCH_S3C2410)

unsigned int oldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON;

unsigned int oldval_bankcon4 = *(volatile unsigned int *)S3C2410_BANKCON4;

*((volatile unsigned int *)S3C2410_BWSCON) =

(oldval_bwscon & ~(3<<16)) | S3C2410_BWSCON_DW4_16 | S3C2410_BWSCON_WS4 | S3C2410_BWSCON_ST4;

*((volatile unsigned int *)S3C2410_BANKCON4) = 0x1f7c;

#endif

如下图:

⑨修改dm9000_probe函数。

if (!is_valid_ether_addr(ndev->dev_addr))前添加:(大约1464行)

// add by xuepeng

memcpy(ndev->dev_addr, "\x08\x90\x90\x90\x90\x90", 6);

如下图:

⑩配置编译内核。

Device Drivers --->

Network device support --->

Ethernet(10 or 100Mbit) --->

<*> DM9000 support

可见,Linux-2.6.32.2已经默认支持DM9000了。

# make zImage

烧写到开发板,运行ifconfig命令,检验是否有eth0信息。

A,没有移植DM9000之前:

B,移植DM9000之后:

此时的启动信息见/temp/串口输出信息3.txt

10,激活TRC驱动

Linux-2.6.32.22440RTC驱动已经十分完善了,只需要将设备加入即可。

(修改arch/arm/mach-s3c2440/mach-mini2440.c

static struct platform_device *mini2440_devices[]中添加平台设备:

&s3c_device_rtc, // add by xuepeng

如下图:

②配置内核。

# make menuconfig

Device Drivers --->

<*> Real Time Clock --->

如下图:

可见,linux-2.6.32.2已经默认选择了RTC相关的选项。

这里需要特别注意的地方是最下方的<*> Sansung S3C series SoC RTC选项,因为这里才是内核中真正的2440RTC驱动配置项。

③编译测试。

# make zImage

烧写到开发平台,输入如下命令测试:

# date -s 052617142012.00

# hwclock -w

A,加入RTC驱动前:

B,加入RTC驱动后:

另外,还可以通过查看/dev/下是否有rtc设备驱动:

11,添加背光驱动

①添加mini2440_backlight.c文件。

drivers/video目录下添加一个mini2440_backlight.c的驱动文件。内容如下:

// 以下头文件可能并不是每一个必须的,但多余的并不会影响驱动程序的内容

#include <linux/errno.h>

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/slab.h>

#include <linux/input.h>

#include <linux/init.h>

#include <linux/serio.h>

#include <linux/delay.h>

#include <linux/clk.h>

#include <linux/miscdevice.h>

#include <linux/gpio.h>

#include <asm/io.h>

#include <asm/irq.h>

#include <asm/uaccess.h>

#include <mach/regs-clock.h>

#include <plat/regs-timer.h>

 

#include <mach/regs-gpio.h>

#include <linux/cdev.h>

#undef DEBUG

//#define DEBUG

#ifdef DEBUG

#define DPRINTK(x...) {printk(__FUNCTION__"(%d): ",__LINE__);printk(##x);}

#else

#define DPRINTK(x...) (void)(0)

#endif

// 定义背光驱动的名称为backlight,将会出现在/dev/backlight

#define DEVICE_NAME "backlight"

// 定义背光驱动变量bl_state,以记录背光的开关状态

static unsigned int bl_state;

// 设置背光开关的函数,主要是翻转背光变量bl_state

static inline void set_bl(int state)

{

bl_state = !!state; // 翻转bl_state变量

s3c2410_gpio_setpin(S3C2410_GPG(4), bl_state); // 把结果写入背光所用的寄存器GPG4

}

// 获取背光状态

static inline unsigned int get_bl(void)

{

return bl_state;

}

// 从应用程序读取参数,并传递到内核中

static ssize_t dev_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)

{

unsigned char ch;

int ret;

if (count == 0) {

return count;

}

// 使用copy_from_user函数从用户层/应用层读取参数

ret = copy_from_user(&ch, buffer, sizeof ch) ? -EFAULT : 0;

if (ret) {

return ret;

}

ch &= 0x01; // 判断奇数还是偶数

set_bl(ch); // 设置背光状态

return count;

}

// 把内核参数传递给用户层/应用层的读函数

static ssize_t dev_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)

{

int ret;

unsigned char str[] = {'0', '1' };

if (count == 0) {

return 0;

}

// 使用copy_to_user函数把内核参数传递到用户层/应用层

ret = copy_to_user(buffer, str + get_bl(), sizeof(unsigned char) ) ? -EFAULT : 0;

if (ret) {

return ret;

}

return sizeof(unsigned char);

}

// 设备操作集

static struct file_operations dev_fops = {

owner: THIS_MODULE,

read: dev_read,

write: dev_write,

};

static struct miscdevice misc = {

.minor = MISC_DYNAMIC_MINOR,

.name = DEVICE_NAME,

.fops = &dev_fops,

};

// 设备初始化,内核启动时就有效

static int __init dev_init(void)

{

int ret;

ret = misc_register(&misc);

printk (DEVICE_NAME"\tinitialized\n");

// 初始化背光所用的端口GPG4为输出

s3c2410_gpio_cfgpin(S3C2410_GPG(4), S3C2410_GPIO_OUTPUT);

// 启动内核时打开背光

set_bl(1);

return ret;

}

static void __exit dev_exit(void)

{

misc_deregister(&misc);

}

module_init(dev_init); // 注册背光驱动模块

module_exit(dev_exit); // 卸载背光驱动模块

MODULE_LICENSE("GPL");

MODULE_AUTHOR("FriendlyARM Inc.");

②把背光配置加入到内核配置菜单。

# vi drivers/video/Kconfig

config FB_S3C2410_DEBUG

config FB_SM501

之间,添加:

config BACKLIGHT_MINI2440

tristate "Backlight support for mini2440 from FriendlyARM"

depends on MACH_MINI2440 && FB_S3C2410

help

  backlight driver for MINI2440 from FriendlyARM

如下图:

③在Makefile中,根据配置定义加入驱动目标文件。

# vi drivers/video/Makefile

在最后,添加:

obj-$(CONFIG_BACKLIGHT_MINI2440) += mini2440_backlight.o

如下图:

④配置内核。

# make menuconfig

Device Drivers --->

Graphics support --->

<*> Support for frame buffer devices --->

选上:

< > Backlight support for mini2440 from FriendlyARM

如下图:

保存、退出。

⑤编译、测试。

# make zImage

烧写到开发平台,并启动。可以看到屏幕有闪烁了。

进入命令行,输入命令测试:

# echo 0 > /dev/backlight 可以关闭LCD背光(发送偶数)

# echo 1 > /dev/backlight 可以打开LCD背光(发送奇数)

12,移植LCD显示驱动

①删除原先的LCD设备平台代码。

# vi arch/arm/mach-s3c2440/mach-mini2440.c

删掉以下代码:(大约200行左右)

/* LCD driver info */

static struct s3c2410fb_display mini2440_lcd_cfg __initdata = {

.lcdcon5 = S3C2410_LCDCON5_FRM565 |

  S3C2410_LCDCON5_INVVLINE |

  S3C2410_LCDCON5_INVVFRAME |

  S3C2410_LCDCON5_PWREN |

  S3C2410_LCDCON5_HWSWP,

.type = S3C2410_LCDCON1_TFT,

.width = 240,

.height = 320,

.pixclock = 166667, /* HCLK 60 MHz, divisor 10 */

.xres = 240,

.yres = 320,

.bpp = 16,

.left_margin = 20,

.right_margin = 8,

.hsync_len = 4,

.upper_margin = 8,

.lower_margin = 7,

.vsync_len = 4,

};

static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {

.displays = &mini2440_lcd_cfg,

.num_displays = 1,

.default_display = 0,

#if 0

/* currently setup by downloader */

.gpccon = 0xaa940659,

.gpccon_mask = 0xffffffff,

.gpcup = 0x0000ffff,

.gpcup_mask = 0xffffffff,

.gpdcon = 0xaa84aaa0,

.gpdcon_mask = 0xffffffff,

.gpdup = 0x0000faff,

.gpdup_mask = 0xffffffff,

#endif

.lpcsel = ((0xCE6) & ~7) | 1<<4,

};

②增加新LCD代码

代码如下:

// add by xuepneg

/* LCD driver info */

// NEC 3.5"的配置和参数设置

#if defined(CONFIG_FB_S3C2410_N240320)

#define LCD_WIDTH 240

#define LCD_HEIGHT 320

#define LCD_PIXCLOCK 100000

#define LCD_RIGHT_MARGIN 36

#define LCD_LEFT_MARGIN 19

#define LCD_HSYNC_LEN 5

#define LCD_UPPER_MARGIN 1

#define LCD_LOWER_MARGIN 5

#define LCD_VSYNC_LEN 1

// 夏普 8"的配置和参数设置

#elif defined(CONFIG_FB_S3C2410_TFT640480)

#define LCD_WIDTH 640

#define LCD_HEIGHT 480

#define LCD_PIXCLOCK 80000

#define LCD_RIGHT_MARGIN 67 

#define LCD_LEFT_MARGIN 40

#define LCD_HSYNC_LEN 31

#define LCD_UPPER_MARGIN 25

#define LCD_LOWER_MARGIN 5

#define LCD_VSYNC_LEN 1

// 统宝 3.5"的配置和参数设置

#elif defined(CONFIG_FB_S3C2410_T240320)

#define LCD_WIDTH 240

#define LCD_HEIGHT 320

#define LCD_PIXCLOCK 146250 // 170000

#define LCD_RIGHT_MARGIN 25

#define LCD_LEFT_MARGIN 0

#define LCD_HSYNC_LEN 4

#define LCD_UPPER_MARGIN 1

#define LCD_LOWER_MARGIN 4

#define LCD_VSYNC_LEN 1

// 群创 7"的配置和参数设置

#elif defined(CONFIG_FB_S3C2410_TFT800480)

#define LCD_WIDTH 800

#define LCD_HEIGHT 480

#define LCD_PIXCLOCK 11463 // 40000

#define LCD_RIGHT_MARGIN 67

#define LCD_LEFT_MARGIN 40

#define LCD_HSYNC_LEN 31

#define LCD_UPPER_MARGIN 25

#define LCD_LOWER_MARGIN 5

#define LCD_VSYNC_LEN 1

// LCD2VGA(分辨率为1024x768)模块的配置和参数设置

#elif defined(CONFIG_FB_S3C2410_VGA1024768)

#define LCD_WIDTH 1024

#define LCD_HEIGHT 768

#define LCD_PIXCLOCK 80000

#define LCD_RIGHT_MARGIN 15

#define LCD_LEFT_MARGIN 199

#define LCD_HSYNC_LEN 15

#define LCD_UPPER_MARGIN 1

#define LCD_LOWER_MARGIN 1

#define LCD_VSYNC_LEN 1

#define LCD_CON5 (S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_HWSWP)

#endif

// add by xuepeng

#if defined (LCD_WIDTH)

static struct s3c2410fb_display mini2440_lcd_cfg __initdata = {

#if !defined (LCD_CON5)

.lcdcon5 = S3C2410_LCDCON5_FRM565 |

  S3C2410_LCDCON5_INVVLINE |

  S3C2410_LCDCON5_INVVFRAME |

  S3C2410_LCDCON5_PWREN |

  S3C2410_LCDCON5_HWSWP,

#else

.lcdcon5 = LCD_CON5,

#endif

.type = S3C2410_LCDCON1_TFT,

.width = LCD_WIDTH,

.height = LCD_HEIGHT,

.pixclock = LCD_PIXCLOCK,

.xres = LCD_WIDTH,

.yres = LCD_HEIGHT,

.bpp = 16,

.left_margin = LCD_LEFT_MARGIN + 1,

.right_margin = LCD_RIGHT_MARGIN + 1,

.hsync_len = LCD_HSYNC_LEN + 1,

.upper_margin = LCD_UPPER_MARGIN + 1,

.lower_margin = LCD_LOWER_MARGIN + 1,

.vsync_len = LCD_VSYNC_LEN + 1,

};

// add by xuepeng

static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {

.displays = &mini2440_lcd_cfg,

.num_displays = 1,

.default_display = 0,

.gpccon =       0xaa955609,

.gpccon_mask =  0xffc003cc,

.gpcup =        0x0000ffff,

.gpcup_mask =   0xffffffff,

.gpdcon =       0xaa95aaa1,

.gpdcon_mask =  0xffc0fff0,

.gpdup =        0x0000faff,

.gpdup_mask =   0xffffffff,

.lpcsel = 0xf82,

};

#endif

③修改mini2440_machine_init函数。

mini2440_machine_init函数中,将

s3c24xx_fb_set_platdata(&mini2440_fb_info);

改为:

#if defined (LCDD_WIDTH)

     s3c24xx_fb_set_platdata(&mini2440_fb_info);

#endif

如下图:

④增加配置选项。

# vi drivers/video/Kconfig

1930行左右添加:

# add by xuepeng

choice

prompt "LCD select"

depends on FB_S3C2410

help

   S3C24x0 LCD size select

config FB_S3C2410_T240320

boolean "3.5 inch 240X320 Toppoly LCD"

depends on FB_S3C2410

help

  3.5 inch 240X320 Toppoly LCD

config FB_S3C2410_N240320

boolean "3.5 inch 240X320 NEC LCD"

depends on FB_S3C2410

help

   3.5 inch 240x320 NEC LCD

config FB_S3C2410_TFT640480

boolean "8 inch 640X480 L80 LCD"

depends on FB_S3C2410

help

   8 inch 640X480 LCD

config FB_S3C2410_TFT800480

boolean "7 inch 800x480 TFT LCD"

depends on FB_S3C2410

help

   7 inch 800x480 TFT LCD

config FB_S3C2410_VGA1024768

boolean "VGA 1024x768"

depends on FB_S3C2410

help

   VGA 1024x768

endchoice

如下图:

……

⑤修改drivers/video/s3c2410_fb.c文件。(为什么修改?有待探讨!!!!!!!)

# vi drivers/video/s3c2410_fb.c

688行左右,s3c2410fb_init_registers函数中,添加变量:

unsigned long tmp; // add by xuepeng

709行左右,添加:

// add by xuepeng

tmp = readl(S3C2410_GPCCON) & 0xFFFFFF0F;

tmp = tmp | 0x00000050; 

writel(tmp , S3C2410_GPCCON);

// add by xuepeng

tmp = readl(S3C2410_GPCDAT) & 0xFFF3;

writel(tmp , S3C2410_GPCDAT);

⑥配置内核

# make menuconfig

Device Drivers --->

Graphics support --->

<*> Support for frame buffer devices --->

LCD select (3.5 inch 240X320 Toppoly LCD) --->

选中:

( ) 7 inch 800x480 FTF LCD

保存、退出。

⑦编译、测试。

# make zImage

zImage烧写到开发平台,并启动。

可以看到一个可爱的小企鹅在屏幕的左上方。O(_)o 

13,修改Linux Logo

开机logo对应文件是:drivers/video/logo/logo_linux_clut224.ppm

①使用LogoMaker制作Linux LOGO.

Ø LogoMaker的安装:

A,官网下载LogoMaker

B,执行命令:

# tar zxvf logomaker.tgz -C /

执行以上命令,LogoMaker将会安装到/usr/sbin目录下。

Ø LogoMaker的使用:

A,终端下运行命令:

# logomaker

即可启动LogoMaker

B,打开一张图片。

注意打开图片的大小!!!!!

C,转换并保存。

点击File->Convert the picture to a Linux Logo File,会打开如下对话框:

点击“打开”即可。(此处应该是“保存”,软件有缺陷!)

此时,就会自动生成一个logo_linux_clut224.ppm文件。

②覆盖源码文件。

将生成的logo_linux_clut224.ppm文件,替换掉drivers/video/logo/logo_linux_clut224.ppm即可。

③编译、测试。

# make zImage

烧写到开发平台,开机。会发现开机Logo已经换成了我们刚才制作的那个了。

14,添加ADC驱动

需要解决ADC和触摸屏共享资源问题。

①添加驱动文件

drivers/char/下建立文件:mini2440_adc.c,内容如下:

// add by xuepeng

#include <linux/errno.h>

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/slab.h>

#include <linux/input.h>

#include <linux/init.h>

#include <linux/serio.h>

#include <linux/delay.h>

#include <linux/clk.h>

#include <linux/wait.h>

#include <linux/sched.h>

#include <asm/io.h>

#include <asm/irq.h>

#include <asm/uaccess.h>

#include <mach/regs-clock.h>

#include <plat/regs-timer.h>

 

#include <plat/regs-adc.h>

#include <mach/regs-gpio.h>

#include <linux/cdev.h>

#include <linux/miscdevice.h>

//自己定义的头文件,因原生内核并没有包含

#include "s3c24xx-adc.h"

#undef DEBUG

//#define DEBUG

#ifdef DEBUG

#define DPRINTK(x...) {printk(__FUNCTION__"(%d): ",__LINE__);printk(##x);}

#else

#define DPRINTK(x...) (void)(0)

#endif

// 定义ADC转换设备名称,将出现在/dev/adc

#define DEVICE_NAME "adc"

static void __iomem *base_addr;

// 定义ADC设备结构

typedef struct {

wait_queue_head_t wait;

int channel;

int prescale;

}ADC_DEV;

// 声明全局信号量,以便和触摸屏驱动程序共享A/D转换器

DECLARE_MUTEX(ADC_LOCK);

// ADC驱动是否拥有A/D转换器资源的状态变量

static int OwnADC = 0;

static ADC_DEV adcdev;

static volatile int ev_adc = 0;

static int adc_data;

static struct clk *adc_clock;

// 定义ADC相关的寄存器

#define ADCCON      (*(volatile unsigned long *)(base_addr + S3C2410_ADCCON)) //ADC control

#define ADCTSC      (*(volatile unsigned long *)(base_addr + S3C2410_ADCTSC)) //ADC touch screen control

#define ADCDLY      (*(volatile unsigned long *)(base_addr + S3C2410_ADCDLY)) //ADC start or Interval Delay

#define ADCDAT0     (*(volatile unsigned long *)(base_addr + S3C2410_ADCDAT0)) //ADC conversion data 0

#define ADCDAT1     (*(volatile unsigned long *)(base_addr + S3C2410_ADCDAT1)) //ADC conversion data 1

#define ADCUPDN     (*(volatile unsigned long *)(base_addr + 0x14)) //Stylus Up/Down interrupt status

#define PRESCALE_DIS        (0 << 14)

#define PRESCALE_EN         (1 << 14)

#define PRSCVL(x)           ((x) << 6)

#define ADC_INPUT(x)        ((x) << 3)

#define ADC_START           (1 << 0)

#define ADC_ENDCVT          (1 << 15)

// 定义“开启AD输入”宏,因为比较简单,故没有做成函数

#define START_ADC_AIN(ch, prescale) \

do{ \

ADCCON = PRESCALE_EN | PRSCVL(prescale) | ADC_INPUT((ch)) ; \

ADCCON |= ADC_START; \

}while(0)

// ADC中断处理函数

static irqreturn_t adcdone_int_handler(int irq, void *dev_id)

{

// 如果ADC驱动拥有“A/D转换器”资源,则从ADC寄存器读取转换结果

if (OwnADC) {

adc_data = ADCDAT0 & 0x3ff;

ev_adc = 1;

wake_up_interruptible(&adcdev.wait);

}

return IRQ_HANDLED;

}

// ADC读函数,一般对应于用户层/应用层的设备读函数(read

static ssize_t s3c2410_adc_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)

{

char str[20];

int value;

size_t len;

// 判断“A/D转换器”资源是否可用

if (down_trylock(&ADC_LOCK) == 0) {

OwnADC = 1; // 标记“A/D转换器”资源状态为可用

START_ADC_AIN(adcdev.channel, adcdev.prescale); // 开始转换

wait_event_interruptible(adcdev.wait, ev_adc); // 通过终端的方式等待转换结果

ev_adc = 0;

DPRINTK("AIN[%d] = 0x%04x, %d\n", adcdev.channel, adc_data, ADCCON & 0x80 ? 1:0);

// 把转换结果赋予value,以便传递到用户层/应用层

value = adc_data;

// 释放“A/D转换器”资源

OwnADC = 0;

up(&ADC_LOCK);

} else {

// 没有“A/D转换器”资源,赋值为“-1

value = -1;

}

len = sprintf(str, "%d\n", value);

if (count >= len) {

// 把转换结果传递到用户层/应用层

int r = copy_to_user(buffer, str, len);

return r ? r : len;

} else {

return -EINVAL;

}

}

// 打开ADC设备的函数,一般对应于用户态程序的open

static int s3c2410_adc_open(struct inode *inode, struct file *filp)

{

// 初始化中断队列

init_waitqueue_head(&(adcdev.wait));

// 缺省通道为“0

adcdev.channel=0;

adcdev.prescale=0xff;

DPRINTK( "adc opened\n");

return 0;

}

static int s3c2410_adc_release(struct inode *inode, struct file *filp)

{

DPRINTK( "adc closed\n");

return 0;

}

static struct file_operations dev_fops = {

owner: THIS_MODULE,

open: s3c2410_adc_open,

read: s3c2410_adc_read,

release: s3c2410_adc_release,

};

static struct miscdevice misc = {

.minor = MISC_DYNAMIC_MINOR,

.name = DEVICE_NAME,

.fops = &dev_fops,

};

static int __init dev_init(void)

{

int ret;

base_addr=ioremap(S3C2410_PA_ADC,0x20);

if (base_addr == NULL) {

printk(KERN_ERR "Failed to remap register block\n");

return -ENOMEM;

}

adc_clock = clk_get(NULL, "adc");

if (!adc_clock) {

printk(KERN_ERR "failed to get adc clock source\n");

return -ENOENT;

}

clk_enable(adc_clock);

/* normal ADC */

ADCTSC = 0;

// 注册中断

ret = request_irq(IRQ_ADC, adcdone_int_handler, IRQF_SHARED, DEVICE_NAME, &adcdev);

if (ret) {

iounmap(base_addr);

return ret;

}

// 注册设备

ret = misc_register(&misc);

printk (DEVICE_NAME"\tinitialized\n");

return ret;

}

static void __exit dev_exit(void)

{

// 释放中断

free_irq(IRQ_ADC, &adcdev);

iounmap(base_addr);

if (adc_clock) {

clk_disable(adc_clock);

clk_put(adc_clock);

adc_clock = NULL;

}

misc_deregister(&misc);

}

// 导出信号量“ADC_LOCK,以便触摸屏驱动使用

EXPORT_SYMBOL(ADC_LOCK);

module_init(dev_init);

module_exit(dev_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("FriendlyARM Inc.");

②添加头文件。

drivers/char/下新建文件:s3c24xx-adc.h,内容如下:

#ifndef _S3C2410_ADC_H_

#define _S3C2410_ADC_H_

#define ADC_WRITE(ch, prescale) ((ch)<<16|(prescale))

#define ADC_WRITE_GETCH(data) (((data)>>16)&0x7)

#define ADC_WRITE_GETPRE(data) ((data)&0xff)

#endif /* _S3C2410_ADC_H_ */

③修改Makefile文件。

# vi drivers/char/Makefile

114行左右,添加:

Obj-$(CONFIG_MINI2440_ADC) += mini2440_adc.o

如下图:

④添加配置选项。

# vi drivers/char/Kconfig

100行左右,添加:

# add by xuepeng

config MINI2440_ADC

bool "ADC driver for FriendlyARM Mini2440 development boards"

depends on MACH_MINI2440

default y if MACH_MINI2440

help

this is ADC driver for FriendlyARM Mini2440 development boards

Nots:the touch-screen-driver required this option

如下图:

⑤配置内核。

# make menuconfig

Device Drivers --->

Character devices --->

选上:

[*] ADC driver for FriendlyARM Mini2440 development boards (NEW)

如下图:

⑥编译、测试内核。

# make zImage

烧写进开发平台,编写测试程序如下:

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/ioctl.h>

#include <fcntl.h>

#include <linux/fs.h>

#include <errno.h>

#include <string.h>

int main(void)

{

fprintf(stderr, "press Ctrl-C to stop\n");

int fd = open("/dev/adc", 0);

if (fd<0)

{

perror("open ADC device:");

return 1;

}

for(;;)

{

char buffer[30];

int len = read(fd, buffer, sizeof(buffer)-1);

if (len >0)

{

buffer[len] = '\0';

int value = -1;

sscanf(buffer, "%d", &value);

}

else

{

perror("read ADC device:");

return 1;

}

usleep(500*1000);

}

close(fd);

}

据《Mini2440_Linux移植开发实战指南》:

运行test_adc,旋转开发板上的 W1可调电阻,可以看到 ADC转换的结果也在变动,按下触摸屏时,会输出“-1 ”,这和我们在驱动程序中设置的结果是一样的,如图:

但是我们怎么没有任何反应呢?可能是A/D的线路连接方式不一样?还是有的驱动还未移植啊?不懂!稍后再说。

15,添加触摸屏驱动

触摸屏的原理有待加强!

①添加驱动文件。

drivers/input/touchscreen下新建文件s3c2410_ts.c,内容如下:

#include <linux/errno.h>

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/slab.h>

#include <linux/input.h>

#include <linux/init.h>

#include <linux/serio.h>

#include <linux/delay.h>

#include <linux/platform_device.h>

#include <linux/clk.h>

#include <linux/gpio.h>

#include <asm/io.h>

#include <asm/irq.h>

#include <plat/regs-adc.h>

#include <mach/regs-gpio.h>

/* For ts.dev.id.version */

#define S3C2410TSVERSION 0x0101

#define WAIT4INT(x)  (((x)<<8) | \

     S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \

     S3C2410_ADCTSC_XY_PST(3))

#define AUTOPST      (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \

     S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))

static char *s3c2410ts_name = "s3c2410 TouchScreen";

static struct input_dev *dev;

static long xp;

static long yp;

static int count;

extern struct semaphore ADC_LOCK;

static int OwnADC = 0;

static void __iomem *base_addr;

static inline void s3c2410_ts_connect(void)

{

s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON);

s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON);

s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON);

s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON);

}

static void touch_timer_fire(unsigned long data)

{

   unsigned long data0;

   unsigned long data1;

int updown;

   data0 = ioread32(base_addr+S3C2410_ADCDAT0);

   data1 = ioread32(base_addr+S3C2410_ADCDAT1);

  updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));

  if (updown) {

  if (count != 0) {

long tmp;

                                                                                                 

tmp = xp;

xp = yp;

yp = tmp;

                                                                                                 

                        xp >>= 2;

                        yp >>= 2;

  input_report_abs(dev, ABS_X, xp);

  input_report_abs(dev, ABS_Y, yp);

  input_report_key(dev, BTN_TOUCH, 1);

  input_report_abs(dev, ABS_PRESSURE, 1);

  input_sync(dev);

  }

  xp = 0;

  yp = 0;

  count = 0;

  iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);

  iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);

  } else {

  count = 0;

  input_report_key(dev, BTN_TOUCH, 0);

  input_report_abs(dev, ABS_PRESSURE, 0);

  input_sync(dev);

  iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);

if (OwnADC) {

OwnADC = 0;

up(&ADC_LOCK);

}

  }

}

static struct timer_list touch_timer =

TIMER_INITIALIZER(touch_timer_fire, 0, 0);

static irqreturn_t stylus_updown(int irq, void *dev_id)

{

unsigned long data0;

unsigned long data1;

int updown;

if (down_trylock(&ADC_LOCK) == 0) {

OwnADC = 1;

data0 = ioread32(base_addr+S3C2410_ADCDAT0);

data1 = ioread32(base_addr+S3C2410_ADCDAT1);

updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));

if (updown) {

touch_timer_fire(0);

} else {

OwnADC = 0;

up(&ADC_LOCK);

}

}

return IRQ_HANDLED;

}

static irqreturn_t stylus_action(int irq, void *dev_id)

{

unsigned long data0;

unsigned long data1;

if (OwnADC) {

data0 = ioread32(base_addr+S3C2410_ADCDAT0);

data1 = ioread32(base_addr+S3C2410_ADCDAT1);

xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;

yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;

count++;

    if (count < (1<<2)) {

iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);

iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);

} else {

mod_timer(&touch_timer, jiffies+1);

iowrite32(WAIT4INT(1), base_addr+S3C2410_ADCTSC);

}

}

return IRQ_HANDLED;

}

static struct clk *adc_clock;

static int __init s3c2410ts_init(void)

{

struct input_dev *input_dev;

adc_clock = clk_get(NULL, "adc");

if (!adc_clock) {

printk(KERN_ERR "failed to get adc clock source\n");

return -ENOENT;

}

clk_enable(adc_clock);

base_addr=ioremap(S3C2410_PA_ADC,0x20);

if (base_addr == NULL) {

printk(KERN_ERR "Failed to remap register block\n");

return -ENOMEM;

}

/* Configure GPIOs */

s3c2410_ts_connect();

iowrite32(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF),\

     base_addr+S3C2410_ADCCON);

iowrite32(0xffff,  base_addr+S3C2410_ADCDLY);

iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);

/* Initialise input stuff */

input_dev = input_allocate_device();

if (!input_dev) {

printk(KERN_ERR "Unable to allocate the input device !!\n");

return -ENOMEM;

}

dev = input_dev;

dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);

dev->keybit[BITS_TO_LONGS(BTN_TOUCH)] = BIT(BTN_TOUCH);

input_set_abs_params(dev, ABS_X, 0, 0x3FF, 0, 0);

input_set_abs_params(dev, ABS_Y, 0, 0x3FF, 0, 0);

input_set_abs_params(dev, ABS_PRESSURE, 0, 1, 0, 0);

dev->name = s3c2410ts_name;

dev->id.bustype = BUS_RS232;

dev->id.vendor = 0xDEAD;

dev->id.product = 0xBEEF;

dev->id.version = S3C2410TSVERSION;

/* Get irqs */

if (request_irq(IRQ_ADC, stylus_action, IRQF_SHARED|IRQF_SAMPLE_RANDOM,

"s3c2410_action", dev)) {

printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");

iounmap(base_addr);

return -EIO;

}

if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,

"s3c2410_action", dev)) {

printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");

iounmap(base_addr);

return -EIO;

}

printk(KERN_INFO "%s successfully loaded\n", s3c2410ts_name);

/* All went ok, so register to the input system */

input_register_device(dev);

return 0;

}

static void __exit s3c2410ts_exit(void)

{

disable_irq(IRQ_ADC);

disable_irq(IRQ_TC);

free_irq(IRQ_TC,dev);

free_irq(IRQ_ADC,dev);

if (adc_clock) {

clk_disable(adc_clock);

clk_put(adc_clock);

adc_clock = NULL;

}

input_unregister_device(dev);

iounmap(base_addr);

}

module_init(s3c2410ts_init);

module_exit(s3c2410ts_exit);

②修改Makefile文件。

# vi drivers/input/touchscreen/Makefile

在最后,添加:

obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o

如下图:

③添加配置选项。

# vi drivers/input/touchscreen/Kconfig

添加:

config TOUCHSCREEN_S3C2410 

tristate "Samsung S3C2410 touchscreen input driver" 

depends on MACH_MINI2440 && INPUT && INPUT_TOUCHSCREEN && MINI2440_ADC 

help 

Say Y here if you have the s3c2410 touchscreen. 

If unsure, say N. 

 

To compile this driver as a module, choose M here: the 

module will be called s3c2410_ts.

如下图:

④配置内核。

# make menuconfig

Device Drivers --->

Input device support --->

[*] Touchscreens --->

选上:

<*> Samsung S3C2410 touchscreen input driver (NEW)

如下图:

保存、退出。

⑤编译、测试。

# make zImage

烧写到开发平台。启动开发平台,会进入调整触摸屏的界面:

成功啦。

16,配置USB外设

①配置和测试USB键盘、扫描器和鼠标。

对应内核代码为:drivers/hid/usbhid

Ø 配置:

# make menuconfig

Device Drivers --->

[*] HID Devices --->

选上:

<*> USB Human Interface Device (full HID) support

如下图:

Ø 测试:

# make zImage

烧写入开发平台,插入USB鼠标和键盘即可测试。

②配置测试优盘。

Ø 配置:

# make menuconfig

Device Drivers --->

SCSI device support --->

选上:

<*> SCSI device support

<*> SCSI disk support

如下图:

返回Device Drivers菜单,选择

[*] USB support --->

选上:

<*> USB Mass Storage support

如下图:

返回配置主界面,选择:

File systems --->

DOS/FAT/NT Filesystems --->

选上:

<*> MSDOS fs support

返回File systems菜单,选择:

_*_ Native language support --->

选上:

<*> Codepage 437 (United States, Canada)

<*> NLS ISO 8859-1 (Latin 1;Western European Languages)

<*> NLS UTF-8

如下图:

Ø 测试:

# make zImage

烧写进开发平台,启动开发平台。

待启动完毕后插入优盘,会在控制终端中输出以下信息:

③配置和测试USB摄像头

Ø 配置:

# make menuconfig

Device Drivers --->

选上:

<*> Multimedia support --->

选上:

<*> Video For Linux

进入:

[*] Video capture adapters (NEW) --->

[*] V4L USB devices (NEW) --->

选上并进入:

<*> GSPCA based webcams --->

选择所有(如下图):

说明:GSPCA是一个法国程序员写的万能USB摄像头驱动程序。

Ø 测试:(未测试)

# make zImage

烧写进开发平台,启动,插入USB摄像头,打开root_qtopia文件系统带的USB摄像头预览程序进行测试。

④配置和测试USB无线网卡

Ø 配置:

# make menuconfig

n 添加无线网络协议。

[*] Netwoking support --->

[*] Wireless --->

选上:

<*> cfg80211 - wireless configuration API

<*> Generic IEEE 802.11 Networking Stack (mac80211)

如下图:

n 配置无线网卡驱动。

退回到配置主界面。

Device Drivers --->

[*] Network device support --->

[*] Wireless LAN --->

[*] Wireless LAN (IEEE 802.11) --->

我全部选上了。(如下图)

Ø 测试:

# make zImage

烧写进开发平台,启动。

但是,插入USB无线网卡后,并没有启动无线网络连接。没有eth1。有待追究!!!

17,移植SD卡驱动

Linux-2.6.32.2已经自带了s3c2440芯片的SD卡驱动,我们只需在初始化代码中加入SD平台设备结构即可。

# vi arch/arm/mach-s3c2440/mach-mini2440.c

①添加头文件。

#include <linux/mmc/host.h> 

#include <plat/mci.h>

如下图:

②添加static struct s3c24xx_mci_pdata mini2440_mmc_cfg结构体。

/* MMC/SD  */ 

static struct s3c24xx_mci_pdata mini2440_mmc_cfg = { 

   .gpio_detect   = S3C2410_GPG(8), 

   .gpio_wprotect = S3C2410_GPH(8), 

   .set_power     = NULL, 

   .ocr_avail     =  MMC_VDD_32_33|MMC_VDD_33_34, 

}; 

如下图:

③加入到目标平台设备结构体。

 &s3c_device_sdi,

如下图:

④修改drivers/mmc/host/s3cmci.c文件。

SD 卡的驱动程序底层操作实际对应源代码linux-2.6.32.2/drivers/mmc/host/s3cmci.c ,

根据测试,当包含内核打印信息时,SD 卡可以被正常识别使用,而没有打印信息时,则表现

的不太稳定,因此我们在该程序中添加了一句延时代码。如下图:

⑤编译、测试。

# make zImage

因为没有SD卡,所以没有进行测试。

18,移植UDA1341音频驱动

# vi arch/arm/mach-s3c2440/mach-mini2440.c

①添加头文件。

# include <sound/s3c24xx_usa134x.h>

如下图:

②添加static struct s3c24xx_uda134x_platform_data s3c24xx_uda134x_data结构体。

static struct s3c24xx_uda134x_platform_data s3c24xx_uda134x_data = { 

        .l3_clk = S3C2410_GPB(4), 

        .l3_data = S3C2410_GPB(3), 

        .l3_mode = S3C2410_GPB(2), 

        .model = UDA134X_UDA1341, 

}; 

③添加static struct platform_device s3c24xx_uda134x结构体。

static struct platform_device s3c24xx_uda134x = { 

        .name = "s3c24xx_uda134x", 

        .dev = { 

                .platform_data    = &s3c24xx_uda134x_data, 

        } 

}; 

如下图:

④添加UDA134设备平台到内核。

&s3c24xx_uda134x, 

如下图:

⑤配置内核。

# make menuconfig

Device Drivers --->

<*> Sound card support --->

选上:

[*] Preclaim OSS device numbers

进入

<*> Advanced Linux Sound Architecture --->

选择OSS结构相关的配置选项。

进入

<*> ALSA for SoC audio support --->

选上:

_*_ SoC I2C Audio support UDA134X wired to a S3C24XX

如下图:

保存、退出。

⑥编译、测试。

# make zImage

烧写进开发平台。启动。打开root_qtopia文件系统下的madplay播放一首歌曲,把耳机插入插孔测试。

(有待测试!!!)

19,休整串口驱动

①修改arch/arm/mach-s3c2440/mach-mini2440.c

# vi arch/arm/mach-s3c2440/mach-mini2440.c

mini2440_uartcfgs[]中的

[2] = {

……

.ulcon = 0x43,

……

}

改为:

[2] = {

……

.ulcon = 0x03,

……

}

如下图:

②修改drivers/serial/samsung.c文件。

# vi drivers/serial/samsung.c

添加头文件:

#include <linux/gpio.h>

#include <mach/regs-gpio.h>

如下图:

s3c24xx_serial_startup函数中,437行左右添加:

if (port->line == 2) { 

s3c2410_gpio_cfgpin(S3C2410_GPH(6), S3C2410_GPH6_TXD2); 

    s3c2410_gpio_pullup(S3C2410_GPH(6), 1); 

    s3c2410_gpio_cfgpin(S3C2410_GPH(7), S3C2410_GPH7_RXD2); 

    s3c2410_gpio_pullup(S3C2410_GPH(7), 1); 

}

如下图:

③编译、测试。

# make zImage

测试是通过文件系统带的串口助手程序实现的,不过需要用到三针串口线将开发板和电脑相连。(有待测试)

20,移植I2C-EEPROM驱动

Linux-2.6.32.2s3c2440I2C接口提供了完善的驱动,因此只需要配置一下即可。

①配置内核。

# make menuconfig

Device Drivers --->

<*> I2C support --->

I2C Hardware Bus support --->

选上:

<*> S3C2410 I2C Driver

如下图:

可见,内核已经默认选择上了。

②编译、测试。

# make zImage

烧写进开发平台,启动。

在超级终端中输入“i2c -w”即可测试,结果如下:

说明:本开发平台基于I2C总线挂接了一个EEPROM芯片(AT24C08),可通过它进行测试。

i2c的测试程序就是向板子的24C08器件写入数据(0x00-0xff)。

21,移植看门狗驱动

Linux-2.6.32.2内核已经具有完善的S3C2440的看门狗驱动了,我们只需要配置即可。

①配置内核。

# make menuconfig

Device Drivers --->

[*] Watchdog Timer Support --->

内核已经默认选择好了,如下:

对应的驱动源文件是:drivers/watchdog/s3c2410_wdt.c

②编译、测试。

# make zImage

烧写进开发平台,超级终端执行如下命令:

开启看门狗,(随便写入一些数据即可):

# echo 0 > /dev/watchdog

如下图:

等待15s,系统将会重启,证明看门狗已经被启动了。

待开发平台重新启动后,重新输入命令:

# echo 0 > /dev/watchdog

接着输入:

# echo -n V > /dev/watchdog

这里,-n的作用是去掉回车。

再等超过15s,可以看见系统仍然正常运行,证明看门狗已经被关闭了。

 

你可能感兴趣的:(c,测试,Module,buffer,input,平台)