1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\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
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
14 * -------------------------------- Arctic Core ------------------------------*/
\r
16 /* ----------------------------[information]----------------------------------*/
\r
21 * 3.1.5 (ok, it says 3.1.1 but, thats wrong)
\r
24 * Implements the Gpt module
\r
28 * -------------------------------------------
\r
29 * GPT_DEV_ERROR_DETECT Y
\r
32 * GptConfigurationOfOptApiServices Support
\r
33 * -------------------------------------------
\r
35 * GPT_ENABLE_DISABLE_NOTIFICATION_API Y
\r
36 * GPT_TIME_ELAPSED_API Y
\r
37 * GPT_TIME_REMAINING_API Y
\r
38 * GPT_VERSION_INFO_API Y
\r
39 * GPT_WAKEUP_FUNCTIONALITY_API Y
\r
41 * Implementation Notes:
\r
44 * Lots of tagging still to do.
\r
47 /* ----------------------------[includes]------------------------------------*/
\r
49 #include "Std_Types.h"
\r
54 #include "mpc55xx.h"
\r
61 /* ----------------------------[private define]------------------------------*/
\r
62 /* ----------------------------[private macro]-------------------------------*/
\r
64 #if ( GPT_DEV_ERROR_DETECT == STD_ON )
\r
65 #define VALIDATE(_exp,_api,_err ) \
\r
67 Det_ReportError(MODULE_ID_GPT,0,_api,_err); \
\r
71 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
73 Det_ReportError(MODULE_ID_GPT,0,_api,_err); \
\r
77 #define VALID_CHANNEL(_ch) ( Gpt_Global.configured & (1<<(_ch)) )
\r
80 #define VALIDATE(_exp,_api,_err )
\r
81 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
84 /* ----------------------------[private typedef]-----------------------------*/
\r
85 /* ----------------------------[private function prototypes]-----------------*/
\r
86 /* ----------------------------[private variables]---------------------------*/
\r
87 /* ----------------------------[private functions]---------------------------*/
\r
88 /* ----------------------------[public functions]----------------------------*/
\r
91 GPT_STATE_STOPPED = 0, GPT_STATE_STARTED,
\r
95 * Type that holds all global data for Gpt
\r
98 // Set if Gpt_Init() have been called
\r
102 const Gpt_ConfigType *config;
\r
104 #if ( GPT_WAKEUP_FUNCTIONALITY_API == STD_ON )
\r
105 uint8 wakeupEnabled;
\r
108 // One bit for each channel that is configured.
\r
109 // Used to determine if validity of a channel
\r
111 // 0 - NOT configured
\r
114 // Maps the a channel id to a configured channel id
\r
115 uint8 channelMap[GPT_CHANNEL_CNT];
\r
120 * Type that holds data that are specific for a channel
\r
123 Gpt_StateType state;
\r
127 /* GPT_CHANNEL_CNT represents the number of physical channels */
\r
128 Gpt_UnitType Gpt_Unit[GPT_CHANNEL_CNT];
\r
131 Gpt_GlobalType Gpt_Global;
\r
133 //-------------------------------------------------------------------
\r
136 * ISR for a given PIT channel (macro)
\r
138 #if defined(CFG_MPC560X)
\r
139 #define GPT_ISR( _channel ) \
\r
140 static void Gpt_Isr_Channel##_channel( void ) \
\r
142 const Gpt_ConfigType *config; \
\r
145 /* Find the config entry for the PIT channel. */ \
\r
146 confCh = Gpt_Global.channelMap[ _channel ]; \
\r
147 assert(confCh != GPT_CHANNEL_ILL); \
\r
148 config = &Gpt_Global.config[ confCh ]; \
\r
150 if( config->GptChannelMode == GPT_MODE_ONESHOT ) \
\r
152 /* Disable the channel. */ \
\r
153 PIT.CH[_channel].TCTRL.B.TEN = 0; \
\r
154 Gpt_Unit[_channel].state = GPT_STATE_STOPPED; \
\r
156 config->GptNotification(); \
\r
158 /* Clear interrupt. */ \
\r
159 PIT.CH[_channel].TFLG.B.TIF = 1; \
\r
162 #define GPT_ISR( _channel ) \
\r
163 static void Gpt_Isr_Channel##_channel( void ) \
\r
165 const Gpt_ConfigType *config; \
\r
168 /* Find the config entry for the PIT channel. */ \
\r
169 confCh = Gpt_Global.channelMap[ _channel ]; \
\r
170 assert(confCh != GPT_CHANNEL_ILL); \
\r
171 config = &Gpt_Global.config[ confCh ]; \
\r
173 if( config->GptChannelMode == GPT_MODE_ONESHOT ) \
\r
175 /* Disable the channel. */ \
\r
176 PIT.EN.R &= ~( 1 << _channel ); \
\r
178 Gpt_Unit[_channel].state = GPT_STATE_STOPPED; \
\r
180 config->GptNotification(); \
\r
182 /* Clear interrupt. */ \
\r
183 PIT.FLG.R = ( 1 << _channel ); \
\r
187 #define STR__(x) #x
\r
188 #define XSTR__(x) STR__(x)
\r
191 * Create instances of the ISR for each PIT channel.
\r
197 #if !defined(CFG_MPC5606S)
\r
200 #if !defined(CFG_MPC5604B)
\r
203 #if !defined(CFG_MPC5606B)
\r
209 #if defined(CFG_MPC560X)
\r
210 #if defined(CFG_MPC5606S)
\r
211 #define GPT_CHANNEL_PIT_LAST GPT_CHANNEL_PIT_3
\r
212 #elif defined(CFG_MPC5604B)
\r
213 #define GPT_CHANNEL_PIT_LAST GPT_CHANNEL_PIT_5
\r
214 #elif defined(CFG_MPC5606B)
\r
215 #define GPT_CHANNEL_PIT_LAST GPT_CHANNEL_PIT_7
\r
218 #define GPT_CHANNEL_PIT_LAST GPT_CHANNEL_PIT_8
\r
219 #define PIT_INT0 PIT_PITFLG_RTIF
\r
220 #define PIT_INT1 PIT_PITFLG_PIT1
\r
221 #define PIT_INT2 PIT_PITFLG_PIT2
\r
222 #define PIT_INT3 PIT_PITFLG_PIT3
\r
223 #define PIT_INT4 PIT_PITFLG_PIT4
\r
224 #define PIT_INT5 PIT_PITFLG_PIT5
\r
225 #define PIT_INT6 PIT_PITFLG_PIT6
\r
226 #define PIT_INT7 PIT_PITFLG_PIT7
\r
229 //-------------------------------------------------------------------
\r
231 void Gpt_Init(const Gpt_ConfigType *config) {
\r
232 /** @req 3.1.5/GPT280 */
\r
233 /** @req 3.1.5/GPT006 */
\r
234 /** !req 3.1.5/GPT272 Post build not supported */
\r
235 /** @req 3.1.5/GPT107 The module is disabled */
\r
236 /** @req 3.1.5/GPT068 Global registers must be touched */
\r
237 /** @req 3.1.5/GPT205 */
\r
238 /** !req 3.1.5/GPT294 Post build not supported */
\r
239 /** !req 3.1.5/GPT309 TODO: Check*/
\r
242 const Gpt_ConfigType *cfg;
\r
243 /** @req 3.1.5/GPT307 */
\r
244 VALIDATE( (Gpt_Global.initRun == STD_OFF), GPT_INIT_SERVICE_ID, GPT_E_ALREADY_INITIALIZED );
\r
245 #if defined(GPT_VARIANT_PB)
\r
246 VALIDATE( (config != NULL ), GPT_INIT_SERVICE_ID, GPT_E_PARAM_CONFIG );
\r
247 #elif defined(GPT_VARIANT_PC)
\r
248 // We don't support GPT_VARIANT_PC
\r
251 Gpt_ChannelType ch;
\r
253 for (i = 0; i < GPT_CHANNEL_CNT; i++) {
\r
254 Gpt_Global.channelMap[i] = GPT_CHANNEL_ILL;
\r
255 Gpt_Unit[i].state = GPT_STATE_STOPPED;
\r
260 while (cfg->GptChannelId != GPT_CHANNEL_ILL) {
\r
261 ch = cfg->GptChannelId;
\r
263 // Assign the configuration channel used later..
\r
264 Gpt_Global.channelMap[cfg->GptChannelId] = i;
\r
265 Gpt_Global.configured |= (1 << ch);
\r
267 if (ch <= GPT_CHANNEL_PIT_LAST)
\r
269 if (cfg->GptNotification != NULL)
\r
273 case 0: ISR_INSTALL_ISR2( "Gpt_0", Gpt_Isr_Channel0, PIT_INT0, 2, 0 ); break;
\r
274 case 1: ISR_INSTALL_ISR2( "Gpt_1", Gpt_Isr_Channel1, PIT_INT1, 2, 0 ); break;
\r
275 case 2: ISR_INSTALL_ISR2( "Gpt_2", Gpt_Isr_Channel2, PIT_INT2, 2, 0 ); break;
\r
276 case 3: ISR_INSTALL_ISR2( "Gpt_3", Gpt_Isr_Channel3, PIT_INT3, 2, 0 ); break;
\r
277 #if !defined(CFG_MPC5606S)
\r
278 case 4: ISR_INSTALL_ISR2( "Gpt_4", Gpt_Isr_Channel4, PIT_INT4, 2, 0 ); break;
\r
279 case 5: ISR_INSTALL_ISR2( "Gpt_5", Gpt_Isr_Channel5, PIT_INT5, 2, 0 ); break;
\r
280 #if !defined(CFG_MPC5604B)
\r
281 case 6: ISR_INSTALL_ISR2( "Gpt_6", Gpt_Isr_Channel6, PIT_INT6, 2, 0 ); break;
\r
282 case 7: ISR_INSTALL_ISR2( "Gpt_7", Gpt_Isr_Channel7, PIT_INT7, 2, 0 ); break;
\r
283 #if !defined(CFG_MPC5606B)
\r
284 case 8: ISR_INSTALL_ISR2( "Gpt_8", Gpt_Isr_Channel8, PIT_PITFLG_PIT8, 2, 0 );break;
\r
290 // Unknown PIT channel.
\r
301 Gpt_Global.config = config;
\r
303 Gpt_Global.initRun = STD_ON;
\r
305 #if defined(CFG_MPC560X)
\r
306 for(i = 0; i <= GPT_CHANNEL_PIT_LAST; i++)
\r
308 PIT.CH[i].TCTRL.B.TIE = 0;
\r
311 PIT.MCR.B.MDIS = 0;
\r
314 /* @req 3.1.5|GPT258 */
\r
315 PIT.CTRL.B.MDIS = 0;
\r
320 //-------------------------------------------------------------------
\r
322 /** @req 3.1.5/GPT194 */
\r
323 #if GPT_DEINIT_API == STD_ON
\r
325 void Gpt_DeInit(void)
\r
327 /** @req 3.1.5/GPT281 */
\r
328 /** !req 3.1.5/GPT008 TODO: Shouldn't MDIS be set to 1 */
\r
329 /** @req 3.1.5/GPT161 */
\r
330 /** @req 3.1.5/GPT105 */
\r
331 /** @req 3.1.5/GPT162 */
\r
332 /** !req 3.1.5/GPT308 Post build not supported */
\r
333 /** !req 3.1.5/GPT234 It has sideaffects now */
\r
335 Gpt_ChannelType channel;
\r
337 /* @req 3.1.5/GPT220 */
\r
338 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_DEINIT_SERVICE_ID, GPT_E_UNINIT );
\r
339 for (channel=0; channel<GPT_CHANNEL_CNT; channel++) // Validate that all channels have been stopped
\r
341 VALIDATE( (Gpt_Unit[channel].state == GPT_STATE_STOPPED), GPT_DEINIT_SERVICE_ID, GPT_E_BUSY );
\r
343 Gpt_Global.initRun = STD_OFF;
\r
344 Gpt_Global.configured = 0;
\r
348 //-------------------------------------------------------------------
\r
349 // period is in "ticks" !!
\r
350 void Gpt_StartTimer(Gpt_ChannelType channel, Gpt_ValueType period_ticks) {
\r
351 #if !defined(CFG_MPC560X)
\r
356 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_STARTTIMER_SERVICE_ID, GPT_E_UNINIT );
\r
357 VALIDATE( VALID_CHANNEL(channel), GPT_STARTTIMER_SERVICE_ID, GPT_E_PARAM_CHANNEL );
\r
358 VALIDATE( (Gpt_Unit[channel].state == GPT_STATE_STOPPED), GPT_STARTTIMER_SERVICE_ID, GPT_E_BUSY );
\r
359 // GPT_E_PARAM_VALUE, all have 32-bit so no need to check
\r
361 DEBUG(DEBUG_HIGH, "Gpt_StartTimer ch=%d, period=%d [ticks]\n", channel, period_ticks);
\r
363 confCh = Gpt_Global.channelMap[channel];
\r
364 #if defined(CFG_MPC560X)
\r
365 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
367 PIT.CH[channel].LDVAL.R = period_ticks;
\r
369 // Make sure that no interrupt is pending.
\r
370 PIT.CH[channel].TFLG.B.TIF = 1;
\r
372 PIT.CH[channel].TCTRL.B.TEN = 1;
\r
375 if (channel <= GPT_CHANNEL_PIT_LAST) {
\r
376 uint32 *tlval = (uint32 *) &PIT.TLVAL0;
\r
377 uint32 *tval = (uint32 *) &PIT.TVAL0;
\r
379 tlval[channel] = period_ticks;
\r
380 tval[channel] = period_ticks;
\r
382 // always select interrupt
\r
383 if (channel != GPT_CHANNEL_RTI) {
\r
384 PIT.INTSEL.R |= (1 << channel);
\r
387 // Make sure that no interrupt is pending.
\r
388 PIT.FLG.R = (1 << channel);
\r
391 PIT.EN.R |= (1 << channel);
\r
392 } else if (channel == GPT_CHANNEL_DEC) {
\r
394 tmp = get_spr(SPR_HID0);
\r
396 set_spr(SPR_HID0,tmp);
\r
398 /* Initialize the Decrementer */
\r
399 set_spr(SPR_DEC, period_ticks);
\r
400 set_spr(SPR_DECAR, period_ticks);
\r
402 if (Gpt_Global.config[confCh].GptChannelMode == GPT_MODE_CONTINUOUS) {
\r
403 /* Set autoreload */
\r
404 tmp = get_spr(SPR_TCR);
\r
406 set_spr(SPR_TCR,tmp);
\r
410 if (Gpt_Global.config[confCh].GptNotification != NULL) {
\r
412 Gpt_EnableNotification(channel);
\r
415 Gpt_Unit[channel].state = GPT_STATE_STARTED;
\r
418 void Gpt_StopTimer(Gpt_ChannelType channel) {
\r
420 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_STOPTIMER_SERVICE_ID, GPT_E_UNINIT ); VALIDATE( VALID_CHANNEL(channel), GPT_STOPTIMER_SERVICE_ID, GPT_E_PARAM_CHANNEL );
\r
422 #if defined(CFG_MPC560X)
\r
423 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
426 PIT.CH[channel].TCTRL.B.TEN = 0;
\r
429 if (channel <= GPT_CHANNEL_PIT_LAST) {
\r
431 PIT.EN.R &= ~(1 << channel);
\r
432 } else if (channel == GPT_CHANNEL_DEC) {
\r
434 tb = get_spr(SPR_HID0);
\r
436 set_spr(SPR_HID0,tb);
\r
439 Gpt_DisableNotification(channel);
\r
440 Gpt_Unit[channel].state = GPT_STATE_STOPPED;
\r
443 #if ( GPT_TIME_REMAINING_API == STD_ON )
\r
445 Gpt_ValueType Gpt_GetTimeRemaining(Gpt_ChannelType channel)
\r
447 VALIDATE_W_RV( (Gpt_Global.initRun == STD_ON), GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_UNINIT, 0 );
\r
448 VALIDATE_W_RV( VALID_CHANNEL(channel),GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_PARAM_CHANNEL, 0 );
\r
449 VALIDATE_W_RV( (Gpt_Unit[channel].state == GPT_STATE_STARTED), GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_NOT_STARTED, 0 );
\r
450 Gpt_ValueType remaining;
\r
452 #if defined(CFG_MPC560X)
\r
453 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
455 // Time remaining is the time until it hits 0, so just return the current timer value
\r
456 remaining = PIT.CH[channel].CVAL.R;
\r
459 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
461 uint32 *tval = (uint32 *)&PIT.TVAL0;
\r
462 // Time remaining is the time until it hits 0, so just return the current timer value
\r
463 remaining = tval[channel];
\r
465 else if (channel == GPT_CHANNEL_DEC)
\r
467 remaining = get_spr(SPR_DEC);
\r
471 /* We have written a fault in the fault log. Return 0. */
\r
480 #if ( GPT_TIME_ELAPSED_API == STD_ON )
\r
481 Gpt_ValueType Gpt_GetTimeElapsed(Gpt_ChannelType channel)
\r
483 Gpt_ValueType timer;
\r
485 VALIDATE_W_RV( (Gpt_Global.initRun == STD_ON), GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_UNINIT ,0 );
\r
486 VALIDATE_W_RV( VALID_CHANNEL(channel),GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_PARAM_CHANNEL, 0 );
\r
487 VALIDATE_W_RV( (Gpt_Unit[channel].state == GPT_STATE_STARTED),GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_NOT_STARTED, 0 );
\r
490 // These little creatures count down
\r
492 #if defined(CFG_MPC560X)
\r
493 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
495 uint32 tval = PIT.CH[channel].CVAL.R;
\r
496 uint32 tlval = PIT.CH[channel].LDVAL.R;
\r
497 timer = tlval - tval;
\r
504 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
506 uint32 *tval = (uint32 *)&PIT.TVAL0;
\r
507 uint32 *tlval = (uint32 *)&PIT.TLVAL0;
\r
508 timer = tlval[channel] - tval[channel];
\r
510 else if (channel == GPT_CHANNEL_DEC)
\r
512 timer = get_spr(SPR_DECAR) - get_spr(SPR_DEC);
\r
516 /* We have written a fault in the fault log. Return 0. */
\r
525 #if ( GPT_ENABLE_DISABLE_NOTIFICATION_API == STD_ON )
\r
526 void Gpt_EnableNotification(Gpt_ChannelType channel)
\r
529 VALIDATE( (Gpt_Global.initRun == STD_ON), 0x7, GPT_E_UNINIT );
\r
530 VALIDATE( VALID_CHANNEL(channel),0x7, GPT_E_PARAM_CHANNEL );
\r
532 #if defined(CFG_MPC560X)
\r
533 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
535 PIT.CH[channel].TCTRL.B.TIE = 1;
\r
538 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
540 // enable interrupts
\r
541 PIT.INTEN.R |= ( 1 << channel );
\r
543 else if (channel == GPT_CHANNEL_DEC)
\r
546 tmp = get_spr(SPR_TCR);
\r
548 set_spr(SPR_TCR, tmp );
\r
553 void Gpt_DisableNotification(Gpt_ChannelType channel)
\r
556 VALIDATE( (Gpt_Global.initRun == STD_ON), 0x8, GPT_E_UNINIT );
\r
557 VALIDATE( VALID_CHANNEL(channel),0x8, GPT_E_PARAM_CHANNEL );
\r
559 #if defined(CFG_MPC560X)
\r
560 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
562 PIT.CH[channel].TCTRL.B.TIE = 0;
\r
565 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
567 PIT.INTEN.R &= ~( 1 << channel );
\r
569 else if (channel == GPT_CHANNEL_DEC)
\r
572 tmp = get_spr(SPR_TCR);
\r
574 set_spr(SPR_TCR, tmp );
\r
582 #if ( GPT_WAKEUP_FUNCTIONALITY_API == STD_ON )
\r
584 void Gpt_SetMode(Gpt_ModeType mode)
\r
588 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_SETMODE_SERVIVCE_ID, GPT_E_UNINIT );
\r
589 VALIDATE( ( mode <= GPT_MODE_SLEEP ), GPT_SETMODE_SERVIVCE_ID, GPT_E_PARAM_MODE );
\r
591 #if defined(CFG_MPC560X)
\r
592 if (mode == GPT_MODE_NORMAL)
\r
594 PIT.PITMCR.B.MDIS = 0;
\r
595 // Do NOT restart channels
\r
597 else if (mode == GPT_MODE_SLEEP)
\r
599 PIT.PITMCR.B.MDIS = 0;
\r
600 // Disable all but RTI
\r
601 for (i= 0; i <= GPT_CHANNEL_PIT_LAST; i++)
\r
607 if (mode == GPT_MODE_NORMAL)
\r
609 PIT.CTRL.B.MDIS = 0;
\r
610 // Do NOT restart channels
\r
612 else if (mode == GPT_MODE_SLEEP)
\r
615 PIT.CTRL.B.MDIS = 1;
\r
616 // Disable all but RTI
\r
617 for (i= 0; i <= GPT_CHANNEL_PIT_LAST; i++)
\r
625 void Gpt_DisableWakeup(Gpt_ChannelType channel)
\r
627 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_DISABLEWAKEUP_SERVICE_ID, GPT_E_UNINIT );
\r
628 VALIDATE( VALID_CHANNEL(channel), GPT_DISABLEWAKEUP_SERVICE_ID, GPT_E_PARAM_CHANNEL );
\r
629 // Only RTI have system wakeup
\r
630 if (channel == GPT_CHANNEL_RTI)
\r
632 Gpt_Global.wakeupEnabled = STD_OFF;
\r
641 void Gpt_EnableWakeup(Gpt_ChannelType channel)
\r
643 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_ENABLEWAKEUP_SERVICE_ID, GPT_E_UNINIT );
\r
644 VALIDATE( VALID_CHANNEL(channel),GPT_ENABLEWAKEUP_SERVICE_ID, GPT_E_PARAM_CHANNEL );
\r
645 if (channel == GPT_CHANNEL_RTI)
\r
647 Gpt_Global.wakeupEnabled = STD_ON;
\r
656 void Gpt_Cbk_CheckWakeup(EcuM_WakeupSourceType wakeupSource)
\r