Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1638763
  • 博文数量: 197
  • 博客积分: 10046
  • 博客等级: 上将
  • 技术积分: 1983
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-07 12:36
个人简介

在外企做服务器开发, 目前是项目经理, 管理两个server开发的项目。不做嵌入式好久了。

文章分类
文章存档

2011年(2)

2010年(6)

2009年(18)

2008年(30)

2007年(100)

2006年(41)

分类: LINUX

2007-11-15 12:51:40

思考以下问题:

 

 

思考题:

 

1>  学习volatile , 为什么要用volatile ?什么条件下用volatile   volatile driver有什么用?

 

为什么我们下面的程序用到了 volatile , 为什么 kernel自带的watchdog driver (drivers/char/watchdog/s3c2410-wdt.c 没有用volatile ??

 

 

 

2> 强化c语言编程知识,

 

找出下列的定义有什么区别?

 

const int a;

const int *a;

int *const a;

int const *a;

const int *const a ;

const int const *a ; 

 

 

再写driver 的时候, 声明变量的时候, 还是严谨一些比较好。该加const 最好加const ,免得意外出错。

 

 

3> google上学习 , 对齐方面的知识 , 写一个宏, 实现 32 对齐, 分为 32向前对齐和向后对齐:   fn_before(33) = 32 ,    fn_after(33) = 64 

 

学习 __attribute__((__packed__))  到底是什么意思?   明白后, 继续学习 GNU 其他的扩展语法。

 

 

 

 //先自己写, 然后再对照这个程序。

 

 

 

核心的部分, 就是下面几句。

 

思想就是 把 一段内存的起始地址转换为一个结构体的指针 , 这样 ,就可以通过结构体 来存取 寄存器的值,  写起程序来, 比较方便 和便捷 。

 

 

 

//一定要用 volatile来定义, 对于写driver ,定义寄存器一定要用volatile 修饰

typedef volatile u8  S3C24X0_REG8;

typedef volatile u16 S3C24X0_REG16;

typedef volatile u32 S3C24X0_REG32;

 

 

#define S3C2410_WDTCON_RSTEN   (0x01) // 1<<0

#define S3C2410_WDTCON_INTEN   (1<<2)

#define S3C2410_WDTCON_ENABLE  (1<<5)

 

 

 

/* WATCH DOG TIMER (see manual chapter 18) */

typedef struct {

       S3C24X0_REG32 WDTCON;

       S3C24X0_REG32 WDTDAT;

       S3C24X0_REG32 WDTCNT;

} /*__attribute__((__packed__))*/ S3C24X0_WATCHDOG;

 

 

#define S3C24X0_WATCHDOG_BASE       s3c_wdt_base

 

static inline S3C24X0_WATCHDOG * const S3C24X0_GetBase_WATCHDOG(void)

{

       return (S3C24X0_WATCHDOG * const)S3C24X0_WATCHDOG_BASE;

}

 

 

 

static void wdt_enable(void)

{

       //这里用const 修饰符, 表示 , rWATCHDOG 是个指针常量。

       S3C24X0_WATCHDOG *const rWATCHDOG = S3C24X0_GetBase_WATCHDOG();                     //255           //128

       u16 COUNTER_VALUE = heartbeat * ( 50000000 / (PRESCALER + 1) / DIVISION_FACTOR );

      

       //WATCHDOG DAT REGISTER

       rWATCHDOG->WDTDAT = COUNTER_VALUE;

      

       //WATCHDOG COUNTER REGISTER

       rWATCHDOG->WDTCNT = COUNTER_VALUE;

      

       //write WDTCON  register

       rWATCHDOG->WDTCON &= ~0xff00;     //bit8~bit15 清零,然后写入PRESCALER

       rWATCHDOG->WDTCON |= (PRESCALER << 8);

             

       rWATCHDOG->WDTCON |= S3C2410_WDTCON_ENABLE | S3C2410_WDTCON_RSTEN;

      

      

}

 

 

 

//可以对比一下, 用 readb/readw/readl() 代码量就多了不少, 而且 不自然。  !虽然是这样, kernel的开发者还是推荐用 readb/w/l () 系列的函数, 最新的就是 ioread8/16/32()系列函数。

 

 

 

static void wdt_enable(void)

{

       u32 tmp;                             //255           //128

       u16 COUNTER_VALUE = heartbeat * ( 50000000 / (PRESCALER + 1) / DIVISION_FACTOR );

       //u16 COUNTER_VALUE = (1 << 16) -10;

      

       printk("COUNTER_VALUE=%hu\n",COUNTER_VALUE);

       printk("S3C2410_WTCNT address = %p\n",S3C2410_WTCNT);

       //写入 S3C2410_WTDAT

       iowrite32(COUNTER_VALUE, S3C2410_WTDAT);

       //写入S3C2410_WTCNT

       iowrite32(COUNTER_VALUE, S3C2410_WTCNT);

      

       tmp = ioread32(S3C2410_WTCON);   

       tmp &= ~0xff00;      //bit8~bit15 清零,然后写入PRESCALER

       tmp |= (PRESCALER << 8);

      

       //再写入division factor

       tmp &= ~(0x03 << 3);

       tmp |= 0x03 << 3;  //11b  is 128 division

      

       printk("the value written S3C2410_WTCON=0x%04x\n",tmp);

       iowrite32(tmp, S3C2410_WTCON);

      

       //重新eanble reset

       tmp = ioread32(S3C2410_WTCON);

       iowrite32(tmp |S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN , S3C2410_WTCON);

      

      

       //test,

       tmp = ioread32(S3C2410_WTCNT);

       printk("S3C2410_WTCNT value = %hu\n",tmp);

}

 

 

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