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
18 #include "Std_Types.h"
\r
26 #if defined(USE_DET)
\r
33 #define FIRST_OC_REG 0x50
\r
35 // Implementation specific
\r
37 #if ( GPT_DEV_ERROR_DETECT == STD_ON )
\r
38 #define VALIDATE(_exp,_api,_err ) \
\r
40 Det_ReportError(MODULE_ID_GPT,0,_api,_err); \
\r
44 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
46 Det_ReportError(MODULE_ID_GPT,0,_api,_err); \
\r
50 #define VALID_CHANNEL(_ch) ( Gpt_Global.configured & (1<<(_ch)) )
\r
53 #define VALIDATE(_exp,_api,_err )
\r
54 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
59 GPT_STATE_STOPPED = 0,
\r
64 * Type that holds all global data for Gpt
\r
68 // Set if Gpt_Init() have been called
\r
72 const Gpt_ConfigType *config;
\r
74 uint8 wakeupEnabled;
\r
76 // One bit for each channel that is configured.
\r
77 // Used to determine if validity of a channel
\r
79 // 0 - NOT configured
\r
82 // Maps the a channel id to a configured channel id
\r
83 uint8 channelMap[GPT_CHANNEL_CNT];
\r
88 * Type that holds data that are specific for a channel
\r
92 Gpt_StateType state;
\r
96 // Holds the enable/disable status of notifications.
\r
97 uint8 GptNotificationStatuses[8] = {
\r
108 uint16 GptPeriods[GPT_CHANNEL_CNT];
\r
110 #if (GPT_TIME_ELAPSED_API == STD_ON)
\r
111 uint16 GptPrevOc[GPT_CHANNEL_CNT];
\r
115 Gpt_UnitType Gpt_Unit[GPT_CHANNEL_CNT];
\r
118 Gpt_GlobalType Gpt_Global;
\r
120 //-------------------------------------------------------------------
\r
124 * ISR helper-function that handles the HW channels( 0 to 8 )
\r
126 * @param channel - Channel that the raised the interrupt
\r
128 static void Gpt_IsrCh(Gpt_ChannelType channel)
\r
130 const Gpt_ConfigType *config;
\r
133 confCh = Gpt_Global.channelMap[channel];
\r
134 assert(confCh != GPT_CHANNEL_ILL);
\r
136 config = &Gpt_Global.config[confCh];
\r
138 if (GptNotificationStatuses[channel] == STD_ON) {
\r
139 config->GptNotification();
\r
142 if (config->GptChannelMode == GPT_MODE_ONESHOT)
\r
144 // Disable the channel
\r
145 Gpt_StopTimer(channel);
\r
146 Gpt_Unit[channel].state = GPT_STATE_STOPPED;
\r
149 // Start the next period.
\r
150 uint16 curr_oc = PORTIO_16((FIRST_OC_REG + (2 * channel)));
\r
151 PORTIO_16((FIRST_OC_REG + (2*channel))) = curr_oc + GptPeriods[channel];
\r
153 #if (GPT_TIME_ELAPSED_API == STD_ON)
\r
154 GptPrevOc[channel] = curr_oc;
\r
160 //-------------------------------------------------------------------
\r
161 // Macro that counts leading zeroes.
\r
162 #define CNTLZW_INV(x) (31-cntlzw(x))
\r
166 * ISR that handles all interrupts to the PIT channels
\r
167 * ( NOT the decrementer )
\r
169 #define DECLARE_GPT_ISR_PROTOTYPE(x) \
\r
170 void Gpt_Isr_##x (void) { \
\r
174 #define GPT_IRQ_TYPE(x) IRQ_TYPE_TC(x)
\r
176 DECLARE_GPT_ISR_PROTOTYPE(0)
\r
177 DECLARE_GPT_ISR_PROTOTYPE(1)
\r
178 DECLARE_GPT_ISR_PROTOTYPE(2)
\r
179 DECLARE_GPT_ISR_PROTOTYPE(3)
\r
180 DECLARE_GPT_ISR_PROTOTYPE(4)
\r
181 DECLARE_GPT_ISR_PROTOTYPE(5)
\r
182 DECLARE_GPT_ISR_PROTOTYPE(6)
\r
183 DECLARE_GPT_ISR_PROTOTYPE(7)
\r
186 //-------------------------------------------------------------------
\r
188 void Gpt_Init(const Gpt_ConfigType *config)
\r
191 const Gpt_ConfigType *cfg;
\r
192 VALIDATE( (Gpt_Global.initRun == STD_OFF), GPT_INIT_SERVICE_ID, GPT_E_ALREADY_INITIALIZED );
\r
193 VALIDATE( (config != NULL ), GPT_INIT_SERVICE_ID, GPT_E_PARAM_CONFIG );
\r
195 Gpt_ChannelType ch;
\r
197 for (i=0; i<GPT_CHANNEL_CNT; i++)
\r
199 Gpt_Global.channelMap[i] = GPT_CHANNEL_ILL;
\r
204 while (cfg->GptChannelId != GPT_CHANNEL_ILL)
\r
206 ch = cfg->GptChannelId;
\r
208 // Assign the configuration channel used later..
\r
209 Gpt_Global.channelMap[cfg->GptChannelId] = i;
\r
210 Gpt_Global.configured |= (1<<ch);
\r
212 if (ch <= GPT_CHANNEL_7)
\r
214 if (cfg->GptNotification != NULL)
\r
218 ISR_INSTALL_ISR2("Gpt_Isr_0",Gpt_Isr_0,IRQ_NR_TC0,1,0);
\r
221 ISR_INSTALL_ISR2("Gpt_Isr_1",Gpt_Isr_1,IRQ_NR_TC1,1,0);
\r
224 ISR_INSTALL_ISR2("Gpt_Isr_2",Gpt_Isr_2,IRQ_NR_TC2,1,0);
\r
227 ISR_INSTALL_ISR2("Gpt_Isr_3",Gpt_Isr_3,IRQ_NR_TC3,1,0);
\r
230 ISR_INSTALL_ISR2("Gpt_Isr_4",Gpt_Isr_4,IRQ_NR_TC4,1,0);
\r
233 ISR_INSTALL_ISR2("Gpt_Isr_5",Gpt_Isr_5,IRQ_NR_TC5,1,0);
\r
236 ISR_INSTALL_ISR2("Gpt_Isr_6",Gpt_Isr_6,IRQ_NR_TC6,1,0);
\r
239 ISR_INSTALL_ISR2("Gpt_Isr_7",Gpt_Isr_7,IRQ_NR_TC7,1,0);
\r
249 Gpt_Global.config = config;
\r
251 Gpt_Global.initRun = STD_ON;
\r
253 TSCR1 |= TEN; // Turn timer on.
\r
256 //-------------------------------------------------------------------
\r
258 #if GPT_DEINIT_API == STD_ON
\r
259 void Gpt_DeInit(void)
\r
261 Gpt_ChannelType channel;
\r
262 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_DEINIT_SERVICE_ID, GPT_E_UNINIT );
\r
263 for (channel=0; channel<GPT_CHANNEL_CNT; channel++) // Validate that all channels have been stopped
\r
265 VALIDATE( (Gpt_Unit[channel].state == GPT_STATE_STOPPED), GPT_DEINIT_SERVICE_ID, GPT_E_BUSY );
\r
266 Gpt_StopTimer(channel); // Should this be done here?
\r
268 Gpt_Global.initRun = STD_OFF;
\r
269 Gpt_Global.configured = 0;
\r
270 TSCR1 &= ~TEN; // Turn timer off.
\r
271 //_config.config = NULL;
\r
275 //-------------------------------------------------------------------
\r
276 // period is in "ticks" !!
\r
277 void Gpt_StartTimer(Gpt_ChannelType channel, Gpt_ValueType period_ticks)
\r
281 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_STARTTIMER_SERVICE_ID, GPT_E_UNINIT );
\r
282 VALIDATE( VALID_CHANNEL(channel), GPT_STARTTIMER_SERVICE_ID, GPT_E_PARAM_CHANNEL );
\r
283 VALIDATE( (Gpt_Unit[channel].state == GPT_STATE_STOPPED), GPT_STARTTIMER_SERVICE_ID, GPT_E_BUSY );
\r
284 // GPT_E_PARAM_VALUE, all have 32-bit so no need to check
\r
286 DEBUG(DEBUG_HIGH, "Gpt_StartTimer ch=%d, period=%d [ticks]\n", channel, period_ticks);
\r
288 confCh = Gpt_Global.channelMap[channel];
\r
290 if (channel <= GPT_CHANNEL_7) {
\r
294 // Setup channel for output compare (OC).
\r
295 TIOS |= (1 << channel);
\r
297 // Enable interrupt for timer
\r
298 TIE |= (1 << channel);
\r
301 uint16 curr_cnt = TCNT;
\r
302 PORTIO_16((FIRST_OC_REG + (2*channel))) = curr_cnt + period_ticks;
\r
304 #if (GPT_TIME_ELAPSED_API == STD_ON)
\r
305 GptPrevOc[channel] = curr_cnt;
\r
309 #if ( GPT_ENABLE_DISABLE_NOTIFICATION_API == STD_ON )
\r
310 if( Gpt_Global.config[confCh].GptNotification != NULL )
\r
313 Gpt_EnableNotification(channel);
\r
317 GptPeriods[channel] = period_ticks;
\r
318 Gpt_Unit[channel].state = GPT_STATE_STARTED;
\r
321 void Gpt_StopTimer(Gpt_ChannelType channel)
\r
324 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_STOPTIMER_SERVICE_ID, GPT_E_UNINIT );
\r
325 VALIDATE( VALID_CHANNEL(channel), GPT_STOPTIMER_SERVICE_ID, GPT_E_PARAM_CHANNEL );
\r
327 if (channel <= GPT_CHANNEL_7)
\r
329 TIE &= ~(1 << channel);
\r
332 #if ( GPT_ENABLE_DISABLE_NOTIFICATION_API == STD_ON )
\r
333 Gpt_DisableNotification(channel);
\r
336 Gpt_Unit[channel].state = GPT_STATE_STOPPED;
\r
340 #if ( GPT_TIME_REMAINING_API == STD_ON )
\r
341 Gpt_ValueType Gpt_GetTimeRemaining(Gpt_ChannelType channel)
\r
343 VALIDATE_W_RV( (Gpt_Global.initRun == STD_ON), GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_UNINIT, 0 );
\r
344 VALIDATE_W_RV( VALID_CHANNEL(channel),GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_PARAM_CHANNEL, 0 );
\r
345 VALIDATE_W_RV( (Gpt_Unit[channel].state == GPT_STATE_STARTED), GPT_GETTIMEREMAINING_SERVICE_ID, GPT_E_NOT_STARTED, 0 );
\r
346 Gpt_ValueType remaining = 0;
\r
348 if (channel <= GPT_CHANNEL_7)
\r
351 uint16 next = PORTIO_16((FIRST_OC_REG + (2*channel)));
\r
353 remaining = next - now;
\r
356 remaining = next + (0xFF - now) ;
\r
364 #if ( GPT_TIME_ELAPSED_API == STD_ON )
\r
365 Gpt_ValueType Gpt_GetTimeElapsed(Gpt_ChannelType channel)
\r
367 Gpt_ValueType elapsed = 0;
\r
369 VALIDATE_W_RV( (Gpt_Global.initRun == STD_ON), GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_UNINIT ,0 );
\r
370 VALIDATE_W_RV( VALID_CHANNEL(channel),GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_PARAM_CHANNEL, 0 );
\r
371 VALIDATE_W_RV( (Gpt_Unit[channel].state == GPT_STATE_STARTED),GPT_GETTIMEELAPSED_SERVICE_ID, GPT_E_NOT_STARTED, 0 );
\r
373 if (channel <= GPT_CHANNEL_7) {
\r
375 if (now > GptPrevOc[channel]) {
\r
376 elapsed = now - GptPrevOc[channel];
\r
379 elapsed = (0xFF - GptPrevOc[channel]) + now;
\r
387 #if ( GPT_ENABLE_DISABLE_NOTIFICATION_API == STD_ON )
\r
388 void Gpt_EnableNotification(Gpt_ChannelType channel)
\r
391 VALIDATE( (Gpt_Global.initRun == STD_ON), 0x7, GPT_E_UNINIT );
\r
392 VALIDATE( VALID_CHANNEL(channel),0x7, GPT_E_PARAM_CHANNEL );
\r
394 if (channel <= GPT_CHANNEL_7)
\r
396 GptNotificationStatuses[channel] = STD_ON;
\r
400 void Gpt_DisableNotification(Gpt_ChannelType channel)
\r
402 VALIDATE( (Gpt_Global.initRun == STD_ON), 0x8, GPT_E_UNINIT );
\r
403 VALIDATE( VALID_CHANNEL(channel),0x8, GPT_E_PARAM_CHANNEL );
\r
405 if (channel <= GPT_CHANNEL_7)
\r
407 GptNotificationStatuses[channel] = STD_OFF;
\r
412 #if ( GPT_WAKEUP_FUNCTIONALITY_API == STD_ON )
\r
414 void Gpt_SetMode(Gpt_ModeType mode)
\r
418 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_SETMODE_SERVIVCE_ID, GPT_E_UNINIT );
\r
419 VALIDATE( ( mode <= GPT_MODE_SLEEP ), GPT_SETMODE_SERVIVCE_ID, GPT_E_PARAM_MODE );
\r
421 if (mode == GPT_MODE_NORMAL)
\r
425 else if (mode == GPT_MODE_SLEEP)
\r
431 void Gpt_DisableWakeup(Gpt_ChannelType channel)
\r
433 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_DISABLEWAKEUP_SERVICE_ID, GPT_E_UNINIT );
\r
434 VALIDATE( VALID_CHANNEL(channel), GPT_DISABLEWAKEUP_SERVICE_ID, GPT_E_PARAM_CHANNEL );
\r
439 void Gpt_EnableWakeup(Gpt_ChannelType channel)
\r
441 VALIDATE( (Gpt_Global.initRun == STD_ON), GPT_ENABLEWAKEUP_SERVICE_ID, GPT_E_UNINIT );
\r
442 VALIDATE( VALID_CHANNEL(channel),GPT_ENABLEWAKEUP_SERVICE_ID, GPT_E_PARAM_CHANNEL );
\r
446 void Gpt_Cbk_CheckWakeup(EcuM_WakeupSourceType wakeupSource)
\r