Strange behavior of epit timer - imx6sx m4 core

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

Strange behavior of epit timer - imx6sx m4 core

1,015 Views
alancasinelli
Contributor II

Hello,

I'm currenty running some examples from the mqx rtos 4.1.0 for the imx6sx cortex-m4 core. In particular the hwtimer one. I'm able to run them both from OCRAM and DDR though i'm experiencing problems when the timer interrupt is set to frequencies >= 150kHz.

I modified the sample code of the hwtimer example by using only one timer (BSP_HWTIMER1_DEV = epit1) at a frequency of 150kHz and every time the callback is fired, I will toggle a pin of the board. I should expect a periodic waveform of 75kHz period and 50% duty cicle, instead I see a duty cicle of about 85% (or 15% as sometimes the pin seems like not to toggle at all).

The timer displays the right frequency (24MHz when the perclk is derived from the osc) and the Load register displays the right value 0x9f (159/24MHz = 6,625us).

The strangest thing is that if the code is running from the DDR and the a9 boots up, then the waveform duty cicle and period gets corrected to the right ones.

The same doesn't happen if the code is running from the OCRAM.

I've checked the different clocks configurations and they all seems to be equal, except the pll1 which is derived from the step_clk in linux and from the core clock in the m4.

Thanks for your help.

EDIT: I made some more research about how the clocks and frequecies are set in the BSP library.

I switched the perclk to be derived from the ipg and the frequency displayed is 60MHz instead of 66MHz ( the ahb_clk id derived from pll2_pfd2 with a pll2_pfd2_frac = 24; the ahb_podf and ipg_podf are 3 and 2 respectively, so pll2_pfd2=528*18/24MHz=396MHz, ahb=396/3MHz=132MHz and finally ipg=132/2MHz=66MHz)

Also considering how the divider is set, shouldn't the load register get filled with 0xA0 instead of 0x9f, since 24MHz/150kHz=160=0xA0? Or the epit timer needs 1 clock tick to generate the interrupt after the value has been compared?

Labels (4)
2 Replies

579 Views
Yuri
NXP Employee
NXP Employee

Hello,

  First, to avoid software issues - please check EPIT operation in
hardware mode. I mean special external pin(s) (EPITx_OUT, x=1,2)

toggling (without interrupts).

  Also, please follow recommendations in section 25.5.1 (Change
of Clock Source) in the Reference Manual (IMX6SXRM, Rev 0, 2/2015).


Have a great day,
Yuri

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

579 Views
alancasinelli
Contributor II

Hi,
unfortunately setting the bit 22 of the EPIT_CR register seems not to do anything. I added (0x01 << 22) in the hwtimer_epit.c when the EPIT_CR_REG(epit_base) get set. As far as the 25.5.1 section of the reference manual, it seems to be all right.

I changed the CCM_CSCMR1 register from 0x40 to 0x00 (bit 6 is the perclk_clk_sel; if 0 => derived from ipg; if 1 => derived from osc);
The initialization of the hwtimer is left unchanged from the mqx rtos:

    /* Set the clock source and modes */

    EPIT_CR_REG(epit_base) &= ~(EPIT_CR_EN_MASK | (0x3 << 22) | EPIT_CR_OCIEN_MASK | EPIT_CR_IOVW_MASK | (0x3 << 24) | (0xFFF << 4));

    EPIT_CR_REG(epit_base) |= (EPIT_CR_DBGEN_MASK | EPIT_CR_ENMOD_MASK | EPIT_CR_RLD_MASK ); // i've added (0x1 << 22) here

    EPIT_SR_REG(epit_base) = EPIT_SR_OCIF_MASK;

Later, when the hwtimer_set_freq function is called, the clocksource is set:

    EPIT_CR_REG(epit_base) &= ~(0x3 << 24);

    if (hwtimer->clock_id == EPIT_CLOCK_LP_HIGH_FREQ)

        EPIT_CR_REG(epit_base) |= (2 << 24);

    else if (hwtimer->clock_id == EPIT_CLOCK_LP_CKIL)

        EPIT_CR_REG(epit_base) |= (3 << 24);

    else

        EPIT_CR_REG(epit_base) |= (1 << 24);

Printing the CR register, after the timer has been started will give the following output:
0x16C000F => 01 CLKSRC: peripheral_clk as

                          01 OM: toggle output pin

                            1 STOPEN: enabled in stop mode

                            1 WAITEN: enabled in wait mode

                            1 DBGEN: enabled in debug mode

                                     0 IOVW: do not overwrite the counter when lr is set

                            0 SWR: epit is out of reset

                               [0..0] PRESCALAR: divide by 1

                                     1 RLD: when counter reaches 0, count back from rld

                                     1 OCIEN: fire interrupt on compare

                                     1 ENMOD: start counting from RLD when re-enabled

                                     1 EN: enable epit


I need to get a very precise timer that fires a callback function every 3.2us. Since it will be the only task running in the m4 core, I shouldn't have problems with the scheduler, am I right?

0 Kudos