Pinguino Forum

Full Version: [PIC32 MX220] Not enough flash memory
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hello,

Once more, I have a problem...

I try to compile this code:

Code:
#define trigPin 7
#define echoPin 8

long duration;
long distance;

void setup()
{
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop()
{
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);

  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH, 1000);

  distance = duration/58.2;

  CDC.printf("%l cm\n", distance);

  delay(50);
}

And the compiler returns me:

Code:
/home/flaco/prog/X.4r912/linux/p32/bin/../lib/gcc/mips-elf/4.5.2/../../../../mips-elf/bin/ld: address 0x9d008394 of /home/flaco/prog/X.4r912/source/main32.elf section `.text' is not within region `kseg0_program_mem'

/home/flaco/prog/X.4r912/linux/p32/bin/../lib/gcc/mips-elf/4.5.2/../../../../mips-elf/bin/ld: /home/flaco/prog/X.4r912/source/main32.elf section `.rodata' will not fit in region `kseg0_program_mem'

/home/flaco/prog/X.4r912/linux/p32/bin/../lib/gcc/mips-elf/4.5.2/../../../../mips-elf/bin/ld: address 0x9d008394 of /home/flaco/prog/X.4r912/source/main32.elf section `.text' is not within region `kseg0_program_mem'

/home/flaco/prog/X.4r912/linux/p32/bin/../lib/gcc/mips-elf/4.5.2/../../../../mips-elf/bin/ld: region `kseg0_program_mem' overflowed by 1572 bytes

collect2: ld returned 1 exit status

/home/flaco/prog/X.4r912/source/Makefile32.linux:128: recipe for target 'link' failed

I have tried to compile this code by changing the board in the settings and I had no problems (with the Emperor 460).
Is my MX220 not powerful enough or something for this little code?

Note that the code is compiling if I comment the CDC.printf("%l\n", distance); line.

Thanks :)
CDC library includes printf library but CDC on one side and printf on the other side are both quite big libraries that use a lot of RAM. So yes, it's probably the origin of the problem.
Possible solutions :
#1 - use Serial instead of CDC
#2 - try to rewrite CDC.print (CDCprint in p32/include/pinguino/core/__cdc.c) without any call to CDCprintf and place some #define in the usb.pdl32 file to use them in __cdc.c in order to not systematically include the printf library in the CDC one (Am I clear Undecided ?) :

in usb.pdl32 :
CDC.printf CDCprintf#include <__cdc.c>#define __CDCPRINTF__

in __cdc.c :

#if defined(__CDCPRINTF__)
#include <printf.c>
#endif

...

#if defined(__CDCPRINTF__)
void CDCprintf(const u8 *fmt, ...)
{
...
}
#endif
But isn't it ROM that's overflowing?

I'm struggling to see how a chip with so much ROM & RAM can be too small.

John
Hello guys, thanks again for the assistance.

I'm actually trying your first option, Régis; and I've got a strange issue.
No /dev/ttyACM0 is created (I have waited around 3 - 4 minutes) when I use a Serial.*() function.

Here's my code:

Code:
void setup() {
    //run once:
    Serial.begin(9600);
    }

void loop() {
    //run repeatedly:
    Serial.printf("Hello\n");
    delay(200);
    Serial.println("Hello2\n");
    delay(200);
    Serial.print("Hello3\n");
    delay(200);
    }

I don't understand what could go wrong here.
I found nothing in the Arduino language documentation or on the world wide web.

Can you help me?

Thanks guys,
Flaco

EDIT: Also; I don't understand the second option, Régis. I mean, yes, rewriting a lib's source but I don't understand the explanation.
(04-11-2013, 08:12 PM)FlacoDev Wrote: [ -> ]I'm actually trying your first option, Régis; and I've got a strange issue.
No /dev/ttyACM0 is created (I have waited around 3 - 4 minutes) when I use a Serial.*() function.

Serial is not USB CDC. USB CDC uses /dev/ttyACM0 and Serial uses /dev/ttyS0, /dev/ttyS1, etc., depending on the port you use.
I would recommend to use minicom for both CDC and Serial. See Here.

Quote: Also; I don't understand the second option, Régis. I mean, yes, rewriting a lib's source but I don't understand the explanation.

CDCprint is based on CDCprintf which use printf library which is quite big. So you have to rewrite CDCprint function without any call to printf. But printf is automatically included in the code, so you will have to add some #define in pinguino.pdl32 to load printf library only if CDCprintf is used.
(04-11-2013, 08:12 PM)FlacoDev Wrote: [ -> ]EDIT: Also; I don't understand the second option, Régis. I mean, yes, rewriting a lib's source but I don't understand the explanation.

I think he means like this( i think i have the latest version of it?)
*by the way, Regis... You're a star, mate ! Pinguino owes a lot to you , man !

usb.pdl32@ p32/pdl

Code:
CDC.init init_CDC#include <__cdc.c>
CDC.puts CDCputs#include <__cdc.c>
CDC.write CDCwrite#include <__cdc.c>
CDC.print CDCprint#include <__cdc.c>
CDC.println CDCprintln#include <__cdc.c>
CDC.printf CDCprintf#include <__cdc.c>#define __CDCPRINTF__
CDC.read CDCgets#include <__cdc.c>
CDC.getKey CDCgetkey#include <__cdc.c>
CDC.getString CDCgetstring#include <__cdc.c>

_cdc.c @p32/include/pinguino/core

Code:
// cdc module for Pinguino32X
// Jean-Pierre Mandon 2010
// Based on the Microchip USB stack
// printf, println, print, write, getKey, getString - Régis Blanchot 2011

// 25 Feb. 2012 added support for 32MX220F032 jp.mandon
// 03 Mar. 2012 fixed a bug in WINDOWS CDC jp.mandon

#ifndef __USBCDC
#define __USBCDC

#include <stdarg.h>

#include <typedef.h>
#include <system.c>
#include <interrupt.c>
#include <delay.c>
#if defined(__CDCPRINTF__)
#include <printf.c>
#endif

extern void USBCheckCDCRequest();
extern void CDCInitEP();
extern void USBTask();
extern void USBDeviceInit();
extern void USBDeviceAttach();
extern void putUSBUSART(char*, char);
extern char getsUSBUSART(char*, char);
extern void CDCTxService();
extern unsigned char cdc_trf_state;

#define mUSBUSARTIsTxTrfReady() (cdc_trf_state==0)

typedef enum
{
    EVENT_NONE = 0,
    EVENT_DEVICE_STACK_BASE = 1,
    EVENT_HOST_STACK_BASE = 100,
    EVENT_HUB_ATTACH,          
    EVENT_STALL,                  
    EVENT_VBUS_SES_REQUEST,    
    EVENT_VBUS_OVERCURRENT,    
    EVENT_VBUS_REQUEST_POWER,  
    EVENT_VBUS_RELEASE_POWER,  
    EVENT_VBUS_POWER_AVAILABLE,
    EVENT_UNSUPPORTED_DEVICE,  
    EVENT_CANNOT_ENUMERATE,    
    EVENT_CLIENT_INIT_ERROR,    
    EVENT_OUT_OF_MEMORY,        
    EVENT_UNSPECIFIED_ERROR,    
    EVENT_DETACH,
    EVENT_TRANSFER,
    EVENT_SOF,                  
    EVENT_RESUME,
    EVENT_SUSPEND,
    EVENT_RESET,  
    EVENT_DATA_ISOC_READ,
    EVENT_DATA_ISOC_WRITE,
    EVENT_GENERIC_BASE  = 400,
    EVENT_MSD_BASE      = 500,
    EVENT_HID_BASE      = 600,
    EVENT_PRINTER_BASE  = 700,
    EVENT_CDC_BASE      = 800,
    EVENT_CHARGER_BASE  = 900,
    EVENT_AUDIO_BASE    = 1000,
    EVENT_USER_BASE     = 10000,
    EVENT_BUS_ERROR     = 2^31-1
} USB_EVENT;

typedef enum
{
    EVENT_CONFIGURED = EVENT_DEVICE_STACK_BASE,
    EVENT_SET_DESCRIPTOR,
    EVENT_EP0_REQUEST,
    EVENT_ATTACH,
    EVENT_TRANSFER_TERMINATED
} USB_DEVICE_STACK_EVENTS;

// this function is here to insure compatibility between USB microchip
// stack and Pinguino interrupt code

void INTEnableSystemMultiVectoredInt()
{
    IntConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
}

// this function is here to insure compatibility between USB microchip
// stack and Pinguino interrupt code

void INTEnableInterrupts()
{
    IntEnable(INT_USB);
}

#if defined(__32MX220F032D__)||defined(__32MX250F128B__)||defined(__32MX220F032B__)
// nothing to do
#else

// this is the Set Line coding CallBack function

void mySetLineCodingHandler()
{
/*
    //If the request is not in a valid range
    if(cdc_notice.GetLineCoding.dwDTERate.Val > 115200)
    {
        //NOTE: There are two ways that an unsupported baud rate could be
        //handled.  The first is just to ignore the request and don't change
        //the values.  That is what is currently implemented in this function.
        //The second possible method is to stall the STATUS stage of the request.
        //STALLing the STATUS stage will cause an exception to be thrown in the
        //requesting application.  Some programs, like HyperTerminal, handle the
        //exception properly and give a pop-up box indicating that the request
        //settings are not valid.  Any application that does not handle the
        //exception correctly will likely crash when this requiest fails.  For
        //the sake of example the code required to STALL the status stage of the
        //request is provided below.  It has been left out so that this demo
        //does not cause applications without the required exception handling
        //to crash.
        //---------------------------------------
        //USBStallEndpoint(0,1);
    }
    else
    {
        u32 dwBaud;

        //Update the baudrate info in the CDC driver
        CDCSetBaudRate(cdc_notice.GetLineCoding.dwDTERate.Val);

        //Update the baudrate of the UART
        U2BRG = ((GetPeripheralClock()+(BRG_DIV2/2*line_coding.dwDTERate.Val))/BRG_DIV2/line_coding.dwDTERate.Val-1);
        //U2MODE = 0;
        U2MODEbits.BRGH = BRGH2;
        //U2STA = 0;
    }
*/
}

// this is the USB Event CallBack function

void USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event_usb)
{
    switch(event_usb)
    {
        case EVENT_EP0_REQUEST:
            USBCheckCDCRequest();
            break;
        case EVENT_CONFIGURED:
            CDCInitEP();
            break;
    }
}

#endif /* not __32MX220F032D__ */

// this function is called by the main32.c file
// CDC.init
void CDC_init()
{
    USBDeviceInit();        // Initializes USB module SFRs and firmware
    #if defined(__32MX220F032D__)||defined(__32MX250F128B__)||defined(__32MX220F032B__)
        // nothing to do
    #else
        USBDeviceAttach();
    #endif
    Delayms(1500);
}

// CDC.puts
// 18-05-2011 modified by régis blanchot
void CDCputs(u8 *buffer, u8 length)
{
    u16 i;
    for (i = 1000; i > 0; --i)
    {
        if (mUSBUSARTIsTxTrfReady())
            break;
        #if defined(__32MX220F032D__)||defined(__32MX250F128B__)||defined(__32MX220F032B__)
            USB_Service();
        #else
            CDCTxService();
        #endif
    }
    if (i > 0)
    {
        putUSBUSART(buffer,length);
        #if defined(__32MX220F032D__)||defined(__32MX250F128B__)||defined(__32MX220F032B__)
            USB_Service();
        #else
            CDCTxService();
        #endif
    }
}
    
// CDC.read
u8 CDCgets(u8 *buffer)
{
    u8 numBytesRead;
        
    #if defined(__32MX220F032D__)||defined(__32MX250F128B__)||defined(__32MX220F032B__)
        USB_Service();
        numBytesRead = USB_Service_CDC_GetString( buffer );
    #else
        CDCTxService();
        numBytesRead = getsUSBUSART(buffer, 64);
    #endif
        return numBytesRead;
/*
    if (mUSBUSARTIsTxTrfReady())
    {
        CDCTxService();
        numBytesRead = getsUSBUSART(buffer, 64);
        CDCTxService();
        return numBytesRead;
    }
*/
}

// added by regis blanchot 29/05/2011
// ---------------------------------------------------------------------

// CDC.write
void CDCwrite(u8 c)
{
//    CDCputs(c, 1);
    CDCputs(&c, 1);
}
#if defined(__CDCPRINTF__)
// CDC.printf
void CDCprintf(const u8 *fmt, ...)
{
    u8 buffer[80];
    //char *buffer;
    u8 length;
    va_list    args;

    va_start(args, fmt);
    //length = strlen(fmt);
    //buffer = (char *) malloc(1 + length * sizeof(char));    
    length = psprintf2(buffer, fmt, args);
    CDCputs(buffer,length);
    va_end(args);
}
#endif
// CDC.print
// last is a string (char *) or an integer

void CDCprint(const u8 *fmt, ...)
{
    u8 s;
    va_list args;                            // a list of arguments
    va_start(args, fmt);                    // initialize the list
    s = (u8) va_arg(args, u32);                // get the first variable arg.
    
    //switch (*args)
    switch (s)
    {
        case FLOAT:
            CDCprintf("%f", (u32)fmt);
            break;
        case DEC:
            CDCprintf("%d", (u32)fmt);
            break;
        case HEX:
            CDCprintf("%x", (u32)fmt);
            break;
        case BYTE:
            //CDCprintf("%d", (u8)fmt);
            CDCprintf("%d", (u32)fmt);
            break;
        case OCT:
            CDCprintf("%o", (u32)fmt);
            break;
        case BIN:
            CDCprintf("%b", (u32)fmt);
            break;          
        default:
            CDCprintf(fmt);
            break;
    }
    va_end(args);
}

// CDC.println
void CDCprintln(const u8 *fmt, ...)
{
    va_list args;                            // a list of arguments
    va_start(args, fmt);                    // initialize the list

    CDCprintf(fmt, args);
    CDCprintf("\n\r");
    //CDCprintf(fmt);
    //CDCprintf("\n\r");
}

// CDC.getKey
char CDCgetkey()
{
    u8 buffer[64];        // always get a full packet

    while (!CDCgets(buffer));
    return (buffer[0]);    // return only the first character
}

// CDC.getString
char * CDCgetstring(void)
{
    u8 c, i = 0;
    static u8 buffer[80];
    
    do {
        c = CDCgetkey();
        CDCprintf("%c", c);
        buffer[i++] = c;
    } while (c != '\r');
    buffer[i] = '\0';
    return buffer;
}

#endif    /* __USBCDC */
Thank you guys!

I will take a look at Minicom. Smile
Hello guys, sorry for the double post (I wanted to bump so instead of editing and then bumping I just double post...)

I have edited the files (like iyahdub did) but the problem is that the function CDCprint() implicitely uses CDCprintf() so, unless I call CDC.printf(), I can't use CDCprint() or CDCprintln(). ^^
And if I use CDC.printf() I have the same problem as earlier.

Should I give up the "print the distance in a terminal" idea ? (it was just for tests, after all).
I'm gonna take a look at the documentation but, well, I had fun with LEDs instead. Smile

Flaco

EDIT: after re-reading your answer, regis, I understand what you said but how could I re-write CDCprint() without CDCprintf() ?
Time to read some more code. Big Grin
EDIT²: I tried writing a substitute pprint() function in __cdc.c but I'm gonna have to re-write a substitute pprints(), pprintc(), etc...
Isn't it gonna be too heavy as well?

I'll try tomorrow! Smile
(06-11-2013, 05:10 AM)FlacoDev Wrote: [ -> ]I tried writing a substitute pprint() function in __cdc.c but I'm gonna have to re-write a substitute pprints(), pprintc(), etc...
Take a look at liblcd.c and you won't have to reinvent the wheel.
The best would be to write an apart library with print, printFloat, printNumber, ... that could be used with lcdlib.c, __cdc.c, serial.c, etc ...
I took a look at output.map and so on.

The chip has 32K flash but under Pinguino only 13.5K is for the user program and much of that is used by support code (ISR wrappers, printf etc).

The other 18.5K looks to be the bootloader and ... I'm unsure what else. Is there a full list please? Or, how do I find it?

4K of the 18.5K is exception_mem but can that be dropped/reduced - what is it / which file(s) is it created from?

John
Pages: 1 2