LPC804 maximum MRT frequency?

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

LPC804 maximum MRT frequency?

1,033 Views
martinfierz
Contributor II

I am trying to use an LPC804 to read a PWM input and at the same time generate a defined output pattern on 4 GPIO outputs to drive an H-bridge. 

The PWM input is 20kHz fixed, and I need to find its duty cycle.

The output pattern I need to generate on the GPIOs somewhere around 22kHz but I need to track a resonance frequency, so it is variable. The output pattern has 3 different states for the pins, and they should last about 25,3,21 and 3 microseconds each (roughly, changing a bit depending on total frequency). 

I wanted to do this by using the multi-rate timer (MRT) for the output and the standard counter timer (CTIMER) to demodulate the input PWM. I wanted to use one channel of the MRT in repeat mode to make the ~22kHz frequency, and then use a second channel of the MRT in one-shot mode to count down the number of microseconds necessary. The code is pretty straightforward; I pasted it below - and it also kind of works - only when I use short time intervals such as ...

LPC_MRT->Channel[1].INTVAL = ForceLoad | (3*15);     // 3*15 counts should be 3 us

...the interrupt comes far too late - instead of generating an interrupt after 3us it takes about 10us to make the interrupt (measured with a scope). 

I then went on to just toggle a single GPIO with the MRT, with a single channel of the MRT, with repeat mode. That works fine up until values of 150 (giving me a 100kHz timer), but values smaller than 150 seem to have no effect - it remains a 100kHz timer. So I am guessing that the MRT for some reason is unable to go faster than this, and values <150 written to the register are somehow rounded up to 150? However, nothing like this is written in the documentation. 

My questions are: 

(1) is there really a 100kHz limit on the MRT, and if yes why isn't it documented?

(2) does anyone see a way to achieve my objective of demodulating a PWM while at the same time generating a fast output waveform on 4 GPIOs with the LPC804? The CTIMER seems to be useful to generate PWM but since I think I need to use it to demodulate the input PWM I feel stuck?!

best regards

  Martin

FWIW the code:

setup: 

LPC_MRT->Channel[0].CTRL = (MRT_Repeat<<MRT_MODE) | (1<<MRT_INTEN);
LPC_MRT->Channel[1].CTRL = (MRT_OneShot<<MRT_MODE) | (1<<MRT_INTEN);
NVIC_EnableIRQ(MRT_IRQn);

LPC_MRT->Channel[0].INTVAL = 750; 

With the 15MHz Clock, the value of 750 counter would correspond to 20 kHz. 

interrupt service routine:

void MRT_IRQHandler(void) {
   static int count = 0; 

   if (LPC_MRT->IRQ_FLAG & (1<<GFLAG0)) {
      chan = 0;

      count = 0; 

   }
   else
      count++;


// Clear the interrupt flags
LPC_MRT->Channel[0].STAT = 1<<MRT_INTFLAG;
LPC_MRT->Channel[1].STAT = 1<<MRT_INTFLAG;

switch(count) {

   case 0:       // main ~22kHz timer has triggered
   LPC_GPIO_PORT->SET[0] = ((1<<DRV1_PIN) | (1<<DRV4_PIN));
   LPC_GPIO_PORT->CLR[0] = ((1<<DRV2_PIN) | (1<<DRV3_PIN));

   LPC_MRT->Channel[1].INTVAL = ForceLoad | (25*15);     // 25*15 counts should be 25 us

   break; 

   

   case 1: 
   LPC_GPIO_PORT->SET[0] = ((1<<DRV2_PIN) | (1<<DRV4_PIN));
   LPC_GPIO_PORT->CLR[0] = ((1<<DRV1_PIN) | (1<<DRV3_PIN));

   LPC_MRT->Channel[1].INTVAL = ForceLoad | (3*15);     // 3*15 counts should be 3 us

   break; 

   case 2: 
   LPC_GPIO_PORT->SET[0] = ((1<<DRV2_PIN) | (1<<DRV3_PIN));
   LPC_GPIO_PORT->CLR[0] = ((1<<DRV1_PIN) | (1<<DRV4_PIN));

   LPC_MRT->Channel[1].INTVAL = ForceLoad | (21*15);     // 21*15 counts should be 21 us

   break; 

   case 3: 

   LPC_GPIO_PORT->SET[0] = ((1<<DRV2_PIN) | (1<<DRV4_PIN));
   LPC_GPIO_PORT->CLR[0] = ((1<<DRV1_PIN) | (1<<DRV3_PIN));

   // no need to load a value to MRT channel 1 as channel 0 will trigger next

}

0 Kudos
3 Replies

956 Views
martinfierz
Contributor II

Hi Jeremy,

I have already given the MRT interrupt a higher priority than all others; and I have also tried doing absolutely nothing else than just the MRT, disabling all the other hardware I need. It doesn't change a thing, 100kHz is the maximal frequency I get out. 

cheers

  Martin

0 Kudos

956 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Martin Fierz,

Thanks for your reply.
I've run the MRT demo which is from the SDK library on the OM40001 board, it can toggle the GPIO pin with about 125 KHz in the interrupt.
Below are the testing demo code and the signal which is visualized in an oscilloscope.
Maybe you can give a try.

/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright 2016-2017 NXP
 * All rights reserved.
 * 
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "fsl_debug_console.h"
#include "board.h"
#include "fsl_mrt.h"

#include "pin_mux.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define APP_LED_INIT LED_RED_INIT(1)
#define APP_LED_ON (LED_RED_ON())
#define APP_LED_TOGGLE (LED_RED_TOGGLE())
#define MRT_CLK_FREQ CLOCK_GetFreq(kCLOCK_CoreSysClk)

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

/*******************************************************************************
 * Variables
 ******************************************************************************/

static volatile bool mrtIsrFlag = false;

/*******************************************************************************
 * Code
 ******************************************************************************/
void MRT0_IRQHandler(void)
{
    /* Clear interrupt flag.*/
    MRT_ClearStatusFlags(MRT0, kMRT_Channel_0, kMRT_TimerInterruptFlag);
    //mrtIsrFlag = true;
    APP_LED_TOGGLE;
    /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
      exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
    __DSB();
#endif
}

/*!
 * @brief Main function
 */
int main(void)
{
    uint32_t mrt_clock;

    /* Structure of initialize MRT */
    mrt_config_t mrtConfig;

    /* Board pin, clock, debug console init */
    /* Attach main clock to USART0 (debug console) */
    CLOCK_Select(kUART0_Clk_From_MainClk);

    BOARD_InitPins();
    BOARD_InitBootClocks();
    BOARD_InitDebugConsole();

    /* Initialize and enable LED */
    APP_LED_INIT;

    mrt_clock = MRT_CLK_FREQ;

    /* mrtConfig.enableMultiTask = false; */
    MRT_GetDefaultConfig(&mrtConfig);

    /* Init mrt module */
    MRT_Init(MRT0, &mrtConfig);

    /* Setup Channel 0 to be repeated */
    MRT_SetupChannelMode(MRT0, kMRT_Channel_0, kMRT_RepeatMode);

    /* Enable timer interrupts for channel 0 */
    MRT_EnableInterrupts(MRT0, kMRT_Channel_0, kMRT_TimerInterruptEnable);

    /* Enable at the NVIC */
    EnableIRQ(MRT0_IRQn);

    /* Start channel 0 */
    PRINTF("\r\nStarting channel No.0 ...");
    MRT_StartTimer(MRT0, kMRT_Channel_0, USEC_TO_COUNT(4U, mrt_clock));

    while (true)
    {
        /* Check whether occur interupt and toggle LED */
//        if (true == mrtIsrFlag)
//        {
//            PRINTF("\r\n Channel No.0 interrupt is occured !");
//            APP_LED_TOGGLE;
//            mrtIsrFlag = false;
//        }
    }
}

pastedImage_1.png

pastedImage_2.png

Have a great day,
TIC

 

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

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

956 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Martin Fierz,

Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
(1) is there really a 100kHz limit on the MRT, and if yes why isn't it documented?
-- No, in my opinion, this interrupt is not serviced as expected because of the happening of higher interrupt preempted or cost a bit long time in the interrupt, it needs to figure it out by doing more testing.
(2) Does anyone see a way to achieve my objective of demodulating a PWM while at the same time generating a fast output waveform on 4 GPIOs with the LPC804? The CTIMER seems to be useful to generate PWM but since I think I need to use it to demodulate the input PWM I feel stuck?!
-- Your scheme is good actually, however, it still needs some optimation.

Have a great day,
TIC

 

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

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos