zoukankan      html  css  js  c++  java
  • ARM开发步步深入之定时加速

    实验目的:通过使用MPLL提高系统时钟,启动定时器产生中断来点亮LED灯,启动Watchdog定时器,如果程序跑飞,借助Watchdog重新运行程序,借此掌握S3C2410的时钟管理、PWM及看门狗定时器。

    实验环境及说明:恒颐S3C2410开发板H2410

    实验思路:开发板上电启动后,自动将NandFlash开始的4K数据复制到SRAM中,然后跳转到0地址开始执行。然后来设置MPLL来改变FCLKHCLKPCLK的值,初始化存储控制器来使用SDRAM。初始化LED灯管脚、定时中断控制器和看门狗,使能定时中断控制器和看门狗。之后进入main函数死循环等待中断的发生,每隔设定的时间触发定时中断,调用定时中断处理函数点亮/熄灭LED灯。若程序跑飞,触发看门狗重启。

    知识掌握:系统时钟、PWM定时器和Watchdog定时器
    一、系统时钟:S3C2410的时钟控制逻辑为整个芯片提供了三种时钟。
    FCLK用于CPU核;HCLK用于AHB总线上设备---CPU核、存储器控制器、中断控制器、LCD控制器、DMAUSB主机模块;PCLK用于APB总线上设备---WatchdogIISI2CPWM定时器、MMC接口、ADCUARTGPIORTCSPI
    AHB(Advanced High performance Bus)---主要用于高性能模块间的连接;APB(Advanced Peripheral Bus)---主要用于低带宽的周边外设之间的连接。
    开发板时钟频率为12MHz,主要是为了降低电磁干扰和板间布线要求,需要通过PLL提高系统时钟。S3C2410包括MPLL(用于FCLKHCLKPLCK)UPLL(用于USB设备),他们的设置方法类似。开发板上电→FCLK=Fin(外部输入时钟)→设置MPLL相关寄存器等待(Lock Time:长短由寄存器LOCKTIME设定)→MPLL输出稳定,CPU工作在新的时钟FCLK下。


    设置MPLL需要设置下面几个重要寄存器:
    ●LOCKTIME
    寄存器(LOCK TIME COUNT)用于设置lock time的长度,初始值0x00FFFFFF
    ●MPLLCON(Main PLL Control)
    寄存器用于设置FCLKFin的倍数,初始值0x0005C080
    ●CLKDIVN(CLOCK DIVIDER CONTROL)
    寄存器用于设置FCLKHCLKPCLK三者的比例。
    二、PWM(pulse width modulation)定时器
    S3C2410共有516位的定时器,其中定时器0123PWM功能,因为它们都有一个输出引脚,可以通过定时器来控制引脚周期性的高、低电平变化;定时器4木有输出引脚就不有PWM功能了。
    PLCK是定时部件的时钟源,先通过28位预分频器(定时器01共用第一个定时器,234共用第二个),输出进入第二级分频(输出2/4/8/16分频或者外部时钟TCLK0/TCLK1)。这两次预分频都是通过设置TCFG0寄存器完成的。每个定时器工作在哪种频率下可以通过TCFG1寄存器来选择的。
    定时器的使用主要涉及以下寄存器:
    ●TCFG0
    寄存器:位[7:0],位[15:8]分别用于控制预分频器01;它们的值为0~255。经过分频器出来的时钟频率:PLCK/(TCFG0[7:0]+1TCFG0[15:8]+1)


    ●TCFG1
    寄存器:设定相应定时器为经过分频器出来的时钟频率的几分频。定时器工作频率= PLCK/(TCFG0[70]TCFG0[158]+1)/几分频。


    ●TCNTBn/TCMPBn
    寄存器:这两个寄存器都只用到位[15:0]TCNTBn中保存定时器的初始计数值,TCMPBn中保存比较值。它们的在启动定时器时,被传到定时器内部寄存器TCNTnTCMPn中。
    ●TCNTOn
    寄存器:n0~4,内部寄存器TCNTn在其工作时钟下不断减1计数,可以通过读取TCNTOn寄存器得知其值。
    ●TCON
    寄存器:它的功能如下:第一次启动定时器时,手动将TCNTBn/TCMPBn寄存器的值装入内部寄存器TCNTnTCMPn中;启动,停止定时器;决定在定时器计数到达0时是否自动装入初值;决定定时器的管脚TOUTn的输出电平是否反转。


    三、Watchdog定时器:其使用和PWM定时器很类此。
    PLCK先经过8位预分频器后再被分成4种频率(16/32/64/128分频)。使用看门狗定时器的一个最主要目的当然是让它给你看门了。程序正常执行时,必须不断重新设置WTCNT寄存器使其不为0,这样可以保证系统不被重启,称为喂狗;程序崩溃时不能按时喂狗,则计数值到达0后系统重启,使得程序可以重新正常运行。
    Watchdog存在的意义:开启Watchdog之后程序必须定时向其反馈信息,这看似麻烦又耗资源,其实是很重要的行为,是程序向硬件传递自身运行状态的一种方法。如果程序运行良好则它应该可以在规定的时间间隔内向Watchdog反馈信息,借此来说明程序运行正常;若程序由于某个不当的操作而进入死循环等,则无法向Watchdog反馈信息,Watchdog将发生记时超时,从而引起硬件重起。如果没有Watchdog,程序死掉就死掉了,只能等待用户自己发现去吧。
    相关寄存器:
    ●WTCON
    寄存器:用于设置预分频系数,选择工作频率,决定是否使能中断,是否启用WATDOG功能等。


    ●WTDAT
    寄存器:用以决定Watchdog定时器的超时周期,值自动写入WTCNT
    ●WTCNT
    寄存器:在启动WATDOG定时器前,必须往这个寄存器写入初始计数值,启动定时器后,它做减1操作,当计数器值达到0时,如果中断被使能的话,就发出中断,如果Watchdog功能被使能的话就发出复位信号,装载WTDAT寄存器的值并重新计数。

    关键代码解析:
    head.S头文件来初始化,设置中断模式、系统模式的栈,设置好中断处理函数
    .text
    .global _start
    _start:
    @
    中断向量表处理函数,只给出复位和普通中断模式的处理函数,其它异常未使用
        b   Reset
    ......
    @0x18:
    中断模式的向量地址
        b   HandleIRQ
    @0x1c:
    快中断模式的向量地址
    HandleFIQ:
        b   HandleFIQ

    Reset:                                                             @
    复位处理
        bl disable_watch_dog                             @
    关门喂狗
        ldr sp,=0x4096                                          @clock
    初始化栈地址
        bl clock_init                                                 @
    设置MPLL,改变FCLKHCLKPCLK
        bl mem_control_setup                             @
    设置存储控制器以使用SDRAM
        bl copy_steppingstone_to_sdram         @
    复制代码到SDRAM
        ldr pc, =on_sdram                                     @
    跳到SDRAM中继续执行
    on_sdram:
        msr cpsr_c, #0xd2             @
    进入中断模式
        ldr sp, =0x32000000         @
    设置中断模式栈指针
        msr cpsr_c, #0xdf              @
    进入系统模式
        ldr sp, =0x34000000         @
    设置系统模式栈指针
        bl init_led                             @
    初始化LED
        bl init_timer0                       @
    初始化定时器0
        bl enable_timer0                @
    使能定时器0
        bl init_watchdog                 @
    初始化Watchdog
        bl enable_watchdog          @
    使能Watchdog
        msr cpsr_c, #0x5f               @
    设置I-bit=0,开IRQ中断
        ldr lr, =halt_loop                  @
    设置返回地址
        ldr pc, =main                       @
    调用main函数
    halt_loop:
        b   halt_loop

    init.c文件实现时钟、GPIO、中断及定时的初始化,主要代码:
    /*
    *
    时钟初始化
    */
    #define S3C2410_MPLL_200MHZ     ((0x5c<<12)|(0x04<<4)|(0x00))

    void init_clock(void)
    {
        CLKDIVN  = 0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1

    /*
    如果HDIVN0CPU的总线模式应该从"fast bus mode"变为"asynchronous bus mode"*/
    __asm__(
        "mrc    p15, 0, r1, c1, c0, 0\n"        /*
    读出控制寄存器 */
        "orr    r1, r1, #0xc0000000\n"          /*
    设置为"asynchronous bus mode" */
        "mcr    p15, 0, r1, c1, c0, 0\n"        /*
    写入控制寄存器 */
        );
        MPLLCON = S3C2410_MPLL_200MHZ;  /* FCLK=200MHz
    HCLK=100MHzPCLK=50MHz */
    }
    /*
    *
    定时器0初始化
    */
    void init_timer0(void)
    {
        TCFG0  = 99;        //
    预分频器0 = 99
        TCFG1  = 0x03;      //
    选择16分频
        TCNTB0 = 31250;     // 0.5
    秒钟触发一次中断
        TCON   |= (1<<1);   //
    手动更新
        TCON   = 0x09;      //
    自动加载,清手动更新位,启动定时器0
    }
    /*
    *
    定时器0中断使能
    */
    void enable_timer0(void)
    {
        INTMSK   &= (~(1<<10));  //
    定时器0中断使能
    }
    /*
    * Watchdog
    初始化
    */
    void init_watchdog(void)
    {
        //Prescaler Value = 99
    Division_factor = 16(Clock Select=16)Interrupt Generation = 0(不产生中断)Reset = 1(开启Reset Signal)
        WTCON = 0x6381;
        //
    设置寄存器WTDAT的值为0x8000,时间一定要大于Timer0的时间
        WTDAT = 0x8000;
    }
    /*
    * Watchdog
    使能
    */
    void enable_watchdog(void)
    {
        WTCON|=1<<5;
    }

    interrupt.c文件实现中断的处理,主要代码:
    /*
    *
    定时器0中断处理函数
    */
    void Timer0_Handle(void)
    {
        //
    喂狗
        WTCNT=0x8000;
        //
    每次中断令4LED改变状态
        if(INTOFFSET == 10)
            GPFDAT = ~(GPFDAT & (0xf << 4));
        //
    清中断
        SRCPND = 1 << INTOFFSET;
        INTPND = INTPND;
    }

  • 相关阅读:
    关于read函数的一些分析
    条件变量
    epoll的边缘触发与水平触发
    内核态的接收缓冲区和发送缓冲区
    SourceTreet提交时显示remote: Incorrect username or password ( access token )(4种解决办法)
    前端技术汇总+Vue最新快速上手
    MyBatisPlus性能分析插件,条件构造器,代码自动生成器详解
    博客园怎样在Markdown编辑模式下调整图片大小(已解决)
    MyBatisPlus分页查询,删除操作
    idea括号选中时出现一条下滑线(突出显示)打开或关闭方法
  • 原文地址:https://www.cnblogs.com/ljf181275034/p/2184529.html
Copyright © 2011-2022 走看看