Interrupt

Store load with volatile

Hi everyone, I have a problem about the load and store instructions related to volatile global variables.
I am using the MPU to constrain the accessible memory range of the unprivileged application code.
However, I find that if there is one global variable labeled as volatile, and this global variable is pointed by a global pointer, then the unprivileged application code will trigger a memory management fault if access this global variable through the pointer, even if the memory range of that global variable is allowed to access by the MPU.
It is kind of weird to me. Does anybody know how to fix this bug?
The compiler I use is Clang, and the MCU I use is ARM CortexM4
Here is the example code:

volatile uint32_t FLAG = 0;
uint32_t *ptr = &FLAG;

void foo(void) {
    ...
    *ptr = 1;	// Raises an memory management fault here.
    ...
}

int main(void) {
    foo();
}

I really appreciate any help you can provide!

Can you dump the values of the fault register here? IIRC mem manage faults are not necessarily MPU related!

The value of the CFSR register is 0x82, indicating that its a Data access violation

Hmm, there’s nothing obviously wrong with your code. Next I would look at the disassembled code around that access, and dump the MPU registers for us to inspect. Happy to look at those two things if you can provide them!

Thanks for your reply Francois! :smiley:
After debugging, I confirmed that the keyword volatile is nothing to with this bug.
In this case, the region number is 3, i.e., MPU->RNR = 3.
The RBAR’s value is 0x2001_fd93, indicating that the start address of region 3 is 0x2001_fd80.
The RASR’s value is 0x1306_000f, indicating that the region size is 0x100
Therefore, the region range is 0x2001_fd80<=addr<=0x2001_fe7f.
However, when I tried to dereference a pointer that points to 0x2001_fe00, 0x80 bytes offset to the region start address 0x2001_fd80, it raises a memory management fault.
But the dereference to the memory address 0x2001_fdff is OK.
In fact, the region size declared by region 3 is halved from 0x100 to 0x80.
Is this a hardware error? Does anybody know why this can happen? :thinking: Many thanks in advance!

I find out the root cause…It’s because the start_address of region 3 doesn’t align to the region size :joy: