Shop OBEX P1 Docs P2 Docs Learn Events
Program too big, hub overflow by X bytes — Parallax Forums

Program too big, hub overflow by X bytes

Hi there,
First of all sorry if this is not the appropiate category, couldn't find another one that fit properly.

I have the ActivityBot and been working on a rather small code to make the bot rotate if PING or IR detect obstacles.
When compiling, I'm getting
"hub overflow" -> "Your program is too big for the memory model selected".

Have done some research and there are options to store the program on the SD card, but I haven't found clues or manuals on how to do so.
As you will see the program is not that big... not even 80 lines!!

Would appreciate some help :). Thanks!

BTW, you will see that "loga" function. I'm trying to find out why PING doesn't recognizes obstacles sometimes (talking about furniture).

Memory model: CMM Main RAM Compact
Compiler options: Simple printf, 32bit doubles
Linker: MAth lib, tiny lib

Code:

#include "simpletools.h"
#include "abdrive.h"
#include "ping.h"

int LEFT_IR = 13;
int RIGHT_IR = 0;
int NO_OBSTACLE = 1;

int distanceRight, distanceLeft;
int DO = 22, CLK = 23, DI = 24, CS = 25;
int irLeft, irRight;
char *log_msg;

int sides_are_not_free();
void loga();

int main() // Main function
{
sd_mount(DO, CLK, DI, CS);
while(1)
{
if(ping_cm(7) < 15) {
drive_ramp(0,0);
high(26);
log_msg="Turn";
loga();

while(ping_cm(7) < 15 && sides_are_not_free()) {
drive_goto(26,0);
}
}
low(26);
drive_ramp(64, 64);
}
}

int sides_are_not_free()
{
freqout(LEFT_IR, 1, 38000); // Check left & right objects
irLeft = input(11);

freqout(RIGHT_IR, 1, 38000);
irRight = input(1);
if (irLeft == NO_OBSTACLE && irRight == NO_OBSTACLE){
return 0;
} else {
return 1;
}
}

void loga()
{
char *buf;
size_t sz;
sz = snprintf(NULL,0,"At L%fR%f - %s \n",(distanceLeft*3.25)/10,(distanceRight*3.25)/10, log_msg);
buf = (char *)malloc(sz + 1); /* make sure you check for != NULL in real code */

char *s =snprintf(buf, sz+1, "At L%fR%f - %s \n",(distanceLeft*3.25)/10,(distanceRight*3.25)/10, log_msg);
drive_getTicks(&distanceLeft, &distanceRight);
FILE* log_file = fopen("logs_2017_047_04.txt", "a+");
fwrite(s,1,sizeof(s),log_file);
fclose(log_file);
}



Comments

  • You are using file I/O, floating point and snprintf, which combine to take up lots of memory. Try eliminating the floating point calculations by doing "distanceLeft*325" instead of "(distanceLeft*3.25)/10". The values printed out will be 1000 times larger, but it will probably fit in hub memory. If that's not enough you'll have to get rid of snprintf and format your file prints yourself.
  • Thanks Dave, will give it a try. Memory limit is at 2K?

    However that opens the next question: How can I make space for "larger" programs?
  • The memory limit is 32K for LMM and CMM programs. You are using the CMM mode, which is the Compact Memory Model. One way to handle larger programs is to use the XMMC memory model, but that requires some form of external memory, such as flash memory. Another way is to not use floating point and the stdio functions in the C library. snprintf pulls in a lot of code from the libraries, so it is better to use simple versions of that code. There is already a simple printf, which you are using. I can provide you with a simple version of snprintf if you want, or you can write your own.

    File I/O takes up a lot of space also. You can save some space by using a file driver called FSRW, which has to be imported from a Spin object. There is a tool call spin2cpp that can convert Spin code to C/C++.

    The other possibility is to program in Spin instead of C. The CMM mode is about as compact as Spin bytecodes, but C programs tend to pull in stuff from the libraries. With Spin you have more control over what gets pulled in. In Spin you have to explicitly include external code as objects. If you are careful in C you can create equivalent programs that are about the same size as Spin programs. You just have to work a little harder to do it.

    The big issue in the Prop is the 32K hub RAM. It's just not quite big enough to handle a lot of C code. It's unfortunate that a 64K version of the Prop was never done. This would have resolved the C memory issue on the Prop. Hopefully in a couple of years we'll have the P2 that will have 512K of RAM, and not suffer from these memory issues.
  • egulias wrote: »
    I have the ActivityBot and been working on a rather small code to make the bot rotate if PING or IR detect obstacles.
    When compiling, I'm getting
    "hub overflow" -> "Your program is too big for the memory model selected".

    Have done some research and there are options to store the program on the SD card, but I haven't found clues or manuals on how to do so.
    As you will see the program is not that big... not even 80 lines!!

    It isn't your code too big but the number of dependencies it brings in (call to library functions, that calls other functions, etc.).
    Memory model: CMM Main RAM Compact
    Compiler options: Simple printf, 32bit doubles
    Linker: MAth lib, tiny lib

    I tried to reproduce and I see that you are not using the math library, try to disable it from the Linker tab, this should free enough memory to allow you to compile.
    BTW, you will see that "loga" function. I'm trying to find out why PING doesn't recognizes obstacles sometimes (talking about furniture).

    That function won't work.
    void loga()
    {
      char *buf;
      size_t sz;
      sz = snprintf(NULL,0,"At L%fR%f - %s \n",(distanceLeft*3.25)/10,(distanceRight*3.25)/10, log_msg);
      buf = (char *)malloc(sz + 1); /* make sure you check for != NULL in real code */
    
      char *s =snprintf(buf, sz+1, "At L%fR%f - %s \n",(distanceLeft*3.25)/10,(distanceRight*3.25)/10, log_msg);
      drive_getTicks(&distanceLeft, &distanceRight);
      FILE* log_file = fopen("logs_2017_047_04.txt", "a+");
      fwrite(s,1,sizeof(s),log_file);
      fclose(log_file);
    }
    

    1. In the second call to snprintf you are assigning the returned value to a char pointer and use that pointer to write the string, however snprintf returns an integer count and not a pointer, as you are correctly using it in the first call. The compiler gives you a warning on that, do you see it ? Never ignore warnings, unless you know what you are doing!

    2. In the fwrite function you are using the (wrong) s pointer and sizeof(s) which doesn't return the length of the string but the size of the pointer, you'll write just 4 random bytes to the file.

    3. You are allocating memory with malloc but don't free it, each time you call loga memory will be allocated until the heap ends and your program will likely crash.

    In C there is the fprintf function that could replace all that code:
    FILE * log_file = fopen("logs_2017_047_04.txt", "a+");
    fprintf(log_file, "At L%dR%d - %s \n", (distanceLeft * 325) / 1000,
                      (distanceRight * 325) / 1000, log_msg);
    fclose(log_file);
    

    Haven't tested (just compiled), hope it helps.
  • fprintf pulls in much of the same library code as snprintf, so the program is still too big with fprintf. Try this version of loga. The resulting program is about 24K in size. PropGCC doesn't seem to have itoa in the libraries, so I had to include the function itoa10. I haven't tested it, but I think it will work OK.
    char *itoa10(char *ptr, int value, char *ptr)
    {
        char *rval = ptr;
        int zeroflag = 0;
        int i = 1000000000;
    
        if (value < 0)
        {
            *ptr++ = '-';
            if (value == 0x80000000)
            {
                *ptr++ = '2';
                value += 2000000000;
            }
            value = -value;
        }
    
        while (i)
        {
            if (value >= i)
            {
                *ptr++ = (value / i) + '0';
                value %= i;
                zeroflag = 1;
            }
            else if (zeroflag || i == 1)
            {
                *ptr++ = '0';
            }
            i /= 10;
        }
        *ptr = 0;
        return rval;
    }
    
    void loga()
    {
      FILE * log_file = fopen("logs_2017_047_04.txt", "a+");
      char tmpstr[12];
      
      fputs("At L", log_file);
      fputs(itoa10(tmpstr, (distanceLeft * 325) / 1000), log_file);
      fputs("R", log_file);
      fputs(itoa10(tmpstr, (distanceRight * 325) / 1000), log_file);
      fputs(" - ", log_file);
      fputs(log_msg, log_file);
      fputs(" \n", log_file);
    
      fclose(log_file);
    }
    
Sign In or Register to comment.