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