This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Hardware Faults for Ram in nRF51 chips.

I'm exploring an nRF51 DK board I bought using openOCD (on circuit debugger), eclipse, and the gcc/gdb toolchain under Linux.

I'm trying to understand the chip by hand probing it and activating various peripherals, manually, using the debugger.

After reading the nRF51 reference guides, I noticed they mentioned that RAM is mappable;  There were also discussions of hardware exceptions being raised if "protected" NVM (FLASH ROM) that was protected was written to.  So, I see that a memory manager of sorts exists in ARM Cortex M0+ chips.   But I don't see a general explanation of whether or not hardware faults can be generated on bad RAM accesses as well as ROM accesses, eg: writes or reads to non-extant ram addresses in the RAM space; 

I can only see, from the manual, that each page of RAM (4k block) is on a separate APB bus, so that peripherals can simultaneously access different 4K blocks of ram without interfering with each other.

But, I'm interested in triggering exceptions/interrupts when a user program accesses non-ram, non-rom memory.   Does  this happen automatically?

While exploring, I realized the nRF51422 iin the nRF51-DK s supposed to have 32K of RAM total, so that would be 8 distinct 4K blocks of ram total.

The reference manual was clear that the byte addresses 0x2000_0000 - 0x2000_7FFF are all memory addresses, by default.

I tested that range using gnu-debugger (gdb), and openOCD in SWD mode; and found it is exactly filled with ram, and not one byte more.

gdb

set target remote localhost:3333

print *(0x20000000)=-2, *(0x20000000)  # Will set first RAM addresses to 4 byte  signed value,  -2 and print the result from memory.

print *(0x20007FFC)=-2, *(0x20007FFC)  # Will set last RAM addresses to 4 byte  signed value,  -2 and print the result from memory.

print *(0x20008000)=-2, *(0x20008000)  # Will attempt to set empty ram space to -2, but it fails and prints 0.

So, I know that all 32K of ram specified in the nrF51422 manual is really present at the 0x2000 0000 base address shown in the reference manual.

However, in the main memory map, address 0x60000000 and 0x80000000 are both shown as RAM addresses, too.

Attempts to write to either 0x6000000 or 0x8000000 address with GDB reveals that no ram exists there by default.  The reference manual is not very clear about how RAM can be mapped.

So, what I am curious about are two things:  Is it possible to cause 4k blocks of ram from address range 0x20000000-0x20007FFFF to be mirrored into some of the higher addresses?

And secondly, where gaps between memory blocks exist (eg: unmapped addresses, like 0x20008000), is it possible to cause an interrupt to occur if a  user program tries to read or write there?

Another example:   if I mapped a single 4K ram block to 0x60000000 *assuming it's possible* ; would a hardware fault occur if I tried to read or write 0x60001000 (one byte beyond 4K of memory) ?

What I'm wanting to do is have memory blocks that are separated  by unmapped memory, so that if a program exceeds a 4K buffer size, the nRF51 will call an interrupt routine.

I assume that the hardware fault exception can be probed to determine what caused it, or what line of program code was executing, and that can be exploited to do error recovery.

 eg: What I want to do is similar to how a memory page fault in Linux can cause the kernel to be activated, memory swapped in, and the user process restarted.

Parents
  • Hi,

     

    But, I'm interested in triggering exceptions/interrupts when a user program accesses non-ram, non-rom memory.   Does  this happen automatically?

    That would be a hardfault on the Cortex M0 core (or a mem fault on Cortex M4), given that the CPU tries to access out-of-bounds.

    However, in the main memory map, address 0x60000000 and 0x80000000 are both shown as RAM addresses, too.

    This is the "system map". You have to look at the "nRF51 Address Map details" to see what is implemented in the nRF51-series devices.

    So, what I am curious about are two things:  Is it possible to cause 4k blocks of ram from address range 0x20000000-0x20007FFFF to be mirrored into some of the higher addresses?

    No, that is not possible with the nRF51-series. nRF52-devices has a code RAM area, that is a mirror of the RAM area (See this section for nRF52810).

    And secondly, where gaps between memory blocks exist (eg: unmapped addresses, like 0x20008000), is it possible to cause an interrupt to occur if a  user program tries to read or write there?

    There's no such peripheral in the nRF51-devices. A fault condition is generated if the CPU executes an out-of-bounds operation. nRF52 has the option to use the generic MPU (ARM Cortex M4 feature), which can restrict access within the mapped address area.

    Another example:   if I mapped a single 4K ram block to 0x60000000 *assuming it's possible* ; would a hardware fault occur if I tried to read or write 0x60001000 (one byte beyond 4K of memory) ?

    With the debugger, you can try to access it, but if the CPU tries to do that, it would generate a fault.

    I assume that the hardware fault exception can be probed to determine what caused it, or what line of program code was executing, and that can be exploited to do error recovery.

    Yes, this can be determined, but you have to read the CPU registers in order to see where you were before the fault occurred. This can be due to a unaligned (non-word aligned) access, free running pointer, or many other scenarios. The debugger does not tell you this straight away, you need to figure that out based on the debug infor and stack traces. Note that it is not always you can get proper information by looking at the core registers, like the stack pointer / link register etc. Based on the current CPU registers, you can try to align the addresses towards how your firmware is linked (ie: addr2line -e myprogram.elf 0xADDR) to see if you can get any info on which function or operation caused the fault.

    We offer a "helper library" for hardfaults in our SDK: HardFault handling library

    I'd also recommend searching for "how to debug a hardfault" to learn more about this.

    What I want to do is similar to how a memory page fault in Linux can cause the kernel to be activated, memory swapped in, and the user process restarted.

    A Cortex M0 device is far less complicated than this, which also has a down-side that you have to manually dig out the information from the CPU registers and use the debug info you have available (call stack, or "backtrace" in gdb, if its not optimized away).

     

    Best regards,

    Håkon

Reply
  • Hi,

     

    But, I'm interested in triggering exceptions/interrupts when a user program accesses non-ram, non-rom memory.   Does  this happen automatically?

    That would be a hardfault on the Cortex M0 core (or a mem fault on Cortex M4), given that the CPU tries to access out-of-bounds.

    However, in the main memory map, address 0x60000000 and 0x80000000 are both shown as RAM addresses, too.

    This is the "system map". You have to look at the "nRF51 Address Map details" to see what is implemented in the nRF51-series devices.

    So, what I am curious about are two things:  Is it possible to cause 4k blocks of ram from address range 0x20000000-0x20007FFFF to be mirrored into some of the higher addresses?

    No, that is not possible with the nRF51-series. nRF52-devices has a code RAM area, that is a mirror of the RAM area (See this section for nRF52810).

    And secondly, where gaps between memory blocks exist (eg: unmapped addresses, like 0x20008000), is it possible to cause an interrupt to occur if a  user program tries to read or write there?

    There's no such peripheral in the nRF51-devices. A fault condition is generated if the CPU executes an out-of-bounds operation. nRF52 has the option to use the generic MPU (ARM Cortex M4 feature), which can restrict access within the mapped address area.

    Another example:   if I mapped a single 4K ram block to 0x60000000 *assuming it's possible* ; would a hardware fault occur if I tried to read or write 0x60001000 (one byte beyond 4K of memory) ?

    With the debugger, you can try to access it, but if the CPU tries to do that, it would generate a fault.

    I assume that the hardware fault exception can be probed to determine what caused it, or what line of program code was executing, and that can be exploited to do error recovery.

    Yes, this can be determined, but you have to read the CPU registers in order to see where you were before the fault occurred. This can be due to a unaligned (non-word aligned) access, free running pointer, or many other scenarios. The debugger does not tell you this straight away, you need to figure that out based on the debug infor and stack traces. Note that it is not always you can get proper information by looking at the core registers, like the stack pointer / link register etc. Based on the current CPU registers, you can try to align the addresses towards how your firmware is linked (ie: addr2line -e myprogram.elf 0xADDR) to see if you can get any info on which function or operation caused the fault.

    We offer a "helper library" for hardfaults in our SDK: HardFault handling library

    I'd also recommend searching for "how to debug a hardfault" to learn more about this.

    What I want to do is similar to how a memory page fault in Linux can cause the kernel to be activated, memory swapped in, and the user process restarted.

    A Cortex M0 device is far less complicated than this, which also has a down-side that you have to manually dig out the information from the CPU registers and use the debug info you have available (call stack, or "backtrace" in gdb, if its not optimized away).

     

    Best regards,

    Håkon

Children
No Data
Related