1
\$\begingroup\$

I'm using a Microchip PIC16F1825 with the XC8 (v1.12) compiler and defining some arrays (size between 16 and 64 bytes). I was able to declare them (linker output below). However, as soon as I try to access a few of them in a for-loop, I get an error on build:

error: could not find space (32 bytes) for variable _tempMeasurements
(908) exit status = 1

The more arrays I try to access the more Data Space usage goes up. How can I avoid running out of memory? Clearly, not all banks are used.

Memory Class Usage:

Program space:
    CONST                used     0h (     0) of  2000h words   (  0.0%)
    CODE                 used   B8Dh (  2957) of  2000h words   ( 36.1%)
    STRCODE              used     0h (     0) of  2000h words   (  0.0%)
    ENTRY                used     0h (     0) of  2000h words   (  0.0%)
    STRING               used     5h (     5) of  2000h words   (  0.1%)

Data space:
    COMMON               used     Eh (    14) of    10h bytes   ( 87.5%)
    BANK0                used    4Fh (    79) of    50h bytes   ( 98.8%)
    BANK1                used    4Eh (    78) of    50h bytes   ( 97.5%)
    BANK2                used    4Ah (    74) of    50h bytes   ( 92.5%)
    BANK3                used    50h (    80) of    50h bytes   (100.0%)
    BANK4                used    40h (    64) of    50h bytes   ( 80.0%)
    BANK5                used    40h (    64) of    50h bytes   ( 80.0%)
    BANK6                used    40h (    64) of    50h bytes   ( 80.0%)
    BANK7                used    40h (    64) of    50h bytes   ( 80.0%)
    BANK8                used     0h (     0) of    50h bytes   (  0.0%)
    BANK9                used     0h (     0) of    50h bytes   (  0.0%)
    BANK10               used     0h (     0) of    50h bytes   (  0.0%)
    BANK11               used     0h (     0) of    50h bytes   (  0.0%)
    BANK12               used     0h (     0) of    30h bytes   (  0.0%)
    ABS1                 used   16Ah (   362) of   400h bytes   ( 35.4%)

EEPROM space:
    EEDATA               used     0h (     0) of   100h bytes   (  0.0%)

Configuration bits:
    CONFIG               used     2h (     2) of     2h words   (100.0%)

ID Location space:
    IDLOC                used     0h (     0) of     4h words   (  0.0%)


Memory Summary:
    Program space        used   B92h (  2962) of  2000h words   ( 36.2%)
    Data space           used   3AFh (   943) of   400h bytes   ( 92.1%)
    EEPROM space         used     0h (     0) of   100h bytes   (  0.0%)
    Configuration bits   used     2h (     2) of     2h words   (100.0%)
    ID Location space    used     0h (     0) of     4h bytes   (  0.0%)
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Are these globals? Are they in the scope of main or some other function? Without seeing where you've declared them, it's hard to answer your question (hint: include your declaration and usage code, not just your linker output and error message) \$\endgroup\$ May 14 '13 at 17:25
  • \$\begingroup\$ Yes, they're globals. Sorry for forgetting to mention that. \$\endgroup\$
    – Norbert
    May 17 '13 at 7:34
2
\$\begingroup\$

Consecutive direct accesses to variables in the same bank will be faster than direct accesses to variables in different banks. Consequently, the compiler is probably trying to consolidate variables which are accessed near each other so they'll be placed in the same bank. Unfortunately, it may be attempting to consolidate more variables than will actually fit into a bank.

I'm not familiar with the particular compiler you're using; on some compilers, variables will only be consolidated if their primary (non-extern) definition is in the same source file. Moving some arrays to separately-compiled source files may prevent the compiler from trying to consolidate them. Alternatively, it may be helpful to have some arrays which are only accessed by routines that are used especially for that purpose. For example, have a source file that's something like:

static unsigned short foo[32];

unsigned short get_foo(unsigned char addr)
{
  return foo[addr];
}
void put_foo(unsigned char addr, unsigned short value)
{
  foo[addr] = value;
}

Note that if you use this approach, you may be able to work with arrays that are too large to fit in a single page, using something like:

static unsigned short foo0[32],foo1[32];

unsigned short get_foo(unsigned char addr)
{
  if (addr & 32)
    return foo0[addr];
  else
    return foo1[addr-32];
}
void put_foo(unsigned char addr, unsigned short value)
{
  if (addr & 32)
    foo0[addr] = value;
  else
    foo1[addr-32] = value;
}

Such things aren't beautiful, but they may save code compared to some of the other techniques that would otherwise be necessary.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.