1 /*
2  *  Blackfin Timer Driven Profiling Example
3  *
4  *  Copyright (C) 2003
5  *  by Green Hills Software Inc.
6  *
7  *  This program is the property of Green Hills Software, Inc,
8  *  its contents are proprietary information and no part of it
9  *  is to be disclosed to anyone except employees of Green Hills
10  *  Software, Inc., or as agreed in writing signed by the President
11  *  of Green Hills Software, Inc.
12  */
13 
14 #include <cdefBF533.h>
15 
16 /* These defines are missing from some Analog header files */
17 #ifndef PLL_CTL
18 #define PLL_CTL (0xffc00000)
19 #endif
20 #ifndef PLL_DIV
21 #define PLL_DIV (0xffc00004)
22 #endif
23 #ifndef pPLL_CTL
24 #define pPLL_CTL ((volatile unsigned short *)PLL_CTL)
25 #endif
26 #ifndef pPLL_DIV
27 #define pPLL_DIV ((volatile unsigned short *)PLL_DIV)
28 #endif
29 
30 /* This should be set to CLKIN - assume 27MHz, which is what the
31    ADSP-BF533 EZ-KIT Lite has. */
32 #define INPUT_CLOCK (27000000)
33 
34 /* Number of cycles between each counter decrement */
35 #define TICK_RATE (16)
36 
37 /* Return the number of times the count register is decremented per
38    second. On Blackfin, calculate by reading PLL_CTL and having CLKIN
39    defined above. This is implemented as described in Chapter 8 of the
40    ADSP-BF533 Blackfin Processor Specification. Note that other Blackfin
41    processors may differ slightly. */
TICKS_PER_SEC(void)42 int TICKS_PER_SEC(void) {
43     short pll_ctl = *pPLL_CTL;
44     int csel = ((*pPLL_DIV) >> 4) & 3;
45     int clock = INPUT_CLOCK; /* Initialize clock to CLKIN */
46     int msel = (pll_ctl >> 9) & 0x3f;
47 
48     if (msel == 0)
49         /* MSEL of 0 has special meaning */
50         msel = 64;
51     clock *= msel;
52     /* Divide clock by DF */
53     clock >>= (pll_ctl & 1);
54     /* clock is now VCO, so shift by CSEL to get CCLK */
55     clock >>= csel;
56 
57     /* TICKS_PER_SEC is CCLK (clock) divided by TCOUNT + 1 */
58     return clock / TICK_RATE;
59 }
60 
61 /* Initialize the count and compare registers. */
TIMER_INIT(unsigned int compare)62 void TIMER_INIT(unsigned int compare)
63 {
64     /* Setup TCOUNT */
65     *pTCOUNT = compare;
66 }
67 
68 /* Enable the timer interrupt */
ENABLE_TIMER_INTERRUPT(void)69 void ENABLE_TIMER_INTERRUPT(void)
70 {
71     /* Set TMPWR to turn on power to the timer. */
72     *pTCNTL = 1;
73 
74     /* Setup the event vector */
75     *pEVT6 = (void *) __ghs_manprf_timer_handler;
76 
77     /* Enable the core timer interrupt */
78     *pIMASK |= (1 << 6);
79 
80     /* Decrement TCOUNT every TICK_RATE cycles */
81     *pTSCALE = TICK_RATE - 1;
82 
83     /* Ensure all those writes had time to take effect */
84     __CSYNC();
85 
86     /* Start the timer */
87     *pTCNTL = 3;
88 }
89 
90 /* Read the exception PC. */
GET_EPC(void)91 asm unsigned int GET_EPC(void)
92 {
93     /* move from reti */
94     r0 = reti;
95 }
96 
97 /* Clear the timer interrupt. */
CLEAR_TIMER_INTERRUPT(void)98 void CLEAR_TIMER_INTERRUPT(void)
99 {
100     /* Restart the timer, clear TINT */
101     *pTCNTL = 3;
102 
103     __CSYNC();
104 }
105