Shop OBEX P1 Docs P2 Docs Learn Events
Writing globals from cog — Parallax Forums

Writing globals from cog

JBWolfJBWolf Posts: 405
edited 2011-10-11 17:30 in Propeller 1
Im a little hazy as to how I should write to a global long from inside a cog method.
The variable is declared as Long in the VAR section and initialized before use.
I am starting a method in a new cog and passing the address with @.
i.e - cognew(Method(@variable), @stack[40])

inside the new method, I am writing the global variable to a local one as the global may change while the method code runs.
i.e. - PUB Method(VariableAddress) | VariableTemp
VariableTemp := long[VariableAddress]

But how should I write a value to the global variable from within this cog?
Variable := 123 ?
long[VariableAddress] := 123 ?

Do I have to pass the address to use it in the new cog?
Can I just assume since it is global, it already knows where it is and just directly write to it?
i.e -
PUB Method | VariableTemp
VariableTemp := Variable
Variable := 123

Comments

  • Cluso99Cluso99 Posts: 18,069
    edited 2011-10-09 05:56
    Since you are still in spin, it knows all the hub addresses of variables, so yes you just set the variable var := 123

    Pasm is different.
  • JBWolfJBWolf Posts: 405
    edited 2011-10-09 21:37
    Do PUB and PRI methods both work the same way?
    So I can write to a global variable from within a PRI without having to pass the variable address when the method is initially launched in a new cog?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2011-10-10 07:52
    The only time you have to pass an address for a global variable is when the other code using the variable is in a different object.

    If you keep you code in one object, all the methods (and cogs using Spin) can access the same global variables.

    Duane
  • Martin_HMartin_H Posts: 4,051
    edited 2011-10-10 08:20
    I don't know enough PASM to know the answer and this is related to the thread.

    Are writes to hub longs atomic? What about writes to hub bytes and words? Does the prop have alignment issues for longs and words that are not naturally aligned on their natural boundary? The reason I'm asking is that some processor architectures have byte tearing issues on scalar values and require locks even for simple concurrent programming usage.

    Imagine one cog reading a PING))) sensor and another COG acting on that output. With byte tearing the most significant word might get written, a read occur, then the least significant word written. So the distance reading wouldn't be stable.

    Back when I has a heavy assembly programmer RISC systems were only atomic for writes on a natural boundary and byte tearing was the bane of our existence. Even the single writer with multiple readers use case of a long value could cause problems.

    I'll admit to ignoring this issue with my Spin programs to date, but feeling some shame that I didn't know the answer one way or the other.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2011-10-10 08:39
    Martin,

    The cogs can read and write a long at a time. Since each cog takes turn reading and writing to the hub, you wont have any problems with two cogs accessing the same long (or bytes with in the long) at the same time.

    You can run into trouble if bytes and words aren't long aligned (assuming your reading them a long at a time).

    One way to long align bytes is to use the org statement. The first byte after the org will be long aligned.

    You really have to be careful passing a byte address using par. par loses the two LSBs and is only useful for long aligned addresses.

    If you're reading and writing chunks of data larger than a long, then you'll probably need locks or some other flag system to know when the data is complete.

    Duane
  • Martin_HMartin_H Posts: 4,051
    edited 2011-10-10 16:55
    Thanks Duane, that is basically the assumption I was operating on. Currently I have always been using four byte multiples andwill have to remember the Org statement.
  • kuronekokuroneko Posts: 3,623
    edited 2011-10-10 17:05
    Duane Degn wrote: »
    You can run into trouble if bytes and words aren't long aligned (assuming your reading them a long at a time).
    Wouldn't it then be better to read them as bytes or words?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2011-10-10 19:20
    kuroneko wrote: »
    Wouldn't it then be better to read them as bytes or words?

    Yes, your right. You are usually better off reading them as bytes or words. The code required to separate bytes out of a long would likely take more time than just reading the four bytes in individually. I think there are a couple of situations when reading four bytes are a time would be advantageous. I've thought I might do this when using eight SRAM chips in parallel. I could speed the read and writes by using longs instead of bytes. I'd still need to shift the bytes around but I think this could be faster than treating the bytes individually. With the 8-bit SRAM, I have to read or write eight bytes at a time anyway so, in this case, grouping bytes together in longs is probably a good idea.

    I think the main problem you can have using bytes with PASM is passing a byte address with par.

    I've used the org statement when I wanted to use a buffer that started before a section of PASM code. The buffer extended into the PASM section and I wanted to make sure there wasn't a gap in the buffer.

    The buffer wasn't used until after the cog was launched (and the cog could not be relaunched later(since the code had been overwritten by the buffer)).

    I know these are exceptions to the usual way of using bytes with PASM but they were what I was thinking about when I wrote what I did above.

    Duane
  • Martin_HMartin_H Posts: 4,051
    edited 2011-10-10 19:34
    kuroneko wrote: »
    Wouldn't it then be better to read them as bytes or words?

    If you read a long that's not naturally aligned (address of 0, 4, 8, ...) the results are highly architecture dependent.

    Most modern RISC processors generate an unaligned address fault and code in the fault handler does two separate reads, bit shifts and AND's them to get the final result. So the fault handler is much like your idea of reading using smaller units. But the fault handler is multiple instructions which is not atomic and can result in byte tearing. Some older RISC processors outright failed and the program halted on an unaligned address fault.

    CISC processors usually handle this in their microcode, so it appears atomic from the point of view of the higher level instructions set, but something similar to the fault handler went on in the micro-architecture. One of the CPU designers I knew at DEC told me that this single feature and the fallout it generated was why CISC processors lagged behind RISC processors.

    The propeller doesn't have interrupts and I thought the unaligned address fault handler for RISC processors was interrupt based. So I really need to learn PASM to fully understand how the propeller handles this case.
  • JBWolfJBWolf Posts: 405
    edited 2011-10-10 23:26
    Ah thank you for clearing that up, I was wondering why I would pass an address from within the same object... using it only on outside objects makes alot more sense :)

    I have another Q
    Will this work?
    Good := 1
    Limit := 19
    repeat until X == Good or Limit 
    
    Would it repeat until the X variable == 1 or repeats 19 times, whichever comes first?
    Or would it use the Limit at the end as an 'if true' statement
  • kuronekokuroneko Posts: 3,623
    edited 2011-10-10 23:48
    The way it is now Limit is evaluated as TRUE. Try this:
    repeat until X == Good or not Limit--
    
    which will repeat Limit times or exit when X == Good whichever comes first.
  • JBWolfJBWolf Posts: 405
    edited 2011-10-11 15:20
    Ah I get it.... but wont that decrement the value stored in 'limit'?
    I will have to make an extra counter variable for comparing as I cannot change that value in the loop or it will mess things up.
    Thank you alot though!
  • kuronekokuroneko Posts: 3,623
    edited 2011-10-11 16:03
    JBWolf wrote: »
    Ah I get it.... but wont that decrement the value stored in 'limit'?
    Yes. Since you introduced the until it becomes a boolean expression so that' s the way it is.
  • kuronekokuroneko Posts: 3,623
    edited 2011-10-11 16:26
    You could also use something like this:
    repeat Limit
      if X == Good
        quit
    
    Maybe a bit slower in terms of general execution time but works just as well.
  • JBWolfJBWolf Posts: 405
    edited 2011-10-11 17:30
    ah, Quit was not in the PE textbook! very useful
    Does this only exit the immediate repeat loop?
    Say I have 3 nested repeats and use this in the 3rd, would it exit from the 3rd repeat loop back to the 2nd?

    Another Q
    If I have an array of arrays.... say variable names are sequential and each has 400 values. so:
    var1
    var2
    var3

    could I write a loop somehow to access all of these variable names?
    something like
    X := X + 1
    var(X)[X] := 292
    This should make Var1[1] == 292
Sign In or Register to comment.