Skip to main content
Associate II
July 7, 2026
Question

Setup HAL UART Interrupts in a Trustzone environment without CubeMX

  • July 7, 2026
  • 6 replies
  • 87 views

Hi ST,

I’ve run into a whole lot of issues adding interrupt-based UART to your OEMiRoT w/ Trustzone example on a NUCLEO-U385RG-Q.

As you may know this example is not compatible with CubeMX, and it’s not clear which steps are needed to manually incorporate UART4 so that it activates an interrupt on receipt of input when running in the Non-Secure region of code. The idea is to only access the Secure region when needing to utilise certain sensitive variables, called from within a Non-Secure function.

Let’s take this opportunity to establish a step-by-step guide for someone who isn’t (yet) an embedded professional, please excuse my ignorance if this already exists, I’d be just as happy to be directed there. My settings so far are:

1. Secure/Inc/partition_stm32u385xx.h: Initialise UART4_IRQn as Non-Secure
#define NVIC_INIT_ITNS2    1
#define NVIC_INIT_ITNS2_VAL      0x00000001

2. Secure/Src/main.c: Define UART4 pins (CN7 1 & 2, or PC10 & 11) as NonSecure
HAL_GPIO_ConfigPinAttributes(GPIOC, GPIO_PIN_10|GPIO_PIN_11, GPIO_PIN_NSEC);

3. NonSecure/Src/stm32u3xx_it.c: Define interrupt handler (+ function definition in the related header file)

void UART4_IRQHandler(void) {
  HAL_UART_IRQHandler(&huart4);
}

4. NonSecure/Src/main.c: Add Interrupt enable and priority inside MX_UART4_Init

  HAL_NVIC_SetPriority(UART4_IRQn, 0, 0);

  HAL_NVIC_EnableIRQ(UART4_IRQn);

5. NonSecure/Src/main.c: Add UART RX Interrupt callback

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ 
HAL_UART_Receive_IT(&huart4, &uart_rx_byte, 1);
}

Is there anything here I don’t need to do? And the more obvious question - what am I missing?

For future reference - how is a ‘successful’ user currently accessing this kind of information without needing your forum? I have 4 seperate user manuals consisting of the nucleo user manual (MB1841), the STM32U3 user manual (RM0487), the programmers manual (PM0264) and the TrustZone application note (AN5347) and neither of them contain a clear guide to implementing this basic(?) functionality.

Thanks for your help!


 

6 replies

Jocelyn RICARD
ST Employee
July 8, 2026

Hello ​@AdsBot ,

I agree there is no specific documentation helping with stepping into TrustZone step by step.

AN5347 provides a good overview but does not make the link to the actual implementation using HAL for instance.

One possible way to know what is needed to add in context of TrustZone is to create an empty TrustZone project with STM32CubeMX.

From first code generation you create a first git commit that is the baseline.

Then add your peripheral in non secure, here the UART for instance, and launch code generation again.

The git diff will give you all the changes required to make it work.

 

Regarding the integration of a CubeMX generated project as an application run by STM32U3 OEMiROT there is no specific resource available.

I will ask internally to create a wiki page for that.

Best regards

Jocelyn

AdsBotAuthor
Associate II
July 10, 2026

Hi ​@Jocelyn RICARD,

Thanks for getting back to me, appreciate the support.

Excuse the code dump but I thought I’d provide the results of my git diff to help narrow down the issue, as my OEMiRoT project is still not responding to UART.

I didn’t add any of the code in the first five files (all the .cproject, .project etc) because I assume just the source code is relevant. All the code I have included is what I added to my OEMiRoT project. I also added all the ‘untracked files’ into my NonSecure\Inc folder as that’s the domain using the UART.

Did you have any other ideas I could try, or spot anything here that is missing?


Changes not staged for commit:
modified: .mxproject
modified: BasicProject.ioc
modified: NonSecure/.cproject
modified: NonSecure/.project
modified: Secure/.cproject

modified: NonSecure/Core/Inc/stm32u3xx_hal_conf.h
+#define HAL_UART_MODULE_ENABLED

modified: NonSecure/Core/Inc/stm32u3xx_it.h
+void UART4_IRQHandler(void);

modified: NonSecure/Core/Src/main.c

+UART_HandleTypeDef huart4;
+static void MX_UART4_Init(void);
+ MX_UART4_Init();

+static void MX_UART4_Init(void)
+{
+ huart4.Instance = UART4;
+ huart4.Init.BaudRate = 115200;
+ huart4.Init.WordLength = UART_WORDLENGTH_8B;
+ huart4.Init.StopBits = UART_STOPBITS_1;
+ huart4.Init.Parity = UART_PARITY_NONE;
+ huart4.Init.Mode = UART_MODE_TX_RX;
+ huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ huart4.Init.OverSampling = UART_OVERSAMPLING_16;
+ huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
+ huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
+ huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
+}
+ __HAL_RCC_GPIOC_CLK_ENABLE();

modified: NonSecure/Core/Src/stm32u3xx_hal_msp.c
+void HAL_UART_MspInit(UART_HandleTypeDef* huart)
+{
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
+ if(huart->Instance==UART4)
+ {
+ /* USER CODE BEGIN UART4_MspInit 0 */
+
+ /* USER CODE END UART4_MspInit 0 */
+
+ /** Initializes the peripherals clock
+ */
+ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_UART4;
+ PeriphClkInit.Uart4ClockSelection = RCC_UART4CLKSOURCE_PCLK1;
+ if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
+ {
+ Error_Handler();
+ }
+
+ /* Peripheral clock enable */
+ __HAL_RCC_UART4_CLK_ENABLE();
+
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ /**UART4 GPIO Configuration
+ PC10 ------> UART4_TX
+ PC11 ------> UART4_RX
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
+ GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
+ HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+ /* UART4 interrupt Init */
+ HAL_NVIC_SetPriority(UART4_IRQn, 0, 0);
+ HAL_NVIC_EnableIRQ(UART4_IRQn);
+ /* USER CODE BEGIN UART4_MspInit 1 */
+
+ /* USER CODE END UART4_MspInit 1 */
+
+ }
+
+}

+void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
+{
+ if(huart->Instance==UART4)
+ {
+ /* USER CODE BEGIN UART4_MspDeInit 0 */
+
+ /* USER CODE END UART4_MspDeInit 0 */
+ /* Peripheral clock disable */
+ __HAL_RCC_UART4_CLK_DISABLE();
+
+ /**UART4 GPIO Configuration
+ PC10 ------> UART4_TX
+ PC11 ------> UART4_RX
+ */
+ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11);
+
+ /* UART4 interrupt DeInit */
+ HAL_NVIC_DisableIRQ(UART4_IRQn);
+ }
+}

modified: NonSecure/Core/Src/stm32u3xx_it.c
+extern UART_HandleTypeDef huart4;
+void UART4_IRQHandler(void)
+ HAL_UART_IRQHandler(&huart4);

modified: Secure/Core/Inc/partition_stm32u385xx.h
+// <o.0> UART4_IRQn <1=> Non-Secure state
+#define NVIC_INIT_ITNS2_VAL 0x00000001

modified: Secure/Core/Src/main.c
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ HAL_GPIO_ConfigPinAttributes(GPIOC, GPIO_PIN_10|GPIO_PIN_11, GPIO_PIN_NSEC);

Untracked files:
(use "git add <file>..." to include in what will be committed)
Drivers/STM32U3xx_HAL_Driver/Inc/stm32u3xx_hal_uart.h
Drivers/STM32U3xx_HAL_Driver/Inc/stm32u3xx_hal_uart_ex.h
Drivers/STM32U3xx_HAL_Driver/Inc/stm32u3xx_ll_lpuart.h
Drivers/STM32U3xx_HAL_Driver/Inc/stm32u3xx_ll_usart.h
Drivers/STM32U3xx_HAL_Driver/Src/stm32u3xx_hal_uart.c
Drivers/STM32U3xx_HAL_Driver/Src/stm32u3xx_hal_uart_ex.c

 

AdsBotAuthor
Associate II
July 12, 2026

*added the untracked .h files to NonSecure\Inc folder, and the .c files to the NonSecure\Src file

AdsBotAuthor
Associate II
August 19, 2026

As it turns out, there is a bug in the ST provided startup_STM32U385RGTxQ.s file for this project. What should be called ‘UART4_IRQHandler’ is called “USART4_IRQHandler” instead. This is true for the UART3 handler as well. The interrupts can never fire with this config. 

So to provide the implementation guide I’ve needed all along, the confirmed changes required to implement interrupt-based UART4 on pins A0,A1 on the NUCLEO-U385RG within OEMiRoT_Appli_TrustZone example are:

1. Secure/Inc/partition_stm32u385xx.h: Register the UART4_IRQn as Non-Secure
#define NVIC_INIT_ITNS2    1
#define NVIC_INIT_ITNS2_VAL      0x00000001

2. Secure/Src/main.c: Define UART4 pins (CN8 A0 and A1) as NonSecure
  HAL_GPIO_ConfigPinAttributes(GPIOA, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_NSEC);
 

3. NonSecure/Src/stm32u3xx_it.c: Define interrupt handler (+ function prototype in the associated .h file)
void UART4_IRQHandler(void) {
  HAL_UART_IRQHandler(&huart4);
}
 

4. NonSecure/Src/com.c: Add GPIO config and interrupt enable to HAL_UART_MspInit:

  if(huart->Instance==UART4)

  {

    __HAL_RCC_UART4_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

    GPIO_InitStruct.Alternate = GPIO_AF8_UART4;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 

    HAL_NVIC_SetPriority(UART4_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(UART4_IRQn);

  }

5. NonSecure/Src/main.c: Initiate UART_RX in main and add UART RX Interrupt callback function

In main function after initialising steps → HAL_UART_Receive_IT(&huart4, uart4_rx_buffer, 1U);

Seperate function→ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ 

  if (huart->Instance == UART4)

  {

  HAL_UART_Transmit_IT(&huart4, uart4_rx_buffer, 4);

  HAL_UART_Receive_IT(&huart4, uart4_rx_buffer, 1U);
  }
}

6. Fix the bug I mentioned.

Also keep in mind I built this into the bootloader logic (ie. in the switch case inside FW_APP_Run()) so that turning on the uart was just another menu item. Probably your best bet for an initial test but i will have to decouple it eventually for my usecase. Hope this helps!

Jocelyn RICARD
ST Employee
August 19, 2026

Hello ​@AdsBot ,

I’m sorry your lost lot of time debugging this issue. This is first time I see this actually.

Having a look to startup files, this issue actually concerns all OEMiROT application examples and only these examples.

For instance, the Template projects for OEMiROT (in STM32Cube_FW_U3_V1.4.0\Projects\NUCLEO-U385RG-Q\Templates\ROT\) use the right startup files.

I can’t understand where this .s file comes from as it has also other issues on I3C and TIM1 handlerse.

I will create a ticket to have this fixed hopefully on next delivery

Best regards

Jocelyn

AdsBotAuthor
Associate II
August 26, 2026

No worries Jocelyn thanks for letting me know, glad I could help.