Chinaunix首页 | 论坛 | 博客
  • 博客访问: 209838
  • 博文数量: 56
  • 博客积分: 1085
  • 博客等级: 少尉
  • 技术积分: 652
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-29 13:50
文章分类
文章存档

2014年(4)

2012年(25)

2011年(27)

我的朋友

分类: Delphi

2011-11-30 14:31:44

<一>U-boot源码结构

 

      图片来自韦东山的《嵌入式linux应用开发完全手册》

       U-boot下载地址:

      交叉编译工具链  3.3.2

U-Boot在FL2440上移植(一)----修改系统时钟

U-Boot在FL2440上移植(一)----修改系统时钟

<二>U-boot移植

    1.新建一个fl2440开发板目录和文件

      ①在board目录下新建fl2440目录,讲smdk2410目录下的文件复制到fl2440目录下,并将board/fl2440/smdk2410.c重命名为fl2440.c

      在include/configs目录下建立一个配置文件fl2440.h。

      ②修改u-boot-1.1.6目录下Makefile文件

smdk2410_config : unconfig

@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

后面加上

fl2410_config : unconfig

@$(MKCONFIG) $(@:_config=) arm arm920t fl2410 NULL s3c24x0

然后在board/fl2440/Makefile中修改

COBJS := smdk2410.o flash.o    为   COBJS := fl2440.o flash.o

2.修改SDRAM的配置

①修改board/fl2440/lowlevel_init.s文件中的126行

 

#define REFCNT    0x4f4 

 

修改board/fl2440/fl2440.c中的board_init函数,即替换掉整个函数board_init包括它本身的所有语句。

board_init函数在识别上S3C2440或是S3C2410后,设置了机器类型ID:gd-db-bi_arch_number,后面的函数可以通过它来分辨S3C2410还是S3C2440。首先要在程序的开头增加如下一行,这样才能使用gd变量。

DECLARE_GLOBAL_DATA_PTR;

 

#define S3C2440_MPLL_400MHZ ((0x7f<<12)|(0x02<<4)|(0x01))

#define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02))

#define S3C2440_CLKDIV 0x05

 

 

#define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))

#define S3C2410_UPLL_48MHZ ((0x28<<12)|(0x01<<4)|(0x02))

#define S3C2410_CLKDIV 0x03

 

int board_init (void)

{

S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();

 

 

gpio->GPACON = 0x007FFFFF;

gpio->GPBCON = 0x00044555;

gpio->GPBUP = 0x000007FF;

gpio->GPCCON = 0xAAAAAAAA;

gpio->GPCUP = 0x0000FFFF;

gpio->GPDCON = 0xAAAAAAAA;

gpio->GPDUP = 0x0000FFFF;

gpio->GPECON = 0xAAAAAAAA;

gpio->GPEUP = 0x0000FFFF;

gpio->GPFCON = 0x000055AA;

gpio->GPFUP = 0x000000FF;

gpio->GPGCON = 0xFF95FFBA;

gpio->GPGUP = 0x0000FFFF;

gpio->GPHCON = 0x002AFAAA;

gpio->GPHUP = 0x000007FF;

 

 

if ((gpio->GSTATUS1 == 0x32410000) || (gpio->GSTATUS1 == 0x32410002))

{

 

clk_power->CLKDIVN = S3C2410_CLKDIV;

 

 

__asm__( "mrc p15, 0, r1, c1, c0, 0\n"

"orr r1, r1, #0xc0000000\n"

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

:::"r1"

);

 

 

clk_power->LOCKTIME = 0xFFFFFF;

 

 

clk_power->MPLLCON = S3C2410_MPLL_200MHZ;

 

 

delay (4000);

 

 

clk_power->UPLLCON = S3C2410_UPLL_48MHZ;

 

 

delay (8000);

 

 

gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;

}

else

{

 

clk_power->CLKDIVN = S3C2440_CLKDIV;

 

 

__asm__( "mrc p15, 0, r1, c1, c0, 0\n"

"orr r1, r1, #0xc0000000\n"

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

:::"r1"

);

 

 

clk_power->LOCKTIME = 0xFFFFFF;

 

 

clk_power->MPLLCON = S3C2440_MPLL_400MHZ;

 

 

delay (4000);

 

 

clk_power->UPLLCON = S3C2440_UPLL_48MHZ;

 

 

delay (8000);

 

 

gd->bd->bi_arch_number = MACH_TYPE_S3C2440;

}

 

 

gd->bd->bi_boot_params = 0x30000100;

 

icache_enable();

dcache_enable();

 

return 0;

}

③S3C2410和S3C2440的MPLL,UPLL计算公式不一样,所以get_PLLCLK函数也需要修改

在cpu/arm920t/s3c24X0/speed.c中修改:

 

board_init函数在识别上S3C2440或是S3C2410后,设置了机器类型ID:gd-db-bi_arch_number,后面的函数可以通过它来分辨S3C2410还是S3C2440。首先要在程序的开头增加如下一行,这样才能使用gd变量。

DECLARE_GLOBAL_DATA_PTR;

修改get_PLLCLK函数:

static ulong get_PLLCLK(int pllreg)

{

S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

ulong r, m, p, s;

 

if (pllreg == MPLL)

r = clk_power->MPLLCON;

else if (pllreg == UPLL)

r = clk_power->UPLLCON;

else

hang();

 

m = ((r & 0xFF000) >> 12) + 8;

p = ((r & 0x003F0) >> 4) + 2;

s = r & 0x3;

 

 

if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)

return((CONFIG_SYS_CLK_FREQ * m) / (p << s));

else

return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));

}

即在get_PLLCLK函数下加入上面的红色字体。

修改get_HCLK, get_PCLK(直接粘贴下面代码,来把这个两个函数覆盖掉):

 

#define S3C2440_CLKDIVN_PDIVN (1<<0)

#define S3C2440_CLKDIVN_HDIVN_MASK (3<<1)

#define S3C2440_CLKDIVN_HDIVN_1 (0<<1)

#define S3C2440_CLKDIVN_HDIVN_2 (1<<1)

#define S3C2440_CLKDIVN_HDIVN_4_8 (2<<1)

#define S3C2440_CLKDIVN_HDIVN_3_6 (3<<1)

#define S3C2440_CLKDIVN_ LK (1<<3)

 

#define S3C2440_CAMDIVN_CAMCLK_MASK (0xf<<0)

#define S3C2440_CAMDIVN_CAMCLK_SEL (1<<4)

#define S3C2440_CAMDIVN_HCLK3_HALF (1<<8)

#define S3C2440_CAMDIVN_HCLK4_HALF (1<<9)

#define S3C2440_CAMDIVN_DVSEN (1<<12)

 

 

ulong get_HCLK(void)

{

S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

unsigned long clkdiv;

unsigned long camdiv;

int hdiv = 1;

 

 

if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)

return((clk_power->CLKDIVN & 0x2) ? get_FCLK()/2 : get_FCLK());

else

{

clkdiv = clk_power->CLKDIVN;

camdiv = clk_power->CAMDIVN;

 

 

 

switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {

case S3C2440_CLKDIVN_HDIVN_1:

hdiv = 1;

break;

 

case S3C2440_CLKDIVN_HDIVN_2:

hdiv = 2;

break;

 

case S3C2440_CLKDIVN_HDIVN_4_8:

hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;

break;

 

case S3C2440_CLKDIVN_HDIVN_3_6:

hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;

break;

}

 

return get_FCLK() / hdiv;

}

}

 

 

ulong get_PCLK(void)

{

S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

unsigned long clkdiv;

unsigned long camdiv;

int hdiv = 1;

 

 

if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)

return((clk_power->CLKDIVN & 0x1) ? get_HCLK()/2 : get_HCLK());

else

{

clkdiv = clk_power->CLKDIVN;

camdiv = clk_power->CAMDIVN;

 

 

 

switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {

case S3C2440_CLKDIVN_HDIVN_1:

hdiv = 1;

break;

 

case S3C2440_CLKDIVN_HDIVN_2:

hdiv = 2;

break;

 

case S3C2440_CLKDIVN_HDIVN_4_8:

hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;

break;

 

case S3C2440_CLKDIVN_HDIVN_3_6:

hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;

break;

}

 

return get_FCLK() / hdiv / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);

}

}

重新执行make fl2440_config make all 生成u-boot.bin,由于还没有增加NAND Flash的支持,所以可烧入NOR Flash中运行

在make all时会出现错误:没有CAMDIVN

这个要在include/s3c24x0.h头文件中定义,在129行S3C24X0_CLOCK_POWER结构体中增加:S3C24X0_REG32 CAMDIVN;

现在执行 make fl2440_config 和 make all生成U-Boot.bin就可以烧入norflash了。

<一>选择NOR flash型号

    我的开发板上的nor flash芯片是Intel的JS28F320(4MB)(1device=32blocks,1block=128MB

fl2440默认是nandflash启动,norflash启动只需将跳线帽J5拔掉就可以了
  

   1. 把开发板的配置文件fl2440.h(/include/configs/fl2440.h)中关于flash的配置部分都删掉,换成下面的配置:


 
#define CONFIG_NR_DRAM_BANKS     1           
 
#define PHYS_SDRAM_1          0x30000000       
 
#define PHYS_SDRAM_1_SIZE     0x04000000       
 
#define PHYS_FLASH_1         0x00000000         
 
#define CFG_FLASH_BASE       PHYS_FLASH_1
 
#define CFG_MONITOR_BASE    TEXT_BASE
 
#define FLASH_BASE0_PRELIM           PHYS_FLASH_1
 

 
#define CONFIG_SYS_FLASH_PROTECTION    1
 
#define CFG_MAX_FLASH_BANKS     1      
 
#define CONFIG_SYS_FLASH_SIZE     0x00400000    
 
#define CFG_MAX_FLASH_SECT     32    
 

 
#define CFG_FLASH_ERASE_TOUT     (2*CONFIG_SYS_HZ)


 
#define CONFIG_SYS_FLASH_WRITE_TOUT     (2*CONFIG_SYS_HZ)


 
#define CFG_ENV_IS_IN_FLASH     1
 
#define CFG_ENV_SIZE         0x20000       
 
#define CFG_ENV_OFFSET      0x40000


#define CONFIG_SYS_HZ                   1000

 

如果出现   警告: “no newline at end of file" 只需在这段代码后加几个回车就可以了

   

  
 

    2. 把开发板目录下flash.c文件替换成下面的/board/cmi/下面的flash.c文件,然后删除这个write_short函数的申明和定义、删除write_buff函数。替换成下面的两个函数

int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
   ulong cp, wp;
   ushort data;
   int l;
   int i, rc;

   wp = (addr & ~1);       

  
   if ((l = addr - wp) != 0)
   {
      data = 0;
      for (i=0, cp=wp; i       data = (data >> 8) | (*(uchar *)cp << 8);
      }
      for (; i<2 && cnt>0; ++i) {
     data = (data >> 8) | (*src++ << 8);
     --cnt;
     ++cp;
      }
      for (; cnt==0 && i<2; ++i, ++cp) {
     data = (data >> 8) | (*(uchar *)cp << 8);
      }

      if ((rc = write_word(info, wp, data)) != 0) {
     return (rc);
      }
      wp += 2;
   }

  
   while (cnt >= 2) {
      data = *((vu_short*)src);
      if ((rc = write_word(info, wp, data)) != 0) {
      return (rc);
      }
      src += 2;
      wp  += 2;
      cnt -= 2;
   }

   if (cnt == 0) {
      return ERR_OK;
   }

  
   data = 0;
   for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
      data = (data >> 8) | (*src++ << 8);
      --cnt;
   }
   for (; i<2; ++i, ++cp) {
      data = (data >> 8) | (*(uchar *)cp << 8);
   }

   return write_word(info, wp, data);
}


static int write_word (flash_info_t *info, ulong dest, ushort data)
{
   vu_short *addr = (vu_short *)dest, val;
   int rc = ERR_OK;
   int flag;


  
   if ((*addr & data) != data)
      return ERR_NOT_ERASED;

  
   flag = disable_interrupts();

  
   *addr = 0x50;

  
   *addr = 0x40;

  
   *addr = data;

  
   reset_timer_masked();

  
   while(((val = *addr) & 0x80) != 0x80)
   {
      if (get_timer_masked() > CONFIG_SYS_FLASH_WRITE_TOUT) {
      rc = ERR_TIMOUT;
     
      *addr = 0xB0;
      goto outahere;
      }
   }

   if(val & 0x1A) {       
      printf("\nFlash write error x at address lx\n",
           (int)val, (unsigned long)dest);
      if(val & (1<<3)) {
     printf("Voltage range error.\n");
     rc = ERR_PROG_ERROR;
     goto outahere;
      }
      if(val & (1<<1)) {
     printf("Device protect error.\n");
     rc = ERR_PROTECTED;
     goto outahere;
      }
      if(val & (1<<4)) {
     printf("Programming error.\n");
     rc = ERR_PROG_ERROR;
     goto outahere;
      }
      rc = ERR_PROG_ERROR;
      goto outahere;
   }

outahere:
  
   *addr = 0xFF;

   if (flag)
      enable_interrupts();

   return rc;
}

   3. 修改board/fl2440/flash.c中函数申明:

static ulong flash_get_size (vu_short *addr, flash_info_t *info);

//static int write_short (flash_info_t *info, ulong dest, ushort data);

static int write_word (flash_info_t *info, ulong dest, ushort data);

static void flash_get_offsets (ulong base, flash_info_t *info);

    4. 修改flash.c文件中的一个宏定义:
把:
#define FLASH_BLOCK_SIZE        0x00010000
改为:
#define FLASH_BLOCK_SIZE        0x00020000

 

<二>执行make fl2440config 和 make all将生成的U-Boot.bin烧入norflash

NOR Flash常用命令 :查看NOR flash信息  flinfo

                    加/解写保护命令 protect

                    擦出命令    erase

                    读norflash     mm/cp

                    写norflash     cp  

 

  

U-Boot在FL2440上移植(二)----支持NOR Flash

<一>支持NAND Flash

 

    1. 首先在配置文件 include/config/fl2440.h 的宏 CONFIG_COMMANDS 中增加 CFG_CMD_NAND,

#define CONFIG_COMMANDS \
   (CONFIG_CMD_DFL  | \
   CFG_CMD_CACHE  | \
   CFG_CMD_NAND  | \
    \

 

    2.在配置文件 include/configs/fl2440.h 中增加如下3个宏

#define CFG_NAND_BASE 0 //无实际意义:基地址,在board_nand_init中重新定义

#define CFG_MAX_NAND_DEVICE 1 //NAND Flash设备数目为1

#define NAND_MAX_CHIPS 1 //每个NAND设备由1个NADN芯片组成

 

3.在 include/s3c24x0.h 文件中增加s3c2440_NAND 数据结构

 

 

typedef struct {

S3C24X0_REG32 NFCONF;

S3C24X0_REG32 NFCONT;

S3C24X0_REG32 NFCMD;

S3C24X0_REG32 NFADDR;

S3C24X0_REG32 NFDATA;

S3C24X0_REG32 NFMECCD0;

S3C24X0_REG32 NFMECCD1;

S3C24X0_REG32 NFSECCD;

S3C24X0_REG32 NFSTAT;

S3C24X0_REG32 NFESTAT0;

S3C24X0_REG32 NFESTAT1;

S3C24X0_REG32 NFMECC0;

S3C24X0_REG32 NFMECC1;

S3C24X0_REG32 NFSECC;

S3C24X0_REG32 NFSBLK;

S3C24X0_REG32 NFEBLK;

 

} S3C2440_NAND;

 

4.在 includ/s3c2410.h 文件中仿照 s3c2410_GetBase_NAND 函数定义 S3C2440_GetBase_NAND 函数

 

static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
   {
       return (S3C2440_NAND * const)S3C2410_NAND_BASE;

 

5.在 cpu/arm920t/s3c24x0 下新建nand_flash.c文件,代码如下。

 

 


#include

#include

#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include
#include

DECLARE_GLOBAL_DATA_PTR;

#define S3C2410_NFSTAT_READY    (1<<0)
#define S3C2410_NFCONF_nFCE     (1<<11)

#define S3C2440_NFSTAT_READY    (1<<0)
#define S3C2440_NFCONT_nFCE     (1<<1)


static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
{
 S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

    if (chip == -1) {
        s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;   
    } else {
        s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;    
    }
}

 

static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
    struct nand_chip *chip = mtd->priv;

    switch (cmd) {
    case NAND_CTL_SETNCE:
    case NAND_CTL_CLRNCE:
        printf("%s: called for NCE\n", __FUNCTION__);
        break;

    case NAND_CTL_SETCLE:
        chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;
        break;

    case NAND_CTL_SETALE:
        chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;
        break;
 }
}

static int s3c2410_nand_devready(struct mtd_info *mtd)
{
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();

    return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);
}



static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)
{
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

    if (chip == -1) {
        s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;
    } else {
        s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;
    }
}


static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
    struct nand_chip *chip = mtd->priv;

    switch (cmd) {
    case NAND_CTL_SETNCE:
    case NAND_CTL_CLRNCE:
        printf("%s: called for NCE\n", __FUNCTION__);
        break;

    case NAND_CTL_SETCLE:
        chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;
        break;

    case NAND_CTL_SETALE:
        chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;
        break;

       
       
    default:
        chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
        break;
    }
}


static int s3c2440_nand_devready(struct mtd_info *mtd)
{
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

    return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);
}


static void s3c24x0_nand_inithw(void)
{
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

#define TACLS   0
#define TWRPH0  4
#define TWRPH1  2

    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410)
    {
       
        s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
    }
    else
    {
       
        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
       
        s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);
    }
}


void board_nand_init(struct nand_chip *chip)
{
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

    s3c24x0_nand_inithw();

    if (gd->bd->bi_arch_number == MACH_TYPE_SMDK2410) {
        chip->IO_ADDR_R    = (void *)&s3c2410nand->NFDATA;
        chip->IO_ADDR_W    = (void *)&s3c2410nand->NFDATA;
        chip->hwcontrol    = s3c2410_nand_hwcontrol;
        chip->dev_ready    = s3c2410_nand_devready;
        chip->select_chip  = s3c2410_nand_select_chip;
        chip->options      = 0;   
    } else {
        chip->IO_ADDR_R    = (void *)&s3c2440nand->NFDATA;
        chip->IO_ADDR_W    = (void *)&s3c2440nand->NFDATA;
        chip->hwcontrol    = s3c2440_nand_hwcontrol;
        chip->dev_ready    = s3c2440_nand_devready;
        chip->select_chip  = s3c2440_nand_select_chip;
        chip->options      = 0;    
    }

    chip->eccmode       = NAND_ECC_SOFT;    
}

#endif

 

    6.修改cpu/arm920t/s3c24x0/Makefile

 

COBJS = 加上一项nand_flash.o

  

    7.修改 cpu/arm920t/s3c24x0/Makefile文件如下

 

COBJS = i2c.o interrupts.o serial.o speed.o \
   usb_ohci.o nand_flash.o

 

<二>现在就可以编译了,如果出现错误

 

文件格式错误: failed to merge target specific data of file /usr/local/arm/3.3.2/lib/gcc-lib/arm-linux/3.3.2/libgcc.a(_clz.oS)

修改 cpu/arm920t/config.mk 文件如下(不使用软浮点进行编译,即用硬浮点进行编译)

PLATFORM_RELFLAGS += -fno-strict-aliasing  -fno-common -ffixed-r8 \
#   -msoft-float

可以使用新编译的U-Boot.bin烧入NAND Flash了。

 

<一>支持网卡芯片DM9000

 

driver下,有网卡驱动DM9000x.cDM9000x.h

DM9000接在BANK4,位宽16

 

include/configs/TX2440.h中设置网卡基地址:

56行处,将CS8900的定义改成:

#define CONFIG_DRIVER_DM9000 1

#define CONFIG_DM9000_BASE 0x20000300

#define DM9000_IO CONFIG_DM9000_BASE

#define DM9000_DATA (CONFIG_DM9000_BASE + 4)

#define CONFIG_DM9000_USE_16BIT

阅读(2257) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~