一、内核配置和编译
1.修改顶层Makefile第195行
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-根据自己的环境修改交叉编译器前缀
2.修改arch/arm/boot/Makefile 增加第57行
@echo ' Kernel: $@ is ready'
cp arch/arm/boot/zImage /tftpboot根据自己的ftp服务器目录修改
3.匹配机器码
1) 启动u-boot执行bd将输出开发板的相关信息,包括机器码
TQ2440 # bd
arch_number = 0x0000016A机器码362
boot_params = 0x30000100
DRAM bank = 0x00000000
-> start = 0x30000000
-> size = 0x04000000
ethaddr = 00:01:02:03:04:05
ip_addr = 192.168.1.100
baudrate = 115200 bps
TLB addr = 0x33FF0000
relocaddr = 0x33F40000
reloc off = 0x33F40000
irq_sp = 0x33B2FF68
sp start = 0x33B2FF58
FB base = 0x00000000
TQ2440 #
2) 内核机器码:arch/arm/mach-s3c24xx/mach-smdk2440.c 第178行MACHINE_START(S3C2440, "SMDK2440")
其中的S3C2440即为机器码
再查看arch/arm/tools/mach-types 第88行即为S3C2440所对应的机器码362,必须和u-boot的机器码相同,否则没法启动内核
4.修改系统时钟
arch/arm/mach-s3c24xx/mach-smdk2440.c 第165行,我们的开发板使用12MHZ
s3c24xx_init_clocks(12000000);
5.执行默认配置
root@zjh:/home/work/linux-3.5.5# make s3c2410_defconfig
6.配置内核
root@zjh:/home/work/linux-3.5.5# make menuconfig
Kernel Features --->
[*] Use the ARM EABI to compile the kernel
[*] Allow old ABI binaries to run with this kernel (EXPERIMENTAL)
注:使用 4.X.X 版本的交叉编译器一定要选中以上两项,否则会出现Kernel panic - not syncing: Attempted to kill init! 这样的错误以致没法启动内核
System Type --->
SAMSUNG S3C24XX SoCs Support --->
[*] SAMSUNG S3C2440
[*] SMDK2440
[*] SMDK2440 with S3C2440 CPU module
只选中这三项即可
7.编译内核
root@zjh:/home/work/linux-3.5.5# make zImage
8.制作uImage
1) 将编译好的u-boot目录下的tools目录下的mkimage拷贝到/usr/bin目录下
root@zjh:/home/work# cp u-boot-2012.07/tools/mkimage /usr/bin/
2) 进入/tftpboot目录并制作uImage
root@zjh:/tftpboot# mkimage -n 'linux-3.5.5' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage uImage
Image Name: linux-3.5.5
Created: Thu Oct 4 19:05:36 2012
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2357264 Bytes = 2302.02 kB = 2.25 MB
Load Address: 30008000
Entry Point: 30008040
9.启动u-boot,执行如下操作
TQ2440 # tftp 30008000 uImage
TQ2440 # bootm 30008000
## Booting kernel from Legacy Image at 30008000 ...
Image Name: linux-3.5.5
Created: 2012-10-04 11:05:36 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2357264 Bytes = 2.2 MiB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0
Linux version 3.5.5 (root@zjh) (gcc version 4.3.3 (Sourcery G++ Lite 2009q1-176) ) #1 Thu Oct 4 19:04:53 CST 2012
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache
Machine: SMDK2440
Memory policy: ECC disabled, Data cache writeback
CPU S3C2440A (id 0x32440001)
S3C24XX Clocks, Copyright 2004 Simtec Electronics
S3C244X: core 400.000 MHz, memory 100.000 MHz, peripheral 50.000 MHz
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
…………
二、DM9000网卡驱动移植
1.修改arch/arm/mach-s5pc100/mach-smdkc100.c
第51行添加如下代码
#ifdef CONFIG_DM9000
#include <linux/dm9000.h>
#endif
/* DM9000 Support*/
#ifdef CONFIG_DM9000
static struct resource s3c_dm9000_resources[] = {
[0] = {
.start=S3C2410_CS4,// DM9000网卡基地址,ADDR2=0,发送地址时使用这个地址
.end=S3C2410_CS4 + 0x3,
.flags=IORESOURCE_MEM,
},
[1] = {
.start=S3C2410_CS4 + 0x4, // ADDR2=1,传输数据时使用这个地址
.end=S3C2410_CS4 + 0x4 + 0x3,
.flags=IORESOURCE_MEM,
},
[2] = {
.start=IRQ_EINT7,// 中断号
.end=IRQ_EINT7,
.flags=IORESOURCE_IRQ | IRQF_TRIGGER_RISING,
},
};
static struct dm9000_plat_data s3c_dm9000_platdata = {
.flags = DM9000_PLATF_16BITONLY,
.dev_addr[0] = 0x00,
.dev_addr[1] = 0x00,
.dev_addr[2] = 0x3e,
.dev_addr[3] = 0x26,
.dev_addr[4] = 0x0a,
.dev_addr[5] = 0x00,
};
static struct platform_device s3c_device_dm9000 = {
.name = "dm9000",
.id = 0,
.num_resources = ARRAY_SIZE(s3c_dm9000_resources),
.resource = s3c_dm9000_resources,
.dev = {
.platform_data = &s3c_dm9000_platdata,
}
};
#endif
第202行添加如下代码
&s3c_device_i2c0,
&s3c_device_iis,
#ifdef CONFIG_DM9000
&s3c_device_dm9000,
#endif
2.修改drivers/net/ethernet/davicom/dm9000.c第44行加入如下代码
#include "dm9000.h"
#if defined(CONFIG_ARCH_S3C2440)
#include <mach/regs-mem.h>
#endif
第1375行加入如下代码
u32 id_val;
#if defined(CONFIG_ARCH_S3C2440)
unsigned int oldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON;
unsigned int oldval_bankcon4 = *(volatile unsigned int *)S3C2410_BANKCON4;
#endif
/* Init network device */
第1387行加入如下代码
dev_dbg(&pdev->dev, "dm9000_probe()\n");
#if defined(CONFIG_ARCH_S3C2440)
/* 设置Bank4:总线宽度为16,使能nWAIT */
*((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<16)) |
S3C2410_BWSCON_DW4_16 | S3C2410_BWSCON_WS4 | S3C2410_BWSCON_ST4;
/* 设置Bandk4的时间参数 */
*((volatile unsigned int *)S3C2410_BANKCON4) = 0x1f7c;
#endif
/* setup board info structure */
第1615行
out:
/* 恢复寄存器原来的值 */
#if defined(CONFIG_ARCH_S3C2440)
*(volatile unsigned int *)S3C2410_BWSCON = oldval_bwscon;
*(volatile unsigned int *)S3C2410_BANKCON4 = oldval_bankcon4;
#endif
3.配置内核支持DM9000
root@zjh:/home/work/linux-3.5.5# make menuconfig
[*] Networking support --->
Networking options --->
<*> Packet socket
<*> Unix domain socket
[*] TCP/IP networking
[*] IP: multicasting
[*] IP: kernel level autoconfiguration
[*] IP: BOOTP support
Device Drivers --->
[*] Network device support --->
[*] Ethernet driver support (NEW) --->
<*> DM9000 support
File systems --->
[*] Network File Systems (NEW) --->
<*> NFS client support
[*] NFS client support for NFS version 3 (NEW)
[*] NFS client support for the NFSv3 ACL protocol extension
[*] Root file system on NFS
4.编译内核并制作uImage
5.重新设置u-boot启动参数,通过NFS挂载根文件系统
TQ2440 # set bootargs root=/dev/nfs nfsroot=192.168.1.8:/home/work/rootfs ip=192.168.1.100 init=/linuxrc console=ttySAC0,115200
TQ2440 # save
6.下载内核并启动
TQ2440 # tftp 30008000 uImage
TQ2440 # bootm 30008000
………………
dm9000 Ethernet Driver, V1.31
eth0: dm9000e at c4812000,c4814004 IRQ 51 MAC: 00:00:3e:26:0a:00 (platform data)
………………
dm9000 dm9000.0: >eth0: link down
IP-Config: Guessing netmask 255.255.255.0
IP-Config: Complete:
device=eth0, addr=192.168.1.100, mask=255.255.255.0, gw=255.255.255.255
host=192.168.1.100, domain=, nis-domain=(none)
bootserver=255.255.255.255, rootserver=192.168.1.8, rootpath=
dm9000 dm9000.0: >eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
VFS: Mounted root (nfs filesystem) on device 0:9.
Freeing init memory: 120K
Please press Enter to activate this console. Processing /etc/profile...
Done
[root@tq2440 /]#
三、LED驱动移植
1.在drivers/char/目录下创建文件tq2440_led_drv.c,内容如下
#include <linux/miscdevice.h>
#include <mach/regs-gpio.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <mach/gpio-fns.h>
#define DEVICE_NAME "tq2440_led" /* 设备名,加载模块后执行cat /proc/devices看到的设备名 */
/* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
#define IOCTL_GPIO_ON 1
#define IOCTL_GPIO_OFF 0
static long tq2440_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case IOCTL_GPIO_ON:
// 设置指定引脚的输出电平为0
s3c2410_gpio_setpin(S3C2410_GPB(arg + 5), 0);
return 0;
case IOCTL_GPIO_OFF:
// 设置指定引脚的输出电平为1
s3c2410_gpio_setpin(S3C2410_GPB(arg + 5), 1);
return 0;
default:
return -EINVAL;
}
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = tq2440_gpio_ioctl,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int __init dev_init(void)
{
int ret;
int i;
for (i = 0; i < 4; i++)
{
s3c_gpio_cfgpin(S3C2410_GPB(5 + i), S3C2410_GPIO_OUTPUT);
s3c2410_gpio_setpin(S3C2410_GPB(5 + i), 1); // 初始全灭
}
ret = misc_register(&misc);
printk (DEVICE_NAME" initialized\n");
return ret;
}
static void __exit dev_exit(void)
{
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
2.在内核源码中添加对LED驱动的支持
修改同目录下的Kconfig文件,在menu "Character devices"下面添加
config TQ2440_LED
tristate "TQ2440 LED Device Support"
depends on ARCH_S3C2440
help
support led device on TQ2440 Board
修改同目录下的Makefile,在末尾添加
obj-$(CONFIG_TQ2440_LED)+= tq2440_led_drv.o
3.配置内核支持我们写LED驱动
root@zjh:/home/work/linux-3.5.5# make menuconfig
Device Drivers --->
Character devices --->
<*> TQ2440 LED Device Support
4.编写用户层测试程序led_test.c
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char **argv)
{
int fd;
int led_no;
int led_ctl;
if (argc != 3 || sscanf(argv[1], "%d", &led_no)!= 1 || sscanf(argv[2], "%d", &led_ctl)!= 1 |
led_no < 1 || led_no > 4 || led_ctl < 0 || led_ctl > 1)
{
fprintf(stderr, "Usage:%s led_no 0|1\n", argv[0]);
exit(1);
}
fd = open("/dev/tq2440_led", O_RDONLY);
if (fd < 0)
{
perror("open");
exit(1);
}
ioctl(fd, led_ctl, led_no - 1);
close(fd);
return 0;
}
5.交叉编译led_test.c
root@zjh:/home/work# arm-linux-gcc -static led_test.c -o led
将生成的可执行文件拷贝到根文件系统
root@zjh:/home/work# cp led rootfs
6.重新编译内核,通过NFS挂载
TQ2440 # tftp 30008000 uImage
TQ2440 # bootm 30008000
…………
tq2440_led initialized
…………
[root@tq2440 /]# ./led 1 1 点亮LED1
[root@tq2440 /]# ./led 1 0 熄灭LED1
四、RTC驱动移植
1.在arch/arm/mach-s3c24xx/mach-smdk2440.c添加rtc平台设备列表
&s3c_device_iis,
&s3c_device_rtc,
2.配置内核
Device Drivers --->
[*] Real Time Clock --->
[*] Set system time from RTC on startup and resume (NEW)
(rtc0) RTC used to set the system time
[*] /sys/class/rtc/rtcN (sysfs) (NEW)
[*] /proc/driver/rtc (procfs for rtc0) (NEW)
[*] /dev/rtcN (character devices) (NEW)
<*> Samsung S3C series SoC RTC
3.重新编译内核并下载到开发板
[root@tq2440 /]# date
Sat Oct 6 18:09:55 UTC 2012
[root@tq2440 /]# date -s 2012.10.6-18:11:0 设置时间
Sat Oct 6 18:11:00 UTC 2012
[root@tq2440 /]# hwclock -w 设置硬件时间为当前系统时间
这样系统重启后会自动更新到硬件时间
五、WDT看门狗驱动移植
1.在arch/arm/mach-s3c24xx/mach-smdk2440.c已经添加了wdt平台设备列表
&s3c_device_wdt,
2.修改drivers/watchdog/s3c2410_wdt.c 第52行启动看门狗
#define CONFIG_S3C2410_WATCHDOG_ATBOOT (1) // 启动看门狗
#define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15) //超时值15s
3.配置内核
Device Drivers --->
[*] Watchdog Timer Support --->
<*> S3C2410 Watchdog
4.重新编译内核并下载到开发板,串口输出:
s3c2410_wdt: S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics
s3c2410-wdt s3c2410-wdt: >starting watchdog timer
s3c2410-wdt s3c2410-wdt: >watchdog active, reset enabled, irq disabled
此时由于没有喂狗,系统启动后过会会自动重启
5.编写喂狗程序feed_wdt.c
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/watchdog.h>
int main()
{
int fd;
if ((fd = open("/dev/watchdog", O_RDONLY))< 0)
{
perror("open");
exit(1);
}
for (;;)
{
ioctl(fd, WDIOC_KEEPALIVE);
sleep(3);
}
close(fd);
return 0;
}
6.交叉编译feed_wdt.c
root@zjh://home/work# arm-linux-gcc -static feed_wdt.c -o feed_wdt
将生成的可执行文件feed_wdt拷贝到根文件系统/bin目录下
root@zjh://home/work# cp feed_wdt rootfs/bin/
7.修改启动脚本文件rootfs/etc/init.d/rcS
#!/bin/sh
#This is the first script called by init process
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev>/proc/sys/kernel/hotplug
mdev -s
feed_wdt &
ifconfig lo 127.0.0.1
ifconfig eth0 192.168.1.100 netmask 255.255.255.0
route add default gw 192.168.1.1
六、NAND FLASH驱动移植
1.修改arch/arm/mach-s3c24xx/common-smdk.c
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name= "u-boot",
.size= SZ_256K,
.offset= 0,
},
[1] = {
.name= "kernel",
.offset = SZ_1M,
.size= SZ_1M * 3,
},
[2] = {
.name= "rootfs",
.offset = SZ_4M,
.size= SZ_4M,
},
[3] = {
.name= "usrfs",
.offset= SZ_8M,
.size= MTDPART_SIZ_FULL,
}
};
第148行,根据NAND FLASH芯片手册
static struct s3c2410_platform_nand smdk_nand_info = {
.tacls= 10,
.twrph0= 20,
.twrph1= 10,
.nr_sets = ARRAY_SIZE(smdk_nand_sets),
.sets = smdk_nand_sets,
};
2.配置内核
root@zjh:/home/work/linux-3.5.5# make menuconfig
Device Drivers --->
<*> Memory Technology Device (MTD) support --->
<*> NAND Device Support --->
<*> NAND Flash support for Samsung S3C SoCs
[ ] Samsung S3C NAND Hardware ECC
3.制作cramfs文件系统(首先要确保你已经制作好一个根文件系统)
root@zjh:/home/work# mkfs.cramfs rootfs rootfs.cramfs 注:rootfs为根文件系统目录
将rootfs.cramfs拷贝到ftp服务器目录
root@zjh:/home/work# cp rootfs.cramfs /tftpboot/
将rootfs.cramfs固化到NAND FLASH第3个分区(/dev/mtdblock2)
TQ2440 # tftp 32000000 rootfs.cramfs
TQ2440 # nand erase 400000 400000
TQ2440 # nand write 32000000 400000 400000
4.重新设置u-boot启动参数
TQ2440 # set bootargs root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200
TQ2440 # save
5.下载内核uImage到内存
TQ2440 # tftp 30008000 uImage
TQ2440 # bootm 30008000
## Booting image at 30008000 ...
Image Name: linux-3.5.5
Created: 2012-10-04 15:48:54 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2168120 Bytes = 2.1 MB
Load Address: 30008000
Entry Point: 30008040
Verifying Checksum ... OK
XIP Kernel Image ... OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0
Linux version 3.5.5 (root@zjh) (gcc version 4.3.3 (Sourcery G++ Lite 2009q1-176) ) #4 Thu Oct 4 23:47:56 CST 2012
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache
Machine: SMDK2440
………………
………………
Creating 4 MTD partitions on "NAND":
0x000000000000-0x000000040000 : "u-boot"
0x000000100000-0x000000400000 : "kernel"
0x000000400000-0x000000800000 : "rootfs"
0x000000800000-0x000010000000 : "usrfs"
………………
………………
VFS: Mounted root (cramfs filesystem) readonly on device 31:2.
Freeing init memory: 132K
ifconfig: SIOCSIFADDR: No such device
route: SIOCADDRT: Network is unreachable
Please press Enter to activate this console.
Processing /etc/profile...
Done
[root@tq2440 /]# cat /proc/mtd
dev: size erasesize name
mtd0: 00040000 00020000 "u-boot"
mtd1: 00300000 00020000 "kernel"
mtd2: 00400000 00020000 "rootfs"
mtd3: 0f800000 00020000 "usrfs"