UART hangs in FreeRTOS xEventGroupWaitBits call

I’m using FreeRTOS Kernel 10.4.3 and the 2.5.0 version of the FreeRTOS specific UART drivers for the NXP MK24FN1M0VLQ12 MCU. When I try to use the UART_RTOS send and receive calls provided by that driver the code hangs at the xEventGroupWaitBits call. Trying to debug into that function just sends the processor into a reset.

Here is the applicable source code - it is 99% generated code from NXP’s MCUxpresso, including the peripheral initialization to try and keep human error out of things for solving this problem - my production code is doing the same thing:


  • Copyright 2016-2024 NXP
  • All rights reserved.
  • SPDX-License-Identifier: BSD-3-Clause


  • @file MK24F12_Project.cpp
  • @brief Application entry point.
    #include <stdio.h>
    #include “board.h”
    #include “peripherals.h”
    #include “pin_mux.h”
    #include “clock_config.h”
    #include “MK24F12.h”
    #include “fsl_debug_console.h”
    #include “fsl_gpio.h”
    #include “FreeRTOS.h”
    #include “task.h”
    #include “fsl_uart.h”

/* TODO: insert other include files here. */

/* TODO: insert other definitions and declarations here. */

#define GPIO_PORTA GPIOA //GPIO A port data output register 0x400FF000
#define GPIO_PWRON_PIN 27u //ublox power on pin, MK24 PTA27 GPIO out, schematic CELL_ON_OFF signal,
// signal HIGH to turn on power the ublox
#define GPIO_RESET_PIN 28u //ublox reset pin, MK24 PTA28 GPIO out, schematic CELL_SHUTDN signal,
// signal HIGH to reset the ublox
#define GPIO_VINT_PIN 29u //ublox V_INT (1.8 VDC) pin, MK24 PTA29 GPIO in, schematic CELL_PWR_STAT signal,
// goes LOW when the ublox internal voltage regulator turns ON
#define GPIO_PORTA_PORT PORTA //Port A multiplexing control 0x40049000

const gpio_pin_config_t gpio_outputLowConfig = { kGPIO_DigitalOutput, 0 };

const gpio_pin_config_t gpio_outputHighConfig = { kGPIO_DigitalOutput, 1 };

const gpio_pin_config_t gpio_inputConfig = { kGPIO_DigitalInput, 0 };

void SaraOn()
GPIO_PinInit(GPIO_PORTA, GPIO_RESET_PIN, &gpio_outputLowConfig); // Configure GPIO as output and set LOW
GPIO_PinInit(GPIO_PORTA, GPIO_PWRON_PIN, &gpio_outputLowConfig); // Configure GPIO as output and set LOW

//wait for 100 ms
const TickType_t xDelay = 100 / portTICK_PERIOD_MS;
vTaskDelay( xDelay );

GPIO_PinWrite(GPIO_PORTA, GPIO_RESET_PIN, 1U); // set the cellular module reset pin LOW (HIGH at the mcu)
vTaskDelay( xDelay );
GPIO_PinWrite(GPIO_PORTA, GPIO_RESET_PIN, 0U); // set the cellular module reset pin HIGH (LOW at the mcu)
vTaskDelay( xDelay );
const TickType_t yDelay = 300 / portTICK_PERIOD_MS;
GPIO_PinWrite(GPIO_PORTA, GPIO_PWRON_PIN, 1U); // set the cellular module power on pin LOW (HIGH at the mcu)
vTaskDelay( yDelay );
GPIO_PinWrite(GPIO_PORTA, GPIO_PWRON_PIN, 0U); // set the cellular module power on pin HIGH (LOW at the mcu)
vTaskDelay( yDelay );

// Send AT command to cellular module
std::string txData = "AT\r";
std::string rxData = "123456789012";
UART_WriteBlocking(UART0, (uint8_t*)txData.c_str(), txData.size());

// UART_WriteBlocking(UART4, (uint8_t*)txData.c_str(), txData.size());
// UART_ReadBlocking(UART4, (uint8_t*)rxData.c_str(), rxData.size());
UART_RTOS_Send(&UART4_rtos_handle, (uint8_t*)txData.c_str(), txData.size());
size_t received = 0;

UART_RTOS_Receive(&UART4_rtos_handle, (uint8_t*)rxData.c_str(), rxData.size(), &received);
txData = "Received data:\r\n";
UART_WriteBlocking(UART0, (uint8_t*)txData.c_str(), txData.size());
UART_WriteBlocking(UART0, (uint8_t*)rxData.c_str(), rxData.size());


static TaskHandle_t TestHandle;
void Test_Thread(void const *argument)

while (1);



  • @brief Application entry point.
    int main(void) {

    /* Init board hardware. /
    Init FSL debug console. */

    PRINTF(“Hello World\r\n”);

    xTaskCreate((TaskFunction_t)Test_Thread, “TEST”, configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 3, &TestHandle);


    /* 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 ;

you need to provide more information if you expect an answer. Like for example your source code.

Apologies - I have edited the original post to include the applicable source code - This is the line where it fails in the FreeRTOS UART driver (within the UART_RTOS_Send() call):

ev = xEventGroupWaitBits(handle->txEvent, RTOS_UART_COMPLETE, pdTRUE, pdFALSE, portMAX_DELAY);

FreeRTOS does not have a UART driver. All of that is code provided by NXP, you may want to contact them. Since you do not include the code from your driver, everything is guess work.

Edit: Check to see if your Tx interrupt is configured properly and fires. It is probably the instance responsible for sending the notification. That is all the guessing I am willing to make without knowing what the driver does.

1 Like

Thank you for the help! I will contact NXP.

One question though, the function call where it is hanging xEventGroupWaitBits is in the freertos kernel directory, specifically the eventgroups.c file… wouldn’t that be FreeRTOS and not NXP?

No. FreeRTOS simply provides the API. If an application system is not set up to use the API properly, there is nothing FreeRTOS can do about that. Although it is theoretically possible that there is a bug in the event group implementation, it is unlikely.

Edit: You did not specify “hang,” so I am left to guessing again, and I guess that the function does exactly what it is intended to do - namely wait until another thread of execution signals the notification - which (another guess) does simply not happen, so there is nothing wrong in the function call itself, just its usage.