Shop OBEX P1 Docs P2 Docs Learn Events
GCC usage? - Page 3 — Parallax Forums

GCC usage?

13

Comments

  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-17 13:13
    Dave Hein wrote: »
    It looks OK, except there's some ambiguity about the ';' character. An ESCAPE character (0x1b) would be mapped to a semicolon (0x3b). As long as your string doesn't contain an ESCAPE character you should be OK.
    I have yet to see any G-Code that contains an escape, so it should be ok, lol.
  • jmgjmg Posts: 15,173
    edited 2015-04-17 16:36
    Does this look better? :
      while (codebuf[offset] < 0x21) offset++; /*Skip spaces.*/
      while ((codebuf[offset] != 0x0D) && (codebuf[offset] != 0x0A) && codebuf[offset]){
        switch (codebuf[offset++] | 0x20){
    
    
            for (tmp = 0;(tstr[tmp] = codebuf[offset++]) > 0x2F && tmp < 0x3A;++tmp);
            for (tmp = 0;(tstr[tmp] = codebuf[offset++]) > 0x2F && tmp < 0x3A;++tmp);
            for (tmp = 0;(tstr[tmp] = codebuf[offset++]) > 0x2F && tmp < 0x3A;++tmp);
            for (tmp = 0;(tstr[tmp] = codebuf[offset++]) > 0x2F && tmp < 0x3A;++tmp);
            for (tmp = 0;(tstr[tmp] = codebuf[offset++]) > 0x2F && tmp < 0x3A;++tmp);
            for (tmp = 0;(tstr[tmp] = codebuf[offset++]) > 0x2F && tmp < 0x3A;++tmp);
            for (tmp = 0;(tstr[tmp] = codebuf[offset++]) > 0x2F && tmp < 0x3A;++tmp);
    
            while (codebuf[offset] != 0x0A && codebuf[offset] != 0x0D) ++offset;
    

    That looks like a lot of duplicated skip code - can that not move outside the case tests to drop the code size significantly ?
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-17 18:57
    jmg wrote: »
    That looks like a lot of duplicated skip code - can that not move outside the case tests to drop the code size significantly ?
    I have already changed it. I posted the new version in the C firmware thread, though here it is again:
    long GCstr2inum(long o, long *r){
      long rv, tmp, cnt, mp, bmp;
      char *s, tc;
      s = &codebuf[o];
      
      for (tmp = 0, cnt = 0; (tc = s[tmp]) >= 0x30 && tc <= 0x39; tmp++, cnt++);
      for (mp = 1; cnt; cnt--, mp * 10) rv = (s[cnt] - 0x30) * mp;
      rv <<= 8;
      if (s[tmp] == '.')       // Check for fractional part.
        for (tmp++, mp = 10; s[tmp] <= 0x30 && s[tmp] <= 0x39 && mp <= 100; tmp++, mp * 10)
          rv = (256/mp) * (s[tmp] - 0x30) + rv;
    
      *r = tmp + o;
      return rv;  
    }  
     
    /**************************************************************************
    * int GetGParams(long offset)                                             *
    *                                                                         *
    * Parses the G-Code parameter string and fills in the GCodePar struct for *
    * this command.                                                           *
    *                                                                         *
    * PARAMETERS:                                                             *
    * long offset : The offset in the codebuf buffer where the parameters     *
    *               begin                                                     *
    *                                                                         *
    * RETURNS:                                                                *
    *   The offset in the G-Code buffer after the end of the parameters.      *
    *                                                                         *
    * TODO:                                                                   *
    *   DONE: Add the ability to skip past comments at the end of line.       *
    **************************************************************************/
    int GetGParams(long offset){
      int  tmp;
      
      if (codebuf[offset] >= 0x30 && codebuf[offset] <= 0x39){
        offset++;
        GCodePar.gc = GCstr2inum(offset, &offset);
      }    
        
      
      while (codebuf[offset] < 0x21) offset++; /*Skip spaces.*/
      while ((codebuf[offset] != 0x0D) && (codebuf[offset] != 0x0A) && codebuf[offset]){
        switch (codebuf[offset++] | 0x20){
          case 'x':
            GCodePar.x = GCstr2inum(offset, &offset); break;
          case 'y':
            GCodePar.y = GCstr2inum(offset, &offset); break;
          case 'z':
            GCodePar.z = GCstr2inum(offset, &offset); break;
          case 'e':
            GCodePar.e = GCstr2inum(offset, &offset); break;
          case 'f':
            GCodePar.f = GCstr2inum(offset, &offset); break;
          case 'p':
            GCodePar.p = GCstr2inum(offset, &offset); break;
          case 's':
            GCodePar.s = GCstr2inum(offset, &offset); break;
          case ';':
            while (codebuf[offset] != 0x0A && codebuf[offset] != 0x0D) ++offset;
        }      
      }  
      
      return offset;
    }
    
    
    /**************************************************************************
    * int ExecMCode(void)
    **************************************************************************/
    int ExecMCode(){
      switch (GCodePar.gc) {
        case 0:           //All stop.
          StopSteppers();StopExtruder();
          break;
        case 2:           //End G-Code prog.
         StpTo(0,0,0);
         StopSteppers(); StopExtruder();
         break;
        case 82:          //Only absolute supported for extruder.
          break;
        case 104:         //Set extruder tempurature.
           ExTemp(GCodePar.s); break;
        case 106:         //fan on.
          /*FanSet(GCodePar.s)*/; break;
        case 107:         //Fan Off.
          /*FanSet(0)*/; break;
        case 109:         //Set extruder temp (we always wait).
           ExTemp(GCodePar.s); break;
        case 116:         //wait for all to be ready.
          break;          //We always wait for ready, so do nothing.
      }
          
      return 0;
    }
    
    
    /**************************************************************************
    * int ExecGcode(void)                                                     *
    *                                                                         *
    * Perform an Gxxx command.                                                *
    **************************************************************************/
    int ExecGCode(void){
      switch (GCodePar.gc){
        case 0:
        case 1:
          G0(); break;
        case 4:
          WaitMS(GCodePar.p); break;
        case 21:
          GCodePar.dmul = inch; break;
        case 22:
          GCodePar.dmul = mm; break;
        case 90:            //G90 Only absolute positioning supported.
          break;
      }    
      return 0;
    }
    
    
    /**************************************************************************
    * int GCode(void)                                                         *
    *                                                                         *
    * This function is the outer level of the simple G-Code parser.           *
    *                                                                         *
    * PARAMETERS:                                                             *
    * The contents of the character buffer, codebuf.                          *
    *                                                                         *
    * TODO:                                                                   *
    *   DONE: Add the ability to skip past comments at the end of line.       *
    **************************************************************************/
    int GCode(void){
      char tc;
      short offset;
      offset = 0;
    
      while (codebuf[offset]){  /*Continue until next char is NULL.*/
        while (codebuf[offset] < 0x21) offset++; /*skip leading spaces.*/
        if ((codebuf[offset++] == 0xD) || (codebuf[offset++] == 0x0A))   /*check for end of line*/
          while (GCodePar.status);      /*Wait for command to finish running.*/
    
        switch (codebuf[offset++] | 0x20) {                 /*Determine if we are using a G command or M command.*/
          case 'g':
            offset = GetGParams(offset); ExecGCode(); break;
          case 'm':
            offset = GetGParams(offset); ExecMCode(); break;
          case ';':
            while (codebuf[offset] != 0x0A && codebuf[offset] != 0x0D && codebuf[offset] != 0) ++offset;
        }    
      }
      return 0;
    }
    
  • David BetzDavid Betz Posts: 14,516
    edited 2015-04-17 18:59
    I think your code would be easier to read if you would use '0' instead of 0x30 and '9' instead of 0x39, etc. Is there some reason you're not using character constants?
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-17 19:01
    David Betz wrote: »
    I think your code would be easier to read if you would use '0' instead of 0x30 and '9' instead of 0x39, etc. Is there some reason you're not using character constants?
    Very old habit, that I picked up in 6502 assembly a long time ago (using $30 and $39 for the number character bounds).

    I can definitely change it to '0' and '9' to simplify for others, thank you.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-17 19:05
    David Betz wrote: »
    I think your code would be easier to read if you would use '0' instead of 0x30 and '9' instead of 0x39, etc. Is there some reason you're not using character constants?
    More like this?
    long WaitMS(long w){
      long tmp,tmpend;
      
      tmp = CNT;
      tmpend = (CLKFREQ / 1000) * w + tmp;
      while (CNT < tmpend);
      return 0;
    }  
    
    
    long GCstr2inum(long o, long *r){
      long rv, tmp, cnt, mp, bmp;
      char *s, tc;
      s = &codebuf[o];
      
      for (tmp = 0, cnt = 0; (tc = s[tmp]) >= '0' && tc <= '9'; tmp++, cnt++);
      for (mp = 1; cnt; cnt--, mp * 10) rv = (s[cnt] - 0x30) * mp;
      rv <<= 8;
      if (s[tmp] == '.')       // Check for fractional part.
        for (tmp++, mp = 10; s[tmp] <= '0' && s[tmp] <= '9' && mp <= 100; tmp++, mp * 10)
          rv = (256/mp) * (s[tmp] - '0') + rv;
    
      *r = tmp + o;
      return rv;  
    }  
     
    /**************************************************************************
    * int GetGParams(long offset)                                             *
    *                                                                         *
    * Parses the G-Code parameter string and fills in the GCodePar struct for *
    * this command.                                                           *
    *                                                                         *
    * PARAMETERS:                                                             *
    * long offset : The offset in the codebuf buffer where the parameters     *
    *               begin                                                     *
    *                                                                         *
    * RETURNS:                                                                *
    *   The offset in the G-Code buffer after the end of the parameters.      *
    *                                                                         *
    * TODO:                                                                   *
    *   DONE: Add the ability to skip past comments at the end of line.       *
    **************************************************************************/
    int GetGParams(long offset){
      int  tmp;
      
      if (codebuf[offset] >= '0' && codebuf[offset] <= '9'){
        offset;
        GCodePar.gc = GCstr2inum(offset, &offset);
      }    
        
      
      while (codebuf[offset] < 0x20) offset++; /*Skip spaces.*/
      while ((codebuf[offset] != 0x0D) && (codebuf[offset] != 0x0A) && codebuf[offset]){
        switch (codebuf[offset++] | 0x20){
          case 'x':
            GCodePar.x = GCstr2inum(offset, &offset); break;
          case 'y':
            GCodePar.y = GCstr2inum(offset, &offset); break;
          case 'z':
            GCodePar.z = GCstr2inum(offset, &offset); break;
          case 'e':
            GCodePar.e = GCstr2inum(offset, &offset); break;
          case 'f':
            GCodePar.f = GCstr2inum(offset, &offset); break;
          case 'p':
            GCodePar.p = GCstr2inum(offset, &offset); break;
          case 's':
            GCodePar.s = GCstr2inum(offset, &offset); break;
          case ';':
            while (codebuf[offset] != 0x0A && codebuf[offset] != 0x0D) ++offset;
        }      
      }  
      
      return offset;
    }
    
    
    /**************************************************************************
    * int ExecMCode(void)
    **************************************************************************/
    int ExecMCode(){
      switch (GCodePar.gc) {
        case 0:           //All stop.
          StopSteppers();StopExtruder();
          break;
        case 2:           //End G-Code prog.
         StpTo(0,0,0);
         StopSteppers(); StopExtruder();
         break;
        case 82:          //Only absolute supported for extruder.
          break;
        case 104:         //Set extruder tempurature.
           ExTemp(GCodePar.s); break;
        case 106:         //fan on.
          /*FanSet(GCodePar.s)*/; break;
        case 107:         //Fan Off.
          /*FanSet(0)*/; break;
        case 109:         //Set extruder temp (we always wait).
           ExTemp(GCodePar.s); break;
        case 116:         //wait for all to be ready.
          break;          //We always wait for ready, so do nothing.
      }
          
      return 0;
    }
    
    
    /**************************************************************************
    * int ExecGcode(void)                                                     *
    *                                                                         *
    * Perform an Gxxx command.                                                *
    **************************************************************************/
    int ExecGCode(void){
      switch (GCodePar.gc){
        case 0:
        case 1:
          G0(); break;
        case 4:
          WaitMS(GCodePar.p); break;
        case 21:
          GCodePar.dmul = inch; break;
        case 22:
          GCodePar.dmul = mm; break;
        case 90:            //G90 Only absolute positioning supported.
          break;
      }    
      return 0;
    }
    
    
    /**************************************************************************
    * int GCode(void)                                                         *
    *                                                                         *
    * This function is the outer level of the simple G-Code parser.           *
    *                                                                         *
    * PARAMETERS:                                                             *
    * The contents of the character buffer, codebuf.                          *
    *                                                                         *
    * TODO:                                                                   *
    *   DONE: Add the ability to skip past comments at the end of line.       *
    **************************************************************************/
    int GCode(void){
      char tc;
      short offset;
      offset = 0;
    
      while (codebuf[offset]){  /*Continue until next char is NULL.*/
        while (codebuf[offset] < 0x21) offset++; /*skip leading spaces.*/
        if ((codebuf[offset++] == 0xD) || (codebuf[offset++] == 0x0A))   /*check for end of line*/
          while (GCodePar.status);      /*Wait for command to finish running.*/
    
        switch (codebuf[offset++] | 0x20) {                 /*Determine if we are using a G command or M command.*/
          case 'g':
            offset = GetGParams(offset); ExecGCode(); break;
          case 'm':
            offset = GetGParams(offset); ExecMCode(); break;
          case ';':
            while (codebuf[offset] != 0x0A && codebuf[offset] != 0x0D && codebuf[offset] != 0) ++offset;
        }    
      }
      return 0;
    }
    
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-18 13:50
    I have to mask, what is the huge difference between CMM and LMM? Twice the size is extreme, so there must be something to the story.
  • SRLMSRLM Posts: 5,045
    edited 2015-04-18 13:56
    I have to mask, what is the huge difference between CMM and LMM? Twice the size is extreme, so there must be something to the story.

    This page has some good documentation:

    https://propgcc.googlecode.com/hg/doc/Memory.html
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-18 14:06
    SRLM wrote: »
    This page has some good documentation:

    https://propgcc.googlecode.com/hg/doc/Memory.html
    Thank you for that. How much slower is CMM than LMM?

    What means of compression are used (I would assume just something like 16 bit instructions, that can be quickly expanded to 32-bit)?
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-18 14:16
    I just found the documentation of the CMM opcodes, and it looks as though they can be executed fairly quickly, so I would guess that a speed close to that of LMM is possible in CMM.

    I may have to look at the actual interpreter to be sure.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-04-18 14:29
    I just found the documentation of the CMM opcodes, and it looks as though they can be executed fairly quickly, so I would guess that a speed close to that of LMM is possible in CMM.

    I may have to look at the actual interpreter to be sure.

    The cmm opcodes have to be interpreted unfortunately. It is very much like Spin - compact, but slow. Most people experience about half the size and half the speed of LMM. Combining CMM with inline assembly is an great combination though.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-18 14:44
    Ok I guess I am down to only one question:

    Is it possible to mix C (using PropGCC or Catalina) with Spin, in a simple way??

    Same goes for PropBASIC + C, as I would like to be able to take it a bit slower when converting to PropBASIC (as I have decided to use the C code as a model for the PropBASIC code).
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-04-18 15:06
    Is it possible to mix C (using PropGCC or Catalina) with Spin, in a simple way??

    Simple or not, I believe SpinWrap is your only option.

    I can't speak for PropBASIC - out of my expertise zone.
  • David BetzDavid Betz Posts: 14,516
    edited 2015-04-18 15:30
    Ok I guess I am down to only one question:

    Is it possible to mix C (using PropGCC or Catalina) with Spin, in a simple way??

    Same goes for PropBASIC + C, as I would like to be able to take it a bit slower when converting to PropBASIC (as I have decided to use the C code as a model for the PropBASIC code).
    You can use spin2cpp to compiler your Spin code to C++ (or C) and link that with your other C code.
  • SRLMSRLM Posts: 5,045
    edited 2015-04-18 15:34
    I just found the documentation of the CMM opcodes, and it looks as though they can be executed fairly quickly, so I would guess that a speed close to that of LMM is possible in CMM.

    I may have to look at the actual interpreter to be sure.

    I'm glad you asked: https://sites.google.com/site/propellergcc/documentation/faq#TOC-Q:-What-are-the-performance-numbers-of-PropellerGCC-
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-18 17:27
    OK so CMM C code with GCC is still more than two times faster than SPIN, only 2.7 times slower than LMM, and only 9.86 times slower than COG C code. That is prety good in my book for an interpreted code.

    ________________________________________________________________________________________________________________________
    Just to make sure I have things correct:

    With COG C code compiled with GCC:
    1:All global variables are in hub memory (even those declared static, and thus module local).
    2:All stack usage is done in HUB memory, no matter what.
    3:Declaring a function as _NATIVE prevents the use of the stack for return, as well as parameters.
    4:Static local variables are honored (some compilers still put them on the stack).

    Does that pretty much cover it for COG mode?? If so I think that I can simply recompile the current source as COG C, I have broken it down a good bit.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-18 17:32
    OK I just discovered a couple more questions:

    When compiling for COG mode, how do you start a cog?

    When compiling COG model how do you access the control registers?

    I decided to give COG memory model a try, the only error in compile was related to the lack of a COG ram version of simpletools.
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-04-18 17:50
  • ersmithersmith Posts: 6,053
    edited 2015-04-18 18:45
    Just to make sure I have things correct:

    With COG C code compiled with GCC:
    1:All global variables are in hub memory (even those declared static, and thus module local).
    2:All stack usage is done in HUB memory, no matter what.
    Yes to both.
    3:Declaring a function as _NATIVE prevents the use of the stack for return, as well as parameters.
    _NATIVE does not affect parameters. The first 6 longs worth of parameters are passed in registers in any case, except for varargs functions (which use the stack for the ... portion).
    4:Static local variables are honored (some compilers still put them on the stack).
    I can't understand how any compiler can do this and still comply with any kind of C standard (including the original K&R). But anyway, yes, GCC handles static variables correctly. In our case they're treated the same as global variables (placed in HUB memory at fixed locations) unless you use the _COGMEM attribute.

    Finally, another tip: if you only need full COG performance intermittently, you may be able to forgo COG C completely. Tight loops are accelerated by the compiler using "fcache", which means they are loaded into a reserved area of the original COG's LMM/CMM kernel and run from there at full COG speed. You can also order a whole function to be run this way by marking it __attribute__((fcache)).
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-19 04:46
    ersmith wrote: »
    Yes to both.


    _NATIVE does not affect parameters. The first 6 longs worth of parameters are passed in registers in any case, except for varargs functions (which use the stack for the ... portion).


    I can't understand how any compiler can do this and still comply with any kind of C standard (including the original K&R). But anyway, yes, GCC handles static variables correctly. In our case they're treated the same as global variables (placed in HUB memory at fixed locations) unless you use the _COGMEM attribute.
    That seems like it would not comply with the standard, as a static local veriable is supposed to be with its code block, ok not specified that way, though strongly implied int the second edition book.
    Finally, another tip: if you only need full COG performance intermittently, you may be able to forgo COG C completely. Tight loops are accelerated by the compiler using "fcache", which means they are loaded into a reserved area of the original COG's LMM/CMM kernel and run from there at full COG speed. You can also order a whole function to be run this way by marking it __attribute__((fcache)).
    The reason is not speed in this case. CMM is actually faster than what I need.

    I am looking to free up most of the HUB Ram to use for data (buffering G-Code, a small text buffer [40x25 = 100 bytes] for the display, and a small tile buffer for some graphics).
  • ersmithersmith Posts: 6,053
    edited 2015-04-19 05:16
    That seems like it would not comply with the standard, as a static local veriable is supposed to be with its code block, ok not specified that way, though strongly implied int the second edition book.
    I think you're misreading something. Code goes in the .text section, data (including static local variables) in the .data section. I guess a "const" static local variable could go in .text, but in general C has always maintained a separation between code and data. It's kind of moot anyway where exactly the variable goes, as long as the behavior is correct. A static local variable is only accessible by the particular function it is declared in (its label will be unique, and will not be exported) and it has to preserve its value between function invocations (so it cannot go in temporary storage, like the stack).
    The reason is not speed in this case. CMM is actually faster than what I need.
    I am looking to free up most of the HUB Ram to use for data (buffering G-Code, a small text buffer [40x25 = 100 bytes] for the display, and a small tile buffer for some graphics).

    Ah. Then you may want to look in to XMMC mode. You can put all the code in external memory then, and have most of HUB memory (except for the cache space) free for data.

    In general moving functions into COGs will not automatically free up HUB memory because the original code block used to load the COG will still reside in the HUB (the C runtime cannot know how many COGs are going to be started, or when, so it can't recycle the original image). You can manually re-use that space, or you can place the COG code in EEPROM.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-19 05:50
    ersmith wrote: »
    I think you're misreading something. Code goes in the .text section, data (including static local variables) in the .data section. I guess a "const" static local variable could go in .text, but in general C has always maintained a separation between code and data. It's kind of moot anyway where exactly the variable goes, as long as the behavior is correct. A static local variable is only accessible by the particular function it is declared in (its label will be unique, and will not be exported) and it has to preserve its value between function invocations (so it cannot go in temporary storage, like the stack).



    Ah. Then you may want to look in to XMMC mode. You can put all the code in external memory then, and have most of HUB memory (except for the cache space) free for data.

    In general moving functions into COGs will not automatically free up HUB memory because the original code block used to load the COG will still reside in the HUB (the C runtime cannot know how many COGs are going to be started, or when, so it can't recycle the original image). You can manually re-use that space, or you can place the COG code in EEPROM.
    OK that is an unexpected limit of COGC with GCC. I want pure cog mode (load the code into the cogs one time only, and reuse the HUB RAM).

    Does Catalina do better with that?
  • ersmithersmith Posts: 6,053
    edited 2015-04-19 07:21
    OK that is an unexpected limit of COGC with GCC. I want pure cog mode (load the code into the cogs one time only, and reuse the HUB RAM).

    Does Catalina do better with that?

    Catalina doesn't support COG mode C code.

    If all your code fits in one COG then you can run a pure COG app (in which case all the HUB will be free, except for any stack and variable space you need). But once you have multiple COGs and LMM code to manage them, things get a lot more complicated

    There are still options. The simplest are to use XMMC mode (keeps most the code out of HUB to start with) or to store the COGC code in EEPROM (keeps at least the COGC stuff out of HUB). Another is to use a linker script to re-arrange the sections so the COGC code is together and can easily be re-used by your application for data storage. Come to think of it, if you use "binary blobs" stored in C arrays for your COG code you could then re-use those arrays for data, without having to do any linker tricks at all.
  • ersmithersmith Posts: 6,053
    edited 2015-04-19 07:24
    Note that Spin has the same issue -- the PASM image in the DAT section is still present in HUB memory after the COG is loaded.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-19 09:33
    ersmith wrote: »
    Catalina doesn't support COG mode C code.

    If all your code fits in one COG then you can run a pure COG app (in which case all the HUB will be free, except for any stack and variable space you need). But once you have multiple COGs and LMM code to manage them, things get a lot more complicated

    There are still options. The simplest are to use XMMC mode (keeps most the code out of HUB to start with) or to store the COGC code in EEPROM (keeps at least the COGC stuff out of HUB). Another is to use a linker script to re-arrange the sections so the COGC code is together and can easily be re-used by your application for data storage. Come to think of it, if you use "binary blobs" stored in C arrays for your COG code you could then re-use those arrays for data, without having to do any linker tricks at all.
    Well I have never liked ld as linkers go, though I guess I could learn to deal with it. Though the possibility of binary blobs stored in initialized arrays sounds interesting, I will have to give that some thought.

    Is there a way to just use all COG C, I can break my code down to run in 6 cogs, with out needing HUB mem for the code. Would it be possible while keeping the .data section together? Just a thought.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-19 09:37
    ersmith wrote: »
    Note that Spin has the same issue -- the PASM image in the DAT section is still present in HUB memory after the COG is loaded.
    Yes though you can overwrite the area used by the PASM code, as you know exactly where it is (eg if PASM starts at MyPasm you know that from @MyPasm to the end of the code can be overwritten, and used for many things). There does not seem to be a simple way to get the address of the COG code, otherwise it would be a no brainner to simply typecast the address to an appropriate pointer type and use it.
  • David BetzDavid Betz Posts: 14,516
    edited 2015-04-19 09:41
    Yes though you can overwrite the area used by the PASM code, as you know exactly where it is (eg if PASM starts at MyPasm you know that from @MyPasm to the end of the code can be overwritten, and used for many things). There does not seem to be a simple way to get the address of the COG code, otherwise it would be a no brainner to simply typecast the address to an appropriate pointer type and use it.
    Huh? If you use cognew or coginit you pass in an array of longs to use as the new COG image. Once you've loaded the COG, you're free to use that array for anything you like just like in Spin.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-19 09:43
    David Betz wrote: »
    Huh? If you use cognew or coginit you pass in an array of longs to use as the new COG image. Once you've loaded the COG, you're free to use that array for anything you like just like in Spin.
    I still need to figure out how to use either one from COGC, as they do not work from COGC, as I get library not found errors all over from ld when attempting to compile as COGC.
  • David BetzDavid Betz Posts: 14,516
    edited 2015-04-19 10:01
    I still need to figure out how to use either one from COGC, as they do not work from COGC, as I get library not found errors all over from ld when attempting to compile as COGC.
    You just have to make sure that there is at least one symbol defined in your COG C module that is referenced by your main code. This is essentially the same with any file that comes from a library. Some symbol in the library module must be needed to resolve a reference in the main program for the module to be pulled from the library.
  • jmgjmg Posts: 15,173
    edited 2015-04-19 12:52
    ersmith wrote: »
    In general moving functions into COGs will not automatically free up HUB memory because the original code block used to load the COG will still reside in the HUB (the C runtime cannot know how many COGs are going to be started, or when, so it can't recycle the original image). You can manually re-use that space, or you can place the COG code in EEPROM.

    Maybe add a means so that the user can tell the C runtime how many COGs are going to be started, so it can recycle the original image(s) ?
Sign In or Register to comment.