Trap use of NULL pointer, memory access exception, on MCF54418 ColdFire V4 using MMU?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Trap use of NULL pointer, memory access exception, on MCF54418 ColdFire V4 using MMU?

1,807 Views
colin
Contributor III

Is there a way to trigger an exception on access to an invalid memory address?  The most important special case of this is accesses caused by deferencing a NULL pointer: accessing address zero.

 

It seems like if we enable the MMU and then put a couple of static entries in the TLB, we can achieve the goal.  We want to say that memory near address zero is not readable, not writable, and not executable.  I haven't been able to find any example code that does this.  Yet it seems extremely useful, since otherwise NULL pointer access (both read and write operations) can go unnoticed for a long time, and the program will behave unpredictably in a later execution context.  This makes it tremendously difficult to identify the source of the problem since no exception handler gets triggered where the NULL pointer is used.

 

In the ColdFire V4 MCF54418 memory map, address zero is a valid address, but is mapped to FlexBus and our application does not use that address range for FlexBus purposes.

 

I see that there are two main features of the ColdFire V4 MMU: first, access control registers (ACRs), of which there are four; and second, the translation lookaside buffer (TLB) entries. The MQX 4.0.2 we are using has apparently very limited MMU support.  Basically it just allows setting up the ACRs but doesn't even fully support all features of the ACRs (e.g. it doesn't allow setting "not readable" flag).

 

Or, is there any other way to trap use of NULL pointers so we can catch the program errors early in the development process and stomp these bugs?  Thanks for any help!!

 

Regards,

Colin

Labels (1)
0 Kudos
3 Replies

982 Views
TomE
Specialist II

Yes, setting up a CPU to trap NULL is a very good idea.

I had this working on an MPC860 back in 2002 or earlier.

Given it was an MPC8xx device, we had to program up the MMU in order to enable the Cache(!). But even then I didn't use the MMU to trap the Null pointers.

I used the Debug Module. It set debug traps on "write to address between x and y" and it has two sets of those. So I had the memory set up with the code at the bottom, then the read-only data, then the stack, then the BSS. So I programmed "trap on write to read-only-data and below" which caught writes to NULL, writes to code space, read-only data and also caught stack overflow. The second debug trap was set to trap on "any read or write below 64k". It is also worth putting a code breakpoint at zero or (if there is RAM there) putting an illegal instruction there as well.

It might be easier to do this than to learn to use the MMU from the very limited information in the Reference Manual.

> It seems like if we enable the MMU and then put a couple of static entries in the TLB, we can achieve the goal.

If you enable the MMU you may have to create TLB entries to map your entire RAM, ROM and Peripheral space. I see the TLBs can map 16M so this mightn't be that hard.

If you want to look for some example code, then there might be something close if you search here:

http://lxr.free-electrons.com/ident?i=MMUTR

> I see that there are two main features of the ColdFire V4 MMU: first, access control registers

> (ACRs), of which there are four; and second, the translation lookaside buffer (TLB) entries.

The ACRs are what the simpler chips that don't have an MMU use to configure cacheable and non-cacheable regions. The TLBs seem to be an "add-on" but I haven't read this in details.

> Or, is there any other way to trap use of NULL pointers

If you're using a debugger then set breakpoints on zero. That isn't good enough as the null pointer might point to a large structure and the code might fetch a few bytes (or few hundred bytes) above the base, so you want a lot of low memory causing the traps. If the debugger doesn't support the CPU's debug features of setting traps on RANGES of addresses, see if you can find one that will.

Otherwise, the Debug Module is made so that you can have a CPU-resident debugger, using the debug module to set breakpoints and single-step and so on. So you should be able to program it to cause the traps you want. Note though that this probably won't work (or will misbehave) if you have your code trying to write to the debug module while a debug pod is attached and using it. One or the other. Or the approach I had was to have the code DETECT that the debug pod was connected (in the MPC860 some registers went from read-write to read-only) and enable the traps when the debug pod wasn't connected.

I can send you the MPC860 code if that might help. I think the debug modules are "related".

> In the ColdFire V4 MCF54418 memory map, address zero is a valid address, but is mapped to FlexBus

So what? The TLBs enable VIRTUAL memory, so you cam map any physical address to any virtual address. You can map NULL pointer accesses to any spare (or real) physical addresses and map any devices at zero to anywhere else in the address space.

Read this one for someone who had problems with this chip performing "Speculative Fetches" to NULL pointers and locking up for a long time as a result.

https://community.freescale.com/message/326812#326812

Tom

982 Views
colin
Contributor III

Good ideas, Tom.  After much effort, I have good results from using the WDEBUG instruction to set up the Debug Module with address breakpoints for a range of memory around address zero.  The main issue has been getting the proper program counter value for the offending instruction.  I have a custom unexpected interrupt handler that I have registered with MQX, but for some reason it doesn't get the final stack frame in the same way for the Debug Exception as it does for other exceptions, such as Access Error.  I assume this is the fault of MQX trying to be too clever for its own good, rather than a ColdFire MCU shortcoming.

Using the MMU sounds like a better and more powerful solution in most ways, though the speculative fetching issue could make it unusable for protecting against null pointer reads.  It seems like you could enable the MMU in a very simple way, by inserting locked TLB entries for the necessary regions, but there are possibly more than would be practical to do, depending on where the memory-mapped peripherals are located and whether they are in a single 16 MB block.

Anyway, thanks for the response.  I think I have a workable solution now.

0 Kudos

982 Views
TomE
Specialist II

> I assume this is the fault of MQX trying to be too clever for its own good, rather than a ColdFire MCU shortcoming.

Does MQX come with sources? You should be able to find out what it is doing if it does.


if not, there's probably nothing preventing you from installing your own interrupt vector, and handling the exception yourself.

0 Kudos