How to address main memory in PASM?
RalfSt
Posts: 19
Hi,
I'm trying for hours to access main memory and become more and more confused.
I try to access the main memory like shown in the following code:
This kind of code sometimes works, sometimes not. It depends on the position of the instructions. So I think I'm accessing memory, but not the one I want. I guess I overwrite some instructions.
Now I figured out that the addresses of #mainmem does not make much sense.
I declared the #mainmem as follows:
Looking at the addresses now tells me, that #mainmem is 0x00000000 and #other is 0x00000001.
Why is the distance between the two longs only 1?
And why starts the address as 0?
Is this the right way to declare "global" variables? In spin I've to use VAR, but then the symbols are not available to the assembler.
ps.: I use OpenSpin as assembler
I'm trying for hours to access main memory and become more and more confused.
I try to access the main memory like shown in the following code:
DAT org 0 test mov :addr, #mainmem movd :addr, #mainmem >> 9 rdlong :data, :addr jmp #test :addr res 1 :data res 1 fit
This kind of code sometimes works, sometimes not. It depends on the position of the instructions. So I think I'm accessing memory, but not the one I want. I guess I overwrite some instructions.
Now I figured out that the addresses of #mainmem does not make much sense.
I declared the #mainmem as follows:
PUB main cognew(@blink, 0) ' … more cogs started … cognew(@test, 0) cogstop(cogid) DAT mainmem long 0 ' For testing DAT other long 0 ' For testing
Looking at the addresses now tells me, that #mainmem is 0x00000000 and #other is 0x00000001.
Why is the distance between the two longs only 1?
And why starts the address as 0?
Is this the right way to declare "global" variables? In spin I've to use VAR, but then the symbols are not available to the assembler.
ps.: I use OpenSpin as assembler
Comments
In some non-standard assemblers (bstc, fastspin, I think homespun) there is a triple @ operator that does give the absolute HUB address of a symbol. The forum messes up the at sign, so I'm going to insert spaces between them, but in the real program the 3 at signs should come immediately together:
There are multiple correct ways of doing it, here are some of them:
1. Pass a pointer to one variable in through the PAR register (= the second parameter to cognew) Advantages:
- No code patching => no issues when multiple cogs are being started
Disadvantages:
- Only one pointer - If you need more you need to either use multiple "adjacent" memory locations (= an array or multiple variables defined in a particular order) or add an additional layer of indirection
2. Patch in the pointers before starting the cog
Advantages:
- Multiple pointers without any mess
Disadvantages:
- Can cause issues when starting multiple cogs in quick succession (IIRC a cog needs roughly 8192 cycles to start up and fill its memory). When in doubt, add a waitcnt after the cognew
3. Use manually allocated memory at the end of RAM (here: last LONG at $7FFC) Advantages:
- Smaller code
- Nicer in an application that consists of mostly/only custom PASM
Disadvantages:
- Is a huge mess to keep track of
- Not suited for "plug-and-play" reusable Spin objects
This is very helpful information.
I'm writing an XMM application in C using the Catalina compiler. This is due to a bunch of menus and stuff that I can't fit into CMM mode.
But I also need to run another cog to handle traffic management to a GPS receiver and some motors.
Unfortunately due to the caching issue within XMM, Catalina is unable to start another cog containing C code. But it can start another cog to run Spin or Assembly code.
So I'm thinking about writing the traffic manager code in Assembly.
I'm using the SMALL XMM memory model, meaning that all of the variables I'm using are contained within HubRam.
I'm now wondering if I create a structure in C that contains all of the variables the traffic manager needs, and then pass a pointer to that structure to the cog running the Assembly code, if it will work. At first glance it seems that it should.
Thanks for giving me some ideas on how to do this...
Method 2 works perfectly for my purpose.
I know exactly how many memory I need for each buffer and I only start one instance/cog for each code "segment".
So I can simply assign all memory addresses first and then start the cogs.