NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » Need help with function pointers

April 08, 2010
by jban4us
jban4us's Avatar

I've been having a problem with indexing arrays of all kinds which I find very strange. If I have two arrays, say:

int array1[2] = {0,4};
int array2[6]={1,2,3,4,5,6};

and I do something like:

int b = array2[array1[1]];

the microcontroller constantly resets itself. I cannot for the life of me figure out why this doesn't work. For a more significant example, I have a function that does the following:

uint8_t program[2];
...
typedef uint16_t (*PROGRAM)(uint16_t, uint8_t, uint8_t, volatile bool*);
PROGRAM programs[12] = {
        sequentialRGB, sequentialR, sequentialG, sequentialB,
        NO_PROG,NO_PROG,NO_PROG,NO_PROG,
        NO_PROG,NO_PROG,NO_PROG,NO_PROG
};
...
int z = program[0];
bar1 = programs[z](bar1,beatTickCounter,currentFOB[0], &refreshNeeded);

And this also resets the controller repeatedly. This is very odd to me because when I instead call

bar1 = programs[0](bar1,beatTickCounter,currentFOB[0], &refreshNeeded);

everything works fine, and I am sure that the value of program[0] is 0, both because it's initially set as that and because I have the program print it twice, earlier in the execution, and then right before the problem line. Any insight would be greatly appreciated!

Thanks!

-Jared

April 09, 2010
by jban4us
jban4us's Avatar

Hey guys I think I figured this one out. It seems that the compiler was putting the function pointer array in PROGMEM instead of data memory. Then when I tried to dereference it, I was trying to dereference a pointer to program memory and it was crashing. It seems that the compiler was smart enough that when I told it to just try the 0 index, it would put that in data memory and everything would work.

This is my first time working with a Harvard architecture, I'm used to just throwing around pointers to anything and it just working ;)

Here is the solution in case it might be helpful to anyone else (sorry I called things variations of "program" it makes this all kinda confusing):

uint8_t program[2];
...
typedef uint16_t (*PROGRAM)(uint16_t, uint8_t, uint8_t, volatile bool*);
const PROGRAM PROGMEM programs[12] = {
    sequentialRGB, sequentialR, sequentialG, sequentialB,
    NO_PROG,NO_PROG,NO_PROG,NO_PROG,
    NO_PROG,NO_PROG,NO_PROG,NO_PROG
};
...

main() {
...
PROGRAM p;
memcpy_P( &p, &programs[program[0]], 2);  // get a copy of function pointer
bar1 = p(bar1,beatTickCounter,currentFOB[0], &refreshNeeded);  // call it
April 09, 2010
by bretm
bretm's Avatar

You figured part of it out. In your original code you didn't specify PROGMEM, so the array day would have been place in data memory instead, which is probably what you expected, but it may have failed because the "avr-copy" command in the makefile would need to include "-j .data" in order for the data segment to be included in the .hex file uploaded to the chip.

In your second posting you've added PROGMEM which puts the array data in program memory. The compiler wasn't doing that automatically before. But you have to be careful. It could be that the second example only works because you're still explicitly accessing program[0]. The compiler can optimize that so that it's not an array indexing operation and instead use a direct reference to the variable. So it might work with program[0] but not with program[i] or some other run-time-determine index.

Now that your array is decorated with PROGMEM, you'll want to use the pgm_read_word function to access the values in the array.

Post a Reply

Please log in to post a reply.

Did you know that binary numbers use base 2 to represent numbers, and these are important for understanding microcontroller registers? Learn more...