Writing globals from cog
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
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
Pasm is different.
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?
If you keep you code in one object, all the methods (and cogs using Spin) can access the same global variables.
Duane
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.
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
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
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.
I have another Q
Will this work? 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
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!
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