Here's the latest release of p2gcc. This release contains the fixes for running under MacOS and the SD SPI driver fix that allows using the latest version of PropGCC. There are also several changes in p2asm that fixes problems with assembling ROM_137PBJ.spin2 and SD2_test_121a.spin2.
Finally, I fixed the -s option in loadp2 that enables loading a program at a different address than address 0. This feature is used with the shell program that runs at location $8000. the shell program is similar to filetest, but also contains a "run" command to execute binaries located on an SD card.
Adding a port (-p "") option in p2gcc that would just pass the P2's port name as-is to p2load would make for a smooth one-command build-load-run for all OS's. Right now, I think the p2gcc-p2load process (when runs as: "p2gcc -r -T ... filename.spin2) assumes a Linux-style port name and searches for a currently accessible P2 that way. If we can just include the name of a known port (i.e. on macOS, something like: "-p /dev/cu.usbseriaXXXNNNXX", on Linux "-p /dev/tty01...") to p2gcc and it can just pass that text along to p2load as a "-p" option, it would help.
As it is now, I have to NOT use the -r, -t and/or -T options for p2gcc and then need to run p2load as a separate command.
I'll add the port option to p2gcc when I have a chance. At some point I need to look at the loader in the P1 PropGCC to see how it finds the port.
It uses a rather kludgy method. I'd be happy to extract it from propeller-load if you'd like. As you might guess, there is a different method used for Windows, Mac, and Linux. All you really need is a function that iterates over all of the serial ports on the system. Then you have to try the identify sequence on each one until you find one that responds like a Propeller chip.
I'll add the port option to p2gcc when I have a chance. At some point I need to look at the loader in the P1 PropGCC to see how it finds the port.
It uses a rather kludgy method. I'd be happy to extract it from propeller-load if you'd like. As you might guess, there is a different method used for Windows, Mac, and Linux. All you really need is a function that iterates over all of the serial ports on the system. Then you have to try the identify sequence on each one until you find one that responds like a Propeller chip.
One method (for macOS & Linux) is to look at all the content of /dev and filter known USB serial port names (yeah, kludgy!). I'm not sure what method is used in SimpleIDE & PropellerIDE. I know, both used custom routines for WIN, macOS & Linux.
When I want to use a special feature of the P2 I do it using inline assembly. I typically put the inline code in a small function, where I know that the parameters are passed in r0, r1, etc., and the return value is passed in r0. I either define the function in a separate file, or add the "noinline" attribute to ensure that the code is called as a function. This is a temporary solution because there is extra overhead from calling the function. Ultimately, the best way to do this is to create a set of "builtin" functions that directly map into the processor's special instructions as was done with the P1.
When I want to use a special feature of the P2 I do it using inline assembly. I typically put the inline code in a small function, where I know that the parameters are passed in r0, r1, etc., and the return value is passed in r0. I either define the function in a separate file, or add the "noinline" attribute to ensure that the code is called as a function. This is a temporary solution because there is extra overhead from calling the function. Ultimately, the best way to do this is to create a set of "builtin" functions that directly map into the processor's special instructions as was done with the P1.
Ah yes, I forgot about the built-in functions. They are mostly to provide direct access to hardware instructions. I haven't looked at the smart pin instructions much. I guess they should all have built-ins.
Typically compilers do not use or understand anything but the most basic instructions to move data around, perform arithmetic/logical operations, jump around, call and return from functions etc. You know, MOV, ADD, SUB, AND, OR, JMP, CALL, RET, etc.
The P2 has hundreds of not so simple instructions. They will have to be accessed via library calls, inline assembler or intrinsics.
"builtin" functions would be great. Else, I have to figure out why to say "noinline" when I want inline assembly...
The compiler copies inline text directly to the output assembly file. If "noinline" is not specified the optimizer will copy the C source for small functions instead of calling the function. In this case, the parameters for the function may not be in the registers starting at r0, but may be in other registers. So "noinline" is needed when using hardcoded register values.
Here's an example of a program that computes the square root of a 32-bit int using the cordic qsqrt instruction.
#include <stdio.h>
int __attribute__((noinline)) isqrt32(int value)
{
__asm__("qsqrt r0, #0");
__asm__("getqx r0");
}
int main(void)
{
int value;
while (1)
{
printf("Enter value: ");
scanf("%d", &value);
printf("Square Root of %d = %d\n", value, isqrt32(value));
}
return 0;
}
This program doesn't work correctly if the "noinline" attribute is not used.
C++ doesn't work currently. It needs some C++ functions from the library, and I think there was a problem with long C++ symbols in p2asm. I'm not a C++ programmer, so I haven't made much effort to try to get it to work. I'll have to try a C++ "Hello World" program again to see what it takes to get it to run.
What kind of performance/memory penalty would you expect from using C++ instead of C?
None unless you try to use fancy C++ features like exceptions and dynamic allocation. GCC will likely generate exactly the same code for C and C++ for a similar program.
David Betz is right.
gcc/clang/vc have all matured very will on code generation for C++, such that in most cases C++ will perform equally with C for similar code. Just avoid exceptions and RTTI.
Even memory allocation will depend more on the OS memory systems than the code/compiler. If you have a decent small block allocation setup, then perf will be very good.
Also, it's a common misconception that C++ is slower than C. It's more that C++ allows you to write less text and get more end result code out of it (some would say this is bad, but it depends). A lot of this comes from using C++ standard libraries and STL, both of which are easily avoided and likely most of which won't be around on MCUs. C++ has more hidden or implied code when you use it's features. If you were to implement the exact same functionality in your C code as you used in your C++ code, then they would perform the same (although in many cases the C++ version would actually be faster because of the compiler maturity).
Looks like p2asm is the latest version of qasm, right?
If I'm seeing it right, one could take p2asm combine it with a text editor and a loader and make their own version of Pnut...
Yes. Or do the same with fastspin. In fact I did that already with spin2gui (https://github.com/totalspectrum/spin2gui) which is a complete Spin / Pasm development environment for P1 and P2. The text editor isn't particularly great, so you may prefer to do the editing in an editor of your choice. Note that fastspin has some Spin2 features (at least the ones we know about) but obviously isn't a complete Spin2 since that doesn't exist yet.
@Rayman, p2asm evolved from qasm. qasm worked for both the P1 and P2. p2asm started out as a later version of qasm, but then I removed the P1 mode and simplified the code generation. I've also added a mode to generate object files, and it now supports some of the GAS pseudo-ops. So p2asm has diverged quite a bit from qasm.
@ersmith, I've used fastspin and spin2gui, and I think they are great. I might be nice to use the debug features of the P2 and add a debugger as well. Another nice feature would be integrate a P2 simulator so that code could be executed and debugged without requiring hardware.
@ersmith, I've used fastspin and spin2gui, and I think they are great. I might be nice to use the debug features of the P2 and add a debugger as well. Another nice feature would be integrate a P2 simulator so that code could be executed and debugged without requiring hardware.
Thanks, Dave. p2asm is great too, and I think fastspin and p2asm are complementary -- p2asm is a lean and efficient assembler, and I think it's much easier to modify than fastspin, so it would make a great back end for compilers. fastspin is heavy weight since it includes the complete Spin compiler.
Thanks too for the suggestions. I seem to recall that you had tried spinsim with spin2gui -- did that work OK? Was there anything that I would need to change in spin2gui for this? It should be easy to add a "run with simulator" menu option to the spin2gui TCL code. In general I think TCL makes for an easy to modify GUI, I like it for that.
Thanks, fastspin looks interesting. I remember it now, converts to C/C++ and then uses GCC...
fastspin is based on spin2cpp, but it doesn't have the C conversion ability -- it compiles directly to PASM and then to binary, so no C compiler is required.
Comments
Finally, I fixed the -s option in loadp2 that enables loading a program at a different address than address 0. This feature is used with the shell program that runs at location $8000. the shell program is similar to filetest, but also contains a "run" command to execute binaries located on an SD card.
One small request...
Adding a port (-p "") option in p2gcc that would just pass the P2's port name as-is to p2load would make for a smooth one-command build-load-run for all OS's. Right now, I think the p2gcc-p2load process (when runs as: "p2gcc -r -T ... filename.spin2) assumes a Linux-style port name and searches for a currently accessible P2 that way. If we can just include the name of a known port (i.e. on macOS, something like: "-p /dev/cu.usbseriaXXXNNNXX", on Linux "-p /dev/tty01...") to p2gcc and it can just pass that text along to p2load as a "-p" option, it would help.
As it is now, I have to NOT use the -r, -t and/or -T options for p2gcc and then need to run p2load as a separate command.
dgately
dgately
Since this is based on P1 GCC, how can one do things like interact with smartpins using p2gcc?
The P2 has hundreds of not so simple instructions. They will have to be accessed via library calls, inline assembler or intrinsics.
Here's an example of a program that computes the square root of a 32-bit int using the cordic qsqrt instruction. This program doesn't work correctly if the "noinline" attribute is not used.
gcc/clang/vc have all matured very will on code generation for C++, such that in most cases C++ will perform equally with C for similar code. Just avoid exceptions and RTTI.
Even memory allocation will depend more on the OS memory systems than the code/compiler. If you have a decent small block allocation setup, then perf will be very good.
Also, it's a common misconception that C++ is slower than C. It's more that C++ allows you to write less text and get more end result code out of it (some would say this is bad, but it depends). A lot of this comes from using C++ standard libraries and STL, both of which are easily avoided and likely most of which won't be around on MCUs. C++ has more hidden or implied code when you use it's features. If you were to implement the exact same functionality in your C code as you used in your C++ code, then they would perform the same (although in many cases the C++ version would actually be faster because of the compiler maturity).
If I'm seeing it right, one could take p2asm combine it with a text editor and a loader and make their own version of Pnut...
Yes. Or do the same with fastspin. In fact I did that already with spin2gui (https://github.com/totalspectrum/spin2gui) which is a complete Spin / Pasm development environment for P1 and P2. The text editor isn't particularly great, so you may prefer to do the editing in an editor of your choice. Note that fastspin has some Spin2 features (at least the ones we know about) but obviously isn't a complete Spin2 since that doesn't exist yet.
@ersmith, I've used fastspin and spin2gui, and I think they are great. I might be nice to use the debug features of the P2 and add a debugger as well. Another nice feature would be integrate a P2 simulator so that code could be executed and debugged without requiring hardware.
What is the license for p2asm? I looked around, but didn't see it...
I might have to take a closer look...
Yes - for a portable and fast version of a Python P2 loader see the thread https://forums.parallax.com/discussion/168850/python-p2-loader#latest
Thanks, Dave. p2asm is great too, and I think fastspin and p2asm are complementary -- p2asm is a lean and efficient assembler, and I think it's much easier to modify than fastspin, so it would make a great back end for compilers. fastspin is heavy weight since it includes the complete Spin compiler.
Thanks too for the suggestions. I seem to recall that you had tried spinsim with spin2gui -- did that work OK? Was there anything that I would need to change in spin2gui for this? It should be easy to add a "run with simulator" menu option to the spin2gui TCL code. In general I think TCL makes for an easy to modify GUI, I like it for that.
fastspin is based on spin2cpp, but it doesn't have the C conversion ability -- it compiles directly to PASM and then to binary, so no C compiler is required.