6

I have been trying to run the following code:

void reset();

int board[8][8];
int i,switcher,j,k;

void main() {
    TRISB = 0X00;
    TRISD = 0X00;
    TRISC = 0X00;
    reset();
    ADCON1 = 0X06;
    TRISA =0X11;
    while(1)
    {
        for( i=0;i<16;i++)
        {
            switcher = i;
            PORTB.F0  = switcher%2;
            switcher /= 2;
            PORTB.F1 = switcher%2;
            switcher /= 2;
            PORTB.F2 = switcher%2;
            switcher /= 2;
            PORTB.F3 = switcher%2 ;
            if (!PORTA.F0 == board[i/8][i%8])
                break;
            delay_ms(1000);
       }
       switcher = i;
       PORTC.F0   =  switcher%2;
       switcher /= 2;
       PORTC.F1 = switcher%2;
       switcher /= 2;
       PORTC.F2 = switcher%2;
       switcher /= 2;
       PORTC.F3 = switcher%2 ;
       switcher /= 2;
       PORTC.F4 = switcher%2;
       switcher /= 2;
       PORTC.F5 = switcher%2 ;
       break;
   }
}

void reset()
{
    PORTB = 0;
    PORTD = 0;
    PORTC= 0;
}

On running this code, it's showing

"Not enough RAM" error.

However on running this code :

void reset();

int board[80][80];

void main() {
    TRISB = 0X00;
    TRISD = 0X00;
    TRISC = 0X00;
    reset();
    ADCON1 = 0X06;
    TRISA =0X11;
}

void reset()
{
    PORTB = 0;
    PORTD = 0;
    PORTC= 0;
}

It runs successfully with no errors (Note that I am creating a multidimensional array of 80x80 whereas for the previous one it's only 8x8). Can someone help me in identifying the cause for the problem? And if possible then also the proper solution for the problem ?

Mike
  • 2,146
  • 1
  • 14
  • 29
ferty567
  • 73
  • 3
  • 5
    Your array presumably uses more memory than the chip has. In the second case, you never actually use it, so it is dropped by the compiler and there is no issue. – Chris Stratton Sep 09 '19 at 15:01
  • 2
    You have probably chosen the wrong part for a task approached in this way, but you should also be using a bitmap not a full `int` (which is likely 2 or even 4 bytes) to store what appears to be a binary value. – Chris Stratton Sep 09 '19 at 15:03
  • 1
    I have tried using uint8_t for declaring variables instead of int , which i assume should only take around 100 bytes for the program . But still it is showing the same error. – ferty567 Sep 09 '19 at 15:23
  • 2
    That's still using 8 bits to store only one. And there may be other reservations taking memory beyond just your array. – Chris Stratton Sep 09 '19 at 15:33
  • Ok Chris i will try. Thank you for your reply. – ferty567 Sep 09 '19 at 15:35

1 Answers1

14

The PIC16f877a only has 368 bytes of memory, meaning that the 8x8 array is already in danger of exhausting available memory (either 128 or 256 bytes depending on sizeof(int)) given a requirement for other structures (other symbols, stack, etc).

However, in the second program, your compiler recognizes that you do not access the 80x80 array in any way, and thus optimizes it out. As a result, the linker doesn't need to find space for a variable of size 80*80*sizeof(int) bytes and the program is successfully compiled and linked.

Presumably, you are only using each element of the array for a single boolean value--in that case you can reduce your space requirements to 64 bytes of space by packing the data more efficiently. This answer describes one way to do this, where bitwise operations are used to index into an array of uint8_t values. Alternatively, you could try using your existing technique (2D integer array) with a uint8_t[8][8] to avoid making larger code changes, but this remains wasteful of memory (8x waste).

nanofarad
  • 18,062
  • 2
  • 47
  • 73
  • Thanks a lot for your quick reply! Can you please recommend a good micro-controller having a decent RAM ? – ferty567 Sep 09 '19 at 15:05
  • @ferty567 I'd start by seeing if you can make do with what you have given the advice and link at the end; past that I don't really have a clear favorite (and product recommendations are a bit off-topic for this site) but I've been using the atmega328p as a generic microcontroller for small projects where I don't have a specific requirement that it can't handle. It's available in a DIP package and has 2 KB of RAM; I'm certain that if you needed even more you could shop around for a specific uC with a suitable amount. – nanofarad Sep 09 '19 at 15:07
  • The reason I used a PIC16F577a because it is having 40 pins . Whereas Atmega328p is only having 28 pins . Can you please suggest me a micro-controller having pins comparable to 40 or a way to increase the number of operable pins in Atmega328p ? – ferty567 Sep 09 '19 at 15:16
  • 1
    @ferty567 Unfortunately high pin counts are often incompatible with DIP packages due to cost/market reasons--almost all uCs with 1K or RAM and 40 I/Os are [SMT nowadays](https://www.digikey.com/products/en/integrated-circuits-ics/embedded-microcontrollers/685). If you really need to use DIP packages and can handle the higher latency you could consider an I/O expander such as one or more [MCP23017/MCP23s17](http://ww1.microchip.com/downloads/en/devicedoc/20001952c.pdf) units, which provide 16 I/Os per chip. You will need to use SPI or I2C in this case. – nanofarad Sep 09 '19 at 15:23
  • 2
    Thanks for your replies . Hope you keep helping like this. :) – ferty567 Sep 09 '19 at 15:29
  • ATMEGA1284P-PU-ND is a 40 pin DIP with 16K of RAM, that said, there's hardly any reason to use DIPs any more except for breadboarding, and little reason to breadboard large projects. – Chris Stratton Sep 09 '19 at 15:31
  • @ChrisStratton Thanks, I missed that one in my search (I think I queried for 40 I/Os after subtracting dedicated power/ground/clock pins) – nanofarad Sep 09 '19 at 15:41
  • _"The PIC16f877a only has 368 bytes of memory, meaning that both the 8x8 and the 80x80 int arrays cannot be placed into memory (assuming that an int is at least two bytes)."_ - 8x8x2 = 128 bytes, and 8x8x4 = 256 bytes, both below the 368 byte limit. Of course, there's probably more in memory, but you can't conclude the 8x8 array can't be placed in memory just from that array alone. – marcelm Sep 09 '19 at 16:14
  • @marcelm D'oh, I multiplied wrong. I'll revise now. – nanofarad Sep 09 '19 at 18:09
  • He can get away with simply changing int to uint8_t. That's 64 bytes, so there will be some space left for other stuff. I don't know PIC types that well, but there are ARM based uCs and dev boards with plenty of computing power, memory, and pins at a reasonable price. E.g. check the so called "blue pill" board (STM32F103T8C6), around $1.5, 72 MHz, 32 bits, 20kB RAM, 64 or 128kB ROM. – Nyos Sep 10 '19 at 08:53
  • @Nyos OP, in a comment on the question, mentioned that even `uint8_t[8][8]` didn't fit. I'll present both, but I think that using a proper bitfield is still recommended – nanofarad Sep 10 '19 at 13:33