Running binaries from Hub RAM
d2rk
Posts: 31
There are two binaries in the Hub RAM with addresses binary1_addr and binary2_addr respectively. Each binary has fixed 16-byte header and represents the next program:
compiled with LMM model. The following code executes each binary one by one on a new cog:
where interpreter is
As a result each cog should print a message with test and cog id. The output:
As can be seen, from some moment the first test occupied two cogs. Where can be a problem and how to fix it?
Thank you.
int main() { while (1) { printf("TEST#%d on COG#%d\n", TEST_ID, cogid()); msec_delay(DELAY); /* each test has own delay value */ } return 0; }
compiled with LMM model. The following code executes each binary one by one on a new cog:
add binary1_addr, #4 shl binary1_addr, #16 mov dst, interpreter or dst, binary1_addr coginit dst mov time, cnt ' small delay to allow COG to settle add time, delay waitcnt time, #0 add binary2_addr, #4 shl binary2_addr, #16 mov dst, interpreter or dst, binary2_addr coginit dst
where interpreter is
[INDENT]interpreter long ($0000 << 16) | ($F004 << 2) | %1000[/INDENT]
As a result each cog should print a message with test and cog id. The output:
TEST#1 on COG#0
TEST#1 on COG#0
TEST#1 on COG#0
TEST#2 on COG#1
TEST#1 on COG#0
TEST#2 on COG#1
TEST#1 on COG#0
TEST#2 on COG#1
TEST#2 on COG#1
TEST#1 on COG#0
TEST#2 on COG#1
TEST#2 on COG#1
TEST#1 on COG#0
TEST#1 on COG#1
TEST#1 on COG#0
TEST#1 on COG#1
TEST#1 on COG#0
TEST#1 on COG#1
TEST#1 on COG#0
TEST#1 on COG#1
As can be seen, from some moment the first test occupied two cogs. Where can be a problem and how to fix it?
Thank you.
Comments
If you want to run two different threads of C under the LMM kernel, you should have the same executable and use the _start_cog_thread function to start each thread with its own runtime and stack space.
If you really need separate executables, you're going to need to modify the LMM kernel to be able to locate the stack/heap in a constrained area that you set up for each program. This probably is not a trivial exercise.
Just started to review LMM kernel. I thought it will use right stack information from header.
It does, but that's assuming the interpreter has been kicked off by the original interpreter (via the aforementioned _start_cog_thread). You're trying to use the LMM kernel in a way it wasn't designed to be used, so I think you're blazing your own trail here...
Were the 2 programs linked to start at binary1_addr and binary2_addr? If so, how did you do that?
I have been able to run LMM C programs at address 0 while running Spin programs at higher addresses. I had to patch the startup code in the C code so that I could specify a stack address other than $8000.
It appears that program 1 and program 2 were identical in his test - although d2rk may want to run two different executables, it looks like he started by trying to run two instances of the same executable.
Now I need to solve the second problem. I will try to fix LMM interpreter first. Otherwise I have one more idea.
On this moment I modified crt0_lmm.s file with LMM kernel and made the stack pointer to be based on __hub_end value which is unique for each binary.
Dave,
How did you relocate the Spin programs? Did you do this manually, or do you have a programmatic way to do that? I saw this thread: http://forums.parallax.com/showthread.php?138534-Spin-modules-as-separate-relocatable-modules-(in-OS) and I'm guessing that you have solved that problem for Spinx (http://forums.parallax.com/showthread.php?123795-spinix). Do you have a pointer to the code and/or methodology you use to allow an arbitrary Spin program to be loaded at a different address?
I'm asking because I'd like to use arbitrary Spin objects from within a C program. I'd like to kick off the Spin interpreter running Spin in a separate cog, the Spin program would be located at a non-standard location in RAM (i.e. it wouldn't be at 0x20); that's the trick I don't currently know how to do. I'd use the more-or-less "standard" mailbox approach to send method requests through a mailbox and wait for the response; I think I know what to do in that regard.
Thanks!
- Ted
The Spin runner code normally puts the values of $FFFFFFF9 in the two longs (4 words) that make up the initial stack frame. This basically traps any aborts and discards the return value, and causes a return jump to location $FFF9 in the ROM. The code at $FFF9 does a cogstop(cogid), which stops the cog. I wanted to jump to an exit routine instead, so I set the initial stack frame up differently. word[dbase][-4] specifies the calling program's PBASE. The 2 least-signifcant bits are used to trap aborts and inidicate whether a return value should be pushed to the stack. PBASE is just given by @@0.
word[dbase][-3] is the calling programs VBASE. I get this from the address of the first long in the VAR section, which in my case is "firstvar". word[dbase][-2] is the value of DCURR that should be use after a return. I set this to 16 longs after DBASE. In theory, this would be set to DBASE plus four times the number of local variables that a method uses, but the exact value wasn't important in my case. word[dbase][-1] is the return address. In my case, I want it to return to my exit routine, which I placed as the first method in the object. This way I could obtain its address from the method table as word[pbase][2] + pbase.