copy function and run it

I am using a PPC750 and vxWorks. I am trying to copy a function outside of the text/data/bss segment into an unused portion of RAM and jump to it. The function to be copied contains no library calls or function calls. The executing function then copies a vxworks image from another location in user defined memory over top of the existing running image and jumps to it. Is this valid? People are telling me it should work but does not. When it jumps to the copied function in unused RAM I get the error "invalid instruction" and the task suspends. Listing the original function in the text segment, and the copied function in the unused portion of RAM show they are identical.

Can anyone help?

l copyImageAndBoot copyImageAndBoot 002ebf70 9421ffe0 stwu r1,-32(r1) 002ebf74 7c0802a6 mfspr r0,LR 002ebf78 93e1001c stw r31,28(r1) 002ebf7c 90010024 stw r0,36(r1) 002ebf80 7c3f0b78 or r31,r1,r1 002ebf84 907f0008 stw r3,8(r31) 002ebf88 3d20002f lis r9,0x2f # 47 002ebf8c 3869bfc8 addi r3,r9,0xbfc8 #

-16440 002ebf90 809f0008 lwz r4,8(r31) 002ebf94 38a00000 li r5,0x0 # 0 value = 0 = 0x0 l 0x00400000 00400000 9421ffe0 stwu r1,-32(r1) 00400004 7c0802a6 mfspr r0,LR 00400008 93e1001c stw r31,28(r1) 0040000c 90010024 stw r0,36(r1) 00400010 7c3f0b78 or r31,r1,r1 00400014 907f0008 stw r3,8(r31) 00400018 3d20002f lis r9,0x2f # 47 0040001c 3869bfc8 addi r3,r9,0xbfc8 #

-16440 00400020 809f0008 lwz r4,8(r31) 00400024 38a00000 li r5,0x0 # 0 value = 0 = 0x0

------------------------------------------------------- C O D E

------------------------------------------------------- #define MAX_BOOT_FUNC_SIZE 300 #define BOOT_FUNC_ADDRESS 0x00400000 #define VXWORKS_BOOT_ADDRESS 0x00010000 #define IMAGE_LOC ((unsigned char*)sysMemTop() + 0x8000)

typedef void (*ENTRYPOINT)(); typedef void (*COPYENTRYPOINT)(const void *);

void copyCodeAndRun(); void copyImageAndBoot(const void *src);

/* this function copies the copyImageAndBoot function outside of the existing running image and jumps to it

*/ void copyCodeAndRun() { COPYENTRYPOINT bootFunc = (COPYENTRYPOINT)BOOT_FUNC_ADDRESS;

char *destPtr = (char *)BOOT_FUNC_ADDRESS; const char *srcPtr = (const char *)copyImageAndBoot; int i;

/* Copy the boot function to a place where it won't be overwritten by the new boot image. */ for( i = 0; i < MAX_BOOT_FUNC_SIZE; ++i ) destPtr[i] = srcPtr[i];

/* take control of CPU */ (void)intLock(); (void)taskLock();

/* execute copied code */ bootFunc( IMAGE_LOC );

}

/* this function is copied to a location outside of the existing executing image. It then copies an alternate image over on top of the existing image and runs

*/ void copyImageAndBoot(const void *src) { ENTRYPOINT vxWorksBootAddr = (ENTRYPOINT)VXWORKS_BOOT_ADDRESS;

/* Copy 5 MB in 4-byte chunks */ size_t length = (1024 * 1024 * 5) / 4; uint32_t *destPtr = (uint32_t *)VXWORKS_BOOT_ADDRESS; const uint32_t *srcPtr = (const uint32_t *)src;

/* Copy the new image over the current running image. */ while( length-- ) *destPtr++ = *srcPtr++;

/* Jump to the new image entry point. */ vxWorksBootAddr();

Reply to
sconnet
Loading thread data ...

You must be sure that this part of memory is marked as executable w.r.t. the MMU (I don't know about vxworks how to check or do this).

Your code must be aware of the harvard architecture of PPC L1 caches (i.e. without coherency of the L1 instruction cache): Before jumping to the new code it must be flushed from the data caches, e.g. using dcbf instructions, and the corresponding address range must be invalidated in the instruction cache, using icbi instructions. The jump will then cause loading of the new code into instruction cache and execute it. Otherwise behaviour is undefined.

Good.

I don't know, depends on vxworks behaviour....

Do you have more error status of the CPU (exception number, srr0, srr1 registers) ?

Rob

Reply to
Rob Windgassen

I am not particularly familiar with the specifics of VxWorks, however I did the things similar to what you are trying to do. Yes, it is possible, however it requires a lot of care.

  1. Make sure your function is properly linked. I.e. the code is placed at one location, and it is supposed to run from the other location.
  2. There could be some agreement on the run time environment required to execute a function. Make sure the environment is correct at the location where the function is executed.
  3. A compiler could have optimized your function away as a dead code.
  4. It could be a problem with near/far memory access model depending on your CPU.
  5. Make sure that the location in the RAM is not used by anything else. You should define it as the dedicated section in the linker file.

Vladimir Vassilevsky

DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.