I am trying to use the MPU to detect stack overflow. The basic idea is to create two SRAM entries in the MPU: (1) from start of SRAM to base of stack minus N bytes and (2) from base of stack to the end of SRAM. I would over allocate the stack so that the N bytes below the base of the stack would be unused normally and I can safely leave this as a hole in the memory map when programming the MPU. If any write into this area occurs the I expect to see a mem fault.
Looking at the CM33 MPU_RBAR register, it looks like the lower 5 bits of the memory addresses are "don't cares" (they are masked out and are used as control bits.) This implies the MPU is able to control access to memory in increments of 32-bytes. In order to satisfy this requirement, I have ensured (a) the base of my stack is 32-byte aligned and (b) the N byte hole in the memory map is 32 bytes.
This doesn't seem to work for me. If I loop through the 32-byte region (the N bytes below the base of the stack) and write each byte one by one, I am able to write the entire 32-byte region without tripping a mem fault. I tried to increase the alignment to 64-bytes (stack base is 64-byte aligned, N byte hole is set to 64 bytes) and I see a difference in behavior. If I started at the base of the stack and wrote byte by byte towards low memory, I get a mem fault as soon as I write the first byte below the stack base. If I started at the low memory (i.e. first byte of the 64 byte memory hole) and worked my way up in the same fashion, I do not get a mem fault until I am exactly 32 bytes into the N byte region (and write to a 32-byte aligned address.) What might be happening here? I should be running without the cache at this point (CACHE64->CCR is zero).
MPU set up in C main():
ARM_MPU_SetMemAttr(0, ARM_MPU_ATTR(ARM_MPU_ATTR_MEMORY_(1, 0, 1, 0), ARM_MPU_ATTR_MEMORY_(1, 0, 1, 0) ) );
ARM_MPU_SetMemAttr(1, ARM_MPU_ATTR(ARM_MPU_ATTR_MEMORY_(1, 0, 1, 0), ARM_MPU_ATTR_MEMORY_(1, 0, 1, 0) ) );
ARM_MPU_SetMemAttr(2, ARM_MPU_ATTR(ARM_MPU_ATTR_DEVICE_nGnRnE, ARM_MPU_ATTR_DEVICE_nGnRnE ) );
ARM_MPU_SetMemAttr(3, ARM_MPU_ATTR(ARM_MPU_ATTR_DEVICE_nGnRnE, ARM_MPU_ATTR_DEVICE_nGnRnE ) );
ARM_MPU_SetRegion(MPU_REGION_INDEX_SRAM, ARM_MPU_RBAR(0x00000000, ARM_MPU_SH_INNER, 0, 1, 0), ARM_MPU_RLAR(0x00001000, 0) );
ARM_MPU_SetRegion(MPU_REGION_INDEX_PERIPHERAL, ARM_MPU_RBAR(0x40000000, ARM_MPU_SH_OUTER, 0, 1, 1), ARM_MPU_RLAR(0x60000000, 2) );
ARM_MPU_SetRegion(MPU_REGION_INDEX_PERIPHERAL2, ARM_MPU_RBAR(0xE0000000, ARM_MPU_SH_OUTER, 0, 1, 1), ARM_MPU_RLAR(0xE0100000, 3) );
ARM_MPU_SetRegion(MPU_REGION_INDEX_SRAM2, ARM_MPU_RBAR(0x00001040, ARM_MPU_SH_OUTER, 0, 1, 0), ARM_MPU_RLAR(0x00480000, 0) );