Chinaunix首页 | 论坛 | 博客
  • 博客访问: 974402
  • 博文数量: 238
  • 博客积分: 2842
  • 博客等级: 少校
  • 技术积分: 2765
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-16 00:20
个人简介

stdlf

文章分类

全部博文(238)

文章存档

2013年(6)

2012年(13)

2011年(82)

2010年(89)

2009年(48)

我的朋友

分类:

2009-09-04 22:19:36

我所分析的uboot代码是基于恒丰锐科的s3c44b0x开发板,不是做广告,因为我现在在用这个板子。

由于本人能力有限,所做的工作如有纰漏,请原谅,谢谢指正。
/*
* S3C44B0 CPU specific code
*/

#include
#include
#include

static void s3c44b0_flush_cache(void)   //刷新cache
{
volatile int i;
/* flush cycle 它用一个for循环进行内部的缓冲区初始化,由于S3C44B0决定每次读写都是按16字节进行的。因此,这里的i就是不断地加16个字节*/
for(i=0x10002000;i<0x10004800;i+=16)//缓存在使用内部ram映射区域为tag0,1,2,3还有LRU,这些都是按字(32b)访问的,地址为
                                      //0x10002000--0x100047f0 由于按16字节读写i<0x10004800也可以,详细参考cpu说明书
{
   *((int *)i)=0x0;      //全部写0
}
}

int cpu_init (void)     //初始化cpu函数, 该处理器没有使用IRQ和FIQ机制,所以不需要建立中断栈了
{
icache_enable();      /* 在里面调用了函数icache_enable(),它就是用来初始化S3C44B0的缓冲区,并且启用CPU缓冲区。因为CPU在加电之

后,它的初始化值是不启用内部的8K缓冲区的,必须由程序进行设置 。见77行*/

return 0;
}

int cleanup_before_linux (void)   //载入linux之前所做的工作
{
/*在调用linux之前应该启用cache,这样可以加快linux内核的解压缩
   cache memory should be enabled before calling
   Linux to make the kernel uncompression faster
*/
icache_enable();   //清空缓冲区,启用缓存

disable_interrupts (); //禁用中断

return 0;
}

void reset_cpu (ulong addr)//复位cpu
{
/*
   reset the cpu using watchdog
*/

/* Disable the watchdog.禁用看门狗*/
WTCON&=~(1<<5);    //第五位清零

/* set the timeout value to a short time...设置一个超时值 */
WTCNT = 0x1; //看门狗定时器计数寄存器

/* Enable the watchdog. 启用看门狗*/
WTCON|=1;
WTCON|=(1<<5);    //第5位置1

while(1) {
   /*NOP*/
}
}

int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
extern void reset_cpu (ulong addr);   //调用外部函数reset_cpu

disable_interrupts ();
reset_cpu (0);

/*NOTREACHED*/
return (0);
}

void icache_enable (void)

{
ulong reg;
//清空内存的缓冲区.
s3c44b0_flush_cache();
/*初始化缓冲区,设置非缓冲区的起始地址和结束地址。
第一个寄存器指明下面的地址不要缓存,低16位是起始地址,高16位是结束地址。并且空间大小都是以4K为界。0x0000:0000 - 0x0C00:0000
   Init cache
   Non-cacheable area (everything outside RAM)
   0x0000:0000 - 0x0C00:0000    因为不是所有内存都需要进行缓冲的,比

如读取外面的IO,就不需要进行缓冲;读取FLASH也不需要因此,设置第一个非缓冲区的起始地址为NCACHBE0 =

0xC0000000,这个值里的低16位是起始地址0x0000,它的32位地址就是从0x00000000开始。它的高16位是结束地址

0Xc000,它的32位地址就是从0Xc0000000结束。*/
NCACHBE0 = 0xC0000000;    //只设置第一个非缓冲区
NCACHBE1 = 0x00000000;

/*
   Enable chache    设置SYSCFG寄存器启用8K缓冲区。S3C44B0X的Cache提供完整的Cache使能和禁止操作模式。
   能够通过设置SYSCFG寄存器中CM域中的值为01或11来使能Cache(其中,01为使能4KB Cache, 11为使能8 KB Cache),
   而通过清除SYSCFG寄存器中[2:1]域为0来禁止Cache功能 */
reg = SYSCFG;
reg |= 0x00000006; /* 8kB */
SYSCFG = reg;
}

void icache_disable (void)      //禁用cache
{
ulong reg;

reg = SYSCFG;
reg &= ~0x00000006; /* 8kB 清除SYSCFG寄存器中[2:1]域为0来禁止Cache功能*/
SYSCFG = reg;
}

int icache_status (void)
{
return 0;
}

void dcache_enable (void)
{
icache_enable();
}

void dcache_disable (void)
{
icache_disable();
}

int dcache_status (void)
{
return dcache_status();
}

/*
RTC stuff
*/
#include
#ifndef BCD2HEX
#define BCD2HEX(n) ((n>>4)*10+(n&0x0f))   //转化公式
#endif
#ifndef HEX2BCD
#define HEX2BCD(x) ((((x) / 10) << 4) + (x) % 10)
#endif

void rtc_get (struct rtc_time* tm)
{
RTCCON |= 1;     //RTC读写允许位=1,允许。
tm->tm_year = BCD2HEX(BCDYEAR); //BCD to HEX
tm->tm_mon   = BCD2HEX(BCDMON);
tm->tm_wday   = BCD2HEX(BCDDATE);
tm->tm_mday   = BCD2HEX(BCDDAY);
tm->tm_hour = BCD2HEX(BCDHOUR);
tm->tm_min = BCD2HEX(BCDMIN);
tm->tm_sec = BCD2HEX(BCDSEC);

if (tm->tm_sec==0) {
   /* we have to re-read the rtc data because of the "one second deviation" problem */
   /* see RTC datasheet for more info about it   必须重读RTC,因为有1秒偏差问题,详细请查看RTC资料*/
   tm->tm_year = BCD2HEX(BCDYEAR);
   tm->tm_mon   = BCD2HEX(BCDMON);
   tm->tm_mday   = BCD2HEX(BCDDAY);
   tm->tm_wday   = BCD2HEX(BCDDATE);
   tm->tm_hour = BCD2HEX(BCDHOUR);
   tm->tm_min = BCD2HEX(BCDMIN);
   tm->tm_sec = BCD2HEX(BCDSEC);
}

RTCCON &= ~1;   //禁用,不允许读写

if(tm->tm_year >= 70)    //以1970年为界。
   tm->tm_year += 1900;
else
   tm->tm_year += 2000;
}

void rtc_set (struct rtc_time* tm)    //设置实时时钟
{
if(tm->tm_year < 2000)
   tm->tm_year -= 1900;
else
   tm->tm_year -= 2000;

RTCCON |= 1;  
BCDYEAR = HEX2BCD(tm->tm_year);
BCDMON = HEX2BCD(tm->tm_mon);
BCDDAY = HEX2BCD(tm->tm_mday);
BCDDATE = HEX2BCD(tm->tm_wday);
BCDHOUR = HEX2BCD(tm->tm_hour);
BCDMIN = HEX2BCD(tm->tm_min);
BCDSEC = HEX2BCD(tm->tm_sec);
RTCCON &= 1;
}
//复位实时时钟
void rtc_reset (void)
{
RTCCON |= 1;
BCDYEAR = 0;
BCDMON = 0;
BCDDAY = 0;
BCDDATE = 0;
BCDHOUR = 0;
BCDMIN = 0;
BCDSEC = 0;
RTCCON &= 1;
}

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