RCM6700 execute from bbram

I’m needing to run the 6700 at very low clock rates to minimize power consumption. Based on comments in low_power.lib it appears that the 6700 on chip ram will become corrupted when running below 12MHz. For my application this is actually OK as long as I can jump back through the reset vector based on an appropriate RTC value. I have written a small function that does what I want but now I need to …

a) somehow place the function in bbram (which is immune to the 12MHz limitation) either by forcing Dynamic C to generate the code there OR by copy the memory from codespace to bbram space.
b) Once the copy to bbram is done then I need to jump to that place in bbram where the code was relocated.

I’ve used _xalloc(x,2,XMEM_BB) to allocate a chunk of bbram but I’m stuck on moving the code to the allocated buffer and then getting it to execute.

Tips, Pointers, code samples appreciated!

Thanks
Jim

I think this will be very difficult to achieve unless you can lock down the system very tightly.

As well as relocating code to the BBRAM you would also need to relocate the stack as otherwise it will be trashed when you enter low power mode. Also, any variables used by your code and any routines it calls (including interrupt service routines etc) will need to be in BBRAM.

The documentation for the linker functionality in DC is almost non existant so figuring out how to force code to be placed in a particular RAM location is going to be difficult.

Your best bet would probably be to try and write your code as position independent assembly language (maybe using the listing file for the c code as a starting point), and using labels in the code to mark the start and end points. This will allow you copy the code to BBRAM. Calling the code should be possible through the use of a function pointer.

The only other fly in the ointment is whether the MMU configuration will cause problems if you are trying to execute code from data memory?

Sorry I can’t be more helpful :frowning:

Regards,
Peter

Peter…thanks for your reply. Some of the issues you brought up, I had anticipated, eg loss of stack, position independent code, etc.

I have written my “wait till RTC hits a certain time” routine in assembly. It uses no stack, nothing but relative jumps, and does not return. Given these characteristics I am hopeful that it will continue to execute properly without a functioning stack (I have also disabled all interrupts!) and when relocated to an arbitrary memory location.

“… figuring out how to force code to be placed in a particular RAM location is going to be difficult.” - Yes!! My fallback position is to try and use _xalloc() to get a buffer in bbram and then use either assembly code or something like (root2xmem, memcpy, memmove) to copy to the 100 bytes or so of my code to bbram. Have not gotten it to work yet but I think this is doable.

I’m still stumped on how to then jump to the start of my little code snippet once its relocated.

Thanks for your tips… Btw your posts on other topics are always educational…I lurk in this forum a fair bit!

Cheers,
Jim

Thanks Jim.

Once you can copy the code to xmem, executing it is easy. All you need is to define a pointer to a function and set it to the new address of the code then de-reference it to call the code.

e.g.

typedef void (*x_function)(void);

x_function fnptr;

fnptr = 0x1234;

fnptr();

or something similar.

Regards,
Peter

Regards,
Peter

Hi Peter,

Yes…I thought that would work but its a little trickier than that. As noted in my prior message, I’m using _xalloc() to get a buffer which is in bbram. It appears that the “address” value returned by _xalloc() is not the kind you can just assign to a pointer and then de-reference. I’m starting to think this has something to do with logical vs physical addresses and the necessary translations between them …and certainly highlights my ignorance in the area of the Rabbit/DynamicC MMU handling!

Thanks for the tips!

Regards,
Jim

Hi Jim,

I’ve had a look at what Dynamic C does for function pointers and it is a bit trickier. The BACnet stack uses function tables to provide access to functions based on object type so I looked at the listing file for some of the access to the tables.

The function pointer stored in the table is a 16 bit value which points to a code stub in root memory which performs the actual far jump to the code in xmem by using an LJP instruction. This requires stubs for each function that is called from a function pointer as the addresses are calculated at compile time.

You have two options in trying to replicate this for calling a function dynamically.

  1. Set up a dummy function which is called via a function pointer. Then use the function pointer to find the address of the stub in root memory and alter the address portion of the code to put your real address in it. You are dependent on the compiler producing the same code sequence for the stubs every time so that you know where to alter the 3 address bytes.

  2. Create a dummy function in root memory with some code in it to allocate space. Build your own stub dynamically by writing the opcodes directly at the address of the dummy function and then executing the dummy function. The code might be as simple as a single LLJP instruction (0x27) and the 3 byte address in PC low, PC high, Seg order.

Regards,
Peter

Hi Peter
Did some more reading. The problem I was having is definitely because _xalloc() returns a physical address so my attempt to blindly use it as a function pointer was doomed. It does seem like the newer DC “far” keyword may be of some use here. My impression is that “far” pointers (ie pointers to far things) are in fact physical address rather than logical address. Must still be used however as the target of a LLJP instruction as you suggested…we’ll see!

Cheers,
Jim