SCTimer Falling Edge Event Not Consistently Firing

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

SCTimer Falling Edge Event Not Consistently Firing

1,539 Views
use
Contributor II

I am currently attempting to use the SCTimer on the LPC54606 to measure pulse widths. The state registers are configured so that when a rising edge occurs, the state moves to 1. When in state 1, a falling edge event is allowed. This event lowers the state back to 0 and triggers an interrupt where I grab the counter data and reset it. This seems to work about 80% of the time but it is occasionally missing the falling edge and so the state remains in state 1. Even with slow pulses (0.5 ms on, 0.5 ms off) it is missing edges and the event doesn't fire. Has anybody else experienced this?

Thanks

Labels (1)
5 Replies

1,161 Views
timcarney
Contributor II

I believe I have seen similar behavior. My issue has been reported here: https://community.nxp.com/message/1062204 

0 Kudos

1,161 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,

Thank you for your interest in NXP Semiconductor products and 
the opportunity to serve you.
I was wondering if you can share the demo code which can replicate the phenomenon.

Have a great day,
TIC

 

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!

0 Kudos

1,161 Views
use
Contributor II

I am using the high counter for the edge detection counter and the low (currently unused) for PWM generation.

sctimer_event_callback_t sctimer_callback_table = { SCT_Detection_Callback };

void PulseDetection_Init(void)
{

   sctimer_config_t sctimerInfo;

   SCTIMER_GetDefaultConfig(&sctimerInfo);
   sctimerInfo.enableCounterUnify = FALSE;
   SCTIMER_Init(SCT0, &sctimerInfo);

   INPUTMUX->SCT0_INMUX[2] = 0x2; //GPIO0_2

   uint32_t risingEdge_Event;
   uint32_t fallingEdge_Event;
   //Create an event for rising edge //kSCTIMER_InputLowEvent kSCTIMER_InputFallEvent
   SCTIMER_CreateAndScheduleEvent(SCT0,kSCTIMER_InputRiseEvent,0,2,kSCTIMER_Counter_H,&risingEdge_Event);
   SCTIMER_CreateAndScheduleEvent(SCT0,kSCTIMER_InputFallEvent,0,2,kSCTIMER_Counter_H,&fallingEdge_Event);

   //Start counter when Rising Edge occurs
   SCTIMER_SetupCounterStartAction(SCT0,kSCTIMER_Counter_H,risingEdge_Event);
   SCTIMER_SetupNextStateAction(SCT0,1,risingEdge_Event); //not working as expected

   //HALT counter when falling edge occurs
   SCTIMER_SetupCounterHaltAction(SCT0,kSCTIMER_Counter_H,fallingEdge_Event);

   //Set callback for interrupt
   SCTIMER_SetCallback(SCT0, sctimer_callback_table, fallingEdge_Event);

   SCTIMER_EnableInterrupts(SCT0,1<<fallingEdge_Event);
   NVIC_SetPriority(SCT0_IRQn, IRQ_PRIORITY_CTIMER);

   SCT0->EVENT[risingEdge_Event].CTRL |= 0x0000C010; //set state to 1 after this event occurs and HEVENT to 1
   SCT0->EVENT[fallingEdge_Event].CTRL |= 0x00004010; //set state to 0 after this event occurs

   NVIC_EnableIRQ(SCT0_IRQn);

   //SCTIMER_StartTimer(SCT0,kSCTIMER_Counter_H);

   SCT0->EVENT[risingEdge_Event].STATE = 0x00000001; //enable rising egde in state 0
   SCT0->EVENT[fallingEdge_Event].STATE = 0x00000002; //enable falling edge in state 1

   uint32_t CTRL_Enable_Event = SCT0->CTRL;

   CTRL_Enable_Event &= (~(SCT_CTRL_HALT_H_MASK) ); //clear halt H bit
   CTRL_Enable_Event |= SCT_CTRL_STOP_H_MASK; //set stop H bit

   SCT0->CTRL = CTRL_Enable_Event; //Write both changes at once

   SCT0->CTRL |= (1<<19);//clear counter
}

void SCT_Detection_Callback(void)
{

   widths[count++] = (SCT0->COUNT) >> 16; //add width value to array

   SCT0->CTRL |= (1<<19);//clear counter

   uint32_t CTRL_Enable_Event = SCT0->CTRL;
   CTRL_Enable_Event &= (~(SCT_CTRL_HALT_H_MASK) ); //clear halt H bit
   CTRL_Enable_Event |= SCT_CTRL_STOP_H_MASK; //set stop H bit
   SCT0->CTRL = CTRL_Enable_Event; //Write both changes at once
}

0 Kudos

1,161 Views
jeremyzhou
NXP Employee
NXP Employee

Hi use,

In my honest, your coding style will make some troubles for you in future and it takes me some time to figure it out.

And I've simplified your code which is illustrated below, please giving it a try.

/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright 2016-2017 NXP
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * o Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "fsl_debug_console.h"
#include "board.h"
#include "fsl_sctimer.h"

#include "pin_mux.h"
#include "fsl_inputmux.h"
#include <stdbool.h>
/*******************************************************************************
 * Definitions
 ******************************************************************************/

#define BUS_CLK_FREQ CLOCK_GetFreq(kCLOCK_BusClk)


/*******************************************************************************
 * Prototypes
 ******************************************************************************/
sctimer_event_callback_t sctimer_callback_table={SCT_Detection_Callback};


uint32_t widths;

void SCT_Detection_Callback(void)
{

  widths = SCT0->COUNT;

   SCT0->CTRL |= (1<<19);//clear counter

   uint32_t CTRL_Enable_Event = SCT0->CTRL;
   CTRL_Enable_Event &= (~(SCT_CTRL_HALT_H_MASK) ); //clear halt H bit
   CTRL_Enable_Event |= SCT_CTRL_STOP_H_MASK; //set stop H bit
   SCT0->CTRL = CTRL_Enable_Event; //Write both changes at once
}





/*******************************************************************************
 * Code
 ******************************************************************************/
/*!
 * @brief Main function
 */
int main(void)
{
    sctimer_config_t sctimerInfo;

    uint32_t stateNumber;
    uint32_t eventNumberInput, eventNumberInputPlus;
    uint32_t sctimerClock;

    /* Board pin, clock, debug console init */
    CLOCK_EnableClock(kCLOCK_Gpio0);
    CLOCK_EnableClock(kCLOCK_Gpio3);
    /* attach 12 MHz clock to FLEXCOMM0 (debug console) */
    CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);

    /* configure the input mux for the sct timer input1 from external pin*/
    INPUTMUX_Init(INPUTMUX);
    INPUTMUX_AttachSignal(INPUTMUX, 1U, kINPUTMUX_SctGpi6ToSct0);

    BOARD_InitPins();
    BOARD_BootClockFROHF48M();
    BOARD_InitDebugConsole();

    sctimerClock = BUS_CLK_FREQ;

    /* Print a note to terminal */
    PRINTF("\r\nSCTimer example\r\n");

    /* Default configuration operates the counter in 32-bit mode */
    SCTIMER_GetDefaultConfig(&sctimerInfo);

    /* Initialize SCTimer module */
    SCTIMER_Init(SCT0, &sctimerInfo);

    stateNumber = SCTIMER_GetCurrentState(SCT0);

    /* Schedule an event to look for a rising edge on input 1 in this state */
    if (SCTIMER_CreateAndScheduleEvent(SCT0, kSCTIMER_InputRiseEvent, 0, kSCTIMER_Input_1, kSCTIMER_Counter_L,
                                       &eventNumberInput) == kStatus_Fail)
    {
        return -1;
    }

    /* Transition to next state when a rising edge is detected on input 1 */
    SCTIMER_SetupNextStateAction(SCT0, stateNumber + 1, eventNumberInput);

    /* Go to next state; State 1 */
    SCTIMER_IncreaseState(SCT0);

    /* Schedule an event to look for a rising edge on input 1 in this state */
    if (SCTIMER_CreateAndScheduleEvent(SCT0, kSCTIMER_InputFallEvent, 0, kSCTIMER_Input_1, kSCTIMER_Counter_L,
                                       &eventNumberInputPlus) == kStatus_Fail)
    {
        return -1;
    }

    /* Transition to next state when a rising edge is detected on input 1 */
    SCTIMER_SetupNextStateAction(SCT0, stateNumber - 2, eventNumberInputPlus);

    //HALT counter when falling edge occurs
     SCTIMER_SetupCounterHaltAction(SCT0,kSCTIMER_Counter_L,eventNumberInputPlus);

     SCTIMER_SetCallback(SCT0, sctimer_callback_table, eventNumberInputPlus);

     SCTIMER_EnableInterrupts(SCT0,1<<eventNumberInputPlus);


     NVIC_EnableIRQ(SCT0_IRQn);


    /* Start the timer, use counter L as we are operating counter in 32-bit mode */
    SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_L);


    while (1)
    {
    }
}

TIC

 

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!

 

0 Kudos

843 Views
TPN_CHN
Contributor II

Dear Sir,

Above method trying is not work.

i got assert failed following error.

ASSERT ERROR " C:\Users\XXXX\Documents\MCUXpressoIDE_11.5.0_7232\workspace\lpcxpresso54628_ctimer_pwm_example\drivers/fsl_sctimer.h:1058 : 0U == (base->CONFIG & SCT_CONFIG_UNIFY_MASK)

My code :

#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "board.h"
#include "fsl_ctimer.h"
#include "fsl_sctimer.h"
#include "fsl_inputmux.h"
#include <stdbool.h>
/*******************************************************************************
* Definitions
******************************************************************************/
#define CTIMER CTIMER1 /* Timer 1 */
#define CTIMER_MAT_OUT kCTIMER_Match_1 /* Match output 1 */
#define CTIMER_CLK_FREQ CLOCK_GetFreq(kCLOCK_BusClk)
#ifndef CTIMER_MAT_PWM_PERIOD_CHANNEL
#define CTIMER_MAT_PWM_PERIOD_CHANNEL kCTIMER_Match_3
#endif
#define BUS_CLK_FREQ CLOCK_GetFreq(kCLOCK_BusClk)


void SCT_Detection_Callback(void);

/*******************************************************************************
* Prototypes
******************************************************************************/

/*******************************************************************************
* Variables
******************************************************************************/
volatile uint32_t g_pwmPeriod = 0U;
volatile uint32_t g_pulsePeriod = 0U;

/*******************************************************************************
* Code
******************************************************************************/
status_t CTIMER_GetPwmPeriodValue(uint32_t pwmFreqHz, uint8_t dutyCyclePercent, uint32_t timerClock_Hz)
{
/* Calculate PWM period match value */
g_pwmPeriod = (timerClock_Hz / pwmFreqHz) - 1U;

/* Calculate pulse width match value */
g_pulsePeriod = (g_pwmPeriod + 1U) * (100 - dutyCyclePercent) / 100;

return kStatus_Success;
}

sctimer_event_callback_t sctimer_callback_table={SCT_Detection_Callback};


uint32_t widths;

void SCT_Detection_Callback(void)
{

widths = SCT0->COUNT;

SCT0->CTRL |= (1<<19);//clear counter

uint32_t CTRL_Enable_Event = SCT0->CTRL;
CTRL_Enable_Event &= (~(SCT_CTRL_HALT_H_MASK) ); //clear halt H bit
CTRL_Enable_Event |= SCT_CTRL_STOP_H_MASK; //set stop H bit
SCT0->CTRL = CTRL_Enable_Event; //Write both changes at once
}

/*!
* @brief Main function
*/
int main(void)
{
ctimer_config_t config;
uint32_t srcClock_Hz;
uint32_t timerClock;

sctimer_config_t sctimerInfo;

uint32_t stateNumber;
uint32_t eventNumberInput, eventNumberInputPlus;
uint32_t sctimerClock;


/* Init hardware*/
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);

/* Enable the asynchronous bridge */
SYSCON->ASYNCAPBCTRL = 1;

/* Use 12 MHz clock for some of the Ctimers */
CLOCK_AttachClk(kFRO12M_to_ASYNC_APB);

BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();

/* CTimer0 counter uses the AHB clock, some CTimer1 modules use the Aysnc clock */
srcClock_Hz = CTIMER_CLK_FREQ;

PRINTF("CTimer example to generate a PWM signal\r\n");

CTIMER_GetDefaultConfig(&config);
timerClock = srcClock_Hz / (config.prescale + 1);

CTIMER_Init(CTIMER, &config);

/* Get the PWM period match value and pulse width match value of 20Khz PWM signal with 20% dutycycle */
CTIMER_GetPwmPeriodValue(20000, 20, timerClock);
CTIMER_SetupPwmPeriod(CTIMER, CTIMER_MAT_PWM_PERIOD_CHANNEL, CTIMER_MAT_OUT, g_pwmPeriod, g_pulsePeriod, false);
CTIMER_StartTimer(CTIMER);

#if 1
sctimerClock = BUS_CLK_FREQ;
sctimerInfo.enableCounterUnify = 0;
sctimerInfo.inputsync = 1<<1;
SCTIMER_GetDefaultConfig(&sctimerInfo);

/* Initialize SCTimer module */
SCTIMER_Init(SCT0, &sctimerInfo);

stateNumber = SCTIMER_GetCurrentState(SCT0);

/* Schedule an event to look for a rising edge on input 1 in this state */
if (SCTIMER_CreateAndScheduleEvent(SCT0, kSCTIMER_InputRiseEvent, 0, kSCTIMER_Input_1, kSCTIMER_Counter_L,
&eventNumberInput) == kStatus_Fail)
{
return -1;
}

/* Transition to next state when a rising edge is detected on input 1 */
SCTIMER_SetupNextStateAction(SCT0, stateNumber + 1, eventNumberInput);

/* Go to next state; State 1 */
SCTIMER_IncreaseState(SCT0);

/* Schedule an event to look for a rising edge on input 1 in this state */
if (SCTIMER_CreateAndScheduleEvent(SCT0, kSCTIMER_InputFallEvent, 0, kSCTIMER_Input_1, kSCTIMER_Counter_L,
&eventNumberInputPlus) == kStatus_Fail)
{
return -1;
}

/* Transition to next state when a rising edge is detected on input 1 */
SCTIMER_SetupNextStateAction(SCT0, stateNumber - 2, eventNumberInputPlus);

//HALT counter when falling edge occurs
SCTIMER_SetupCounterHaltAction(SCT0,kSCTIMER_Counter_L,eventNumberInputPlus);

SCTIMER_SetCallback(SCT0, sctimer_callback_table, eventNumberInputPlus);

SCTIMER_EnableInterrupts(SCT0,1<<eventNumberInputPlus);


NVIC_EnableIRQ(SCT0_IRQn);


/* Start the timer, use counter L as we are operating counter in 32-bit mode */
SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_L);

#endif

 

 

 

while (1)
{
}
}

 

Please advise

Thanks

 

 

Tags (1)
0 Kudos