It could be the receiver not keeping up. Try a slower baud. If there is bit drops the receiver could even loose track of the start-stop framing bits. Without an idle break there is no way to re-identify the framing.
EDIT: I just compiled that example as is. It seems to run fine for me. Loop count is over 4000 and still looks the same. eg:
@JRoark: I can't seem to reproduce the corruption on my system either. I think @evanh is right, it's most likely a PC side issue (the PC is not keeping up with the data). What baud rate are you running at?
This is interesting, and I think @ersmith and @evanh are right. While playing with this, I noticed something: after a couple of minutes, when the program terminated normally, the blue usb activity LED stopped blinking about 5 seconds BEFORE the screen stopped scrolling. So the terminal program is slow and buffering, and I’ll bet you dollars to donuts its wrapping the buffer. As a test I scattered some delays in between the PRINT statements and sure enough, all of the “problems” disappeared.
BTW: this is running on Win10 on a Dell laptop with the USB link speed set to 256k. The laptop isnt exactly slow, so I’ll keep poking at this. It would be nice to debug at full speed.
Thank you both for your help!
EDIT: There is definitely something happening on the PC side with buffering, and when this happens the PC apparently signals down the USB channel and kills the P2-EVAL. The effect is the same as if you'd closed the debug window in FlexGUI. With delays inserted in the code to allow the PC to catch up, it's a non-issue. As the baud rate increases, so must the value of any delay inserted between print statements. Things seem solid with a 15 mS delay between PRINT statements, regardless of baud rate. Where do I go from here?
@JRoark : Maybe we should step back a bit and figure out what you want to accomplish. If you're sending a large amount of data from the eval board to the PC, perhaps it makes sense to write it into a file using the 9p file system? There's some flow control built in to that so it shouldn't encounter the same problems as the regular terminal.
I've been bitten a couple times now by the shift operators like << having the lowest precedence in C whereas they have about the highest precedence in Spin1&Spin2.
Guess I'm biased, but I wish C gave shifts a high precedence like Spin2.
If you've downloaded the PNut folder you should have the Spin2 interpreter source in it. I explore this a lot, trying to get a handle on how Chip does things. I think the little code snippet above will behave just as Spin2 based on what the interpreter is doing.
Ok, thanks. And I see in the P2 docs that it should work.
Tried this and seems to work:
int r;
__asm {
getrnd r
}
r &= 0x3fffffff;
That last line is something that C's rand() does for you automatically.
Found out the hard way that my code explodes if you don't do that.
Probably something about negative numbers messing things up...
Not sure why FlexSpin C RAND_MAX value is 0x3fffffff and not 0x7fffffff though...
@JRoark : Maybe we should step back a bit and figure out what you want to accomplish. If you're sending a large amount of data from the eval board to the PC, perhaps it makes sense to write it into a file using the 9p file system? There's some flow control built in to that so it shouldn't encounter the same problems as the regular terminal.
Good point, Eric. The back story: this all started when I rewrote all the FlexBASIC string functions for speed. To flush out any memory leaks or misbehaviors I ran a test program in a continuous loop. Basically I was just banging the bejeepers out of the string libraries trying to break them. And I broke it spectacularly. And randomly. No real pattern. It felt like a memory problem, but after a deep inspection of my code, I started getting a feeling that my code was (mostly) ok. And then EvanH and you both twigged to the idea that this was really a PC comm issue. And indeed it was.
So what I’m really trying to do is to break things in a way that lets me study the output so I can see what broke. For realtime use I’ve already changed to printing to the VGA driver Eric wrote. For unattended testing I may use 9p.
Might want to check the Advanced Settings in Device Manager for the USB Serial Port.
there are buffer size settings and some other things there...
Your comment resulted in me following some interesting rabbit trails down in the bowels of Windows, but in the end nothing I did really made any difference. The USB latency timer seemed promising initially but ultimately made no real difference. Still, it was a useful exercise and I do appreciate the input.
Is there a C way to use the Spin2 GETRND() function?
It's called _rnd() and is declared in <propeller2.h>. It should probably be renamed _getrnd(), but we (forum users) made the propeller2.h file definition back when the function was still RND() in Spin2.
Thanks @ersmith. Does this do the AND with RAND_MAX?
No, and in C (as opposed to Spin) it's not really so necessary, since C has unsigned integers.
Also, why is RAND_MAX not $7FFF_FFFF?
I think it's due to the pseudo-random number generator (in rand.c) making some of the bits very predictable e.g. it would always alternate positive / negative. Masking out the upper bits hides that. It's not an issue for _getrnd() or _rnd(), there's no need to mask those.
@ersmith Thanks. This foo(...) way works, this is perfect. Think I tried a couple weeks ago and couldn't make it work, but must have done something wrong... Works now.
Long filenames work! As @ersmith said, you just add -DFF_USE_LFN=1 to the command line.
Finally free from 8.3 filenames... Now, we just need to be able to use different pins for the uSD...
There's documentation on the SD card file system now in general.pdf:
If you define the symbol `FF_USE_LFN` on the command line with an option like `-DFF_USE_LFN` then long file names will be enabled for the SD card.
The pins to use for the SD card may be changed by changing the following defines on the command line:
```
PIN_CLK (default 61)
PIN_SS (default 60)
PIN_MOSI (default 59)
PIN_MISO (default 58)
```
So for example to change to using pins 0-3 for these you would add `-DPIN_MISO=0 -DPIN_MOSI=1 -DPIN_SS=2 -DPIN_CLK=3` to the command line.
The docs don't say, but should, that if you redefine any of the PIN_* symbols then you should redefine them all.
Perfect! BTW: I just did a quick compile test and it looks like adding 8.3 uSD support adds about 20 kB to program size and adding long filenames adds about 10 kB on top of that.
This code runs as expected with the Prop tool, however only returns the pin status of the basepin for dpins, apins, cpins, all other pins return 0.
Not sure if it is addpins , pinfloat, or readpin.
In the code below, it never sees a value of 3 on the cpins. ie P25 high and P24 low. Only sees P24 go high. So it never exists the loop looking for that status.
This code runs as expected with the Prop tool, however only returns the pin status of the basepin for dpins, apins, cpins, all other pins return 0.
Not sure if it is addpins , pinfloat, or readpin.
It's readpin, unfortunately. It's only reading a single pin. There's an interesting story behind that: for both pinwrite and pinread, handling multiple pins is much more complicated than handling a single pin. One pin operation can be translated to a single assembly instruction (testp in the case of readpin) but multiple pins requires using the hardware registers and shifting and masking. I implemented the pinread code back when only one pin was supported in Spin2, and forgot to update it when Chip changed the language.
It'll be fixed in the next release of the compiler, although alas this fix will come at a performance cost for the common case of reading a single pin.
For now, you can use the replacement function below (it should work in PNut/PropTool as well):
pub mypinread(x) : y
y := (x & $20) ? outb : outa
y >>= x ' implicitly relies on only bottom 5 bits being used
x >>= 6 ' now x has number of pins to use
y := y ZEROX x
It's interesting to compare the assembly generated by flexspin for this with the code for pinr_ in Chip's interpreter. The interpreter code reads:
pinr_ testb x,#5 wc 'read ina or inb
if_nc mov y,ina
if_c mov y,inb
ror y,x 'lsb-justify
shr x,#6 'trim
zerox y,x
_ret_ mov x,y 'result in stack top
Which would be the same number of instructions except for the "ret" at the end; one of these days I'll have to add an optimization pass to get rid of ret when possible.
It'll be fixed in the next release of the compiler, although alas this fix will come at a performance cost for the common case of reading a single pin.
Thanks for the quick fix with the spin code, I will give it a try later today!
I wonder if there could be any optimization that could be done at compile time to determine if only one pin is being used or not.
Comments
EDIT: I just compiled that example as is. It seems to run fine for me. Loop count is over 4000 and still looks the same. eg:
Loadp2 version string: version 0.043 Dec 20 2020
PS: Loadp2 user baud was set to Eric's preferred 230400. I'm guessing that's same for you given there's nothing changing the baud in the program.
BTW: this is running on Win10 on a Dell laptop with the USB link speed set to 256k. The laptop isnt exactly slow, so I’ll keep poking at this. It would be nice to debug at full speed.
Thank you both for your help!
EDIT: There is definitely something happening on the PC side with buffering, and when this happens the PC apparently signals down the USB channel and kills the P2-EVAL. The effect is the same as if you'd closed the debug window in FlexGUI. With delays inserted in the code to allow the PC to catch up, it's a non-issue. As the baud rate increases, so must the value of any delay inserted between print statements. Things seem solid with a 15 mS delay between PRINT statements, regardless of baud rate. Where do I go from here?
there are buffer size settings and some other things there...
Guess I'm biased, but I wish C gave shifts a high precedence like Spin2.
Tried this and seems to work:
That last line is something that C's rand() does for you automatically.
Found out the hard way that my code explodes if you don't do that.
Probably something about negative numbers messing things up...
Not sure why FlexSpin C RAND_MAX value is 0x3fffffff and not 0x7fffffff though...
Good point, Eric. The back story: this all started when I rewrote all the FlexBASIC string functions for speed. To flush out any memory leaks or misbehaviors I ran a test program in a continuous loop. Basically I was just banging the bejeepers out of the string libraries trying to break them. And I broke it spectacularly. And randomly. No real pattern. It felt like a memory problem, but after a deep inspection of my code, I started getting a feeling that my code was (mostly) ok. And then EvanH and you both twigged to the idea that this was really a PC comm issue. And indeed it was.
So what I’m really trying to do is to break things in a way that lets me study the output so I can see what broke. For realtime use I’ve already changed to printing to the VGA driver Eric wrote. For unattended testing I may use 9p.
Your comment resulted in me following some interesting rabbit trails down in the bowels of Windows, but in the end nothing I did really made any difference. The USB latency timer seemed promising initially but ultimately made no real difference. Still, it was a useful exercise and I do appreciate the input.
It's called _rnd() and is declared in <propeller2.h>. It should probably be renamed _getrnd(), but we (forum users) made the propeller2.h file definition back when the function was still RND() in Spin2.
If not, maybe _rnd() can add RAND_MAX and _getrnd() can be without that?
Also, why is RAND_MAX not $7FFF_FFFF?
I think it's due to the pseudo-random number generator (in rand.c) making some of the bits very predictable e.g. it would always alternate positive / negative. Masking out the upper bits hides that. It's not an issue for _getrnd() or _rnd(), there's no need to mask those.
Ok, I've replaced code above with this and seems all OK:
Can I use these as a poor man's polymorphism?
I have a function that is currently in 3 different forms to accept 2, 3 or 4 integer arguments.
Can I combine them into one using Variadic form?
Might be more work that it's worth though, even if it possible...
In C++ (and FlexC) there's another option, to declare default values for arguments, e.g.: can be called as "foo(1, 2)", "foo(1,2,3)" or "foo(1,2,3,4)". The first two expand to "foo(1, 2, 98, 99)" and "foo(1, 2, 3, 99)" respectively.
Finally free from 8.3 filenames... Now, we just need to be able to use different pins for the uSD...
This code runs as expected with the Prop tool, however only returns the pin status of the basepin for dpins, apins, cpins, all other pins return 0.
Not sure if it is addpins , pinfloat, or readpin.
In the code below, it never sees a value of 3 on the cpins. ie P25 high and P24 low. Only sees P24 go high. So it never exists the loop looking for that status.
You haven’t given us a full description of the output of your code, so I’m not sure how much help can be given.
It's readpin, unfortunately. It's only reading a single pin. There's an interesting story behind that: for both pinwrite and pinread, handling multiple pins is much more complicated than handling a single pin. One pin operation can be translated to a single assembly instruction (testp in the case of readpin) but multiple pins requires using the hardware registers and shifting and masking. I implemented the pinread code back when only one pin was supported in Spin2, and forgot to update it when Chip changed the language.
It'll be fixed in the next release of the compiler, although alas this fix will come at a performance cost for the common case of reading a single pin.
For now, you can use the replacement function below (it should work in PNut/PropTool as well):
It's interesting to compare the assembly generated by flexspin for this with the code for pinr_ in Chip's interpreter. The interpreter code reads: The flexspin compiled version looks like: Which would be the same number of instructions except for the "ret" at the end; one of these days I'll have to add an optimization pass to get rid of ret when possible.
Thanks for the quick fix with the spin code, I will give it a try later today!
I wonder if there could be any optimization that could be done at compile time to determine if only one pin is being used or not.