.... Mainly it's useful because it's written in C and doesn't use much of the standard library, so it was a good platform for testing fastspin's C support and shaking out bugs (which it did a lot of).
Do you know which C version that Lisp interpreter required ? Maybe that is already a C99 test ?
I wrote the Lisp interpreter several years ago for P1, and it was generic C89. I have compiled some programs that use C99 features, though (like fft_bench).
Another piece that can use some work is the IDE; spin2gui is just a toy that's designed to get people working with fastspin easily. It looks like @Rayman 's SpinEdit program is a great solution for Windows, and I think it's been made to work on Linux and the Mac using Wine. It might also be nice to be able to use fastspin with SimpleIDE and/or PropellerIDE. I think that shouldn't be too hard? But it's not something I have time to look at.
ersmith,
By porting libraries I assume you mean C standard library stuff, right? I found this recently: https://github.com/PetteriAimonen/Baselibc it's BSD license and meant to be very small. Perhaps we can just use it?
I don't have a lot of time, so I can't promise much, but I will try to use the C stuff in your compiler more. Perhaps take a stab at getting some of the Simple Libraries compiling and working? Maybe, the above libc?
ersmith,
By porting libraries I assume you mean C standard library stuff, right? I found this recently: https://github.com/PetteriAimonen/Baselibc it's BSD license and meant to be very small. Perhaps we can just use it?
Well, I was thinking both of the standard C library and the Simple libraries (and anything else Blockly needs).
For the standard library I think it makes sense for us to port the PropGCC library,since that already works on the Propeller and it's small and efficient. The stdio interface is probably the only part that'll be tricky, and I'd like to change that anyway (in PropGCC we used FILE handles directly instead of going through Unix like open(), read(), write(), and that ended up being kind of awkward).
I'm not too familiar with the Simple libraries, so it'd be great if someone else could take a look at those and see what needs to be done to port them.
I don't get it. I have not used your tool but I thought you said it does not support linking.
So does that mean every time I need to create a program everything get compiled again.
Yes, everything that's used in the program is compiled together. This allows the compiler to do whole-program optimization, including things like inlining any eligible functions and removing unused functions.
People have expressed concern that this will lead to slow compile times. I haven't found this to be an issue so far, for two reasons: (1) only the functions that are actually referenced are compiled, and (2) the largest possible program for the P1 is 32KB, and for P2 is 512KB. By today's standards those are miniscule, and modern computers should easily be able to compile such programs quickly.
If it becomes an issue then I'll revisit the linking question. For now I'm trying to get something that works first, then I'll look at optimizing it later.
Well with Arduino I wait 5 minutes while it complies everything and it's a pain after a while.
I think $THEY rebuild all libraries used in your project even for the slightest change in your sources.
If you want to avoid this, use AVR-GCC, make and friends without the Arduino-IDEEditor.
Well with Arduino I wait 5 minutes while it complies everything and it's a pain after a while.
Also a lot of the custom libraries have test code that is not compiled into the finished library. That will be hard to hide.
I don't know about Arduino: it sounds like they're doing things wrong. It's a different platform, using a different compiler, and compiling different libraries, so I'd say it may end up performing differently than fastspin.
I'd rather have a slow C compiler than no C compiler at all, so I'm just going to keep on developing fastspin and fix problems as they occur, rather than trying to forsee every possible issue and spending years trying to plan everything out. I'm not idealogically opposed to a linker, and if we had a standard one for the P2 I could use that. Perhaps you'd be good enough to port GNU binutils to the P2? Both p2gcc and fastspin could benefit from that.
Perhaps you'd be good enough to port GNU binutils to the P2? Both p2gcc and fastspin could benefit from that.
We have yet to decide if we want to use GAS or if we want to try to use Dave's p2asm assembler or your fastspin assembler. If we're going to use p2asm or fastspin, we need to get whichever one we choose to produce ELF files that are acceptable to the GNU linker and also modify the GCC driver program to invoke it instead of GAS.
Edit: Well, I guess we don't need to modify the GCC driver program if we're not using the GCC C/C++ compiler.
ersmith,
I'll start looking at the Simple Libraries for porting. I'm going to assume that we want to make them able to work with both P1 and P2, since your compiler targets both.
People have expressed concern that this will lead to slow compile times. I haven't found this to be an issue so far, for two reasons: (1) only the functions that are actually referenced are compiled, and (2) the largest possible program for the P1 is 32KB, and for P2 is 512KB. By today's standards those are miniscule, and modern computers should easily be able to compile such programs quickly.
Yes, PCs are easily fast enough today, to build-all, and that does make for more predictable results and safer archiving and version control.
The only time linking is useful, is when your compiler either cannot compile all the sources, or cannot access all the sources.
Even in the latter case, a relocatable object file could be considered to be 'source' so you could 'compile' that to achieve apparent linking ?
ersmith,
I'll start looking at the Simple Libraries for porting. I'm going to assume that we want to make them able to work with both P1 and P2, since your compiler targets both.
I've been using ADCs to learn the P2 tools. I've run the MCP3204 in spin2gui basic and TAQOZ, and run ADC using smart pins in spin2+p2asm, and TAQOZ. I've been wanting to do it in basic, but I don't think there are Basic commands for the smart pin functions.
Looking at ersmiths asm example above, I decided to give basic + p2asm a try. The code below works using pin 22 as a smart pin. I will eventually upgrade it to auto calibrate, but I wanted to show it as is so maybe there will be some others using smart pins with spin2gui basic.
Any suggestions on how to simplify or improve the code are welcome.
Tom
' Use Smart Pin in ADC Mode
' clock will be set to 180MHz
' set terminal baud to 230400
const _mode = 0x010c4708
const _clkfreq = 180_000_000
clkset(_mode, _clkfreq)
_setbaud(230400)
' **** Constants
const ADC_MODE = 0b0000_0000_000_100011_0000000_00_01111_0
const ADC_PIN = 22
const ADC_CYCLES = 16384
const valmin = 2850
const valmax = 13343
' **** variables for demo (calling) program
dim raw1
dim value1
dim volts#
' **** variables needed in calling program for function fadc()
dim stack(64)
dim shared flag = 0 ' 0 = raw data not ready, 1 = ready
' flag=0, calling program waits until flag=1, and sets flag=0
' when data is taken.
' ****************************
function fadc() ' ***** define function fadc()
' returns: raw ADC value
' flag = 0 data not ready, 1 = data ready, wait until taken
' ****************************
dim time, val ' **** define fadc locals
' **** in fadc use inline asm to setup & start ADC smartpin
' ADC_MODE, ADC_PIN, and ADC_CYCLES, and set ADC_PIN dir high
asm
wrpin ADC_MODE, ADC_PIN
wxpin ADC_CYCLES, ADC_PIN
wypin 0, ADC_PIN
dirh ADC_PIN
getct time
addct1 time, ADC_CYCLES
end asm
while 1 ' **** basic infinite repeat
pausems 100 ' wait sufficient time for ADC_CYCLES
' **** get smartpin reading
' ***** start 2nd asm, rdpin and put value in local
asm
waitct1
addct1 time, ADC_CYCLES
rdpin val, ADC_PIN
end asm
' *** put local in global & use flags as needed
value1 = val
flag = 1 ' tell calling cog data is ready
while flag = 1 ' wait until calling cog takes data
wend
wend ' loop back to basic infinite repeat
end function
' *************************
' ***** Test fadc() function
' **** call fadc in new cog
var a = cpu(fadc(), @stack(1)) ' run function in new cog, a is cog number
pausems(20) ' time for cog to start
while 1
while flag = 0 ' wait until data ready
wend
raw1 = value1
volts# = (raw1 - valmin) * 3300 / (valmax - valmin)
volts# = volts# / 1000
flag = 0 ' data received
print "raw1 = "; raw1, "volts = "; volts#
pausems(300)
wend
I corrected the code in the post above. I had copied the voltage calculation from my MCP3204 program which used 5v as reference. The smartpin version uses 3.3 v.
Tom
There are new releases of spin2gui and fastspin. This release has Dave Hein's latest loadp2, and a bunch of bug fixes and improvements to fastspin. The fastspin changes are more focused on BASIC and Spin this time around. Highlights are:
- Support for old school BASIC programs with line numbers. This is still a bit incomplete, but it's pretty easy to port programs from www.classicbasicgames.org, for example
- Support for shorter BASIC lambda expressions (kind of the opposite end of the pole from the above)
- A new Spin construct, "PUB FILE", which allows you to import functions from another file and even another language. For example, to add an "atoi" method to your object you can write:
PUB FILE "libc/stdlib/atoi.c" atoi(x)
This will fetch the definition of atoi from the C library "atoi.c" file and include it as a method of the curent Spin object.
If it becomes an issue then I'll revisit the linking question. For now I'm trying to get something that works first, then I'll look at optimizing it later.
@ersmith
I am having problems with the latest version of spin2gui (v1.3.7) running the smartpin adc basic program 4 posts above this one. The program runs fine in v1.3.6.
The errors I get are in the function fadc(). I've copied that section below and marked the lines that are shown as errors with +++++.
The first error is:
C:/Users/tandj/Documents/robot/P2ES/Tests/smartpin_adc.bas(46) error: syntax error, unexpected while, expecting end
Then I commented out line 46 and all following lines up to the next +++++ and got this error:
... /smartpin_adc.bas(58) error: syntax error, unexpected identifier `value1', expecting end
I'm not sure if there are any other errors.
**edit** I also tried just commenting out the while 1 on line 46. I got an error referring to the following line
pausems 100
So it appears that anything after the
end asm
causes an error.
Any ideas what is(are) the problem(s)?(is it supposed to only allow 1 in-line asm and then end the function?)
Tom
function fadc() ' ***** define function fadc()
' returns: raw ADC value
' flag = 0 data not ready, 1 = data ready, wait until taken
' ****************************
dim time, val ' **** define fadc locals
' **** in fadc use inline asm to setup & start ADC smartpin
' ADC_MODE, ADC_PIN, and ADC_CYCLES, and set ADC_PIN dir high
asm
wrpin ADC_MODE, ADC_PIN
wxpin ADC_CYCLES, ADC_PIN
wypin 0, ADC_PIN
dirh ADC_PIN
getct time
addct1 time, ADC_CYCLES
end asm
' +++++ the line below is line (46) referred to in the first error statement.
while 1 ' **** basic infinite repeat
pausems 100 ' wait sufficient time for ADC_CYCLES
' **** get smartpin reading
' ***** start 2nd asm, rdpin and put value in local
asm
waitct1
addct1 time, ADC_CYCLES
rdpin val, ADC_PIN
end asm
' *** put local in global & use flags as needed
' +++++ the next line is line 58 where the 2nd error was reported.
value1 = val
flag = 1 ' tell calling cog data is ready
while flag = 1 ' wait until calling cog takes data
wend
wend ' loop back to basic infinite repeat
end function
for the first asm block and got error messages for each of the asm lines that used constants stating that they had to be immediates. I put # in front of each constant and that error went away.
@twm47099 : Your program is (mostly) OK, you just ran into a bug in the new BASIC parsing code. Due to a typo in the grammar the "end asm" has to be the last thing in a function. I didn't notice this because (a) it only affects BASIC and (b) I usually put inline asm into small functions that don't do anything else, and rely on the compiler to inline those. But it should have worked to have multiple inline asms in one function.
I've attached an updated fastspin.exe to this post; if you replace the one in spin2gui/bin/fastspin.exe with the one from this zip file it should correct that problem.
The immediates before constants was something that should always have been there, unless you really intended to directly access locations in COG RAM. The old inline assembly parser was kind of lax about this, if it saw a number or a constant it just assumed you wanted an immediate. But in fact PASM does allow you to directly specify a COG memory location, so the new parser does distinguish between these. This was only ever an issue in inline assembly, regular assembly in DAT blocks always required # for immediate constants and could handle COG memory addresses. The inline assembly parser is a bit different because it has to cope with local variables, and that's where the confusion came in.
@ersmith,
Thanks. The fixed fastspin worked.
Re the use of immediate constants. When I originally wrote the program, I lifted the P2asm from a spin2+asm program. The original had the constants prefaced by ##. I wasn't sure how basic would deal with constants and even if they had to be declared in the function or not. So I intended to just try different ways until it worked. Using v1.3.6 it worked on my first try (in "main" without #). I agree the version 1.3.7 is more consistent (although would it ever require ##)?
Rereading the Basic documentation, I am confused about a few things.
I don't understand how shared and member variables work. In the program above I declare value1 as
dim value1
. That variable is used in bot the function running in the second cog and in the first cog to transfer its value from the function to "main". In my most recent version I have changed it to
dim shared value1
I originally defined flag the same way, but changed it to
dim shared flag
. It is used to signal each cog when the other is ready for a transfer.
In all cases the program ran correctly. When would it make a difference?
Where are variables stored? (HUB, cog?) How about constants?
@ersmith,
Thanks. The fixed fastspin worked.
Re the use of immediate constants. When I originally wrote the program, I lifted the P2asm from a spin2+asm program. The original had the constants prefaced by ##. I wasn't sure how basic would deal with constants and even if they had to be declared in the function or not. So I intended to just try different ways until it worked. Using v1.3.6 it worked on my first try (in "main" without #). I agree the version 1.3.7 is more consistent (although would it ever require ##)?
In general you should use the same syntax as in Spin2+PASM. So ## would probably be the best thinig to put in there, although as you've discovered the inline assembler is more forgiving and will accept just # (and convert it to ## if necessary).
That raises an interesting difference with the inline assembler: it goes through the optimizer, so it does change things in the code (like converting ## to # if it can). In Spin2 DAT sections this is not the case, if you write ## then you'll always get an AUG prefix (so the instruction will really take 8 longs and 4 cycles) even if the immediate would fit in 4 bytes.
Rereading the Basic documentation, I am confused about a few things.
I don't understand how shared and member variables work. In the program above I declare value1 as
dim value1
. That variable is used in bot the function running in the second cog and in the first cog to transfer its value from the function to "main". In my most recent version I have changed it to
dim shared value1
"dim shared" always puts things in HUB, and there is only one copy shared by all instances of the object. It's like a value in a DAT section in Spin. Just plain "dim" usually goes in HUB (unless you use a special compiler flag) but it's like a member variable in Spin, each copy of the class gets its own copy of the variable. For the top level program this doesn't really matter, both "dim shared" and "dim" will end up being pretty similar. It matters only if you want to write re-usable classes in BASIC.
Where are variables stored? (HUB, cog?) How about constants?
Shared variables always go in HUB. "dim" at the top level (outside sub or function declarations) declares a member variable, which goes in HUB. "dim" inside a sub or function creates a local variable, which usually goes in COG memory unless you take its address or there's something else funny going on in the function, in which case it'll go on the stack in HUB memory.
Constants usually don't end up being "stored" anywhere, they're encoded directly in the instruction as an immediate value.
Eric,
Thanks for the info. I am trying to understand more how these compilers work and how to best use them.
In my program I have 2 in-line asm segments in the function. The first "turns on" the adc smart pin. The second is embedded in a BASIC while loop. The asm reads the value from the smart pin and stores it in a variable and then exits the asm. The BASIC stores the local (adc value) into the shared variable that is then read by a different cog. After testing if the value was retrieved by the cog, the while loop then repeats.
If I read the documentation correctly (along with what you had posted earlier in the thread) I can't have the asm store the rdpin result into a global. Is that correct. Is there any way to start the smart pin and then loop in asm to directly send the result to the calling cog or is the way I'm doing it reasonable. I like my method because I can see what is happening.
I looked at using pointers, but just ended up confusing myself.
In my program I have 2 in-line asm segments in the function. The first "turns on" the adc smart pin. The second is embedded in a BASIC while loop. The asm reads the value from the smart pin and stores it in a variable and then exits the asm. The BASIC stores the local (adc value) into the shared variable that is then read by a different cog. After testing if the value was retrieved by the cog, the while loop then repeats.
That sounds pretty reasonable.
In general I like to keep the inline asm to a minimum, because the compiler produces pretty decent code on its own. So usually I just use inline asm to do some instruction that isn't built in to the compiler, and then do all the looping and variable update / manipulation in a high level language.
You could try to mess around with pointers and having the asm store directly with wrlong, but it's likely you'll end up with the same code anyway and it'll be more confusing . The compiler will optimize the combination of your code inline code and the code it's creating from BASIC, so for example:
dim shared pinval
sub getpin(p)
dim val as integer
dim dummy as integer
dim one
one = 1 ' redundant, we can just use #1 in the rdpin
asm
rdpin val, one
end asm
dummy = val ' redundant copy
pinval = dummy
end sub
(Unless you turn off the optimizer, but I wouldn't usually do that unless you're hunting for a bug.)
Given that, it's probably best to write the code in whatever way is simplest and clearest for you, and not to worry too much about optimizing or about writing as much as possible in assembly.
'' doesn't set clock to output
outa[clk] := outa[di] := outa[cs] := 1
dira[clk] := dira[di] := dira[cs] := 1
' doesn't set di output
outa[clk] := outa[di] := 1
outa[cs] := dira[clk] := 1
dira[di] := dira[cs] := 1
'' but this works
outa[clk] := 1
outa[di] := 1
outa[cs] := 1
dira[clk] := 1
dira[di] := 1
dira[cs] := 1
* edit - this was with Fastspin V3.9.19, pretty sure that's the latest. I also keep getting "error: Unknown symbol COUNT_" when I try to compile the file in question as the root object?
That raises an interesting difference with the inline assembler: it goes through the optimizer, so it does change things in the code (like converting ## to # if it can). In Spin2 DAT sections this is not the case, if you write ## then you'll always get an AUG prefix (so the instruction will really take 8 longs and 4 cycles) even if the immediate would fit in 4 bytes.
That raises an interesting difference with the inline assembler: it goes through the optimizer, so it does change things in the code (like converting ## to # if it can). In Spin2 DAT sections this is not the case, if you write ## then you'll always get an AUG prefix (so the instruction will really take 8 longs and 4 cycles) even if the immediate would fit in 4 bytes.
There are new releases of fastspin and spin2gui. The changes are mainly bug fixes to fastspin:
Version 3.9.20
- Allow closures to access variables and functions in the enclosing object
- Fixed some parsing problems with inline assembly
- Fixed incorrect inlining of some functions in -O2
- Fixed some C parser errors
- Fixed some C type conversion errors
- Fixed encodings of setpiv and setpix instructions
- Fixed a bug in chained assignments of register ranges
There is a new release of spin2gui and of fastspin. The changes are:
- Increased stack size on Windows to prevent a crash
- Added if_00, if_same, and other missing P2 conditions
- Fixed an incorrect result for ">| 0" on P2
- Added some P2 specific optimizations
- Added Spin serial drivers to default include directory
- Rewrote C static and variable handling code to fix a number of bugs and to allow nested variable scopes to work
- Fixed an optimizer bug where register masks could be created before the variables they dependend on were initialized
- Fixed a P2 optimizer bug affecting varargs
- Fixed several C type casting bugs including conversion of arrays and functions to pointers
- Fixed handling of enums in C
- Fixed checking for duplicate labels
- Added some standard Spin serial routines to the include/spin folder
Comments
I wrote the Lisp interpreter several years ago for P1, and it was generic C89. I have compiled some programs that use C99 features, though (like fft_bench).
By porting libraries I assume you mean C standard library stuff, right? I found this recently: https://github.com/PetteriAimonen/Baselibc it's BSD license and meant to be very small. Perhaps we can just use it?
I don't have a lot of time, so I can't promise much, but I will try to use the C stuff in your compiler more. Perhaps take a stab at getting some of the Simple Libraries compiling and working? Maybe, the above libc?
For the standard library I think it makes sense for us to port the PropGCC library,since that already works on the Propeller and it's small and efficient. The stdio interface is probably the only part that'll be tricky, and I'd like to change that anyway (in PropGCC we used FILE handles directly instead of going through Unix like open(), read(), write(), and that ended up being kind of awkward).
I'm not too familiar with the Simple libraries, so it'd be great if someone else could take a look at those and see what needs to be done to port them.
Thanks,
Eric
So does that mean every time I need to create a program everything get compiled again.
Mike
Yes, everything that's used in the program is compiled together. This allows the compiler to do whole-program optimization, including things like inlining any eligible functions and removing unused functions.
People have expressed concern that this will lead to slow compile times. I haven't found this to be an issue so far, for two reasons: (1) only the functions that are actually referenced are compiled, and (2) the largest possible program for the P1 is 32KB, and for P2 is 512KB. By today's standards those are miniscule, and modern computers should easily be able to compile such programs quickly.
If it becomes an issue then I'll revisit the linking question. For now I'm trying to get something that works first, then I'll look at optimizing it later.
Regards,
Eric
Also a lot of the custom libraries have test code that is not compiled into the finished library. That will be hard to hide.
Mike
If you want to avoid this, use AVR-GCC, make and friends without the Arduino-IDEEditor.
I don't know about Arduino: it sounds like they're doing things wrong. It's a different platform, using a different compiler, and compiling different libraries, so I'd say it may end up performing differently than fastspin.
I'd rather have a slow C compiler than no C compiler at all, so I'm just going to keep on developing fastspin and fix problems as they occur, rather than trying to forsee every possible issue and spending years trying to plan everything out. I'm not idealogically opposed to a linker, and if we had a standard one for the P2 I could use that. Perhaps you'd be good enough to port GNU binutils to the P2? Both p2gcc and fastspin could benefit from that.
Regards,
Eric
Edit: Well, I guess we don't need to modify the GCC driver program if we're not using the GCC C/C++ compiler.
I'll start looking at the Simple Libraries for porting. I'm going to assume that we want to make them able to work with both P1 and P2, since your compiler targets both.
Yes, PCs are easily fast enough today, to build-all, and that does make for more predictable results and safer archiving and version control.
The only time linking is useful, is when your compiler either cannot compile all the sources, or cannot access all the sources.
Even in the latter case, a relocatable object file could be considered to be 'source' so you could 'compile' that to achieve apparent linking ?
That sounds good Roy. Thanks!
Looking at ersmiths asm example above, I decided to give basic + p2asm a try. The code below works using pin 22 as a smart pin. I will eventually upgrade it to auto calibrate, but I wanted to show it as is so maybe there will be some others using smart pins with spin2gui basic.
Any suggestions on how to simplify or improve the code are welcome.
Tom
Tom
- Support for old school BASIC programs with line numbers. This is still a bit incomplete, but it's pretty easy to port programs from www.classicbasicgames.org, for example
- Support for shorter BASIC lambda expressions (kind of the opposite end of the pole from the above)
- A new Spin construct, "PUB FILE", which allows you to import functions from another file and even another language. For example, to add an "atoi" method to your object you can write: This will fetch the definition of atoi from the C library "atoi.c" file and include it as a method of the curent Spin object.
- Lots of bug fixes
"Premature optimization is the root of all evil" -- Donald Knuth, 1974 Turing Award Lecture.
(So important that he says it twice)
I am having problems with the latest version of spin2gui (v1.3.7) running the smartpin adc basic program 4 posts above this one. The program runs fine in v1.3.6.
The errors I get are in the function fadc(). I've copied that section below and marked the lines that are shown as errors with +++++.
The first error is:
Then I commented out line 46 and all following lines up to the next +++++ and got this error: I'm not sure if there are any other errors.
**edit** I also tried just commenting out the while 1 on line 46. I got an error referring to the following line So it appears that anything after the causes an error.
Any ideas what is(are) the problem(s)?(is it supposed to only allow 1 in-line asm and then end the function?)
Tom
I've attached an updated fastspin.exe to this post; if you replace the one in spin2gui/bin/fastspin.exe with the one from this zip file it should correct that problem.
The immediates before constants was something that should always have been there, unless you really intended to directly access locations in COG RAM. The old inline assembly parser was kind of lax about this, if it saw a number or a constant it just assumed you wanted an immediate. But in fact PASM does allow you to directly specify a COG memory location, so the new parser does distinguish between these. This was only ever an issue in inline assembly, regular assembly in DAT blocks always required # for immediate constants and could handle COG memory addresses. The inline assembly parser is a bit different because it has to cope with local variables, and that's where the confusion came in.
Thanks. The fixed fastspin worked.
Re the use of immediate constants. When I originally wrote the program, I lifted the P2asm from a spin2+asm program. The original had the constants prefaced by ##. I wasn't sure how basic would deal with constants and even if they had to be declared in the function or not. So I intended to just try different ways until it worked. Using v1.3.6 it worked on my first try (in "main" without #). I agree the version 1.3.7 is more consistent (although would it ever require ##)?
Rereading the Basic documentation, I am confused about a few things.
I don't understand how shared and member variables work. In the program above I declare value1 as . That variable is used in bot the function running in the second cog and in the first cog to transfer its value from the function to "main". In my most recent version I have changed it to
I originally defined flag the same way, but changed it to . It is used to signal each cog when the other is ready for a transfer.
In all cases the program ran correctly. When would it make a difference?
Where are variables stored? (HUB, cog?) How about constants?
Thanks for your help
Tom
That raises an interesting difference with the inline assembler: it goes through the optimizer, so it does change things in the code (like converting ## to # if it can). In Spin2 DAT sections this is not the case, if you write ## then you'll always get an AUG prefix (so the instruction will really take 8 longs and 4 cycles) even if the immediate would fit in 4 bytes.
"dim shared" always puts things in HUB, and there is only one copy shared by all instances of the object. It's like a value in a DAT section in Spin. Just plain "dim" usually goes in HUB (unless you use a special compiler flag) but it's like a member variable in Spin, each copy of the class gets its own copy of the variable. For the top level program this doesn't really matter, both "dim shared" and "dim" will end up being pretty similar. It matters only if you want to write re-usable classes in BASIC.
Shared variables always go in HUB. "dim" at the top level (outside sub or function declarations) declares a member variable, which goes in HUB. "dim" inside a sub or function creates a local variable, which usually goes in COG memory unless you take its address or there's something else funny going on in the function, in which case it'll go on the stack in HUB memory.
Constants usually don't end up being "stored" anywhere, they're encoded directly in the instruction as an immediate value.
Regards,
Eric
Thanks for the info. I am trying to understand more how these compilers work and how to best use them.
In my program I have 2 in-line asm segments in the function. The first "turns on" the adc smart pin. The second is embedded in a BASIC while loop. The asm reads the value from the smart pin and stores it in a variable and then exits the asm. The BASIC stores the local (adc value) into the shared variable that is then read by a different cog. After testing if the value was retrieved by the cog, the while loop then repeats.
If I read the documentation correctly (along with what you had posted earlier in the thread) I can't have the asm store the rdpin result into a global. Is that correct. Is there any way to start the smart pin and then loop in asm to directly send the result to the calling cog or is the way I'm doing it reasonable. I like my method because I can see what is happening.
I looked at using pointers, but just ended up confusing myself.
Thanks
Tom
In general I like to keep the inline asm to a minimum, because the compiler produces pretty decent code on its own. So usually I just use inline asm to do some instruction that isn't built in to the compiler, and then do all the looping and variable update / manipulation in a high level language.
You could try to mess around with pointers and having the asm store directly with wrlong, but it's likely you'll end up with the same code anyway and it'll be more confusing . The compiler will optimize the combination of your code inline code and the code it's creating from BASIC, so for example: compiles to something like: (Unless you turn off the optimizer, but I wouldn't usually do that unless you're hunting for a bug.)
Given that, it's probably best to write the code in whatever way is simplest and clearest for you, and not to worry too much about optimizing or about writing as much as possible in assembly.
Regards,
Eric
* edit - this was with Fastspin V3.9.19, pretty sure that's the latest. I also keep getting "error: Unknown symbol COUNT_" when I try to compile the file in question as the root object?
Yes sorry, typo.
Version 3.9.20
- Allow closures to access variables and functions in the enclosing object
- Fixed some parsing problems with inline assembly
- Fixed incorrect inlining of some functions in -O2
- Fixed some C parser errors
- Fixed some C type conversion errors
- Fixed encodings of setpiv and setpix instructions
- Fixed a bug in chained assignments of register ranges
- Increased stack size on Windows to prevent a crash
- Added if_00, if_same, and other missing P2 conditions
- Fixed an incorrect result for ">| 0" on P2
- Added some P2 specific optimizations
- Added Spin serial drivers to default include directory
- Rewrote C static and variable handling code to fix a number of bugs and to allow nested variable scopes to work
- Fixed an optimizer bug where register masks could be created before the variables they dependend on were initialized
- Fixed a P2 optimizer bug affecting varargs
- Fixed several C type casting bugs including conversion of arrays and functions to pointers
- Fixed handling of enums in C
- Fixed checking for duplicate labels
- Added some standard Spin serial routines to the include/spin folder