The doc demonstrates how to use MRT(Multi-rate Timer) module to implement the delay function, the delay time is programmable. The MRT has a One-shot stall mode, with the mode, while the MRT channel counter counts down, the core stalls until the MRT channel counter reaches to zero.
After the MRT channel counter reaches to zero, the MRT channel becomes idle, the core continues to work.
Sometimes, it is expected that there is a programmable delay between two instructions, for example
Instruction 1
Delay
Instruction 2
In general, the delay function can be implemented by forcing the core to execute __asm(“NOP”) instructions
This code is like:
Void delay(uint32_t interval)
{
Uint32_t counter;
Counter=ConvertTimeToCounter(interval);
For(uint32_t i=0; i<counter); i++)
{
__asm(“nop”)
}
}
The macro convertTimeToCounter is used to convert a time to a number of loop
The MRT module of LPC family provides a unique feature called One-shot stall mode, because the test is based on LPC55S69-EVK board, so I referred to the section 27.5.3 One-shot stall mode in UM11126.pdf.
The MRT does not have external pad.
One-shot stall mode:
Bus stall mode can be used when a short delay is need between two software controlled
events, or when a delay is expected before software can continue. Since in this mode
there are no bus transactions while the MRT is counting down, the CPU core stalls, consumes a minimum amount of power during that time until the MRT counter reaches to zero. Therefore the One-shot stall mode of MRT can make core stall during the MRT counting down process, the delay function can be implemented.
For the LPC55S69, the clock source of MRT module is the AHB Bus clock, which is the same as the core clock.
For the LPC55S69 example, there is the code to set up the core clock
void BOARD_InitBootClocks(void)
{
BOARD_BootClockPLL150M();
}
So the MRT clock frequency is 150MHz.
The delay time is a time, but the MRT is a counter, so the delay time must be converted to the counter value. The counter value is dependent on the MRT clock frequency. The MRT clock source is AHB bus clock, or the core clock.
The LPC55S69 core clock frequency is 150Mhz, so we can define
#define MRT_CLOCK_FREQUENCY 150MHz
If the required delay time is delay_time variable in second unit, the required MRT counter value is
MRT counter value=delay_time/(MRT clock cycle time)=delay_time* MRT_CLOCK_FREQUENCY.
For example, assume the required delay_time is 1mS or 1*10**(-3) Second, the corresponding counter value is 1*(10**-3)*150*(10**6)=150 000
The MRT delay time restriction.
The MRT counter register is 24 bits, the maximum counter value is 2**24= 16,777,216, the maximum delay time is 16777216/(150*10**6)=0.111848 S or 111 mS.
MRT delay function source code is based on SDK package SDK_2_11_1_LPCXpresso55S69.zip, the tools is MCUXpresso IDE v11.5.0. The example is run on LPC55S69-EVK
The example uses MRT to delay 100mS(0.1 Second), after the delay, a LED is toggled
The MRT counter value is 0.1S*150*(10**6)=15 000 000
For the mrt_init() api function, it initializes the MRT and set the MRT channel0 in OneShotStall mode.
Once the core executes the line MRT_StartTimer(MRT0, kMRT_Channel_0, 15000000); the MRT channel0 counter will count down from 15000000, during the counting process the Cortex-M33 will stall. After the counter reach to ZERO, the core finishes the stalling mode and continues to execute the next line, the MRT channel0 counter will be in idle mode.
/**
* @file LPC55S69_Project_mrt_stall.c
* @brief Application entry point.
*/
#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "LPC55S69_cm33_core0.h"
#include "fsl_debug_console.h"
#include "fsl_mrt.h"
#include "fsl_iocon.h"
/* TODO: insert other include files here. */
#define BOARD_LED_PORT BOARD_LED_BLUE_GPIO_PORT
#define BOARD_LED_PIN BOARD_LED_BLUE_GPIO_PIN
/* TODO: insert other definitions and declarations here. */
void mrt_init(void);
/*
* @brief Application entry point.
*/
int main(void) {
/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
#ifndef BOARD_INIT_DEBUG_CONSOLE_PERIPHERAL
/* Init FSL debug console. */
BOARD_InitDebugConsole();
#endif
mrt_init();
PRINTF("Hello World\n");
for(;;)
{
MRT_StartTimer(MRT0, kMRT_Channel_0, 15000000);
GPIO_PortToggle(GPIO, BOARD_LED_PORT, 1u << BOARD_LED_PIN);
__asm("nop");
}
/* Force the counter to be placed into memory. */
volatile static int i = 0 ;
/* Enter an infinite loop, just incrementing a counter. */
while(1) {
i++ ;
/* 'Dummy' NOP to allow source level single stepping of
tight while() loop */
__asm volatile ("nop");
}
return 0 ;
}
uint32_t mrt_clock;
mrt_config_t mrtConfig;
void mrt_init(void)
{
/* 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_OneShotStallMode);
//MRT_StartTimer(MRT0, kMRT_Channel_0, 15000000);
}
}
When the above code is running, user can see the blue LED toggles on the LPC55S69-EVK board. Connecting the PIO1_4 pin signal ( the pin 5 of P18 connector) on LPC55S69-EVK, the PIO1_4 signal toggling frequency is 5Hz, the cycle time is 200mS, so the delay is 100mS.