converting function pointers to/from object pointers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello experts,

I have some old code, which worked fine with old GCC releases, but
fails with current GCC.

With current GCC, I get a warning:

    "ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]"

and the system crashes.

I understand that converting function pointers to object pointers (and
vice versa) is highly non-portable, because there's no guarranty that
the different pointer types would have the same amount of bits and might
even resice on different busses (e.g. harvard architecture)

In this application (68332) though, only one bus exists and all the
pointers are of the same size (32 bits).


The purpose of the code in question  is to upgrade flash chips in an
embedded envoronment. During the upgrade process, code can not be executed
from the flash. Therefore the upgrade code is copied to RAM and executed
from there. For this, conversions/calculations need to be done on those
pointers.


Below, I have appended a rough outline of the code.

The question is now, what would be the proper way to copy the code to the RAM
and run it from there?


Any suggestions? Thanks in advance!


Here's the outline of the code:



/* Since the flash can't be read during erase/programming operation, we need
   to copy the relevant stuff into RAM to execute it from there. Note that
   the copied code needs to be PIC. In addition, the copy of the PIC-code
   can't access static variables, therefore we hold everything in automatic
   variables on the stack.

   To find out which ROM areas need to be copied, we define two symbols:
   clone_region_start() and clone_region_end(). All the functions between
   those two
   symbols need to be copied to RAM and executed from there.

   clone_region_start() and clone_region_end() are NOOP's. They exist only to
   find out the memory area which needs to be copied and to calculate the
   offsets which are needed to calculate the addresses of the function clones.
*/


/* Define a symbol to mark the start of the code region we need to copy.
 */
static void clone_region_start (void)
{
}

/* The following set of functions need to be executed from RAM
 */

static unsigned int read_id_op (chip_t *c, unsigned short *pos)
{ /* ... */ }

static void erase_op (chip_t *c, unsigned short *pos, int cnt)
{ /* ... */ }

static int prog_op (chip_t *c, unsigned short *pos, int cnt,
                    unsigned short *contents,)
{ /* ... */ }

static void flash_op (chip_t *c, unsigned shor *pos, int cnt,
                      unsigned short *contents)
{
    if (!(read_id_op (c, pos) == XXXXX)) return;

    erase_op (c, pos, cnt);
    prog_op (c, pos, cnt, contents);

    /* When the caller function was reprogrammed, we can't expect to return
       properly. So it is better to wait for watchdog to give us a hardware
       reset.
    */
    while (1)
        ;
}

/* Define a symbol to mark the end of the code region we need to copy.
 */
static void clone_region_end (void)
{
}



/* This is the external interface for the flash driver.
 */
void flash_upgrade (chip_t *chip, unsigned short *pos, int cnt,
                    unsigned short *contents)
{
    unsigned short clone[600]; /* 1200 bytes for RAM-copy */

    /* Calculate code length and offsets for functions we need to copy/call
     */
    int code_length = ((char *)clone_region_end) - ((char *)clone_region_start);
    int flash_offset   = ((short *)flash_op)   - ((short *)clone_region_start);
    int read_id_offset = ((short *)read_id_op) - ((short *)clone_region_start);

    /* Calculate function pointers to the copies of the functions
     */
    ((void(*) (chip_t *, unsigned short *)))
        read_id_clone = clone + read_id_offset;

    ((void(*) (chip_t *, unsigned short *, int *, unsigned short *)))
        flash_clone = clone + flash_offset;


    /* Make sure we detect insufficient memory size in integration test
     */
    if (code_length>sizeof(clone))
        halt_system (1, "required clone memory: %d\r\n", code_length);

    /* Copy the flash functions to RAM
     */
    memcpy (clone, (void*)clone_region_start, code_length);

    /* Disable Interrupts
     */
    set_ipl (7);

    /* Configure chip select for write enable pin
     */
    *((unsigned long *)SIM_CSBARBT)=0x000067830;

    /* now call the clone of the flash_op() function.
       This function will return only if the flash chip could not be
       identified.
     */
    flash_clone (c, pos, cnt, contents);
}

-- 
Josef Wolf
jw@xxxxxxxxxxxxx



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux