s3c2410watchdog(编辑完毕)作者:蔡于清.什么是watchdog?watchdog,中文名称叫做“看门狗”,全称watchdogtimer,从字面上我们可以知道其实它属于一种定时器。然而它与我们平常所接触的定时器在作用上又有所不同。普通的定时器一般起记时作用,记时超时(TimerOut)则引起一个中断,例如触发一个系统时钟中断。熟悉windows开发的朋友应该用过windows的Timer,windowsTimer的作用与方才所讨论的定时器在功能上是相同的,只是windowsTimer属于软件定时器,当windowsTimer记时超时则引起App向System发送一条消息从而触发某个事件的发生。我们从以上的描述可知不论软件定时器或硬件定时器他们的作用都是在某个时间点上引起一个事件的发生,对于硬件定时器来说这个事件可能是通过中断的形式得以表现,对于软件定时器,这个事件则可以是以系统消息的形式得以表现。正如本文开头所讲的,watchdog本质上是一种定时器,那么普通定时器所拥有的特征它也应该具备,是的,当它记时超时时也会引起事件的发生,只是这个事件除了可以是系统中断外,它也可以是一个系统重起信号(ResetSignal),可以这么说吧,能发送系统重起信号的定时器我们就叫它watchdog.2.watchdog的工作描述当一个硬件系统开启了watchdog功能,那么运行在这个硬件系统之上的软件必须在规定的时间间隔内向watchdog发送一个信号.这个行为简称为喂狗(feeddog),以免watchdog记时超时引发系统重起。3.watchdog存在的意义是什么?你可能会问watchdog存在的意义是什么?开启了watchdog之后软件必须定时向它发信息,这不是麻烦又耗费资源的行为吗?其实这个行为很重要,这个行为是软件向硬件报告自身运行状态的一中手法。一个软件运行良好,那么它应该可以在规定的时间间隔内向watchdog发送信息,这等同于软件每隔一段时间就告诉硬件:“嘿,哥们,我在好好的跑着呢,你放心吧。”,若软件由于某个不当的操作而进入死循环(也就是俗称的死机),则他无法向watchdog发送信息了,watchdog将发生记时超时,从而引起硬件重起。如果没有watchdog的存在,程序已经死掉了,但我们的用户还一头雾水,以为系统正在进行大规模的运算而进行耐心的等待。。。这一等可就是天荒地老啊。。。-_-!!4.s3c2410watchdog的操作对于s3c2410的watchdog来说,PCLK是它唯一的时钟信号源。(不知道PCLK的朋友可以上网搜搜或看我下一篇文章)s3c2410用了3个寄存器对watchdog进行操作,3个寄存器分别为:WTCON,WTDAT,WTCNT。WTCON:watchdog控制寄存器WTDAT:watchdog数据寄存器WTCNT:watchdog记数寄存器以上各个寄存器的详细信息请参考s3c2410数据手册上关于watchdog部分5.s3c2410watchdog工作描述:在开启watchdog之前,我们必需在寄存器WTDAT里面存有一个值,在watchdog开启之后这个值会被自动加载进寄存器WTCNT中,WTCNT的作用将在下面进行讲解,现在你只需要知道WTDAT必须有一个值,这个值将被自动装进WTCNT中(注1)Watchdog根据PCLK,PrescalerValue,ClockSelect会产生一个watchdog自己的工作周期,我们把这个工作周期记为t_watchdog(注2),watchdog在一个t_watchdog周期结束时会产生一个记数递减信号,每当这个信号产生时,WTCNT中的值便减1,若在WTCNT递减为0(TimerOut)的时候软件层还没有重新往WTCNT中写入数值(这个行为便是我上文提到的喂狗),则watchdog触发ResetSignal,系统重起。根据上述的描述,我们可以更形象地描述watchdog的工作原理和3个寄存器之间的相互关系:WTCNT通过WTDAT得到一个值,watchdog在每个t_watchdog周期里向WTCNT发送一个递减信号,当WTCNT的值递减到0的时候则发生timeout,重而重起系统。下面我帖出一段设置watchdog并开启watchdog的程序1:voidenable_watchdog()2:{3:rWTCON=0x7F81;4:rWTDAT=0x8000;5:rWTCON|=15;6:}rWTCON,rWTDAT分别为寄存器WTCON,WTDAT的地址解引用,我如下定义他们#definerWTCON(*(volatileunsignedint*)0x53000000)#definerWTDAT(*(volatileunsignedint*)0x53000004)从上面的设置我们可知寄存器WTCON的值为0x7F81,分解出来得:PrescalerValue=255Division_factor=16(ClockSelect=16)InterruptGeneration=0(不产生中断)Reset=1(开启ResetSignal)第4行设置寄存器WTDAT的值为0x8000。第5行开启watchdog当调用上面的函数之后,你的系统已经开启了watchdog,所以你必须在WTCNT中的值递减到0之前重新往该寄存器写入一个非0值(feeddog),否则将引起系统重起,以下是feed_dog函数voidfeed_dog(){rWTCNT=0x8000;}下面是voidenable_watchdog()和feed_dog()配合使用的一个例子voidmain(){init_system();.........enable_watchdog();.........while(1){feed_dog();}}在这个例子中我假设了main函数是系统的主函数,在做完一系列系统初始化之后enable_watchdog()函数被调用,此时watchdog被启动,下面的while循环则是不断的进行feed_dog,使系统不发生重起。当然在实际应用中不可能采取这种架构来对watchdog进行操作,一般来说feed_dog函数的调用是被安插在定时器的中断服务例程中,当然,定时器的timeout(注意是定时器的timeout,不是watchdog的timeout)时间长度必须合适,否则在定时器还没来得及发生中断调用feed_dog函数之前,watchdog已经timeout了,那也将引起系统重起.注1:事实上,WTDAT和WTCNT这两个寄存器在系统上电之后会被硬件自动的填入两个初始值0x8000,开启watchdog之后,WTCNT并没有马上就把WTDAT中的值装入,而是使用初始值0x8000。在发生第一次timeout之后,WTDAT寄存器中的值才会被真正的装载进WTCNT寄存器中。注2:t_watchdog可根据公式对其进行计算:t_watchdog=1/(PCLK/(Prescalervalue+1)/Division_factor)PrescalerValue位于寄存器WTCON的8至15位,其值为0~255Division_factor由寄存器WTCON中的3~4位(ClockSelect)决定,其值可以为00,01,10,11分别代表Division_factor的值为16,32,64,128关于各个寄存器的详细信息请参考s3c2410的操作手册s3c2410NandFlashK9F1208U0A/K9F1208U0B的读取操作(编辑完毕)作者:蔡于清,下面我将对此型号的NandFlash读取操作做一个讲解。首先我们先从物理结构上来了解这颗芯片,结构图如下所示正如硬盘的盘片被分为磁道,每个磁道又被分为若干扇区,一块NandFlash被分为若干Block,每个Block又被分为若干Page。由上图我们可以知道flash中Byte(字节),Page(页),Block(块)3个单位之间的关系为:1Page=512BytesDataField+16BytesSpareField1Blcok=32Pages我们讨论的K9F1208U0B总共有4096个Blocks,故我们可以知道这块flash的容量为4096*(32*528)=69206016Bytes=66MB但事实上每个Page上的昀后16Bytes是用于存贮检验码用的,并不能存放实际的数据,所以实际上我们可以操作的芯片容量为4096*(32*512)=67108864Bytes=64MB由上图所示,1个Page总共由528Bytes组成,这528个字节按顺序由上而下以列为单位进行排列(1列代表一个Byte。第0行为第0Byte,第1行为第1Byte,以此类推,每个行又由8个位组成,每个位表示1个Byte里面的1bit)。这528Bytes按功能分为两大部分,分别是DataField和SpareField,其中SpareField占528Bytes里的16Bytes,这16Bytes是用于在读写操作的时候存放校验码用的,一般不用做普通数据的存储区,除去这16Bytes,剩下的512Bytes便是我们用于存放数据用的DataField,所以一个Page上虽然有528个Bytes,但我们只按512Bytes进行容量的计算。DataField按位置关系又可分为两个部分,分别称为1sthalf与2ndhalf,每个half各占256个bytes。或许你会感到纳闷,为什么要把DataField分为两个部分?把他们看做一个整体进行操作不就好了吗?呵呵,凡事都有因果,这么分块自然有它的道理所在,但现在还不是告诉你答案的时候。我们还是先讨论一下它的操作吧。对K9F1208U0B的操作是通过向NandFlash命令寄存器(对于s3c2410来说此寄存器为NFCMD,内存映射地址为0x4e000004)发送命令队列进行的,为什么说是命令队列?就是因为要完成某个操作的时候发送的不是一条命令,而是连续几条命令或是一条命令加几个参数下面是K9F1208U0B的操作命令集:读命令有两个,分别是Read1,Read2其中Read1用于读取DataField的数据,而Read2则是用于读取SpareField的数据。对于NandFlash来说,读操作的昀小操作单位为Page,也就是说当我们给定了读取的起始位置后,读操作将从该位置开始,连续读取到本Page的昀后一个Byte为止(可以包括SpareField)NandFlash的寻址NandFlash的地址寄存器把一个完整的NandFlash地址分解成ColumnAddress与PageAddress.进行寻址ColumnAddress:列地址。ColumnAddress其实就是指定Page上的某个Byte,指定这个Byte其实也就是指定此页的读写起始地址。PaageAddress:页地址。由于页地址总是以512Bytes对齐的,所以它的低9位总是0。确定读写操作是在Flash上的哪个页进行的。Read1命令当我们得到一个NandFlash地址src_addr时我们可以这样分解出ColumnAddress和PageAddresscolumn_addr=src_addr%512;//columnaddresspage_address=(src_addr9);//pageaddress也可以这么认为,一个NandFlash地址的A0~A7是它的column_addr,A9~A25是它的PageAddress。(注意地址位A8并没有出现,也就是A8被忽略,在下面你将了解到这是什么原因)Read1命令的操作分为4个Cycle,发送完读命令00h或01h(00h与01h的区别请见下文描述)之后将分4个Cycle发送参数,1st.Cyc