Dave,
I'm back home now and have been testing loadp2 out. It still has a problem with DTR under Linux, particularly when transitioning to terminal_mode(). It looks like DTR is always raised on a tcsetattr() call. Which I think can be managed.
What I'm thinking is the hwreset() function should always leave DTR set. And DTR can be left set when the comport is closed. This way, DTR only needs to toggle when hwreset() is called.
I tried something like that before, but it didn't seem to work for me on my Linux machines. However, I may have had other changes in my code that were messing things up. I'll try your fix on my Linux machine, and see if works.
Ah, found out how to specify a particular USB device comport among many. There is an ID for each. I was looking for something like UUID when I found them. Here's an example command for programming my P2ES board:
I checked a couple of changes into GitHub for loadp2. The first one fixes a problem with computing the clock mode for frequencies above 200 MHz. The second one incorporates evanh's hwreset routine. This fixes the problem with switching baud rates on Linux, and hopefully on the Mac as well. On Linux I can now load at 2 Mbaud, and then switch the serial port to the user baud rate.
The first change is in loadp2_src/loadp2.c, and the second change is in loadp2_src/osint_linux.c.
I still have to remove the restoring call inside of serial_done(). I probably should have said that this notably impacts the P123 board when exiting the terminal mode. And probably also causes an immediate reset without terminal mode. I think the short pulse length means the capacitor discharge curve prevents any reset in one polarity but not the other. So the P2ES board, without the inverting transistor, is not affected. Any other boards that has the inverting transistor on DTR will be affected also.
I don't see any great need to restore any prior config.
I checked a couple of changes into GitHub for loadp2. The first one fixes a problem with computing the clock mode for frequencies above 200 MHz. The second one incorporates evanh's hwreset routine. This fixes the problem with switching baud rates on Linux, and hopefully on the Mac as well.
I still have to remove the restoring call inside of serial_done(). I probably should have said that this notably impacts the P123 board when exiting the terminal mode. And probably also causes an immediate reset without terminal mode. I think the short pulse length means the capacitor discharge curve prevents any reset in one polarity but not the other. So the P2ES board, without the inverting transistor, is not affected. Any other boards that has the inverting transistor on DTR will be affected also.
I don't see any great need to restore any prior config.
So would this change be safe do in all cases? That is should I remove the tcsetattr enitrely for Windows, Linux and Mac. Or should I just remove it only for Mac connected to an FPGA? I'll test it with Windows and Linux with both the P2 Eval board and a DE2-115 FPGA. If it works OK for those cases I'll just remove the tcsetattr from serial_done.
I checked a couple of changes into GitHub for loadp2. The first one fixes a problem with computing the clock mode for frequencies above 200 MHz. The second one incorporates evanh's hwreset routine. This fixes the problem with switching baud rates on Linux, and hopefully on the Mac as well.
However, there are some P2 intrinsics that I want to implement using the magical GCC incantations. I just haven't gotten around to figuring out how to do it. I think it might require compiling the definitions into the compiler. At some point we need to modify the GCC compiler to generate native P2 assembly instead of post-converting P1 assembly into P2 code.
However, there are some P2 intrinsics that I want to implement using the magical GCC incantations. I just haven't gotten around to figuring out how to do it. I think it might require compiling the definitions into the compiler. At some point we need to modify the GCC compiler to generate native P2 assembly instead of post-converting P1 assembly into P2 code.
The volatile is important, but you're definitely right about not needing the extra colons. And about getting this built into GCC.... just as soon as Parallax hold that meeting so we can get started....
Hey Dave, is there any chance you could update p2gcc to return non-zero when an error occurs?
Checked in a change to GitHub so that p2gcc now returns a value of 1 when an error occurs.
Yay! Thank you that makes my life much better. I've set up a run configuration in CLion that invokes my Makefile (the run-* targets, which first compile and then load the binary) and it happened multiple times where a build would fail but Make would soldier on with the old binary and I'd be going "but I fixed that problem! what's going on???"
I checked in a change to loadp2.c to check for a P2 when the serial port is specified on the command line. This fixes a problem with loadp2 not automatically configuring for the P2 version.
I checked in the change suggested by evanh that removed the call to tcsetattr in the serial_done routine.
Could each of the binaries built within the p2gcc project output its version? Keeping up with the latest binaries from p2gcc, spin2cpp & spin2gui projects (which all include loadp2 sources), is a little bit of an issue.
I actually place the most common binaries into /opt/parallax/bin (typical for macOS & Linux users). I like to keep that directory filled with the latest tool binaries. It would be good to quickly get versions from the tools and place only the newest into my tool directory.
p2gcc doesn't have any inherent support for ISRs yet, does it? If I want an ISR, I'll have to load the IJMP* register myself and call RETI* when I'm done; is that right?
Could each of the binaries built within the p2gcc project output its version? Keeping up with the latest binaries from p2gcc, spin2cpp & spin2gui projects (which all include loadp2 sources), is a little bit of an issue.
I updated the version number for loadp2, and added version numbers to p2asm, p2link, s2pasm, p2dump and p2dumpobj. The current version numbers are:
That's correct. You have to handle interrupts yourself. There's nothing in p2gcc to support it. What kind of features are you thinking of?
All I can think of at this moment is something like so:
ISR1(my_fancy_isr) {
// Do stuff
}
And having "ISR1" would declare it as "naked", automatically append the IRET1 instruction at the end, and maybe even inject the appropriate instruction to write its address to IJMP1? GCC documentation (https://gcc.gnu.org/onlinedocs/gcc/ARM-Function-Attributes.html) implies that naked will limit us to "Basic asm" and NO C, which is too bad. But ISRs should be short... so hopefully workable.
I think the "naked" is a good thing to have on an ISR... but maybe not? Been a long time since I did anything with interrupts. I want to ensure GCC doesn't mess with the stack (push/pop r0-r15, etc) once inside the function.
For the moment, I'm using this macro:
#define ISR(name) __attribute__ ((naked)) void name (void)
Core was generated by `p2asm -c -o -hub blinky.spin2'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:62
62 ../sysdeps/x86_64/multiarch/strlen-avx2.S: No such file or directory.
(gdb) bt
#0 __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:62
#1 0x00007f1a7b93531e in _IO_vfprintf_internal (s=0x563824e324a0, format=0x563823624478 "ERROR: Invalid opcode \"%s\"\n", ap=0x7ffe45218740) at vfprintf.c:1638
#2 0x000056382361a3c0 in PrintError (str=0x563823624478 "ERROR: Invalid opcode \"%s\"\n") at p2asm.c:95
#3 0x000056382361fac4 in ParseDat (pass=1, buffer2=0x563823678400 <buffer2> "\tsetintISR_1 #4", tokens=0x7ffe45218970, num=3) at p2asm.c:1718
#4 0x0000563823620748 in Parse (pass=1) at p2asm.c:1980
#5 0x0000563823620ce0 in main (argc=5, argv=0x7ffe45219438) at p2asm.c:2060
(gdb) q
p2asm with debugging symbols, core file, and spin files are in the attached zip
I can see where my problem is, both in the spin and original C source code, so no need to help me debug that. But I thought you might appreciate knowing about the segfault.
The problem is caused by s2pasm. It converts P1 COG assembly to P2 hubexec. The P1 COG model puts everything in cog memory, whereas the P2 code resides in hub memory. So I have to convert variable access that use MOV to hub accesses using RDLONG and WRLONG. s2pasm contains a list of register names such as ina and outa, and it will not change the MOV to a RDLONG/WRLONG for registers. However, I neglected to include ijmpx and iretx in the list of register names.
I added ijmp1, ijmp2, ijmp3, iret1, iret2 and iret3 to the list of register names and checked it into GitHub.
I think at some point I will switch to running PropGCC in the LMM mode instead of the COG mode. This will eliminate having to convert MOV to RDLONG/WRLONG. However, I will have to handle the LMM pseudo-ops.
Note that when using __asm__ to insert assembly code you can produce code that s2pasm can't handle well. Labels need to be on a line by themselves. There is also a problem with handling instructions that have 3 parameters, such as SETBYTE.
Comments
I'm back home now and have been testing loadp2 out. It still has a problem with DTR under Linux, particularly when transitioning to terminal_mode(). It looks like DTR is always raised on a tcsetattr() call. Which I think can be managed.
What I'm thinking is the hwreset() function should always leave DTR set. And DTR can be left set when the comport is closed. This way, DTR only needs to toggle when hwreset() is called.
EDIT: Actually, it's weirder. DTR must have been a complete pulse at this call.
Thanks.
And here's another one that I can issue together for the P123 FPGA board without confusion:
The first change is in loadp2_src/loadp2.c, and the second change is in loadp2_src/osint_linux.c.
I don't see any great need to restore any prior config.
That lets you write something like
Which, I think, is much easier than
dgately
I think you could just do However, there are some P2 intrinsics that I want to implement using the magical GCC incantations. I just haven't gotten around to figuring out how to do it. I think it might require compiling the definitions into the compiler. At some point we need to modify the GCC compiler to generate native P2 assembly instead of post-converting P1 assembly into P2 code.
The volatile is important, but you're definitely right about not needing the extra colons. And about getting this built into GCC.... just as soon as Parallax hold that meeting so we can get started....
I don't see an issue. Worst case is messing with future runs of other programming software like Pnut. Those will tend to do their own settings anyway.
Checked in a change to GitHub so that p2gcc now returns a value of 1 when an error occurs.
Yay! Thank you that makes my life much better. I've set up a run configuration in CLion that invokes my Makefile (the run-* targets, which first compile and then load the binary) and it happened multiple times where a build would fail but Make would soldier on with the old binary and I'd be going "but I fixed that problem! what's going on???"
I checked in the change suggested by evanh that removed the call to tcsetattr in the serial_done routine.
Could each of the binaries built within the p2gcc project output its version? Keeping up with the latest binaries from p2gcc, spin2cpp & spin2gui projects (which all include loadp2 sources), is a little bit of an issue.
I actually place the most common binaries into /opt/parallax/bin (typical for macOS & Linux users). I like to keep that directory filled with the latest tool binaries. It would be good to quickly get versions from the tools and place only the newest into my tool directory.
Thx
dgately
All I can think of at this moment is something like so:
And having "ISR1" would declare it as "naked", automatically append the IRET1 instruction at the end, and maybe even inject the appropriate instruction to write its address to IJMP1? GCC documentation (https://gcc.gnu.org/onlinedocs/gcc/ARM-Function-Attributes.html) implies that naked will limit us to "Basic asm" and NO C, which is too bad. But ISRs should be short... so hopefully workable.
I think the "naked" is a good thing to have on an ISR... but maybe not? Been a long time since I did anything with interrupts. I want to ensure GCC doesn't mess with the stack (push/pop r0-r15, etc) once inside the function.
For the moment, I'm using this macro:
Here's the gdb output
p2asm with debugging symbols, core file, and spin files are in the attached zip
I can see where my problem is, both in the spin and original C source code, so no need to help me debug that. But I thought you might appreciate knowing about the segfault.
In blinky.s, the mov instruction looks correct:
But it looks like p2asm is then converting that "mov" into a wrlong. Any way around this?
I added ijmp1, ijmp2, ijmp3, iret1, iret2 and iret3 to the list of register names and checked it into GitHub.
I think at some point I will switch to running PropGCC in the LMM mode instead of the COG mode. This will eliminate having to convert MOV to RDLONG/WRLONG. However, I will have to handle the LMM pseudo-ops.
Note that when using __asm__ to insert assembly code you can produce code that s2pasm can't handle well. Labels need to be on a line by themselves. There is also a problem with handling instructions that have 3 parameters, such as SETBYTE.