Reading value of CTRA in cog 0 by another cog
MJHanagan
Posts: 189
I need to coordinate some activities in a few cogs to the exact same 1 Hz time signal without consuming a separate cog to update a common shared RAM variable. I was thinking of setting up CTRA in the main cog (cog 0) to count the 1 Hz signal from an RTC. Upon bootup I would querty the RTC for the actual time then convert this value to the numer of seconds since midnight and set the initial value of CTRA accordingly. Each 1 Hz pulse from the RTC would then increment CTRA by 1 thus the value in CTRA would reflect the current time. Once the CTRA is setup and initialize there is no further attention needed from the code to maintaining the elapsed time counter (i.e. no programming overhead). Reading the value of this register in the main cog can be done in at least two straight forwards ways:
Etime := CTRA
Etime := SPR[8]
A third way would be possible if you know the RAM address of the CTRA register:
Etime := LONG[ addrCTRA ]
If the address of CTRA in cog 0 is known then presumably any running cog could read the value in SPIN using the same LONG[ addr ] method or in ASM using RDLONG variable, addr.
I tried addrCTRA := @CTRA to get the address of CTRA but this would not compile, nor would addrCTRA := @SPR[8].
I then saw in Table 1-3 in the Propeller manual that CTRA has a local RAM address of $1F8, but when I tried Etime := LONG[ $1F8 ] I didn't get the correct value (even within cog 0). CNT is a common value to all cogs so I am inclined to think there should be a way to access other fixed or special registers such as CTRA.
So my question is this: how can I get the RAM address of CTRA in cog 0 so I can reference its value in another cog running SPIN code?
Etime := CTRA
Etime := SPR[8]
A third way would be possible if you know the RAM address of the CTRA register:
Etime := LONG[ addrCTRA ]
If the address of CTRA in cog 0 is known then presumably any running cog could read the value in SPIN using the same LONG[ addr ] method or in ASM using RDLONG variable, addr.
I tried addrCTRA := @CTRA to get the address of CTRA but this would not compile, nor would addrCTRA := @SPR[8].
I then saw in Table 1-3 in the Propeller manual that CTRA has a local RAM address of $1F8, but when I tried Etime := LONG[ $1F8 ] I didn't get the correct value (even within cog 0). CNT is a common value to all cogs so I am inclined to think there should be a way to access other fixed or special registers such as CTRA.
So my question is this: how can I get the RAM address of CTRA in cog 0 so I can reference its value in another cog running SPIN code?
Comments
On the other hand, each Cog also has dedicated hardware that is to be used by the task that is running in that Cog. So, the two configurable counters, PHSA and PHSB exist independently for each independent Cog and therefore also for the task that runs in those Cogs. So there is a total of 16 configurable counters in a Propeller processor, 2 per Cog.
Oh, so its just the values of CNT, DIRA, DIRB, INA and INB which are updated automatically in the RAM hub - none of the other special registers such as PHSA from each cog?
I guess I could query the RTC for the time and pass this value to each cog that needs to know the time when it starts. I would then need to set up the local CTRA and initialize PSHA to that time value and run its own counter using the same 1 Hz pin. Starting a new cog takes less than a second to the accuracy of the passed value would be off by no more than 1 second. The only problem then comes at midnight when the value reaches 86400 and thus needs to be reset to 0. A bit of extra code in each cog would be needed to look for and do the reset. I guess that is better than using up a cog just to keep time.
Thanks for the help!
Think of CogRAM as a large set, with 16 specials, of general registers, one set for each Cog. Think of HubRAM as main memory. Each task can address all of HubRAM but only one Cog.
If you put your RTC values in HubRAM then only one copy is needed and can be easily shared between all tasks.
-Phil
Updating the time shouldn't require a dedicated cog. The 1pps pin can be checked and the time updated with a few PASM or Spin instructions as part of a loop that executes a few times per second. The cogs that need to be synchronized to the timer would be passed the address of that variable when they start up.
An alternative would be to load the time (seconds since midnight) into the cog counter, have the 1pps increment the counter, and write the value in the counter to the hub variable.
With that in mind, something like Etime := CTRA will copy the value from the task's Cog SPR for CTRA into the variable ETime. The variable ETime is always in HubRAM.
PPS: Keep an eye out for Parallax's new tutorial - http://forums.parallax.com/showthread.php/161030-What%E2%80%99s-a-Multicore-Microcontroller-Tutorial
There is no way to directly read some other cog's registers/memory unless that cog writes it register values to some globally accessible hub location. Trying to read from $01F8 will indeed read from $01F8, in hub ram that is, but not from the cog's internal 512 word 9-bit address memory.
Each cog has two counters, CTRA and CTRB. So there are eight CTRAs and eight CTRBs, and all the CTRAs are at each cog's internal 9-bit address of $01F8. Just imagine eight separate CPU chips, you can't access the other CPU's internal memory from another CPU, but in the case of the Propeller they are however all ported together with a hub memory and accessed via special instructions such as RDLONG etc.
If you try to read CTRA in Spin it will only read it from the cog that is running that Spin code.
Now even if it were possible to read the internal memory of another cog directly, you would still have to specify which cog, you can't just say gimme $01F8. So I just wonder how you were specifying a particular cog then?
CNT is in hub and global but this has nothing to do with each cog's CTRA and CTRB. There is no "automatic update" in hub RAM, the only update possible is by means of software and each cog can only access its own counters, period.
without it cooperating.
All other communication is by the cog executing hub instructions explicitly.
There is no way to probe another cog's state, since there is no datapath between a cog and any other cog - the hub is
the only connection.
Actually there is one exception to this - the video hardware has a field AURALSUB in the VCFG register that selects
the PLL from CTRA of a nominated cog - so there is a global bus of these PLL signals too.
I may be a bit off on this but I DIRA/B and INA/B are unique to each cog. Where I and certainly others starting with this chip get into trouble is not watching out for assignments of the I/O pins using these registers. The logic is a bit different; for TTL logic, lows suck. That is if a number of outputs were to share a pin and say two of the three were high out and one low, the low one would win and the signal would appear as a low. With the cumulative or'ing of the prop outputs, highs (ones) win. so if you wanted to gate a clock/counter output to a particular I/O pin, you could have a cog look for a particular condition to set a pin low to "turn on" the clock or go high to disable the counter output on that pin, leaving the pin at a constant high output. High signals win. Took some getting used to. I used this to my advantage in using a cog to control the counter output for use as the clock signal with an MCP3201 ADC.
As to shared cog data, search for and root through the thread PASM for beginners, as there are some very good examples of this provided by Kuroneko, Heater, and others.
-Phil