1. 程式人生 > >ARMulator下定時器中斷測試程式

ARMulator下定時器中斷測試程式

/****************************************************************************************/
/*  NAME:   test.c                                                                      */
/*  DESC:   test doby through I/O Port with timer interrupt(1s).                        */
/*  Date:   06.18.2008                                                                  */
/*  version:    0.0                                                                     */
/*  Program:    Shen Hui (Shh)                                                          */
/****************************************************************************************/
/*  程式主要演示怎樣使用armulator的定時器中斷.輸入也可以不在程式中賦值,直接在記憶體中改  */
/*  關鍵的地方在:                                                                       */
/*  1>.要開啟中斷.                                                                      */
/*  2>.要更改IRQ的服務程式.                                                             */
/*  3>.'服務程式'必須離'向量'在32MB範圍內.即25位地址.                                   */
/*  4>.無中斷向量初始化程式(無.s檔案),只設置了IRQ.                                      */
/*  5>.目標CPU必須與偵錯程式一致(例如,同是arm920T).                                       */
/*  6>.MMU/PU initialization Pagetab必須設定為NO_PAGERABLES,否則對映不對                */
/****************************************************************************************/
/*Input:                                                                                */
/*  0805ff01: D0-start  h active                                                        */
/*  0805ff02: D0-stop   l active                                                        */
/*Output:                                                                               */
/*  0805ff0d: D0-doby1  l active            0805ff0e:   D0-doby1    l active            */
/*            D1-doby1  l active                        D1-doby1    l active            */
/*            D2-doby1  l active                        D2-doby1    l active            */
/*            D3-doby1  l active                        D3-doby1    l active            */
/*            D4-doby1  l active                        D4-doby1    l active            */
/*            D5-doby1  l active                        D5-doby1    l active            */
/*            D6-doby1  l active                        D6-doby1    l active            */
/*            D7-doby1  l active                        D7-doby1    l active            */
/****************************************************************************************/ 
#include "test.h" 
void itoa2(unsigned short n, unsigned char *str)
{//not find itoa in stdlib.h
    int i=0;
    int swap;
    do
    {
        str[i]=n%2+'0';
        i++;
    
    }while(n/=2);
    str[i--]='/0';
    for(n=0; n<i; n++, i--)
    {
        swap=str[n];
        str[n]=str[i];
        str[i]=swap;
    }
}
void __irq IRQ_Handler(void)
{
  unsigned status;
  status = IRQStatus;
  /* 處理中斷源 */
  if (status & IRQTimer1)
  {
    Timer1Clear = 0; /* 清除中斷 */
    IntCT1++;        /* 置標記   */
  } 
}
/* ************************************************** */
/* 更新'向量'的內容使他包含一個轉移到'服務程式'的指令 */
/* 函式返回原'向量'值.                                */
/* 注意: '服務程式'必須離'向量'在32MB範圍內.          */
/* ************************************************** */
unsigned Install_Handler (unsigned routine, unsigned *vector)
{ 
    unsigned vec, oldvec;
    vec = ((routine - (unsigned)vector - 0x8)>>2);
    if (vec & 0xff000000)
    {
        printf ("Installation of Handler failed");
        exit(1);
    }
    vec = 0xea000000 | vec;//EA=
    oldvec = *vector;
    *vector = vec;
    return (oldvec);
}
/* ************************************************** */
/* 開啟或關閉中斷                                     */
/* 通過讀 cpsr 標記然後更新第7位來開啟或關閉中斷      */
/* 這些函式只能用於 privileged 模式,因為cpsr和spsr的  */
/* 控制位在使用者模式下不能改變.                        */
/* ************************************************** */
__inline void enable_IRQ(void)
{
    int tmp;
    __asm
    {
        MRS tmp, CPSR
        BIC tmp, tmp, #0x80
        MSR CPSR_c, tmp
    }
}
//
__inline void disable_IRQ(void)
{
    int tmp;
    __asm
    {
        MRS tmp, CPSR
        ORR tmp, tmp, #0x80
        MSR CPSR_c, tmp
    }
}
// 如果目標為920T則要清除所有中斷捕獲!
int main(void)
{
    unsigned short  Mask=1;
    unsigned char *str;
    
    DOBYINPUT0_7=0xff;
    DOBYINPUT8_F=0xff;
    
//  itoa2(0x1234,str );
//  printf("str %s/n",str);
    
    printf("Timer Interrupt/n");
    
//未安裝前   00000018       [0xe7ff0010]   dci      0xe7ff0010 ; ? undefined
//使地址(IRQ)00000018處為:  [0xea002022]  * b  IRQ_Handler
    Install_Handler ((unsigned)IRQ_Handler, irqvec);
    
    printf("Normal (RAM at 0x8000, semihosting) version/n/n");
    printf("Initializing.../n");
//
    enable_IRQ();
    IRQEnableClear = ~0;      // 清除所有的中斷
    
    Timer1Control = 0;        // 通過控制位關閉計數器
    Timer1Clear = 0 ;         // 通過寫任何值到'清除'清除暫存器來清除中斷
    Timer1Load = 2000;        // 裝計數器值,可通過晶頻計算,這裡2000只是為了測試 
    Timer1Control = (TimerEnable | TimerPeriodic | TimerPrescale8 );     
    IRQEnableSet = IRQTimer1; 
    printf("Running.../n");
    IntCT1 = 0;          // 清 CT1 標記
     
    while (START)
    {
        if(STOP) break;
        if (IntCT1 != 0)        // 定時器1產生中斷
        {
            IntCT1 = 0;         // 復位定時器1中斷標記
            DOBYOUTPUT0_7 = (~Mask) & 0xFF;
            DOBYOUTPUT8_F =((~Mask) & 0xFF00)>>8;
            itoa2(Mask,str);
            printf("%016s/n",str);
            Mask<<=1;
            if(Mask==0) Mask=1;
        }
    }
    printf("Ended/n");
    disable_IRQ();
}