Shop OBEX P1 Docs P2 Docs Learn Events
Reading value of CTRA in cog 0 by another cog — Parallax Forums

Reading value of CTRA in cog 0 by another cog

MJHanaganMJHanagan Posts: 189
edited 2015-06-21 20:23 in Propeller 1
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?

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2015-06-19 05:40
    You can't do this directly. cnt is the same for all cogs (i.e. it's shared implicitly) but the counters are local to each cog. In order to share them you have to go via a hub location. Also, you want to read phsa instead.
  • evanhevanh Posts: 15,919
    edited 2015-06-19 06:31
    To be a bit more verbose than Kuroneko, CNT is a singular hardware counter that never stops. It is globally routed in hardware to all 8 Cogs and appears simultaneously identical to all running programs (tasks).

    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.
  • MJHanaganMJHanagan Posts: 189
    edited 2015-06-19 07:04
    evanh wrote: »
    To be a bit more verbose than Kuroneko, CNT is a singular hardware counter that never stops. It is globally routed in hardware to all 8 Cogs and appears simultaneously identical to all running programs (tasks).

    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!
  • evanhevanh Posts: 15,919
    edited 2015-06-19 07:35
    MJHanagan wrote: »
    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?
    Yes ... but all these SPR's are not HubRAM addresses, they are CogRAM addresses. The ones you've listed are duplicated into each Cog. The pin I/O registers, for example, may seem as a singular group but there are factors that show up their Cog separation.

    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 Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2015-06-19 07:48
    MJHanagan wrote:
    Oh, so its just the values of CNT, DIRA, DIRB, INA and INB
    Each cog has its own values of DIRA and DIRB, and they can be (and usually are) different for each cog.

    -Phil
  • kwinnkwinn Posts: 8,697
    edited 2015-06-19 07:49
    Wouldn't it be simpler to have to have the main cog set up a global variable in hub ram, set it up with the number of seconds since midnight, and update it or have one of the other cogs update it once per second?

    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.
  • evanhevanh Posts: 15,919
    edited 2015-06-19 07:51
    PS: Spin doesn't use CogRAM for variables so probably the only time you'll bump into Cog addresses is when you access the SPRs.

    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
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2015-06-19 07:55
    To be a lot more verbose, but hopefully more precise..

    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.
  • Mark_TMark_T Posts: 1,981
    edited 2015-06-21 16:29
    The only access you get to another cog's RAM is by doing cognew/coginit - this is the only way to affect another cogs state
    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.
  • frank freedmanfrank freedman Posts: 1,983
    edited 2015-06-21 18:37
    MJHanagan wrote: »
    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!

    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 Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2015-06-21 20:23
    I may be a bit off on this but I DIRA/B and INA/B are unique to each cog.
    Partly, true, the DIRA, DIRB and INB parts. Although INA is theoretically unique to each cog, the values returned to all the cogs from the register in an instruction's source field will be the same. The only uniqueness applies if you use their associated shadow registers in the destination field of an instruction. As to DIRB and INB, those are just unallocated I/O registers -- thus general-purpose -- and unique to each cog.

    -Phil
Sign In or Register to comment.