Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

# processor.c

    00001 /*! \file processor.c \brief AT91SAM7S Processor Initialization and Support. */
    00002 //*****************************************************************************
    00003 //
    00004 // File Name    : 'processor.c'
    00005 // Title        : AT91SAM7S Processor Initialization and Support
    00006 // Author       : Pascal Stang - Copyright (C) 2006
    00007 // Created      : 2006.01.30
    00008 // Revised      : 2006.02.20
    00009 // Version      : 0.1
    00010 // Target MCU   : ARM processors
    00011 // Editor Tabs  : 4
    00012 //
    00013 // NOTE: This code is currently below version 1.0, and therefore is considered
    00014 // to be lacking in some functionality or documentation, or may not be fully
    00015 // tested.  Nonetheless, you can expect most functions to work.
    00016 //
    00017 //*****************************************************************************
    00018
    00019 // Include the processor definitions
    00020 #include "at91sam7s64.h"
    00021 // Include project-level definitions
    00022 #include "global.h"
    00023
    00024 #include "processor.h"
    00025
    00026 // The following functions must be writen in ARM mode this function called directly
    00027 // by exception vector
    00028 extern void AT91F_Spurious_handler(void);
    00029 extern void AT91F_Default_IRQ_handler(void);
    00030 extern void AT91F_Default_FIQ_handler(void);
    00031
    00032 // if you wish to change the interrupt priority for the system interrupt,
    00033 // DO NOT EDIT THE LINE BELOW.  Add your desired definition for
    00034 // xxx_INTERRUPT_LEVEL to your project's global.h and it will override
    00035 // this default definition.
    00036 #ifndef SYS_INTERRUPT_LEVEL
    00037 #define SYS_INTERRUPT_LEVEL     AT91C_AIC_PRIOR_HIGHEST
    00038 #endif
    00039
    00040 typedef void (*voidFuncPtr)(void);
    00041 volatile static voidFuncPtr SysIntFunc[SYSPID_NUM];
    00042
    00043
    00044 // Low-level processor initialization and clock control
    00045 // ** requires valid stack setup
    00046 void processorInit( void)
    00047 {
    00048     // make pointer to PMC to reduce code size
    00049     //AT91PS_PMC pPMC = AT91C_BASE_PMC;
    00050
    00051     // Set Flash wait state to 1WS
    00052     // Single Cycle Access at Up to 30 MHz, or 40
    00053     AT91C_BASE_MC->MC_FMR = AT91C_MC_FWS_1FWS;
    00054
    00055     // Disable watchdog
    00056     AT91C_BASE_WDTC->WDTC_WDMR= AT91C_WDTC_WDDIS;
    00057
    00058     // Enable the Main Oscillator
    00059     // SCK = 1/32768 = 30.51 uSecond
    00060     // Start up time = 8 * 6 / SCK = 56 * 30.51 = 1.46484375 ms
    00061     AT91C_BASE_PMC->PMC_MOR = (( AT91C_CKGR_OSCOUNT & (0x06<<8) ) | AT91C_CKGR_MOSCEN );
    00062     // Wait the startup time
    00063     while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS));
    00064
    00065     // Set PLL and divider:
    00066     // - div by 5 Fin = 3.6864 =(18.432 / 5)
    00067     // - Mul 25+1: Fout =   95.8464 =(3.6864*26)
    00068     // for 96 MHz the erroe is 0.16%
    00069     // Field out NOT USED = 0
    00070     // PLLCOUNT pll startup time estimate at : 0.844 ms
    00071     // PLLCOUNT 28 = 0.000844 /(1/32768)
    00072     AT91C_BASE_PMC->PMC_PLLR =
    00073         ((AT91C_CKGR_DIV & (OSC_DIV)) |
    00074         (AT91C_CKGR_PLLCOUNT & (28<<8)) |
    00075         (AT91C_CKGR_MUL & ((PLL_MUL-1)<<16)));
    00076
    00077     // Wait for PLL to lock and for clock to become ready
    00078     while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK));
    00079     while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY));
    00080
    00081     // Set Processor Clock and Master Clock to PLL Clock/2
    00082     AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
    00083     while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY));
    00084
    00085     AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;
    00086     while(!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY));
    00087
    00088     // if 18.432MHz crystal, master clock now 47.9232MHz -> 48MHz for USB operation
    00089
    00090     // setup initial AIC config
    00091     processorAicInit();
    00092     // attach the system interrupt distributer
    00093     processorAicAttach(AT91C_ID_SYS, (SYS_INTERRUPT_LEVEL|AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL), processorSysIntService);
    00094 }
    00095
    00096 unsigned int processorDisableInt(unsigned int cpsr_mask)
    00097 {
    00098     unsigned int cpsr;
    00099     // read CPSR
    00100     asm volatile ("mrs  %0, cpsr" : "=r" (cpsr) : );
    00101     // set interrupt disable bit and write CPSR
    00102     asm volatile ("msr  cpsr, %0" : : "r" (cpsr|(cpsr_mask&CPSR_MASK_INT)) );
    00103     // return the original CPSR
    00104     return cpsr;
    00105 }
    00106
    00107 unsigned int processorEnableInt(unsigned int cpsr_mask)
    00108 {
    00109     unsigned int cpsr;
    00110     // read CPSR
    00111     asm volatile ("mrs  %0, cpsr" : "=r" (cpsr) : );
    00112     // clear interrupt disable bit(s) and write CPSR
    00113     asm volatile ("msr  cpsr, %0" : : "r" (cpsr&~(cpsr_mask&CPSR_MASK_INT)) );
    00114     // return the original CPSR
    00115     return cpsr;
    00116 }
    00117
    00118 unsigned int processorRestoreInt(unsigned int cpsr_orig)
    00119 {
    00120     unsigned int cpsr;
    00121     // read CPSR
    00122     asm volatile ("mrs  %0, cpsr" : "=r" (cpsr) : );
    00123     // clear interrupt disable bit(s) and write CPSR
    00124     asm volatile ("msr  cpsr, %0" : : "r" ( (cpsr&~CPSR_MASK_INT) | (cpsr_orig&CPSR_MASK_INT)) );
    00125     // return the original CPSR
    00126     return cpsr;
    00127 }
    00128
    00129 void processorAicInit(void)
    00130 {
    00131     int i;
    00132
    00133     // Set up the default interrupt handler vectors
    00134     AT91C_BASE_AIC->AIC_SVR[0] = (unsigned int)AT91F_Default_FIQ_handler;
    00135     for(i=1; i<31; i++)
    00136     {
    00137         AT91C_BASE_AIC->AIC_SVR[i] = (unsigned int)AT91F_Default_IRQ_handler;
    00138     }
    00139     AT91C_BASE_AIC->AIC_SPU  = (unsigned int)AT91F_Spurious_handler;
    00140 }
    00141
    00142 void processorAicAttach(int pid, int srcmode, void (*userFunc)(void) )
    00143 {
    00144     // first disable the interrupt at the AIC
    00145     AT91C_BASE_AIC->AIC_IDCR = (1<<pid);
    00146     // set a new interrupt handler routine pointer
    00147     AT91C_BASE_AIC->AIC_SVR[pid] = (unsigned int)userFunc;
    00148     // configure the interrupt
    00149     AT91C_BASE_AIC->AIC_SMR[pid] = srcmode;
    00150     // clear the interrupt flag in the AIC
    00151     AT91C_BASE_AIC->AIC_ICCR = (1<<pid);
    00152     // enable the interrupt at the AIC
    00153     AT91C_BASE_AIC->AIC_IECR = (1<<pid);
    00154 }
    00155
    00156 void processorAicDetach(int pid)
    00157 {
    00158     // first disable the interrupt at the AIC
    00159     AT91C_BASE_AIC->AIC_IDCR = (1<<pid);
    00160     // clear the interrupt flag in the AIC
    00161     AT91C_BASE_AIC->AIC_ICCR = (1<<pid);
    00162     // clear the interrupt handler routine pointer
    00163     AT91C_BASE_AIC->AIC_SVR[pid] = 0;
    00164 }
    00165
    00166 void processorAicAttachSys(int syspid, void (*userFunc)(void) )
    00167 {
    00168     // make sure the interrupt number is within bounds
    00169     if(syspid < SYSPID_NUM)
    00170     {
    00171         // set the interrupt service to run the supplied user function
    00172         SysIntFunc[syspid] = userFunc;
    00173     }
    00174 }
    00175
    00176 void processorSysIntService(void)
    00177 {
    00178     // service most likely SYSINT interrupt sources first.
    00179     // in each if(), we are careful to check only *enabled* interrupt sources!
    00180
    00181     // check if sysint caused by PITC (periodic interval timer)
    00182     if( (AT91C_BASE_PITC->PITC_PIMR & AT91C_PITC_PITIEN) &&
    00183         (AT91C_BASE_PITC->PITC_PISR & AT91C_PITC_PITS) )
    00184     {
    00185         if(SysIntFunc[SYSPID_PITC]) SysIntFunc[SYSPID_PITC]();
    00186         return;
    00187     }
    00188     // check if sysint caused by DBGU (debug uart)
    00189     if(AT91C_BASE_DBGU->DBGU_IMR & AT91C_BASE_DBGU->DBGU_CSR)
    00190     {
    00191         if(SysIntFunc[SYSPID_DBGU]) SysIntFunc[SYSPID_DBGU]();
    00192         return;
    00193     }
    00194     // check if sysint caused by RTT (real-time timer)
    00195     if( ((AT91C_BASE_RTTC->RTTC_RTMR>>16) & AT91C_BASE_RTTC->RTTC_RTSR) &
    00196             (AT91C_RTTC_RTTINC|AT91C_RTTC_ALMS) )
    00197     {
    00198         if(SysIntFunc[SYSPID_RTTC]) SysIntFunc[SYSPID_RTTC]();
    00199         return;
    00200     }
    00201     // check if sysint caused by EFC (embedded flash controller)
    00202     if( (AT91C_BASE_MC->MC_FMR & AT91C_BASE_MC->MC_FSR) &
    00203             (AT91C_MC_FRDY|AT91C_MC_LOCKE|AT91C_MC_PROGE) )
    00204     {
    00205         if(SysIntFunc[SYSPID_EFC]) SysIntFunc[SYSPID_EFC]();
    00206         return;
    00207     }
    00208     // check if sysint caused by PMC (power management controller)
    00209     if( AT91C_BASE_PMC->PMC_IER & AT91C_BASE_PMC->PMC_SR )
    00210     {
    00211         if(SysIntFunc[SYSPID_PMC]) SysIntFunc[SYSPID_PMC]();
    00212         return;
    00213     }
    00214
    00215     // could not determine source of interrupt
    00216     // throw error?
    00217 }
    00218