]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cm3/drivers/Gpt.c
Cleanup of makefiles. Cleanup of merge.
[arc.git] / arch / arm / arm_cm3 / drivers / Gpt.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 \r
17 \r
18 #include "Std_Types.h"\r
19 //#include "Det.h"\r
20 #include "Gpt.h"\r
21 #include <string.h>\r
22 #if defined(USE_KERNEL)\r
23 #include "Os.h"\r
24 #include "isr.h"\r
25 #include "arc.h"\r
26 #endif\r
27 #include "stm32f10x.h"\r
28 \r
29 \r
30 \r
31 //TIM2->DIER =\r
32 \r
33 \r
34 /* -------------------------------- Arctic Core ------------------------------\r
35  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
36  *\r
37  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
38  *\r
39  * This source code is free software; you can redistribute it and/or modify it\r
40  * under the terms of the GNU General Public License version 2 as published by the\r
41  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
42  *\r
43  * This program is distributed in the hope that it will be useful, but\r
44  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
45  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
46  * for more details.\r
47  * -------------------------------- Arctic Core ------------------------------*/\r
48 \r
49 \r
50 \r
51 \r
52 \r
53 \r
54 \r
55 \r
56 #include "Std_Types.h"\r
57 #include "Gpt.h"\r
58 #include "Cpu.h"\r
59 #include <assert.h>\r
60 #include <string.h>\r
61 #include "Mcu.h"\r
62 #include "Det.h"\r
63 #if defined(USE_KERNEL)\r
64 #include "Os.h"\r
65 #include "isr.h"\r
66 #endif\r
67 \r
68 // Implementation specific\r
69 /* STM32 helper arrays\r
70  *\r
71  */\r
72 TIM_TypeDef * const TimAddr[] =\r
73 {\r
74         ((TIM_TypeDef *)TIM1_BASE),\r
75         ((TIM_TypeDef *)TIM2_BASE),\r
76         ((TIM_TypeDef *)TIM3_BASE),\r
77         ((TIM_TypeDef *)TIM4_BASE),\r
78         ((TIM_TypeDef *)TIM5_BASE),\r
79         ((TIM_TypeDef *)TIM6_BASE),\r
80     ((TIM_TypeDef *)TIM7_BASE),\r
81 };\r
82 \r
83 #if ( GPT_DEV_ERROR_DETECT == STD_ON )\r
84 #define VALIDATE(_exp,_api,_err ) \\r
85                 if( !(_exp) ) { \\r
86                         Det_ReportError(MODULE_ID_GPT,0,_api,_err); \\r
87                         return; \\r
88                 }\r
89 \r
90 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \\r
91                 if( !(_exp) ) { \\r
92                         Det_ReportError(MODULE_ID_GPT,0,_api,_err); \\r
93                         return (_rv); \\r
94                 }\r
95 \r
96 #define VALID_CHANNEL(_ch)              ( Gpt_Global.configured & (1<<(_ch)) )\r
97 \r
98 #else\r
99 #define VALIDATE(_exp,_api,_err )\r
100 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\r
101 #endif\r
102 \r
103 const uint32 IrqVector[] =\r
104 {\r
105                 TIM1_UP_IRQn,\r
106                 TIM2_IRQn,\r
107                 TIM3_IRQn,\r
108                 TIM4_IRQn,\r
109 };\r
110 \r
111 typedef enum\r
112 {\r
113         GPT_STATE_STOPPED = 0,\r
114                         GPT_STATE_STARTED,\r
115 } Gpt_StateType;\r
116 \r
117 /**\r
118  * Type that holds all global data for Gpt\r
119  */\r
120 typedef struct\r
121 {\r
122         // Set if Gpt_Init() have been called\r
123         boolean initRun;\r
124 \r
125         // Our config\r
126         const Gpt_ConfigType *config;\r
127 \r
128         uint8 wakeupEnabled;\r
129 \r
130         // One bit for each channel that is configured.\r
131         // Used to determine if validity of a channel\r
132         // 1 - configured\r
133         // 0 - NOT configured\r
134         uint32 configured;\r
135 \r
136         // Maps the a channel id to a configured channel id\r
137         uint8 channelMap[GPT_CHANNEL_CNT];\r
138 \r
139 } Gpt_GlobalType;\r
140 \r
141 /**\r
142  * Type that holds data that are specific for a channel\r
143  */\r
144 typedef struct\r
145 {\r
146         Gpt_StateType state;\r
147 } Gpt_UnitType;\r
148 \r
149 Gpt_UnitType Gpt_Unit[GPT_CHANNEL_CNT];\r
150 \r
151 // Global config\r
152 Gpt_GlobalType Gpt_Global;\r
153 \r
154 //-------------------------------------------------------------------\r
155 \r
156 \r
157 /**\r
158  * ISR helper-function that handles the HW channels( 0 to 8 )\r
159  *\r
160  * @param channel - Channel that the raised the interrupt\r
161  */\r
162 static void Gpt_IsrCh(Gpt_ChannelType channel)\r
163 {\r
164         const Gpt_ConfigType *config;\r
165         int confCh;\r
166 \r
167         confCh = Gpt_Global.channelMap[channel];\r
168         assert(confCh != GPT_CHANNEL_ILL);\r
169 \r
170         config = &Gpt_Global.config[confCh];\r
171 \r
172         if (config->GptChannelMode == GPT_MODE_ONESHOT)\r
173         {\r
174                 // Disable the channel\r
175                 TimAddr[channel]->CR1 &= ~TIM_CR1_CEN;\r
176 \r
177                 Gpt_Unit[channel].state = GPT_STATE_STOPPED;\r
178         }\r
179         config->GptNotification();\r
180 \r
181         // Clear interrupt\r
182         TimAddr[channel]->SR &= ~TIM_SR_UIF;\r
183 }\r
184 \r
185 //-------------------------------------------------------------------\r
186 // Macro that counts leading zeroes.\r
187 #define CNTLZW_INV(x) (31-cntlzw(x))\r
188 \r
189 /**\r
190  * ISR that handles all interrupts\r
191  */\r
192 static void Gpt_Isr(void)\r
193 {\r
194         static int i;\r
195         int found = 0;\r
196         /* Find channel for this interrupt. */\r
197         for (i = 0; ((i < GPT_CHANNEL_CNT) && !found);i++)\r
198         {\r
199                 found = (((TimAddr[i]->SR & TIM_SR_UIF) == TIM_SR_UIF) &&\r
200                                  ((TimAddr[i]->CR1 & TIM_CR1_CEN) == TIM_CR1_CEN));\r
201         }\r
202         if (found)\r
203         {\r
204                 Gpt_IsrCh(i - 1);\r
205         }\r
206 }\r
207 //-------------------------------------------------------------------\r
208 \r
209 void Gpt_Init(const Gpt_ConfigType *config)\r
210 {\r
211         uint32_t i=0;\r
212         const Gpt_ConfigType *cfg;\r
213         VALIDATE( (Gpt_Global.initRun == STD_OFF), GPT_INIT_SERVICE_ID, GPT_E_ALREADY_INITIALIZED );\r
214 #if defined(GPT_VARIANT_PB)\r
215         VALIDATE( (config != NULL ), GPT_INIT_SERVICE_ID, GPT_E_PARAM_CONFIG );\r
216 #elif   defined(GPT_VARIANT_PC)\r
217         // We don't support GPT_VARIANT_PC\r
218         assert(0);\r
219 #endif\r
220         Gpt_ChannelType ch;\r
221 \r
222         for (i=0; i<GPT_CHANNEL_CNT; i++)\r
223         {\r
224                 Gpt_Global.channelMap[i] = GPT_CHANNEL_ILL;\r
225         }\r
226 \r
227         i = 0;\r
228         cfg = config;\r
229         while (cfg->GptChannelId != GPT_CHANNEL_ILL)\r
230         {\r
231                 ch = cfg->GptChannelId;\r
232 \r
233                 // Assign the configuration channel used later..\r
234                 Gpt_Global.channelMap[cfg->GptChannelId] = i;\r
235                 Gpt_Global.configured |= (1<<ch);\r
236 \r
237                 if (ch <= GPT_CHANNEL_CNT)\r
238                 {\r
239                         if (cfg->GptNotification != NULL)\r
240                         {\r
241 \r
242 #if defined(USE_KERNEL)\r
243                                 TaskType tid;\r
244                                 tid = Os_Arc_CreateIsr(Gpt_Isr, 6, "Gpt_Isr");\r
245                                 Irq_AttachIsr2(tid, NULL, IrqVector[ch]);\r
246 #else\r
247                                 //IntCtrl_InstallVector(Gpt_Isr, PIT_PITFLG_RTIF + ch, 1, CPU_Z1); TODO\r
248 #endif\r
249                         }\r
250                 }\r
251 #if defined(USE_KERNEL)\r
252                 // Don't install if we use kernel.. it handles that.\r
253 #else\r
254 \r
255 #endif\r
256 \r
257                 cfg++;\r
258                 i++;\r
259         }\r
260 \r
261         Gpt_Global.config = config;\r
262 \r
263         Gpt_Global.initRun = STD_ON;\r
264         //PIT.CTRL.B.MDIS = 0;\r
265 }\r
266 \r
267 //-------------------------------------------------------------------\r
268 \r
269 #if GPT_DEINIT_API == STD_ON\r
270 void Gpt_DeInit(void)\r
271 {\r
272         Gpt_ChannelType channel;\r
273         VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_DEINIT_SERVICE_ID, GPT_E_UNINIT );\r
274         for (channel=0; channel<GPT_CHANNEL_CNT; channel++) // Validate that all channels have been stopped\r
275         {\r
276                 VALIDATE( (Gpt_Unit[channel].state == GPT_STATE_STOPPED), GPT_DEINIT_SERVICE_ID, GPT_E_BUSY );\r
277                 Gpt_StopTimer(channel); // Should this be done here?\r
278         }\r
279         Gpt_Global.initRun = STD_OFF;\r
280         Gpt_Global.configured = 0;\r
281         //_config.config = NULL;\r
282 }\r
283 #endif\r
284 \r
285 //-------------------------------------------------------------------\r
286 // period is in "ticks" !!\r
287 void Gpt_StartTimer(Gpt_ChannelType channel, Gpt_ValueType period_ticks)\r
288 {\r
289         int confCh;\r
290 \r
291         VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_STARTTIMER_SERVICE_ID, GPT_E_UNINIT );\r
292         VALIDATE( VALID_CHANNEL(channel), GPT_STARTTIMER_SERVICE_ID, GPT_E_PARAM_CHANNEL );\r
293         VALIDATE( (Gpt_Unit[channel].state == GPT_STATE_STOPPED), GPT_STARTTIMER_SERVICE_ID, GPT_E_BUSY );\r
294         // GPT_E_PARAM_VALUE, all have 32-bit so no need to check\r
295 \r
296         //DEBUG(DEBUG_HIGH, "Gpt_StartTimer ch=%d, period=%d [ticks]\n", channel, period_ticks);\r
297 \r
298         confCh = Gpt_Global.channelMap[channel];\r
299 \r
300         if (channel <= GPT_CHANNEL_CNT)\r
301         {\r
302                 uint32 *tlval = (uint32 *)&(TimAddr[channel]->ARR);\r
303                 uint32 *tval = (uint32 *)&(TimAddr[channel]->CNT);\r
304 \r
305                 *tlval = period_ticks;\r
306                 *tval = period_ticks;\r
307 \r
308                 // always select interrupt\r
309                 //TimAddr[channel]->DIER |= TIM_DIER_UIE;\r
310 \r
311                 // Make sure that no interrupt is pending.\r
312                 TimAddr[channel]->SR &= ~TIM_SR_UIF;\r
313 \r
314                 // Set prescaler.\r
315                 TimAddr[channel]->PSC = Gpt_Global.config[confCh].GptChannelPrescale;\r
316 \r
317                 // Enable timer\r
318                 TimAddr[channel]->CR1 |= (TIM_CR1_CEN | TIM_CR1_URS | TIM_CR1_DIR);\r
319                 TimAddr[channel]->CR1 &= ~TIM_CR1_UDIS;\r
320         }\r
321         #if ( GPT_ENABLE_DISABLE_NOTIFICATION_API == STD_ON )\r
322         if( Gpt_Global.config[confCh].GptNotification != NULL )\r
323         {\r
324                 // GPT275\r
325                 Gpt_EnableNotification(channel);\r
326         }\r
327         #endif\r
328         Gpt_Unit[channel].state = GPT_STATE_STARTED;\r
329 }\r
330 \r
331 void Gpt_StopTimer(Gpt_ChannelType channel)\r
332 {\r
333 \r
334         VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_STOPTIMER_SERVICE_ID, GPT_E_UNINIT );\r
335         VALIDATE( VALID_CHANNEL(channel), GPT_STOPTIMER_SERVICE_ID, GPT_E_PARAM_CHANNEL );\r
336 \r
337         if (channel <= GPT_CHANNEL_CNT)\r
338         {\r
339                 // Disable timer\r
340                 TimAddr[channel]->CR1 &= ~TIM_CR1_CEN;\r
341         }\r
342         #if ( GPT_ENABLE_DISABLE_NOTIFICATION_API == STD_ON )\r
343         Gpt_DisableNotification(channel);\r
344         #endif\r
345         Gpt_Unit[channel].state = GPT_STATE_STOPPED;\r
346 }\r
347 \r
348 #if ( GPT_TIME_REMAINING_API == STD_ON )\r
349 \r
350 Gpt_ValueType Gpt_GetTimeRemaining(Gpt_ChannelType channel)\r
351 {\r
352         VALIDATE_W_RV( (Gpt_Global.initRun == STD_ON), GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_UNINIT, 0 );\r
353         VALIDATE_W_RV( VALID_CHANNEL(channel),GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_PARAM_CHANNEL, 0 );\r
354         VALIDATE_W_RV( (Gpt_Unit[channel].state == GPT_STATE_STARTED), GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_NOT_STARTED, 0 );\r
355         Gpt_ValueType remaining;\r
356 \r
357         if (channel <= GPT_CHANNEL_CNT)\r
358         {\r
359                 uint32 *tval = (uint32 *)&(TimAddr[channel]->CNT);\r
360                 // Time remaining is the time until it hits 0, so just return the current timer value\r
361                 remaining = *tval;\r
362         }\r
363 \r
364         return remaining;\r
365 }\r
366 #endif\r
367 \r
368 #if ( GPT_TIME_ELAPSED_API == STD_ON )\r
369 Gpt_ValueType Gpt_GetTimeElapsed(Gpt_ChannelType channel)\r
370 {\r
371         Gpt_ValueType timer;\r
372 \r
373         VALIDATE_W_RV( (Gpt_Global.initRun == STD_ON), GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_UNINIT ,0 );\r
374         VALIDATE_W_RV( VALID_CHANNEL(channel),GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_PARAM_CHANNEL, 0 );\r
375         VALIDATE_W_RV( (Gpt_Unit[channel].state == GPT_STATE_STARTED),GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_NOT_STARTED, 0 );\r
376 \r
377         // NOTE!\r
378         // These little creatures count down\r
379 \r
380         if (channel <= GPT_CHANNEL_CNT)\r
381         {\r
382                 uint32 *tlval = (uint32 *)&(TimAddr[channel]->ARR);\r
383             uint32 *tval = (uint32 *)&(TimAddr[channel]->CNT);\r
384                 timer = *tlval - *tval;\r
385         }\r
386 \r
387         return (timer);\r
388 }\r
389 #endif\r
390 \r
391 #if ( GPT_ENABLE_DISABLE_NOTIFICATION_API == STD_ON )\r
392 void Gpt_EnableNotification(Gpt_ChannelType channel)\r
393 {\r
394 \r
395         VALIDATE( (Gpt_Global.initRun == STD_ON), 0x7, GPT_E_UNINIT );\r
396         VALIDATE( VALID_CHANNEL(channel),0x7, GPT_E_PARAM_CHANNEL );\r
397 \r
398         if (channel <= GPT_CHANNEL_CNT)\r
399         {\r
400                 // enable interrupts\r
401                 TimAddr[channel]->DIER |= TIM_DIER_UIE;\r
402         }\r
403 }\r
404 \r
405 void Gpt_DisableNotification(Gpt_ChannelType channel)\r
406 {\r
407 \r
408         VALIDATE( (Gpt_Global.initRun == STD_ON), 0x8, GPT_E_UNINIT );\r
409         VALIDATE( VALID_CHANNEL(channel),0x8, GPT_E_PARAM_CHANNEL );\r
410 \r
411         if (channel <= GPT_CHANNEL_CNT)\r
412         {\r
413                 TimAddr[channel]->DIER &= ~TIM_DIER_UIE;\r
414         }\r
415 \r
416         return;\r
417 }\r
418 \r
419 #endif\r
420 \r
421 #if ( GPT_WAKEUP_FUNCTIONALITY_API == STD_ON )\r
422 \r
423 void Gpt_SetMode(Gpt_ModeType mode)\r
424 {\r
425         int i;\r
426 \r
427         VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_SETMODE_SERVIVCE_ID, GPT_E_UNINIT );\r
428         VALIDATE( ( mode <= GPT_MODE_SLEEP ), GPT_SETMODE_SERVIVCE_ID, GPT_E_PARAM_MODE );\r
429 \r
430         if (mode == GPT_MODE_NORMAL)\r
431         {\r
432                 //PIT.CTRL.B.MDIS = 0; TODO\r
433                 // Do NOT restart channels\r
434         }\r
435         else if (mode == GPT_MODE_SLEEP)\r
436         {\r
437 \r
438                 //PIT.CTRL.B.MDIS = 1; TODO\r
439                 // Disable all\r
440                 for (i= 0; i <= GPT_CHANNEL_CNT; i++)\r
441                 {\r
442                         Gpt_StopTimer(i);\r
443                 }\r
444         }\r
445 }\r
446 \r
447 void Gpt_DisableWakeup(Gpt_ChannelType channel)\r
448 {\r
449         VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_DISABLEWAKEUP_SERVICE_ID, GPT_E_UNINIT );\r
450         VALIDATE( VALID_CHANNEL(channel), GPT_DISABLEWAKEUP_SERVICE_ID, GPT_E_PARAM_CHANNEL );\r
451         // Only RTI have system wakeup\r
452         if (channel == GPT_CHANNEL_RTI)\r
453         {\r
454                 Gpt_Global.wakeupEnabled = STD_OFF;\r
455         }\r
456         else\r
457         {\r
458                 // TODO:\r
459                 //assert(0);\r
460         }\r
461 }\r
462 \r
463 void Gpt_EnableWakeup(Gpt_ChannelType channel)\r
464 {\r
465         VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_ENABLEWAKEUP_SERVICE_ID, GPT_E_UNINIT );\r
466         VALIDATE( VALID_CHANNEL(channel),GPT_ENABLEWAKEUP_SERVICE_ID, GPT_E_PARAM_CHANNEL );\r
467         if (channel == GPT_CHANNEL_RTI)\r
468         {\r
469                 Gpt_Global.wakeupEnabled = STD_ON;\r
470         }\r
471         else\r
472         {\r
473                 // TODO:\r
474                 //assert(0);\r
475         }\r
476 }\r
477 \r
478 void Gpt_Cbk_CheckWakeup(EcuM_WakeupSourceType wakeupSource)\r
479 {\r
480 \r
481 }\r
482 \r
483 #endif\r
484 \r