Shop OBEX P1 Docs P2 Docs Learn Events
confused about sharing data between cogs when using XMMC and cog memory models — Parallax Forums

confused about sharing data between cogs when using XMMC and cog memory models

sssidneysssidney Posts: 64
edited 2012-08-26 18:57 in Propeller 1
I'm confused about sharing data between cogs when using XMMC and cog memory models. In this example
I've declared 3 globals in the main routine compiled in XMMC mode and tried to write to them in a cog mode routine.
The writes never seem to happen when the main is compiled in XMMC mode. When I compile with the main routine in LMM mode it works fine.
I've compiled the code with the optimizer turned off. I'm obviously missing something pretty basic.

Here is the main routine/file:
#include <stdio.h>
#include <propeller.h>


#define STACK_SIZE 32
struct {
    unsigned stack[STACK_SIZE];
    int m;
} parms;

extern _Driver _SimpleSerialDriver;
_Driver *_driverlist[] = {
  &_SimpleSerialDriver,
  NULL
};

int sharedInt3 = 0;
volatile int sharedInt2 = 0;
HUBDATA volatile int sharedInt1 = 0;

int startWav(void *parptr)
{
    extern unsigned int _load_start_tst1cogc_cog[];
    return cognew(_load_start_tst1cogc_cog, parptr);
}

int audioCogId = -1;
int main (int argc,  char* argv[])
{
    waitcnt(CNT + CLKFREQ);

    printf("starting main in cog %d\n", cogid());
    printf("before - sharedInt1 %d sharedInt2 %d sharedInt3 %d \n", 
           sharedInt1, sharedInt2, sharedInt3);

    audioCogId = startWav(&parms.m);
    printf("cogstart %d\n", audioCogId);

    waitcnt(CNT + (CLKFREQ*2));

    printf("after - sharedInt1 %d sharedInt2 %d sharedInt3 %d \n", 
           sharedInt1, sharedInt2, sharedInt3);

    return 0;
}

Here is the cogc code:
#include <propeller.h>

extern int sharedInt3;
extern volatile int sharedInt2;
HUBDATA extern volatile int sharedInt1;

_NATIVE
void main (volatile int *m)
{
    sharedInt1 = 123;
    sharedInt2 = 456;
    sharedInt3 = 789;
}


Output from XMMC mode:
starting main in cog 3
before - sharedInt1 0 sharedInt2 0 sharedInt3 0
cogstart 0
after - sharedInt1 0 sharedInt2 0 sharedInt3 0

Output from LMM mode:
starting main in cog 0
before - sharedInt1 0 sharedInt2 0 sharedInt3 0
cogstart 1
after - sharedInt1 123 sharedInt2 456 sharedInt3 789


Any help is greatly appreciated.

Thanks!!!

Comments

  • ersmithersmith Posts: 6,095
    edited 2012-08-26 08:46
    cognew doesn't work properly in XMM and XMMC modes -- it's arguable whether that's a bug or a feature. To start a new cog in XMM or XMMC you have to use
      load_cog_driver_xmm(_load_start_tst1cogc_cog, 496, parptr);
    
    The extra "496" parameter is the number of longs to load; you can optimize the load time by making this the correct value (e.g. by calculating the size based on _load_stop_tst1cogc_cog) but 496 should always work since that's the maximum size of a COG program.

    See the toggle/cog_c_toggle demo for an example.
  • jazzedjazzed Posts: 11,803
    edited 2012-08-26 12:06
    The example given doesn't work because it doesn't have a pointer to the data in a mailbox. The cog has no way to know how to reference global variables as shown.

    COGs should always share data via mailbox pointers.

    Spin has a problem with global variables like in the example. Spin methods can access any data in VAR or DAT directly, but cog code has to get the variable addresses or add an offset for things to work when accessing global data. LMM works both ways because it is in the global map.

    Propeller-GCC cognew does work properly with xmm modes when the mailbox rule is followed. I use it all the time with xmmc. If you want to use xmm-single or xmm-split, you have to copy the cog memory from the xmm space to HUB space before doing cognew. XMMC or LMM doesn't require copying because all data lives in HUB RAM. The failure here is lack of documentation.
  • sssidneysssidney Posts: 64
    edited 2012-08-26 16:23
    I was trying to determine if I could access global variables in XMMC mode. So if I pass the addresses of these variables in the struct passed to the cog routine then it would work in XMMC mode?
  • jazzedjazzed Posts: 11,803
    edited 2012-08-26 17:17
    sssidney wrote: »
    I was trying to determine if I could access global variables in XMMC mode. So if I pass the addresses of these variables in the struct passed to the cog routine then it would work in XMMC mode?

    For any XMM memory model where a COG-C program is used, we need to copy code to HUB memory for cognew to work; COG-C programs live in the text segment. The demos/toggle/cog_c_toggle program does not copy the code first, and will fail in XMMC mode. Any imported PASM program like used in demos/toggle/pasm_toggle will work fine in XMMC mode without copying first (but not XMM-SINGLE or XMM-SPLIT).

    My earlier post omits the step of copying the COG from XMMC code space to HUB memory. Sorry about that.

    To make the demos/toggle/cog_c_toggle program work, two things need to be changed (this needs to be fixed before our next distribution):

    1) The pins toggled should not include the XMMC storage pins. Remove the 3 from the pins declaration for EEPROM XMMC. Other XMM solutions may need other adjustments.
    static _COGMEM unsigned int pins = 0xFFFFFFF;  /* all pins except Serial IO and I2C */
    


    2) The start function should be replaced with something like this:
    /*
     * function to start up a new cog running the toggle code
     */
    void start(volatile void *parptr)
    {
        extern unsigned int _load_start_toggle_fw_cog[];
        extern unsigned int _load_stop_toggle_fw_cog[];    
    
    
        // copy code should be used for any XMM cognew.
        // theoretically this step is not necessary for LMM
        int size = (_load_stop_toggle_fw_cog - _load_start_toggle_fw_cog);
        unsigned int code[size];
        memcpy(code, _load_start_toggle_fw_cog, size << 2); // size * 4 bytes
        cognew(code, parptr);
    }
    
  • ersmithersmith Posts: 6,095
    edited 2012-08-26 17:27
    jazzed wrote: »
    The example given doesn't work because it doesn't have a pointer to the data in a mailbox. The cog has no way to know how to reference global variables as shown.

    COGs should always share data via mailbox pointers.

    You're thinking of binary blobs (PASM compiled to .DAT). In fact COGC code can share data directly -- the linker will fix up data references. That's why we have to go through some hoops to link COGC programs.

    The problem is that the COGs aren't even running, because cognew does not work on text (such as the COGC code) in XMM or XMMC modes. It does work on binary blobs, because (as you say) they're stored in hub memory. COGC code is not.

    The cog_c_toggle code actually does work in XMM mode, it has #if defined(__PROPELLER_XMM__) || defined(__PROPELLER_XMMC__) in the places where LMM and XMM differ.

    Eric
  • jazzedjazzed Posts: 11,803
    edited 2012-08-26 18:57
    ersmith wrote: »
    The cog_c_toggle code actually does work in XMM mode, it has #if defined(__PROPELLER_XMM__) || defined(__PROPELLER_XMMC__) in the places where LMM and XMM differ.
    You're right. I was looking at an old copy of propgcc demos in the SimpleIDE tree. Looks like I need to merge some things.

    Thanks.
Sign In or Register to comment.