Passing 2D array to a function - Hard Falt when reading it

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Passing 2D array to a function - Hard Falt when reading it

Jump to solution
827 Views
anthonyduhamel
NXP Employee
NXP Employee

Hello,

I'm coding on a KL46Z Mcu, using CW10.6/PEx IDE plus MQXLite and I have some troubles with double pointer accesses. In fact I'm passing a 2D array to a function. When I read the double pointer value, there is a Cpu Hard Fault.

Basically my function is:

vMyClass_MyFunction(int16_t** __aai16_Buffer,uint8_t __u8_BufferLength)

{

     int16_t __i16_test;

     uint16_t __u16_i;

     for(__u16_i=0;__u16_i<__u8_BufferLength ;__u16_i++)

       {

               //__i16_test= __aai16_Buffer[0][__u16_i];  // Hardfault when uncommented

               if(  __aai16_Buffer[0][__u16_i]!=0 && __aai16_Buffer[1][__u16_i]!=0) // hard fault here

               {

                    // do something

               }

        }  

}

Called by:

static int16_t _aai16_globalBuffer[2][100];

vMyClass_MyFunction(_aai16_globalBuffer, 100);

This function worked in an other project. Maybe there is an option to tick or enable to allow those kind of access in my project.

Does anybody have an answer to fix that?

Thanks!

Anthony

0 Kudos
1 Solution
612 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Anthony:

I think this is a coding issue. In your code the compiler does not interpret the parameter __aai16_Buffer as a "2D array", but as a "pointer to pointer", which is not the same thing. Then you would need to cast the pointer back to 2D array type.

So the function definition should be something like this:

void vMyClass_MyFunction(int16_t** __aai16_Buffer,uint8_t __u8_BufferLength)

{

    int16_t __i16_test;

    uint16_t __u16_i;

    for(__u16_i=0;__u16_i<__u8_BufferLength ;__u16_i++)

    {

        __i16_test= ((int16_t(*)[__u8_BufferLength])__aai16_Buffer)[0][__u16_i];

        if(((int16_t(*)[__u8_BufferLength])__aai16_Buffer)[0][__u16_i]!=0 && ((int16_t(*)[__u8_BufferLength])__aai16_Buffer)[1][__u16_i]!=0)

        {

            // do something

        }

    }

}

or this:

void vMyClass_MyFunction(int16_t** __aai16_Buffer,uint8_t __u8_BufferLength)

{

    int16_t __i16_test;

    uint16_t __u16_i;

    for(__u16_i=0;__u16_i<__u8_BufferLength ;__u16_i++)

    {

        __i16_test= (*((int16_t(*)[__u8_BufferLength])__aai16_Buffer+0))[__u16_i];

        if( (*((int16_t(*)[__u8_BufferLength])__aai16_Buffer+0))[__u16_i]!=0 && (*((int16_t(*)[__u8_BufferLength])__aai16_Buffer+1))[__u16_i]!=0)

        { 

            // do something

        }

    }

}

And even simpler if you use the correct parameter type instead of int16_t**, although this requires a fixed array size:

void vMyClass_MyFunction(int16_t __aai16_Buffer[][100],uint8_t __u8_BufferLength)

{

    int16_t __i16_test;

    uint16_t __u16_i;

    for(__u16_i=0;__u16_i<__u8_BufferLength ;__u16_i++)

    {

        __i16_test= __aai16_Buffer[0][__u16_i];

        if(__aai16_Buffer[0][__u16_i]!=0 && __aai16_Buffer[1][__u16_i]!=0)

        {

            break;

        }

    }

}

Regards!
Jorge Gonzalez

View solution in original post

0 Kudos
3 Replies
612 Views
anthonyduhamel
NXP Employee
NXP Employee

The strange thing is that I can read the 2D-array cell value by attacking directly the memory with pointers & casts.

__i16_test=*( ((int16_t*)__aai16_Buffer)+0*__u8_BufferLength+__u16_i);// equals to [0][i]

__i16_test=*( ((int16_t*)__aai16_Buffer)+1*__u8_BufferLength+__u16_i);// equals to [1][i]

.. without cpu Hard fault ....

Anthony

0 Kudos
613 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Anthony:

I think this is a coding issue. In your code the compiler does not interpret the parameter __aai16_Buffer as a "2D array", but as a "pointer to pointer", which is not the same thing. Then you would need to cast the pointer back to 2D array type.

So the function definition should be something like this:

void vMyClass_MyFunction(int16_t** __aai16_Buffer,uint8_t __u8_BufferLength)

{

    int16_t __i16_test;

    uint16_t __u16_i;

    for(__u16_i=0;__u16_i<__u8_BufferLength ;__u16_i++)

    {

        __i16_test= ((int16_t(*)[__u8_BufferLength])__aai16_Buffer)[0][__u16_i];

        if(((int16_t(*)[__u8_BufferLength])__aai16_Buffer)[0][__u16_i]!=0 && ((int16_t(*)[__u8_BufferLength])__aai16_Buffer)[1][__u16_i]!=0)

        {

            // do something

        }

    }

}

or this:

void vMyClass_MyFunction(int16_t** __aai16_Buffer,uint8_t __u8_BufferLength)

{

    int16_t __i16_test;

    uint16_t __u16_i;

    for(__u16_i=0;__u16_i<__u8_BufferLength ;__u16_i++)

    {

        __i16_test= (*((int16_t(*)[__u8_BufferLength])__aai16_Buffer+0))[__u16_i];

        if( (*((int16_t(*)[__u8_BufferLength])__aai16_Buffer+0))[__u16_i]!=0 && (*((int16_t(*)[__u8_BufferLength])__aai16_Buffer+1))[__u16_i]!=0)

        { 

            // do something

        }

    }

}

And even simpler if you use the correct parameter type instead of int16_t**, although this requires a fixed array size:

void vMyClass_MyFunction(int16_t __aai16_Buffer[][100],uint8_t __u8_BufferLength)

{

    int16_t __i16_test;

    uint16_t __u16_i;

    for(__u16_i=0;__u16_i<__u8_BufferLength ;__u16_i++)

    {

        __i16_test= __aai16_Buffer[0][__u16_i];

        if(__aai16_Buffer[0][__u16_i]!=0 && __aai16_Buffer[1][__u16_i]!=0)

        {

            break;

        }

    }

}

Regards!
Jorge Gonzalez

0 Kudos
612 Views
anthonyduhamel
NXP Employee
NXP Employee

Thanks for your answer Jorge. It makes sense that the compiler can not interpret the 2D array because it does not know the size of the array of array.

The last option is more legible, but it assumes fixed array size..

By the way,  all methods work. And mine too.

Thanks again.

Anthony

0 Kudos