@ersmith said:
I'd really need more context to try to guess what's wrong. In one of your other posts you mentioned using a conditional debug in assembly (like if_b DEBUG()). The hardware doesn't actually support that, and so it should produce an error in flexprop, but if it somehow gets through it'll do weird things.
The particular weird thing that happens (when C=0 in that case) is that INT0 gets triggered without latching the BRK argument. So it'll repeat the processing of the most recent debug statement. If the cog never did a debug before, I think it defaults to $00, which IIRC triggers single step mode, which FlexProp doesn't have a way to handle. That would look a lot like a hard crash (incl. garbage spew on the terminal).
Is it possible to have some files of your project compile to byte code and some to machine code? I'm thinking about a software radio, with dsp compiled to machine code with quite a few largish buffers taking up memory and the gui running as byte code to fit in the remaining space. If this has been answered elsewhere, could someone point me to it please? Cheers, Bob
@bob_g4bby said:
Is it possible to have some files of your project compile to byte code and some to machine code? I'm thinking about a software radio, with dsp compiled to machine code with quite a few largish buffers taking up memory and the gui running as byte code to fit in the remaining space. If this has been answered elsewhere, could someone point me to it please? Cheers, Bob
Unfortunately that is difficult to do. It is possible, if you can completely separate the two parts -- @Wuerfel_21 did something like this with one of her game emulators (NeoYume and/or MegaYume) where she basically compiled two independent programs with different flags, one of them with the -E -H xxx flags so that it would run at a different hub address. This "upper" program could then be run by the "lower" program.
Another possibility is to use the -W flag to produce "wrapped" Spin code that's basically inline assembly. But that isn't well tested and probably doesn't work very well.
I would suggest as a first step just compiling everything into bytecode with -2nu, and then using inline assembly to accelerate the dsp part as necessary. That would be much easier than the other options.
Thank you for the advice, @ersmith . I've started with a DSP library made of inline assembly methods working on arrays - just about to add the cordic functions, which will be pretty fast thanks to the use of a cog pair with shared lut. Quite a tricky ballet dance to coordinate the two cogs to give 14 cycles per iq sample. My initial experiments indicate that a string of these methods running in a byte code program would spend by far the most time in the inline code and very little time in Spin.
So your compiler gives me a chance to compile either way and find out which fits inside 500k.
Cheers, bob
@ersmith Testing out Spin2 on P1...
How does one set the clock? I can't find anything in the docs about it...
This works, although obviously shouldn't:
CON
_clkfreq = 320_000_000
It is just automatically always setting the clock to 80 MHz?
Found that you can set the clock the P1 one way in Spin2 for P1, but setting to anything other than 80 MHz seems to break the serial interface.
So, maybe best to just let it automatically set itself for 80 MHz and leave off the con section for clock?
Also, things like "pinh" seem to work, but should really be "_pinh" right?
Actually, found a note in the docs:
Note that in Spin2
mode many of these are available without the leading underscore, and in fact
it's better to use the non-underscore versions since those are also supported in
the official Parallax compiler.
Seems pinf() should be in this section too, but it does seem to work regardless...
@ersmith Seeing something in Spin manual that am not understanding...
Object pointers
The proposed Spin2 syntax for abstract object definitions and object pointers is
accepted by flexspin, even in Spin1 mode. A declaration like:
OBJ
fds = "FullDuplexSerial"
declares fds as having the methods of a FullDuplexSerial object, but without
any actual variable or storage being instantiated. Symbols declared this way
may be used to cast parameters to an object type, for example:
PUB print(f, c)
fds[f].dec(c)
PUB doprint22
print(@aFullDuplexSerialObj, 22)
Maybe slow today, but isn't fds = "FullDuplexSerial" just the regular way of declaring an object?
Also where is the "a" in "@aFullDuplexSerialObj" coming from? Is that a typo?
And, what about the "Obj" at the end? Where does that come from?
Ok, maybe seeing that usual way is fds : "FullDuplexSerial". So, replacing colon with equal sign is the difference.
@Rayman said:
@ersmith Testing out Spin2 on P1...
How does one set the clock? I can't find anything in the docs about it...
This works, although obviously shouldn't:
CON
_clkfreq = 320_000_000
On P1 you need to set up a _clkmode constant (just like you do for Spin1 code). If there isn't one there then any _clkfreq constants are ignored. Probably there should be a warning for this case.
Found that you can set the clock the P1 one way in Spin2 for P1, but setting to anything other than 80 MHz seems to break the serial interface.
So, maybe best to just let it automatically set itself for 80 MHz and leave off the con section for clock?
Hmmm, other frequencies should work for serial, but it's not tested much (P1 in general doesn't get much attention any more). So yeah, probably safest to just leave the default.
@Rayman said:
Also, things like "pinh" seem to work, but should really be "_pinh" right?
No, I think in Spin2 it's called pinh, isn't it? Has Chip changed that? The _pinh version is always there in all the languages though, so it's what I tend to use.
@Rayman said:
@ersmith Seeing something in Spin manual that am not understanding...
Object pointers
The proposed Spin2 syntax for abstract object definitions and object pointers is
accepted by flexspin, even in Spin1 mode. A declaration like:
OBJ
fds = "FullDuplexSerial"
declares fds as having the methods of a FullDuplexSerial object, but without
any actual variable or storage being instantiated. Symbols declared this way
may be used to cast parameters to an object type, for example:
PUB print(f, c)
fds[f].dec(c)
PUB doprint22
print(@aFullDuplexSerialObj, 22)
Maybe slow today, but isn't fds = "FullDuplexSerial" just the regular way of declaring an object?
As you figured out later, the difference is equal vs colon sign.
Also where is the "a" in "@aFullDuplexSerialObj" coming from? Is that a typo?
No, it's supposed to represent some concrete object whose address is being taken to pass to the print function. The example isn't quite complete. There should be a declaration like:
@Rayman said:
@ersmith Is there a fundamental reason why FatFs can't work with P1?
I'm thinking it should be able to work, but maybe I'm missing something?
I think the only fundamental issue is that it probably needs more memory than will fit on P1, or at least more than will fit comfortably. I could be wrong, but I don't think there'd be much space, if any, left after the file system code is included.
Comments
The particular weird thing that happens (when C=0 in that case) is that INT0 gets triggered without latching the BRK argument. So it'll repeat the processing of the most recent debug statement. If the cog never did a debug before, I think it defaults to $00, which IIRC triggers single step mode, which FlexProp doesn't have a way to handle. That would look a lot like a hard crash (incl. garbage spew on the terminal).
Is it possible to have some files of your project compile to byte code and some to machine code? I'm thinking about a software radio, with dsp compiled to machine code with quite a few largish buffers taking up memory and the gui running as byte code to fit in the remaining space. If this has been answered elsewhere, could someone point me to it please? Cheers, Bob
Unfortunately that is difficult to do. It is possible, if you can completely separate the two parts -- @Wuerfel_21 did something like this with one of her game emulators (NeoYume and/or MegaYume) where she basically compiled two independent programs with different flags, one of them with the
-E -H xxxflags so that it would run at a different hub address. This "upper" program could then be run by the "lower" program.Another possibility is to use the
-Wflag to produce "wrapped" Spin code that's basically inline assembly. But that isn't well tested and probably doesn't work very well.I would suggest as a first step just compiling everything into bytecode with
-2nu, and then using inline assembly to accelerate the dsp part as necessary. That would be much easier than the other options.Thank you for the advice, @ersmith . I've started with a DSP library made of inline assembly methods working on arrays - just about to add the cordic functions, which will be pretty fast thanks to the use of a cog pair with shared lut. Quite a tricky ballet dance to coordinate the two cogs to give 14 cycles per iq sample. My initial experiments indicate that a string of these methods running in a byte code program would spend by far the most time in the inline code and very little time in Spin.
So your compiler gives me a chance to compile either way and find out which fits inside 500k.
Cheers, bob
@ersmith Testing out Spin2 on P1...
How does one set the clock? I can't find anything in the docs about it...
This works, although obviously shouldn't:
CON _clkfreq = 320_000_000It is just automatically always setting the clock to 80 MHz?
Found that you can set the clock the P1 one way in Spin2 for P1, but setting to anything other than 80 MHz seems to break the serial interface.
So, maybe best to just let it automatically set itself for 80 MHz and leave off the con section for clock?
Also, things like "pinh" seem to work, but should really be "_pinh" right?
Actually, found a note in the docs:
Seems pinf() should be in this section too, but it does seem to work regardless...
Should Pinfields work with Spin2 for P1?
Thought they might with some under the hood magic, but seems like they don't.
@ersmith Seeing something in Spin manual that am not understanding...
Maybe slow today, but isn't
fds = "FullDuplexSerial"just the regular way of declaring an object?Also where is the "a" in "@aFullDuplexSerialObj" coming from? Is that a typo?
And, what about the "Obj" at the end? Where does that come from?
Ok, maybe seeing that usual way is
fds : "FullDuplexSerial". So, replacing colon with equal sign is the difference.On P1 you need to set up a
_clkmodeconstant (just like you do for Spin1 code). If there isn't one there then any_clkfreqconstants are ignored. Probably there should be a warning for this case.Hmmm, other frequencies should work for serial, but it's not tested much (P1 in general doesn't get much attention any more). So yeah, probably safest to just leave the default.
No, I think in Spin2 it's called
pinh, isn't it? Has Chip changed that? The_pinhversion is always there in all the languages though, so it's what I tend to use.As you figured out later, the difference is equal vs colon sign.
No, it's supposed to represent some concrete object whose address is being taken to pass to the
printfunction. The example isn't quite complete. There should be a declaration like:Interesting error when clicking on an object in Spin2 file when compiling for P1...
Seems that FlexProp wants the extension specified in this case...
Maybe it could assume that a Spin2 file will have objects that are also Spin2, unless otherwise specified?
@Rayman that's a typo in the GUI source code (Tcl/Tk, which is interpreted). It's fixed in github now, thanks.
@ersmith Is there a fundamental reason why FatFs can't work with P1?
I'm thinking it should be able to work, but maybe I'm missing something?
I think the only fundamental issue is that it probably needs more memory than will fit on P1, or at least more than will fit comfortably. I could be wrong, but I don't think there'd be much space, if any, left after the file system code is included.
Ok, yeah can see that
Thanks
@ersmith Seeing a possible issue with waitus(2) with P1 in Spin2 mode...
Seems to take ~10x longer than it should... See attached code.
I see there's a lot going on in the waitus() assembly, so maybe P1 just isn't fast enough for waitus(2)?