Program space full - any tips?

Hi, i’ve been working on an application with the wixel for some months now. Today i ran out of space in the flash, program is too big. When i started splitting the code into separate files, even with include guards, i saw that space was bigger. Any ideas, tips, or known issues with SDCC that you may of, in order to save some space. My program uses the two uarts, the 4 timers & usb. Are there any libraries in the wixel-sdk that i can get rid of ? any ideas will help.

Hello. Wow, I do not think I have ever come close to filling up 29 KB of flash on an 8-bit microcontroller. What is this project?

First of all, you should inspect the generated .map file carefully to see what is taking up all that space. If there is one particular object or function that is taking up many kilobytes, then that is a good place to start doing your optimizations. Also, you should constantly be looking at the .mem file produced by the compiler so you can get feedback about how many bytes you save or lose each time you make a change to the code. You should also get in the habit of looking at parts of the .lst file so you understand what type of assembly instructions the C compiler needs to generate when it compiles your code.

SDCC’s linker will automatically exclude entire object files (which correspond to .c files) if you don’t use any of the variables or functions in that file, so it will not help to remove unused libraries. However, you could look at the libraries your program uses and remove any unused functions from them by modifying their source code. This would break other apps in the Wixel SDK, but you can just delete those apps.

Try to avoid using pointers as much as possible because extra indirection results in extra instructions being generated when you read or write from the variable being pointed to.

If you are using pointers, avoid the use of SDCC’s generic pointers as much as possible because they take more overhead to deal with. The generic pointers take three bytes. Every bit of memory is accessible in the XDATA memory space, so use XDATA pointers which are only two bytes:

uint8 XDATA * pointer;

Store commonly used variables in the DATA section (“internal” RAM) because it takes fewer instructions to access that section. Don’t fill up the DATA section too much though because you have to share that space with the stack.

uint8 DATA var;  // store var in internal RAM

Try to avoid using functions like printf and sprintf.

Try to avoid doing floating point calculations.

You could even get your own CC2511 programmer and start using the entire 32 KB of flash.

There are lots of suboptimal things you might be doing and it’s hard to make a list of all of them. If you share your code with us, maybe I will have more tips for you.

–David

Thanks, here’s a summary, the project is a wireless remote control for a special machine. Here’s how the peripherals are used:

Timer 1 - Variable squarewave generator
Timer 2 - Watchdog timer
Timer 3 - Measure the speed of a motor by looking at a tachometer square wave
Timer 4 - Used by the delay function - so didnt messed with that

Uart0 - Wifi module
Uart1 - RS232 port to communicate with the machine

P0 - interrupts inputs from I/O
P1 - General I/O

USB - communicate to a PC

Total interrupt sources is 8 counting the uarts

My RAM usage is 240 out of 256, XDATA is 3200 out of ~3800

I have a file with like 50 string constants which alone is like 1K. I will look at the files that you suggested, the .map file i look at it constatnly. I am wondering if there are any SDCC optimizations that can potentially be used, but because of going through the makefile then those are not possible to change easily. Not familiar enought with SDCC options, so that will help too. How can i override the bootloader on the wixel, is that possible ? how can i program it ?

Did you remove code for LEDs? :smiley: I did that at one point.

Are you using the USB during your application (wasn’t apparent to what extent you’re communicating with the computer)? If not you can drop that library and add a button to trigger bootloader mode.

I probably qualify as a horrible embedded programmer, and I have a robot using two Wixels to get around the 256 byte RAM limit.

I have not checked recently, but I do not recall SDCC having any optimization options. However, if you read the SDCC manual and find something you want to try, then you can do it by just adding a line like this to the Makefile:

C_FLAGS += --newoption

To erase the bootloader, you would need to use the CC2511’s debug interface, which is on P2_1 and P2_2. The debug interface is described in detail on the datasheet in chapter 11. You would need to find some sort of device that can generate the right signals to load a program into flash through the debug interface. Unfortunately, I do not have any good programmer to recommend to you. You should be able to use one Wixel to program another if someone writes the code for it.

We don’t support putting the bootloader back onto the Wixel after you have erased it, so if you did that to a Wixel then you should just count on using the debug interface exclusively as the way you upload programs to that Wixel.

–David

how much will i get back if i get rid of the bootloader ? 1k ?

I thought the flash was locked and the bootloader was not erasable. I’ll take a look at chapter 11. Getting rid of USB is an option, yes, i will check how much i will save with that, it is my primary debug interface as well…so that will make things harder too. But if the USB library is significant, maybe it’s time to get rid of it somehow.

The bootloader takes up 3 kB, so that is how much space you could save by getting rid of it. --David

Thanks David. Couple of extra questions about the bootloader.

  1. Using the BL brings any benefits to reduce flash wear-out ? like it writes only the bytes that change ?
  2. Which libraries of the wixel-sdk won’t work without the bootloader ?

thanks

  1. No, it does not. I would not worry about the flash wearing out if I were you.
  2. All of the Wixel libraries should continue working. One thing to watch out for is code that reads the bootloader’s USB device descriptor or the serial number; both of those are in bootloader flash area and their locations are defined here. Currently, none of our libraries use that, so it should not be a problem.

–David

although i am using pointers with XDATA as you suggested, i found that they take a lot of space. I was using a linked list, and that takes a lot of space. I converted that to a static list using arrays and saved some space. Also each call to the following function takes about 60 bytes on EACH CALL !!. which is a lot. i have like 50 calls to this:

void DbgPrint(const char *stringToSend, ...)
{
    static char XDATA buffer[TX_MAX_PACKET_SIZE];   // need to make buffer static due to compiler requirement
    
    if(debugMode)
    {
    
    va_list(ap);
    va_start(ap,stringToSend);
    vsprintf(buffer,stringToSend,ap);
    va_end(ap);
    
    usbSend(buffer,strlen(buffer));
    }  
}

i tried multiple SDCC flags, with no change. But reducing the number of DbgPrint() calls - pointers, i was able so save 2.5K