Shop OBEX P1 Docs P2 Docs Learn Events
Problems with timer. CNT — Parallax Forums

Problems with timer. CNT

DarkGFXDarkGFX Posts: 17
edited 2013-11-20 01:36 in Learn with BlocklyProp
Hello everyone I'm new to Propeller chip and SimpleIDE and have some questions about a part of my program.

I have two COG's that is supposed to save the time from CLK register when they their input is "HIGH".
I tough it was working pretty good, but when I connected the input for both of them together and triggered them at the same time, I got a different CLK time on both of them.

Code for one of the cogs, both are equal:
// Function that can continue on its
// own if launched into another cog.
void microphone1(void *par)                         // microphone1 keeps going on its own
{
    unsigned temp_tid1;                             // local variable for reading CLK
  while(1)                                          // Endless loop
  {
    if(input(1) == 1){                              // Check if Input 1 is triggerd 
        temp_tid1 = CNT;                            // save CNT to internal ram!
        L1 = temp_tid1;                             // L1 sends ram value to global ram
        trigg1 = 1  ;                               // send triggerd value to main 
        us_delay(50);                               // Wait 50us <- hommade delay function 
        trigg1 = 0;                                 // reset trigger
    }                               
  }                         
}


So my question is, why are these two cogs reading different CLK times when they have the same function?

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2013-11-13 04:38
    See http://forums.parallax.com/showthread.php/151277-Multi-cog-and-timing-rising-edge. While it deals with SPIN/PASM the issue is basically the same (no sync).
  • DarkGFXDarkGFX Posts: 17
    edited 2013-11-13 09:02
    I have already read that post actually, but there is no final solution.
    because the user TxRX and I are working on the same project, he is trying to write it in SPIN while I try to write it in C.

    So we are both trying to find a good solution for the "no sync" problem and hope someone could come up with a good answer.

    While some of the solutions in the other thread is good, I will have a problem implementing these for 6 cogs that will be the final project.

    So my question: is there a good way to synchronize the clock for all the cogs?
  • jazzedjazzed Posts: 11,803
    edited 2013-11-13 11:12
    @DarkGFX

    Your approach needs some refinement. Mainly, you should consider using the waitpne() macro instead of input().

    I show a program that does this below.

    @kuroneko, Could you go into more detail about why the counts read immediately after waitpne() by different COGs would be different by 2? I know that if we simply log the value received by INA after syncing on CNT that the count difference can be as low as 1.
    /*
     * Get counters after an input transition on multiple cogs.
     * This program uses the simpletools library for setting pins with high/toggle.
     *
     * OUTPUT:
     *
      COG 1 CNT 0
      COG 2 CNT 0
      COG 3 CNT 0
      COG 4 CNT 0
      COG 5 CNT 0
      COG 6 CNT 0
      COG 1 CNT 344bd83d
      COG 2 CNT 344bd82f
      COG 3 CNT 344bd831
      COG 4 CNT 344bd833
      COG 5 CNT 344bd835
      COG 6 CNT 344bd837
      COG 1 CNT 0
      COG 2 CNT 0
      COG 3 CNT 0
      COG 4 CNT 0
      COG 5 CNT 0
      COG 6 CNT 0
      COG 1 CNT 3938741d
      COG 2 CNT 3938740f
      COG 3 CNT 39387411
      COG 4 CNT 39387413
      COG 5 CNT 39387415
      COG 6 CNT 39387417
     */
    #include "simpletools.h"
    
    /* set pin to monitor */
    #define PIN (25)
    
    #define NUMCOG 6
    #define STACKBYTES 180
    
    typedef struct mailbox_st
    {
      int pinmask;
      int counter;
      int cog;
    } mbox_t;
    
    mbox_t boxes[NUMCOG];
    int stack[NUMCOG][STACKBYTES/5];
    
    void monitor(void *arg)
    {
      int pinmask;
      mbox_t *mbox = (mbox_t*) arg;
    
      mbox->cog = cogid();
      pinmask = mbox->pinmask;
    
      /* wait for initial count to sync-up cogs */
      waitcnt(mbox->counter);
    
      for(;;) {
        /* wait for pin to go low */
        waitpne(pinmask, pinmask);
        mbox->counter = 0;
        /* wait for pin to go high */
        waitpeq(pinmask, pinmask);
        mbox->counter = CNT;
      }
    }
    
    /**
     * This is the main WaitInput program file.
     */
    int main(void)
    {
      int n;
      int startcount;
    
      /* set a start count for syncing monitors */
      startcount = CNT + CLKFREQ/10;
    
      for(n = 0; n < NUMCOG; n++) {
        boxes[n].counter = startcount; 
        boxes[n].pinmask = 1 << PIN; // monitor pin
        cogstart(monitor, &boxes[n], &stack[n], STACKBYTES);
      }
    
      /* pause to let all cogs startup */
      pause(100);
    
      /* set pin to output high to start */
      high(PIN);
    
      while(1) {
        toggle(PIN);
        for(n = 0; n < NUMCOG; n++) {
          putStr("\nCOG ");
          putDec(boxes[n].cog);
          putStr(" CNT ");
          putHex(boxes[n].counter);    
        }
        pause(500);
      }
      return 0;
    }
    
    
  • ersmithersmith Posts: 6,052
    edited 2013-11-13 14:25
    If the C code is running in LMM mode (or any related mode; CMM, XMM, etc. -- anything but pure COG C) then the clocks could be different because the COGs are reading instructions from HUB memory, which will cause a phase shift (the COGs will have to take turns fetching instructions). This may or may not be mitigated by the code being placed in FCACHE, depending on the optimization levels and size of the code.

    Eric
  • jazzedjazzed Posts: 11,803
    edited 2013-11-13 14:38
    I think the CNT+2 readings are because of the HUBness of waitpne() ... that is if I interpret kruroneko's explanation of the transactions correctly. I'm guessing the result would be similar though delayed by some amount regardless of the memory mode (no more time for experimenting today though).
  • kuronekokuroneko Posts: 3,623
    edited 2013-11-13 15:16
    jazzed wrote: »
    @kuroneko, Could you go into more detail about why the counts read immediately after waitpne() by different COGs would be different by 2? I know that if we simply log the value received by INA after syncing on CNT that the count difference can be as low as 1.
    This delta only applies when reading cnt is aliased to the hub, i.e. even if both waitpxx exit at the exact same time you'll get a cogid based difference due to an intervening hubop. If a waitpxx/read cnt sequence is run from FCACHE (without hubop in between) then you're fine.
  • jazzedjazzed Posts: 11,803
    edited 2013-11-13 15:39
    kuroneko wrote: »
    This delta only applies when reading cnt is aliased to the hub, i.e. even if both waitpxx exit at the exact same time you'll get a cogid based difference due to an intervening hubop. If a waitpxx/read cnt sequence is run from FCACHE (without hubop in between) then you're fine.

    Ya, it works.

    Eric, I'm sorry I forgot that CMM/LMM read instructions from HUB (which you did point out ... more coffee!).

    Simply adding "__attribute__ ((fcache)) " solves it.

    Thanks for making it clear.

    __attribute__ ((fcache)) void monitor(void *arg)
    {
      int pinmask;
      mbox_t *mbox = (mbox_t*) arg;
    
    
      mbox->cog = cogid();
      pinmask = mbox->pinmask;
    
    
      /* wait for initial count to sync-up cogs */
      waitcnt(mbox->counter);
    
    
      for(;;) {
        /* wait for pin to go low */
        waitpne(pinmask, pinmask);
        mbox->counter = 0;
        /* wait for pin to go high */
        waitpeq(pinmask, pinmask);
        mbox->counter = CNT;
      }
    }
    


    COG 1 CNT 0
    COG 2 CNT 0
    COG 3 CNT 0
    COG 4 CNT 0
    COG 5 CNT 0
    COG 6 CNT 0
    COG 1 CNT b939c109
    COG 2 CNT b939c109
    COG 3 CNT b939c109
    COG 4 CNT b939c109
    COG 5 CNT b939c109
    COG 6 CNT b939c109
    COG 1 CNT 0
    COG 2 CNT 0
    COG 3 CNT 0
    COG 4 CNT 0
    COG 5 CNT 0
    COG 6 CNT 0
    COG 1 CNT be266769
    COG 2 CNT be266769
    COG 3 CNT be266769
    COG 4 CNT be266769
    COG 5 CNT be266769
    COG 6 CNT be266769
  • DarkGFXDarkGFX Posts: 17
    edited 2013-11-19 05:47
    Thank you everyone!
    This a lot of good information, and I have now fixed my sync problem!

    thanks to you're code jazzed, I can now see clearly that I need to learn more about how to initialize the COG's.
    Could care to explain you're method to me?
  • jazzedjazzed Posts: 11,803
    edited 2013-11-19 09:05
    DarkGFX wrote: »
    Could care to explain you're method to me?

    There are different ways to start a COG.

    1. Use cognew to start PASM, GAS, or COGC running in a COG.
    https://sites.google.com/site/propellergcc/documentation/libraries/propeller-h-library#TOC-cognew

    2. Use cogstart to start a C function which runs in the CMM/LMM interpreter.
    https://sites.google.com/site/propellergcc/documentation/libraries/propeller-h-library#TOC-cogstart

    I used the cogstart method since it can all be in one file. The stack is a two dimensional array where the stacks are kept for each COG. The mailbox structure is used for communications with the COGs. I set a target clock CNT for each COG to find before doing cogstart.

    The critical piece that makes the display show the exact counts is to make sure that each pin monitor sits entirely in the COGs' cache overlay area.
  • DarkGFXDarkGFX Posts: 17
    edited 2013-11-19 12:47
    Thank you again, you are really helping me!
    One more thing, I just swapped out my if() function for the waitpne, but I do not quite understand how to set it up.

    If I want it to wait for HIGH on pin 1, how do I write this?
  • jazzedjazzed Posts: 11,803
    edited 2013-11-19 15:54
    DarkGFX wrote: »
    If I want it to wait for HIGH on pin 1, how do I write this?
    The code I presented before uses waitpeq to wait for a high. Here is the simplified version.
    int mask = 1 << 1; // this sets P1 (bit 1) high as in 0x00000002
    waitpeq(mask, mask); // wait for P1 to be high ignoring all other inputs
    
    
  • DarkGFXDarkGFX Posts: 17
    edited 2013-11-20 01:36
    Alright so that's the way to do it =D!
    I'm going to try this as soon as I come hope, really exited!

    Thank you so much, I really appreciate all the help you are giving me!
Sign In or Register to comment.