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

Optimizing problems (volatile hardware register)

I have had a rather ugly problem caused due to the optimization.

I am reading data from a fifo. The read port is at address 0x8200 (read only access). It also has a read reset port. Its address is also 0x8200 (both xdata) (write onle access).

When I declare the varables for accessing the fifo like this:

xdata uchar fifo_data     _at_ 0x8200; xdata uchar fifo_rres     _at_ 0x8200;
It will result in a linker warning memory overlap. Thus I have decided to do it like this:
xdata uchar fifo_data     _at_ 0x8200;
#define fifo_rres fifo_data

In a routine I have programmed this code:
  fifo_rres = 0xff;                // reset fifo read
  jpg_adr = 1;                     // set jpg file address to the next address to be read
  fbuf_start = 0;                  // set buffer start pointer to zero
  fbuf_in = 1;                     // set buffer input pointer to next free byte in buffer
  fbuf_pos = 0;                    // set buffer read pointer to zero
  fbuf_startadr = 0;               // set buffer startadress to zero
  fbuf[0] = fifo_data;             // read first byte from jpg file

The result was, that fbuf[0] was always 0xff. Then I have read the disassembly and found that when I want to set fbuf[0], I don't access the fifo read register, but it is written with 0xff.

I think, this is matter of the compiler optimization. The compiler thinks, that when I write 0xff into some address and read it some lines later, it will still be 0xff.

How can I tell the compiler, that it is not the same? I didn't find anything in my C51 manual about that topic. Maybe I just didn't find it.

  • To flesh out a bit;

    volatile xdata uchar fifo_data     _at_ 0x8200;
    #define fifo_rres fifo_data
    
    The keyword 'volatile' tells the compiler to not optimize accesses to a variable, assuming it can be changed by some other, unknown, means. It should be used anytime a variable is changed by a background function, hardware or in a different thread in multi-threaded systems.
    Best luck

  • xdata uchar fifo_data     _at_ 0x8200; 
    xdata uchar fifo_rres     _at_ 0x8200;

    As far as the 'C' language is concerned, these are two separate definitions creating 2 distinct variables - so you will obviously get the Linker warning!

    An alternative might be to use a Union - not sure how that might affect the efficiency of access, though?

    Other options would be to do it in Assembler, or leave it to the Linker.

  • what about

    xdata uchar fifo_data     _at_ 0x8200; 
    #define fifo_rres  fifo_data
    
    Erik

  • Hi there,

    thanks for the quick help. I had heard something about "volatile" before, but I couldn't find anything about it in my Keil books. After I got the reply, I have found it as a footnote in the Kernighan&Ritchie.

    So what I have done is:

    #define FIFO_READ_ADR 0x8200
    [...]
    xdata volatile uchar fifo_data _at_ FIFO_READ_ADR;  // fifo data register (read only)
    #define fifo_rres fifo_data
    

    And voila (or should I say volatile), it works.

  • Just a suggestion:

    File fifoin.c:

    xdata uchar fifo_data  _at_ 0x8200;
    

    File fifoin.h:
    extern xdata uchar fifo_data;
    #define fifo_rres  XBYTE[0x8200]
    

    File the_file_i_use_the_fifo_stuff.c:
    #include <absacc.h>
    #include "fifoin.h"
    /* now fifo_data and fifo_rres are */
    /*competely different to the Compiler*/
    

    I know, this is too complicated and -yuck- it's ugly
    style, but as a starting point for further ideas it may do.

    Good Luck

    Norbert

  • I'd like to cancel my prevoius message.

  • If you're hell-bent on having 2 variables at the same address, there is an easy way to handle it.

    1. In your C code, create external definitions. For example:

    extern unsigned char xdata var1;
    extern unsigned char xdata var2;

    2. Create an assembler module that appears as follows:

    xseg	at	0x8000
    
    public var1
    public var2
    
    var1:
    var2:	DS	1
    
    end

    This declares var1 and var2 at XDATA address 0x8000. Each is 1 byte long. If these variables are 16-bit vars, change the DS 1 to DS 2.

    Jon