系统移植手册


实验一  交叉工具链的安装    
实验二  u-boot的烧写及使用    
实验三  u-boot-2010.03的移植    
实验四 内核的配置和编译    
实验五 网卡驱动的移植    
实验六 LED驱动的移植    
实验七  Nand flash驱动的移植    
实验八 LCD驱动的移植    
实验九 USB驱动的移植    
实验十  SD卡驱动的移植    
实验十一  yaffs2文件系统的移植    
实验十二 内核调试    
实验十三 内存调试    
实验十四 文件系统的移植    

实验一 交叉工具链的安装

【实验目的】

       了解交叉工具链的编译过程及其使用。

       说明:在实验中命令行提示符“$”表示在主机上运行,“#”表示在目标板上运行

【实验环境】

1、  ubuntu 10.10发行版

2、  FS_S5PC100平台

【实验步骤】

       1、如果要自己编译工具链,从以下链接下载源码

       crosstools-ng下载地址

http://ymorin.is-a-geek.org/download/crosstool-ng/

       同时对每一个版本都有相应的补丁我们尽量把这些补丁打上,这些补丁的下载地址是

http://ymorin.is-a-geek.org/download/crosstool-ng/01-fixes/

 

2、工具的安装

在使用之前先安装下列软件

$ sudo  apt-get  install  gawk  autotools-dev  automake  texinfo  libtool  cvs  patch  bison  flex  libncurses5-dev

为了节约时间,我们已下载了相关的安装包,大家可以在本地安装

$ sudo  dpkg  -i  tools/*.deb

 

3、   解压工具链压缩包

$  cd  ~

$ tar  xvf  arm-cortex_a8-linux-gnueabi.tar.bz2

$ mv  arm-cortex_a8  toolchain

 

4、   环境变量的添加

修改文件/etc/bash.bashrc添加如下内容

export  PATH=$PATH:/home/linux/toolchain/bin

重启配置文件

$ source  /etc/bash.bashrc

 

5、   工具链的测试

$ arm-cortex_a8-linux-gnueabi-gcc  –v

Using built-in specs.

Target : arm-cortex_a8-linux-gnueabi

Configured with: /home/linux/src/gcc-4.4.6/configure --build=i686-build_pc-linux-gnu --host=i686-build_pc-linux-gnu --target=arm-cortex_a8-linux-gnueabi --prefix=/home/linux/toolchain --with-sysroot=/home/linux/toolchain/arm-cortex_a8-linux-gnueabi//sys-root --enable-languages=c,c++,fortran --disable-multilib --with-arch=armv7-a    --with-float=soft --with-pkgversion=crosstool-NG-1.12.4-none --disable-sjlj-exceptions --enable-__cxa_atexit --disable-libmudflap --with-gmp=/home/linux/toolchain/toolchain-build/targets/arm-cortex_a8-linux-gnueabi/build/static --with-mpfr=/home/linux/ toolchain/toolchain-build/targets/arm-cortex_a8-linux-gnueabi/build/static --enable-threads=posix --enable-target-optspace --with-local-prefix=/home/linux/toolchain/arm-cortex_a8-linux-gnueabi//sys-root --disable-nls --enable-symvers=gnu --enable-c99 --enable-long-long

Thread model: posix

gcc version 4.4.6 (crosstool-NG  1.12.4)

这样我们的交叉工具链就安装好了

实验二 u-boot的烧写及使用

【实验目的】

       了解u-boot的常用命令和linux内核的引导。

【实验环境】

1、  ubuntu 10.10发行版

2、  u-boot-2010.03

3、  FS_S5PC100平台

4、  交叉编译器 arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

1、  u-boot的烧写

         先认真阅读FS_S5PC100平台用户手册

 

    运行串口通信程序(putty)

 

关闭开发板电源,将拨码开关SW1调至0001(usb启动模式)后打开电源

         

加载运行USB Installer_DDR2.bin

USB Port à Transmit à Transmit,选中image目录下的USB Installer_DDR2.bin  

        

        

 

加载运行u-boot.bin

USB Port à Transmit à Transmit,选中image目录下的u-boot.bin  如下图所示

 

 

串口终端下能看到如下内容(如果有倒计时数字,按任意键出现提示符)

        

设置并保存环境变量

# printenv     // 查看环境变量的值并按如下设置

# setenv  baudrate  115200

# setenv  ethaddr  11:22:33:44:55:66

# setenv  gatewayip  192.168.1.1

# setenv  serverip  192.168.1.100        //  serverip要和虚拟机的ip相同

# setenv  ipaddr  192.168.1.200       //  ipaddr也可以是192.168.1.x其他值

# setenv  netmask  255.255.255.0

 

保存环境变量

# saveenv

 

拷贝image/u-boot.bin到虚拟机/tftpboot目录下

 

        测试网络是否连通  //  只能通过u-boot去ping虚拟机

        #ping  <serverip>

 

烧写u-boot.bin到nand flash起始地址

# tftp  20008000  u-boot.bin

# nand  erase  0  40000

# nand  write  20008000  0  40000

 

关闭开发板电源,将拨码开关SW1调至0000(nand启动模式)后打开电源

 

2、  通过网络加载内核和文件系统

设置内核启动参数

# setenv  bootargs  root=nfs  nfsroot=192.168.1.100:/source/rootfs  ip=192.168.1.200  init=/linuxrc  console=ttySAC0,115200

# saveenv

 

设置虚拟机

拷贝/image/zImage到虚拟机/tftpboot目录下

解压rootfs.tgz到虚拟机/source目录下

修改虚拟机nfs配置文件/etc/exports,添加如下内容并重启nfs服务

/source/rootfs  *(rw,sync,no_subtree_check,no_root_squash)

$sudo  /etc/init.d/nfs-kernel-server  restart

 

下载、启动内核

# tftp  20008000  zImage

# go  20008000

 

3、  从nand flash加载内核和文件系统

拷贝rootfs.cramfs到虚拟机/tftpboot目录下

烧写内核镜像到nand flash

# tftp  20008000  zImage

# nand  erase  100000  300000

# nand  write  20008000  100000  300000

 

      烧写文件系统镜像到nand  flash

# tftp  20008000  rootfs.cramfs

# nand  erase  400000  400000

# nand  write  20008000  400000  400000

 

设置启动参数

# setenv  bootdelay  3

# setenv  bootcmd  nand  read  20008000  100000  300000\; go 20008000

# setenv  bootargs  root=/dev/mtdblock2  ip=192.168.1.200  init=/linuxrc  console=ttySAC0,115200

# saveenv

 

4、 重新启动开发板,u-boot自动加载、执行内核

 

 

5、  u-boot其他命令

u-boot支持的命令我们可以通过在终端上输入”?”查看

 

 

6、  交叉编译和交叉调试

  • 编辑程序源码myapp.c
  • 交叉编译后复制到/source/rootfs   (编译时添加选项-g)
  • 复制gdbserver到/source/rootfs/bin    (gdbserver在工具链安装路径下查找)
  • 在开发板上如下运行

# gdbserver  192.168.1.200:1234  myapp &

  • 在主机上运行交叉调试器

$ arm-cortex_a8-linux-gnueabi-gdb  myapp

  • 在交叉调试器下和开发板gdbserver建立连接

(gdb)  target  remote  192.168.1.200:1234

  • 设置断点,输入命令c开始调试程序(注意观察串口输出)

实验三 u-boot-2010.03的移植

【实验目的】

       了解u-boot-2010.03的代码结构及移植方法。

【实验环境】

1、  ubuntu 10.10发行版

2、  u-boot-2010.03

3、  FS_S5PC100平台

4、  交叉编译器 arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

       说明:后面实验中的命令行提示符是($)则为主机命令(主机上执行),(#)则为开发板命令(开发板上执行)

一、建立自己的平台

1、 下载源码

我们可以在下面这个网站上下载最新的和以前任一版本的uboot

ftp://ftp.denx.de/pub/u-boot/

 

2、 解压uboot源码并进入目录

$ tar  xvf  u-boot-2010.03.tar.gz

$ cd  u-boot-2010.03

3、 添加fsc100平台信息

我们关心的板级相关文件或目录

u-boot-2010.03/Makefile

u-boot- 2010.03/include/configs/smdkc100.h

u-boot- 2010.03 /cpu/arm_cortexa8/start.S

u-boot- 2010.03 /board/samsung/smdkc100

u-boot- 2010.03 /lib_arm

smdkc100是使用s5pc100芯片的参考板,我们在其基础之上移植fsc100

$ cd  board/samsung/

$ cp  –a  smdkc100  fsc100

$ cd  fsc100

$ mv  smdkc100.c  fsc100.c

$ vim  Makefile

修改

COBJS-y := smdkc100.o

COBJS-y := fsc100.o

 

$ cd  include/configs

$ cp  smdkc100.h  fsc100.h

 

修改u-boot顶层目录下的Makefile,指定交叉工具链

$ vim  Makefile

ifeq ($(HOSTARCH, $(ARCH))

CROSS_COMPILE ?=

endif

下添加:

ifeq (arm, $(ARCH))

CROSS_COMPILE ?= arm-cortex_a8-linux-gnueabi-

endif

 

在u-boot顶层目录下的Makefile中添加fsc100配置信息

$ vim  Makefile

smdkc100_config: unconfig

    @$(MKCONFIG)  $(@:_config=)  arm  arm_cortexa8  smdkc100  samsung s5pc1xx

下添加:

fsc100_config: unconfig

   @$(MKCONFIG)  $(@:_config=)  arm  arm_cortexa8  fsc100  samsung  s5pc1xx

4、 编译u-boot-2010.03

$ make  distclean

$ make  fsc100_config

$ make

编译完成后生成的u-boot.bin就是可执行的镜像文件。但是该文件只能在smdkc100平台上运行,我们需要对u-boot源代码进行相应的修改。

二、针对我们的fsc100平台进行相应的移植

1、 修改include/configs/fsc100.h

修改内存基址

#define  CONFIG_SYS_SDRAM_BASE   0x30000000

#define  CONFIG_SYS_SDRAM_BASE   0x20000000

 

#undef   CONFIG_CMD_NAND

改成

#define  CONFIG_CMD_NAND

 

#undef   CONFIG_CMD_NET

改成

#define  CONFIG_CMD_NET

 

#define   CONFIG_CMD_NAND

后添加

#define  CONFIG_SYS_ICACHE_OFF          1

 

注释以下内容

#define  CONFIG_CMD_ONENAND

 

注释以下内容

#define  MTDIDS_DEFAULT  “onenand…”

……

#define  CONFIG_UPDATEB  “updateb=……”

 

注释以下内容

#define  CONFIG_EXTRA_ENV_SETTINGS          \

……

“ubi=enabled”

 

修改提示符

#define  CONFIG_SYS_PROMPT             “SMDKC100  #  ”

#define  CONFIG_SYS_PROMPT          FSC100  #  ”

 

修改

#define  CONFIG_SYS_MEMTEST_END      (CONFIG_SYS_SDRAM_BASE+0x5e00000)

#define  CONFIG_SYS_MEMTEST_END      (CONFIG_SYS_SDRAM_BASE+0x10000000)

 

修改内核加载地址

#define  CONFIG_SYS_LOAD_ADDR              CONFIG_SYS_SDRAM_BASE

#define  CONFIG_SYS_LOAD_ADDR        (CONFIG_SYS_SDRAM_BASE+0x8000)

 

修改内存容量

#define  PHYS_SDRAM_1_SIZE        (128 << 20)

#define  PHYS_SDRAM_1_SIZE             (256 << 20)

 

修改环境变量存放位置

#define   CONFIG_ENV_IS_IN_ONENAND           1

#define  CONFIG_ENV_IS_IN_NAND            1

 

注释以下内容

#define   CONFIG_USE_ONENAND_BOARD_INIT

                    到

#define  CONFIG_SYS_ONENAND_BASE              0xE7100000

 

#define  CONFIG_DOS_PARTITION            1

下面添加如下信息

 

添加NAND信息

#define  CONFIG_SYS_MAX_NAND_DEVICE            1

#define  CONFIG_SYS_NAND_MAX_CHIPS        1

#define  CONFIG_SYS_NAND_BASE            0xE7200000

#define  CONFIG_NAND_S5PC100         1

#define  CONFIG_NAND_BL1_8BIT_ECC            1

#define  CFG_NAND_HWECC         1

 

#define  NAND_ENABLE_CE() (NFCONT_REG &= ~(1<<1))

#define  NAND_DISABLE_CE()       (NFCONT_REG |= (1<<1))

#define  NF_TRANSRnB()    do {while (! (NFSTAT_REG  & (1<<0)) );} while(0)

 

添加网卡信息

#ifdef  CONFIG_CMD_NET

#define  CONFIG_NET_MULTI

#define  CONFIG_CMD_PING         1

#define  CONFIG_DRIVER_DM9000             1

#define  CONFIG_DM9000_BASE           0x88000000

#define  DM9000_IO   CONFIG_DM9000_BASE

#define  DM9000_DATA   (CONFIG_DM9000_BASE  +  4)

#define  CONFIG_DM9000_USE_16BIT

#define  CONFIG_DM9000_NO_SROM         1

#define  CONFIG_ETHADDR   11:22:33:44:55:66

#define  CONFIG_IPADDR          192.168.1.200

#define  CONFIG_SERVERIP          192.168.1.100

#define  CONFIG_GATEWAYIP     192.168.1.1

#define  CONFIG_NETMASK   255.255.255.0

#endif

 

2、 复制lowlevel_init.S  mem_setup.Sboard/samsung/fsc100

上述代码专门针对fsc100使用的内存进行初始化,可参考相关芯片手册

 

3、 复制fsc100.cboard/smsung/fsc100 覆盖原来的fsc100.c

fsc100.c 包含的是板级初始化函数

 

4、 board/samsung/fsc100/目录下添加nand_cp.c

#include  <common.h>

#ifdef  CONFIG_S5PC1XX

#include  <asm/io.h>

#include  <linux/mtd/nand.h>

 

#define  _REG__(x)          (*(volatile  unsigned  long  *)(x))

#define  _REGb__(x)        (*(volatile  unsigned  char  *)(x))

#define  NFCONT_REG           _REG__(0xE7200004)

#define  NFCMD_REG          _REG__(0xE7200008)

#define  NFADDR_REG        _REG__(0xE720000C)

#define  NFDATA8_REG      _REGb__(0xE7200010)

#define  NFSTAT_REG         _REG__(0xE7200028)

 

#define  NAND_CONTROL_ENABLE()      (NFCONT_REG |= (1 << 0))

 

static  int  nandll_read_page (uchar  *buf,  ulong  addr,  int  large_block)

{

     int  i;

     int  page_size = 512;

    

if  (large_block)   page_size = 2048;

     NAND_ENABLE_CE();

     NFCMD_REG = NAND_CMD_READ0;

     /*  Write  Address  */

     NFADDR_REG = 0;

     if  (large_block)   NFADDR_REG  =  0;

     NFADDR_REG = (addr) & 0xff;

     NFADDR_REG = (addr >> 8) & 0xff;

     NFADDR_REG = (addr >> 16) & 0xff;

 

     if  (large_block)   NFCMD_REG = NAND_CMD_READSTART;

     NF_TRANSRnB();

     for (i=0; i<page_size; i++) {

         *buf++ = NFDATA8_REG;

     }

     NAND_DISABLE_CE();

     return  0;

}

 

static  int  nandll_read_blocks (ulong  dst_addr,  ulong  size,  int  large_block)

{

     uchar  *buf = (uchar *)dst_addr;

     int  i, pages;

     uint  page_shift = 9;

 

     if  (large_block)  page_shift = 11;

     pages  =  size >> page_shift;

     for (i=0;  i<pages; i++)  {

        nandll_read_page(buf,  i,  large_block);

        buf  +=  (1 << page_shift);

}

return  0;

}

 

int  copy_uboot_to_ram (void)

{

     int  i, large_block = 0;

     vu_char  id;

 

     NAND_CONTROL_ENABLE();

     NAND_ENABLE_CE();

     NFCMD_REG = NAND_CMD_READID;

     NFADDR_REG = 0x0;

 

     /*   wait  for a  while  */

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

     id  =  NFDATA8_REG;

     id  =  NFDATA8_REG;

     if  (id  >  0x80)   large_block  =  1;

 

     return  nandll_read_blocks(0x2ff80000,  0x40000,  large_block);

}

#endif

 

5、 修改board/samsung/fsc100/Makefile

SOBJS     :=  lowlevel_init.o

改成

SOBJS     :=  lowlevel_init.o  mem_setup.o

 

COBJS-y  :=  fsc100.o

改成

COBJS-y :=  fsc100.o  nand_cp.o

 

6、 修改board/samsun/fsc100/config.mk

TEXT_BASE  =  0x34800000

改成

TEXT_BASE  =  0x2FF80000

 

7、 修改cpu/arm_cortexa8/start.S

#ifndef  CONFIG_SKIP_LOWLEVEL_INIT

       bl   cpu_init_crit

#endif

之后添加如下代码

/*  判断uboot是否在内存中运行 */

ldr   r0,  =_TEXT_BASE

adr  r1,  _TEXT_BASE

cmp  r0,  r1

beq   stack_setup

 

ldr  sp,  =(0x22000000)

bl  copy_uboot_to_ram

b   stack_setup

 

8、 链接文件的修改

修改cpu/arm_cortexa8/u-boot.lds为:

       ……

       .text   :

      {

          cpu/arm_cortexa8/start.o       (.text)

          board/samsung/fsc100/lowlevel_init.o

board/samsung/fsc100/mem_setup.o

          board/samsung/fsc100/nand_cp.o

          *(.text)

}

……

 

9、 复制s5pc100.h  s5pc1x0.h  hardware.h   include/asm-arm/arch-s5pc1xx/

 

10、 复制s5p_nand.cdrivers/mtd/nand/

 

11、 修改drivers/mtd/nand/Makefile

COBJS-$(CONFIG_NAND_S3C64XX)  +=  s3c64xx.o

后面添加

COBJS-$(CONFIG_NAND_S5PC100)  += s5p_nand.o

 

12、 修改include/linux/mtd/mtd-abi.h

struct  nand_ecclayout  {

……

struct  nand_oobfree  oobfree[MTD_MAX_OOBFREE_ENTRIES];

uint32_t  useecc;

uint32_t  reserved;

};

 

13、 lib_arm/board.c中添加网卡初始化代码

eth_initialize(gd->bd);

后面添加

eth_init(gd->bd);

 

14、 修改网卡驱动drivers/net/dm9xxx.c

在函数dm9000_init中,

DM9000_iow(DM9000_IMR, IMR_PAR);

之后的内容都注释掉,直到该函数结束(return  0之前)

 

15、 修改include/net.h

static inline  int  is_multicast_ether_addr(const u8 *addr)

{

         return  (0x01  ==  addr[0]);

}

 

 

16、 修改net/net.c

在 int  NetArpWaitTry; 后添加如下代码

ulong  timer_clk;

 

void  ArpTimeoutCheck(void)

{

     ……

     把

     t  =   get_timer(0);

改成

t  =  get_timer(0)  /  (timer_clk / CONFIG_SYS_HZ);

}

 

extern unsigned  long  (*get_pclk)(void);

int  NetLoop(proto_t  protocol)

{

        bd_t  *bd  =  gd->bd;

        添加如下代码:

      timer_clk  =  get_pclk()  /  (16 * 2);

      ……

     

      注释以下代码

      eth_halt();

eth_set_current();

if  (eth_init(bd)  <  0)  {

       eth_halt();

       return  -1;

}

 

      把 

if  (timeHandler  && ( … > timeDelta) {

      改成

      ulong  t;

      t  =  get_timer(0) / (timer_clk  /  CONFIG_SYS_HZ);

      if  (timeHandler  && (t  -  timeStart)  > timeDelta)  {

      ……

}

 

void  NetSetTimeout(ulong  iv,  thand_f  *f)

{

      把

      timeStart  =  get_timer(0);

     改成

      timeStart  =  get_timer(0)  /  (timer_clk  /  CONFIG_SYS_HZ);

}

 

int  NetSendUDPPacket(uchar *ether,  IPaddr_t  dest,  int  dport,  int  sport,  int  len)

{

      ……

     把

      NetArpWaitTimerStart  =  get_timer(0);

     改成

     NetArpWaitTimerStart  =  get_timer(0)  /  (timer_clk  /  CONFIG_SYS_HZ);

     ……

}

 

int  PingSend(void)

{

      ……

      把

NetArpWaitTimerStart  =  get_timer(0);

      改成

     NetArpWaitTimerStart  =  get_timer(0)  /  (timer_clk  /  CONFIG_SYS_HZ);

     ……

}

 

注释该文件中所有的eth_halt()

 

17、 go命令的优化

修改该common/cmd_boot.c

int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])

{

ulong   addr, rc;

int    rcode = 0;

      if  (argc < 2) {

return  cmd_usage(cmdtp);

}

/**************** added by farsight 2011-12-18 *****************/

char *cmdline  =  getenv("bootargs");

struct param_struct *kernel_params=(struct param_struct *)0x20000100;

 

printf("setup linux parameters at 0x20000100\n");

memset(kernel_params, 0, sizeof(struct  param_struct));

kernel_params->u1.s.page_size=4096;

kernel_params->u1.s.nr_pages=0x10000000>>12;

memcpy(kernel_params->commandline, cmdline, strlen(cmdline)+1);

printf("linux command line is: \"%s\"\n",cmdline);

/***************************************************************/ 

 addr = simple_strtoul(argv[1], NULL, 16);

 printf ("## Starting application at 0x%08lX ...\n", addr);

 

/******************* added by farsight 2011-12-18 ******************/

__asm__(

"ldr  r1, =1826\n"

"mov        ip, #0\n"

"mcr        p15, 0, ip, c8, c7, 0\n"        

"mcr        p15, 0, ip, c7, c5, 0\n"        

"mcr        p15, 0, ip, c7, c5, 6\n"       

"mcr        p15, 0, ip, c7, c10, 4\n"        

"mcr        p15, 0, ip, c7, c5, 4\n"        

 

"mrc        p15, 0, ip, c1, c0, 0\n"   

"bic        ip, ip, #0x00002000\n"  

"bic        ip, ip, #0x00000007\n"

"orr        ip, ip, #0x00000002\n"

"orr        ip, ip, #0x00000800\n"

"bic        ip, ip, #0x00001000\n"

"mcr        p15, 0, ip, c1, c0, 0\n"   

 

"mov pc, %0\n"

"nop\n"

:

:"r"(addr)

);

/***************************************************************/

 

rc = do_go_exec ((void *)addr, argc - 1, argv + 1);

if (rc != 0) rcode = 1;

 

printf ("## Application terminated, rc = 0x%lX\n", rc);

return rcode;

}

 

三、重新编译

$ make  distclean

$ make  fsc100_config

$ make

这样我们就得到能够在fsc100平台上使用的u-boot.bin

 

实验四  内核的配置和编译

【实验目的】

       了解内核的编译过程及配置选项的内容

【实验环境】

  • 主机:ubuntu 10.10发行版
  • 目标机:FS_S5PC100平台
  • 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

  • 解压内核

将linux-2.6.35.tar.bz2拷贝到/home/linux下并解压

$tar  xvf  linux-2.6.35.tar.bz2

$ cd  linux-2.6.35

  • 修改内核顶层目录下的Makefile

$ vim Makefile

修改:

ARCH             ?= $(SUBARCH)

CROSS_COMPILE ?=

CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)

为:

ARCH            ?= arm

CROSS_COMPILE      ?= arm-cortex_a8-linux-gnueabi-

  • 拷贝标准板配置文件

$ cp  arch/arm/configs/s5pc100_defconfig   .config

  • 配置内核

$ make  menuconfig

该命令执行时会弹出一个菜单,我们可以对内核进行详细的配置。这里我们先查看一下,内核都提供了那些功能!

  • 编译内核

$ make  zImage

通过上述操作我们能够在arch/arm/boot目录下生成一个zImage文件,这就是经过压缩的内核镜像。

实验五  网卡驱动的移植

【实验目的】

       通过上面的实验我们能够获得一个内核,但是这个内核只是一个最基本的配置,很多的功能并没有包含。

       网卡是嵌入式产品最常用的设备,这里我们需要完成网卡驱动的移植。FS_S5PC100使用的是DM9000网卡,我们通过这个实验能够了解如何在内核中添加网卡驱动及网络功能的基本配置。

【实验环境】

  • 主机:ubuntu 10.10发行版
  • 目标机:FS_S5PC100平台
  • 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

  • 平台代码修改

vim  arch/arm/mach-s5pc100/mach-smdkc100.c

 

  • 添加需要的头文件(注:由于linux的头文件之间也有依赖关系,所以应该讲将下面的头文件加到原来头问价的最后)

#if defined (CONFIG_DM9000)

#include <linux/dm9000.h>

#include <linux/irq.h>

#endif

 

  • 平台设备的添加

/* DM9000 Support */

#if  defined(CONFIG_DM9000)

static struct resource dm9000_resources[] = {

[0] = {

.start        = 0x88000000,

.end        = 0x88000000 + 0x3,

.flags        = IORESOURCE_MEM,

},

[1] = {

.start        = 0x88000000 + 0x4,

.end        = 0x88000000 + 0x4 +0x3,

.flags        = IORESOURCE_MEM,

},

[2] = {

      .start = IRQ_EINT(10),

      .end   = IRQ_EINT(10),

.flags        = IORESOURCE_IRQ | IRQ_TYPE_LEVEL_HIGH,

},

};

 

static struct dm9000_plat_data s5pc100_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 s5pc100_device_dm9000 = {

.name        = "dm9000",

.id        = -1,

.num_resources        = ARRAY_SIZE(dm9000_resources),

.resource        = dm9000_resources,

.dev = {

.platform_data  = & s5pc100_dm9000_platdata,

}

};

#endif

 

  • 平台设备列表的添加:

在smdkc100_devices[]结构体数组中添加如下内容:

   #if  defined(CONFIG_DM9000)

   &s5pc100_device_dm9000,

   #endif

 

  • 配置内核

$ make menuconfig

 

  • 网络配置:

[*] Networking support (NEW)  --->

Networking options  --->

<*> Packet socket

<*> Unix domain sockets

[*] TCP/IP networking

[*]   IP: multicasting

[*]   IP: kernel level autoconfiguration

[*]     IP: BOOTP support

 

  • 网卡驱动配置

Device Drivers  ---> 

[*] Network device support  --->

[*]   Ethernet (10 or 100Mbit)  --->

<*>   DM9000 support

 

  • 网络文件系统的配置

File systems  ---> 

[*] Network File Systems  --->

<*>   NFS client suppor

[*]     NFS client support for NFS version 3 

[*]       NFS client support for the NFSv3 ACL protocol extension

[*]     Root file system on NFS

 

  • 编译内核,并拷贝到tftpboot目录下

$ make  zImage

$ cp arch/arm/boot/zImage  /tftpboot

 

  • 启动开发板,修改内核启动参数,通过NFS方式挂载根文件系统

 

实验六  LED驱动的移植

【实验目的】

  1. 驱动程序的静态编译和动态编译
  2. 应用程序如何打开/操作设备

【实验环境】

  • 主机:ubuntu 10.10发行版
  • 目标机:FS_S5PC100平台
  • 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

  • 修改内核配置

$ make menuconfig

Kernel Features  --->

       [*] Use the ARM EABI to compile the kernel

       [*]   Allow old ABI binaries to run with this kernel (EXPERIMENTAL)

 

Ÿ   添加驱动文件

将实验代码LED_TEST/fsc100_led_drv.c拷贝到drivers/char下

 

Ÿ   修改drivers/char/Kconfig

在menu "Character devices"下面

添加如下内容:

config  FSC100_LED

     tristate "FSC100  LED  Device Support"

       depends on  ARCH_S5PC100

           help

     support  led  device  on  FS_S5PC100  develop  board

 

Ÿ   修改drivers/char/Makefile

在 obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o 下一行添加:

obj-$(CONFIG_FSC100_LED) += fsc100_led_drv.o

 

Ÿ   交叉编译测试程序fsc100_led_test.c

arm-cortex_a8-linux-gnueabi-gcc  fsc100_led_test.c  –o  fsc100_led_test 

sudo  cp  fsc100_led_test   /source/rootfs

 

Ÿ   设置u-boot环境变量

# setenv  serverip 192.168.1.100

# setenv  ipaddr 192.168.1.200

# setenv  bootcmd  tftp  20008000  zImage\; go  20008000

# setenv  bootargs  root=nfs  nfsroot=192.168.1.100:/source/rootfs  console=ttySAC0,115200 init=/linuxrc  ip=192.168.1.200

# saveenv

 

1、 静态编译LED驱动

  • 配置内核时按“空格”选择,配置完成后保存退出

$ make menuconfig

       Device Drivers  ---> 

              Character devices  ---> 

                     <*> FSC100  LED  Device Support

 

  • 保存退出,重新编译后把zImage拷贝到tftpboot下

$ make  zImage

$ cp  arch/arm/boot/zImage  /tftpboot

 

重新启动开发板,加载内核并运行。在终端下执行下面操作

  • 创建设备节点

# mknod  /dev/led  c  252  0

 

  • 运行测试程序并观察现象

# ./fsc100_led_test

 

2、 动态编译LED驱动

  • 配置内核时按“空格”选择,配置完成后保存退出

$ make menuconfig

       Device Drivers  ---> 

              Character devices  ---> 

                     <M> FSC100  LED  Device  Support

 

  • 保存退出,重新编译后把zImage拷贝到tftpboot下,把驱动模块拷贝到/source/rootfs下

$ make  zImage  modules

$ cp  arch/arm/boot/zImage  /tftpboot

$ cp  drivers/char/fsc100_led_drv.ko  /source/rootfs

 

重新启动开发板,linux运行起来后在终端下操作

  • 创建设备节点

# mknod  /dev/led  c  252  0          //c表示 字符设备,252是主设备号,0是次设备号

 

  • 加载LED驱动模块

#insmod  fsc100_led_drv.ko

 

  • 运行测试程序并观察现象

# ./fsc100_led_test

 

 

 

 

实验七  Nand flash驱动的移植

【实验目的】

       Nand flash 是嵌入式系统最常用的外部存储设备,这里介绍Nand flash驱动移植的过程。

       说明:在本系统移植课程实验中命令行提示符 “$”表示是在主机上执行,“#”表示在目标板执行

【实验环境】

  • 主机:ubuntu 10.10发行版
  • 目标机:FS_S5PC100平台
  • 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

Ÿ   添加针对我们平台的Nand flash驱动

拷贝s3c_nand.c到drivers/mtd/nand下

拷贝regs-nand.h到arch/arm/mach-s5pc100/include/mach下

Ÿ   针对平台上的nand flash设备,修改drivers/mtd/nand/nand_base.c第2812行

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

  • 添加内核配置选项

修改drivers/mtd/nand/Kconfig,在if  mtd_nand下面添加如下内容:

 

config  MTD_NAND_S3C

        tristate "NAND Flash support for S3C SoC"

        depends on (ARCH_S3C64XX || ARCH_S5P64XX || ARCH_S5PC1XX || ARCH_S5PC100) && MTD_NAND

        help

          This enables the NAND flash controller on the S3C. 

          No board specfic support is done by this driver, each board

          must advertise a platform_device for the driver to attach.

 

config  MTD_NAND_S3C_DEBUG

        bool "S3C NAND driver debug"

        depends on MTD_NAND_S3C

        help

          Enable debugging of the S3C NAND driver

 

config  MTD_NAND_S3C_HWECC

        bool "S3C NAND Hardware ECC"

        depends on MTD_NAND_S3C

        help

          Enable the use of the S3C's internal ECC generator when

          using NAND. Early versions of the chip have had problems with

          incorrect ECC generation, and if using these, the default of

          software ECC is preferable.

 

          If you lay down a device with the hardware ECC, then you will

          currently not be able to switch to software, as there is no

          implementation for ECC method used by the S3C

 

修改drivers/mtd/nand/Makefile添加如下内容:

obj-$(CONFIG_MTD_NAND_S3C)  +=  s3c_nand.o

 

  • 修改平台代码

修改arch/arm/mach-s5pc100/mach-smdkc100.c添加如下内容:

 

  • 添加头文件

#if defined (CONFIG_MTD_NAND_S3C)

#include <linux/mtd/partitions.h>

#include <linux/mtd/mtd.h>

#include <plat/nand.h>

#endif

 

  • 添加平台设备

#if defined(CONFIG_MTD_NAND_S3C)

/* Nand Flash Support */

static struct mtd_partition s5pc100_nand_part[] = {

        [0] = {

                .name        = "bootloader",

                .size        = SZ_1M,

                .offset        = 0,

        },

        [1] = {

                .name        = "kernel",

                .offset = MTDPART_OFS_APPEND,

                .size        = SZ_1M*3,

        },

        [2] = {

                .name        = "rootfs",

                .offset               = MTDPART_OFS_APPEND,

                .size        = SZ_4M,

        },

        [3] = {

                .name        = "usrfs",

                .offset        = MTDPART_OFS_APPEND,

                .size        = MTDPART_SIZ_FULL,

        },

};

 

struct s3c_nand_mtd_info s5pc100_nand_mtd_part_info = {

        .chip_nr = 1,

        .mtd_part_nr = ARRAY_SIZE(s5pc100_nand_part),

        .partition = s5pc100_nand_part,

};

 

static struct resource s5pc100_nand_resource[] = {

        [0] = {

                .start = 0xE7200000,

                .end   = 0xE7200000 + SZ_1M,

                .flags = IORESOURCE_MEM,

        }

};

 

struct platform_device s5pc100_device_nand = {

        .name                  = "s5pc100-nand",

        .id                  = -1,

        .num_resources          = ARRAY_SIZE(s5pc100_nand_resource),

        .resource          = s5pc100_nand_resource,

        .dev = {

                .platform_data = &s5pc100_nand_mtd_part_info,

        }

};

#endif

 

  • 添加平台设备列表

在smdkc100_device[]结构体数组中添加如下内容:

#if defined(CONFIG_MTD_NAND_S3C)

        &s5pc100_device_nand,

#endif

 

  • 修改arch/arm/plat-samsung/include/plat/nand.h添加如下内容:

struct s3c_nand_mtd_info {

        uint chip_nr;

        uint mtd_part_nr;

        struct mtd_partition *partition;

};

 

  • 配置内核

$ make menuconfig

Device Drivers  --->

        <*> Memory Technology Device (MTD) support  --->

               [*]   MTD partitioning support

<*>   Caching block device access to MTD devices

               <*>   NAND Device Support  --->

                      <*>   NAND Flash support for S3C SoC

                      [*]     S3C NAND Hardware ECC

 

File Systems  --->

         Partition  Types  --->

                [*]    Advanced partition selection

                [*]    PC  BIOS  (MSDOS  partition  tables)  support

                [*]         BSD  disklabel  (FreeBSD  partition  tables)  support

 

  • 编译内核并拷贝到tftpboot下

$ make  zImage

$ cp  arch/arm/boot/zImage  /tftpboot

 

  • 测试

启动目标板,在目标板上完成如下操作:

# cat  /proc/partitions

dev:        size       erasesize     name

mtd0: 00100000 00020000  "bootloader"

mtd1: 00300000 00020000  "kernel"

mtd2: 00400000 00020000  "rootfs"

mtd3: 0f800000 00020000  "usrfs"

 

 

 

实验八    LCD驱动移植

【实验目的】

       了解交叉工具链的编译过程及其使用。

       说明:在本系统移植课程实验中命令行提示符 “$”表示是在主机上执行,“#”表示在目标板执行

【实验环境】

  • 主机:ubuntu 10.10发行版
  • 目标机:FS_S5PC100平台
  • 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

  • 修改arch/arm/mach-s5pc100/mach-smdkc100.c

修改smdkc100_fb_win0结构体内容为:

static struct s3c_fb_pd_win smdkc100_fb_win0 = {

/* this is to ensure we use win0 */

.win_mode        = {

.pixclock = 1000000000000ULL / ((8+43+1+480)*(4+10+12+272)*80),

.left_margin        = 8,

.right_margin        = 43,

.upper_margin        = 4,

.lower_margin        = 12,

.hsync_len        = 1,

.vsync_len        = 10,

.xres                = 480,

.yres                = 272,

},

.max_bpp        = 32,

.default_bpp        = 16,

};

      

  • 修改drivers/video/Kconfig

修改:

depends on (FB && ARCH_S3C64XX)

为:

depends on (FB && ARCH_S3C64XX) || (FB && ARCH_S5PC100)

      

  • 配置内核

$ make menuconfig

Device Drivers  --->

Graphics support  --->

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

<*>   Samsung S3C framebuffer support

Console display driver support  --->

                    <*> Framebuffer Console support

[*] Bootup logo  --->

 

  • 编译内核并拷贝到tftpboot下

$ make  zImage

$ cp  arch/arm/boot/zImage  /tftpboot

 

  • 测试

插上屏,启动开发板,能够看到屏幕上显示一个小企鹅就是移植成功了!

 

 

 

 

实验九    USB驱动的移植

【实验目的】

       USB接口是现在计算机系统中最通用的一种接口,

       说明:在本系统移植课程实验中命令行提示符 “$”表示是在主机上执行,“#”表示在目标板执行

【实验环境】

  • 主机:ubuntu 10.10发行版
  • 目标机:FS_S5PC100平台
  • 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

  • 添加针对我们板子的USB驱动及相关头文件

拷贝ohci-s3c2410.c drivers/usb/host/

 

拷贝regs-clock.h arch/arm/mach-s5pc100/include/mach/

 

  • 修改drivers/usb/Kconfig

在:

default  y  if  ARCH_S3C2410

后添加:

default  y  if  ARCH_S5PC100

 

  • 修改drivers/usb/host/ohci-hcd.c

修改:

#if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX)

为:

#if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_ARCH_S5PC100)

 

  • 修改arch/arm/mach-s5pc100/include/mach/map.h

添加如下内容:

#define S3C_PA_USBHOST          (0xED400000)

 

  • 修改arch/arm/plat-samsung/dev-usb.c

修改

[1] = {

.start = IRQ_USBH,

.end   = IRQ_USBH,

.flags = IORESOURCE_IRQ,

}

为:

[1] = {

.start = IRQ_UHOST,

.end   = IRQ_UHOST,

.flags = IORESOURCE_IRQ,

}

 

  • 添加平台设备

修改arch/arm/mach-s5pc100/Kconfig

select  S3C_PL330_DMA

后添加

select  S3C_DEV_USB_HOST

 

修改arch/arm/mach-s5pc100/mach-smdkc100.c

 

添加头文件

#if defined (CONFIG_USB_SUPPORT)

#include <plat/pll.h>

#include <linux/usb/ch9.h>

#include <mach/regs-clock.h>

#endif

 

添加平台设备

 

#if defined(CONFIG_USB_SUPPORT)

void usb_host_clk_en(void) {

        /* Setting the epll clk to 48 MHz, P=3, M=96, S=3 */

        writel((readl(S5P_EPLL_CON) & ~(S5P_EPLL_MASK)) | (S5P_EPLL_EN \

                                | S5P_EPLLVAL(96,3,3)), S5P_EPLL_CON);

        writel((readl(S5P_CLK_SRC0) | S5P_CLKSRC0_EPLL_MASK), S5P_CLK_SRC0);

        writel((readl(S5P_CLK_SRC1)& ~S5P_CLKSRC1_UHOST_MASK), S5P_CLK_SRC1);

 

        /* USB host clock divider ratio is 1 */

        writel((readl(S5P_CLK_DIV2)& ~S5P_CLKDIV2_UHOST_MASK), S5P_CLK_DIV2);

        writel(readl(S5P_CLKGATE_D10)|S5P_CLKGATE_D10_USBHOST, S5P_CLKGATE_D10);

        writel(readl(S5P_SCLKGATE0)|S5P_CLKGATE_SCLK0_USBHOST, S5P_SCLKGATE0);

}

EXPORT_SYMBOL(usb_host_clk_en);

#endif

 

添加平台设备列表

在smdkc100_device[]结构体数组中添加如下内容:

#if defined(CONFIG_USB_SUPPORT)

        & s3c_device_ohci,

#endif

 

  • 配置内核

$ make menuconfig

USB控制器支持

Device Drivers  --->

       [*] USB support  --->

              <*>   Support for Host-side USB

              <*>     OHCI HCD support

 

U盘支持

Device Drivers  --->

       SCSI device support  --->

              <*> SCSI device support

              <*> SCSI disk support

              <*> SCSI generic support

              <*> SCSI media changer support

 

Device Drivers  --->

       [*] USB support  --->

<*>   USB Mass Storage support

 

文件系统及语言配置:

File systems  --->

DOS/FAT/NT Filesystems  --->

<*> VFAT (Windows-95) fs support 

-*- Native language support  --->

<*>   Codepage 437 (United States, Canada)

<*>   Simplified Chinese charset (CP936, GB2312)

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

<*>   ASCII (United States)

<*>   NLS UTF-8

            

  • 编译内核并拷贝到tftpboot下

$ make  zImage

$ cp  arch/arm/boot/zImage  /tftpboot

 

  • 测试

启动目标板并在目标板上完成如下操作:

# mount  -t  vfat  /dev/sda1 /mnt

# ls

可以查看到U盘内容,即完成实验。

 

 

 

实验十    SD卡驱动移植

【实验目的】

       SD卡是嵌入式系统最常用的外部扩展存储设备,这里介绍SD驱动移植的过程。

       说明:在系统移植课程实验中命令行提示符 “$”表示是在主机上执行,“#”表示在目标板执行

【实验环境】

  • 主机:ubuntu 10.10发行版
  • 目标机:FS_S5PC100平台
  • 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

  • 修改配置文件

修改drivers/mmc/host/Kconfig

 

修改:

depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX)

为:

depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX || ARCH_S5PC100)

 

修改driver/mmc/host/sdhci.c

 

修改:

mmc->f_min = host->max_clk / 256;

mmc->f_min = host->max_clk / 512;

 

  • 配置内核

$ make  menuconfig

 

SD卡驱动配置:

Device Drivers  --->

       <*> MMC/SD/SDIO card support  --->

              <*>   SDHCI support on Samsung S3C SoC

                     [*]   DMA support on S3C SDHCI

 

 

  • 编译内核并拷贝到tftpboot下

$ make  zImage

$ cp  arch/arm/boot/zImage  /tftpboot

 

  • 测试

启动目标板并在目标板上完成如下操作:

# mount  -t  vfat  /dev/mmcblk0p1  /mnt

# ls

可以查看到SD卡内容,即完成实验。 

 

 

 

 

 

 

 

 

 

实验十一  yaffs2文件系统的移植

【实验目的】

       yaffs2文件系统是嵌入式系统中常用到的一种文件系统,并且在主要用在nand flash上,这里我们在内核里添加yaffs2的支持

【实验环境】

1、  ubuntu 10.10发行版

2、  FS_S5PC100平台

3、  交叉编译器 arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

1、  源码下载

       $ wget http://www.aleph1.co.uk/cgi-bin/viewcvs.cgi/yaffs2.tar.gz

2、  解压到内核源码linux-2.6.35同级目录下

       $ tar  xvf  yaffs2.tar.gz

3、  往内核打yaffs2补丁

$ cd  yaffs2

$ ./patch-ker.sh  c  ../linux-2.6.35

4、  配置内核

$ cd  ../linux-2.6.35

       $ make  menuconfig

File systems  --->

           [*] Miscellaneous filesystems  --->

                     <*>   YAFFS2 file system support

                    -*-     512 byte / page devices

                     -*-     2048 byte (or larger) / page devices

                     [*]       Autoselect yaffs2 format

                     [*]      Cache  short  names  in  RAM

5、  重新编译内核

       $ make  zImage

6、  拷贝内核到开发板上

       $ cp  arch/arm/boot/zImage  /tftpboot

7、  重新启动开发板

# cat  /proc/filesystems

 nodev    sysfs

 nodev    rootfs

 nodev    bdev

 nodev    proc

 nodev    tmpfs

 nodev    sockfs

 nodev    usbfs

 nodev    pipefs

 nodev    anon_inodefs

 nodev    rpc_pipefs

 nodev    devpts

             ext3

              ext2

              cramfs

 nodev    ramfs

             vfat

              msdos

              iso9660

nodev      nfs

nodev      jffs2

              romfs

              yaffs

              yaffs2

nodev      mtd_inodefs

 

 

 

 

实验十二  内存调试

【实验目的】

段错误和内存错误是C语言编程经常遇到的问题,使用memwatch是由johan lindh编写,是一个开发源代码C语言内存错误检测工具。能检测双重释放,错误释放,没有释放内存,溢出等等情况。

【实验环境】

1、  ubuntu 10.10发行版

2、  FS_S5PC100平台

3、  交叉编译器 arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

1、  解压memwatch.-2.7.1.tar.gz,在解开的目录下添加代码memtest.c

#include <stdlib.h>

#include <stdio.h>

#include "memwatch.h"

int main(int argc,char **argv)

{

        char *ptr1;

        char *ptr2;

        ptr1 = malloc(512);

        ptr2 = malloc(512);

        ptr1[512]="A";

        ptr2 = ptr1;

        free(ptr2);

        free(ptr1);

        return 0;

}

2、  修改  Makefile

Makefile文件为:

CC=arm-cortex_a8-linux-gnueabi-gcc

memtest:

        $(CC) -DMEMWATCH -DMW_STDIO  memtest.c  memwatch.c

5、运行make并将编译生成的可执行程序a.out拷贝到开发板的根目录下执行,会生成一个记录文件memwatch.log,内容如下:

============= MEMWATCH 2.71 Copyright (C) 1992-1999 Johan Lindh =========

 

Started at Thu Jan  1 00:08:33 1970

 

Modes: __STDC__ 32-bit mwDWORD==(unsigned long)

mwROUNDALLOC==4 sizeof(mwData)==32 mwDataSize==32

 

  • overflow: <3> memtest.c(12), 512 bytes alloc'd at <1> memtest.c(8)

double-free: <4> memtest.c(13), 0x1a1b4 was freed from memtest.c(12)

 

Stopped at Thu Jan  1 00:08:33 1970

 

unfreed: <2> test.c(9), 512 bytes at 0x1a3e4      {FE FE FE FE FE FE FE FE FE FE FE FE FE FE FE FE ................}

 

Memory usage statistics (global):

 N)umber of allocations made: 2

 L)argest memory usage      : 1024

 T)otal of all alloc() calls: 1024

 U)nfreed bytes totals      : 512

//overflow: <3> memtest.c(12)缓冲区溢出,当程序执行到第15行free(ptr2)才检测到的;

512 bytes alloc'd at <1> memtest.c(9)

//表示出错缓冲区的大小为512字节,是在memtest.c的第9行分配的。很容易发现代码的ptr1[512]="A"出现错误。

double-free: <4> memtest.c(13), 0x1a7f4 was freed from memtest.c(12)

//double-free: <4> memtest.c(16)是一个双重释放的错误,表示程序执行到16行的时候才检测到。

0x1a7f4 was freed from memtest.c(12)

//表示首地址为 0x1a7f4的内存在15行已经被释放。

Stopped at Wed Dec 31 19:00:38 1969

unfreed: <2> memtest.c(10), 512 bytes at 0x1aa24        {FE FE FE FE FE FE FE FE

//表示一块内存没有释放,表示这块内存是在memtest.c的第10行分配,大小为512字节,首地址为0x1aa24。

Memory usage statistics (global):

 N)umber of allocations made: 2

 L)argest memory usage      : 1024

 //程序结束时能够是使用的最大动态内存

 T)otal of all alloc() calls: 1024 //总共分配的动态内存

 U)nfreed bytes totals      : 512

 //表示未释放的内存

 

实验十三  内核调试

【实验目的】

由于在驱动开发中经常看到内核崩溃的问题,最常见的就是OOPS错误,本实验要求学员掌握这种调试方法。

【实验环境】

1、  ubuntu 10.10发行版

2、  FS_S5PC100平台

3、  交叉编译器 arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

1、通过OOPS信息中PC寄存器的值可以知道出错指令的地址,通过栈回朔信息可以知道出错时的函数调用的关系,根据这两点可以很快定位错误。

2、 修改drivers/video/s3c-fb.c,在s3c_fb_probe函数中int  ret=0;下增加下面语句:

int *ptr  =  NULL;

*ptr  = 0xff;

3、编译内核下载到开发板上,内核启动会出现如类似下信息:

Unable to handle kernel NULL pointer dereference at virtual address 00000000

pgd = c0004000

[00000000] *pgd=00000000

Internal error: Oops: 805 [#1]

 

Modules linked in:

CPU: 0    Not tainted  (2.6.35 #6)

PC is at s3c_fb_probe+0xc/0x67c

LR is at platform_drv_probe+0x1c/0x24

pc : [<c0290a28>]    lr : [<c01a44e4>]    psr: a0000013

sp : cfc29f0c     ip : cfc457c0    fp : 00000000

r10: 00000000  r9 : 00000000   r8 : c03ad4f8

r7 : c03a93d0   r6 : c03a93d0   r5 : c0395258   r4 : 00000000

r3 : 000000ff    r2 : cfc28000    r1 : 00000000   r0 : c0395250

 

 

4、Unable to handle kernel NULL pointer dereference at virtual address 00000000

可以看出使用了空指针。找出函数调用关系:PC is at s3c_fb_probe+0xc/0x67c

,表示出错指令为 s3c_fb_probe函数中偏移为0xc的指令。pc : [<c0290a28>] 表示出错指令的地址为c0290a28.

 

5、结合内核源代码和反汇编代码定位问题。

arm-cortex_a8-linux-gnueabi-objdump -D vmlinux > vmlinux.dis   //  文件vmlinux.dis非常大

出错地址c001abc4附近的部分汇编代码如下:

c0290a1c  <s3c_fb_probe>:

c0290a1c:   e92d4ff0       push  {r4, r5, r6, r7, r8, r9, sl, fp, lr}

c0290a20:   e3a030ff       mov  r3, #255

c0290a24:   e3a04000     mov  r4, #0

c0290a28:   e5843000     str  r3, [r4]

c0290a2c:   e590106c     ldr  r1,  [r0, #108]

……

对应C代码如下:

  struct  device  *dev = &pdev->dev;

  struct  s3c_fb_platdata  *pd;

  struct  s3c_fb  *sfb;

  struct  resource  *res;

  int  win;

  int  ret = 0;

  int *ptr = NULL;

  *ptr = 0xff;

6、对于大多数情况,从反汇编代码定位到C代码并不会如此容易,需要有较强的阅读汇编代码的能力。

7、另外一种方法是通过addr2line去定位

arm-cortex_a8-linux-gnueabi-addr2line  0xc0290a28  -e  vmlinux  -f

 

重要  该实验完成后不要忘记恢复被修改的代码

实验十四  文件系统的移植

【实验目的】

       熟悉Linux文件系统目录结构,创建自己的文件系统,通过NFS方式测试;用文件系统工具生成ramdisk文件系统映象文件。

【实验环境】

1、  ubuntu 10.10发行版

2、  FS_S5PC100平台

3、  交叉编译器 arm-cortex_a8-linux-gnueabi-gcc

【实验步骤】

       一、根文件系统制作

1、  源码下载

我们选择的版本是busybox-1.17.3.tar.bz2下载路径为:

http://busybox.net/downloads/

2、  解压源码

$ tar  xvf  busybox-1.17.3.tar.bz2

3、  进入源码目录

$ cd  busybox-1.17.3

4、  配置源码

$ make menuconfig

Busybox Settings --->

       Build Options --->

              [*] Build BusyBox as a static binary (no shared libs)

              [ ] Force NOMMU build

              [ ] Build with Large File Support (for accessing files > 2 GB)

              (arm-cortex_a8-linux-gnueabi-) Cross Compiler prefix

              () Additional CFLAGS

5、  编译

$ make

6、  安装

busybox默认安装路径为源码目录下的_install

$ make  install

7、  进入安装目录下

$ cd  _install

$ ls

bin  linuxrc  sbin  usr

8、  创建其他需要的目录

$ mkdir  dev  etc  mnt  proc  var  tmp  sys  root

9、  添加库

  • 将工具链中的库拷贝到_install目录下

$ cp  /home/linux/toolchain/arm-cortex_a8-linux-gnueabi/lib   ./  -a

  • 删除静态库和共享库文件中的符号表

$ rm  lib/*.a

$ arm-cortex_a8-linux-gnueabi-strip  lib/*

  • 删除不需要的库,确保所有库大小不超过4M

$ rm  lib/libstdc++*

$ du  -mh   lib/

10、 添加系统启动文件

在etc下添加文件inittab,文件内容如下:

#this is run first except when booting in single-user mode.

:: sysinit:/etc/init.d/rcS

# /bin/sh invocations on selected ttys

# start an "askfirst" shell on the console (whatever that may be)

::askfirst:-/bin/sh

# stuff to do when restarting the init process

::restart:/sbin/init

# stuff to do before rebooting

::ctrlaltdel:/sbin/reboot

 

在etc下添加文件fstab,文件内容如下:

#device     mount-point     type        options         dump     fsck order

proc         /proc             proc           defaults     0                0

tmpfs         /tmp                   tmpfs         defaults         0                 0

sysfs           /sys                    sysfs           defaults           0                 0

tmpfs     /dev                   tmpfs         defaults         0                 0

       这里我们挂载的文件系统有三个proc、sysfs和tmpfs。在内核中proc和sysfs默认都支持,而tmpfs是没有支持的,我们需要添加tmpfs的支持

修改内核配置:

File systems --->

       Pseudo filesystems --->

              [*] Virtual memory file system support (former shm fs)

              [*] Tmpfs POSIX Access Control Lists

重新编译内核

      

       在etc下创建init.d目录,并在init.d下创建rcS文件,rcS文件内容为:

#!/bin/sh

# This is the first script called by init process

/bin/mount  -a

echo  /sbin/mdev  >  /proc/sys/kernel/hotplug

/sbin/mdev  -s

       为rcS添加可执行权限:

       $ chmod   +x  init.d/rcS

 

       在etc下添加profile文件,文件内容为:

#!/bin/sh

export HOSTNAME=farsight

export USER=root

export HOME=root

export PS1="[$USER@$HOSTNAME \W]\# "

PATH=/bin:/sbin:/usr/bin:/usr/sbin

LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH

export PATH  LD_LIBRARY_PATH

11、 设备文件创建

根文件系统中有一个设备节点是必须的,在dev下创建console节点

$ sudo  mknod   dev/console  c  5  1

重要:新制作的文件系统尺寸若超出8M,删除不需要的库文件

       二、NFS测试

    1、删除原先的/source/rootfs

    $ sudo  rm  -rf  /source/rootfs   

    2、将我们新建的根文件系统拷贝到/source/rootfs目录下

    $sudo  mkdir  /source/rootfs

    $ sudo  cp  _install/*   /source/rootfs   –a

    3、设置uboot环境变量

# setenv  bootcmd  tftp  20008000  zImage\; go  20008000

# setenv  bootargs  root=nfs  nfsroot=192.168.1.100:/source/rootfs  init=/linuxrc console=ttySAC0,115200  ip=192.168.1.200

# saveenv

重新启动开发板,查看是否能够正常挂载,功能是否正常

 

将NANDFLASH的用户文件系统分区以yaffs2的方式挂载到/mnt目录下:

在/etc/init.d/rcS添加:

mount  -t yaffs2 /dev/mtdblock3 /mnt

这样,就可以以yaffs2文件系统的方式管理nandflash的第四个分区(0~3)了。当然这里的yaffs2也可以换成cramfs、jffs2。但前提是linux内核支持该文件系统。

 

三、制作ramdisk文件系统

通过NFS测试以后,就可以制作ramdisk文件系统了,具体如下:

       1、制作一个大小为8M的镜像文件

        $ cd  ~

       $ dd  if=/dev/zero  of=initrd.img  bs=1k  count=8192 (initrd.img为8M)

       2、格式化这个镜像文件为ext2

       $ mkfs.ext2  -F  initrd.img

       3、在mount下面创建initrd目录作为挂载点

       $ sudo  mkdir  /mnt/initrd

       4、将这个磁盘镜像文件挂载到/mnt/initrd下

       注意这里的initrd.img不要和ubuntu根目录下的initrd.img弄混了,同时initrd.img不能存放在rootfs目录中

       $ sudo  mount  -t  ext2   -o  loop  initrd.img  /mnt/initrd

       5、将我们的文件系统复制到initrd.img中

将测试好的文件系统里的内容全部拷贝到 /mnt/initrd目录下面

       $ sudo  cp  /source/rootfs/*   /mnt/initrd  –a

6、卸载initrd

$ sudo  umount  /mnt/initrd

7、压缩initrd.img为initrd.img.gz并拷贝到/tftpboot下

$ gzip  --best  -c  initrd.img  >  initrd.img.gz

$ cp  initrd.img.gz  /tftpboot

8、配置内核支持RAMDISK

制作完 initrd.img.gz后,需要配置内核支持RAMDISK作为启动文件系统

Device Drivers

       SCSI device support  --->

              <*> SCSI disk support

       Block devices  --->

              <*>RAM  block  device  support  

(1)Default number of RAM disks 

(8192) Default RAM disk size (kbytes)   (修改为8M)

General setup  --->

       [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support

重新编译内核,复制到/tftpboot

       9、在U-BOOT命令行重新设置启动参数:

# setenv  bootcmd  tftp  20008000  zImage \; tftp  20800000  initrd.img.gz \; go  20008000

# setenv  bootargs  root=/dev/ram  rw  init=/linuxrc  initrd=0x20800000,8M console=ttySAC0,115200

# saveenv

重新启动开发板查看能否正常启动

 

       四、制作cramfs文件系统

1、cramfs文件系统镜像制作

由于系统提供制作cramfs文件系统的工具,可以直接使用。具体操作如下;

$ mkfs.cramfs  /source/rootfs  rootfs.cramfs

2、将rootfs.cramfs拷贝到/tftpboot目录下

$ sudo  cp  rootfs.cramfs  /tftpboot

3、将rootfs.cramfs烧写到nand flash的第三个分区上

u-boot下执行如下命令

# tftp  20008000  rootfs.cramfs

# nand  erase  400000  400000

# nand  write  20008000  400000  400000

4、重新设置u-boot启动参数

# setenv  bootcmd  tftp  20008000  zImage\; go  20008000

# setenv  bootargs  root=/dev/mtdblock2   init=/linuxrc  console=ttySAC0,115200

# saveenv

启动开发板,测试是否成功。

[root@farsight /root] # ls /

bin       etc      linuxrc     sbin     tmp      var

dev      lib      mnt      proc     test     usr

[root@farsight /root] # mkdir test

mkdir: Cannot create directory `test': Read-only file system

注意:cramfs格式的文件系统是只读

 

       五、制作jffs2文件系统

       1、配置内核支持jffs2文件系统

File systems  --->

           [*] Miscellaneous filesystems  --->

            <*>   Journalling  Flash  File  System  v2  (JFFS2)  support

重新编译内核并拷贝到/tftpboot下

2、zlib的编译

       解压zlib-1.2.3.tar.bz2并进入zlib-1.2.3配置编译安装

       $ tar  xvf  zlib-1.2.3.tar.bz2

       $ cd  zlib-1.2.3

       $ ./configure

       $ make

       $ sudo  make install

       3、mtd工具编译

       解压mtd-snapshot-20050519.tar.bz2 并进入mtd/util编译安装

       $ tar  xvf  mtd-snapshot-20050519.tar.bz2

       $ cd  mtd/util

       $ make

       $ sudo  make  install

       这样我们的系统里就有了mkfs.jffs2这个工具了

       4、jffs2文件系统镜像制作

       $ mkfs.jffs2   -r  /source/rootfs  -o  rootfs.jffs2  -e  0x20000  --pad=0x400000  -n

       $ sudo  cp  rootfs.jffs2  /tftpboot

       5、jffs2文件系统烧写

# tftp  20008000  rootfs.jffs2

# nand  erase  400000  400000

# nand  write  20008000  400000  400000

       6、设置u-boot启动参数

# setenv  bootcmd  tftp  20008000  zImage\; go  20008000

# setenv  bootargs  root=/dev/mtdblock2   rootfstype=jffs2  rw  init=/linuxrc

   console=ttySAC0,115200 

# saveenv

       重新启动开发板,查看是否成功

posted @ 2013-08-09 14:13  dolinux  阅读(732)  评论(0编辑  收藏  举报