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

struct pointing to RTC in far memory location.

I have a Real Time Clock (RTC) located at address 0x180000

I would like to create a struct of the RTC registers and map it to 0x180000 where the RTC registers start, located in far xdata memory or (HDATA).

I want to access the RTC such as

 RTC.Month = 8; 

Would I use the FVAR or far * in some way to accomplish this?

Thanks for your help..

  • I think that would be a reasonable thing to do, yes. Something like:

    #define RtcAddr  0x180000
    
    typedef struct
        {
        U16 year;
        U8 month;
        U8 day;
        } RtcReg;
    
    #define Rtc  FVAR (RtcReg, RtcAddr)
    
    ...
    
    Rtc.month = 8;
    
    

    If you peek at the definition of FVAR, you'll see that it's a macro that really just adjusts an address for the Keil tag byte coding scheme, casts it to a pointer to the type given, and dereferences that pointer. So it's a way to claim that a variable of a particular type lives at a particular address, without actually declaring a variable.


    The way I read the manual, you should also be able to use the _at_ extension to declare a variable at the right location:

    RtcReg far Rtc _at_ 0x180000UL;
    
    Rtc.month = 8;
    

    But I've never done it that way myself.

    A variation would be to put the variable in a source file by itself, so that it will wind up in a data segment by itself, and then use the linker to specify the location of that data segment. A bit more trouble, but it avoids the use of one non-standard extension if portability is a concern.

    (The first method is, IMO, the most portable; people tend to forget about the linker configuration files, and there's no commonality at all between linker control file / directive syntax from one linker to another. Most projects I've worked on use the cast-an-address route to physically locate a variable.)

  • This is what I came up with that works, it is accessing the RTC at 0x180000.

    #define RTC_ADDRESS (0x180000ul)
    
    typedef struct RTC_REGS
    {
    	unsigned char hsec;
    	unsigned char sec;
    	unsigned char min;
    	unsigned char min_alarm;
    	unsigned char hour;
    	unsigned char hour_alarm;
    	unsigned char day;
    	unsigned char day_alarm;
    	unsigned char date;
    	unsigned char month;
    	unsigned char year;
    	unsigned char cmd;
    	unsigned char wd_hsec;
    	unsigned char wd_sec;
    	unsigned char dummy1;
    	unsigned char dummy2;
    	unsigned char user[48];
    } RTC_regs;
    
    RTC_regs far *RTC_registers = &FVAR(RTC_regs, RTC_ADDRESS);
    
    void RTC_Init( void )
    {
    		RTC_registers->hsec = 0;
    		RTC_registers->sec  = 0;
    		RTC_registers->min  = 0;
    }