1 /*
2  * SPDX-FileCopyrightText: 2015-2019 Cadence Design Systems, Inc.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
7  */
8 
9 /*
10  * Copyright (c) 2015-2019 Cadence Design Systems, Inc.
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining
13  * a copy of this software and associated documentation files (the
14  * "Software"), to deal in the Software without restriction, including
15  * without limitation the rights to use, copy, modify, merge, publish,
16  * distribute, sublicense, and/or sell copies of the Software, and to
17  * permit persons to whom the Software is furnished to do so, subject to
18  * the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included
21  * in all copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30  */
31 
32 /*******************************************************************************
33 *
34 *       XTENSA INFORMATION FOR RTOS TICK TIMER AND CLOCK FREQUENCY
35 *
36 *  This header contains definitions and macros for use primarily by Xtensa
37 *  RTOS assembly coded source files. It includes and uses the Xtensa hardware
38 *  abstraction layer (HAL) to deal with config specifics. It may also be
39 *  included in C source files.
40 *
41 *  User may edit to modify timer selection and to specify clock frequency and
42 *  tick duration to match timer interrupt to the real-time tick duration.
43 *
44 *  If the RTOS has no timer interrupt, then there is no tick timer and the
45 *  clock frequency is irrelevant, so all of these macros are left undefined
46 *  and the Xtensa core configuration need not have a timer.
47 *
48 *******************************************************************************/
49 
50 #ifndef XTENSA_TIMER_H
51 #define XTENSA_TIMER_H
52 
53 #ifdef __ASSEMBLER__
54     #include    <xtensa/coreasm.h>
55 #endif
56 
57 #include    <xtensa/corebits.h>
58 #include    <xtensa/config/system.h>
59 
60 #include    "xtensa_rtos.h" /* in case this wasn't included directly */
61 
62 #include    "FreeRTOSConfig.h"
63 
64 /*
65  * Select timer to use for periodic tick, and determine its interrupt number
66  * and priority. User may specify a timer by defining XT_TIMER_INDEX with -D,
67  * in which case its validity is checked (it must exist in this core and must
68  * not be on a high priority interrupt - an error will be reported in invalid).
69  * Otherwise select the first low or medium priority interrupt timer available.
70  */
71 #if XCHAL_NUM_TIMERS == 0
72 
73     #error "This Xtensa configuration is unsupported, it has no timers."
74 
75 #else
76 
77     #ifndef XT_TIMER_INDEX
78         #if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
79             #if XCHAL_INT_LEVEL( XCHAL_TIMER3_INTERRUPT ) <= XCHAL_EXCM_LEVEL
80                 #undef  XT_TIMER_INDEX
81                 #define XT_TIMER_INDEX    3
82             #endif
83         #endif
84         #if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
85             #if XCHAL_INT_LEVEL( XCHAL_TIMER2_INTERRUPT ) <= XCHAL_EXCM_LEVEL
86                 #undef  XT_TIMER_INDEX
87                 #define XT_TIMER_INDEX    2
88             #endif
89         #endif
90         #if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
91             #if XCHAL_INT_LEVEL( XCHAL_TIMER1_INTERRUPT ) <= XCHAL_EXCM_LEVEL
92                 #undef  XT_TIMER_INDEX
93                 #define XT_TIMER_INDEX    1
94             #endif
95         #endif
96         #if XCHAL_TIMER0_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
97             #if XCHAL_INT_LEVEL( XCHAL_TIMER0_INTERRUPT ) <= XCHAL_EXCM_LEVEL
98                 #undef  XT_TIMER_INDEX
99                 #define XT_TIMER_INDEX    0
100             #endif
101         #endif
102     #endif /* ifndef XT_TIMER_INDEX */
103     #ifndef XT_TIMER_INDEX
104         #error "There is no suitable timer in this Xtensa configuration."
105     #endif
106 
107     #define XT_CCOMPARE        ( CCOMPARE + XT_TIMER_INDEX )
108     #define XT_TIMER_INTNUM    XCHAL_TIMER_INTERRUPT( XT_TIMER_INDEX )
109     #define XT_TIMER_INTPRI    XCHAL_INT_LEVEL( XT_TIMER_INTNUM )
110     #define XT_TIMER_INTEN     ( 1 << XT_TIMER_INTNUM )
111 
112     #if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED
113         #error "The timer selected by XT_TIMER_INDEX does not exist in this core."
114     #elif XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL
115         #error "The timer interrupt cannot be high priority (use medium or low)."
116     #endif
117 
118 #endif /* XCHAL_NUM_TIMERS */
119 
120 /*
121  * Set processor clock frequency, used to determine clock divisor for timer tick.
122  * User should BE SURE TO ADJUST THIS for the Xtensa platform being used.
123  * If using a supported board via the board-independent API defined in xtbsp.h,
124  * this may be left undefined and frequency and tick divisor will be computed
125  * and cached during run-time initialization.
126  *
127  * NOTE ON SIMULATOR:
128  * Under the Xtensa instruction set simulator, the frequency can only be estimated
129  * because it depends on the speed of the host and the version of the simulator.
130  * Also because it runs much slower than hardware, it is not possible to achieve
131  * real-time performance for most applications under the simulator. A frequency
132  * too low does not allow enough time between timer interrupts, starving threads.
133  * To obtain a more convenient but non-real-time tick duration on the simulator,
134  * compile with xt-xcc option "-DXT_SIMULATOR".
135  * Adjust this frequency to taste (it's not real-time anyway!).
136  */
137 #if defined( XT_SIMULATOR ) && !defined( XT_CLOCK_FREQ )
138     #define XT_CLOCK_FREQ    configCPU_CLOCK_HZ
139 #endif
140 
141 #if !defined( XT_CLOCK_FREQ ) && !defined( XT_BOARD )
142     #error "XT_CLOCK_FREQ must be defined for the target platform."
143 #endif
144 
145 /*
146  * Default number of timer "ticks" per second (default 100 for 10ms tick).
147  * RTOS may define this in its own way (if applicable) in xtensa_rtos.h.
148  * User may redefine this to an optimal value for the application, either by
149  * editing this here or in xtensa_rtos.h, or compiling with xt-xcc option
150  * "-DXT_TICK_PER_SEC=<value>" where <value> is a suitable number.
151  */
152 #ifndef XT_TICK_PER_SEC
153     #define XT_TICK_PER_SEC    configTICK_RATE_HZ    /* 10 ms tick = 100 ticks per second */
154 #endif
155 
156 /*
157  * Derivation of clock divisor for timer tick and interrupt (one per tick).
158  */
159 #ifdef XT_CLOCK_FREQ
160     #define XT_TICK_DIVISOR    ( XT_CLOCK_FREQ / XT_TICK_PER_SEC )
161 #endif
162 
163 #ifndef __ASSEMBLER__
164     extern unsigned _xt_tick_divisor;
165     extern void _xt_tick_divisor_init( void );
166 #endif
167 
168 #endif /* XTENSA_TIMER_H */
169