Reply by Vladimir Vassilevsky April 6, 20072007-04-06

sconnet@gmail.com wrote:

> 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.
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 http://www.abvolt.com
Reply by Rob Windgassen April 6, 20072007-04-06
On Fri, 06 Apr 2007 12:53:34 -0700, sconnet wrote:

> 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
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).
> and > jump to it.
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.
> The function to be copied contains no library calls or > function calls.
Good.
> 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?
I don't know, depends on vxworks behaviour....
> When it jumps to the copied function in > unused RAM I get the error "invalid instruction" and the task > suspends.
Do you have more error status of the CPU (exception number, srr0, srr1 registers) ? Rob
Reply by April 6, 20072007-04-06
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();