Skip to main content
Atrahasis
Associate
August 12, 2026
Question

STM32WLE5 System hangs / infinite loop in modem_supervisor_init() during MX_LoRaWAN_Init()

  • August 12, 2026
  • 2 replies
  • 34 views

Hello STM32 Community,

I am encountering an issue on an STM32WL project using the ST LoRaWAN Middleware stack. When I enable and call MX_LoRaWAN_Init(), the MCU gets stuck or enters an infinite loop inside modem_supervisor_init() in modem_supervisor_light.c.

Environment Details

MCU: STM32WLE5CCU6

Board: RAK3172 Module

CubeMX / Firmware Package: STM32CubeWL v1.6.0

Problem Description

When calling MX_LoRaWAN_Init(), execution fails inside modem_supervisor_init(). Debugging shows execution stuck in the for loop below :
 

void modem_supervisor_init( void )
{
memset( &task_manager, 0, sizeof( stask_manager ) );

for( uint8_t i = 0; i < NUMBER_OF_TASKS * NUMBER_OF_STACKS; i++ )
{
task_manager.modem_task[i].priority = TASK_FINISH;
task_manager.modem_task[i].id = ( task_id_t ) i;
task_manager.modem_task[i].stack_id = 0;
task_manager.modem_task[i].updated_locked = false;
}
........
}

What I Have Checked / Observed

Clock & Peripheral Init: RTC, SubGHzSPI, and RNG are initialized prior to calling MX_LoRaWAN_Init().

Sequencer: UTIL_SEQ_Init() and UTIL_TIMER_Init() are called.

Behavior: Halting execution with a debugger shows it never completes modem_supervisor_init().

Any insights or recommendations on how to debug this further would be greatly appreciated!

Thanks in advance.

Here is the main.c code:

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "app_lorawan.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stm32_seq.h"
#include "stm32_timer.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define LED_PORT GPIOA
#define LED_PIN GPIO_PIN_1
#define LED_BLINK_PERIOD_MS 500U /* toggle period -> ~1 Hz blink */
#define BTN_DEBOUNCE_MS 200U
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
RNG_HandleTypeDef hrng;

RTC_HandleTypeDef hrtc;

SUBGHZ_HandleTypeDef hsubghz;

UART_HandleTypeDef huart1;

/* USER CODE BEGIN PV */
static UTIL_TIMER_Object_t LedBlinkTimer;
static volatile uint8_t BlinkEnabled = 1;
static volatile uint32_t LastBtnTick = 0;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RNG_Init(void);
/* USER CODE BEGIN PFP */
static void LedBlinkTimer_Cb(void *context);
static void LedToggle_Task(void);
static void ButtonPress_Task(void);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/**
* @brief UTIL_TIMER callback, fired every LED_BLINK_PERIOD_MS.
* Keep it short: just schedule the sequencer task, never touch
* GPIO or do real work directly inside a timer/IRQ callback.
*/
static void LedBlinkTimer_Cb(void *context)
{
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_LedToggle), CFG_SEQ_Prio_0);
}

/**
* @brief Sequencer task: actually toggles the LED pin.
*/
static void LedToggle_Task(void)
{
HAL_GPIO_TogglePin(LED_PORT, LED_PIN);
}

/**
* @brief Sequencer task: handles a debounced button press.
* Toggles BlinkEnabled and starts/stops the blink timer.
*/
static void ButtonPress_Task(void)
{
BlinkEnabled = !BlinkEnabled;

if (BlinkEnabled)
{
UTIL_TIMER_Start(&LedBlinkTimer);
}
else
{
UTIL_TIMER_Stop(&LedBlinkTimer);
/* Force LED off so it doesn't get stuck lit mid-blink */
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET);
}
}

/* USER CODE END 0 */

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_RNG_Init();
MX_LoRaWAN_Init();
/* USER CODE BEGIN 2 */

/* Register sequencer tasks (IDs come from utilities_def.h) */
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_LedToggle), UTIL_SEQ_RFU, LedToggle_Task);
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_ButtonPress), UTIL_SEQ_RFU, ButtonPress_Task);

/* Create and start the periodic LED blink timer */
UTIL_TIMER_Create(&LedBlinkTimer, LED_BLINK_PERIOD_MS, UTIL_TIMER_PERIODIC,
LedBlinkTimer_Cb, NULL);
UTIL_TIMER_Start(&LedBlinkTimer);

/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
// MX_LoRaWAN_Process();

/* USER CODE BEGIN 3 */
UTIL_SEQ_Run(UTIL_SEQ_DEFAULT);
}
/* USER CODE END 3 */
}

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure LSE Drive Capability
*/
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);

/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_LSE
|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_10;
RCC_OscInitStruct.LSIDiv = RCC_LSI_DIV1;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

/** Enable MSI Auto calibration
*/
HAL_RCCEx_EnableMSIPLLMode();

/** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|RCC_CLOCKTYPE_HCLK
|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}

/**
* @brief RNG Initialization Function
* @param None
* @retval None
*/
static void MX_RNG_Init(void)
{

/* USER CODE BEGIN RNG_Init 0 */

/* USER CODE END RNG_Init 0 */

/* USER CODE BEGIN RNG_Init 1 */

/* USER CODE END RNG_Init 1 */
hrng.Instance = RNG;
hrng.Init.ClockErrorDetection = RNG_CED_ENABLE;
if (HAL_RNG_Init(&hrng) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RNG_Init 2 */

/* USER CODE END RNG_Init 2 */

}

/**
* @brief RTC Initialization Function
* @param None
* @retval None
*/
void MX_RTC_Init(void)
{

/* USER CODE BEGIN RTC_Init 0 */

/* USER CODE END RTC_Init 0 */

RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
RTC_AlarmTypeDef sAlarm = {0};

/* USER CODE BEGIN RTC_Init 1 */

/* USER CODE END RTC_Init 1 */

/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
hrtc.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
hrtc.Init.BinMode = RTC_BINARY_NONE;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}

/* USER CODE BEGIN Check_RTC_BKUP */

/* USER CODE END Check_RTC_BKUP */

/** Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x1;
sDate.Year = 0x0;

if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}

/** Enable the Alarm A
*/
sAlarm.AlarmTime.Hours = 0x0;
sAlarm.AlarmTime.Minutes = 0x0;
sAlarm.AlarmTime.Seconds = 0x0;
sAlarm.AlarmTime.SubSeconds = 0x0;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask = RTC_ALARMMASK_NONE;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDateWeekDay = 0x1;
sAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */

/* USER CODE END RTC_Init 2 */

}

/**
* @brief SUBGHZ Initialization Function
* @param None
* @retval None
*/
void MX_SUBGHZ_Init(void)
{

/* USER CODE BEGIN SUBGHZ_Init 0 */

/* USER CODE END SUBGHZ_Init 0 */

/* USER CODE BEGIN SUBGHZ_Init 1 */

/* USER CODE END SUBGHZ_Init 1 */
hsubghz.Init.BaudratePrescaler = SUBGHZSPI_BAUDRATEPRESCALER_8;
if (HAL_SUBGHZ_Init(&hsubghz) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SUBGHZ_Init 2 */

/* USER CODE END SUBGHZ_Init 2 */

}

/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
void MX_USART1_UART_Init(void)
{

/* USER CODE BEGIN USART1_Init 0 */

/* USER CODE END USART1_Init 0 */

/* USER CODE BEGIN USART1_Init 1 */

/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */

/* USER CODE END USART1_Init 2 */

}

/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */

/* USER CODE END MX_GPIO_Init_1 */

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);

/*Configure GPIO pin : PA1 */
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/*Configure GPIO pin : BTN_Pin */
GPIO_InitStruct.Pin = BTN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(BTN_GPIO_Port, &GPIO_InitStruct);

/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);

/* USER CODE BEGIN MX_GPIO_Init_2 */

/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/**
* @brief HAL GPIO EXTI callback, fired from the EXTI9_5 IRQ handler.
* Keep this minimal: debounce with a tick check, then only
* schedule a sequencer task. No blocking calls, no HAL_Delay,
* no direct GPIO toggling here.
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == BTN_Pin)
{
uint32_t now = HAL_GetTick();

if ((now - LastBtnTick) > BTN_DEBOUNCE_MS)
{
LastBtnTick = now;
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_ButtonPress), CFG_SEQ_Prio_0);
}
}
}

/* USER CODE END 4 */

/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

2 replies

Andrew Neil
Super User
August 12, 2026

Behavior: Halting execution with a debugger shows it never completes modem_supervisor_init().

So have you stepped in the debugger to see what prevents it from completing ?

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Atrahasis
AtrahasisAuthor
Associate
August 13, 2026

Code falls into infinite loop between, while (ssr != LL_RTC_TIME_GetSubSecond(RTC)) and return (uint32_t)(READ_BIT(RTCx->SSR, RTC_SSR_SS));

// timer_if.c

static inline uint32_t GetTimerTicks(void)
{
uint32_t ssr = LL_RTC_TIME_GetSubSecond(RTC);

while (ssr != LL_RTC_TIME_GetSubSecond(RTC))
{
ssr = LL_RTC_TIME_GetSubSecond(RTC);
}

return UINT32_MAX - ssr;
}

// stm32wlxx_ll_rtc.h

__STATIC_INLINE uint32_t LL_RTC_TIME_GetSubSecond(const RTC_TypeDef *RTCx)
{
return (uint32_t)(READ_BIT(RTCx->SSR, RTC_SSR_SS));
}