Shop OBEX P1 Docs P2 Docs Learn Events
Can't Wait for PropGCC on the P2? - Page 12 — Parallax Forums

Can't Wait for PropGCC on the P2?

191012141526

Comments

  • Thanks!
  • evanhevanh Posts: 16,032
    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.

  • evanhevanh Posts: 16,032
    This is working for me:
    void hwreset(void)
    {
        int cmd = use_rts_for_reset ? TIOCM_RTS : TIOCM_DTR;
        ioctl(hSerial, TIOCMBIS, &cmd); /* assert bit */
        msleep(10);
        ioctl(hSerial, TIOCMBIC, &cmd); /* clear bit */
        msleep(10);
        ioctl(hSerial, TIOCMBIS, &cmd); /* assert bit */
        msleep(90);
        tcflush(hSerial, TCIFLUSH);
    }
    
    
  • evanhevanh Posts: 16,032
    edited 2019-01-09 03:42
    Oh, and to leave DTR set upon port close I've just removed the restoring tcsetattr() call from serial_done().

    EDIT: Actually, it's weirder. DTR must have been a complete pulse at this call.
  • 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.

    Thanks.
  • evanhevanh Posts: 16,032
    edited 2019-01-09 05:35
    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:
    $ ../bin/loadp2 -v -CHIP -p /dev/serial/by-id/usb-Parallax_Inc._Propeller_P2-EVAL-ES_P2EEL5T-if00-port0 -t all_cogs_blink.binary
    

    And here's another one that I can issue together for the P123 FPGA board without confusion:
    $ ../bin/loadp2 -v -FPGA -p /dev/serial/by-id/usb-FTDI_FT231X_USB_UART_DA01LDZU-if00-port0 -t ad7400-2.binary
    
  • 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.
  • Love it! Just tried it and load was instantaneous. Thanks :)
  • evanhevanh Posts: 16,032
    edited 2019-01-10 02:37
    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.
    void serial_done(void)
    {
        if (hSerial != -1) {
            tcflush(hSerial, TCIOFLUSH);
    //        tcsetattr(hSerial, TCSANOW, &old_sparm);
            ioctl(hSerial, TIOCNXCL);
            close(hSerial);
            hSerial = -1;
        }
    }
    
    
  • evanhevanh Posts: 16,032
    I think I'm seeing why you originally had DTR default to clear state. On the P123 board, it needs to be that if always restoring the port config.
  • Hey Dave, is there any chance you could update p2gcc to return non-zero when an error occurs?
  • DavidZemonDavidZemon Posts: 2,973
    edited 2019-01-10 15:11
    Finally getting around to playing with p2gcc and learning the various assembly instructions. I thought I'd share my first snippet of reusable C:
    #define io_asm(instruction, pinNumber) __asm__ __volatile__ (#instruction " #" #pinNumber)
    

    That lets you write something like
    io_asm(dirh, 58);
    
    Which, I think, is much easier than
    __asm__ __volatile__ ("dirh #58");
    
  • Dave Hein wrote: »
    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.
    Much faster load and exec on macOS!

    dgately

  • Dave HeinDave Hein Posts: 6,347
    edited 2019-01-10 15:01
    evanh wrote: »
    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.
    void serial_done(void)
    {
        if (hSerial != -1) {
            tcflush(hSerial, TCIOFLUSH);
    //        tcsetattr(hSerial, TCSANOW, &old_sparm);
            ioctl(hSerial, TIOCNXCL);
            close(hSerial);
            hSerial = -1;
        }
    }
    
    
    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.
  • dgately wrote: »
    Dave Hein wrote: »
    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.
    Much faster load and exec on macOS!

    dgately
    Glad it's working fine for the Mac.
  • Dave HeinDave Hein Posts: 6,347
    edited 2019-01-10 15:00
    DavidZemon wrote: »
    Finally getting around to playing with p2gcc and learning the various assembly instructions. I thought I'd share my first snippet of reusable C:
    #define io_asm(instruction, pinNumber) __asm__ __volatile__ (#instruction " #" #pinNumber : : )
    

    That lets you write something like
    io_asm(dirh, 58);
    
    Which, I think, is much easier than
    __asm__ __volatile__ ("dirh #58" : : );
    

    I think you could just do
    __asm__("dirh #58");
    
    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.
  • Dave Hein wrote: »
    DavidZemon wrote: »
    Finally getting around to playing with p2gcc and learning the various assembly instructions. I thought I'd share my first snippet of reusable C:
    #define io_asm(instruction, pinNumber) __asm__ __volatile__ (#instruction " #" #pinNumber : : )
    

    That lets you write something like
    io_asm(dirh, 58);
    
    Which, I think, is much easier than
    __asm__ __volatile__ ("dirh #58" : : );
    

    I think you could just do
    __asm__("dirh #58");
    
    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....
  • evanhevanh Posts: 16,032
    Dave Hein wrote: »
    So would this change be safe do in all cases? That is should I remove the tcsetattr enitrely for Windows, Linux and Mac.

    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.

  • DavidZemon wrote: »
    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.
  • Dave Hein wrote: »
    DavidZemon wrote: »
    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.

  • One more request...

    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
  • evanhevanh Posts: 16,032
    All good here. Thanks Dave.
  • 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?
  • 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?
  • Dave HeinDave Hein Posts: 6,347
    edited 2019-01-12 03:18
    dgately wrote: »
    One more request...

    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:
    loadp2    - 0.008
    p2asm     - 0.006
    p2link    - 0.003
    s2pasm    - 0.004
    p2dump    - 0.003
    p2dumpobj - 0.003
    
  • DavidZemonDavidZemon Posts: 2,973
    edited 2019-01-12 04:30
    Dave Hein wrote: »
    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)
    
  • Got a segfault for ya :)

    Here's the gdb output
    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.
  • Trying to set the ISR, and I have the following:
    #define ISR(name) __attribute__ ((naked)) void name (void)
    #define set_isr(interruptNumber, isr) __asm__ volatile ("mov ijmp" #interruptNumber ", #_" #isr)
    
    int main () {set_isr(1, my_fancy_isr);}
    
    ISR(my_fancy_isr) {
        io_asm(drvnot, 57);
        interrupt_return(1);
    }
    

    In blinky.s, the mov instruction looks correct:
    mov ijmp1, #_my_fancy_isr
    

    But it looks like p2asm is then converting that "mov" into a wrlong. Any way around this?
    wrlong	#_my_fancy_isr, ##ijmp1
    
  • 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.
Sign In or Register to comment.