good mornint
I have the following stub of code for PIT0 use.
void pit0_init( void )
{
PIT_DRV_InstallCallback( 0, THIS_PIT_CHANNEL, pit0_isr_cback );
PIT_DRV_Init( 0, false );
PIT_DRV_InitChannel( 0, THIS_PIT_CHANNEL, &pit0_user_config );
timerBase = 0;
NVIC_SetPriority( g_pitIrqId[ THIS_PIT_CHANNEL ], PIT0_INT_PRIO );
}
void pit0_start( void )
{
PIT_HAL_Enable( g_pitBaseAddr[ 0 ] );
PIT_HAL_SetIntCmd( g_pitBaseAddr[ 0 ], THIS_PIT_CHANNEL, true );
PIT_DRV_StartTimer( 0, THIS_PIT_CHANNEL );
}
void pit0_stop( void )
{
PIT_DRV_StopTimer( 0, THIS_PIT_CHANNEL );
PIT_HAL_Disable( g_pitBaseAddr[ 0 ] );
PIT_HAL_SetIntCmd( g_pitBaseAddr[ 0 ], THIS_PIT_CHANNEL, false );
PIT_HAL_ClearIntFlag( g_pitBaseAddr[ 0 ], THIS_PIT_CHANNEL );
// CLOCK_SYS_DisablePitClock( 0 );
}
If I call the pit0_init() then pit0_start() the timer starts and the interrupt is serviced.
Then I call the pit0_stop(). and again the pit0_start(), the timer does not start...
I need to call again the pit0_init()..
Another think I don t understand is why CLOCK_SYS_DisablePitClock( 0 ) is generating a hardware fault...
I am using the MK02FN128VFM10 cpu.
Suggestions welcome...
Pietro
I was disabling all of the pits with PIT_HAL_Disable( g_pitBaseAddr[ 0 ] ); since the MCR_MDIS will be reset.
Not to do...
Thank You
Hi Pietro
It looks like you are using mbed code. This is very convoluted and so there are multiple subroutine (or in-line) calls to do some simple things (like setting a flag in a register) and I think that it is best if you could also show this code (since it takes a long time to analyse otherwise, especially by non-mbed users).
I have added the PIT code below from the uTasker project as reference so that you can compare with it - it allows single-shot or periodic interrupts on all PITs as well as automatic disabling and power down when possible. It also works on all K, KV, KL, KE parts (handles the variations where needed).
Note that it includes two workarounds for erratas e2682 and e7914 - your K02F needs e2682, although I don't think that it is the reasons for your particular problem; if the mbed code doesn't hande erratas it may however be a reason for subsequent problems.
Regards
Mark
Kinetis: µTasker Kinetis support
Hardware Timers: http://www.utasker.com/docs/uTasker/uTaskerHWTimers.PDF
For the complete "out-of-the-box" Kinetis experience and faster time to market
/*********************************************************************** Mark Butcher Bsc (Hons) MPhil MIET M.J.Butcher Consulting Birchstrasse 20f, CH-5406, Rütihof Switzerland www.uTasker.com Skype: M_J_Butcher --------------------------------------------------------------------- File: kinetis_PIT.h Project: Single Chip Embedded Internet --------------------------------------------------------------------- Copyright (C) M.J.Butcher Consulting 2004..2015 ********************************************************************* */ #if defined _PIT_CODE /* =================================================================== */ /* local function prototype declarations */ /* =================================================================== */ static void fnDisablePIT(int iPIT); /* =================================================================== */ /* local variable definitions */ /* =================================================================== */ static void (*pit_interrupt_handler[PITS_AVAILABLE])(void) = {0}; // user callback for each PIT static unsigned char ucPITmodes = 0; // PIT mode containing flags for all PITs /* =================================================================== */ /* PIT Interrupt Handlers */ /* =================================================================== */ #if defined KINETIS_KL // {76} // KL device PIT have a single interrupt which is shared by all PIT channels // static __interrupt void _PIT_Interrupt(void) { int iChannel = 0; KINETIS_PIT_CTL *ptrCtl = (KINETIS_PIT_CTL *)PIT_CTL_ADD; // set PIT control struture pointer to first PIT do { if ((ptrCtl->PIT_TCTRL & (PIT_TCTRL_TIE | PIT_TCTRL_TEN)) == (PIT_TCTRL_TIE | PIT_TCTRL_TEN)) { // if the channel and its interrupt are enabled WRITE_ONE_TO_CLEAR(ptrCtl->PIT_TFLG, PIT_TFLG_TIF); // clear pending interrupts if ((ucPITmodes & (PIT_PERIODIC << (iChannel * 2))) == 0) { // if not periodic mode (single-shot usage) fnDisablePIT(iChannel); // stop PIT operation and power down when no other activity } uDisable_Interrupt(); pit_interrupt_handler[iChannel](); // call handling function uEnable_Interrupt(); } ptrCtl++; // move to next PIT control structure } while (++iChannel < PITS_AVAILABLE); // for each PIT channel that may be interrupting } #else // Common interrupt handler for all PITs // static void _PIT_Handler(int iPIT) { KINETIS_PIT_CTL *ptrCtl = (KINETIS_PIT_CTL *)PIT_CTL_ADD; ptrCtl += iPIT; WRITE_ONE_TO_CLEAR(ptrCtl->PIT_TFLG, PIT_TFLG_TIF); // clear pending interrupts #if defined ERRATA_ID_2682 // {97} (void)(ptrCtl->PIT_TCTRL); // access and PIT register after clearing the interrupt flag to allow subsequent interrupts to operate #endif if ((ucPITmodes & (PIT_PERIODIC << (iPIT * 2))) == 0) { // if not periodic mode (single-shot usage) fnDisablePIT(iPIT); // stop PIT operation and power down when no other activity } uDisable_Interrupt(); pit_interrupt_handler[iPIT](); // call handling function uEnable_Interrupt(); } static __interrupt void _PIT0_Interrupt(void) { _PIT_Handler(0); } static __interrupt void _PIT1_Interrupt(void) { _PIT_Handler(1); } #if PITS_AVAILABLE > 2 static __interrupt void _PIT2_Interrupt(void) { _PIT_Handler(2); } static __interrupt void _PIT3_Interrupt(void) { _PIT_Handler(3); } #endif #endif // Stop PIT operation and power down when no other activity // static void fnDisablePIT(int iPIT) { KINETIS_PIT_CTL *ptrCtl = (KINETIS_PIT_CTL *)PIT_CTL_ADD; ptrCtl += iPIT; ptrCtl->PIT_TCTRL = 0; // disable the individual PIT uDisable_Interrupt(); // {68} protect the mode variable during modification ucPITmodes &= ~((PIT_SINGLE_SHOT | PIT_PERIODIC) << (iPIT * 2)); // clear the PIT's mode flags #if !defined PIT_TIMER_USED_BY_PERFORMANCE_MONITOR // don't power the PITs down if one is being used for performance monitoring if (ucPITmodes == 0) { // if not PITs are in use power down the PIT module POWER_UP(6, SIM_SCGC6_PIT); // {68} ensure that the module is powered up for the next operation PIT_MCR = PIT_MCR_MDIS; // disable clocks to module since no more timers are active POWER_DOWN(6, SIM_SCGC6_PIT); // power down the PIT module } #endif uEnable_Interrupt(); } #endif #if defined _PIT_CONFIG_CODE // PIT_INTERRUPT case in fnConfigureInterrupt() // { PIT_SETUP *PIT_settings = (PIT_SETUP *)ptrSettings; KINETIS_PIT_CTL *ptrCtl = (KINETIS_PIT_CTL *)PIT_CTL_ADD; unsigned long ulCommand; if (PIT_settings->ucPIT >= PITS_AVAILABLE) { return; } if (PIT_settings->mode & PIT_STOP) { fnDisablePIT(PIT_settings->ucPIT); // stop PIT operation and power down when no other activity return; } pit_interrupt_handler[PIT_settings->ucPIT] = PIT_settings->int_handler; // enter the user handler uDisable_Interrupt(); // {68} protect the mode variable during modification ucPITmodes = ((ucPITmodes & ~((PIT_SINGLE_SHOT | PIT_PERIODIC) << (PIT_settings->ucPIT * 2))) | ((PIT_settings->mode & (PIT_SINGLE_SHOT | PIT_PERIODIC)) << (PIT_settings->ucPIT * 2))); // {2} [the variable protects from power downs from this point] uEnable_Interrupt(); ptrCtl += PIT_settings->ucPIT; // set the PIT to be configured POWER_UP(6, SIM_SCGC6_PIT); // {68} ensure the PIT module is powered up #if defined ERRATA_ID_7914 (void)PIT_MCR; // dummy read of PIT_MCR to guaranty a minimum delay of two bus cycles after enabling the clock gate and not losing next write #endif PIT_MCR = 0; // ensure the PIT module is clocked if (PIT_settings->int_handler != 0) { // if an interrupt is required #if defined KINETIS_KL // {76} KL devices have a single interrupt from the PIT channels fnEnterInterrupt(irq_PIT_ID, PIT_settings->int_priority, _PIT_Interrupt); // ensure that the handler for the PIT module is entered #else switch (PIT_settings->ucPIT) { case 0: fnEnterInterrupt(irq_PIT0_ID, PIT_settings->int_priority, _PIT0_Interrupt); // ensure that the handler for this PIT is entered break; case 1: fnEnterInterrupt(irq_PIT1_ID, PIT_settings->int_priority, _PIT1_Interrupt); // ensure that the handler for this PIT is entered break; #if PITS_AVAILABLE > 2 case 2: fnEnterInterrupt(irq_PIT2_ID, PIT_settings->int_priority, _PIT2_Interrupt); // ensure that the handler for this PIT is entered break; case 3: fnEnterInterrupt(irq_PIT3_ID, PIT_settings->int_priority, _PIT3_Interrupt); // ensure that the handler for this PIT is entered break; #endif } #endif ulCommand = (PIT_TCTRL_TEN | PIT_TCTRL_TIE); } else { ulCommand = (PIT_TCTRL_TEN); // no interrupt used } if (PIT_settings->mode & (PIT_SINGLE_SHOT | PIT_RETRIGGER)) { // single shot always behaves as retriggerable - periodic change at next timeout by default but can be forced with PIT_RETRIGGER ptrCtl->PIT_TCTRL = 0; // {4} disable PIT so that it can be retriggered if needed } ptrCtl->PIT_LDVAL = PIT_settings->count_delay; // load interval value ptrCtl->PIT_TFLG = PIT_TFLG_TIF; // clear pending interrupts if (PIT_settings->mode & PIT_TRIGGER_ADC0_A) { // if the PIT output TIF is to trigger ADC0 conversion on channel A #if defined KINETIS_KE SIM_SOPT0 |= SIM_SOPT_ADHWT_PIT0; // trigger ADC on PIT0 overflow #else SIM_SOPT7 = ((SIM_SOPT7_ADC0TRGSEL_PIT0 + PIT_settings->ucPIT) | SIM_SOPT7_ADC0PRETRGSEL_A | SIM_SOPT7_ADC0ALTTRGEN); // trigger ADC0 channel A #endif } else if (PIT_settings->mode & PIT_TRIGGER_ADC0_B) { // if the PIT output TIF is to trigger ADC0 conversion on channel B #if defined KINETIS_KE SIM_SOPT0 |= SIM_SOPT_ADHWT_PIT0; // trigger ADC on PIT0 overflow #else SIM_SOPT7 = ((SIM_SOPT7_ADC0TRGSEL_PIT0 + PIT_settings->ucPIT) | SIM_SOPT7_ADC0PRETRGSEL_B | SIM_SOPT7_ADC0ALTTRGEN); // trigger ADC0 channel B #endif } ptrCtl->PIT_TCTRL = ulCommand; // start PIT with interrupt enabled, when handler defined #if defined _WINDOWS ptrCtl->PIT_CVAL = ptrCtl->PIT_LDVAL; // load current count value with the load value #endif } #endif