Search code examples
ccortex-mpsoc

Trying to understand how *ramVectorTable gets to ramVectorTable[ ]


I'm trying to understand what this code actually does. Specifically the part after declaring and initializing the pointer ramVectorTable confuses me the most.

It is about function that sets the interrupt vector of the specified system interrupt number. It's for cypress's PsoC 5 that has ARM Cortex M3 if this helps somehow.

#define CY_INT_VECT_TABLE ((cyisraddress **) 0xe000ed08u)


typedef void (* cyisraddress)(void);


cyisraddress CyIntSetSysVector(uint8 number, cyisraddress address)
    {
        cyisraddress oldIsr;
        cyisraddress *ramVectorTable = *CY_INT_VECT_TABLE;

 /* Save old Interrupt service routine. */
        oldIsr = ramVectorTable[number & CY_INT_SYS_NUMBER_MASK];

        /* Set new Interrupt service routine. */
        ramVectorTable[number & CY_INT_SYS_NUMBER_MASK] = address;

        return (oldIsr);
    }


Solution

  • It can be understood as follows:

    cyisraddress is a function pointer (a pointer to a function). Here it has the form of a function taking no argument (void) and returning nothing (void). Since this is on ARM Cortex-M3, a pointer shall be a 4-byte value, e.g. 0x20010004. This 4-byte value is the location of the function in memory, i.e. the address of its first instruction. Here, oldIsrand address point to the existing and new ISRs (Interrupt Service Routine) respectively.

    In this line #define CY_INT_VECT_TABLE ((cyisraddress **) 0xe000ed08u), 0xe000ed08u is specified to have the type of cyisraddress **, which means pointer to a pointer to a function pointer. Note that 0xe000ed08u is the address of the register VTOR (Vector Table Offset Register), which stores the offset of the vector table base address from memory address 0x00000000 (reference)

    When they use *CY_INT_VECT_TABLE, it means the value stored at address 0xe000ed08, which effectively is the address of the vector table. This value has a type of pointer to a function pointer.

    Now is the interesting part. For cyisraddress *ramVectorTable, the type of ramVectorTable is a pointer to a function pointer. When reading the code further, you will notice that they use ramVectorTable as an array, which is similar to this simpler version:

    int a[10];
    

    Then you can use either a[i] (a as an array of integers) or *(a+i) (a as a pointer to an integer) to access the array elements.

    Therefore, ramVectorTable can be used as an array of function pointer, thus ramVectorTable[number & CY_INT_SYS_NUMBER_MASK] is just *(ramVectorTable + number & CY_INT_SYS_NUMBER_MASK), this value has the type of cyisraddress (function pointer).

    Lastly, the vector table can be thought of as an array of function pointers, thus ramVectorTable is simply an array of pointers to an ISR.