]> begriffs open source - cmsis/blob - CMSIS/RTOS2/Source/os_tick_gtim.c
RTX5: Moved SVC/PendSV handler priority setup from osKernelInitialize to osKernelStart
[cmsis] / CMSIS / RTOS2 / Source / os_tick_gtim.c
1 /**************************************************************************//**
2  * @file     os_tick_gtim.c
3  * @brief    CMSIS OS Tick implementation for Private Timer
4  * @version  V1.0.0
5  * @date     21. July 2017
6  ******************************************************************************/
7 /*
8  * Copyright (c) 2017 ARM Limited. All rights reserved.
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  *
12  * Licensed under the Apache License, Version 2.0 (the License); you may
13  * not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  * www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
20  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  */
24
25 #include "os_tick.h"
26 #include "irq_ctrl.h"
27
28 #include "RTE_Components.h"
29 #include CMSIS_device_header
30
31 #ifndef GTIM_IRQ_PRIORITY
32 #define GTIM_IRQ_PRIORITY           0xFFU
33 #endif
34
35 #ifndef GTIM_IRQ_NUM
36 #define GTIM_IRQ_NUM                SecurePhyTimer_IRQn
37 #endif
38
39 // Timer interrupt pending flag
40 static uint8_t GTIM_PendIRQ;
41
42 // Timer tick frequency
43 static uint32_t GTIM_Clock;
44
45 // Timer load value
46 static uint32_t GTIM_Load;
47
48 // Setup OS Tick.
49 int32_t  OS_Tick_Setup (uint32_t freq, IRQHandler_t handler) {
50   uint32_t prio, bits;
51
52   if (freq == 0U) {
53     return (-1);
54   }
55
56   GTIM_PendIRQ = 0U;
57
58   // Get timer clock
59 #ifdef SCTR_BASE
60   GTIM_Clock = *(uint32_t*)(SCTR_BASE+0x20);
61 #else
62   // FVP REFCLK CNTControl 100MHz
63   GTIM_Clock = 100000000UL;
64 #endif
65
66   PL1_SetCounterFrequency(GTIM_Clock);
67
68   // Calculate load value
69   GTIM_Load = (GTIM_Clock / freq) - 1U;
70
71   // Disable Generic Timer and set load value
72   PL1_SetControl(0U);
73   PL1_SetLoadValue(GTIM_Load);
74
75   // Disable corresponding IRQ
76   IRQ_Disable(GTIM_IRQ_NUM);
77   IRQ_ClearPending(GTIM_IRQ_NUM);
78
79   // Determine number of implemented priority bits
80   IRQ_SetPriority(GTIM_IRQ_NUM, 0xFFU);
81
82   prio = IRQ_GetPriority(GTIM_IRQ_NUM);
83
84   // At least bits [7:4] must be implemented
85   if ((prio & 0xF0U) == 0U) {
86     return (-1);
87   }
88
89   for (bits = 0; bits < 4; bits++) {
90     if ((prio & 0x01) != 0) {
91       break;
92     }
93     prio >>= 1;
94   }
95   
96   // Adjust configured priority to the number of implemented priority bits
97   prio = (GTIM_IRQ_PRIORITY << bits) & 0xFFUL;
98
99   // Set Private Timer interrupt priority
100   IRQ_SetPriority(GTIM_IRQ_NUM, prio-1U);
101
102   // Set edge-triggered IRQ
103   IRQ_SetMode(GTIM_IRQ_NUM, IRQ_MODE_TRIG_EDGE);
104
105   // Register tick interrupt handler function
106   IRQ_SetHandler(GTIM_IRQ_NUM, handler);
107
108   // Enable corresponding interrupt
109   IRQ_Enable(GTIM_IRQ_NUM);
110
111   // Enable system counter and timer control
112 #ifdef SCTR_BASE
113   *(uint32_t*)SCTR_BASE |= 3U;
114 #endif
115
116   // Enable timer control
117   PL1_SetControl(1U);
118
119   return (0);
120 }
121
122 /// Enable OS Tick.
123 int32_t  OS_Tick_Enable (void) {
124   uint32_t ctrl;
125
126   // Set pending interrupt if flag set
127   if (GTIM_PendIRQ != 0U) {
128     GTIM_PendIRQ = 0U;
129     IRQ_SetPending (GTIM_IRQ_NUM);
130   }
131
132   // Start the Private Timer
133   ctrl = PL1_GetControl();
134   // Set bit: Timer enable
135   ctrl |= 1U;
136   PL1_SetControl(ctrl);
137
138   return (0);
139 }
140
141 /// Disable OS Tick.
142 int32_t  OS_Tick_Disable (void) {
143   uint32_t ctrl;
144   
145   // Stop the Private Timer
146   ctrl = PL1_GetControl();
147   // Clear bit: Timer enable
148   ctrl &= ~1U;
149   PL1_SetControl(ctrl);
150
151   // Remember pending interrupt flag
152   if (IRQ_GetPending(GTIM_IRQ_NUM) != 0) {
153     IRQ_ClearPending(GTIM_IRQ_NUM);
154     GTIM_PendIRQ = 1U;
155   }
156
157   return (0);
158 }
159
160 // Acknowledge OS Tick IRQ.
161 int32_t  OS_Tick_AcknowledgeIRQ (void) {
162   IRQ_ClearPending (GTIM_IRQ_NUM);
163   PL1_SetLoadValue(GTIM_Load);
164   return (0);
165 }
166
167 // Get OS Tick IRQ number.
168 int32_t  OS_Tick_GetIRQn (void) {
169   return (GTIM_IRQ_NUM);
170 }
171
172 // Get OS Tick clock.
173 uint32_t OS_Tick_GetClock (void) {
174   return (GTIM_Clock);
175 }
176
177 // Get OS Tick interval.
178 uint32_t OS_Tick_GetInterval (void) {
179   return (GTIM_Load + 1U);
180 }
181
182 // Get OS Tick count value.
183 uint32_t OS_Tick_GetCount (void) {
184   return (GTIM_Load - PL1_GetCurrentValue());
185 }
186
187 // Get OS Tick overflow status.
188 uint32_t OS_Tick_GetOverflow (void) {
189   CNTP_CTL_Type cntp_ctl;
190   cntp_ctl.w = PL1_GetControl();
191   return (cntp_ctl.b.ISTATUS);
192 }