Shop OBEX P1 Docs P2 Docs Learn Events
Learning P2 Assembly — Parallax Forums

Learning P2 Assembly

I spent today learning P2 Assembly.
Hugely interesting.
First I read the main documentation.

Then I read this excellent tutorial for the P1.
http://www.rayslogic.com/propeller/Programming/DeSilvaAssemblyTutorial.pdf

I understand many of the concepts are similar.
What else do you recommend reading?

I will say it is very different from traditional programming.
Most interesting and enlightening.
Chris

Comments

  • Yeah, I think to understand the P2 one has to start with the P1.

    DeSilva is very good, I recommend to read all the source of @JonnyMac produced objects, everything in the Parallax GitHub starting with JM_ is golden to understand the concepts of P1 or P2.

    A lot of things are similar but a lot of things evolved out of the unusual thinking you need to change your programming style from single execution line to really parallel running processes.

    It is in no way similar to threading used in modern languages and processors. It is different, confusing and way more simple once you - hmm - see the light?

    The major point is that the execution of one COG (=Core) can not affect the execution or timing of another one. You usually have one main program running in one COG and communicating with other processes running in other GOG's via share HUB memory locations, usually called mailboxes here.

    Say you have a video driver, it has its main loop, providing hsync, vsync and the data needed to write to VGA/TV/whatever. That COG/core/process has some idle time while constantly refreshing the screen and reads its mailbox then to - say put a string somewhere on the screen. It does it whenever it can squeeze it in, still providing perfect timing for the video signal.

    The COG/core/process USING it does not need to be aware of any timing constrains of the Video signal on the pins, it just talks to the mailbox and says - hey put that string there.

    So you decouple things and the things itself get simpler.

    The P2 is a step beyond that so you do not just(?) have 8 parallel working COGs/cores/processes but on top of that 64 independent little co processors in each pin. those smart-pins.

    So instead of looping one process to pulse out a PWM signal to a servo and try to keep your loop under 50ms or so, you just tell the pin what you need and the pin will do that while your program can do other things.

    so you are completely right in saying "I will say it is very different from traditional programming"

    Enjoy!

    Mike

  • JonnyMacJonnyMac Posts: 8,926
    edited 2021-07-01 00:29

    You're always too kind to me, Mike. I'm not as gifted at PASM as so many of our forum friends are, but the thing is that the Propeller family was designed by a real-world embedded programmer, not a committee at a giant corporation. That does make it different, and programmer-friendly -- especially the P2. As I have been porting P1 code to the P2 I find that most PASM2 instructions are easier to use. To be candid, though, I wish the P2 had the free-running timers available in the P1 (that are not connected to a pin). Still, the smart pins really shake things up.

    @lozinski : Since Mike brought up P2 smart pins here's a bit of code that I wrote over the weekend to let the P2 control LX-16a "bus servos." These do servo-like things but work in a multi-drop configuration. The half-duplex serial connection is at 3.3V so it's directly compatible with the Propeller. I put a 1K resistor between the P2 and the LX-16A, just to prevent an accident while developing code. I also added a pull-up to the line to keep it idle while the Propeller is booting up or not transmitting. Since the transactions are so short I made this code cogless -- it runs inline. So far I've tested it with a couple features of the LX-16a and it works fine. Even the manufacturer is interested (I reached out to fill some gaps in their protocol specification).

    For me, the ability to toss PASM code into my P2 projects without launching a separate cog is a lot of fun. It certainly makes experimenting with PASM2 much easier than experimenting with PASM1. Have fun, and welcome to the forums.

    con
    
      TX_UART = P_ASYNC_TX | P_OE                                   ' smart pin tx uart
      RX_UART = P_ASYNC_RX                                          ' smart pin rx uart
    
    
    pri lx_coms(pin, mode, p_tx, p_rx) : rxlen | baudtix, x, txlen, tocount
    
    '' Handle serial coms with LX bus servo
    '' -- pin is serial io to lx servo
    '' -- mode is M_TX (transmit only) or M_TXRX (transmit/recieve)
    '' -- p_tx is pointer to transmit buffer
    '' -- p_rx is pointer to recieve buffer (for mode TXRX)
    
      bytefill(p_tx, $55, 2)                                        ' add header to tx packet
      calc_checksum(p_tx, true)                                     ' add checksum to tx packet
    
      baudtix := clkfreq / 115_200                                  ' ticks per bit
    
      org
                    cmp       mode, #M_TX                   wcz
        if_e        jmp       #tx_config
                    cmp       mode, #M_TXRX                 wcz
        if_e        jmp       #tx_config
                    jmp       #done                                 ' exit if not a transmit request
    
    tx_config       fltl      pin                                   ' release pin
                    wrpin     #TX_UART, pin                         ' set to tx uart
                    mov       x, baudtix                            ' setup baud
                    shl       x, #16
                    or        x, #(8-1)                             ' and bits
                    wxpin     x, pin
                    wypin     #0, pin
                    drvl      pin                                   ' activate tx uart
    
                    rep       #1, #10                               ' idle for 1 byte period
                     waitx    baudtix
    
    transmit        mov       x, p_tx                               ' get data length
                    add       x, #LX_DLEN
                    rdbyte    txlen, x
                    tjz       txlen, #done                          ' abort if no length in packet
                    add       txlen, #3                             ' set tx packet length (2x header + cs)
    
                    drvh      #LED1                                 ' tx led on (debugging)
    
    tx_loop         rdbyte    x, p_tx                               ' get packet byte
                    add       p_tx, #1                              ' advance pointer
                    wypin     x, pin                                ' load into sp uart
                    waitx     baudtix                               ' let tx get started
                    rdpin     x, pin                        wc      ' verify busy flag
        if_c        jmp       #$-1                                  ' let byte finish
                    djnz      txlen, #tx_loop                       ' if not end of packet, do next byte
    
                    drvl      #LED1                                 ' tx led off
    
                    cmp       mode, #M_TXRX                 wcz     ' expecting response from this packet?
        if_ne       jmp       #done
    
    turn_around     fltl      pin                                   ' clear tx configuration
                    wrpin     #RX_UART, pin                         ' setup for rx
                    drvl      pin
                    mov       rxlen, #0
    
                    mov       tocount, #60                          ' 60 bit periods = ~500us
    .ta_loop        testp     pin                           wc      ' test for response
        if_c        jmp       #get_byte
                    waitx     baudtix
                    djnz      tocount, #.ta_loop
                    mov       rxlen, ##TIMEOUT                      ' no packet, return timeout error   
                    jmp       #done
    
    rx_loop         mov       tocount, #15                          ' set time-out counter
    check_rx        testp     pin                           wc      ' anything waiting?
        if_c        jmp       #get_byte                             ' yes, get byte from rx uart
                    waitx     baudtix                               ' check for time-out
                    djnz      tocount, #check_rx
                    jmp       #done
    
    get_byte        drvh      #LED2                                 ' rx led on (debugging)
                    rdpin     x, pin                                ' read new byte
                    shr       x, #24                                ' align lsb
                    wrbyte    x, p_rx                               ' write to buffer
                    add       p_rx, #1                              ' bump pointer
                    add       rxlen, #1                             ' bump rx bytes received
                    jmp       #rx_loop                              ' wait for next byte
    
    done            drvl      #LED2                                 ' rx led off
                    ret
      end
    
  • I agree that bottom up design is much better.
    I have looked at so many chips over so many years but this one is way way better. The first one I am jumping on.
    I am tempted to write a comparison and compliments, but I do not want to name the potential competitors.
    Chip is only the second person I know of, in all of history who both designed a chip and a language. Usually the chip designers target C, and the language designers also target C.

    Your point about the advantages of this chip was most helpful. And also explained to me why this architecture evolved in the real-time area. Clearly great for IoT, but not just for IoT.

  • hinvhinv Posts: 1,252

    Correct me if I am wrong, but aren't the "mailboxes" some shared addresses between 0-1, 2-3, 4-5, and 6-7.

  • @hinv said:
    Correct me if I am wrong, but aren't the "mailboxes" some shared addresses between 0-1, 2-3, 4-5, and 6-7.

    I think you are confusing it with LUT where a COG can access the LUT of its twin.
    The mailboxes are just hub ram locations defined for the purpose to exchange information between two or more COGs. These can be everywhere in the HUB and of any size. As I am aware there isn't any standard to present day. A few forumistas have had a debate on this several times but no standard was agreed.

Sign In or Register to comment.