Spin running on P2!

David BetzDavid Betz Posts: 13,723
edited 2013-01-17 - 21:09:33 in Propeller 2
Using the latest version of PropGCC for P2 and a slightly hacked version of Eric's spin2cpp translator, I got the following code running on my DE2-115:
VAR
  long val

PUB main
  dirb := $ffffffff
  val := $55555555
  repeat
    pinb := val
    val ^= $ffffffff
    waitcnt(getcnt + 30000000)
I'm not sure though if this actually qualifies as having Spin working on P2 since it is just Spin translated to C++. :-)
«1

Comments

  • David BetzDavid Betz Posts: 13,723
    edited 2013-01-16 - 04:47:10
    Just in case you wonder why I wrote my blink program the way I did, this program will not work on P2 because of the way PINB works in contrast with OUTA on P1.
    PUB main
      dirb := $ffffffff
      pinb := $55555555
      repeat
        pinb ^= $ffffffff
        waitcnt(getcnt + 30000000)
    
  • Roy ElthamRoy Eltham Posts: 2,790
    edited 2013-01-16 - 09:49:12
    Curious if either of these would work:
    PUB main
      dirb := $ffffffff
      pinb := $55555555
      repeat
        waitcnt(getcnt + 30000000)
        pinb ^= $ffffffff
    
    PUB main
      pinb := $55555555
      dirb := $ffffffff
      repeat
        pinb ^= $ffffffff
        waitcnt(getcnt + 30000000)
    

    I thought you could read PINx registers and expect them to be what you have driven them to as long as you waited long enough. I'm assuming the C++ code in your version would end up with the assigning and the xor'ing happening one after another and would optimize down to just the 2 instructions (mov, xor), with the loop stuff being after the wait, to jump back up? Am I missing something, or just wrong about pinb?

    Roy
  • David BetzDavid Betz Posts: 13,723
    edited 2013-01-16 - 10:01:42
    Roy Eltham wrote: »
    Curious if either of these would work:
    PUB main
      dirb := $ffffffff
      pinb := $55555555
      repeat
        waitcnt(getcnt + 30000000)
        pinb ^= $ffffffff
    
    PUB main
      pinb := $55555555
      dirb := $ffffffff
      repeat
        pinb ^= $ffffffff
        waitcnt(getcnt + 30000000)
    

    I thought you could read PINx registers and expect them to be what you have driven them to as long as you waited long enough. I'm assuming the C++ code in your version would end up with the assigning and the xor'ing happening one after another and would optimize down to just the 2 instructions (mov, xor), with the loop stuff being after the wait, to jump back up? Am I missing something, or just wrong about pinb?

    Roy

    Rearranging the code as you suggested did not make it work. Maybe Chip will comment on how PINx works. I seem to remember him saying that a read-modify-write instruction will do what we expect but not two separate instructions. I don't think propgcc optimizes to a single read-modify-write instruction.
  • SapiehaSapieha Posts: 2,964
    edited 2013-01-16 - 10:59:38
    Hi David.

    Have You tested use this instruction first?
    000011 zcn 1 cccc ddnnddddd 011100101   |   SETPORB     |   D/#n    | Assign PORTB to physical I/O ports (0-2) or internal I/O port 3
                                                                        | given register “D (0-511)” or number “n (0-3)”.
    
    
    David Betz wrote: »
    Rearranging the code as you suggested did not make it work. Maybe Chip will comment on how PINx works. I seem to remember him saying that a read-modify-write instruction will do what we expect but not two separate instructions. I don't think propgcc optimizes to a single read-modify-write instruction.
  • David BetzDavid Betz Posts: 13,723
    edited 2013-01-16 - 11:01:40
    Sapieha wrote: »
    Hi David.

    Have You tested use this instruction first?
    000011 zcn 1 cccc ddnnddddd 011100101   |   SETPORB     |   D/#n    | Assign PORTB to physical I/O ports (0-2) or internal I/O port 3
                                                                        | given register “D (0-511)” or number “n (0-3)”.
    
    
    No, I haven't tried that. Will it help with the problem I'm having?
  • SapiehaSapieha Posts: 2,964
    edited 2013-01-16 - 11:05:33
    Hi David.

    Maybe.

    I dont know how ports are on default mode ---> so this instruction can give You correct results if default are different that You wait

    David Betz wrote: »
    No, I haven't tried that. Will it help with the problem I'm having?
  • David BetzDavid Betz Posts: 13,723
    edited 2013-01-16 - 11:08:06
    Sapieha wrote: »
    Hi David.

    Maybe.

    I dont know how ports are on default mode ---> so this instruction can give You correct results if default are different that You wait
    I think the ports default to natural mapping where PINA is 0-31, PINB is 32-63, etc. I guess I wasn't clear in my original posts. The code in the top post of this topic works fine and blinks the 18 red LEDs on the DE2-115 board alternately, even then odd. The code in the second post does not work but that isn't because of port mapping. It seems to a consequence of the fact that P2 merges INx and OUTx into PINx. Sorry for the confusion!
  • SapiehaSapieha Posts: 2,964
    edited 2013-01-16 - 11:11:10
    Hi David.

    No problem..

    We are here to help others understand P2 ----> so Yours ideas help me and vice-versa
    David Betz wrote: »
    I think the ports default to natural mapping where PINA is 0-31, PINB is 32-63, etc. I guess I wasn't clear in my original posts. The code in the top post of this topic works fine and blinks the 18 red LEDs on the DE2-115 board alternately, even then odd. The code in the second post does not work but that isn't because of port mapping. It seems to a consequence of the fact that P2 merges INx and OUTx into PINx. Sorry for the confusion!
  • Roy ElthamRoy Eltham Posts: 2,790
    edited 2013-01-16 - 14:20:01
    David Betz wrote: »
    Rearranging the code as you suggested did not make it work. Maybe Chip will comment on how PINx works. I seem to remember him saying that a read-modify-write instruction will do what we expect but not two separate instructions. I don't think propgcc optimizes to a single read-modify-write instruction.

    Oh right, I was thinking along the wrong lines there. I think maybe it has to do with what slot the PINB register is accessed from (D or S). So you need PINB to be in the D slot to write out to the pins, but in the S slot to read the input state of the pins. (Or is it the reverse of that? :)

    Can you share the C code produced (since I don't have access to spin2cpp at the moment), and the GAS/PASM output from propgcc?

    Roy
  • David BetzDavid Betz Posts: 13,723
    edited 2013-01-16 - 15:23:13
    Roy Eltham wrote: »
    Oh right, I was thinking along the wrong lines there. I think maybe it has to do with what slot the PINB register is accessed from (D or S). So you need PINB to be in the D slot to write out to the pins, but in the S slot to read the input state of the pins. (Or is it the reverse of that? :)

    Can you share the C code produced (since I don't have access to spin2cpp at the moment), and the GAS/PASM output from propgcc?

    Roy

    Here is the generated code using -Os -mno-fcache.
            mov     r7, PINB
            xor     r7,__MASK_FFFFFFFF
            mov     PINB, r7
    

    I guess it's obvious what the problem is here. GCC doesn't generate a read-modify-write instruction with PINB in the destination field. I'm not sure if the optimizer could be improved to handle this case. Maybe Eric will know.
  • Cluso99Cluso99 Posts: 15,842
    edited 2013-01-16 - 17:43:48
    From what I recall, reading PINB will read what is actually on the pin, not what you have written to the pin. Normally they should be the same, but not always.
  • David BetzDavid Betz Posts: 13,723
    edited 2013-01-16 - 17:46:50
    Cluso99 wrote: »
    From what I recall, reading PINB will read what is actually on the pin, not what you have written to the pin. Normally they should be the same, but not always.
    Do you know under what conditions they would be different?
  • Roy ElthamRoy Eltham Posts: 2,790
    edited 2013-01-16 - 18:17:04
    You clipped out all the surrounding code. What about the GAS/PASM just before that where it initializes DIRB and PINB? if the initializing of PINB closer than 2 instruction apart from the first reading of it?
  • David BetzDavid Betz Posts: 13,723
    edited 2013-01-16 - 18:22:57
    Roy Eltham wrote: »
    You clipped out all the surrounding code. What about the GAS/PASM just before that where it initializes DIRB and PINB? if the initializing of PINB closer than 2 instruction apart from the first reading of it?
    Sorry, here is some more context.
            .global __ZN6blink24MainEv
    __ZN6blink24MainEv
            mvi     r7,#.LC0
            mvi     r6,#30000000
            rdlong  PINB, r7
            neg     DIRB, #1
    .L2
    ' 76 "/opt/parallax/lib/gcc/propeller-elf/4.6.1/../../../../propeller-elf/include/propeller2.h" 1
            getcnt r7
    ' 0 "" 2
            add     r7, r6
            waitcnt r7,#0
            mov     r7, PINB
            xor     r7,__MASK_FFFFFFFF
            mov     PINB, r7
            brs     #.L2
    
  • SapiehaSapieha Posts: 2,964
    edited 2013-01-16 - 19:08:48
    Hi Dvid.

    Chip:
    OFFP D/#n - clears both the DIR bit and PIN bit for the PIN (input with output bit low)
    GETP and GETNP do not affect the DIR bit. They only read the input, regardless of its DIR state. In other words,
    if a PIN is outputting a low, but is externally being forced high, you will read the high state.


    David Betz wrote: »
    Do you know under what conditions they would be different?
  • Roy ElthamRoy Eltham Posts: 2,790
    edited 2013-01-16 - 20:16:44
    David Betz wrote: »
    Sorry, here is some more context.
            .global __ZN6blink24MainEv
    __ZN6blink24MainEv
            mvi     r7,#.LC0
            mvi     r6,#30000000
            rdlong  PINB, r7
            neg     DIRB, #1
    .L2
    ' 76 "/opt/parallax/lib/gcc/propeller-elf/4.6.1/../../../../propeller-elf/include/propeller2.h" 1
            getcnt r7
    ' 0 "" 2
            add     r7, r6
            waitcnt r7,#0
            mov     r7, PINB
            xor     r7,__MASK_FFFFFFFF
            mov     PINB, r7
            brs     #.L2
    

    Thanks, I don't understand why that doesn't work? Can you share the GAS/PASM of the version that does work?
  • Cluso99Cluso99 Posts: 15,842
    edited 2013-01-16 - 21:25:50
    David: You have an external device forcing the pin in the opposite polarity of the output state. Different micros read this differently, so r-m-w instructions may or may not work as desired.

    Sapieha: This is exactly what I though I remembered Chip saying a while back - that it read the IO pin and not the internal output latch. (And IIRC this is different to the P1).
  • cgraceycgracey Posts: 12,641
    edited 2013-01-16 - 22:19:13
    David Betz wrote: »
    No, I haven't tried that. Will it help with the problem I'm having?

    Note that bits 5 and 6 of D/#n will determine which port gets selected. There was a time when my assembler would treat constants differently for PORT instructions, using bits 0 and 1, but I thought it would be troublesome, so I made it not shift the constant bits down, giving identical function for either a register or a constant (that is, bits 5 and 6 are used).

    It is true that only a read-modify-write (or a write) to a PINx register will affect the output latches. A read-without-write will read the pins' input states, not the output latches. This is an unintended consequence of getting rid of discrete IN and OUT registers - it is not an issue in assembly, but it is in high-level languages.
  • Roy ElthamRoy Eltham Posts: 2,790
    edited 2013-01-16 - 22:23:43
    Chip, does this mean that a read/modify/write instruction reads the output latches instead of the input state?
  • cgraceycgracey Posts: 12,641
    edited 2013-01-16 - 22:25:00
    Roy Eltham wrote: »
    Chip, does this mean that a read/modify/write instruction reads the output latches instead of the input state?

    That's right.
  • SapiehaSapieha Posts: 2,964
    edited 2013-01-17 - 03:50:57
    Hi Chip.

    Ariba write in one of threads that. BUT You never commented it. It is correct?

    (Ariba:) ? ? ?
    If you use one of the pin output instructions (SETP, CLRP, NOTP ...) the direction is automatically set to output,
    you don't need to set DIRx first.
    So: Yes there is another way beside setting DIRx.



    cgracey wrote: »
    That's right.
  • David BetzDavid Betz Posts: 13,723
    edited 2013-01-17 - 05:10:37
    cgracey wrote: »
    It is true that only a read-modify-write (or a write) to a PINx register will affect the output latches. A read-without-write will read the pins' input states, not the output latches. This is an unintended consequence of getting rid of discrete IN and OUT registers - it is not an issue in assembly, but it is in high-level languages.
    Any chance at this late date that you might consider separating PINx into INx and OUTx again? Or better, make PINx read the output latches if the corresponding DIRx bit is set.
  • AribaAriba Posts: 2,248
    edited 2013-01-17 - 07:33:53
    Sapieha wrote: »
    Hi Chip.

    Ariba write in one of threads that. BUT You never commented it. It is correct?

    (Ariba:) ? ? ?
    If you use one of the pin output instructions (SETP, CLRP, NOTP ...) the direction is automatically set to output,
    you don't need to set DIRx first.
    So: Yes there is another way beside setting DIRx.

    If you don't trust me then you can try it yourself with your DE0_NANO. That's how I found it out, it's not just phantasy.
    A possible testcode:
    DAT
      org 0
      mov  dira,#0
      setp #0                  'set pin 0 (and dira[0])
      wrlong dira, h2000       'read dira (to hubram)
      coginit monitor,monpins  'go to monitor
    
    monitor	long $70C
    monpins	long 90<<9 + 91
    h2000   long $2000
    
    ' then check the long at $2000 with the monitor:
    ' n2000<cr>
    
    Andy
  • cgraceycgracey Posts: 12,641
    edited 2013-01-17 - 07:41:42
    It's true that when you do a pin operation like SETP, The DIR bit is affected as well as the OUT bit.

    It's too late to change anything, at this point.

    A high-level language may have to do read-modify-writes intended for OUT on a separate register which always gets copied to the PIN register.
  • David BetzDavid Betz Posts: 13,723
    edited 2013-01-17 - 07:46:02
    cgracey wrote: »
    It's true that when you do a pin operation like SETP, The DIR bit is affected as well as the OUT bit.

    It's too late to change anything, at this point.

    A high-level language may have to do read-modify-writes intended for OUT on a separate register which always gets copied to the PIN register.
    Yeah, I figured it was probably too late. I mentioned the change just in case I was wrong. I guess I wasn't. :-)

    The separate register approach is what I used in the first message of this topic. It works just fine. I have LEDs blinking on my DE2-115 board running the Spin code in that post.
  • AribaAriba Posts: 2,248
    edited 2013-01-17 - 07:58:41
    David Betz wrote: »
    Any chance at this late date that you might consider separating PINx into INx and OUTx again? Or better, make PINx read the output latches if the corresponding DIRx bit is set.

    If the DIRx bit is set you should anyway read the output states at the inputs. Otherwise you have a serious hardware problem (driving two outputs with opposite states against each other).
    I only see a problem with "OpenDrain" outputs and PullUps which you preset to Low and then change only the DIRx bit. The Low of the output latch may be changed to High if you do a "Read PINx - Write PINX" sequence to modify another pin. But normally you will do OpenDrain pins with "CLRP pin" for Low and "OFFP pin" for High on the Prop 2.

    If this is really a big problem then instead of separate INx and OUTx registers an easier solution my be a special "read output latch" instruction: RDOUTA r1

    Andy
  • David BetzDavid Betz Posts: 13,723
    edited 2013-01-17 - 08:01:47
    Ariba wrote: »
    If the DIRx bit is set you should anyways read the output states at the inputs. Otherwise you have a serious hardware problem (driving two outputs with opposite states against each other).
    I only see a problem with "OpenDrain" outputs and PullUps which you preset to Low and then change only the DIRx bit. The Low of the output latch may be changed to High if you do a "Read PINx - Write PINX" sequence to modify another pin. But normally you will do OpenDrain pins with "CLRP pin" for Low and "OFFP pin" for High on the Prop 2.

    If this is really a big problem then instead of separate INx and OUTx registers an easier solution my be a special "read output latch" instruction: RDOUTA r1

    Andy
    You would think that reading the input pins would read the value last written but, if that is the case, why doesn't the code in the second post of this thread work on the DE2-115?
  • SapiehaSapieha Posts: 2,964
    edited 2013-01-17 - 08:11:34
    Hi Andy.

    It si not that I don't trust You.

    But for PDF I build i need INFO that are confirmed by Chip.


    Ariba wrote: »
    If you don't trust me then you can try it yourself with your DE0_NANO. That's how I found it out, it's not just phantasy.
    A possible testcode:
    DAT
      org 0
      mov  dira,#0
      setp #0                  'set pin 0 (and dira[0])
      wrlong dira, h2000       'read dira (to hubram)
      coginit monitor,monpins  'go to monitor
    
    monitor    long $70C
    monpins    long 90<<9 + 91
    h2000   long $2000
    
    ' then check the long at $2000 with the monitor:
    ' n2000<cr>
    
    Andy

    Ps.
    Yours code now applied as example.
  • AribaAriba Posts: 2,248
    edited 2013-01-17 - 08:11:51
    @David

    I don't know. It should work.
    And it works when I run a similar code with the PNUT "IDE".

    Andy
  • SapiehaSapieha Posts: 2,964
    edited 2013-01-17 - 08:12:54
    Hi Chip.

    Thanks.

    Now I can apply that to PDF as confirmed.

    cgracey wrote: »
    It's true that when you do a pin operation like SETP, The DIR bit is affected as well as the OUT bit.

    It's too late to change anything, at this point.

    A high-level language may have to do read-modify-writes intended for OUT on a separate register which always gets copied to the PIN register.
Sign In or Register to comment.