Skip to main content
Visitor
October 8, 2026
Question

[Bug] ll_aton: SecureFault in a non-secure application

  • October 8, 2026
  • 0 replies
  • 13 views

Hello,

Recently I decided to run STM32N6 NPU under non-secure Zephyr and encountered a bug in LL_ATON library. To begin with, this is my platform and SW:

Board: NUCLEO-N657X0-Q
SoC: STM32N657X0H3Q
LL_ATON: atonn-v1.1.3-275-g6770925d
Runtime: NetworkRuntime1201_CM55_GCC.a
STEdge AI: v4.0.1-20581 7ed50de05
   ISPU 2.0.1-RC2
   MLC 1.2.4-RC2
   STM32CubeAI 12.0.1-RC2
Model: st_yolodv2milli_actrelu_pt_coco_person_192_qdq_int8.onnx
SW: OEMUxROT (S) + Zephyr (NS)
XIP: enabled

My application runs in non-secure world and the NPU keeps addressing AXISRAM3-6 through the secure alias (0x342...), so the memory pools in the generated network are placed there. Then, the non-secure CPU is unable to access that alias, because it is running in non-secure and should access via non-secure alias (0x242...). In most cases LL_ATON utilizes ATON_LIB_PHYSICAL_TO_VIRTUAL_ADDR to access correct region, but there are few places that pass address directly instead of utilizing proper macro.

Reproduction steps:
1. Run a network from a non-secure application with the NPU memory pools in the secure AXISRAM alias.
2. Use a model that falls back to the CPU path.
3. Run an interface.

Result:

Secure exception triggered by CPU access to secure memory

 

Proposed fix:

diff --git a/app/lib/ai_runtime/ll_aton/ll_aton_lib.c b/app/lib/ai_runtime/ll_aton/ll_aton_lib.c
index 4ae5d9f..6700958 100644
--- a/app/lib/ai_runtime/ll_aton/ll_aton_lib.c
+++ b/app/lib/ai_runtime/ll_aton/ll_aton_lib.c
@@ -3527,11 +3527,12 @@ LL_ATON_PRINTF("out: b=%d w=%d g=%d c=%d ndims=%d\n",out_batches,out_fwidth,out_
#else // !__LL_LIB_Concat_Cast_USE_ATON_HW
{
/* case when concatenation is on ONNX dim before channels or height */
- unsigned char *start = LL_Buffer_addr_start(output);
+ unsigned char *start = ATON_LIB_PHYSICAL_TO_VIRTUAL_ADDR(LL_Buffer_addr_start(output));
for (i = 0; i < ninputs; i++)
{
// LL_ATON_PRINTF("in[%d]\n",i);
- memcpy((void *)start, (void *)LL_Buffer_addr_start(inputs + i), LL_Buffer_len(inputs + i));
+ memcpy((void *)start, (void *)ATON_LIB_PHYSICAL_TO_VIRTUAL_ADDR(LL_Buffer_addr_start(inputs + i)),
+ LL_Buffer_len(inputs + i));
start += LL_Buffer_len(inputs + i);
}
}
@@ -3598,8 +3599,8 @@ LL_ATON_PRINTF("out: b=%d w=%d g=%d c=%d ndims=%d\n",out_batches,out_fwidth,out_
// LL_ATON_PRINTF("in[%d]\n",i);
unsigned int pix_size = nbytes * inputs[i].nchannels;
unsigned int line_size = pix_size * inputs[i].fwidth;
- unsigned char *out_curr = out_start;
- unsigned char *in_curr = LL_Buffer_addr_start(inputs + i);
+ unsigned char *out_curr = ATON_LIB_PHYSICAL_TO_VIRTUAL_ADDR(out_start);
+ unsigned char *in_curr = ATON_LIB_PHYSICAL_TO_VIRTUAL_ADDR(LL_Buffer_addr_start(inputs + i));
unsigned int row;
for (row = 0; row < in_fheight; row++)
{
@@ -3675,7 +3676,8 @@ LL_ATON_PRINTF("out: b=%d w=%d g=%d c=%d ndims=%d\n",out_batches,out_fwidth,out_
for (dst = start; dst < stop; dst += jump, src += copy_val)
{
// LL_ATON_PRINTF("i =%d dst = %d src = %d\n", i, dst, src);
- memcpy(LL_Buffer_addr_start(output) + dst, LL_Buffer_addr_start(inputs + i) + src, copy_val);
+ memcpy(ATON_LIB_PHYSICAL_TO_VIRTUAL_ADDR(LL_Buffer_addr_start(output) + dst),
+ ATON_LIB_PHYSICAL_TO_VIRTUAL_ADDR(LL_Buffer_addr_start(inputs + i) + src), copy_val);
}
start += copy_val;
}

Result:

After applying proposed fix the interface is running without issues.

Result after applying mentioned patch

Could you confirm whether this fix is correct and, if so, include it in a future release so others can benefit? It might also be worth checking the other CPU paths, as I only verified the ones exercised by this model.

I’m happy to provide more details or do more testing on my setup.

Best regards,
Lubor