# Array manipulation in MCC18

Suppose I have an array:

#define ARRAY_SIZE 576
#pragma udata DATA
float I_1[ARRAY_SIZE]; //My huge array
#pragma udata


And that I access my array like so:

float compute()
{
float *I_1_ptr = &I_1[0];
//Somewhere in loop
I_1_ptr[i] = IL_1 - IO_1 * (exp(Q * V_1/ (NS * N * K * temperature)) - 1.0) - V_1/Rsh;
//Consider other variables constants.

return (I_1_ptr[0] + I_1_ptr[1] + I_1_ptr[2] + I_1_ptr[3]);
}


I've seen on search results on Google that Microchip prefer that one should access the array by pointing to it's first element using pointers.

Did I get this right, or how do I access my array I_1?

For some reason, my calculation doesn't work on my array and when I do division by zero, I get NaN.

Thanks.

-
A bit off-topic: Where did you read that pointers are to be prefered? All of my searches point that they should be avoided, but as far as I can see here due to length of the array they need to be used or i needs to be integer. If i isn't integer, you could have issues there because C18 won't do promote chars into higher types by default. – AndrejaKo May 20 '12 at 23:20
Also check if that #define ARRAY_SIZE 576 is actually using int there. You may need to add a suffix to make it int just in case. Another thing to consider would be break up the line where the I_1_ptr is calculated into several and check each with debugger to see what's exactly happening. – AndrejaKo May 20 '12 at 23:27
when I do division by zero, I get NaN. Yes, that's what is supposed to happen with the floats you are using. – davidcary May 21 '12 at 4:07
@AndrejaKo, see examples (electro-tech-online.com/microcontrollers/… or microchip.com/forums/m470067.aspx). I lost the link of the tutorial I saw. They use pointers to reference to the array. – Buhake Sindi May 21 '12 at 8:02
@davidcary, I know that. I'm trying to find out why there isn't values populated on my array. – Buhake Sindi May 21 '12 at 8:03

hunch

I suspect the problem is here:

#define ARRAY_SIZE 576
float I_1[ARRAY_SIZE]; //My huge array


Since each float uses 4 bytes and each double uses 8 bytes, this is allocating a single array that uses over 2 000 bytes of RAM.

The PIC18F4520 has 1 536 bytes of RAM -- not enough to store that entire array, much less that array plus all the other variables used in your program.

So you must

• upgrade to a bigger MCU with more on-chip RAM, or
• somehow attach some kind of off-chip RAM, or
• figure out a way to use less RAM (perhaps a smaller ARRAY_SIZE, or perhaps using some 16-bit or 8-bit data type that requires less RAM per item in the array, or perhaps somehow storing some of that data in FLASH, or ...)

or some combination of the above.

Many C programming language teachers spend a lot of time explaining that arrays can be accessed using pointers. Much like many chemistry teachers spend a lot of time explaining how molecules can be built up from individual atoms. Much like many physics teachers spend a lot of time explaining how atoms can be built up from individual protons and neutrons.

While doing it that way can be very educational, it's unnecessarily complicated and there's usually a simpler, better way of getting the desired end result. (There are cases where you need to use pointers, but this doesn't appear to be one of them).

An important skill in debugging is taking a program with a known bug and figuring out the exact step where things seem to go wrong.

It sounds like you think the problem is on line

I_1_ptr[i] = IL_1 - IO_1 * (exp(Q * V_1/ (NS * N * K * temperature)) - 1.0) - V_1/Rsh;


That line does many things. It's difficult for a single-step debugger to figure out exactly which thing is going wrong on such a complicated line. If I were having this problem, my first action would be to break that line into a bunch of smaller lines and then single-step through those smaller, simpler lines to narrow down where the problem is. Perhaps something like

float denominator;
float ratio;
float temp1;
float temp2;
//...
denominator = NS * N * K * temperature;
ratio = Q * V_1 / denominator;
temp_1 = exp(ratio) - 1.0;
temp_2 = IL_1 - IO_1 * temp_1 - V_1/Rsh;
I_1[i] = temp2; // normal array access -- pointers not necessary here.


and check that you're getting the expected values at each step. Which step is giving unexpected results?

An important skill in debugging is reducing a big program with a known bug to a very small program that exhibits the same bug.

Could you trim out the parts of your program before and after the line that does something unexpected -- perhaps by setting variables before that line to some constant value rather than going through long series of calculations -- to give us a very short, but complete program that gives the unexpected behavior?

-
 thanks, the problem is that when I "Watch" my I_1 array, MPLAB says "Restricted memory". Unless I know that there's data there, I can't watch it though. – Buhake Sindi May 21 '12 at 21:33 What happens when you reduce "ARRAY_SIZE" to a small number like "4" ? – davidcary May 21 '12 at 21:56 I still had "Restricted memory", I think it's because I had it on udata. Removing it out of udata helps (on small array size, but we need the large array). Alternatively, I can try and re-engineer the solution without array. :-) – Buhake Sindi May 22 '12 at 8:22

According to people on the internet a b c, normally when you use the ICD debugger, the compiler uses the special 'i' linker script to make sure that the RAM used by the debugger doesn't conflict with the RAM used by your program. You tell the compiler to do that by setting the Debug/Release pulldown on the IDE toolbar to "Debug"; and then rebuild and reprogram the chip.

If you have it set the wrong way (to "Release"), and then try to debug, you get a "Restricted memory" message.

"pointers"

p.s.: Elsewhere on the internet a b I see someone repeat the assertion that array access "must be done by pointers", followed by someone else saying normal array access works just fine with the MC C18 compiler -- no need to fiddle around with pointers.

I would stick to normal standard C array access unless I was forced to use a compiler that had some sort of bug that forced me to use a work-around. (I could imagine that an early version of that compiler might have had such a bug, but they fixed it years ago -- those old work-arounds are now obsolete and counter-productive).