新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM開發步步深入之定時加速

        ARM開發步步深入之定時加速

        作者: 時間:2016-12-06 來源:網絡 收藏

          實驗目的:通過使用MPLL提高系統時鐘,啟動定時器產生中斷來點亮LED燈,啟動Watchdog定時器,如果程序跑飛,借助Watchdog重新運行程序,借此掌握的時鐘管理、PWM及看門狗定時器。

        本文引用地址:http://www.104case.com/article/201612/341185.htm

          實驗環境及說明:恒頤開發板H2410。

          實 驗思路:開發板上電啟動后,自動將NandFlash開始的4K數據復制到SRAM中,然后跳轉到0地址開始執行。然后來設置MPLL來改變FCLK、 HCLK、PCLK的值,初始化存儲控制器來使用SDRAM。初始化LED燈管腳、定時中斷控制器和看門狗,使能定時中斷控制器和看門狗。之后進入 main函數死循環等待中斷的發生,每隔設定的時間觸發定時中斷,調用定時中斷處理函數點亮/熄滅LED燈。若程序跑飛,觸發看門狗重啟。

          知識掌握:系統時鐘、PWM定時器和Watchdog定時器

          一、系統時鐘:的時鐘控制邏輯為整個芯片提供了三種時鐘。

          ★FCLK 用于CPU核;HCLK用于AHB總線上設備---CPU核、存儲器控制器、中斷控制器、LCD控制器、DMA和USB主機模塊;PCLK用于APB總線 上設備---Watchdog、IIS、I2C、PWM定時器、MMC接口、ADC、UART、GPIO、RTC和SPI。

          ★AHB(Advanced High performance Bus)---主要用于高性能模塊間的連接;APB(Advanced Peripheral Bus)---主要用于低帶寬的周邊外設之間的連接。

          ★ 開發板時鐘頻率為12MHz,主要是為了降低電磁干擾和板間布線要求,需要通過PLL提高系統時鐘。S3C2410包括MPLL(用于FCLK、 HCLK、PLCK)和UPLL(用于USB設備),他們的設置方法類似。開發板上電→FCLK=Fin(外部輸入時鐘)→設置MPLL相關寄存器→等待 (Lock Time:長短由寄存器LOCKTIME設定)→MPLL輸出穩定,CPU工作在新的時鐘FCLK下。

          ★設置MPLL需要設置下面幾個重要寄存器:

          ●LOCKTIME寄存器(LOCK TIME COUNT)用于設置lock time的長度,初始值0x00FFFFFF。

          ●MPLLCON(Main PLL Control)寄存器用于設置FCLK與Fin的倍數,初始值0x0005C080。

          ●CLKDIVN(CLOCK DIVIDER CONTROL)寄存器用于設置FCLK、HCLK、PCLK三者的比例。

          二、PWM(pulse width modulation)定時器

          ★S3C2410共有5個16位的定時器,其中定時器0、1、2、3有PWM功能,因為它們都有一個輸出引腳,可以通過定時器來控制引腳周期性的高、低電平變化;定時器4木有輸出引腳就不有PWM功能了。

          ★PLCK 是定時部件的時鐘源,先通過2個8位預分頻器(定時器0、1共用第一個定時器,2、3、4共用第二個),輸出進入第二級分頻(輸出2/4/8/16分頻或 者外部時鐘TCLK0/TCLK1)。這兩次預分頻都是通過設置TCFG0寄存器完成的。每個定時器工作在哪種頻率下可以通過TCFG1寄存器來選擇的。

          ★定時器的使用主要涉及以下寄存器:

          ●TCFG0寄存器:位[7:0],位[15:8]分別用于控制預分頻器0,1;它們的值為0~255。經過分頻器出來的時鐘頻率:PLCK/(TCFG0[7:0]+1或TCFG0[15:8]+1)。

          '700')this.width='700';if(this.offsetHeight>'700')this.height='700';" src="http://www.arm79.com/attachment/Mon_1005/94_67_154d167be4af4a1.jpg" onclick="if(this.width>=700) window.open('http://www.arm79.com/attachment/Mon_1005/94_67_154d167be4af4a1.jpg');" border="0" width="700">

          ●TCFG1寄存器:設定相應定時器為經過分頻器出來的時鐘頻率的幾分頻。定時器工作頻率= PLCK/(TCFG0[7:0]或TCFG0[15:8]+1)/幾分頻。

          ●TCNTBn/TCMPBn寄存器:這兩個寄存器都只用到位[15:0]。TCNTBn中保存定時器的初始計數值,TCMPBn中保存比較值。它們的在啟動定時器時,被傳到定時器內部寄存器TCNTn,TCMPn中。

          ●TCNTOn寄存器:n為0~4,內部寄存器TCNTn在其工作時鐘下不斷減1計數,可以通過讀取TCNTOn寄存器得知其值。

          ●TCON寄存器:它的功能如下:第一次啟動定時器時,手動將TCNTBn/TCMPBn寄存器的值裝入內部寄存器TCNTn,TCMPn中;啟動,停止定時器;決定在定時器計數到達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,改變FCLK、HCLK、PCLK

          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

          /* 如果HDIVN非0,CPU的總線模式應該從"fast bus mode"變為"asynchronous bus mode"*/

          __asm__(

          "mrc p15, 0, r1, c1, c0, 0n" /* 讀出控制寄存器 */

          "orr r1, r1, #0xc0000000n" /* 設置為"asynchronous bus mode" */

          "mcr p15, 0, r1, c1, c0, 0n" /* 寫入控制寄存器 */

          );

          MPLLCON = S3C2410_MPLL_200MHZ; /* FCLK=200MHz,HCLK=100MHz,PCLK=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;

          //每次中斷令4個LED改變狀態

          if(INTOFFSET == 10)

          GPFDAT = ~(GPFDAT & (0xf << 4));

          //清中斷

          SRCPND = 1 << INTOFFSET;

          INTPND = INTPND;

          }



        關鍵詞: ARM S3C2410

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 景东| 广安市| 临清市| 中卫市| 额敏县| 宣恩县| 海阳市| 墨脱县| 建德市| 舞阳县| 延边| 盐山县| 海阳市| 靖安县| 分宜县| 平舆县| 普宁市| 汝州市| 华蓥市| 淮北市| 呼伦贝尔市| 治多县| 开远市| 甘孜县| 确山县| 东丽区| 剑阁县| 聊城市| 洛浦县| 兰考县| 酒泉市| 宜黄县| 西和县| 林州市| 德阳市| 昌江| 寿阳县| 宜丰县| 社旗县| 新化县| 日土县|