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
207 #if defined(CFG_MPC560X)
\r
208 #if defined(CFG_MPC5606S)
\r
209 #define GPT_CHANNEL_PIT_LAST GPT_CHANNEL_PIT_3
\r
210 #elif defined(CFG_MPC5604B)
\r
211 #define GPT_CHANNEL_PIT_LAST GPT_CHANNEL_PIT_5
\r
214 #define GPT_CHANNEL_PIT_LAST GPT_CHANNEL_PIT_8
\r
215 #define PIT_INT0 PIT_PITFLG_RTIF
\r
216 #define PIT_INT1 PIT_PITFLG_PIT1
\r
217 #define PIT_INT2 PIT_PITFLG_PIT2
\r
218 #define PIT_INT3 PIT_PITFLG_PIT3
\r
219 #define PIT_INT4 PIT_PITFLG_PIT4
\r
220 #define PIT_INT5 PIT_PITFLG_PIT5
\r
223 //-------------------------------------------------------------------
\r
225 void Gpt_Init(const Gpt_ConfigType *config) {
\r
226 /** @req 3.1.5/GPT280 */
\r
227 /** @req 3.1.5/GPT006 */
\r
228 /** !req 3.1.5/GPT272 Post build not supported */
\r
229 /** @req 3.1.5/GPT107 The module is disabled */
\r
230 /** @req 3.1.5/GPT068 Global registers must be touched */
\r
231 /** @req 3.1.5/GPT205 */
\r
232 /** !req 3.1.5/GPT294 Post build not supported */
\r
233 /** !req 3.1.5/GPT309 TODO: Check*/
\r
236 const Gpt_ConfigType *cfg;
\r
237 /** @req 3.1.5/GPT307 */
\r
238 VALIDATE( (Gpt_Global.initRun == STD_OFF), GPT_INIT_SERVICE_ID, GPT_E_ALREADY_INITIALIZED );
\r
239 #if defined(GPT_VARIANT_PB)
\r
240 VALIDATE( (config != NULL ), GPT_INIT_SERVICE_ID, GPT_E_PARAM_CONFIG );
\r
241 #elif defined(GPT_VARIANT_PC)
\r
242 // We don't support GPT_VARIANT_PC
\r
245 Gpt_ChannelType ch;
\r
247 for (i = 0; i < GPT_CHANNEL_CNT; i++) {
\r
248 Gpt_Global.channelMap[i] = GPT_CHANNEL_ILL;
\r
249 Gpt_Unit[i].state = GPT_STATE_STOPPED;
\r
254 while (cfg->GptChannelId != GPT_CHANNEL_ILL) {
\r
255 ch = cfg->GptChannelId;
\r
257 // Assign the configuration channel used later..
\r
258 Gpt_Global.channelMap[cfg->GptChannelId] = i;
\r
259 Gpt_Global.configured |= (1 << ch);
\r
261 if (ch <= GPT_CHANNEL_PIT_LAST)
\r
263 if (cfg->GptNotification != NULL)
\r
267 case 0: ISR_INSTALL_ISR2( "Gpt_0", Gpt_Isr_Channel0, PIT_INT0, 2, 0 ); break;
\r
268 case 1: ISR_INSTALL_ISR2( "Gpt_1", Gpt_Isr_Channel1, PIT_INT1, 2, 0 ); break;
\r
269 case 2: ISR_INSTALL_ISR2( "Gpt_2", Gpt_Isr_Channel2, PIT_INT2, 2, 0 ); break;
\r
270 case 3: ISR_INSTALL_ISR2( "Gpt_3", Gpt_Isr_Channel3, PIT_INT3, 2, 0 ); break;
\r
271 #if !defined(CFG_MPC5606S)
\r
272 case 4: ISR_INSTALL_ISR2( "Gpt_4", Gpt_Isr_Channel4, PIT_INT4, 2, 0 ); break;
\r
273 case 5: ISR_INSTALL_ISR2( "Gpt_5", Gpt_Isr_Channel5, PIT_INT5, 2, 0 ); break;
\r
274 #if !defined(CFG_MPC5604B)
\r
275 case 6: ISR_INSTALL_ISR2( "Gpt_6", Gpt_Isr_Channel6, PIT_PITFLG_PIT6, 2, 0 ); break;
\r
276 case 7: ISR_INSTALL_ISR2( "Gpt_7", Gpt_Isr_Channel7, PIT_PITFLG_PIT7, 2, 0 ); break;
\r
277 case 8: ISR_INSTALL_ISR2( "Gpt_8", Gpt_Isr_Channel8, PIT_PITFLG_PIT8, 2, 0 );break;
\r
282 // Unknown PIT channel.
\r
293 Gpt_Global.config = config;
\r
295 Gpt_Global.initRun = STD_ON;
\r
297 #if defined(CFG_MPC560X)
\r
298 for(i = 0; i <= GPT_CHANNEL_PIT_LAST; i++)
\r
300 PIT.CH[i].TCTRL.B.TIE = 0;
\r
303 PIT.MCR.B.MDIS = 0;
\r
306 /* @req 3.1.5|GPT258 */
\r
307 PIT.CTRL.B.MDIS = 0;
\r
312 //-------------------------------------------------------------------
\r
314 /** @req 3.1.5/GPT194 */
\r
315 #if GPT_DEINIT_API == STD_ON
\r
317 void Gpt_DeInit(void)
\r
319 /** @req 3.1.5/GPT281 */
\r
320 /** !req 3.1.5/GPT008 TODO: Shouldn't MDIS be set to 1 */
\r
321 /** @req 3.1.5/GPT161 */
\r
322 /** @req 3.1.5/GPT105 */
\r
323 /** @req 3.1.5/GPT162 */
\r
324 /** !req 3.1.5/GPT308 Post build not supported */
\r
325 /** !req 3.1.5/GPT234 It has sideaffects now */
\r
327 Gpt_ChannelType channel;
\r
329 /* @req 3.1.5/GPT220 */
\r
330 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_DEINIT_SERVICE_ID, GPT_E_UNINIT );
\r
331 for (channel=0; channel<GPT_CHANNEL_CNT; channel++) // Validate that all channels have been stopped
\r
333 VALIDATE( (Gpt_Unit[channel].state == GPT_STATE_STOPPED), GPT_DEINIT_SERVICE_ID, GPT_E_BUSY );
\r
335 Gpt_Global.initRun = STD_OFF;
\r
336 Gpt_Global.configured = 0;
\r
340 //-------------------------------------------------------------------
\r
341 // period is in "ticks" !!
\r
342 void Gpt_StartTimer(Gpt_ChannelType channel, Gpt_ValueType period_ticks) {
\r
343 #if !defined(CFG_MPC560X)
\r
348 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_STARTTIMER_SERVICE_ID, GPT_E_UNINIT );
\r
349 VALIDATE( VALID_CHANNEL(channel), GPT_STARTTIMER_SERVICE_ID, GPT_E_PARAM_CHANNEL );
\r
350 VALIDATE( (Gpt_Unit[channel].state == GPT_STATE_STOPPED), GPT_STARTTIMER_SERVICE_ID, GPT_E_BUSY );
\r
351 // GPT_E_PARAM_VALUE, all have 32-bit so no need to check
\r
353 DEBUG(DEBUG_HIGH, "Gpt_StartTimer ch=%d, period=%d [ticks]\n", channel, period_ticks);
\r
355 confCh = Gpt_Global.channelMap[channel];
\r
356 #if defined(CFG_MPC560X)
\r
357 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
359 PIT.CH[channel].LDVAL.R = period_ticks;
\r
361 // Make sure that no interrupt is pending.
\r
362 PIT.CH[channel].TFLG.B.TIF = 1;
\r
364 PIT.CH[channel].TCTRL.B.TEN = 1;
\r
367 if (channel <= GPT_CHANNEL_PIT_LAST) {
\r
368 uint32 *tlval = (uint32 *) &PIT.TLVAL0;
\r
369 uint32 *tval = (uint32 *) &PIT.TVAL0;
\r
371 tlval[channel] = period_ticks;
\r
372 tval[channel] = period_ticks;
\r
374 // always select interrupt
\r
375 if (channel != GPT_CHANNEL_RTI) {
\r
376 PIT.INTSEL.R |= (1 << channel);
\r
379 // Make sure that no interrupt is pending.
\r
380 PIT.FLG.R = (1 << channel);
\r
383 PIT.EN.R |= (1 << channel);
\r
384 } else if (channel == GPT_CHANNEL_DEC) {
\r
386 tmp = get_spr(SPR_HID0);
\r
388 set_spr(SPR_HID0,tmp);
\r
390 /* Initialize the Decrementer */
\r
391 set_spr(SPR_DEC, period_ticks);
\r
392 set_spr(SPR_DECAR, period_ticks);
\r
394 if (Gpt_Global.config[confCh].GptChannelMode == GPT_MODE_CONTINUOUS) {
\r
395 /* Set autoreload */
\r
396 tmp = get_spr(SPR_TCR);
\r
398 set_spr(SPR_TCR,tmp);
\r
402 if (Gpt_Global.config[confCh].GptNotification != NULL) {
\r
404 Gpt_EnableNotification(channel);
\r
407 Gpt_Unit[channel].state = GPT_STATE_STARTED;
\r
410 void Gpt_StopTimer(Gpt_ChannelType channel) {
\r
412 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
414 #if defined(CFG_MPC560X)
\r
415 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
418 PIT.CH[channel].TCTRL.B.TEN = 0;
\r
421 if (channel <= GPT_CHANNEL_PIT_LAST) {
\r
423 PIT.EN.R &= ~(1 << channel);
\r
424 } else if (channel == GPT_CHANNEL_DEC) {
\r
426 tb = get_spr(SPR_HID0);
\r
428 set_spr(SPR_HID0,tb);
\r
431 Gpt_DisableNotification(channel);
\r
432 Gpt_Unit[channel].state = GPT_STATE_STOPPED;
\r
435 #if ( GPT_TIME_REMAINING_API == STD_ON )
\r
437 Gpt_ValueType Gpt_GetTimeRemaining(Gpt_ChannelType channel)
\r
439 VALIDATE_W_RV( (Gpt_Global.initRun == STD_ON), GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_UNINIT, 0 );
\r
440 VALIDATE_W_RV( VALID_CHANNEL(channel),GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_PARAM_CHANNEL, 0 );
\r
441 VALIDATE_W_RV( (Gpt_Unit[channel].state == GPT_STATE_STARTED), GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_NOT_STARTED, 0 );
\r
442 Gpt_ValueType remaining;
\r
444 #if defined(CFG_MPC560X)
\r
445 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
447 // Time remaining is the time until it hits 0, so just return the current timer value
\r
448 remaining = PIT.CH[channel].CVAL.R;
\r
451 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
453 uint32 *tval = (uint32 *)&PIT.TVAL0;
\r
454 // Time remaining is the time until it hits 0, so just return the current timer value
\r
455 remaining = tval[channel];
\r
457 else if (channel == GPT_CHANNEL_DEC)
\r
459 remaining = get_spr(SPR_DEC);
\r
463 /* We have written a fault in the fault log. Return 0. */
\r
472 #if ( GPT_TIME_ELAPSED_API == STD_ON )
\r
473 Gpt_ValueType Gpt_GetTimeElapsed(Gpt_ChannelType channel)
\r
475 Gpt_ValueType timer;
\r
477 VALIDATE_W_RV( (Gpt_Global.initRun == STD_ON), GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_UNINIT ,0 );
\r
478 VALIDATE_W_RV( VALID_CHANNEL(channel),GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_PARAM_CHANNEL, 0 );
\r
479 VALIDATE_W_RV( (Gpt_Unit[channel].state == GPT_STATE_STARTED),GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_NOT_STARTED, 0 );
\r
482 // These little creatures count down
\r
484 #if defined(CFG_MPC560X)
\r
485 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
487 uint32 tval = PIT.CH[channel].CVAL.R;
\r
488 uint32 tlval = PIT.CH[channel].LDVAL.R;
\r
489 timer = tlval - tval;
\r
496 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
498 uint32 *tval = (uint32 *)&PIT.TVAL0;
\r
499 uint32 *tlval = (uint32 *)&PIT.TLVAL0;
\r
500 timer = tlval[channel] - tval[channel];
\r
502 else if (channel == GPT_CHANNEL_DEC)
\r
504 timer = get_spr(SPR_DECAR) - get_spr(SPR_DEC);
\r
508 /* We have written a fault in the fault log. Return 0. */
\r
517 #if ( GPT_ENABLE_DISABLE_NOTIFICATION_API == STD_ON )
\r
518 void Gpt_EnableNotification(Gpt_ChannelType channel)
\r
521 VALIDATE( (Gpt_Global.initRun == STD_ON), 0x7, GPT_E_UNINIT );
\r
522 VALIDATE( VALID_CHANNEL(channel),0x7, GPT_E_PARAM_CHANNEL );
\r
524 #if defined(CFG_MPC560X)
\r
525 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
527 PIT.CH[channel].TCTRL.B.TIE = 1;
\r
530 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
532 // enable interrupts
\r
533 PIT.INTEN.R |= ( 1 << channel );
\r
535 else if (channel == GPT_CHANNEL_DEC)
\r
538 tmp = get_spr(SPR_TCR);
\r
540 set_spr(SPR_TCR, tmp );
\r
545 void Gpt_DisableNotification(Gpt_ChannelType channel)
\r
548 VALIDATE( (Gpt_Global.initRun == STD_ON), 0x8, GPT_E_UNINIT );
\r
549 VALIDATE( VALID_CHANNEL(channel),0x8, GPT_E_PARAM_CHANNEL );
\r
551 #if defined(CFG_MPC560X)
\r
552 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
554 PIT.CH[channel].TCTRL.B.TIE = 0;
\r
557 if (channel <= GPT_CHANNEL_PIT_LAST)
\r
559 PIT.INTEN.R &= ~( 1 << channel );
\r
561 else if (channel == GPT_CHANNEL_DEC)
\r
564 tmp = get_spr(SPR_TCR);
\r
566 set_spr(SPR_TCR, tmp );
\r
574 #if ( GPT_WAKEUP_FUNCTIONALITY_API == STD_ON )
\r
576 void Gpt_SetMode(Gpt_ModeType mode)
\r
580 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_SETMODE_SERVIVCE_ID, GPT_E_UNINIT );
\r
581 VALIDATE( ( mode <= GPT_MODE_SLEEP ), GPT_SETMODE_SERVIVCE_ID, GPT_E_PARAM_MODE );
\r
583 #if defined(CFG_MPC560X)
\r
584 if (mode == GPT_MODE_NORMAL)
\r
586 PIT.PITMCR.B.MDIS = 0;
\r
587 // Do NOT restart channels
\r
589 else if (mode == GPT_MODE_SLEEP)
\r
591 PIT.PITMCR.B.MDIS = 0;
\r
592 // Disable all but RTI
\r
593 for (i= 0; i <= GPT_CHANNEL_PIT_LAST; i++)
\r
599 if (mode == GPT_MODE_NORMAL)
\r
601 PIT.CTRL.B.MDIS = 0;
\r
602 // Do NOT restart channels
\r
604 else if (mode == GPT_MODE_SLEEP)
\r
607 PIT.CTRL.B.MDIS = 1;
\r
608 // Disable all but RTI
\r
609 for (i= 0; i <= GPT_CHANNEL_PIT_LAST; i++)
\r
617 void Gpt_DisableWakeup(Gpt_ChannelType channel)
\r
619 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_DISABLEWAKEUP_SERVICE_ID, GPT_E_UNINIT );
\r
620 VALIDATE( VALID_CHANNEL(channel), GPT_DISABLEWAKEUP_SERVICE_ID, GPT_E_PARAM_CHANNEL );
\r
621 // Only RTI have system wakeup
\r
622 if (channel == GPT_CHANNEL_RTI)
\r
624 Gpt_Global.wakeupEnabled = STD_OFF;
\r
633 void Gpt_EnableWakeup(Gpt_ChannelType channel)
\r
635 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_ENABLEWAKEUP_SERVICE_ID, GPT_E_UNINIT );
\r
636 VALIDATE( VALID_CHANNEL(channel),GPT_ENABLEWAKEUP_SERVICE_ID, GPT_E_PARAM_CHANNEL );
\r
637 if (channel == GPT_CHANNEL_RTI)
\r
639 Gpt_Global.wakeupEnabled = STD_ON;
\r
648 void Gpt_Cbk_CheckWakeup(EcuM_WakeupSourceType wakeupSource)
\r