Hi,
I am implementing a delay function using MCUXpresso and LPC54606 microcontroller board.
The delay function is called is hanging time to time and I cannot find the reason. When I check in debug mode I can see that the high part of my counter gets no longer updated while the low part is still cycling correctly, but the delay fuction never gets out of the while waiting. The code can run OK for minutes, hours or even one day but always hangs.
The example code is below, I have added also several clock init calls also used in my code along with initial code for ethernet for better understanding of the context.
What can be the reason of the hang in the delay code? It is usally hanging when I call "u_delay(2);" within an interrupt callback function.
#include "fsl_ctimer.h"
#define CTIMER CTIMER0 /* Timer 0 */
#define CTIMER_MAT_OUT kCTIMER_Match_0 /* Match output 0 */
#define CTIMER_CLK_FREQ CLOCK_GetFreq(kCLOCK_BusClk)
volatile uint32_t countH=0;
#define TIME_STAMP ((uint64_t)countH<<32|CTIMER_GetTimerCountValue(CTIMER))
void ctimer_match0_callback(uint32_t flags)
{
countH++;
}
ctimer_callback_t ctimer_callback_table[] = {ctimer_match0_callback};
void ctimer0_Configuration(void)
{
ctimer_config_t config;
ctimer_match_config_t matchConfig;
CTIMER_GetDefaultConfig(&config);
CTIMER_Init(CTIMER, &config);
matchConfig.enableCounterReset = true;
matchConfig.enableCounterStop = false;
matchConfig.matchValue = UINT32_MAX;
matchConfig.outControl = kCTIMER_Output_NoAction;
matchConfig.outPinInitState = false;
matchConfig.enableInterrupt = true;
CTIMER_RegisterCallBack(CTIMER, &ctimer_callback_table[0], kCTIMER_SingleCallback);
CTIMER_SetupMatch(CTIMER, CTIMER_MAT_OUT, &matchConfig);
CTIMER_StartTimer(CTIMER);
}
void u_delay(uint32_t umdelay) {
uint64_t weak_delay = TIME_STAMP + (umdelay*180);
while (weak_delay > TIME_STAMP);
}
void main(void) {
CLOCK_EnableClock(kCLOCK_InputMux);
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
CLOCK_AttachClk(kFRO12M_to_FLEXCOMM7);
CLOCK_AttachClk(kFRO12M_to_FLEXCOMM1);
/* reset FLEXCOMM for SPI */
RESET_PeripheralReset(kFC7_RST_SHIFT_RSTn);
RESET_PeripheralReset(kFC1_RST_SHIFT_RSTn);
/* Enable the asynchronous bridge */
SYSCON->ASYNCAPBCTRL = 1;
/* Use 12 MHz clock for Ctimer 0 */
CLOCK_AttachClk(kFRO12M_to_ASYNC_APB);
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
MDIO_Init();
g_phy_resource.read = MDIO_Read;
g_phy_resource.write = MDIO_Write;
time_init();
ctimer0_Configuration();
while(1) {
u_delay(1000000);
PRINTF("Passed 1 seconf\n\r");
}
}
Solved! Go to Solution.
Hi,
If you use 64 bits delay time, although you initialize the countH as 0, but it will increment with the CTimer callBack function automatically when the overflow event of Ctimer happens, so it is okay for 64 bits counting.
But I suppose 32 bits counting is enough, the max delay time is (tick cycle)*2**32
Hope it can help you
BR
XiangJun Rong
Hi,
I suppose that the u_delay api function has issue.
Pls try to use the following api functions:
32 bits variable compare:
void u_delay(uint32_t umdelay) {
CTIMER0->TC=0x00;
while (umdelay >CTIMER_GetTimerCountValue(CTIMER)) {}
}
If the deday is required to be very very long, you can use the api function with uint64_t variable.
void u_delay(uint64_t umdelay) {
CTIMER0->TC=0x00;
countH=0x00;
while (umdelay >TIME_STAMP ) {}
}
Hope it can help you
BR
XiangJun Rong
Thanks for your answer @xiangjun_rong
In your approach I cannot use any longer TIMESTAMP to get the current time, since countH will be reset by the delay function.
I am wondering if my source of problems is that the read of countH is not protected and the data gets corrupt when changed in the ISR and read at the same time in the normal function. I am not sure if uint32_t data length read/write operation is atomic or not.
I will try to disable interrupts when reading this data to see if this helps to my problem.
Thanks
Hi,
If you use 64 bits delay time, although you initialize the countH as 0, but it will increment with the CTimer callBack function automatically when the overflow event of Ctimer happens, so it is okay for 64 bits counting.
But I suppose 32 bits counting is enough, the max delay time is (tick cycle)*2**32
Hope it can help you
BR
XiangJun Rong