Shop Learn
Problem writing bytes not along long boundaries — Parallax Forums

Problem writing bytes not along long boundaries

Here is a min repo of the problem

PUB start | ptr

  DIRA[0] := 1
  OUTA[0] := 1

  ptr := @Shared                             
  byte[ptr] := 1
  cognew(@SetPASM, ptr)
  repeat while (byte[ptr] == 1)

  OUTA[0] := 0

        org    0
        mov    Value,  #2
        wrbyte Value,  PAR

Loop    jmp    #Loop

Value  res   1

  not_used       byte 0
  Shared         byte 0

This app does the following
1. Turns on the debug LED
2. Obtains the address of a byte from within the DAT section
3. Set the byte at that location to 1
4. Start a new Cog that will run some PASM
5. Loop while the byte at that location is 1
6. Turn off the LED
7. End

The problem appears to be in the PASM, it does the following
1. Fills a temp registry with value 2
2. Writes that value to the byte at the location passed via PAR
3. Enters an endless loop jumping back to the Loop label

I would expect that when you run this the LED would flash for just a moment and then go out.
However that is not what I'm observing. The LED turns on, and then stays on.
This indicates that the while condition on the repeat loop stays fulfilled and ultimately that Shared still holds the value 1

The strange thing is that seemingly "unrelated" changes will effect the outcome.

Here are a few that will "fix" the problem
1. Move the byte writes to always occur on long boundaries by doing any of the following

  • Remove the line not_used byte 0
  • Add 3 more bytes after not_used and before Shared like this
not_used       byte 0, 0, 0, 0
Shared         byte 0
  • Change all the references from 'byte' to 'long' (note: swapping to 'word' will reproduce the problem)

2. Do the work in Spin by

  • Adding
  long  Stack[128]
PRI SetSpin(ptr)
  byte[ptr] := 2
  • Change cognew(@SetPASM, ptr) to cognew(SetSpin(ptr), @Stack)

I have done some additional debugging and found that when this misbehaves it does look like a write is occurring, I have seen cases where it appears to corrupt other data in the DAT section. I also did a little double checking by changing all of my references from byte[ptr] to Shared and that seams to indicate that those are equivalent

But I'm clearly missing something :D if you know what it is I'll all ears. Thanks in advance.


  • AribaAriba Posts: 2,481
    edited 2021-05-25 01:44

    @mpholmes said:

    But I'm clearly missing something :D if you know what it is I'll all ears. Thanks in advance.

    Yes, you missed to read the Propeller manual, before you have done a lot of debugging. ;) For example on page 82 it says:

    The ParameterField
    It’s important to note that the Parameterfield is intended to pass a long address, so only
    14 bits (bits 2 through 15) are passed into the cog’s PARregister; the lower two bits are always
    cleared to zero to ensure it’s a long-aligned address. A value other than a long address can
    still be passed via the Parameterfield, but will have to be limited to 14 bits, must be shifted
    left by two bits (for the COGNEW/COGINITcommand), and will have to be shifted right by two
    bits by the assembly program that receives it.


  • You're not the first to miss this important aspect of the par register.

    I had similar issues when I was first learning PASM. I've seen this issue mentioned many many times on the forum.

  • Try out this simple one

  • JonnyMacJonnyMac Posts: 7,622
    edited 2021-05-25 03:24

    As Andy and Duane have pointed out, the par register (that many call the mailbox") must contain a long address (because the two low bits are cleared). Here's a work-around that works in your situation. I happened to have a board with and LED on P8, so I added a constant for that (which is a good idea, anyway).

      LED = 8
      shared        byte      0
      long  mailbox
    pub start
      dira[LED] := 1                                                ' LED on
      outa[LED] := 1
      waitcnt(cnt + clkfreq)                                        ' wait one second
      shared := 1                                                   ' set marker value
      mailbox := @shared                                            ' put address of shared into mailbox
      cognew(@entry, @mailbox)                                      ' start other cog
      repeat while (shared == 1)                                    ' hold while marker value present
      outa[LED] := 0                                                ' LED off
                    org       0
    entry           rdlong    p_shared, par                         ' get the address of shared
                    mov       value, #2
                    wrbyte    value, p_shared
                    jmp       #$
    p_shared        res       1
    value           res       1
                    fit       496
  • Thank you very much for the quick response!

Sign In or Register to comment.