Do you know why the following sample code fail to execute on the P2 with p2gcc...? It compiles without warnings/errors.
If I add an initialized character variable to your hello.c file, nothing gets printed out to the console after download, but if remove it it works fine. In comparison having uninitialized variables is okay.
I came across this when trying to make the a.out file large for downloading tests by putting in a large character array and initializing it with {-1}. Nothing worked if I used initialized data, and I kept on shrinking it down until it was just a single byte and it still didn't work!
Is this a known issue with memory allocation somewhere or some new bug perhaps?
Roger.
#include <stdio.h>
#include <propeller.h>
#define p2clkfreq (*(int *)0x14)
char dummy1; // works fine
//char dummy2 = 'a'; // uncommenting this line fails
void main(void)
{
int i;
waitcnt(CNT+p2clkfreq);
for (i = 1; i <= 10; i++)
{
waitcnt(CNT+p2clkfreq/2);
printf("Hello World - %d\n", i);
}
printf("Goodbye\n");
}
Here's an open source startrek game that I found on the internet. I was curious whether p2gcc could compile and run it. I had to make a few minor changes, but I got it working. It took me a little longer to get it working than it should have. The game uses the least significant bits of the random number generator, which it turns out are not very random. I modified the value returned by the rand function by shifting it down by 5 bits. The program started working after I did that.
The program uses the sqrt() function, so you have to include the math library. Use the following command:
By the way, if the application starts sending data right after boot without any delay, it will corrupt the P2 response checking code. I removed the sleep(1) from main in life.c and got this error now. I think only one byte should be requested from the serial port not 100 (looks like that value in the code was pasted from elsewhere where it reads in the version string). The garbage output below is from this change...
When I changed it to read only one byte it fixes the problem.
num = rx_timeout((uint8_t *)buffer, 1, 100); // change to 100ms timeout --- *** NEW
Well spotted - Yes, that makes sense, P2 only sends one byte - '.' (ok) or '!' (error)
Any wait_drain is going to pause until the SW buffers empty, but that does not include any HW buffers in the chain, which is why some timeout is still needed.
The FT231X has 512 bytes, and it seems MAC HW may have additional HW buffers. Other Serial UARTS can have 1k or 4k buffers.
Examples at 115200 (chosen as the likely slowest-common-denominator users might test with - is there any point supporting lower speeds ? )
512*10/115200 = 0.044s
1024*10/115200 = 0.088s
4096*10/115200 = 0.355s
So 100ms is ok for a total buffer of 1024, but probably light for a 4k buffer device, which higher performance users may be using. (FT2232H)
You could adapt the timeout wait to Baud-speed, but actual timeout is a rare occurrence, and has no usual-use impact if set larger, as the expected byte comes back quickly.
Ideally, code should report any timeout-exit to the user, as it means something is awry (as here).
Dave Hein: Latest loadp2 (version 0.012) displays a failure message when "-SINGLE" option is used on my macOS system with -b & -l baud rates set to 115200 (or any optioned baudrates). And, if the -t option is used, there's no terminal activity as the loader appears to just quit with the error display.
Odd thing is that the program actually gets uploaded and runs (without terminal response, of course)
$ loadp2
loadp2 - a loader for the propeller 2 - version 0.012, 2019-02-03
$ loadp2 -p /dev/cu.usbserial-P2EEI8V -b 115200 -l 115200 -t -SINGLE draw_char_to_LED_Matrix.binary
draw_char_to_LED_Matrix.binary failed to load
Error response was ""
$
I added the checksum logic to the -SINGLE mode, and it appears that I'm not waiting long enough before requesting the status. Once I figure out how to convert a HANDLE to a file descriptor I will use the tcdrain function, and that problem should be resolved.
Roger, can you post your code for wait_drain? tcdrain requires a file descriptor, and I'm sure how to get that from a HANDLE.
From what I can tell your hSerial is a file descriptor (at least in osint_linux.c) so this code worked for me. You might want to tidy up with a specific failure type for your osint.h file if required for other platforms etc. I ignored the return value anyway in loadp2.c.
I added the checksum logic to the -SINGLE mode, and it appears that I'm not waiting long enough before requesting the status. Once I figure out how to convert a HANDLE to a file descriptor I will use the tcdrain function, and that problem should be resolved.
As an interim, you could try this ?
num = rx_timeout((uint8_t *)buffer, 1, 450); // 1Char echo, 450ms MAX wait
That's rogloh's fix for a 1 char echo, and the 450ms is a maximum wait, large enough to allow users testing with FT2232H large HW buffers
Some simple time captures could check how long that Tx-Empty then RX wait actually is ?
Here's my hacked up loadp2 code changes to osint_linux.c and loadp2.c as it stands for anyone who wants to play with it on Macs. It obviously needs further cleanup using correct osint.h declaration pathway before being ready for any integration within a release quality loadp2. Also it still contains a couple of compile type warnings etc as I've been experimenting with port auto-detection and I seem to have that working on the Mac though that will break the other platforms right now that searched for COM1/COM2/COM3 etc.
Both SINGLE and CHIP modes now work for me with lots of baud rates tested below 2Mbps. If you use -SINGLE then also passing -b 33100 seems to work for the serial port baud rate with the RC oscillator speed of ~23MHz. This could vary on other platforms though. 33100 ~ 23/80 * 115200
Any wait_drain is going to pause until the SW buffers empty, but that does not include any HW buffers in the chain, which is why some timeout is still needed.
The FT231X has 512 bytes, and it seems MAC HW may have additional HW buffers. Other Serial UARTS can have 1k or 4k buffers.
Examples at 115200 (chosen as the likely slowest-common-denominator users might test with - is there any point supporting lower speeds ? )
512*10/115200 = 0.044s
1024*10/115200 = 0.088s
4096*10/115200 = 0.355s
So 100ms is ok for a total buffer of 1024, but probably light for a 4k buffer device, which higher performance users may be using. (FT2232H)
You could adapt the timeout wait to Baud-speed, but actual timeout is a rare occurrence, and has no usual-use impact if set larger, as the expected byte comes back quickly.
Ideally, code should report any timeout-exit to the user, as it means something is awry (as here).
Very good points. The HW buffer also introduces its own delay which should be accounted for if high reliability is desired across different serial ports.
Boy am I glad to be out of the loader business! Getting these things to work reliably on lots of different systems is a pain. Thanks for all of your work on this!!
Here's an open source startrek game that I found on the internet. I was curious whether p2gcc could compile and run it. I had to make a few minor changes, but I got it working. It took me a little longer to get it working than it should have. The game uses the least significant bits of the random number generator, which it turns out are not very random. I modified the value returned by the rand function by shifting it down by 5 bits. The program started working after I did that.
I'm using the GNU C routine, which has some known periodicities. At some point I'll add a library function that uses the P2 random number generator. However, there are times when a repeatable generator is useful for debugging purposes.
Boy am I glad to be out of the loader business! Getting these things to work reliably on lots of different systems is a pain. Thanks for all of your work on this!!
It is a pain, but the efforts now will hopefully pay off. As a developer myself I totally despise using flaky tools.
Hopefully over time we can add in some way to download using wifi-serial bridges like the work you did for P1 with ESP8266. I think it might be a little simpler with the P2 than P1 with any luck.
I checked loadp2 version 0.013 into GitHub. I added the wait_drain function that calls tcdrain for Linux and the Mac, and just calls msleep(100) for Windows. I tested the Windows version, and it works fine down to 57600. At lower baud rates the read after the "?" times out.
Roger, thanks for your help on this. I'll look at the code you posted, and incorporate some of those changes also once they have been tested out by others.
Dave,
The XORO32 instruction is also repeatable, ie: only iterates when called. It has a user state variable that can be seeded with srand(). It could directly backend rand(). Not that I'd know how.
I checked loadp2 version 0.013 into GitHub. I added the wait_drain function that calls tcdrain for Linux and the Mac, and just calls msleep(100) for Windows. I tested the Windows version, and it works fine down to 57600. At lower baud rates the read after the "?" times out.
Roger, thanks for your help on this. I'll look at the code you posted, and incorporate some of those changes also once they have been tested out by others.
No problem, sounds good Dave. With any luck there should be some type of Windows API that can emulate tcdrain(). FlushFileBuffers?
If you get a chance I'd be keen to understand why the two variants of the trivial hello.c code example I mention above with this "dummy2" assigned static variable first commented out and then enabled both work and don't work respectively. I've added the two a.out files for both cases. "good.out" is with dummy2 commented out, and "bad.out" is with this line enabled. When I compared the p2dumps of each there are some address differences in the file but I'm not really sure where it goes bad. Perhaps this is a linker issue and the assigned dummy2 variable address is somehow conflicting with the recent clock/baud rate changes, though I don't see the P2 TX LED flash every half second on the board so it's more than baud rate. The bad version when loaded checksums fine in SINGLE mode so I know it is making it into the board. It's strange and I'm wondering if it is a bug or limitation of the p2gcc tools.
There's a bug in one of the tools that doesn't like unaligned data. If you declare a char or short value it will cause the code to be unaligned. In theory the P2 should be able to handle it, but something in the linker or one of the other tools doesn't like it. I generally try to force 32-bit alignment, but 1-3 char variables or a short will cause it to be mis-aligned. The work-around is to declare dummy char's or short's so get it back into 32-bit alignment.
Dave,
I have limited experience using the Windows command prompt. I tried to run your startrek program using the P2gcc006 and got errors. I put "startrek.c" into the p2gcc006 folder and ran p2gcc. I got the following:
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\tandj>cd C:\Users\tandj\Documents\robot\P2ES\p2gcc006\p2gcc006
C:\Users\tandj\Documents\robot\P2ES\p2gcc006\p2gcc006>p2gcc -r -t startrek.c libm.a
's2pasm' is not recognized as an internal or external command,
operable program or batch file.
'p2asm' is not recognized as an internal or external command,
operable program or batch file.
invalid extension in libm.a
C:\Users\tandj\Documents\robot\P2ES\p2gcc006\p2gcc006>
Not sure what I have done wrong, and would appreciate your assistance.
Thanks
Tom
Note:
My builds do lag Dave Hein's source code by a bit (anywhere from a couple hours to a day or two, depending on how quickly I notice his changes) because the CI server is building a fork of his code, not actually his code. If Dave likes the changes I made to the build system and merges my PR, I can go back to building his repo directly.
twm47099, the p2gcc006 zipfile contains a bin directory with Windows executables in it. You need to add this bin directory to your path. On the command line you would type:
set path=%path%;C:\Users\tandj\Documents\robot\P2ES\p2gcc006\p2gcc006\bin
You need to do this every time you start the command prompt window. You could put this in a batch file, and run that each time you start a new window. Or you could add it to your registry, but I wouldn't suggest that if your not experienced in working with the registry.
I haven't tested the Windows build lately, so I tried it just now and found that you can't specify a library. I have an updated p2gcc.bat in the attached zipfile that fixes that. I also found that the linker fails for the startrek program in Windows. I need to look into that. I have included the startrek.bin binary file that you can load by typing:
loadp2 -t startrek.bin
Finally, I included at setpath.bat file that you can use to set your path.
I haven't tested the Windows build lately, so I tried it just now and found that you can't specify a library. I have an updated p2gcc.bat in the attached zipfile that fixes that.
The "p2gcc" file that executes on Linux & macOS, needs the same change to allow "-L" & "-I" to specify Library & Includes locations...
The change I made to p2gcc.bat for Windows was to allow specifying files with a .a extension. So this allowed the following:
p2gcc -r -t startrek.c libm.a
Unfortunately, there is an issue with p2asm or p2link in the Windows build that causes a problem with linking the startrek object.
The p2gcc bash script that is used with Linux, macOS & Cygwin already had the .a extension fix. I just forgot to put it in p2gcc.bat also.
I have thought about adding the -L and -l (lower case L) options used by the linker, and the -D and -I (upper case i) options used by the compiler. It would also be useful to add the -f and -b options for the loader. I just haven't gotten around to it.
I added the -D, -L, -I (upper case i), -b and -f options to p2gcc and p2gcc.bat. The -D and -I options are passed to the compiler, and specify a compile-time symbol and an include directory. The -L option specifies a library directory to the linker. The -b and -f options specify the user baud rate and the clock frequency.
Comments
I'm not using a GUI. I'm using p2gcc under Linux, which is more complete. You can create a Ubuntu/Kubuntu VM and follow the steps to install it via nix:
http://forums.parallax.com/discussion/169589/p2-tooling-installation-via-nix-for-anylinux-any-linux-distribution/
Then, just use the latest zip file containing my code, plug your P2 into the VM, and just run the script.
Kind regards, Samuel Lourenço
Do you know why the following sample code fail to execute on the P2 with p2gcc...? It compiles without warnings/errors.
If I add an initialized character variable to your hello.c file, nothing gets printed out to the console after download, but if remove it it works fine. In comparison having uninitialized variables is okay.
I came across this when trying to make the a.out file large for downloading tests by putting in a large character array and initializing it with {-1}. Nothing worked if I used initialized data, and I kept on shrinking it down until it was just a single byte and it still didn't work!
Is this a known issue with memory allocation somewhere or some new bug perhaps?
Roger.
The program uses the sqrt() function, so you have to include the math library. Use the following command:
p2gcc -r -t startrek.c libm.a
Well spotted - Yes, that makes sense, P2 only sends one byte - '.' (ok) or '!' (error)
Any wait_drain is going to pause until the SW buffers empty, but that does not include any HW buffers in the chain, which is why some timeout is still needed.
The FT231X has 512 bytes, and it seems MAC HW may have additional HW buffers. Other Serial UARTS can have 1k or 4k buffers.
Examples at 115200 (chosen as the likely slowest-common-denominator users might test with - is there any point supporting lower speeds ? )
512*10/115200 = 0.044s
1024*10/115200 = 0.088s
4096*10/115200 = 0.355s
So 100ms is ok for a total buffer of 1024, but probably light for a 4k buffer device, which higher performance users may be using. (FT2232H)
You could adapt the timeout wait to Baud-speed, but actual timeout is a rare occurrence, and has no usual-use impact if set larger, as the expected byte comes back quickly.
Ideally, code should report any timeout-exit to the user, as it means something is awry (as here).
Odd thing is that the program actually gets uploaded and runs (without terminal response, of course)
"-CHIP" works!
dgately
From what I can tell your hSerial is a file descriptor (at least in osint_linux.c) so this code worked for me. You might want to tidy up with a specific failure type for your osint.h file if required for other platforms etc. I ignored the return value anyway in loadp2.c.
As an interim, you could try this ?
num = rx_timeout((uint8_t *)buffer, 1, 450); // 1Char echo, 450ms MAX wait
That's rogloh's fix for a 1 char echo, and the 450ms is a maximum wait, large enough to allow users testing with FT2232H large HW buffers
Some simple time captures could check how long that Tx-Empty then RX wait actually is ?
Both SINGLE and CHIP modes now work for me with lots of baud rates tested below 2Mbps. If you use -SINGLE then also passing -b 33100 seems to work for the serial port baud rate with the RC oscillator speed of ~23MHz. This could vary on other platforms though. 33100 ~ 23/80 * 115200
Cheers,
Roger.
Very good points. The HW buffer also introduces its own delay which should be accounted for if high reliability is desired across different serial ports.
Which random number generator is being used here?
It is a pain, but the efforts now will hopefully pay off. As a developer myself I totally despise using flaky tools.
Hopefully over time we can add in some way to download using wifi-serial bridges like the work you did for P1 with ESP8266. I think it might be a little simpler with the P2 than P1 with any luck.
Roger, thanks for your help on this. I'll look at the code you posted, and incorporate some of those changes also once they have been tested out by others.
The XORO32 instruction is also repeatable, ie: only iterates when called. It has a user state variable that can be seeded with srand(). It could directly backend rand(). Not that I'd know how.
No problem, sounds good Dave. With any luck there should be some type of Windows API that can emulate tcdrain(). FlushFileBuffers?
If you get a chance I'd be keen to understand why the two variants of the trivial hello.c code example I mention above with this "dummy2" assigned static variable first commented out and then enabled both work and don't work respectively. I've added the two a.out files for both cases. "good.out" is with dummy2 commented out, and "bad.out" is with this line enabled. When I compared the p2dumps of each there are some address differences in the file but I'm not really sure where it goes bad. Perhaps this is a linker issue and the assigned dummy2 variable address is somehow conflicting with the recent clock/baud rate changes, though I don't see the P2 TX LED flash every half second on the board so it's more than baud rate. The bad version when loaded checksums fine in SINGLE mode so I know it is making it into the board. It's strange and I'm wondering if it is a bug or limitation of the p2gcc tools.
Cheers,
Roger.
I have limited experience using the Windows command prompt. I tried to run your startrek program using the P2gcc006 and got errors. I put "startrek.c" into the p2gcc006 folder and ran p2gcc. I got the following: Not sure what I have done wrong, and would appreciate your assistance.
Thanks
Tom
You need to compile p2gcc before you can use it. There is a build process that requires mingw system.
I tried to compile it as well and got a bunch of errors about missing functions: __floatsidf, and others...
Mike
Note:
My builds do lag Dave Hein's source code by a bit (anywhere from a couple hours to a day or two, depending on how quickly I notice his changes) because the CI server is building a fork of his code, not actually his code. If Dave likes the changes I made to the build system and merges my PR, I can go back to building his repo directly.
Thanks, I'll give it a try.
Tom
set path=%path%;C:\Users\tandj\Documents\robot\P2ES\p2gcc006\p2gcc006\bin
You need to do this every time you start the command prompt window. You could put this in a batch file, and run that each time you start a new window. Or you could add it to your registry, but I wouldn't suggest that if your not experienced in working with the registry.
I haven't tested the Windows build lately, so I tried it just now and found that you can't specify a library. I have an updated p2gcc.bat in the attached zipfile that fixes that. I also found that the linker fails for the startrek program in Windows. I need to look into that. I have included the startrek.bin binary file that you can load by typing:
loadp2 -t startrek.bin
Finally, I included at setpath.bat file that you can use to set your path.
The "p2gcc" file that executes on Linux & macOS, needs the same change to allow "-L" & "-I" to specify Library & Includes locations...
Thanks,
dgately
p2gcc -r -t startrek.c libm.a
Unfortunately, there is an issue with p2asm or p2link in the Windows build that causes a problem with linking the startrek object.
The p2gcc bash script that is used with Linux, macOS & Cygwin already had the .a extension fix. I just forgot to put it in p2gcc.bat also.
I have thought about adding the -L and -l (lower case L) options used by the linker, and the -D and -I (upper case i) options used by the compiler. It would also be useful to add the -f and -b options for the loader. I just haven't gotten around to it.
"C:/Users/mm/Desktop/spin2gui 1.3.5/spin2gui/spin2gui/bin/fastspin" -2 -l -O1 -L "./lib" "C:/Users/mm/Desktop/spin2works/ping test .spin2"
Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2019 Total Spectrum Software Inc.
Version 3.9.16 Compiled on: Jan 29 2019
child killed: segmentation violation
Thanks