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
22 #if defined(USE_KERNEL)
\r
27 #include "stm32f10x.h"
\r
34 /* -------------------------------- Arctic Core ------------------------------
\r
35 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
37 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\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
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
47 * -------------------------------- Arctic Core ------------------------------*/
\r
56 #include "Std_Types.h"
\r
63 #if defined(USE_KERNEL)
\r
68 // Implementation specific
\r
69 /* STM32 helper arrays
\r
72 TIM_TypeDef * const TimAddr[] =
\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
83 #if ( GPT_DEV_ERROR_DETECT == STD_ON )
\r
84 #define VALIDATE(_exp,_api,_err ) \
\r
86 Det_ReportError(MODULE_ID_GPT,0,_api,_err); \
\r
90 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
92 Det_ReportError(MODULE_ID_GPT,0,_api,_err); \
\r
96 #define VALID_CHANNEL(_ch) ( Gpt_Global.configured & (1<<(_ch)) )
\r
99 #define VALIDATE(_exp,_api,_err )
\r
100 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
103 const uint32 IrqVector[] =
\r
113 GPT_STATE_STOPPED = 0,
\r
118 * Type that holds all global data for Gpt
\r
122 // Set if Gpt_Init() have been called
\r
126 const Gpt_ConfigType *config;
\r
128 uint8 wakeupEnabled;
\r
130 // One bit for each channel that is configured.
\r
131 // Used to determine if validity of a channel
\r
133 // 0 - NOT configured
\r
136 // Maps the a channel id to a configured channel id
\r
137 uint8 channelMap[GPT_CHANNEL_CNT];
\r
142 * Type that holds data that are specific for a channel
\r
146 Gpt_StateType state;
\r
149 Gpt_UnitType Gpt_Unit[GPT_CHANNEL_CNT];
\r
152 Gpt_GlobalType Gpt_Global;
\r
154 //-------------------------------------------------------------------
\r
158 * ISR helper-function that handles the HW channels( 0 to 8 )
\r
160 * @param channel - Channel that the raised the interrupt
\r
162 static void Gpt_IsrCh(Gpt_ChannelType channel)
\r
164 const Gpt_ConfigType *config;
\r
167 confCh = Gpt_Global.channelMap[channel];
\r
168 assert(confCh != GPT_CHANNEL_ILL);
\r
170 config = &Gpt_Global.config[confCh];
\r
172 if (config->GptChannelMode == GPT_MODE_ONESHOT)
\r
174 // Disable the channel
\r
175 TimAddr[channel]->CR1 &= ~TIM_CR1_CEN;
\r
177 Gpt_Unit[channel].state = GPT_STATE_STOPPED;
\r
179 config->GptNotification();
\r
182 TimAddr[channel]->SR &= ~TIM_SR_UIF;
\r
185 //-------------------------------------------------------------------
\r
186 // Macro that counts leading zeroes.
\r
187 #define CNTLZW_INV(x) (31-cntlzw(x))
\r
190 * ISR that handles all interrupts
\r
192 static void Gpt_Isr(void)
\r
196 /* Find channel for this interrupt. */
\r
197 for (i = 0; ((i < GPT_CHANNEL_CNT) && !found);i++)
\r
199 found = (((TimAddr[i]->SR & TIM_SR_UIF) == TIM_SR_UIF) &&
\r
200 ((TimAddr[i]->CR1 & TIM_CR1_CEN) == TIM_CR1_CEN));
\r
207 //-------------------------------------------------------------------
\r
209 void Gpt_Init(const Gpt_ConfigType *config)
\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
220 Gpt_ChannelType ch;
\r
222 for (i=0; i<GPT_CHANNEL_CNT; i++)
\r
224 Gpt_Global.channelMap[i] = GPT_CHANNEL_ILL;
\r
229 while (cfg->GptChannelId != GPT_CHANNEL_ILL)
\r
231 ch = cfg->GptChannelId;
\r
233 // Assign the configuration channel used later..
\r
234 Gpt_Global.channelMap[cfg->GptChannelId] = i;
\r
235 Gpt_Global.configured |= (1<<ch);
\r
237 if (ch <= GPT_CHANNEL_CNT)
\r
239 if (cfg->GptNotification != NULL)
\r
242 #if defined(USE_KERNEL)
\r
244 tid = Os_Arc_CreateIsr(Gpt_Isr, 6, "Gpt_Isr");
\r
245 Irq_AttachIsr2(tid, NULL, IrqVector[ch]);
\r
247 //IntCtrl_InstallVector(Gpt_Isr, PIT_PITFLG_RTIF + ch, 1, CPU_Z1); TODO
\r
251 #if defined(USE_KERNEL)
\r
252 // Don't install if we use kernel.. it handles that.
\r
261 Gpt_Global.config = config;
\r
263 Gpt_Global.initRun = STD_ON;
\r
264 //PIT.CTRL.B.MDIS = 0;
\r
267 //-------------------------------------------------------------------
\r
269 #if GPT_DEINIT_API == STD_ON
\r
270 void Gpt_DeInit(void)
\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
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
279 Gpt_Global.initRun = STD_OFF;
\r
280 Gpt_Global.configured = 0;
\r
281 //_config.config = NULL;
\r
285 //-------------------------------------------------------------------
\r
286 // period is in "ticks" !!
\r
287 void Gpt_StartTimer(Gpt_ChannelType channel, Gpt_ValueType period_ticks)
\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
296 //DEBUG(DEBUG_HIGH, "Gpt_StartTimer ch=%d, period=%d [ticks]\n", channel, period_ticks);
\r
298 confCh = Gpt_Global.channelMap[channel];
\r
300 if (channel <= GPT_CHANNEL_CNT)
\r
302 uint32 *tlval = (uint32 *)&(TimAddr[channel]->ARR);
\r
303 uint32 *tval = (uint32 *)&(TimAddr[channel]->CNT);
\r
305 *tlval = period_ticks;
\r
306 *tval = period_ticks;
\r
308 // always select interrupt
\r
309 //TimAddr[channel]->DIER |= TIM_DIER_UIE;
\r
311 // Make sure that no interrupt is pending.
\r
312 TimAddr[channel]->SR &= ~TIM_SR_UIF;
\r
315 TimAddr[channel]->PSC = Gpt_Global.config[confCh].GptChannelPrescale;
\r
318 TimAddr[channel]->CR1 |= (TIM_CR1_CEN | TIM_CR1_URS | TIM_CR1_DIR);
\r
319 TimAddr[channel]->CR1 &= ~TIM_CR1_UDIS;
\r
321 #if ( GPT_ENABLE_DISABLE_NOTIFICATION_API == STD_ON )
\r
322 if( Gpt_Global.config[confCh].GptNotification != NULL )
\r
325 Gpt_EnableNotification(channel);
\r
328 Gpt_Unit[channel].state = GPT_STATE_STARTED;
\r
331 void Gpt_StopTimer(Gpt_ChannelType channel)
\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
337 if (channel <= GPT_CHANNEL_CNT)
\r
340 TimAddr[channel]->CR1 &= ~TIM_CR1_CEN;
\r
342 #if ( GPT_ENABLE_DISABLE_NOTIFICATION_API == STD_ON )
\r
343 Gpt_DisableNotification(channel);
\r
345 Gpt_Unit[channel].state = GPT_STATE_STOPPED;
\r
348 #if ( GPT_TIME_REMAINING_API == STD_ON )
\r
350 Gpt_ValueType Gpt_GetTimeRemaining(Gpt_ChannelType channel)
\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
357 if (channel <= GPT_CHANNEL_CNT)
\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
368 #if ( GPT_TIME_ELAPSED_API == STD_ON )
\r
369 Gpt_ValueType Gpt_GetTimeElapsed(Gpt_ChannelType channel)
\r
371 Gpt_ValueType timer;
\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
378 // These little creatures count down
\r
380 if (channel <= GPT_CHANNEL_CNT)
\r
382 uint32 *tlval = (uint32 *)&(TimAddr[channel]->ARR);
\r
383 uint32 *tval = (uint32 *)&(TimAddr[channel]->CNT);
\r
384 timer = *tlval - *tval;
\r
391 #if ( GPT_ENABLE_DISABLE_NOTIFICATION_API == STD_ON )
\r
392 void Gpt_EnableNotification(Gpt_ChannelType channel)
\r
395 VALIDATE( (Gpt_Global.initRun == STD_ON), 0x7, GPT_E_UNINIT );
\r
396 VALIDATE( VALID_CHANNEL(channel),0x7, GPT_E_PARAM_CHANNEL );
\r
398 if (channel <= GPT_CHANNEL_CNT)
\r
400 // enable interrupts
\r
401 TimAddr[channel]->DIER |= TIM_DIER_UIE;
\r
405 void Gpt_DisableNotification(Gpt_ChannelType channel)
\r
408 VALIDATE( (Gpt_Global.initRun == STD_ON), 0x8, GPT_E_UNINIT );
\r
409 VALIDATE( VALID_CHANNEL(channel),0x8, GPT_E_PARAM_CHANNEL );
\r
411 if (channel <= GPT_CHANNEL_CNT)
\r
413 TimAddr[channel]->DIER &= ~TIM_DIER_UIE;
\r
421 #if ( GPT_WAKEUP_FUNCTIONALITY_API == STD_ON )
\r
423 void Gpt_SetMode(Gpt_ModeType mode)
\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
430 if (mode == GPT_MODE_NORMAL)
\r
432 //PIT.CTRL.B.MDIS = 0; TODO
\r
433 // Do NOT restart channels
\r
435 else if (mode == GPT_MODE_SLEEP)
\r
438 //PIT.CTRL.B.MDIS = 1; TODO
\r
440 for (i= 0; i <= GPT_CHANNEL_CNT; i++)
\r
447 void Gpt_DisableWakeup(Gpt_ChannelType channel)
\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
454 Gpt_Global.wakeupEnabled = STD_OFF;
\r
463 void Gpt_EnableWakeup(Gpt_ChannelType channel)
\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
469 Gpt_Global.wakeupEnabled = STD_ON;
\r
478 void Gpt_Cbk_CheckWakeup(EcuM_WakeupSourceType wakeupSource)
\r