uboot 移植到s3c2410 第二篇

 
 
二、修改相关源文件
 
主要有三个方面的文件要修改:
 
1.       我们用的flash是两片在一起,组成了32位寻址。而原来的代码是按16位寻址写的。所以关于flash一系列操作的代码要修改。这部分修改要保证能正确操作flash
 
2.       关于i2c设备eeprom的相关配置,主是要是设备地址以及设备内存地址的宽度等。同样,这里修改后要保证能正确读写eeprom
 
3.       关于网卡的设置,网络用了以后我们就可以用过网络从主机上下载相关代码。修改完后要能使用tftp工具进行下载。
 
1) 、flash
 
由于我的开发板是两块e28F128J3A flash组成32位寻址,所以与地址操作相关的数据都由原来的16位改为32位。
 
首先修改flash 相关的命令,在flash_e28_cmi.c
 
#define    FLASH_ID_MASK               0xFFFF
#define FLASH_BLOCK_SIZE             0x00010000
#define FLASH_CMD_READ_ID         0x0090
#define FLASH_CMD_RESET                    0x00ff
#define FLASH_CMD_BLOCK_ERASE              0x0020
#define FLASH_CMD_ERASE_CONFIRM         0x00D0
#define FLASH_CMD_CLEAR_STATUS            0x0050
#define FLASH_CMD_SUSPEND_ERASE          0x00B0
#define FLASH_CMD_WRITE                   0x0040
#define FLASH_CMD_PROTECT        0x0060
#define FLASH_CMD_PROTECT_SET              0x0001
#define FLASH_CMD_PROTECT_CLEAR         0x00D0
#define FLASH_STATUS_DONE         0x0080
 
这些相关的命令状态值等都是16位的,只能操作一片flash。所以要将其全部改为32位
 
#define    FLASH_ID_MASK               0xFFFFFFFF
#define FLASH_BLOCK_SIZE             0x00040000
#define FLASH_CMD_READ_ID         0x00900090
#define FLASH_CMD_RESET                    0x00ff00ff
#define FLASH_CMD_BLOCK_ERASE              0x00200020
#define FLASH_CMD_ERASE_CONFIRM         0x00D000D0
#define FLASH_CMD_CLEAR_STATUS            0x00500050
#define FLASH_CMD_SUSPEND_ERASE          0x00B000B0
#define FLASH_CMD_WRITE                   0x00400040
#define FLASH_CMD_PROTECT        0x00600060
#define FLASH_CMD_PROTECT_SET              0x00010001
#define FLASH_CMD_PROTECT_CLEAR         0x00D000D0
#define FLASH_STATUS_DONE         0x00800080
 
在flash_init() 函数中
 
size_b0 = flash_get_size((vu_short *)FLASH_BASE0_PRELIM, &flash_info[0]);
 
这里是读取flash的大小,其传递的地址是vu_short型,只能读取一片flash的信息。所以做如下修改
 
size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
 
CFG_FLASH_BASE在s3c2410.h中定义。是flash的基地址
 
还有
 
flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]);
 
改为
 
flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
 
 
下面还要到flash_get_size()函数中进行修改
 
static ulong flash_get_size (vu_short *addr, flash_info_t *info)
 
改为
 
static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 
vu_short value;
 
改为
 
vu_long value;
 
flash_get_size函数修改结束。
 
 
擦除flash 函数 flash_erase()
 
擦除比较简单,直接往每个sector的起始地址写擦除命令即可
vu_short *addr = (vu_short *)(info->start[sect]);
 
改为
 
vu_long *addr = (vu_long *)(info->start[sect]);
 
这里还要注意一个问题,下面被注释掉的两行是用来判断擦除单个sector是否超时的,它提供了一个擦除起始时间。但它确在下面的擦除循环之前,这样就是擦除所有sector的起始时间,而不是擦除单个sector的起始时间
        /*the next two lines will lead to timeing out in this location.
        modified by BoySKung 08/11/14 */
       //start = get_timer (0);
       //last  = start;
 
       /* Start erase on unprotected sectors */
       for (sect = s_first; sect<=s_last; sect++) { //这里是擦除循环
              if (info->protect[sect] == 0) {      /* not protected */
                     //vu_short *addr = (vu_short *)(info->start[sect]);
                    vu_long *addr = (vu_long *)(info->start[sect]);/*modified by BoySKung 08/11/05 */
                     unsigned long status;
 
应该把这个起始时间放到循环里面
                   start = get_timer (0);/*modified by BoySKung 08/11/14*/
                   last  = start;
 
                     /* Disable interrupts which might cause a timeout here */
                     flag = disable_interrupts();
 
#ifdef DEBUG
                     printf("Erase sector %d at start addr 0x%08X", sect, (unsigned int)info->start[sect]);
#endif
 
                     *addr = FLASH_CMD_CLEAR_STATUS;
                     *addr = FLASH_CMD_BLOCK_ERASE;
                     *addr = FLASH_CMD_ERASE_CONFIRM;
 
                     /* re-enable interrupts if necessary */
                     if (flag)
                            enable_interrupts();
 
                     /* wait at least 80us - let's wait 1 ms */
                     udelay (1000);
 
                     while (((status = *addr) & FLASH_STATUS_DONE) != FLASH_STATUS_DONE) {
              在这里通过上面的起始时间获得当前时间,判断是否超时
                            if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
                                   printf("Flash erase timeout at address %lx/n", info->start[sect]);
                                   *addr = FLASH_CMD_SUSPEND_ERASE;
                                   *addr = FLASH_CMD_RESET;
                                   return 1;
                            }
 
                            /* show that we're waiting */
                            if ((now - last) > 1000) {      /* every second */
                                   putc ('.');
                                   last = now;
                            }
                     }
                     *addr = FLASH_CMD_RESET;
              }
 
写数据到flash
 
这里涉及到两个函数:
 
write_buff(); //写数据前进行一些调整
 
write_word(); //真正的往flash中写数据
 
这里要修改的地方比较多,主要是数据长度和地址长度方面的凡是我修改的地方都有/*modified by BoySKung 08/11/05*/ 或 /*added by BoySKung 08/11/05*/这样的注释
 
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
       ulong cp, wp;
       //ushort data;
       ulong data;/*modified by BoySKung 08/11/05*/
       int i, rc;
       int l; /*added by BoySKung 08/11/05*/
 
       if (info->flash_id == FLASH_UNKNOWN) {
              return 4;
       }
 
       //wp = (addr & ~1);      /* get lower word aligned address */
     wp = (addr & ~3);       /*modified by BoySKung 08/11/05*/
//现我们是32位操作,所以地址应4字节对齐
       /*
        * handle unaligned start byte
        */
/*
       if (addr - wp) {
              data = 0;
              data = (data << 8) | *src++;
              --cnt;
              if ((rc = write_short(info, wp, data)) != 0) {
                     return (rc);
              }
              wp += 2;
       }
*/                                      /*modified by BoySKung 08/11/05*/
//我把上面那段对未对齐头部处理的代码注释掉,重新写了一段处理代码
//这里要注意,我的cpu初始化后是小端模式
       /*
        * handle unaligned start byte, our cpu is little-endian
        */
    if (l = (addr - wp) > 0)
    {
        data = 0;
        //把从对齐地址wp到目的地址addr的内容保存到data的低字节中,
              //这样可避免改变从wp到addr的内容,
        //因为往flash中写时,是从对齐地址wp一次写四个字节,
        for (i=0, cp=wp; i<l; i++, cp++)  
        {                
            data |= (*(uchar *)cp << 8*i);
        }
 
        //将内存中开始的数据按字节保存到data中,
        for (; i<4 && cnt>0; i++)
        {
            data |= (*src++ << 8*i);
            --cnt;
            ++cp;
        }
 
              //如果要写的总字节数cnt 小于从地址addr到第二个对齐地址wp+4的字节数,
             //那么从addr+cnt到wp+4的内容也要保存到data中
        for (; cnt=0 && i<4; i++, cp++)
        {
            data |= (*(uchar *)cp << 8*i);
        }
 
              //处理完后开始往flash写,一次写四个字节
        if ((rc = write_word(info, wp, data)) != 0)
        {
            return (rc);
        }
         wp += 4; //处理完后地址增加四个字节
    }
       /*
        * handle word aligned part
        */
//这里是处理四字节对齐的部分。比较简单
       while (cnt >= 4) {
              data = 0;
    /*
              for (i=0; i<2; ++i) {
                     data = (data << 8) | *src++;
              }
    */
             data = *(vu_long*)src;   /*modified by BoySKung 08/11/05*/
       
              if ((rc = write_word(info, wp, data)) != 0) {
                     return (rc);
              }
              //wp  += 2;
              //cnt -= 2;
             
              src += 4;
              wp  += 4; /*modified by BoySKung 08/11/05*/
              cnt -= 4;
       }
 
       if (cnt == 0) {
              return (0);
       }
 
       /*
        * handle unaligned tail bytes
        */
 
       data = 0;
    /*
       for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) {
              data = (data << 8) | *src++;
              --cnt;
       }
      
       for (; i<2; ++i, ++cp) {
              data = (data << 8) | (*(uchar *)cp);
       }*/
 
       //尾部不够四字节的处理,当最后一次写时,剩的字节数n<4, 要将flash中addr+cnt
       //后4-n个字节的数据保存到和那剩下的n个字节内容保存到data中,够四字节一次
       //写入
 
       for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {  /*modified by BoySKung 08/11/05*/
              data |= (*src++ << 8*i);
              --cnt;
       }
   
       for (; i<4; ++i, ++cp) {
              data |= (*(uchar *)cp);
       }
 
       return (write_word(info, wp, data));
 
}
 
对write_word里的修改也主要是对数据或地址长度的修改
/*
 * Write 16 bit (short) to flash
 */
/*
 * Write 32 bit (short) to flash
 */
//static int write_short (flash_info_t *info, ulong dest, ushort data)
static int write_word (flash_info_t *info, ulong dest, ulong data)/*modified by BoySKung 08/11/05*/
{
       //vu_short *addr = (vu_short*)(info->start[0]);
       vu_long *addr = (vu_long*)(info->start[0]);  /*modified by BoySKung 08/11/05*/
       ulong start;
       int flag;
 
       /* Check if Flash is (sufficiently) erased */
       //if ((*((vu_short *)dest) & data) != data) {
       if ((*((vu_long *)dest) & data) != data) {  /*modified by BoySKung 08/11/05*/
              return (2);
       }
 
       /* Disable interrupts which might cause a timeout here */
       flag = disable_interrupts();
 
       if (!(info->flash_id & FLASH_VENDMASK)) {
              return 4;
       }
       *addr = FLASH_CMD_ERASE_CONFIRM;
       *addr = FLASH_CMD_WRITE;
 
       //*((vu_short *)dest) = data;
       *((vu_long *)dest) = data;  /*modified by BoySKung 08/11/05*/
 
       /* re-enable interrupts if necessary */
       if (flag) {
              enable_interrupts();
       }
 
       /* data polling for D7 */
       start = get_timer (0);
 
这里要做下说明 ,不能用addr[0] & FLASH_STATUS_DONE的值是否为0来判断其状态是否是完成。因为我们用的是两片flash, FLASH_STATUS_DONE 的值是00800080。这样要是有一片的状态是完成而另一片的状态是没有完成,那么上面表达式结果仍然不为0,也即其状态是完成。这样就会出判断错误
       /* wait for error or finish */
       //while(!(addr[0] & FLASH_STATUS_DONE)){ /*modified by BoySKung*/
    while( (addr[0] & FLASH_STATUS_DONE) != FLASH_STATUS_DONE){
              if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
                     addr[0] = FLASH_CMD_RESET;
                     return (1);
              }
       }
 
       *addr = FLASH_CMD_RESET;
       return (0);
}
 
 
对sector 的保护 flash_real_protect()
 

 
vu_short *addr = (vu_short*)(info->start[sector]);
 
改为
 
vu_long *addr = (vu_long*)(info->start[sector]);  /*modified by BoySKung 08/11/05*/
 
到这里整个关于flash操作的代码就移植完毕,可以等下载下目标板后进行验证
 
在文件的开头有对函数的声明,也要把它们改过来
 
 
2 ) 网卡
 
我们板子上用的是dm9000网卡,找到dirver/dm9000x.c 其初始化程序是eth_init();rcn lib_arm/board.c中的
 
 
 
/*dm9000*/ //added by BoySKung 08/11/06
#ifdef CONFIG_DRIVER_DM9000
    eth_init(gd->bd)
#endif
 
3 )串口
 
因为我们现在用的是UART2作为打印输出口,所以对初始化序列中的函数board_init()中的代码作如下修改:
 
       gpio->GPHCON = 0x002AFAAA;
 
改为
 
       gpio->GPHCON = 0x002AAAAA; /*modified by BoySKung 08/11/11*/
 
这是因为其管脚复用,原来的并未把GPHCON[15-12]设置为1010(RXD2、TXD2).
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值