HUB RAM code location (?)
I have a quick question on executing code from HUB. The following code does not work when I begin cog execution from HUB memory $1600. I do not understand this. If I run from HUB @start ($1498) it works.
What am I not seeing here?
CON
_clkfreq = 297_000_000
CLK_FREQ = 297_000_000
ctreg = $100
PUB main() | addr
'addr := @start
addr := $1600
org
coginit #%1_0_0010, addr
end
debug(uhex(addr))
DAT
orgh $1600
start getct ctreg
.loop drvnot #56
addct1 ctreg, ##CLK_FREQ
waitct1
jmp #.loop
Does not work:
Works:
Comments
This doesn't work because Spin memory layout just doesn't work that way. You need to get the address at runtime using the @ operator. Just is like that. The compiler accepting ORGH with a parameter looks like a bug.
Also, why are you using inline assembly for coginit? There's a perfectly good coginit function. Also, there are symbols for cog startup modes, such as
HUBEXEC_NEW
, see Spin2 manual.So, stick with the following:
CON _clkfreq = 297_000_000 CLK_FREQ = 297_000_000 ctreg = $100 PUB main() | addr addr := @start coginit(1, addr, 0) DAT orgh $1600 start getct ctreg .loop drvnot #56 addct1 ctreg, ##CLK_FREQ waitct1 jmp #.loop
I assume this loads COG RAM?
Well, if we're at it:
CON _clkfreq = 297_000_000 PUB main() coginit(COGEXEC_NEW, @start, 0) DAT org start getct ctreg .loop drvnot #56 addct1 ctreg, ##_clkfreq waitct1 jmp #.loop ctreg res 1
Yes. You need to use plain ORG for cog-mode assembly, otherwise strange things will happen to you
All very good.
I guess I am at a loss on how to execute code from HUB.
This is wrong:
CON _clkfreq = 297_000_000 CLK_FREQ = 297_000_000 ctreg = $100 PUB main() coginit(1, @cog1, 0) DAT org cog1 drvl #57 jmp #start orgh $1600 start getct ctreg .loop drvnot #56 addct1 ctreg, ##CLK_FREQ waitct1 jmp #.loop
You use HUBEXEC_NEW. But that raises the issue that you need to define some Cog RAM locations to use as registers.
CON _xtlfreq = 20_000_000 'The external crystal frequency. Use "_xinfreq" if a buffered oscillator _clkfreq = 100_000_000 'PLL to be used to set sysclock frequency PUB main() coginit(HUBEXEC_NEW, @start, 0) DAT orgh start getct ctreg .loop drvnot #56 addct1 ctreg, ##clkfreq_ waitct1 jmp #.loop org ctreg res 1
EDIT: Doh! put in HUBEXEC_NEW
That is sort of getting back to the point where I started the post. I had specified a HUB address for the code and it was not behaving the way I expected. Is it possible to load HUB code into other locations besides orgh $400? Or, similarly, to load different code sections into non-continuous HUB RAM locations and execute from either one or more cogs?
If you don't require Spin2 there then it can be bypassed and built directly to Pasm2. The Spin2 VM is an optional extra. To do this just remove all PUB/PRI methods and add any desired setup like setting the PLL. eg:
CON _xtlfreq = 20_000_000 'The external crystal frequency. Use "_xinfreq" if a buffered oscillator _clkfreq = 100_000_000 'PLL to be used to set sysclock frequency DAT org HUBSET ##clkmode_ & !%11 'start external clock, stay in RCFAST mode WAITX ##20_000_000/100 'allow 10ms for external clock to stabilize HUBSET ##clkmode_ 'switch to external clock mode coginit #HUBEXEC_NEW, ##@start .idle waitx #500 jmp #.idle orgh $1600 start getct ctreg .loop drvnot #56 addct1 ctreg, ##clkfreq_ waitct1 jmp #.loop org ctreg res 1
You'll note the use of
clkfreq_
. This is the correct symbol to always use in both Spin2 and Pasm2 code sections. Only use_clkfreq
to specify the desired clock frequency in the CON section.PS: Those HUBSETs I've cut'n'pasted from Chip's documentation.
You can also just use the
ASMCLK
macroOops, yes. Been a long time.
CON _xtlfreq = 20_000_000 'The external crystal frequency. Use "_xinfreq" if a buffered oscillator _clkfreq = 100_000_000 'PLL to be used to set sysclock frequency DAT org asmclk coginit #HUBEXEC_NEW, ##@start .idle waitx #500 jmp #.idle orgh $1600 start getct ctreg .loop drvnot #56 addct1 ctreg, ##clkfreq_ waitct1 jmp #.loop org ctreg res 1
The other thing to mention, for Spin2 programs, it's better to forgo use of
clkfreq_
even. Instead theclkfreq
system variable should be used there.Very helpful. Thank you both.
I will continue exploring.
Possibly the most important factor here that hasn’t been specifically stated:
Using orgh only gives information to the compiler (assembler) for calculation of addresses. It doesn’t actually automatically place the code at that address.
In your original example, start is at $1498, so to get it to run at $1600 you’d need to add $168 bytes of data between your existing PUB and DAT sections (safer option) or include another block of code to move the code to be executed into the desired position (danger of overwriting something important this way)
The question I have is why are you trying to force a particular code location?
In pure Pasm2 programs the ORGH address does mean it is located at that address - the binary file is null filled to suit. It assumes all binaries are built for and loaded to address zero.
I'm not sure how an arbitrary address hubRAM loadable module could be done without avoiding hard coded absolute addresses. Pnut's assembler has no support for that I don't think. I haven't tried looking to be honest.
Ok, but the original question involved the use of Spin2 also, so no padding and therefore what I said was correct in the context.