Shop OBEX P1 Docs P2 Docs Learn Events
Full Duplex Serial P2 — Parallax Forums

Full Duplex Serial P2

Has this popular P1 object been ported to P2 yet? I just wanted to ask before porting it myself.

Comments

  • Yes Eric has FullDuplexSerial in FastSpin, also a simple serial.

    I did FullDuplexSerial2 providing two Ports with Buffers in LUT and self contained as PASM object, @RossH uses it also in Catalina.

    FullDuplexSerial2.Spin provides the usual Spin Routines alike FastSpins Driver do and offers asyncron block/string transfers and a simple strIn function also.

    I need to get Eric to provide it together with FlexGui/FastSpin it seems to be stable.

    Mike
  • Why waste a cog on serial when that's what the smartpins are for? You don't need a separate cog: talk to the smartpins directly from the same cog that would talk to your serial cog if you had one. You don't need a transmit buffer: give the smartpin the next byte to send as soon as it finishes sending the previous byte. You don't need a receive buffer, either, usually: set an interrupt to fire whenever a byte comes in, and use that byte immediately via combined coroutines and interrupts, e.g. ires1 at the beginning of your getc function.
  • Why waste a cog on serial when that's what the smartpins are for? You don't need a separate cog: talk to the smartpins directly from the same cog that would talk to your serial cog if you had one. You don't need a transmit buffer: give the smartpin the next byte to send as soon as it finishes sending the previous byte. You don't need a receive buffer, either, usually: set an interrupt to fire whenever a byte comes in, and use that byte immediately via combined coroutines and interrupts, e.g. ires1 at the beginning of your getc function.

    The basic idea is to have 2 ports with 512 bytes buffer each direction in one COG without using HUB ram except a couple of longs for a mailbox

    Mike
  • It seems the most efficient way of handling so called full-duplex serial on the P2 is to not waste a cog, but let the interrupts and smartpins handle it since smartpin serial is very low overhead. Having buffered transmit seems to be a waste most of the time and especially at higher baud rates where it is faster to write it directly to the smartpin and simply interrupt on each receive character for buffering. At least that's how I do it well into the high megabaud range.
  • It's not clear to me right now whether interrupts work in the riscv-p2 environment.
  • It's not clear to me right now whether interrupts work in the riscv-p2 environment.

    They don't, at least not on the risc-v COG. Are you using riscv-p2? Or micropython? If it's just a serial driver that you want then using another COG probably is a good solution for those environments.
  • ersmith wrote: »
    It's not clear to me right now whether interrupts work in the riscv-p2 environment.

    They don't, at least not on the risc-v COG. Are you using riscv-p2? Or micropython? If it's just a serial driver that you want then using another COG probably is a good solution for those environments.
    Thanks, Eric. Just riscv-p2. Although I have checked the micropython source for hints.
  • Saving the Hub RAM for buffers seems like less of a win on P2 where there is so much more Hub RAM. What I would like to see is more ports emulated with maybe one cog doing all the work. If we can do 4 ports at 110 kbaud with one cog on P1 it seems like we should be able to do 8 on P2, maybe even more with smartpins, and that would e a very useful object for some purposes. I am currently working on a P1 board with 12 ports, most of which will only operate at 9600 baud but one of which needs to actually be fast. This is proving a bit of a challenge but should be dead simple on P2.
  • ersmith wrote: »
    It's not clear to me right now whether interrupts work in the riscv-p2 environment.

    They don't, at least not on the risc-v COG. Are you using riscv-p2? Or micropython? If it's just a serial driver that you want then using another COG probably is a good solution for those environments.
    Thanks, Eric. Just riscv-p2. Although I have checked the micropython source for hints.

    Ah, interesting, I didn't know anyone else was using riscv-p2 :). Generally spin2cpp should be able to convert .spin code into something that riscv-p2 can digest. If you have any trouble or questions please let me know!
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2019-12-19 00:52
    Well if we were to dedicate a cog to serial then we should make it handle multiple ports since it can do this easily. I'd even be inclined to have it maintain a runtime and from there time of day if set and countdown timers etc. May as well keep it busy and perhaps it could do other stuff too as a dedicated I/O cog. A millisecond runtime won't roll over for almost 50 days so it's good to use as a timestamp.
  • A millisecond runtime won't roll over for almost 50 days so it's good to use as a timestamp.
    Considering the hardware cycle counter won't roll over in anyone's lifetime, that sounds a bit unimpressive :)
  • Wuerfel_21 wrote: »
    A millisecond runtime won't roll over for almost 50 days so it's good to use as a timestamp.
    Considering the hardware cycle counter won't roll over in anyone's lifetime, that sounds a bit unimpressive :)

    True, but remember the main use for this is as a timestamp in milliseconds whereas you have to fudge 64-bits otherwise and besides its the timeout counters that are useful I find, I even assign an alarm vector to these so that in say 120ms when it times out without being retriggered, then it will execute the alarm vector if set. Don't miss the point of what I'm suggesting is that mainly a cog dedicated to one serial port is a sad cog indeed. Make it happy and useful instead.
  • jmgjmg Posts: 15,173
    It seems the most efficient way of handling so called full-duplex serial on the P2 is to not waste a cog, but let the interrupts and smartpins handle it since smartpin serial is very low overhead. Having buffered transmit seems to be a waste most of the time and especially at higher baud rates where it is faster to write it directly to the smartpin and simply interrupt on each receive character for buffering. At least that's how I do it well into the high megabaud range.

    Yes, the TX buffer is less important, and RX needs the most attention. (in UB3 I made Tx buffer 256 bytes and Rx 1536, to use all available XRAM in that part).
    TX tends to self-pace, and will add more stop bits if the SW is just a bit slower. RX without handshake is less tolerant, so the RX timing needs to manage full packed streams.
    12Mbd is a common upper baud limit, and sometimes 2 stop bits are needed. (UB3 seems to work at 8Md and 12Mbd, with 8.n.2 settings, and 6Mbd and lower are ok with 8.n.1)


    The is a use case for some modest Tx buffering, and that is to allow the upstream host (another COG in P2) to finish any short burst earlier.
    ie it can fill a buffer faster than the link can empty it, so that gives more CPU cycles to the user.
    Long sustained transmits are still essentially link speed determined.

    Another question with libraries, is whether to support HW handshake ?
    That needs more pins, but can work well if a design is unsure how much response delay will occur.
  • jmg wrote: »
    Another question with libraries, is whether to support HW handshake ?
    That needs more pins, but can work well if a design is unsure how much response delay will occur.

    I've never had to use hw handshake ever, and I was never tempted to either. Should we implement a Centronics port too? :)

    While the multi serial port cog can be very easy to implement, what we probably want to do is agree upon the software interface. Should we use mailboxes perhaps? That way all the buffering is looked after by the cog and the cog appears as a standard peripheral with hub memory as registers so that it is language agnostic.


  • msrobotsmsrobots Posts: 3,709
    edited 2019-12-19 08:49
    jmg wrote: »
    Another question with libraries, is whether to support HW handshake ?
    That needs more pins, but can work well if a design is unsure how much response delay will occur.

    I've never had to use hw handshake ever, and I was never tempted to either. Should we implement a Centronics port too? :)

    While the multi serial port cog can be very easy to implement, what we probably want to do is agree upon the software interface. Should we use mailboxes perhaps? That way all the buffering is looked after by the cog and the cog appears as a standard peripheral with hub memory as registers so that it is language agnostic.


    Yes, that is what FullDuplexSerial2 does. I was original inspired by JDserial(?) because it had a self contained PASM COG, once started it just needed two longs in HUB and you could reuse the HUB ram.

    Usable from PASM and SPIN.

    So that was my goal for FullDuplexSerial2. Just PASM and Buffer in the LUT. Simple Mailbox interface for each port.

    It supports async execution, so you can read or write, say a string or a block of bytes from/to HUB without waiting for it, just write two longs and do whatever you have to do next.

    Same with my plan to hijack TAQOZ in ROM. Switch it to Mailbox and it is Language Agnostic. Just another serial port software-wise, and well - yes - it needs the lower 64k, but FastSpin can handle that issue.

    And also yes, without LUT buffering one COG can run a lot of serial ports, I might try that out...

    Mike
Sign In or Register to comment.