This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

May functions return an union?

Is it possible for a function to return a union?

Storing data in the Flash/EEData memory of the ADuC845, is done through operating some SFR registers and page write.
I would like to read and write different kind of variables and wounder if its possible to use the same function.

Example:
// EEData page address
#define SERIAL_NO 0x0000
#define DEV_ADR 0x0010

unsigned long serial_no = 123456789;
unsigned int dev_adr = 255;

void main (void) {
// saving data
write(serial_no, SERIAL_NO);
write(dev_adr, DEV_ADR);
// reading data
serial_no = read(SERIAL_NO);
dev_adr = read(DEV_ADR);
}

My idea was something like this:

union u {
unsigned int ival;
unsigned long lval;
}

void write(union u data, long adr) {
// save data in EEData at address long
}

union u read(long adr) {
// read data from EEData
// and return (???)
}

Is it possible to do it this way or perhaps a solution would be the use of pointers but how?

Any suggestions?

  • union u {
    unsigned int ival;
    unsigned long lval;
    }

    I do return a union like this by returning u.lval

    I doubt you can return a union any longer than a long.

    Erik

  • "... or perhaps a solution would be the use of pointers but how?"

    A more conventional interface is for the read/write routines to deal with data objects of arbitrary size.

    #define SERIAL_NO  0x0000
    #define DEV_ADR    0x0010
    
    unsigned long  serial_no = 123456789;
    unsigned int   dev_adr   = 255;
    
    void write(unsigned ee_addr, void *p_data, size_t size) {
    }
    
    void read(unsigned ee_addr, void *p_data, size_t size) {
    }
    
    void main (void) {
        write(SERIAL_NO, &serial_no, sizeof serial_no);
        write(DEV_ADR, &dev_adr, sizeof dev_addr);
        read(SERIAL_NO, &serial_no, sizeof serial_no);
        read(DEV_ADR, &dev_adr, sizeof dev_addr);
    }
    

  • You can do like the malloc() family: use void* to pass a pointer to the data object, and a unsigned char to pass the size of the object. The use of void pointers is a powerful means of building polymorphic functions. You then pass the actual size of the data object using the sizeof() compiler macro.

    You could do it like this:

    unsigned char xdata user_data[1024];    // simulates xdata mapped space
    
    void write_xeeprom(void xdata *src, unsigned int addr, unsigned char sz)
    {
        // do your thing here
        // e.g., to access *src as bytes, cast it to char:
    
        unsigned char xdata *dst;           // ptr to the xdata array
    
        dst = &user_data[addr];             // addressed relative to the array start
        do
        {
            *dst++ = *((unsigned char xdata*)src)++;
        } while(--sz);
    }
    
    
    void main(void)
    {
        unsigned long lvar;
        unsigned int ivar;
    
        lvar = 0x12345678;
        ivar = 0xabcd;
    
        write_xeeprom(&lvar, 0x0000, sizeof(lvar));
        write_xeeprom(&ivar, 0x0008, sizeof(ivar));
    }
    


    Please note that the above exampleware has a few optimizations:
    1) The pointer passed is for xdata memory, instead of a generic pointer. Passing generic pointers to functions has a very high cost. If a generic ptr is used, the parameters will be passed in global vars, instead of in registers. You may decide that you want the generic version, or you may have one function for each memory type. I always use the second alternative.
    2) The do{}while() loop assumes nonzero size, and optimize to a single DJNZ instruction.
    3) Look at the pointer cast used to get single bytes from the passed ptr. This is where you make the void ptr to become what you want (char* in this case).

    The read() can be done similarly, with the very same prototype and concept.

    The beauty of this method is that you are not limited to scalar types, but you can write and read whole structures with the same simple interface as you do for chars.

  • I see that Dan offered a suggestion similar to mine. We were posting simultaneously, and I couldn't see his post, sorry about that :P

  • Thanks everyone for your reply.

    I really appreciate your time and effort in helping others.

    Regards

    Peter Bøgely